Fix: pass private data to context callbacks
[lttng-ust.git] / python-lttngust / lttngust / cmd.py
1 # -*- coding: utf-8 -*-
2 #
3 # SPDX-License-Identifier: LGPL-2.1-only
4 #
5 # Copyright (C) 2015 Philippe Proulx <pproulx@efficios.com>
6 # Copyright (C) 2014 David Goulet <dgoulet@efficios.com>
7 # Copyright (C) 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8
9 from __future__ import unicode_literals
10 import lttngust.debug as dbg
11 import struct
12
13
14 # server command header
15 _server_cmd_header_struct = struct.Struct('>QII')
16
17
18 # server command header size
19 _SERVER_CMD_HEADER_SIZE = _server_cmd_header_struct.size
20
21
22 # agent protocol symbol size
23 _LTTNG_SYMBOL_NAME_LEN = 256
24
25
26 class _ServerCmdHeader(object):
27 def __init__(self, data_size, cmd_id, cmd_version):
28 self.data_size = data_size
29 self.cmd_id = cmd_id
30 self.cmd_version = cmd_version
31
32
33 def _server_cmd_header_from_data(data):
34 try:
35 data_size, cmd_id, cmd_version = _server_cmd_header_struct.unpack(data)
36 except (Exception) as e:
37 dbg._pdebug('cannot decode command header: {}'.format(e))
38 return None
39
40 return _ServerCmdHeader(data_size, cmd_id, cmd_version)
41
42
43 class _ServerCmd(object):
44 def __init__(self, header):
45 self.header = header
46
47 @classmethod
48 def from_data(cls, header, data):
49 raise NotImplementedError()
50
51
52 class _ServerCmdList(_ServerCmd):
53 @classmethod
54 def from_data(cls, header, data):
55 return cls(header)
56
57
58 class _ServerCmdEnable(_ServerCmd):
59 _NAME_OFFSET = 8
60 _loglevel_struct = struct.Struct('>II')
61 # filter expression size
62 _filter_exp_len_struct = struct.Struct('>I')
63
64 def __init__(self, header, loglevel, loglevel_type, name, filter_exp):
65 super(self.__class__, self).__init__(header)
66 self.loglevel = loglevel
67 self.loglevel_type = loglevel_type
68 self.name = name
69 self.filter_expression = filter_exp
70 dbg._pdebug('server enable command {}'.format(self.__dict__))
71
72 @classmethod
73 def from_data(cls, header, data):
74 try:
75 loglevel, loglevel_type = cls._loglevel_struct.unpack_from(data)
76 name_start = cls._loglevel_struct.size
77 name_end = name_start + _LTTNG_SYMBOL_NAME_LEN
78 data_name = data[name_start:name_end]
79 name = data_name.rstrip(b'\0').decode()
80
81 filter_exp_start = name_end + cls._filter_exp_len_struct.size
82 filter_exp_len, = cls._filter_exp_len_struct.unpack_from(
83 data[name_end:filter_exp_start])
84 filter_exp_end = filter_exp_start + filter_exp_len
85
86 filter_exp = data[filter_exp_start:filter_exp_end].rstrip(
87 b'\0').decode()
88
89 return cls(header, loglevel, loglevel_type, name, filter_exp)
90 except (Exception) as e:
91 dbg._pdebug('cannot decode enable command: {}'.format(e))
92 return None
93
94
95 class _ServerCmdDisable(_ServerCmd):
96 def __init__(self, header, name):
97 super(self.__class__, self).__init__(header)
98 self.name = name
99
100 @classmethod
101 def from_data(cls, header, data):
102 try:
103 name = data.rstrip(b'\0').decode()
104
105 return cls(header, name)
106 except (Exception) as e:
107 dbg._pdebug('cannot decode disable command: {}'.format(e))
108 return None
109
110
111 class _ServerCmdRegistrationDone(_ServerCmd):
112 @classmethod
113 def from_data(cls, header, data):
114 return cls(header)
115
116
117 _SERVER_CMD_ID_TO_SERVER_CMD = {
118 1: _ServerCmdList,
119 2: _ServerCmdEnable,
120 3: _ServerCmdDisable,
121 4: _ServerCmdRegistrationDone,
122 }
123
124
125 def _server_cmd_from_data(header, data):
126 if header.cmd_id not in _SERVER_CMD_ID_TO_SERVER_CMD:
127 return None
128
129 return _SERVER_CMD_ID_TO_SERVER_CMD[header.cmd_id].from_data(header, data)
130
131
132 _CLIENT_CMD_REPLY_STATUS_SUCCESS = 1
133 _CLIENT_CMD_REPLY_STATUS_INVALID_CMD = 2
134
135
136 class _ClientCmdReplyHeader(object):
137 _payload_struct = struct.Struct('>I')
138
139 def __init__(self, status_code=_CLIENT_CMD_REPLY_STATUS_SUCCESS):
140 self.status_code = status_code
141
142 def get_data(self):
143 return self._payload_struct.pack(self.status_code)
144
145
146 class _ClientCmdReplyEnable(_ClientCmdReplyHeader):
147 pass
148
149
150 class _ClientCmdReplyDisable(_ClientCmdReplyHeader):
151 pass
152
153
154 class _ClientCmdReplyList(_ClientCmdReplyHeader):
155 _nb_events_struct = struct.Struct('>I')
156 _data_size_struct = struct.Struct('>I')
157
158 def __init__(self, names, status_code=_CLIENT_CMD_REPLY_STATUS_SUCCESS):
159 super(self.__class__, self).__init__(status_code)
160 self.names = names
161
162 def get_data(self):
163 upper_data = super(self.__class__, self).get_data()
164 nb_events_data = self._nb_events_struct.pack(len(self.names))
165 names_data = bytes()
166
167 for name in self.names:
168 names_data += name.encode() + b'\0'
169
170 data_size_data = self._data_size_struct.pack(len(names_data))
171
172 return upper_data + data_size_data + nb_events_data + names_data
173
174
175 class _ClientRegisterCmd(object):
176 _payload_struct = struct.Struct('>IIII')
177
178 def __init__(self, domain, pid, major, minor):
179 self.domain = domain
180 self.pid = pid
181 self.major = major
182 self.minor = minor
183
184 def get_data(self):
185 return self._payload_struct.pack(self.domain, self.pid, self.major,
186 self.minor)
This page took 0.032641 seconds and 4 git commands to generate.