1 # The MIT License (MIT)
3 # Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
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:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
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
23 from bt2
import native_bt
, object, utils
24 import bt2
.clock_snapshot
33 def _create_from_ptr(ptr
):
34 msg_type
= native_bt
.message_get_type(ptr
)
37 if msg_type
not in _MESSAGE_TYPE_TO_CLS
:
38 raise bt2
.Error('unknown message type: {}'.format(msg_type
))
40 return _MESSAGE_TYPE_TO_CLS
[msg_type
]._create
_from
_ptr
(ptr
)
43 def _msg_types_from_msg_classes(message_types
):
44 if message_types
is None:
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
))
51 msg_types
= [msg_cls
._TYPE
for msg_cls
in message_types
]
56 class _Message(object._SharedObject
):
60 class _CopyableMessage(_Message
):
62 return self
._copy
(lambda obj
: obj
)
64 def __deepcopy__(self
, memo
):
65 cpy
= self
._copy
(copy
.deepcopy
)
70 class EventMessage(_CopyableMessage
):
71 _TYPE
= native_bt
.MESSAGE_TYPE_EVENT
73 def __init__(self
, event
, cc_prio_map
=None):
74 utils
._check
_type
(event
, bt2
.event
._Event
)
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
80 cc_prio_map_ptr
= None
82 ptr
= native_bt
.message_event_create(event
._ptr
, cc_prio_map_ptr
)
85 raise bt2
.CreationError('cannot create event message object')
91 event_ptr
= native_bt
.message_event_get_event(self
._ptr
)
93 return bt2
.event
._create
_from
_ptr
(event_ptr
)
96 def clock_class_priority_map(self
):
97 cc_prio_map_ptr
= native_bt
.message_event_get_clock_class_priority_map(self
._ptr
)
98 assert(cc_prio_map_ptr
)
99 return bt2
.clock_class_priority_map
.ClockClassPriorityMap
._create
_from
_ptr
(cc_prio_map_ptr
)
101 def __eq__(self
, other
):
102 if type(other
) is not type(self
):
105 if self
.addr
== other
.addr
:
110 self
.clock_class_priority_map
,
114 other
.clock_class_priority_map
,
116 return self_props
== other_props
118 def _copy(self
, copy_func
):
119 # We can always use references here because those properties are
120 # frozen anyway if they are part of a message. Since the
121 # user cannot modify them after copying the message, it's
122 # useless to copy/deep-copy them.
123 return EventMessage(self
.event
, self
.clock_class_priority_map
)
126 class PacketBeginningMessage(_CopyableMessage
):
127 _TYPE
= native_bt
.MESSAGE_TYPE_PACKET_BEGINNING
129 def __init__(self
, packet
):
130 utils
._check
_type
(packet
, bt2
.packet
._Packet
)
131 ptr
= native_bt
.message_packet_begin_create(packet
._ptr
)
134 raise bt2
.CreationError('cannot create packet beginning message object')
136 super().__init
__(ptr
)
140 packet_ptr
= native_bt
.message_packet_begin_get_packet(self
._ptr
)
142 return bt2
.packet
._Packet
._create
_from
_ptr
(packet_ptr
)
144 def __eq__(self
, other
):
145 if type(other
) is not type(self
):
148 if self
.addr
== other
.addr
:
151 return self
.packet
== other
.packet
153 def _copy(self
, copy_func
):
154 # We can always use references here because those properties are
155 # frozen anyway if they are part of a message. Since the
156 # user cannot modify them after copying the message, it's
157 # useless to copy/deep-copy them.
158 return PacketBeginningMessage(self
.packet
)
161 class PacketEndMessage(_CopyableMessage
):
162 _TYPE
= native_bt
.MESSAGE_TYPE_PACKET_END
164 def __init__(self
, packet
):
165 utils
._check
_type
(packet
, bt2
.packet
._Packet
)
166 ptr
= native_bt
.message_packet_end_create(packet
._ptr
)
169 raise bt2
.CreationError('cannot create packet end message object')
171 super().__init
__(ptr
)
175 packet_ptr
= native_bt
.message_packet_end_get_packet(self
._ptr
)
177 return bt2
.packet
._Packet
._create
_from
_ptr
(packet_ptr
)
179 def __eq__(self
, other
):
180 if type(other
) is not type(self
):
183 if self
.addr
== other
.addr
:
186 return self
.packet
== other
.packet
188 def _copy(self
, copy_func
):
189 # We can always use references here because those properties are
190 # frozen anyway if they are part of a message. Since the
191 # user cannot modify them after copying the message, it's
192 # useless to copy/deep-copy them.
193 return PacketEndMessage(self
.packet
)
196 class StreamBeginningMessage(_CopyableMessage
):
197 _TYPE
= native_bt
.MESSAGE_TYPE_STREAM_BEGINNING
199 def __init__(self
, stream
):
200 utils
._check
_type
(stream
, bt2
.stream
._Stream
)
201 ptr
= native_bt
.message_stream_begin_create(stream
._ptr
)
204 raise bt2
.CreationError('cannot create stream beginning message object')
206 super().__init
__(ptr
)
210 stream_ptr
= native_bt
.message_stream_begin_get_stream(self
._ptr
)
212 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
214 def __eq__(self
, other
):
215 if type(other
) is not type(self
):
218 if self
.addr
== other
.addr
:
221 return self
.stream
== other
.stream
223 def _copy(self
, copy_func
):
224 # We can always use references here because those properties are
225 # frozen anyway if they are part of a message. Since the
226 # user cannot modify them after copying the message, it's
227 # useless to copy/deep-copy them.
228 return StreamBeginningMessage(self
.stream
)
231 class StreamEndMessage(_CopyableMessage
):
232 _TYPE
= native_bt
.MESSAGE_TYPE_STREAM_END
234 def __init__(self
, stream
):
235 utils
._check
_type
(stream
, bt2
.stream
._Stream
)
236 ptr
= native_bt
.message_stream_end_create(stream
._ptr
)
239 raise bt2
.CreationError('cannot create stream end message object')
241 super().__init
__(ptr
)
245 stream_ptr
= native_bt
.message_stream_end_get_stream(self
._ptr
)
247 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
249 def __eq__(self
, other
):
250 if type(other
) is not type(self
):
253 if self
.addr
== other
.addr
:
256 return self
.stream
== other
.stream
258 def _copy(self
, copy_func
):
259 # We can always use references here because those properties are
260 # frozen anyway if they are part of a message. Since the
261 # user cannot modify them after copying the message, it's
262 # useless to copy/deep-copy them.
263 return StreamEndMessage(self
.stream
)
266 class _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
)
273 if self
._at
== len(self
._clock
_classes
):
277 return self
._clock
_classes
[at
]
280 class _InactivityMessageClockSnapshots(collections
.abc
.Mapping
):
281 def __init__(self
, msg
):
284 def __getitem__(self
, clock_class
):
285 utils
._check
_type
(clock_class
, bt2
.ClockClass
)
286 clock_snapshot_ptr
= native_bt
.message_inactivity_get_clock_snapshot(self
._msg
._ptr
,
289 if clock_snapshot_ptr
is None:
292 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
293 return clock_snapshot
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
,
299 utils
._handle
_ret
(ret
, "cannot set inactivity message object's clock value")
302 return len(self
._msg
.clock_class_priority_map
)
305 return _InactivityMessageClockSnapshotsIterator(self
)
308 class InactivityMessage(_CopyableMessage
):
309 _TYPE
= native_bt
.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
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
316 cc_prio_map_ptr
= None
318 ptr
= native_bt
.message_inactivity_create(cc_prio_map_ptr
)
321 raise bt2
.CreationError('cannot create inactivity message object')
323 super().__init
__(ptr
)
326 def clock_class_priority_map(self
):
327 cc_prio_map_ptr
= native_bt
.message_inactivity_get_clock_class_priority_map(self
._ptr
)
328 assert(cc_prio_map_ptr
)
329 return bt2
.clock_class_priority_map
.ClockClassPriorityMap
._create
_from
_ptr
(cc_prio_map_ptr
)
332 def clock_snapshots(self
):
333 return _InactivityMessageClockSnapshots(self
)
335 def _get_clock_snapshots(self
):
338 for clock_class
, clock_snapshot
in self
.clock_snapshots
.items():
339 if clock_snapshot
is None:
342 clock_snapshots
[clock_class
] = clock_snapshot
344 return clock_snapshots
346 def __eq__(self
, other
):
347 if type(other
) is not type(self
):
350 if self
.addr
== other
.addr
:
354 self
.clock_class_priority_map
,
355 self
._get
_clock
_snapshots
(),
358 other
.clock_class_priority_map
,
359 other
._get
_clock
_snapshots
(),
361 return self_props
== other_props
364 cpy
= InactivityMessage(self
.clock_class_priority_map
)
366 for clock_class
, clock_snapshot
in self
.clock_snapshots
.items():
367 if clock_snapshot
is None:
370 cpy
.clock_snapshots
.add(clock_snapshot
)
374 def __deepcopy__(self
, memo
):
375 cc_prio_map_cpy
= copy
.deepcopy(self
.clock_class_priority_map
)
376 cpy
= InactivityMessage(cc_prio_map_cpy
)
379 for orig_clock_class
in self
.clock_class_priority_map
:
380 orig_clock_snapshot
= self
.clock_snapshot(orig_clock_class
)
382 if orig_clock_snapshot
is None:
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
:
390 # create copy of clock value from copied clock class
391 clock_snapshot_cpy
= cpy_clock_class(orig_clock_snapshot
.cycles
)
393 # set copied clock value in message copy
394 cpy
.clock_snapshots
.add(clock_snapshot_cpy
)
400 class _DiscardedElementsMessage(_Message
):
401 def __eq__(self
, other
):
402 if type(other
) is not type(self
):
405 if self
.addr
== other
.addr
:
411 self
.beginning_clock_snapshot
,
412 self
.end_clock_snapshot
,
417 other
.beginning_clock_snapshot
,
418 other
.end_clock_snapshot
,
420 return self_props
== other_props
423 class _DiscardedPacketsMessage(_DiscardedElementsMessage
):
424 _TYPE
= native_bt
.MESSAGE_TYPE_DISCARDED_PACKETS
428 count
= native_bt
.message_discarded_packets_get_count(self
._ptr
)
434 stream_ptr
= native_bt
.message_discarded_packets_get_stream(self
._ptr
)
436 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
439 def beginning_clock_snapshot(self
):
440 clock_snapshot_ptr
= native_bt
.message_discarded_packets_get_begin_clock_snapshot(self
._ptr
)
442 if clock_snapshot_ptr
is None:
445 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
446 return clock_snapshot
449 def end_clock_snapshot(self
):
450 clock_snapshot_ptr
= native_bt
.message_discarded_packets_get_end_clock_snapshot(self
._ptr
)
452 if clock_snapshot_ptr
is None:
455 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
456 return clock_snapshot
459 class _DiscardedEventsMessage(_DiscardedElementsMessage
):
460 _TYPE
= native_bt
.MESSAGE_TYPE_DISCARDED_EVENTS
464 count
= native_bt
.message_discarded_events_get_count(self
._ptr
)
470 stream_ptr
= native_bt
.message_discarded_events_get_stream(self
._ptr
)
472 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
475 def beginning_clock_snapshot(self
):
476 clock_snapshot_ptr
= native_bt
.message_discarded_events_get_begin_clock_snapshot(self
._ptr
)
478 if clock_snapshot_ptr
is None:
481 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
482 return clock_snapshot
485 def end_clock_snapshot(self
):
486 clock_snapshot_ptr
= native_bt
.message_discarded_events_get_end_clock_snapshot(self
._ptr
)
488 if clock_snapshot_ptr
is None:
491 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
492 return clock_snapshot
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
,