Fix: bt2: pass _TraceClassConst to destruction listeners
[babeltrace.git] / src / bindings / python / bt2 / bt2 / trace_class.py
CommitLineData
0bee8ea9
SM
1# The MIT License (MIT)
2#
3# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
4# Copyright (c) 2018 Francis Deslauriers <francis.deslauriers@efficios.com>
5# Copyright (c) 2019 Simon Marchi <simon.marchi@efficios.com>
6#
7# Permission is hereby granted, free of charge, to any person obtaining a copy
8# of this software and associated documentation files (the "Software"), to deal
9# in the Software without restriction, including without limitation the rights
10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11# copies of the Software, and to permit persons to whom the Software is
12# furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23# THE SOFTWARE.
24
0bee8ea9 25from bt2 import native_bt, utils, object
c946c9de
PP
26from bt2 import stream_class as bt2_stream_class
27from bt2 import field_class as bt2_field_class
467673c1 28from bt2 import integer_range_set as bt2_integer_range_set
c946c9de 29from bt2 import trace as bt2_trace
b2df5780 30from bt2 import value as bt2_value
0bee8ea9
SM
31import collections.abc
32import functools
9cbe0c59 33import bt2
0bee8ea9
SM
34
35
d4024c86
SM
36def _trace_class_destruction_listener_from_native(
37 user_listener, handle, trace_class_ptr
38):
eead7a76 39 trace_class = _TraceClassConst._create_from_ptr_and_get_ref(trace_class_ptr)
0bee8ea9 40 user_listener(trace_class)
d4024c86 41 handle._invalidate()
0bee8ea9
SM
42
43
9cbe0c59 44class _TraceClassConst(object._SharedObject, collections.abc.Mapping):
0bee8ea9
SM
45 _get_ref = staticmethod(native_bt.trace_class_get_ref)
46 _put_ref = staticmethod(native_bt.trace_class_put_ref)
9cbe0c59
FD
47 _borrow_stream_class_ptr_by_index = staticmethod(
48 native_bt.trace_class_borrow_stream_class_by_index_const
49 )
50 _borrow_stream_class_ptr_by_id = staticmethod(
51 native_bt.trace_class_borrow_stream_class_by_id_const
52 )
a6f93683
SM
53 _borrow_user_attributes_ptr = staticmethod(
54 native_bt.trace_class_borrow_user_attributes_const
55 )
9cbe0c59
FD
56 _stream_class_pycls = bt2_stream_class._StreamClassConst
57 _create_value_from_ptr_and_get_ref = staticmethod(
58 bt2_value._create_from_const_ptr_and_get_ref
59 )
0bee8ea9 60
9cbe0c59
FD
61 @property
62 def user_attributes(self):
a6f93683 63 ptr = self._borrow_user_attributes_ptr(self._ptr)
9cbe0c59
FD
64 assert ptr is not None
65 return self._create_value_from_ptr_and_get_ref(ptr)
f377a958 66
0bee8ea9
SM
67 # Number of stream classes in this trace class.
68
69 def __len__(self):
70 count = native_bt.trace_class_get_stream_class_count(self._ptr)
71 assert count >= 0
72 return count
73
74 # Get a stream class by stream id.
75
76 def __getitem__(self, key):
77 utils._check_uint64(key)
78
9cbe0c59 79 sc_ptr = self._borrow_stream_class_ptr_by_id(self._ptr, key)
0bee8ea9
SM
80 if sc_ptr is None:
81 raise KeyError(key)
82
9cbe0c59 83 return self._stream_class_pycls._create_from_ptr_and_get_ref(sc_ptr)
0bee8ea9
SM
84
85 def __iter__(self):
86 for idx in range(len(self)):
9cbe0c59 87 sc_ptr = self._borrow_stream_class_ptr_by_index(self._ptr, idx)
0bee8ea9
SM
88 assert sc_ptr is not None
89
90 id = native_bt.stream_class_get_id(sc_ptr)
91 assert id >= 0
92
93 yield id
94
9cbe0c59
FD
95 @property
96 def assigns_automatic_stream_class_id(self):
97 return native_bt.trace_class_assigns_automatic_stream_class_id(self._ptr)
98
99 # Add a listener to be called when the trace class is destroyed.
100
101 def add_destruction_listener(self, listener):
102
103 if not callable(listener):
104 raise TypeError("'listener' parameter is not callable")
105
d4024c86
SM
106 handle = utils._ListenerHandle(self.addr)
107
9cbe0c59 108 listener_from_native = functools.partial(
d4024c86 109 _trace_class_destruction_listener_from_native, listener, handle
9cbe0c59
FD
110 )
111
d4024c86 112 fn = native_bt.bt2_trace_class_add_destruction_listener
9cbe0c59
FD
113 status, listener_id = fn(self._ptr, listener_from_native)
114 utils._handle_func_status(
115 status, 'cannot add destruction listener to trace class object'
116 )
117
d4024c86
SM
118 handle._set_listener_id(listener_id)
119
120 return handle
9cbe0c59 121
ab778b5c
SM
122 def remove_destruction_listener(self, listener_handle):
123 utils._check_type(listener_handle, utils._ListenerHandle)
124
d4024c86 125 if listener_handle._addr != self.addr:
ab778b5c 126 raise ValueError(
7a16abe7 127 'This trace class destruction listener does not match the trace class object.'
ab778b5c
SM
128 )
129
130 if listener_handle._listener_id is None:
131 raise ValueError(
132 'This trace class destruction listener was already removed.'
133 )
134
135 status = native_bt.trace_class_remove_destruction_listener(
136 self._ptr, listener_handle._listener_id
137 )
138 utils._handle_func_status(status)
d4024c86 139 listener_handle._invalidate()
ab778b5c 140
9cbe0c59
FD
141
142class _TraceClass(_TraceClassConst):
143 _borrow_stream_class_ptr_by_index = staticmethod(
144 native_bt.trace_class_borrow_stream_class_by_index
145 )
146 _borrow_stream_class_ptr_by_id = staticmethod(
147 native_bt.trace_class_borrow_stream_class_by_id
148 )
a6f93683
SM
149 _borrow_user_attributes_ptr = staticmethod(
150 native_bt.trace_class_borrow_user_attributes
151 )
9cbe0c59
FD
152 _stream_class_pycls = bt2_stream_class._StreamClass
153 _create_value_from_ptr_and_get_ref = staticmethod(
154 bt2_value._create_from_ptr_and_get_ref
155 )
156
157 # Instantiate a trace of this class.
158
159 def __call__(self, name=None, user_attributes=None, uuid=None, environment=None):
160 trace_ptr = native_bt.trace_create(self._ptr)
161
162 if trace_ptr is None:
163 raise bt2._MemoryError('cannot create trace class object')
164
165 trace = bt2_trace._Trace._create_from_ptr(trace_ptr)
166
167 if name is not None:
168 trace._name = name
169
170 if user_attributes is not None:
171 trace._user_attributes = user_attributes
172
173 if uuid is not None:
174 trace._uuid = uuid
175
176 if environment is not None:
177 for key, value in environment.items():
178 trace.environment[key] = value
179
180 return trace
181
61d96b89
FD
182 def create_stream_class(
183 self,
184 id=None,
185 name=None,
b2df5780 186 user_attributes=None,
61d96b89
FD
187 packet_context_field_class=None,
188 event_common_context_field_class=None,
189 default_clock_class=None,
190 assigns_automatic_event_class_id=True,
191 assigns_automatic_stream_id=True,
192 supports_packets=False,
193 packets_have_beginning_default_clock_snapshot=False,
194 packets_have_end_default_clock_snapshot=False,
195 supports_discarded_events=False,
196 discarded_events_have_default_clock_snapshots=False,
197 supports_discarded_packets=False,
198 discarded_packets_have_default_clock_snapshots=False,
199 ):
a373e036
SM
200 # Validate parameters before we create the object.
201 bt2_stream_class._StreamClass._validate_create_params(
202 name,
203 user_attributes,
204 packet_context_field_class,
205 event_common_context_field_class,
206 default_clock_class,
207 assigns_automatic_event_class_id,
208 assigns_automatic_stream_id,
209 supports_packets,
210 packets_have_beginning_default_clock_snapshot,
211 packets_have_end_default_clock_snapshot,
212 supports_discarded_events,
213 discarded_events_have_default_clock_snapshots,
214 supports_discarded_packets,
215 discarded_packets_have_default_clock_snapshots,
216 )
0bee8ea9
SM
217
218 if self.assigns_automatic_stream_class_id:
219 if id is not None:
61d96b89
FD
220 raise ValueError(
221 'id provided, but trace class assigns automatic stream class ids'
222 )
0bee8ea9
SM
223
224 sc_ptr = native_bt.stream_class_create(self._ptr)
225 else:
226 if id is None:
61d96b89
FD
227 raise ValueError(
228 'id not provided, but trace class does not assign automatic stream class ids'
229 )
0bee8ea9
SM
230
231 utils._check_uint64(id)
232 sc_ptr = native_bt.stream_class_create_with_id(self._ptr, id)
233
c946c9de 234 sc = bt2_stream_class._StreamClass._create_from_ptr(sc_ptr)
f377a958 235
060aee52
SM
236 if name is not None:
237 sc._name = name
238
b2df5780
PP
239 if user_attributes is not None:
240 sc._user_attributes = user_attributes
241
060aee52
SM
242 if event_common_context_field_class is not None:
243 sc._event_common_context_field_class = event_common_context_field_class
244
245 if default_clock_class is not None:
246 sc._default_clock_class = default_clock_class
247
37a93d41
PP
248 # call after `sc._default_clock_class` because, if
249 # `packets_have_beginning_default_clock_snapshot` or
250 # `packets_have_end_default_clock_snapshot` is true, then this
251 # stream class needs a default clock class already.
61d96b89
FD
252 sc._set_supports_packets(
253 supports_packets,
254 packets_have_beginning_default_clock_snapshot,
255 packets_have_end_default_clock_snapshot,
256 )
37a93d41
PP
257
258 # call after sc._set_supports_packets() because, if
259 # `packet_context_field_class` is not `None`, then this stream
260 # class needs to support packets already.
261 if packet_context_field_class is not None:
262 sc._packet_context_field_class = packet_context_field_class
263
060aee52 264 sc._assigns_automatic_event_class_id = assigns_automatic_event_class_id
f377a958 265 sc._assigns_automatic_stream_id = assigns_automatic_stream_id
61d96b89
FD
266 sc._set_supports_discarded_events(
267 supports_discarded_events, discarded_events_have_default_clock_snapshots
268 )
269 sc._set_supports_discarded_packets(
270 supports_discarded_packets, discarded_packets_have_default_clock_snapshots
271 )
f377a958 272 return sc
0bee8ea9 273
b2df5780
PP
274 def _user_attributes(self, user_attributes):
275 value = bt2_value.create_value(user_attributes)
276 utils._check_type(value, bt2_value.MapValue)
277 native_bt.trace_class_set_user_attributes(self._ptr, value._ptr)
278
279 _user_attributes = property(fset=_user_attributes)
280
0bee8ea9
SM
281 def _assigns_automatic_stream_class_id(self, auto_id):
282 utils._check_bool(auto_id)
61d96b89
FD
283 return native_bt.trace_class_set_assigns_automatic_stream_class_id(
284 self._ptr, auto_id
285 )
0bee8ea9 286
61d96b89
FD
287 _assigns_automatic_stream_class_id = property(
288 fset=_assigns_automatic_stream_class_id
289 )
0bee8ea9 290
060aee52
SM
291 # Field class creation methods.
292
a07f15cb 293 def _check_field_class_create_status(self, ptr, type_name):
060aee52 294 if ptr is None:
614743a5 295 raise bt2._MemoryError('cannot create {} field class'.format(type_name))
060aee52 296
b2df5780
PP
297 @staticmethod
298 def _set_field_class_user_attrs(fc, user_attributes):
299 if user_attributes is not None:
300 fc._user_attributes = user_attributes
301
302 def create_bool_field_class(self, user_attributes=None):
a07f15cb
PP
303 field_class_ptr = native_bt.field_class_bool_create(self._ptr)
304 self._check_field_class_create_status(field_class_ptr, 'boolean')
b2df5780
PP
305 fc = bt2_field_class._BoolFieldClass._create_from_ptr(field_class_ptr)
306 self._set_field_class_user_attrs(fc, user_attributes)
307 return fc
a07f15cb 308
b2df5780 309 def create_bit_array_field_class(self, length, user_attributes=None):
6b29f2d4
PP
310 utils._check_uint64(length)
311
312 if length < 1 or length > 64:
313 raise ValueError(
314 'invalid length {}: expecting a value in the [1, 64] range'.format(
315 length
316 )
317 )
318
319 field_class_ptr = native_bt.field_class_bit_array_create(self._ptr, length)
320 self._check_field_class_create_status(field_class_ptr, 'bit array')
b2df5780
PP
321 fc = bt2_field_class._BitArrayFieldClass._create_from_ptr(field_class_ptr)
322 self._set_field_class_user_attrs(fc, user_attributes)
323 return fc
6b29f2d4 324
61d96b89 325 def _create_integer_field_class(
b2df5780
PP
326 self,
327 create_func,
328 py_cls,
329 type_name,
330 field_value_range,
331 preferred_display_base,
332 user_attributes,
61d96b89 333 ):
a728f6c3 334 field_class_ptr = create_func(self._ptr)
a07f15cb 335 self._check_field_class_create_status(field_class_ptr, type_name)
a728f6c3
SM
336
337 field_class = py_cls._create_from_ptr(field_class_ptr)
338
c8820b76
SM
339 if field_value_range is not None:
340 field_class._field_value_range = field_value_range
a728f6c3 341
c8820b76
SM
342 if preferred_display_base is not None:
343 field_class._preferred_display_base = preferred_display_base
a728f6c3 344
b2df5780 345 self._set_field_class_user_attrs(field_class, user_attributes)
a728f6c3
SM
346 return field_class
347
61d96b89 348 def create_signed_integer_field_class(
b2df5780 349 self, field_value_range=None, preferred_display_base=None, user_attributes=None
61d96b89
FD
350 ):
351 return self._create_integer_field_class(
60bbfc7c 352 native_bt.field_class_integer_signed_create,
c946c9de 353 bt2_field_class._SignedIntegerFieldClass,
61d96b89
FD
354 'signed integer',
355 field_value_range,
356 preferred_display_base,
b2df5780 357 user_attributes,
61d96b89
FD
358 )
359
360 def create_unsigned_integer_field_class(
b2df5780 361 self, field_value_range=None, preferred_display_base=None, user_attributes=None
61d96b89
FD
362 ):
363 return self._create_integer_field_class(
60bbfc7c 364 native_bt.field_class_integer_unsigned_create,
c946c9de 365 bt2_field_class._UnsignedIntegerFieldClass,
61d96b89
FD
366 'unsigned integer',
367 field_value_range,
368 preferred_display_base,
b2df5780 369 user_attributes,
61d96b89
FD
370 )
371
372 def create_signed_enumeration_field_class(
b2df5780 373 self, field_value_range=None, preferred_display_base=None, user_attributes=None
61d96b89
FD
374 ):
375 return self._create_integer_field_class(
60bbfc7c 376 native_bt.field_class_enumeration_signed_create,
c946c9de 377 bt2_field_class._SignedEnumerationFieldClass,
61d96b89
FD
378 'signed enumeration',
379 field_value_range,
380 preferred_display_base,
b2df5780 381 user_attributes,
61d96b89
FD
382 )
383
384 def create_unsigned_enumeration_field_class(
b2df5780 385 self, field_value_range=None, preferred_display_base=None, user_attributes=None
61d96b89
FD
386 ):
387 return self._create_integer_field_class(
60bbfc7c 388 native_bt.field_class_enumeration_unsigned_create,
c946c9de 389 bt2_field_class._UnsignedEnumerationFieldClass,
61d96b89
FD
390 'unsigned enumeration',
391 field_value_range,
392 preferred_display_base,
b2df5780 393 user_attributes,
61d96b89 394 )
27d97a3f 395
76276a81
FD
396 def create_single_precision_real_field_class(self, user_attributes=None):
397 field_class_ptr = native_bt.field_class_real_single_precision_create(self._ptr)
398 self._check_field_class_create_status(field_class_ptr, 'single-precision real')
27d97a3f 399
76276a81
FD
400 field_class = bt2_field_class._SinglePrecisionRealFieldClass._create_from_ptr(
401 field_class_ptr
402 )
403
404 self._set_field_class_user_attrs(field_class, user_attributes)
405
406 return field_class
407
408 def create_double_precision_real_field_class(self, user_attributes=None):
409 field_class_ptr = native_bt.field_class_real_double_precision_create(self._ptr)
410 self._check_field_class_create_status(field_class_ptr, 'double-precision real')
411
412 field_class = bt2_field_class._DoublePrecisionRealFieldClass._create_from_ptr(
413 field_class_ptr
414 )
27d97a3f 415
b2df5780 416 self._set_field_class_user_attrs(field_class, user_attributes)
27d97a3f
SM
417
418 return field_class
419
b2df5780 420 def create_structure_field_class(self, user_attributes=None):
060aee52 421 field_class_ptr = native_bt.field_class_structure_create(self._ptr)
a07f15cb 422 self._check_field_class_create_status(field_class_ptr, 'structure')
b2df5780
PP
423 fc = bt2_field_class._StructureFieldClass._create_from_ptr(field_class_ptr)
424 self._set_field_class_user_attrs(fc, user_attributes)
425 return fc
060aee52 426
b2df5780 427 def create_string_field_class(self, user_attributes=None):
060aee52 428 field_class_ptr = native_bt.field_class_string_create(self._ptr)
a07f15cb 429 self._check_field_class_create_status(field_class_ptr, 'string')
b2df5780
PP
430 fc = bt2_field_class._StringFieldClass._create_from_ptr(field_class_ptr)
431 self._set_field_class_user_attrs(fc, user_attributes)
432 return fc
060aee52 433
b2df5780 434 def create_static_array_field_class(self, elem_fc, length, user_attributes=None):
c946c9de 435 utils._check_type(elem_fc, bt2_field_class._FieldClass)
c8820b76 436 utils._check_uint64(length)
60bbfc7c 437 ptr = native_bt.field_class_array_static_create(self._ptr, elem_fc._ptr, length)
a07f15cb 438 self._check_field_class_create_status(ptr, 'static array')
b2df5780
PP
439 fc = bt2_field_class._StaticArrayFieldClass._create_from_ptr_and_get_ref(ptr)
440 self._set_field_class_user_attrs(fc, user_attributes)
441 return fc
c8820b76 442
b2df5780
PP
443 def create_dynamic_array_field_class(
444 self, elem_fc, length_fc=None, user_attributes=None
445 ):
c946c9de 446 utils._check_type(elem_fc, bt2_field_class._FieldClass)
93d7d5d1 447 length_fc_ptr = None
c8820b76
SM
448
449 if length_fc is not None:
c946c9de 450 utils._check_type(length_fc, bt2_field_class._UnsignedIntegerFieldClass)
93d7d5d1 451 length_fc_ptr = length_fc._ptr
c8820b76 452
60bbfc7c 453 ptr = native_bt.field_class_array_dynamic_create(
61d96b89
FD
454 self._ptr, elem_fc._ptr, length_fc_ptr
455 )
a07f15cb 456 self._check_field_class_create_status(ptr, 'dynamic array')
b8ddb4f0 457 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
b2df5780
PP
458 self._set_field_class_user_attrs(fc, user_attributes)
459 return fc
c8820b76 460
467673c1
PP
461 def create_option_without_selector_field_class(
462 self, content_fc, user_attributes=None
b2df5780 463 ):
84eba0d9 464 utils._check_type(content_fc, bt2_field_class._FieldClass)
467673c1
PP
465 ptr = native_bt.field_class_option_without_selector_create(
466 self._ptr, content_fc._ptr
467 )
468 self._check_field_class_create_status(ptr, 'option')
469 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
470 self._set_field_class_user_attrs(fc, user_attributes)
471 return fc
84eba0d9 472
467673c1
PP
473 def create_option_with_bool_selector_field_class(
474 self, content_fc, selector_fc, selector_is_reversed=False, user_attributes=None
475 ):
476 utils._check_type(content_fc, bt2_field_class._FieldClass)
477 utils._check_bool(selector_is_reversed)
478 utils._check_type(selector_fc, bt2_field_class._BoolFieldClass)
8bc207af 479 ptr = native_bt.field_class_option_with_selector_field_bool_create(
467673c1
PP
480 self._ptr, content_fc._ptr, selector_fc._ptr
481 )
482 self._check_field_class_create_status(ptr, 'option')
483 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
484 self._set_field_class_user_attrs(fc, user_attributes)
485 fc._selector_is_reversed = selector_is_reversed
486 return fc
84eba0d9 487
467673c1
PP
488 def create_option_with_integer_selector_field_class(
489 self, content_fc, selector_fc, ranges, user_attributes=None
490 ):
491 utils._check_type(content_fc, bt2_field_class._FieldClass)
492 utils._check_type(selector_fc, bt2_field_class._IntegerFieldClass)
493
494 if len(ranges) == 0:
495 raise ValueError('integer range set is empty')
496
497 if isinstance(selector_fc, bt2_field_class._UnsignedIntegerFieldClass):
498 utils._check_type(ranges, bt2_integer_range_set.UnsignedIntegerRangeSet)
8bc207af 499 ptr = native_bt.field_class_option_with_selector_field_integer_unsigned_create(
467673c1
PP
500 self._ptr, content_fc._ptr, selector_fc._ptr, ranges._ptr
501 )
502 else:
503 utils._check_type(ranges, bt2_integer_range_set.SignedIntegerRangeSet)
e30908cf
PP
504 ptr = (
505 native_bt.field_class_option_with_selector_field_integer_signed_create(
506 self._ptr, content_fc._ptr, selector_fc._ptr, ranges._ptr
507 )
467673c1 508 )
84eba0d9 509
84eba0d9 510 self._check_field_class_create_status(ptr, 'option')
b2df5780
PP
511 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
512 self._set_field_class_user_attrs(fc, user_attributes)
513 return fc
84eba0d9 514
b2df5780 515 def create_variant_field_class(self, selector_fc=None, user_attributes=None):
02b61fe0 516 selector_fc_ptr = None
c8820b76
SM
517
518 if selector_fc is not None:
c946c9de 519 utils._check_type(selector_fc, bt2_field_class._IntegerFieldClass)
02b61fe0 520 selector_fc_ptr = selector_fc._ptr
c8820b76 521
02b61fe0 522 ptr = native_bt.field_class_variant_create(self._ptr, selector_fc_ptr)
a07f15cb 523 self._check_field_class_create_status(ptr, 'variant')
b2df5780
PP
524 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
525 self._set_field_class_user_attrs(fc, user_attributes)
526 return fc
This page took 0.07489 seconds and 4 git commands to generate.