python: remove internal `import bt2` imports
[babeltrace.git] / src / bindings / python / bt2 / bt2 / message_iterator.py
CommitLineData
0235b0db 1# SPDX-License-Identifier: MIT
81447b5b
PP
2#
3# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
81447b5b 4
e5914347
SM
5from bt2 import native_bt
6from bt2 import object as bt2_object
7from bt2 import utils as bt2_utils
3fb99a22 8from bt2 import message as bt2_message
81447b5b 9import collections.abc
3fb99a22
PP
10from bt2 import stream as bt2_stream
11from bt2 import event_class as bt2_event_class
12from bt2 import packet as bt2_packet
13from bt2 import port as bt2_port
14from bt2 import clock_class as bt2_clock_class
c345b078 15from bt2 import error as bt2_error
81447b5b
PP
16
17
5602ef81 18class _MessageIterator(collections.abc.Iterator):
81447b5b 19 def __next__(self):
811644b8 20 raise NotImplementedError
81447b5b
PP
21
22
e5914347
SM
23class _UserComponentInputPortMessageIterator(
24 bt2_object._SharedObject, _MessageIterator
25):
9dee90bd
SM
26 @staticmethod
27 def _get_ref(ptr):
28 native_bt.message_iterator_get_ref(ptr)
29
30 @staticmethod
31 def _put_ref(ptr):
32 native_bt.message_iterator_put_ref(ptr)
1975af3d 33
2ae9f48c 34 def __init__(self, ptr):
cfbd7cf3
FD
35 self._current_msgs = []
36 self._at = 0
37 super().__init__(ptr)
811644b8
PP
38
39 def __next__(self):
2ae9f48c 40 if len(self._current_msgs) == self._at:
1975af3d
SM
41 status, msgs = native_bt.bt2_self_component_port_input_get_msg_range(
42 self._ptr
43 )
e5914347 44 bt2_utils._handle_func_status(
f5567ea8 45 status, "unexpected error: cannot advance the message iterator"
cfbd7cf3 46 )
2ae9f48c
SM
47 self._current_msgs = msgs
48 self._at = 0
49
50 msg_ptr = self._current_msgs[self._at]
51 self._at += 1
52
3fb99a22 53 return bt2_message._create_from_ptr(msg_ptr)
81447b5b 54
f00b8d40 55 def can_seek_beginning(self):
9a2c8b8e 56 (status, res) = native_bt.message_iterator_can_seek_beginning(self._ptr)
e5914347 57 bt2_utils._handle_func_status(
f2fb1b32 58 status,
f5567ea8 59 "cannot check whether or not message iterator can seek its beginning",
f2fb1b32 60 )
f00b8d40
SM
61 return res != 0
62
63 def seek_beginning(self):
b6909b73 64 # Forget about buffered messages, they won't be valid after seeking.
f00b8d40
SM
65 self._current_msgs.clear()
66 self._at = 0
67
9a2c8b8e 68 status = native_bt.message_iterator_seek_beginning(self._ptr)
e5914347 69 bt2_utils._handle_func_status(status, "cannot seek message iterator beginning")
f00b8d40 70
c182d7dd 71 def can_seek_ns_from_origin(self, ns_from_origin):
e5914347 72 bt2_utils._check_int64(ns_from_origin)
9a2c8b8e 73 (status, res) = native_bt.message_iterator_can_seek_ns_from_origin(
c182d7dd
SM
74 self._ptr, ns_from_origin
75 )
e5914347 76 bt2_utils._handle_func_status(
c182d7dd 77 status,
f5567ea8 78 "cannot check whether or not message iterator can seek given ns from origin",
c182d7dd
SM
79 )
80 return res != 0
81
82 def seek_ns_from_origin(self, ns_from_origin):
e5914347 83 bt2_utils._check_int64(ns_from_origin)
c182d7dd
SM
84
85 # Forget about buffered messages, they won't be valid after seeking.
86 self._current_msgs.clear()
87 self._at = 0
88
9a2c8b8e 89 status = native_bt.message_iterator_seek_ns_from_origin(
c182d7dd
SM
90 self._ptr, ns_from_origin
91 )
e5914347 92 bt2_utils._handle_func_status(
f5567ea8 93 status, "message iterator cannot seek given ns from origin"
c182d7dd
SM
94 )
95
8d8b141d
SM
96 @property
97 def can_seek_forward(self):
9a2c8b8e 98 return native_bt.message_iterator_can_seek_forward(self._ptr)
8d8b141d
SM
99
100
101class _MessageIteratorConfiguration:
102 def __init__(self, ptr):
103 self._ptr = ptr
104
105 def can_seek_forward(self, value):
e5914347 106 bt2_utils._check_bool(value)
8d8b141d
SM
107 native_bt.self_message_iterator_configuration_set_can_seek_forward(
108 self._ptr, value
109 )
110
111 can_seek_forward = property(fset=can_seek_forward)
112
811644b8 113
c5f330cd
SM
114# This is extended by the user to implement component classes in Python. It
115# is created for a given output port when an input port message iterator is
7a2d4e2d 116# created on the input port on the other side of the connection.
c5f330cd
SM
117#
118# Its purpose is to feed the messages that should go out through this output
119# port.
5602ef81 120class _UserMessageIterator(_MessageIterator):
81447b5b 121 def __new__(cls, ptr):
811644b8 122 # User iterator objects are always created by the native side,
81447b5b
PP
123 # that is, never instantiated directly by Python code.
124 #
811644b8
PP
125 # The native code calls this, then manually calls
126 # self.__init__() without the `ptr` argument. The user has
127 # access to self.component during this call, thanks to this
85906b6b 128 # self._bt_ptr argument being set.
81447b5b 129 #
85906b6b 130 # self._bt_ptr is NOT owned by this object here, so there's nothing
81447b5b
PP
131 # to do in __del__().
132 self = super().__new__(cls)
85906b6b 133 self._bt_ptr = ptr
81447b5b
PP
134 return self
135
8d8b141d 136 def _bt_init_from_native(self, config_ptr, self_output_port_ptr):
3fb99a22 137 self_output_port = bt2_port._create_self_from_ptr_and_get_ref(
cfbd7cf3
FD
138 self_output_port_ptr, native_bt.PORT_TYPE_OUTPUT
139 )
8d8b141d
SM
140 config = _MessageIteratorConfiguration(config_ptr)
141 self.__init__(config, self_output_port)
c5f330cd 142
8d8b141d 143 def __init__(self, config, self_output_port):
81447b5b
PP
144 pass
145
146 @property
811644b8 147 def _component(self):
85906b6b 148 return native_bt.bt2_get_user_component_from_user_msg_iter(self._bt_ptr)
81447b5b 149
14503fb1
SM
150 @property
151 def _port(self):
152 port_ptr = native_bt.self_message_iterator_borrow_port(self._bt_ptr)
153 assert port_ptr is not None
154 return bt2_port._create_self_from_ptr_and_get_ref(
155 port_ptr, native_bt.PORT_TYPE_OUTPUT
156 )
157
81447b5b
PP
158 @property
159 def addr(self):
85906b6b 160 return int(self._bt_ptr)
81447b5b 161
9b4f9b42
PP
162 @property
163 def _is_interrupted(self):
164 return bool(native_bt.self_message_iterator_is_interrupted(self._bt_ptr))
165
6a91742b 166 def _user_finalize(self):
81447b5b
PP
167 pass
168
811644b8 169 def __next__(self):
c345b078 170 raise bt2_utils.Stop
811644b8 171
85906b6b 172 def _bt_next_from_native(self):
811644b8
PP
173 # this can raise anything: it's catched by the native part
174 try:
5602ef81 175 msg = next(self)
811644b8 176 except StopIteration:
c345b078 177 raise bt2_utils.Stop
4c4935bf 178 except Exception:
811644b8
PP
179 raise
180
e5914347 181 bt2_utils._check_type(msg, bt2_message._MessageConst)
81447b5b 182
d79a8353
SM
183 # The reference we return will be given to the message array.
184 # However, the `msg` Python object may stay alive, if the user has kept
185 # a reference to it. Acquire a new reference to account for that.
186 msg._get_ref(msg._ptr)
187 return int(msg._ptr)
2ae9f48c 188
85906b6b 189 def _bt_can_seek_beginning_from_native(self):
f00b8d40
SM
190 # Here, we mimic the behavior of the C API:
191 #
14cfc8ce 192 # - If the iterator has a _user_can_seek_beginning method,
6a91742b 193 # read it and use that result.
5a096c63 194 # - Otherwise, the presence or absence of a `_user_seek_beginning`
f00b8d40 195 # method indicates whether the iterator can seek beginning.
f5567ea8 196 if hasattr(self, "_user_can_seek_beginning"):
14cfc8ce 197 can_seek_beginning = self._user_can_seek_beginning()
e5914347 198 bt2_utils._check_bool(can_seek_beginning)
f00b8d40
SM
199 return can_seek_beginning
200 else:
f5567ea8 201 return hasattr(self, "_user_seek_beginning")
f00b8d40 202
85906b6b 203 def _bt_seek_beginning_from_native(self):
6a91742b 204 self._user_seek_beginning()
f00b8d40 205
c182d7dd 206 def _bt_can_seek_ns_from_origin_from_native(self, ns_from_origin):
c0e46a7c
SM
207 # Return whether the iterator can seek ns from origin using the
208 # user-implemented seek_ns_from_origin method. We mimic the behavior
209 # of the C API:
c182d7dd
SM
210 #
211 # - If the iterator has a _user_can_seek_ns_from_origin method,
212 # call it and use its return value.
213 # - Otherwise, if there is a `_user_seek_ns_from_origin` method,
214 # we presume it's possible.
c0e46a7c 215
f5567ea8 216 if hasattr(self, "_user_can_seek_ns_from_origin"):
c182d7dd 217 can_seek_ns_from_origin = self._user_can_seek_ns_from_origin(ns_from_origin)
e5914347 218 bt2_utils._check_bool(can_seek_ns_from_origin)
c182d7dd 219 return can_seek_ns_from_origin
c182d7dd 220 else:
f5567ea8 221 return hasattr(self, "_user_seek_ns_from_origin")
c182d7dd
SM
222
223 def _bt_seek_ns_from_origin_from_native(self, ns_from_origin):
224 self._user_seek_ns_from_origin(ns_from_origin)
225
9a2c8b8e 226 def _create_message_iterator(self, input_port):
e5914347 227 bt2_utils._check_type(input_port, bt2_port._UserComponentInputPort)
ca02df0a 228
415d43a1 229 if not input_port.is_connected:
f5567ea8 230 raise ValueError("input port is not connected")
415d43a1 231
75882e97
FD
232 (
233 status,
234 msg_iter_ptr,
9a2c8b8e 235 ) = native_bt.bt2_message_iterator_create_from_message_iterator(
ca02df0a
PP
236 self._bt_ptr, input_port._ptr
237 )
e5914347 238 bt2_utils._handle_func_status(status, "cannot create message iterator object")
e803df70 239 assert msg_iter_ptr is not None
ca02df0a
PP
240
241 return _UserComponentInputPortMessageIterator(msg_iter_ptr)
242
36d9460d 243 def _create_event_message(self, event_class, parent, default_clock_snapshot=None):
e5914347 244 bt2_utils._check_type(event_class, bt2_event_class._EventClass)
26fc5aed
PP
245
246 if event_class.stream_class.supports_packets:
e5914347 247 bt2_utils._check_type(parent, bt2_packet._Packet)
26fc5aed 248 else:
e5914347 249 bt2_utils._check_type(parent, bt2_stream._Stream)
2ae9f48c
SM
250
251 if default_clock_snapshot is not None:
c6af194f 252 if event_class.stream_class.default_clock_class is None:
cfbd7cf3 253 raise ValueError(
f5567ea8 254 "event messages in this stream must not have a default clock snapshot"
cfbd7cf3 255 )
c6af194f 256
e5914347 257 bt2_utils._check_uint64(default_clock_snapshot)
26fc5aed
PP
258
259 if event_class.stream_class.supports_packets:
260 ptr = native_bt.message_event_create_with_packet_and_default_clock_snapshot(
cfbd7cf3
FD
261 self._bt_ptr, event_class._ptr, parent._ptr, default_clock_snapshot
262 )
26fc5aed
PP
263 else:
264 ptr = native_bt.message_event_create_with_default_clock_snapshot(
cfbd7cf3
FD
265 self._bt_ptr, event_class._ptr, parent._ptr, default_clock_snapshot
266 )
2ae9f48c 267 else:
c6af194f 268 if event_class.stream_class.default_clock_class is not None:
cfbd7cf3 269 raise ValueError(
f5567ea8 270 "event messages in this stream must have a default clock snapshot"
cfbd7cf3 271 )
c6af194f 272
26fc5aed
PP
273 if event_class.stream_class.supports_packets:
274 ptr = native_bt.message_event_create_with_packet(
cfbd7cf3
FD
275 self._bt_ptr, event_class._ptr, parent._ptr
276 )
26fc5aed
PP
277 else:
278 ptr = native_bt.message_event_create(
cfbd7cf3
FD
279 self._bt_ptr, event_class._ptr, parent._ptr
280 )
2ae9f48c
SM
281
282 if ptr is None:
c345b078 283 raise bt2_error._MemoryError("cannot create event message object")
2ae9f48c 284
3fb99a22 285 return bt2_message._EventMessage(ptr)
2ae9f48c 286
9ec609ec 287 def _create_message_iterator_inactivity_message(self, clock_class, clock_snapshot):
e5914347 288 bt2_utils._check_type(clock_class, bt2_clock_class._ClockClass)
9ec609ec 289 ptr = native_bt.message_message_iterator_inactivity_create(
cfbd7cf3
FD
290 self._bt_ptr, clock_class._ptr, clock_snapshot
291 )
9ec609ec
SM
292
293 if ptr is None:
c345b078 294 raise bt2_error._MemoryError("cannot create inactivity message object")
9ec609ec 295
3fb99a22 296 return bt2_message._MessageIteratorInactivityMessage(ptr)
9ec609ec 297
188edac1 298 def _create_stream_beginning_message(self, stream, default_clock_snapshot=None):
e5914347 299 bt2_utils._check_type(stream, bt2_stream._Stream)
2ae9f48c 300
85906b6b 301 ptr = native_bt.message_stream_beginning_create(self._bt_ptr, stream._ptr)
2ae9f48c 302 if ptr is None:
c345b078
SM
303 raise bt2_error._MemoryError(
304 "cannot create stream beginning message object"
305 )
2ae9f48c 306
3fb99a22 307 msg = bt2_message._StreamBeginningMessage(ptr)
9ec609ec 308
188edac1
SM
309 if default_clock_snapshot is not None:
310 msg._default_clock_snapshot = default_clock_snapshot
9ec609ec 311
9ec609ec
SM
312 return msg
313
188edac1 314 def _create_stream_end_message(self, stream, default_clock_snapshot=None):
e5914347 315 bt2_utils._check_type(stream, bt2_stream._Stream)
5f25509b 316
85906b6b 317 ptr = native_bt.message_stream_end_create(self._bt_ptr, stream._ptr)
5f25509b 318 if ptr is None:
c345b078 319 raise bt2_error._MemoryError("cannot create stream end message object")
5f25509b 320
3fb99a22 321 msg = bt2_message._StreamEndMessage(ptr)
188edac1
SM
322
323 if default_clock_snapshot is not None:
324 msg._default_clock_snapshot = default_clock_snapshot
325
326 return msg
5f25509b 327
2ae9f48c 328 def _create_packet_beginning_message(self, packet, default_clock_snapshot=None):
e5914347 329 bt2_utils._check_type(packet, bt2_packet._Packet)
2ae9f48c 330
e8ac1aae 331 if packet.stream.cls.packets_have_beginning_default_clock_snapshot:
2ae9f48c 332 if default_clock_snapshot is None:
cfbd7cf3
FD
333 raise ValueError(
334 "packet beginning messages in this stream must have a default clock snapshot"
335 )
2ae9f48c 336
e5914347 337 bt2_utils._check_uint64(default_clock_snapshot)
2ae9f48c 338 ptr = native_bt.message_packet_beginning_create_with_default_clock_snapshot(
cfbd7cf3
FD
339 self._bt_ptr, packet._ptr, default_clock_snapshot
340 )
2ae9f48c
SM
341 else:
342 if default_clock_snapshot is not None:
cfbd7cf3
FD
343 raise ValueError(
344 "packet beginning messages in this stream must not have a default clock snapshot"
345 )
2ae9f48c 346
85906b6b 347 ptr = native_bt.message_packet_beginning_create(self._bt_ptr, packet._ptr)
2ae9f48c
SM
348
349 if ptr is None:
c345b078
SM
350 raise bt2_error._MemoryError(
351 "cannot create packet beginning message object"
352 )
2ae9f48c 353
3fb99a22 354 return bt2_message._PacketBeginningMessage(ptr)
5f25509b
SM
355
356 def _create_packet_end_message(self, packet, default_clock_snapshot=None):
e5914347 357 bt2_utils._check_type(packet, bt2_packet._Packet)
5f25509b 358
e8ac1aae 359 if packet.stream.cls.packets_have_end_default_clock_snapshot:
9ec609ec 360 if default_clock_snapshot is None:
cfbd7cf3
FD
361 raise ValueError(
362 "packet end messages in this stream must have a default clock snapshot"
363 )
9ec609ec 364
e5914347 365 bt2_utils._check_uint64(default_clock_snapshot)
5f25509b 366 ptr = native_bt.message_packet_end_create_with_default_clock_snapshot(
cfbd7cf3
FD
367 self._bt_ptr, packet._ptr, default_clock_snapshot
368 )
5f25509b 369 else:
9ec609ec 370 if default_clock_snapshot is not None:
cfbd7cf3
FD
371 raise ValueError(
372 "packet end messages in this stream must not have a default clock snapshot"
373 )
9ec609ec 374
85906b6b 375 ptr = native_bt.message_packet_end_create(self._bt_ptr, packet._ptr)
5f25509b
SM
376
377 if ptr is None:
c345b078 378 raise bt2_error._MemoryError("cannot create packet end message object")
5f25509b 379
3fb99a22 380 return bt2_message._PacketEndMessage(ptr)
9ec609ec 381
cfbd7cf3
FD
382 def _create_discarded_events_message(
383 self, stream, count=None, beg_clock_snapshot=None, end_clock_snapshot=None
384 ):
e5914347 385 bt2_utils._check_type(stream, bt2_stream._Stream)
9ec609ec 386
e8ac1aae 387 if not stream.cls.supports_discarded_events:
f5567ea8 388 raise ValueError("stream class does not support discarded events")
2e90378a 389
e8ac1aae 390 if stream.cls.discarded_events_have_default_clock_snapshots:
2e90378a 391 if beg_clock_snapshot is None or end_clock_snapshot is None:
cfbd7cf3 392 raise ValueError(
f5567ea8 393 "discarded events have default clock snapshots for this stream class"
cfbd7cf3 394 )
2e90378a 395
e5914347
SM
396 bt2_utils._check_uint64(beg_clock_snapshot)
397 bt2_utils._check_uint64(end_clock_snapshot)
5d9ef4cb
SM
398
399 if beg_clock_snapshot > end_clock_snapshot:
400 raise ValueError(
f5567ea8 401 "beginning default clock snapshot value ({}) is greater than end default clock snapshot value ({})".format(
5d9ef4cb
SM
402 beg_clock_snapshot, end_clock_snapshot
403 )
404 )
405
776a2a25
PP
406 ptr = (
407 native_bt.message_discarded_events_create_with_default_clock_snapshots(
408 self._bt_ptr, stream._ptr, beg_clock_snapshot, end_clock_snapshot
409 )
cfbd7cf3 410 )
9ec609ec 411 else:
2e90378a 412 if beg_clock_snapshot is not None or end_clock_snapshot is not None:
cfbd7cf3 413 raise ValueError(
f5567ea8 414 "discarded events have no default clock snapshots for this stream class"
cfbd7cf3 415 )
2e90378a 416
cfbd7cf3 417 ptr = native_bt.message_discarded_events_create(self._bt_ptr, stream._ptr)
9ec609ec
SM
418
419 if ptr is None:
c345b078 420 raise bt2_error._MemoryError("cannot discarded events message object")
9ec609ec 421
3fb99a22 422 msg = bt2_message._DiscardedEventsMessage(ptr)
9ec609ec
SM
423
424 if count is not None:
425 msg._count = count
426
427 return msg
428
cfbd7cf3
FD
429 def _create_discarded_packets_message(
430 self, stream, count=None, beg_clock_snapshot=None, end_clock_snapshot=None
431 ):
e5914347 432 bt2_utils._check_type(stream, bt2_stream._Stream)
9ec609ec 433
e8ac1aae 434 if not stream.cls.supports_discarded_packets:
f5567ea8 435 raise ValueError("stream class does not support discarded packets")
2e90378a 436
e8ac1aae 437 if stream.cls.discarded_packets_have_default_clock_snapshots:
2e90378a 438 if beg_clock_snapshot is None or end_clock_snapshot is None:
cfbd7cf3 439 raise ValueError(
f5567ea8 440 "discarded packets have default clock snapshots for this stream class"
cfbd7cf3 441 )
2e90378a 442
e5914347
SM
443 bt2_utils._check_uint64(beg_clock_snapshot)
444 bt2_utils._check_uint64(end_clock_snapshot)
5d9ef4cb
SM
445
446 if beg_clock_snapshot > end_clock_snapshot:
447 raise ValueError(
f5567ea8 448 "beginning default clock snapshot value ({}) is greater than end default clock snapshot value ({})".format(
5d9ef4cb
SM
449 beg_clock_snapshot, end_clock_snapshot
450 )
451 )
452
776a2a25
PP
453 ptr = (
454 native_bt.message_discarded_packets_create_with_default_clock_snapshots(
455 self._bt_ptr, stream._ptr, beg_clock_snapshot, end_clock_snapshot
456 )
cfbd7cf3 457 )
9ec609ec 458 else:
2e90378a 459 if beg_clock_snapshot is not None or end_clock_snapshot is not None:
cfbd7cf3 460 raise ValueError(
f5567ea8 461 "discarded packets have no default clock snapshots for this stream class"
cfbd7cf3 462 )
2e90378a 463
cfbd7cf3 464 ptr = native_bt.message_discarded_packets_create(self._bt_ptr, stream._ptr)
9ec609ec
SM
465
466 if ptr is None:
c345b078 467 raise bt2_error._MemoryError("cannot discarded packets message object")
9ec609ec 468
3fb99a22 469 msg = bt2_message._DiscardedPacketsMessage(ptr)
9ec609ec
SM
470
471 if count is not None:
472 msg._count = count
473
474 return msg
This page took 0.110783 seconds and 4 git commands to generate.