bt2: add bt2._OutputPort.create_notification_iterator()
[babeltrace.git] / bindings / python / bt2 / bt2 / notification.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
811644b8 24import bt2.clock_class_priority_map
81447b5b
PP
25import bt2.packet
26import bt2.stream
27import bt2.event
811644b8 28import copy
81447b5b
PP
29import bt2
30
31
32def _create_from_ptr(ptr):
33 notif_type = native_bt.notification_get_type(ptr)
34 cls = None
35
36 if notif_type not in _NOTIF_TYPE_TO_CLS:
37 raise bt2.Error('unknown notification type: {}'.format(notif_type))
38
39 return _NOTIF_TYPE_TO_CLS[notif_type]._create_from_ptr(ptr)
40
41
dc43190b
PP
42def _notif_types_from_notif_classes(notification_types):
43 if notification_types is None:
44 notif_types = None
45 else:
46 for notif_cls in notification_types:
47 if notif_cls not in _NOTIF_TYPE_TO_CLS.values():
48 raise ValueError("'{}' is not a notification class".format(notif_cls))
49
50 notif_types = [notif_cls._TYPE for notif_cls in notification_types]
51
52 return notif_types
53
54
81447b5b
PP
55class _Notification(object._Object):
56 pass
57
58
811644b8
PP
59class _CopyableNotification(_Notification):
60 def __copy__(self):
61 return self._copy(lambda obj: obj)
62
63 def __deepcopy__(self, memo):
64 cpy = self._copy(copy.deepcopy)
65 memo[id(self)] = cpy
66 return cpy
67
68
69class EventNotification(_CopyableNotification):
70 _TYPE = native_bt.NOTIFICATION_TYPE_EVENT
71
72 def __init__(self, event, cc_prio_map=None):
81447b5b 73 utils._check_type(event, bt2.event._Event)
811644b8
PP
74
75 if cc_prio_map is not None:
76 utils._check_type(cc_prio_map, bt2.clock_class_priority_map.ClockClassPriorityMap)
77 cc_prio_map_ptr = cc_prio_map._ptr
78 else:
79 cc_prio_map_ptr = None
80
81 ptr = native_bt.notification_event_create(event._ptr, cc_prio_map_ptr)
81447b5b
PP
82
83 if ptr is None:
811644b8 84 raise bt2.CreationError('cannot create event notification object')
81447b5b
PP
85
86 super().__init__(ptr)
87
88 @property
89 def event(self):
90 event_ptr = native_bt.notification_event_get_event(self._ptr)
811644b8 91 assert(event_ptr)
81447b5b
PP
92 return bt2.event._create_from_ptr(event_ptr)
93
811644b8
PP
94 @property
95 def clock_class_priority_map(self):
96 cc_prio_map_ptr = native_bt.notification_event_get_clock_class_priority_map(self._ptr)
97 assert(cc_prio_map_ptr)
98 return bt2.clock_class_priority_map.ClockClassPriorityMap._create_from_ptr(cc_prio_map_ptr)
99
100 def __eq__(self, other):
101 if type(other) is not type(self):
102 return False
103
104 if self.addr == other.addr:
105 return True
106
107 self_props = (
108 self.event,
109 self.clock_class_priority_map,
110 )
111 other_props = (
112 other.event,
113 other.clock_class_priority_map,
114 )
115 return self_props == other_props
116
117 def _copy(self, copy_func):
118 # We can always use references here because those properties are
119 # frozen anyway if they are part of a notification. Since the
120 # user cannot modify them after copying the notification, it's
121 # useless to copy/deep-copy them.
122 return EventNotification(self.event, self.clock_class_priority_map)
123
124
125class PacketBeginningNotification(_CopyableNotification):
126 _TYPE = native_bt.NOTIFICATION_TYPE_PACKET_BEGIN
81447b5b 127
81447b5b
PP
128 def __init__(self, packet):
129 utils._check_type(packet, bt2.packet._Packet)
130 ptr = native_bt.notification_packet_begin_create(packet._ptr)
131
132 if ptr is None:
811644b8 133 raise bt2.CreationError('cannot create packet beginning notification object')
81447b5b
PP
134
135 super().__init__(ptr)
136
137 @property
138 def packet(self):
139 packet_ptr = native_bt.notification_packet_begin_get_packet(self._ptr)
811644b8 140 assert(packet_ptr)
81447b5b
PP
141 return bt2.packet._Packet._create_from_ptr(packet_ptr)
142
811644b8
PP
143 def __eq__(self, other):
144 if type(other) is not type(self):
145 return False
146
147 if self.addr == other.addr:
148 return True
149
150 return self.packet == other.packet
151
152 def _copy(self, copy_func):
153 # We can always use references here because those properties are
154 # frozen anyway if they are part of a notification. Since the
155 # user cannot modify them after copying the notification, it's
156 # useless to copy/deep-copy them.
157 return PacketBeginningNotification(self.packet)
158
159
160class PacketEndNotification(_CopyableNotification):
161 _TYPE = native_bt.NOTIFICATION_TYPE_PACKET_END
81447b5b 162
81447b5b
PP
163 def __init__(self, packet):
164 utils._check_type(packet, bt2.packet._Packet)
165 ptr = native_bt.notification_packet_end_create(packet._ptr)
166
167 if ptr is None:
811644b8 168 raise bt2.CreationError('cannot create packet end notification object')
81447b5b
PP
169
170 super().__init__(ptr)
171
172 @property
173 def packet(self):
174 packet_ptr = native_bt.notification_packet_end_get_packet(self._ptr)
811644b8 175 assert(packet_ptr)
81447b5b
PP
176 return bt2.packet._Packet._create_from_ptr(packet_ptr)
177
811644b8
PP
178 def __eq__(self, other):
179 if type(other) is not type(self):
180 return False
181
182 if self.addr == other.addr:
183 return True
184
185 return self.packet == other.packet
186
187 def _copy(self, copy_func):
188 # We can always use references here because those properties are
189 # frozen anyway if they are part of a notification. Since the
190 # user cannot modify them after copying the notification, it's
191 # useless to copy/deep-copy them.
192 return PacketEndNotification(self.packet)
193
194
195class StreamBeginningNotification(_CopyableNotification):
196 _TYPE = native_bt.NOTIFICATION_TYPE_STREAM_BEGIN
81447b5b 197
81447b5b
PP
198 def __init__(self, stream):
199 utils._check_type(stream, bt2.stream._Stream)
811644b8 200 ptr = native_bt.notification_stream_begin_create(stream._ptr)
81447b5b
PP
201
202 if ptr is None:
811644b8 203 raise bt2.CreationError('cannot create stream beginning notification object')
81447b5b
PP
204
205 super().__init__(ptr)
206
207 @property
208 def stream(self):
811644b8
PP
209 stream_ptr = native_bt.notification_stream_begin_get_stream(self._ptr)
210 assert(stream_ptr)
81447b5b
PP
211 return bt2.stream._create_from_ptr(stream_ptr)
212
811644b8
PP
213 def __eq__(self, other):
214 if type(other) is not type(self):
215 return False
216
217 if self.addr == other.addr:
218 return True
219
220 return self.stream == other.stream
221
222 def _copy(self, copy_func):
223 # We can always use references here because those properties are
224 # frozen anyway if they are part of a notification. Since the
225 # user cannot modify them after copying the notification, it's
226 # useless to copy/deep-copy them.
227 return StreamBeginningNotification(self.stream)
228
229
230class StreamEndNotification(_CopyableNotification):
231 _TYPE = native_bt.NOTIFICATION_TYPE_STREAM_END
81447b5b 232
811644b8
PP
233 def __init__(self, stream):
234 utils._check_type(stream, bt2.stream._Stream)
235 ptr = native_bt.notification_stream_end_create(stream._ptr)
81447b5b
PP
236
237 if ptr is None:
811644b8 238 raise bt2.CreationError('cannot create stream end notification object')
81447b5b
PP
239
240 super().__init__(ptr)
241
242 @property
811644b8
PP
243 def stream(self):
244 stream_ptr = native_bt.notification_stream_end_get_stream(self._ptr)
245 assert(stream_ptr)
246 return bt2.stream._create_from_ptr(stream_ptr)
247
248 def __eq__(self, other):
249 if type(other) is not type(self):
250 return False
251
252 if self.addr == other.addr:
253 return True
254
255 return self.stream == other.stream
256
257 def _copy(self, copy_func):
258 # We can always use references here because those properties are
259 # frozen anyway if they are part of a notification. Since the
260 # user cannot modify them after copying the notification, it's
261 # useless to copy/deep-copy them.
262 return StreamEndNotification(self.stream)
263
264
265class InactivityNotification(_CopyableNotification):
266 _TYPE = native_bt.NOTIFICATION_TYPE_INACTIVITY
81447b5b 267
811644b8
PP
268 def __init__(self, cc_prio_map=None):
269 if cc_prio_map is not None:
270 utils._check_type(cc_prio_map, bt2.clock_class_priority_map.ClockClassPriorityMap)
271 cc_prio_map_ptr = cc_prio_map._ptr
272 else:
273 cc_prio_map_ptr = None
81447b5b 274
811644b8 275 ptr = native_bt.notification_inactivity_create(cc_prio_map_ptr)
81447b5b
PP
276
277 if ptr is None:
811644b8 278 raise bt2.CreationError('cannot create inactivity notification object')
81447b5b
PP
279
280 super().__init__(ptr)
281
282 @property
811644b8
PP
283 def clock_class_priority_map(self):
284 cc_prio_map_ptr = native_bt.notification_inactivity_get_clock_class_priority_map(self._ptr)
285 assert(cc_prio_map_ptr)
286 return bt2.clock_class_priority_map.ClockClassPriorityMap._create_from_ptr(cc_prio_map_ptr)
287
288 def clock_value(self, clock_class):
289 utils._check_type(clock_class, bt2.ClockClass)
290 clock_value_ptr = native_bt.notification_inactivity_get_clock_value(self._ptr,
291 clock_class._ptr)
292
293 if clock_value_ptr is None:
294 return
295
296 clock_value = bt2.clock_class._create_clock_value_from_ptr(clock_value_ptr)
297 return clock_value
298
299 def add_clock_value(self, clock_value):
300 utils._check_type(clock_value, bt2.clock_class._ClockValue)
301 ret = native_bt.notification_inactivity_set_clock_value(self._ptr,
302 clock_value._ptr)
303 utils._handle_ret(ret, "cannot set inactivity notification object's clock value")
304
305 def _get_clock_values(self):
306 clock_values = {}
307
308 for clock_class in self.clock_class_priority_map:
309 clock_value = self.clock_value(clock_class)
310
311 if clock_value is None:
312 continue
313
314 clock_values[clock_class] = clock_value
315
316 return clock_values
317
318 def __eq__(self, other):
319 if type(other) is not type(self):
320 return False
321
322 if self.addr == other.addr:
323 return True
324
325 self_props = (
326 self.clock_class_priority_map,
327 self._get_clock_values(),
328 )
329 other_props = (
330 other.clock_class_priority_map,
331 other._get_clock_values(),
332 )
333 return self_props == other_props
334
335 def __copy__(self):
336 cpy = InactivityNotification(self.clock_class_priority_map)
337
338 for clock_class in self.clock_class_priority_map:
339 clock_value = self.clock_value(clock_class)
340
341 if clock_value is None:
342 continue
343
344 cpy.add_clock_value(clock_value)
345
346 return cpy
347
348 def __deepcopy__(self, memo):
349 cc_prio_map_cpy = copy.deepcopy(self.clock_class_priority_map)
350 cpy = InactivityNotification(cc_prio_map_cpy)
351
352 # copy clock values
353 for orig_clock_class in self.clock_class_priority_map:
354 orig_clock_value = self.clock_value(orig_clock_class)
355
356 if orig_clock_value is None:
357 continue
358
359 # find equivalent, copied clock class in CC priority map copy
360 for cpy_clock_class in cc_prio_map_cpy:
361 if cpy_clock_class == orig_clock_class:
362 break
363
364 # create copy of clock value from copied clock class
365 clock_value_cpy = cpy_clock_class(orig_clock_value.cycles)
366
367 # set copied clock value in notification copy
368 cpy.add_clock_value(clock_value_cpy)
369
370 memo[id(self)] = cpy
371 return cpy
372
373
374class _DiscardedElementsNotification(_Notification):
375 def __eq__(self, other):
376 if type(other) is not type(self):
377 return False
378
379 if self.addr == other.addr:
380 return True
381
382 self_props = (
383 self.count,
384 self.stream,
385 self.beginning_clock_value,
386 self.end_clock_value,
387 )
388 other_props = (
389 other.count,
390 other.stream,
391 other.beginning_clock_value,
392 other.end_clock_value,
393 )
394 return self_props == other_props
395
396
397class _DiscardedPacketsNotification(_DiscardedElementsNotification):
398 _TYPE = native_bt.NOTIFICATION_TYPE_DISCARDED_PACKETS
399
400 @property
401 def count(self):
402 count = native_bt.notification_discarded_packets_get_count(self._ptr)
403 assert(count >= 0)
404 return count
405
406 @property
407 def stream(self):
408 stream_ptr = native_bt.notification_discarded_packets_get_stream(self._ptr)
409 assert(stream_ptr)
410 return bt2.stream._create_from_ptr(stream_ptr)
411
412 @property
413 def beginning_clock_value(self):
414 clock_value_ptr = native_bt.notification_discarded_packets_get_begin_clock_value(self._ptr)
415
416 if clock_value_ptr is None:
417 return
418
419 clock_value = bt2.clock_class._create_clock_value_from_ptr(clock_value_ptr)
420 return clock_value
421
422 @property
423 def end_clock_value(self):
424 clock_value_ptr = native_bt.notification_discarded_packets_get_end_clock_value(self._ptr)
425
426 if clock_value_ptr is None:
427 return
428
429 clock_value = bt2.clock_class._create_clock_value_from_ptr(clock_value_ptr)
430 return clock_value
431
432
433class _DiscardedEventsNotification(_DiscardedElementsNotification):
434 _TYPE = native_bt.NOTIFICATION_TYPE_DISCARDED_EVENTS
435
436 @property
437 def count(self):
438 count = native_bt.notification_discarded_events_get_count(self._ptr)
439 assert(count >= 0)
440 return count
441
442 @property
443 def stream(self):
444 stream_ptr = native_bt.notification_discarded_events_get_stream(self._ptr)
445 assert(stream_ptr)
446 return bt2.stream._create_from_ptr(stream_ptr)
447
448 @property
449 def beginning_clock_value(self):
450 clock_value_ptr = native_bt.notification_discarded_events_get_begin_clock_value(self._ptr)
451
452 if clock_value_ptr is None:
453 return
454
455 clock_value = bt2.clock_class._create_clock_value_from_ptr(clock_value_ptr)
456 return clock_value
457
458 @property
459 def end_clock_value(self):
460 clock_value_ptr = native_bt.notification_discarded_events_get_end_clock_value(self._ptr)
461
462 if clock_value_ptr is None:
463 return
464
465 clock_value = bt2.clock_class._create_clock_value_from_ptr(clock_value_ptr)
466 return clock_value
81447b5b
PP
467
468
469_NOTIF_TYPE_TO_CLS = {
811644b8
PP
470 native_bt.NOTIFICATION_TYPE_EVENT: EventNotification,
471 native_bt.NOTIFICATION_TYPE_PACKET_BEGIN: PacketBeginningNotification,
472 native_bt.NOTIFICATION_TYPE_PACKET_END: PacketEndNotification,
473 native_bt.NOTIFICATION_TYPE_STREAM_BEGIN: StreamBeginningNotification,
474 native_bt.NOTIFICATION_TYPE_STREAM_END: StreamEndNotification,
475 native_bt.NOTIFICATION_TYPE_INACTIVITY: InactivityNotification,
476 native_bt.NOTIFICATION_TYPE_DISCARDED_PACKETS: _DiscardedPacketsNotification,
477 native_bt.NOTIFICATION_TYPE_DISCARDED_EVENTS: _DiscardedEventsNotification,
81447b5b 478}
This page took 0.048246 seconds and 4 git commands to generate.