6a48f93adde51231f3a957f4f2263eb4b822a1c5
[babeltrace.git] / bindings / python / bt2 / bt2 / message.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22
23 from bt2 import native_bt, object, utils
24 import bt2.clock_snapshot
25 import collections
26 import bt2.packet
27 import bt2.stream
28 import bt2.event
29 import copy
30 import bt2
31
32
33 def _create_from_ptr(ptr):
34 msg_type = native_bt.message_get_type(ptr)
35 cls = None
36
37 if msg_type not in _MESSAGE_TYPE_TO_CLS:
38 raise bt2.Error('unknown message type: {}'.format(msg_type))
39
40 return _MESSAGE_TYPE_TO_CLS[msg_type]._create_from_ptr(ptr)
41
42
43 def _msg_types_from_msg_classes(message_types):
44 if message_types is None:
45 msg_types = None
46 else:
47 for msg_cls in message_types:
48 if msg_cls not in _MESSAGE_TYPE_TO_CLS.values():
49 raise ValueError("'{}' is not a message class".format(msg_cls))
50
51 msg_types = [msg_cls._TYPE for msg_cls in message_types]
52
53 return msg_types
54
55
56 class _Message(object._SharedObject):
57 _get_ref = staticmethod(native_bt.message_get_ref)
58 _put_ref = staticmethod(native_bt.message_put_ref)
59
60
61 class _CopyableMessage(_Message):
62 def __copy__(self):
63 return self._copy(lambda obj: obj)
64
65 def __deepcopy__(self, memo):
66 cpy = self._copy(copy.deepcopy)
67 memo[id(self)] = cpy
68 return cpy
69
70
71 class _EventMessage(_CopyableMessage):
72 _TYPE = native_bt.MESSAGE_TYPE_EVENT
73
74 @property
75 def event(self):
76 event_ptr = native_bt.message_event_borrow_event(self._ptr)
77 assert event_ptr is not None
78 return bt2.event._Event._create_from_ptr_and_get_ref(
79 event_ptr, self._ptr, self._get_ref, self._put_ref)
80
81 @property
82 def default_clock_snapshot(self):
83 if self.event.event_class.stream_class.default_clock_class is None:
84 return None
85
86 snapshot_ptr = native_bt.message_event_borrow_default_clock_snapshot_const(self._ptr)
87
88 return bt2.clock_snapshot._ClockSnapshot._create_from_ptr_and_get_ref(
89 snapshot_ptr, self._ptr, self._get_ref, self._put_ref)
90
91 @property
92 def clock_class_priority_map(self):
93 cc_prio_map_ptr = native_bt.message_event_get_clock_class_priority_map(self._ptr)
94 assert(cc_prio_map_ptr)
95 return bt2.clock_class_priority_map.ClockClassPriorityMap._create_from_ptr(cc_prio_map_ptr)
96
97 def __eq__(self, other):
98 if type(other) is not type(self):
99 return False
100
101 if self.addr == other.addr:
102 return True
103
104 self_props = (
105 self.event,
106 self.clock_class_priority_map,
107 )
108 other_props = (
109 other.event,
110 other.clock_class_priority_map,
111 )
112 return self_props == other_props
113
114 def _copy(self, copy_func):
115 # We can always use references here because those properties are
116 # frozen anyway if they are part of a message. Since the
117 # user cannot modify them after copying the message, it's
118 # useless to copy/deep-copy them.
119 return EventMessage(self.event, self.clock_class_priority_map)
120
121
122 class _PacketBeginningMessage(_CopyableMessage):
123 _TYPE = native_bt.MESSAGE_TYPE_PACKET_BEGINNING
124
125 @property
126 def packet(self):
127 packet_ptr = native_bt.message_packet_begin_get_packet(self._ptr)
128 assert(packet_ptr)
129 return bt2.packet._Packet._create_from_ptr(packet_ptr)
130
131 def __eq__(self, other):
132 if type(other) is not type(self):
133 return False
134
135 if self.addr == other.addr:
136 return True
137
138 return self.packet == other.packet
139
140 def _copy(self, copy_func):
141 # We can always use references here because those properties are
142 # frozen anyway if they are part of a message. Since the
143 # user cannot modify them after copying the message, it's
144 # useless to copy/deep-copy them.
145 return PacketBeginningMessage(self.packet)
146
147
148 class _PacketEndMessage(_CopyableMessage):
149 _TYPE = native_bt.MESSAGE_TYPE_PACKET_END
150
151 @property
152 def packet(self):
153 packet_ptr = native_bt.message_packet_end_get_packet(self._ptr)
154 assert(packet_ptr)
155 return bt2.packet._Packet._create_from_ptr(packet_ptr)
156
157 def __eq__(self, other):
158 if type(other) is not type(self):
159 return False
160
161 if self.addr == other.addr:
162 return True
163
164 return self.packet == other.packet
165
166 def _copy(self, copy_func):
167 # We can always use references here because those properties are
168 # frozen anyway if they are part of a message. Since the
169 # user cannot modify them after copying the message, it's
170 # useless to copy/deep-copy them.
171 return PacketEndMessage(self.packet)
172
173
174 class _StreamBeginningMessage(_CopyableMessage):
175 _TYPE = native_bt.MESSAGE_TYPE_STREAM_BEGINNING
176
177 @property
178 def stream(self):
179 stream_ptr = native_bt.message_stream_begin_get_stream(self._ptr)
180 assert(stream_ptr)
181 return bt2.stream._create_from_ptr(stream_ptr)
182
183 def __eq__(self, other):
184 if type(other) is not type(self):
185 return False
186
187 if self.addr == other.addr:
188 return True
189
190 return self.stream == other.stream
191
192 def _copy(self, copy_func):
193 # We can always use references here because those properties are
194 # frozen anyway if they are part of a message. Since the
195 # user cannot modify them after copying the message, it's
196 # useless to copy/deep-copy them.
197 return StreamBeginningMessage(self.stream)
198
199
200 class _StreamEndMessage(_CopyableMessage):
201 _TYPE = native_bt.MESSAGE_TYPE_STREAM_END
202
203 @property
204 def stream(self):
205 stream_ptr = native_bt.message_stream_end_get_stream(self._ptr)
206 assert(stream_ptr)
207 return bt2.stream._create_from_ptr(stream_ptr)
208
209 def __eq__(self, other):
210 if type(other) is not type(self):
211 return False
212
213 if self.addr == other.addr:
214 return True
215
216 return self.stream == other.stream
217
218 def _copy(self, copy_func):
219 # We can always use references here because those properties are
220 # frozen anyway if they are part of a message. Since the
221 # user cannot modify them after copying the message, it's
222 # useless to copy/deep-copy them.
223 return StreamEndMessage(self.stream)
224
225
226 class _InactivityMessageClockSnapshotsIterator(collections.abc.Iterator):
227 def __init__(self, msg_clock_snapshots):
228 self._msg_clock_snapshots = msg_clock_snapshots
229 self._clock_classes = list(msg_clock_snapshots._msg.clock_class_priority_map)
230 self._at = 0
231
232 def __next__(self):
233 if self._at == len(self._clock_classes):
234 raise StopIteration
235
236 self._at += 1
237 return self._clock_classes[at]
238
239
240 class _InactivityMessageClockSnapshots(collections.abc.Mapping):
241 def __init__(self, msg):
242 self._msg = msg
243
244 def __getitem__(self, clock_class):
245 utils._check_type(clock_class, bt2.ClockClass)
246 clock_snapshot_ptr = native_bt.message_inactivity_get_clock_snapshot(self._msg._ptr,
247 clock_class._ptr)
248
249 if clock_snapshot_ptr is None:
250 return
251
252 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
253 return clock_snapshot
254
255 def add(self, clock_snapshot):
256 utils._check_type(clock_snapshot, bt2.clock_snapshot._ClockSnapshot)
257 ret = native_bt.message_inactivity_set_clock_snapshot(self._msg._ptr,
258 clock_snapshot._ptr)
259 utils._handle_ret(ret, "cannot set inactivity message object's clock value")
260
261 def __len__(self):
262 return len(self._msg.clock_class_priority_map)
263
264 def __iter__(self):
265 return _InactivityMessageClockSnapshotsIterator(self)
266
267
268 class InactivityMessage(_CopyableMessage):
269 _TYPE = native_bt.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
270
271 def __init__(self, cc_prio_map=None):
272 if cc_prio_map is not None:
273 utils._check_type(cc_prio_map, bt2.clock_class_priority_map.ClockClassPriorityMap)
274 cc_prio_map_ptr = cc_prio_map._ptr
275 else:
276 cc_prio_map_ptr = None
277
278 ptr = native_bt.message_inactivity_create(cc_prio_map_ptr)
279
280 if ptr is None:
281 raise bt2.CreationError('cannot create inactivity message object')
282
283 super().__init__(ptr)
284
285 @property
286 def clock_class_priority_map(self):
287 cc_prio_map_ptr = native_bt.message_inactivity_get_clock_class_priority_map(self._ptr)
288 assert(cc_prio_map_ptr)
289 return bt2.clock_class_priority_map.ClockClassPriorityMap._create_from_ptr(cc_prio_map_ptr)
290
291 @property
292 def clock_snapshots(self):
293 return _InactivityMessageClockSnapshots(self)
294
295 def _get_clock_snapshots(self):
296 clock_snapshots = {}
297
298 for clock_class, clock_snapshot in self.clock_snapshots.items():
299 if clock_snapshot is None:
300 continue
301
302 clock_snapshots[clock_class] = clock_snapshot
303
304 return clock_snapshots
305
306 def __eq__(self, other):
307 if type(other) is not type(self):
308 return False
309
310 if self.addr == other.addr:
311 return True
312
313 self_props = (
314 self.clock_class_priority_map,
315 self._get_clock_snapshots(),
316 )
317 other_props = (
318 other.clock_class_priority_map,
319 other._get_clock_snapshots(),
320 )
321 return self_props == other_props
322
323 def __copy__(self):
324 cpy = InactivityMessage(self.clock_class_priority_map)
325
326 for clock_class, clock_snapshot in self.clock_snapshots.items():
327 if clock_snapshot is None:
328 continue
329
330 cpy.clock_snapshots.add(clock_snapshot)
331
332 return cpy
333
334 def __deepcopy__(self, memo):
335 cc_prio_map_cpy = copy.deepcopy(self.clock_class_priority_map)
336 cpy = InactivityMessage(cc_prio_map_cpy)
337
338 # copy clock values
339 for orig_clock_class in self.clock_class_priority_map:
340 orig_clock_snapshot = self.clock_snapshot(orig_clock_class)
341
342 if orig_clock_snapshot is None:
343 continue
344
345 # find equivalent, copied clock class in CC priority map copy
346 for cpy_clock_class in cc_prio_map_cpy:
347 if cpy_clock_class == orig_clock_class:
348 break
349
350 # create copy of clock value from copied clock class
351 clock_snapshot_cpy = cpy_clock_class(orig_clock_snapshot.cycles)
352
353 # set copied clock value in message copy
354 cpy.clock_snapshots.add(clock_snapshot_cpy)
355
356 memo[id(self)] = cpy
357 return cpy
358
359
360 class _DiscardedElementsMessage(_Message):
361 def __eq__(self, other):
362 if type(other) is not type(self):
363 return False
364
365 if self.addr == other.addr:
366 return True
367
368 self_props = (
369 self.count,
370 self.stream,
371 self.beginning_clock_snapshot,
372 self.end_clock_snapshot,
373 )
374 other_props = (
375 other.count,
376 other.stream,
377 other.beginning_clock_snapshot,
378 other.end_clock_snapshot,
379 )
380 return self_props == other_props
381
382
383 class _DiscardedPacketsMessage(_DiscardedElementsMessage):
384 _TYPE = native_bt.MESSAGE_TYPE_DISCARDED_PACKETS
385
386 @property
387 def count(self):
388 count = native_bt.message_discarded_packets_get_count(self._ptr)
389 assert(count >= 0)
390 return count
391
392 @property
393 def stream(self):
394 stream_ptr = native_bt.message_discarded_packets_get_stream(self._ptr)
395 assert(stream_ptr)
396 return bt2.stream._create_from_ptr(stream_ptr)
397
398 @property
399 def beginning_clock_snapshot(self):
400 clock_snapshot_ptr = native_bt.message_discarded_packets_get_begin_clock_snapshot(self._ptr)
401
402 if clock_snapshot_ptr is None:
403 return
404
405 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
406 return clock_snapshot
407
408 @property
409 def end_clock_snapshot(self):
410 clock_snapshot_ptr = native_bt.message_discarded_packets_get_end_clock_snapshot(self._ptr)
411
412 if clock_snapshot_ptr is None:
413 return
414
415 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
416 return clock_snapshot
417
418
419 class _DiscardedEventsMessage(_DiscardedElementsMessage):
420 _TYPE = native_bt.MESSAGE_TYPE_DISCARDED_EVENTS
421
422 @property
423 def count(self):
424 count = native_bt.message_discarded_events_get_count(self._ptr)
425 assert(count >= 0)
426 return count
427
428 @property
429 def stream(self):
430 stream_ptr = native_bt.message_discarded_events_get_stream(self._ptr)
431 assert(stream_ptr)
432 return bt2.stream._create_from_ptr(stream_ptr)
433
434 @property
435 def beginning_clock_snapshot(self):
436 clock_snapshot_ptr = native_bt.message_discarded_events_get_begin_clock_snapshot(self._ptr)
437
438 if clock_snapshot_ptr is None:
439 return
440
441 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
442 return clock_snapshot
443
444 @property
445 def end_clock_snapshot(self):
446 clock_snapshot_ptr = native_bt.message_discarded_events_get_end_clock_snapshot(self._ptr)
447
448 if clock_snapshot_ptr is None:
449 return
450
451 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
452 return clock_snapshot
453
454
455 _MESSAGE_TYPE_TO_CLS = {
456 native_bt.MESSAGE_TYPE_EVENT: _EventMessage,
457 native_bt.MESSAGE_TYPE_PACKET_BEGINNING: _PacketBeginningMessage,
458 native_bt.MESSAGE_TYPE_PACKET_END: _PacketEndMessage,
459 native_bt.MESSAGE_TYPE_STREAM_BEGINNING: _StreamBeginningMessage,
460 native_bt.MESSAGE_TYPE_STREAM_END: _StreamEndMessage,
461 native_bt.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: InactivityMessage,
462 native_bt.MESSAGE_TYPE_DISCARDED_PACKETS: _DiscardedPacketsMessage,
463 native_bt.MESSAGE_TYPE_DISCARDED_EVENTS: _DiscardedEventsMessage,
464 }
This page took 0.03781 seconds and 4 git commands to generate.