python: standardize intra-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
81447b5b
PP
15import bt2
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
PP
169 def __next__(self):
170 raise bt2.Stop
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
PP
176 except StopIteration:
177 raise bt2.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:
f5567ea8 283 raise bt2._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:
f5567ea8 294 raise bt2._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:
f5567ea8 303 raise bt2._MemoryError("cannot create stream beginning message object")
2ae9f48c 304
3fb99a22 305 msg = bt2_message._StreamBeginningMessage(ptr)
9ec609ec 306
188edac1
SM
307 if default_clock_snapshot is not None:
308 msg._default_clock_snapshot = default_clock_snapshot
9ec609ec 309
9ec609ec
SM
310 return msg
311
188edac1 312 def _create_stream_end_message(self, stream, default_clock_snapshot=None):
e5914347 313 bt2_utils._check_type(stream, bt2_stream._Stream)
5f25509b 314
85906b6b 315 ptr = native_bt.message_stream_end_create(self._bt_ptr, stream._ptr)
5f25509b 316 if ptr is None:
f5567ea8 317 raise bt2._MemoryError("cannot create stream end message object")
5f25509b 318
3fb99a22 319 msg = bt2_message._StreamEndMessage(ptr)
188edac1
SM
320
321 if default_clock_snapshot is not None:
322 msg._default_clock_snapshot = default_clock_snapshot
323
324 return msg
5f25509b 325
2ae9f48c 326 def _create_packet_beginning_message(self, packet, default_clock_snapshot=None):
e5914347 327 bt2_utils._check_type(packet, bt2_packet._Packet)
2ae9f48c 328
e8ac1aae 329 if packet.stream.cls.packets_have_beginning_default_clock_snapshot:
2ae9f48c 330 if default_clock_snapshot is None:
cfbd7cf3
FD
331 raise ValueError(
332 "packet beginning messages in this stream must have a default clock snapshot"
333 )
2ae9f48c 334
e5914347 335 bt2_utils._check_uint64(default_clock_snapshot)
2ae9f48c 336 ptr = native_bt.message_packet_beginning_create_with_default_clock_snapshot(
cfbd7cf3
FD
337 self._bt_ptr, packet._ptr, default_clock_snapshot
338 )
2ae9f48c
SM
339 else:
340 if default_clock_snapshot is not None:
cfbd7cf3
FD
341 raise ValueError(
342 "packet beginning messages in this stream must not have a default clock snapshot"
343 )
2ae9f48c 344
85906b6b 345 ptr = native_bt.message_packet_beginning_create(self._bt_ptr, packet._ptr)
2ae9f48c
SM
346
347 if ptr is None:
f5567ea8 348 raise bt2._MemoryError("cannot create packet beginning message object")
2ae9f48c 349
3fb99a22 350 return bt2_message._PacketBeginningMessage(ptr)
5f25509b
SM
351
352 def _create_packet_end_message(self, packet, default_clock_snapshot=None):
e5914347 353 bt2_utils._check_type(packet, bt2_packet._Packet)
5f25509b 354
e8ac1aae 355 if packet.stream.cls.packets_have_end_default_clock_snapshot:
9ec609ec 356 if default_clock_snapshot is None:
cfbd7cf3
FD
357 raise ValueError(
358 "packet end messages in this stream must have a default clock snapshot"
359 )
9ec609ec 360
e5914347 361 bt2_utils._check_uint64(default_clock_snapshot)
5f25509b 362 ptr = native_bt.message_packet_end_create_with_default_clock_snapshot(
cfbd7cf3
FD
363 self._bt_ptr, packet._ptr, default_clock_snapshot
364 )
5f25509b 365 else:
9ec609ec 366 if default_clock_snapshot is not None:
cfbd7cf3
FD
367 raise ValueError(
368 "packet end messages in this stream must not have a default clock snapshot"
369 )
9ec609ec 370
85906b6b 371 ptr = native_bt.message_packet_end_create(self._bt_ptr, packet._ptr)
5f25509b
SM
372
373 if ptr is None:
f5567ea8 374 raise bt2._MemoryError("cannot create packet end message object")
5f25509b 375
3fb99a22 376 return bt2_message._PacketEndMessage(ptr)
9ec609ec 377
cfbd7cf3
FD
378 def _create_discarded_events_message(
379 self, stream, count=None, beg_clock_snapshot=None, end_clock_snapshot=None
380 ):
e5914347 381 bt2_utils._check_type(stream, bt2_stream._Stream)
9ec609ec 382
e8ac1aae 383 if not stream.cls.supports_discarded_events:
f5567ea8 384 raise ValueError("stream class does not support discarded events")
2e90378a 385
e8ac1aae 386 if stream.cls.discarded_events_have_default_clock_snapshots:
2e90378a 387 if beg_clock_snapshot is None or end_clock_snapshot is None:
cfbd7cf3 388 raise ValueError(
f5567ea8 389 "discarded events have default clock snapshots for this stream class"
cfbd7cf3 390 )
2e90378a 391
e5914347
SM
392 bt2_utils._check_uint64(beg_clock_snapshot)
393 bt2_utils._check_uint64(end_clock_snapshot)
5d9ef4cb
SM
394
395 if beg_clock_snapshot > end_clock_snapshot:
396 raise ValueError(
f5567ea8 397 "beginning default clock snapshot value ({}) is greater than end default clock snapshot value ({})".format(
5d9ef4cb
SM
398 beg_clock_snapshot, end_clock_snapshot
399 )
400 )
401
776a2a25
PP
402 ptr = (
403 native_bt.message_discarded_events_create_with_default_clock_snapshots(
404 self._bt_ptr, stream._ptr, beg_clock_snapshot, end_clock_snapshot
405 )
cfbd7cf3 406 )
9ec609ec 407 else:
2e90378a 408 if beg_clock_snapshot is not None or end_clock_snapshot is not None:
cfbd7cf3 409 raise ValueError(
f5567ea8 410 "discarded events have no default clock snapshots for this stream class"
cfbd7cf3 411 )
2e90378a 412
cfbd7cf3 413 ptr = native_bt.message_discarded_events_create(self._bt_ptr, stream._ptr)
9ec609ec
SM
414
415 if ptr is None:
f5567ea8 416 raise bt2._MemoryError("cannot discarded events message object")
9ec609ec 417
3fb99a22 418 msg = bt2_message._DiscardedEventsMessage(ptr)
9ec609ec
SM
419
420 if count is not None:
421 msg._count = count
422
423 return msg
424
cfbd7cf3
FD
425 def _create_discarded_packets_message(
426 self, stream, count=None, beg_clock_snapshot=None, end_clock_snapshot=None
427 ):
e5914347 428 bt2_utils._check_type(stream, bt2_stream._Stream)
9ec609ec 429
e8ac1aae 430 if not stream.cls.supports_discarded_packets:
f5567ea8 431 raise ValueError("stream class does not support discarded packets")
2e90378a 432
e8ac1aae 433 if stream.cls.discarded_packets_have_default_clock_snapshots:
2e90378a 434 if beg_clock_snapshot is None or end_clock_snapshot is None:
cfbd7cf3 435 raise ValueError(
f5567ea8 436 "discarded packets have default clock snapshots for this stream class"
cfbd7cf3 437 )
2e90378a 438
e5914347
SM
439 bt2_utils._check_uint64(beg_clock_snapshot)
440 bt2_utils._check_uint64(end_clock_snapshot)
5d9ef4cb
SM
441
442 if beg_clock_snapshot > end_clock_snapshot:
443 raise ValueError(
f5567ea8 444 "beginning default clock snapshot value ({}) is greater than end default clock snapshot value ({})".format(
5d9ef4cb
SM
445 beg_clock_snapshot, end_clock_snapshot
446 )
447 )
448
776a2a25
PP
449 ptr = (
450 native_bt.message_discarded_packets_create_with_default_clock_snapshots(
451 self._bt_ptr, stream._ptr, beg_clock_snapshot, end_clock_snapshot
452 )
cfbd7cf3 453 )
9ec609ec 454 else:
2e90378a 455 if beg_clock_snapshot is not None or end_clock_snapshot is not None:
cfbd7cf3 456 raise ValueError(
f5567ea8 457 "discarded packets have no default clock snapshots for this stream class"
cfbd7cf3 458 )
2e90378a 459
cfbd7cf3 460 ptr = native_bt.message_discarded_packets_create(self._bt_ptr, stream._ptr)
9ec609ec
SM
461
462 if ptr is None:
f5567ea8 463 raise bt2._MemoryError("cannot discarded packets message object")
9ec609ec 464
3fb99a22 465 msg = bt2_message._DiscardedPacketsMessage(ptr)
9ec609ec
SM
466
467 if count is not None:
468 msg._count = count
469
470 return msg
This page took 0.106222 seconds and 4 git commands to generate.