1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2015 - Philippe Proulx <pproulx@efficios.com>
4 # Copyright (C) 2014 - David Goulet <dgoulet@efficios.com>
5 # Copyright (C) 2015 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 # This library is free software; you can redistribute it and/or modify it under
8 # the terms of the GNU Lesser General Public License as published by the Free
9 # Software Foundation; version 2.1 of the License.
11 # This library is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16 # You should have received a copy of the GNU Lesser General Public License
17 # along with this library; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 from __future__
import unicode_literals
21 import lttngust
.debug
as dbg
25 # server command header
26 _server_cmd_header_struct
= struct
.Struct('>QII')
29 # server command header size
30 _SERVER_CMD_HEADER_SIZE
= _server_cmd_header_struct
.size
33 # agent protocol symbol size
34 _LTTNG_SYMBOL_NAME_LEN
= 256
37 class _ServerCmdHeader(object):
38 def __init__(self
, data_size
, cmd_id
, cmd_version
):
39 self
.data_size
= data_size
41 self
.cmd_version
= cmd_version
44 def _server_cmd_header_from_data(data
):
46 data_size
, cmd_id
, cmd_version
= _server_cmd_header_struct
.unpack(data
)
47 except (Exception) as e
:
48 dbg
._pdebug
('cannot decode command header: {}'.format(e
))
51 return _ServerCmdHeader(data_size
, cmd_id
, cmd_version
)
54 class _ServerCmd(object):
55 def __init__(self
, header
):
59 def from_data(cls
, header
, data
):
60 raise NotImplementedError()
63 class _ServerCmdList(_ServerCmd
):
65 def from_data(cls
, header
, data
):
69 class _ServerCmdEnable(_ServerCmd
):
71 _loglevel_struct
= struct
.Struct('>II')
72 # filter expression size
73 _filter_exp_len_struct
= struct
.Struct('>I')
75 def __init__(self
, header
, loglevel
, loglevel_type
, name
, filter_exp
):
76 super(self
.__class
__, self
).__init
__(header
)
77 self
.loglevel
= loglevel
78 self
.loglevel_type
= loglevel_type
80 self
.filter_expression
= filter_exp
81 dbg
._pdebug
('server enable command {}'.format(self
.__dict
__))
84 def from_data(cls
, header
, data
):
86 loglevel
, loglevel_type
= cls
._loglevel
_struct
.unpack_from(data
)
87 name_start
= cls
._loglevel
_struct
.size
88 name_end
= name_start
+ _LTTNG_SYMBOL_NAME_LEN
89 data_name
= data
[name_start
:name_end
]
90 name
= data_name
.rstrip(b
'\0').decode()
92 filter_exp_start
= name_end
+ cls
._filter
_exp
_len
_struct
.size
93 filter_exp_len
, = cls
._filter
_exp
_len
_struct
.unpack_from(
94 data
[name_end
:filter_exp_start
])
95 filter_exp_end
= filter_exp_start
+ filter_exp_len
97 filter_exp
= data
[filter_exp_start
:filter_exp_end
].rstrip(
100 return cls(header
, loglevel
, loglevel_type
, name
, filter_exp
)
101 except (Exception) as e
:
102 dbg
._pdebug
('cannot decode enable command: {}'.format(e
))
106 class _ServerCmdDisable(_ServerCmd
):
107 def __init__(self
, header
, name
):
108 super(self
.__class
__, self
).__init
__(header
)
112 def from_data(cls
, header
, data
):
114 name
= data
.rstrip(b
'\0').decode()
116 return cls(header
, name
)
117 except (Exception) as e
:
118 dbg
._pdebug
('cannot decode disable command: {}'.format(e
))
122 class _ServerCmdRegistrationDone(_ServerCmd
):
124 def from_data(cls
, header
, data
):
128 _SERVER_CMD_ID_TO_SERVER_CMD
= {
131 3: _ServerCmdDisable
,
132 4: _ServerCmdRegistrationDone
,
136 def _server_cmd_from_data(header
, data
):
137 if header
.cmd_id
not in _SERVER_CMD_ID_TO_SERVER_CMD
:
140 return _SERVER_CMD_ID_TO_SERVER_CMD
[header
.cmd_id
].from_data(header
, data
)
143 _CLIENT_CMD_REPLY_STATUS_SUCCESS
= 1
144 _CLIENT_CMD_REPLY_STATUS_INVALID_CMD
= 2
147 class _ClientCmdReplyHeader(object):
148 _payload_struct
= struct
.Struct('>I')
150 def __init__(self
, status_code
=_CLIENT_CMD_REPLY_STATUS_SUCCESS
):
151 self
.status_code
= status_code
154 return self
._payload
_struct
.pack(self
.status_code
)
157 class _ClientCmdReplyEnable(_ClientCmdReplyHeader
):
161 class _ClientCmdReplyDisable(_ClientCmdReplyHeader
):
165 class _ClientCmdReplyList(_ClientCmdReplyHeader
):
166 _nb_events_struct
= struct
.Struct('>I')
167 _data_size_struct
= struct
.Struct('>I')
169 def __init__(self
, names
, status_code
=_CLIENT_CMD_REPLY_STATUS_SUCCESS
):
170 super(self
.__class
__, self
).__init
__(status_code
)
174 upper_data
= super(self
.__class
__, self
).get_data()
175 nb_events_data
= self
._nb
_events
_struct
.pack(len(self
.names
))
178 for name
in self
.names
:
179 names_data
+= name
.encode() + b
'\0'
181 data_size_data
= self
._data
_size
_struct
.pack(len(names_data
))
183 return upper_data
+ data_size_data
+ nb_events_data
+ names_data
186 class _ClientRegisterCmd(object):
187 _payload_struct
= struct
.Struct('>IIII')
189 def __init__(self
, domain
, pid
, major
, minor
):
196 return self
._payload
_struct
.pack(self
.domain
, self
.pid
, self
.major
,