Fix: lib: usage of output port message iterator
[babeltrace.git] / bindings / python / bt2 / bt2 / message.py
CommitLineData
81447b5b
PP
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
23from bt2 import native_bt, object, utils
4b552f8b 24import bt2.clock_snapshot
71fd6f52 25import collections
81447b5b
PP
26import bt2.packet
27import bt2.stream
28import bt2.event
811644b8 29import copy
81447b5b
PP
30import bt2
31
32
33def _create_from_ptr(ptr):
5602ef81 34 msg_type = native_bt.message_get_type(ptr)
81447b5b
PP
35 cls = None
36
5602ef81
SM
37 if msg_type not in _MESSAGE_TYPE_TO_CLS:
38 raise bt2.Error('unknown message type: {}'.format(msg_type))
81447b5b 39
5602ef81 40 return _MESSAGE_TYPE_TO_CLS[msg_type]._create_from_ptr(ptr)
81447b5b
PP
41
42
5602ef81
SM
43def _msg_types_from_msg_classes(message_types):
44 if message_types is None:
45 msg_types = None
dc43190b 46 else:
5602ef81
SM
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))
dc43190b 50
5602ef81 51 msg_types = [msg_cls._TYPE for msg_cls in message_types]
dc43190b 52
5602ef81 53 return msg_types
dc43190b
PP
54
55
78288f58 56class _Message(object._SharedObject):
81447b5b
PP
57 pass
58
59
5602ef81 60class _CopyableMessage(_Message):
811644b8
PP
61 def __copy__(self):
62 return self._copy(lambda obj: obj)
63
64 def __deepcopy__(self, memo):
65 cpy = self._copy(copy.deepcopy)
66 memo[id(self)] = cpy
67 return cpy
68
69
5602ef81 70class EventMessage(_CopyableMessage):
88f3724d 71 _TYPE = native_bt.MESSAGE_TYPE_EVENT
811644b8
PP
72
73 def __init__(self, event, cc_prio_map=None):
81447b5b 74 utils._check_type(event, bt2.event._Event)
811644b8
PP
75
76 if cc_prio_map is not None:
77 utils._check_type(cc_prio_map, bt2.clock_class_priority_map.ClockClassPriorityMap)
78 cc_prio_map_ptr = cc_prio_map._ptr
79 else:
80 cc_prio_map_ptr = None
81
5602ef81 82 ptr = native_bt.message_event_create(event._ptr, cc_prio_map_ptr)
81447b5b
PP
83
84 if ptr is None:
5602ef81 85 raise bt2.CreationError('cannot create event message object')
81447b5b
PP
86
87 super().__init__(ptr)
88
89 @property
90 def event(self):
5602ef81 91 event_ptr = native_bt.message_event_get_event(self._ptr)
811644b8 92 assert(event_ptr)
81447b5b
PP
93 return bt2.event._create_from_ptr(event_ptr)
94
811644b8
PP
95 @property
96 def clock_class_priority_map(self):
5602ef81 97 cc_prio_map_ptr = native_bt.message_event_get_clock_class_priority_map(self._ptr)
811644b8
PP
98 assert(cc_prio_map_ptr)
99 return bt2.clock_class_priority_map.ClockClassPriorityMap._create_from_ptr(cc_prio_map_ptr)
100
101 def __eq__(self, other):
102 if type(other) is not type(self):
103 return False
104
105 if self.addr == other.addr:
106 return True
107
108 self_props = (
109 self.event,
110 self.clock_class_priority_map,
111 )
112 other_props = (
113 other.event,
114 other.clock_class_priority_map,
115 )
116 return self_props == other_props
117
118 def _copy(self, copy_func):
119 # We can always use references here because those properties are
5602ef81
SM
120 # frozen anyway if they are part of a message. Since the
121 # user cannot modify them after copying the message, it's
811644b8 122 # useless to copy/deep-copy them.
5602ef81 123 return EventMessage(self.event, self.clock_class_priority_map)
811644b8
PP
124
125
5602ef81 126class PacketBeginningMessage(_CopyableMessage):
88f3724d 127 _TYPE = native_bt.MESSAGE_TYPE_PACKET_BEGINNING
81447b5b 128
81447b5b
PP
129 def __init__(self, packet):
130 utils._check_type(packet, bt2.packet._Packet)
5602ef81 131 ptr = native_bt.message_packet_begin_create(packet._ptr)
81447b5b
PP
132
133 if ptr is None:
5602ef81 134 raise bt2.CreationError('cannot create packet beginning message object')
81447b5b
PP
135
136 super().__init__(ptr)
137
138 @property
139 def packet(self):
5602ef81 140 packet_ptr = native_bt.message_packet_begin_get_packet(self._ptr)
811644b8 141 assert(packet_ptr)
81447b5b
PP
142 return bt2.packet._Packet._create_from_ptr(packet_ptr)
143
811644b8
PP
144 def __eq__(self, other):
145 if type(other) is not type(self):
146 return False
147
148 if self.addr == other.addr:
149 return True
150
151 return self.packet == other.packet
152
153 def _copy(self, copy_func):
154 # We can always use references here because those properties are
5602ef81
SM
155 # frozen anyway if they are part of a message. Since the
156 # user cannot modify them after copying the message, it's
811644b8 157 # useless to copy/deep-copy them.
5602ef81 158 return PacketBeginningMessage(self.packet)
811644b8
PP
159
160
5602ef81 161class PacketEndMessage(_CopyableMessage):
88f3724d 162 _TYPE = native_bt.MESSAGE_TYPE_PACKET_END
81447b5b 163
81447b5b
PP
164 def __init__(self, packet):
165 utils._check_type(packet, bt2.packet._Packet)
5602ef81 166 ptr = native_bt.message_packet_end_create(packet._ptr)
81447b5b
PP
167
168 if ptr is None:
5602ef81 169 raise bt2.CreationError('cannot create packet end message object')
81447b5b
PP
170
171 super().__init__(ptr)
172
173 @property
174 def packet(self):
5602ef81 175 packet_ptr = native_bt.message_packet_end_get_packet(self._ptr)
811644b8 176 assert(packet_ptr)
81447b5b
PP
177 return bt2.packet._Packet._create_from_ptr(packet_ptr)
178
811644b8
PP
179 def __eq__(self, other):
180 if type(other) is not type(self):
181 return False
182
183 if self.addr == other.addr:
184 return True
185
186 return self.packet == other.packet
187
188 def _copy(self, copy_func):
189 # We can always use references here because those properties are
5602ef81
SM
190 # frozen anyway if they are part of a message. Since the
191 # user cannot modify them after copying the message, it's
811644b8 192 # useless to copy/deep-copy them.
5602ef81 193 return PacketEndMessage(self.packet)
811644b8
PP
194
195
5602ef81 196class StreamBeginningMessage(_CopyableMessage):
88f3724d 197 _TYPE = native_bt.MESSAGE_TYPE_STREAM_BEGINNING
81447b5b 198
81447b5b
PP
199 def __init__(self, stream):
200 utils._check_type(stream, bt2.stream._Stream)
5602ef81 201 ptr = native_bt.message_stream_begin_create(stream._ptr)
81447b5b
PP
202
203 if ptr is None:
5602ef81 204 raise bt2.CreationError('cannot create stream beginning message object')
81447b5b
PP
205
206 super().__init__(ptr)
207
208 @property
209 def stream(self):
5602ef81 210 stream_ptr = native_bt.message_stream_begin_get_stream(self._ptr)
811644b8 211 assert(stream_ptr)
81447b5b
PP
212 return bt2.stream._create_from_ptr(stream_ptr)
213
811644b8
PP
214 def __eq__(self, other):
215 if type(other) is not type(self):
216 return False
217
218 if self.addr == other.addr:
219 return True
220
221 return self.stream == other.stream
222
223 def _copy(self, copy_func):
224 # We can always use references here because those properties are
5602ef81
SM
225 # frozen anyway if they are part of a message. Since the
226 # user cannot modify them after copying the message, it's
811644b8 227 # useless to copy/deep-copy them.
5602ef81 228 return StreamBeginningMessage(self.stream)
811644b8
PP
229
230
5602ef81 231class StreamEndMessage(_CopyableMessage):
88f3724d 232 _TYPE = native_bt.MESSAGE_TYPE_STREAM_END
81447b5b 233
811644b8
PP
234 def __init__(self, stream):
235 utils._check_type(stream, bt2.stream._Stream)
5602ef81 236 ptr = native_bt.message_stream_end_create(stream._ptr)
81447b5b
PP
237
238 if ptr is None:
5602ef81 239 raise bt2.CreationError('cannot create stream end message object')
81447b5b
PP
240
241 super().__init__(ptr)
242
243 @property
811644b8 244 def stream(self):
5602ef81 245 stream_ptr = native_bt.message_stream_end_get_stream(self._ptr)
811644b8
PP
246 assert(stream_ptr)
247 return bt2.stream._create_from_ptr(stream_ptr)
248
249 def __eq__(self, other):
250 if type(other) is not type(self):
251 return False
252
253 if self.addr == other.addr:
254 return True
255
256 return self.stream == other.stream
257
258 def _copy(self, copy_func):
259 # We can always use references here because those properties are
5602ef81
SM
260 # frozen anyway if they are part of a message. Since the
261 # user cannot modify them after copying the message, it's
811644b8 262 # useless to copy/deep-copy them.
5602ef81 263 return StreamEndMessage(self.stream)
811644b8
PP
264
265
4b552f8b
SM
266class _InactivityMessageClockSnapshotsIterator(collections.abc.Iterator):
267 def __init__(self, msg_clock_snapshots):
268 self._msg_clock_snapshots = msg_clock_snapshots
269 self._clock_classes = list(msg_clock_snapshots._msg.clock_class_priority_map)
71fd6f52
PP
270 self._at = 0
271
272 def __next__(self):
273 if self._at == len(self._clock_classes):
274 raise StopIteration
275
276 self._at += 1
277 return self._clock_classes[at]
278
279
4b552f8b 280class _InactivityMessageClockSnapshots(collections.abc.Mapping):
5602ef81
SM
281 def __init__(self, msg):
282 self._msg = msg
71fd6f52
PP
283
284 def __getitem__(self, clock_class):
285 utils._check_type(clock_class, bt2.ClockClass)
4b552f8b 286 clock_snapshot_ptr = native_bt.message_inactivity_get_clock_snapshot(self._msg._ptr,
71fd6f52
PP
287 clock_class._ptr)
288
4b552f8b 289 if clock_snapshot_ptr is None:
71fd6f52
PP
290 return
291
4b552f8b
SM
292 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
293 return clock_snapshot
71fd6f52 294
4b552f8b
SM
295 def add(self, clock_snapshot):
296 utils._check_type(clock_snapshot, bt2.clock_snapshot._ClockSnapshot)
297 ret = native_bt.message_inactivity_set_clock_snapshot(self._msg._ptr,
298 clock_snapshot._ptr)
5602ef81 299 utils._handle_ret(ret, "cannot set inactivity message object's clock value")
71fd6f52
PP
300
301 def __len__(self):
5602ef81 302 return len(self._msg.clock_class_priority_map)
71fd6f52
PP
303
304 def __iter__(self):
4b552f8b 305 return _InactivityMessageClockSnapshotsIterator(self)
71fd6f52
PP
306
307
5602ef81 308class InactivityMessage(_CopyableMessage):
88f3724d 309 _TYPE = native_bt.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
81447b5b 310
811644b8
PP
311 def __init__(self, cc_prio_map=None):
312 if cc_prio_map is not None:
313 utils._check_type(cc_prio_map, bt2.clock_class_priority_map.ClockClassPriorityMap)
314 cc_prio_map_ptr = cc_prio_map._ptr
315 else:
316 cc_prio_map_ptr = None
81447b5b 317
5602ef81 318 ptr = native_bt.message_inactivity_create(cc_prio_map_ptr)
81447b5b
PP
319
320 if ptr is None:
5602ef81 321 raise bt2.CreationError('cannot create inactivity message object')
81447b5b
PP
322
323 super().__init__(ptr)
324
325 @property
811644b8 326 def clock_class_priority_map(self):
5602ef81 327 cc_prio_map_ptr = native_bt.message_inactivity_get_clock_class_priority_map(self._ptr)
811644b8
PP
328 assert(cc_prio_map_ptr)
329 return bt2.clock_class_priority_map.ClockClassPriorityMap._create_from_ptr(cc_prio_map_ptr)
330
71fd6f52 331 @property
4b552f8b
SM
332 def clock_snapshots(self):
333 return _InactivityMessageClockSnapshots(self)
811644b8 334
4b552f8b
SM
335 def _get_clock_snapshots(self):
336 clock_snapshots = {}
811644b8 337
4b552f8b
SM
338 for clock_class, clock_snapshot in self.clock_snapshots.items():
339 if clock_snapshot is None:
811644b8
PP
340 continue
341
4b552f8b 342 clock_snapshots[clock_class] = clock_snapshot
811644b8 343
4b552f8b 344 return clock_snapshots
811644b8
PP
345
346 def __eq__(self, other):
347 if type(other) is not type(self):
348 return False
349
350 if self.addr == other.addr:
351 return True
352
353 self_props = (
354 self.clock_class_priority_map,
4b552f8b 355 self._get_clock_snapshots(),
811644b8
PP
356 )
357 other_props = (
358 other.clock_class_priority_map,
4b552f8b 359 other._get_clock_snapshots(),
811644b8
PP
360 )
361 return self_props == other_props
362
363 def __copy__(self):
5602ef81 364 cpy = InactivityMessage(self.clock_class_priority_map)
811644b8 365
4b552f8b
SM
366 for clock_class, clock_snapshot in self.clock_snapshots.items():
367 if clock_snapshot is None:
811644b8
PP
368 continue
369
4b552f8b 370 cpy.clock_snapshots.add(clock_snapshot)
811644b8
PP
371
372 return cpy
373
374 def __deepcopy__(self, memo):
375 cc_prio_map_cpy = copy.deepcopy(self.clock_class_priority_map)
5602ef81 376 cpy = InactivityMessage(cc_prio_map_cpy)
811644b8
PP
377
378 # copy clock values
379 for orig_clock_class in self.clock_class_priority_map:
4b552f8b 380 orig_clock_snapshot = self.clock_snapshot(orig_clock_class)
811644b8 381
4b552f8b 382 if orig_clock_snapshot is None:
811644b8
PP
383 continue
384
385 # find equivalent, copied clock class in CC priority map copy
386 for cpy_clock_class in cc_prio_map_cpy:
387 if cpy_clock_class == orig_clock_class:
388 break
389
390 # create copy of clock value from copied clock class
4b552f8b 391 clock_snapshot_cpy = cpy_clock_class(orig_clock_snapshot.cycles)
811644b8 392
5602ef81 393 # set copied clock value in message copy
4b552f8b 394 cpy.clock_snapshots.add(clock_snapshot_cpy)
811644b8
PP
395
396 memo[id(self)] = cpy
397 return cpy
398
399
5602ef81 400class _DiscardedElementsMessage(_Message):
811644b8
PP
401 def __eq__(self, other):
402 if type(other) is not type(self):
403 return False
404
405 if self.addr == other.addr:
406 return True
407
408 self_props = (
409 self.count,
410 self.stream,
4b552f8b
SM
411 self.beginning_clock_snapshot,
412 self.end_clock_snapshot,
811644b8
PP
413 )
414 other_props = (
415 other.count,
416 other.stream,
4b552f8b
SM
417 other.beginning_clock_snapshot,
418 other.end_clock_snapshot,
811644b8
PP
419 )
420 return self_props == other_props
421
422
5602ef81 423class _DiscardedPacketsMessage(_DiscardedElementsMessage):
88f3724d 424 _TYPE = native_bt.MESSAGE_TYPE_DISCARDED_PACKETS
811644b8
PP
425
426 @property
427 def count(self):
5602ef81 428 count = native_bt.message_discarded_packets_get_count(self._ptr)
811644b8
PP
429 assert(count >= 0)
430 return count
431
432 @property
433 def stream(self):
5602ef81 434 stream_ptr = native_bt.message_discarded_packets_get_stream(self._ptr)
811644b8
PP
435 assert(stream_ptr)
436 return bt2.stream._create_from_ptr(stream_ptr)
437
438 @property
4b552f8b
SM
439 def beginning_clock_snapshot(self):
440 clock_snapshot_ptr = native_bt.message_discarded_packets_get_begin_clock_snapshot(self._ptr)
811644b8 441
4b552f8b 442 if clock_snapshot_ptr is None:
811644b8
PP
443 return
444
4b552f8b
SM
445 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
446 return clock_snapshot
811644b8
PP
447
448 @property
4b552f8b
SM
449 def end_clock_snapshot(self):
450 clock_snapshot_ptr = native_bt.message_discarded_packets_get_end_clock_snapshot(self._ptr)
811644b8 451
4b552f8b 452 if clock_snapshot_ptr is None:
811644b8
PP
453 return
454
4b552f8b
SM
455 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
456 return clock_snapshot
811644b8
PP
457
458
5602ef81 459class _DiscardedEventsMessage(_DiscardedElementsMessage):
88f3724d 460 _TYPE = native_bt.MESSAGE_TYPE_DISCARDED_EVENTS
811644b8
PP
461
462 @property
463 def count(self):
5602ef81 464 count = native_bt.message_discarded_events_get_count(self._ptr)
811644b8
PP
465 assert(count >= 0)
466 return count
467
468 @property
469 def stream(self):
5602ef81 470 stream_ptr = native_bt.message_discarded_events_get_stream(self._ptr)
811644b8
PP
471 assert(stream_ptr)
472 return bt2.stream._create_from_ptr(stream_ptr)
473
474 @property
4b552f8b
SM
475 def beginning_clock_snapshot(self):
476 clock_snapshot_ptr = native_bt.message_discarded_events_get_begin_clock_snapshot(self._ptr)
811644b8 477
4b552f8b 478 if clock_snapshot_ptr is None:
811644b8
PP
479 return
480
4b552f8b
SM
481 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
482 return clock_snapshot
811644b8
PP
483
484 @property
4b552f8b
SM
485 def end_clock_snapshot(self):
486 clock_snapshot_ptr = native_bt.message_discarded_events_get_end_clock_snapshot(self._ptr)
811644b8 487
4b552f8b 488 if clock_snapshot_ptr is None:
811644b8
PP
489 return
490
4b552f8b
SM
491 clock_snapshot = bt2.clock_snapshot._create_clock_snapshot_from_ptr(clock_snapshot_ptr)
492 return clock_snapshot
81447b5b
PP
493
494
5602ef81
SM
495_MESSAGE_TYPE_TO_CLS = {
496 native_bt.MESSAGE_TYPE_EVENT: EventMessage,
497 native_bt.MESSAGE_TYPE_PACKET_BEGINNING: PacketBeginningMessage,
498 native_bt.MESSAGE_TYPE_PACKET_END: PacketEndMessage,
499 native_bt.MESSAGE_TYPE_STREAM_BEGINNING: StreamBeginningMessage,
500 native_bt.MESSAGE_TYPE_STREAM_END: StreamEndMessage,
501 native_bt.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: InactivityMessage,
502 native_bt.MESSAGE_TYPE_DISCARDED_PACKETS: _DiscardedPacketsMessage,
503 native_bt.MESSAGE_TYPE_DISCARDED_EVENTS: _DiscardedEventsMessage,
81447b5b 504}
This page took 0.059252 seconds and 4 git commands to generate.