Move to kernel style SPDX license identifiers
[babeltrace.git] / src / bindings / python / bt2 / bt2 / trace_class.py
CommitLineData
0235b0db 1# SPDX-License-Identifier: MIT
fbbe9302
SM
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>
fbbe9302 6
fbbe9302 7from bt2 import native_bt, utils, object
3fb99a22
PP
8from bt2 import stream_class as bt2_stream_class
9from bt2 import field_class as bt2_field_class
0aa006b7 10from bt2 import integer_range_set as bt2_integer_range_set
3fb99a22 11from bt2 import trace as bt2_trace
5783664e 12from bt2 import value as bt2_value
fbbe9302
SM
13import collections.abc
14import functools
f0a42b33 15import bt2
fbbe9302
SM
16
17
67de22ba
SM
18def _trace_class_destruction_listener_from_native(
19 user_listener, handle, trace_class_ptr
20):
f0a42b33 21 trace_class = _TraceClass._create_from_ptr_and_get_ref(trace_class_ptr)
fbbe9302 22 user_listener(trace_class)
67de22ba 23 handle._invalidate()
fbbe9302
SM
24
25
f0a42b33 26class _TraceClassConst(object._SharedObject, collections.abc.Mapping):
fbbe9302
SM
27 _get_ref = staticmethod(native_bt.trace_class_get_ref)
28 _put_ref = staticmethod(native_bt.trace_class_put_ref)
f0a42b33
FD
29 _borrow_stream_class_ptr_by_index = staticmethod(
30 native_bt.trace_class_borrow_stream_class_by_index_const
31 )
32 _borrow_stream_class_ptr_by_id = staticmethod(
33 native_bt.trace_class_borrow_stream_class_by_id_const
34 )
2550c437
SM
35 _borrow_user_attributes_ptr = staticmethod(
36 native_bt.trace_class_borrow_user_attributes_const
37 )
f0a42b33
FD
38 _stream_class_pycls = bt2_stream_class._StreamClassConst
39 _create_value_from_ptr_and_get_ref = staticmethod(
40 bt2_value._create_from_const_ptr_and_get_ref
41 )
fbbe9302 42
f0a42b33
FD
43 @property
44 def user_attributes(self):
2550c437 45 ptr = self._borrow_user_attributes_ptr(self._ptr)
f0a42b33
FD
46 assert ptr is not None
47 return self._create_value_from_ptr_and_get_ref(ptr)
8c2367b8 48
fbbe9302
SM
49 # Number of stream classes in this trace class.
50
51 def __len__(self):
52 count = native_bt.trace_class_get_stream_class_count(self._ptr)
53 assert count >= 0
54 return count
55
56 # Get a stream class by stream id.
57
58 def __getitem__(self, key):
59 utils._check_uint64(key)
60
f0a42b33 61 sc_ptr = self._borrow_stream_class_ptr_by_id(self._ptr, key)
fbbe9302
SM
62 if sc_ptr is None:
63 raise KeyError(key)
64
f0a42b33 65 return self._stream_class_pycls._create_from_ptr_and_get_ref(sc_ptr)
fbbe9302
SM
66
67 def __iter__(self):
68 for idx in range(len(self)):
f0a42b33 69 sc_ptr = self._borrow_stream_class_ptr_by_index(self._ptr, idx)
fbbe9302
SM
70 assert sc_ptr is not None
71
72 id = native_bt.stream_class_get_id(sc_ptr)
73 assert id >= 0
74
75 yield id
76
f0a42b33
FD
77 @property
78 def assigns_automatic_stream_class_id(self):
79 return native_bt.trace_class_assigns_automatic_stream_class_id(self._ptr)
80
81 # Add a listener to be called when the trace class is destroyed.
82
83 def add_destruction_listener(self, listener):
84
85 if not callable(listener):
86 raise TypeError("'listener' parameter is not callable")
87
67de22ba
SM
88 handle = utils._ListenerHandle(self.addr)
89
f0a42b33 90 listener_from_native = functools.partial(
67de22ba 91 _trace_class_destruction_listener_from_native, listener, handle
f0a42b33
FD
92 )
93
67de22ba 94 fn = native_bt.bt2_trace_class_add_destruction_listener
f0a42b33
FD
95 status, listener_id = fn(self._ptr, listener_from_native)
96 utils._handle_func_status(
97 status, 'cannot add destruction listener to trace class object'
98 )
99
67de22ba
SM
100 handle._set_listener_id(listener_id)
101
102 return handle
f0a42b33 103
1114a7d5
SM
104 def remove_destruction_listener(self, listener_handle):
105 utils._check_type(listener_handle, utils._ListenerHandle)
106
67de22ba 107 if listener_handle._addr != self.addr:
1114a7d5 108 raise ValueError(
ab6a6968 109 'This trace class destruction listener does not match the trace class object.'
1114a7d5
SM
110 )
111
112 if listener_handle._listener_id is None:
113 raise ValueError(
114 'This trace class destruction listener was already removed.'
115 )
116
117 status = native_bt.trace_class_remove_destruction_listener(
118 self._ptr, listener_handle._listener_id
119 )
120 utils._handle_func_status(status)
67de22ba 121 listener_handle._invalidate()
1114a7d5 122
f0a42b33
FD
123
124class _TraceClass(_TraceClassConst):
125 _borrow_stream_class_ptr_by_index = staticmethod(
126 native_bt.trace_class_borrow_stream_class_by_index
127 )
128 _borrow_stream_class_ptr_by_id = staticmethod(
129 native_bt.trace_class_borrow_stream_class_by_id
130 )
2550c437
SM
131 _borrow_user_attributes_ptr = staticmethod(
132 native_bt.trace_class_borrow_user_attributes
133 )
f0a42b33
FD
134 _stream_class_pycls = bt2_stream_class._StreamClass
135 _create_value_from_ptr_and_get_ref = staticmethod(
136 bt2_value._create_from_ptr_and_get_ref
137 )
138
139 # Instantiate a trace of this class.
140
141 def __call__(self, name=None, user_attributes=None, uuid=None, environment=None):
142 trace_ptr = native_bt.trace_create(self._ptr)
143
144 if trace_ptr is None:
145 raise bt2._MemoryError('cannot create trace class object')
146
147 trace = bt2_trace._Trace._create_from_ptr(trace_ptr)
148
149 if name is not None:
150 trace._name = name
151
152 if user_attributes is not None:
153 trace._user_attributes = user_attributes
154
155 if uuid is not None:
156 trace._uuid = uuid
157
158 if environment is not None:
159 for key, value in environment.items():
160 trace.environment[key] = value
161
162 return trace
163
cfbd7cf3
FD
164 def create_stream_class(
165 self,
166 id=None,
167 name=None,
5783664e 168 user_attributes=None,
cfbd7cf3
FD
169 packet_context_field_class=None,
170 event_common_context_field_class=None,
171 default_clock_class=None,
172 assigns_automatic_event_class_id=True,
173 assigns_automatic_stream_id=True,
174 supports_packets=False,
175 packets_have_beginning_default_clock_snapshot=False,
176 packets_have_end_default_clock_snapshot=False,
177 supports_discarded_events=False,
178 discarded_events_have_default_clock_snapshots=False,
179 supports_discarded_packets=False,
180 discarded_packets_have_default_clock_snapshots=False,
181 ):
d3bf1370
SM
182 # Validate parameters before we create the object.
183 bt2_stream_class._StreamClass._validate_create_params(
184 name,
185 user_attributes,
186 packet_context_field_class,
187 event_common_context_field_class,
188 default_clock_class,
189 assigns_automatic_event_class_id,
190 assigns_automatic_stream_id,
191 supports_packets,
192 packets_have_beginning_default_clock_snapshot,
193 packets_have_end_default_clock_snapshot,
194 supports_discarded_events,
195 discarded_events_have_default_clock_snapshots,
196 supports_discarded_packets,
197 discarded_packets_have_default_clock_snapshots,
198 )
fbbe9302
SM
199
200 if self.assigns_automatic_stream_class_id:
201 if id is not None:
cfbd7cf3
FD
202 raise ValueError(
203 'id provided, but trace class assigns automatic stream class ids'
204 )
fbbe9302
SM
205
206 sc_ptr = native_bt.stream_class_create(self._ptr)
207 else:
208 if id is None:
cfbd7cf3
FD
209 raise ValueError(
210 'id not provided, but trace class does not assign automatic stream class ids'
211 )
fbbe9302
SM
212
213 utils._check_uint64(id)
214 sc_ptr = native_bt.stream_class_create_with_id(self._ptr, id)
215
3fb99a22 216 sc = bt2_stream_class._StreamClass._create_from_ptr(sc_ptr)
8c2367b8 217
3cdfbaea
SM
218 if name is not None:
219 sc._name = name
220
5783664e
PP
221 if user_attributes is not None:
222 sc._user_attributes = user_attributes
223
3cdfbaea
SM
224 if event_common_context_field_class is not None:
225 sc._event_common_context_field_class = event_common_context_field_class
226
227 if default_clock_class is not None:
228 sc._default_clock_class = default_clock_class
229
26fc5aed
PP
230 # call after `sc._default_clock_class` because, if
231 # `packets_have_beginning_default_clock_snapshot` or
232 # `packets_have_end_default_clock_snapshot` is true, then this
233 # stream class needs a default clock class already.
cfbd7cf3
FD
234 sc._set_supports_packets(
235 supports_packets,
236 packets_have_beginning_default_clock_snapshot,
237 packets_have_end_default_clock_snapshot,
238 )
26fc5aed
PP
239
240 # call after sc._set_supports_packets() because, if
241 # `packet_context_field_class` is not `None`, then this stream
242 # class needs to support packets already.
243 if packet_context_field_class is not None:
244 sc._packet_context_field_class = packet_context_field_class
245
3cdfbaea 246 sc._assigns_automatic_event_class_id = assigns_automatic_event_class_id
8c2367b8 247 sc._assigns_automatic_stream_id = assigns_automatic_stream_id
cfbd7cf3
FD
248 sc._set_supports_discarded_events(
249 supports_discarded_events, discarded_events_have_default_clock_snapshots
250 )
251 sc._set_supports_discarded_packets(
252 supports_discarded_packets, discarded_packets_have_default_clock_snapshots
253 )
8c2367b8 254 return sc
fbbe9302 255
5783664e
PP
256 def _user_attributes(self, user_attributes):
257 value = bt2_value.create_value(user_attributes)
258 utils._check_type(value, bt2_value.MapValue)
259 native_bt.trace_class_set_user_attributes(self._ptr, value._ptr)
260
261 _user_attributes = property(fset=_user_attributes)
262
fbbe9302
SM
263 def _assigns_automatic_stream_class_id(self, auto_id):
264 utils._check_bool(auto_id)
cfbd7cf3
FD
265 return native_bt.trace_class_set_assigns_automatic_stream_class_id(
266 self._ptr, auto_id
267 )
fbbe9302 268
cfbd7cf3
FD
269 _assigns_automatic_stream_class_id = property(
270 fset=_assigns_automatic_stream_class_id
271 )
fbbe9302 272
3cdfbaea
SM
273 # Field class creation methods.
274
aae30e61 275 def _check_field_class_create_status(self, ptr, type_name):
3cdfbaea 276 if ptr is None:
694c792b 277 raise bt2._MemoryError('cannot create {} field class'.format(type_name))
3cdfbaea 278
5783664e
PP
279 @staticmethod
280 def _set_field_class_user_attrs(fc, user_attributes):
281 if user_attributes is not None:
282 fc._user_attributes = user_attributes
283
284 def create_bool_field_class(self, user_attributes=None):
aae30e61
PP
285 field_class_ptr = native_bt.field_class_bool_create(self._ptr)
286 self._check_field_class_create_status(field_class_ptr, 'boolean')
5783664e
PP
287 fc = bt2_field_class._BoolFieldClass._create_from_ptr(field_class_ptr)
288 self._set_field_class_user_attrs(fc, user_attributes)
289 return fc
aae30e61 290
5783664e 291 def create_bit_array_field_class(self, length, user_attributes=None):
ead8c3d4
PP
292 utils._check_uint64(length)
293
294 if length < 1 or length > 64:
295 raise ValueError(
296 'invalid length {}: expecting a value in the [1, 64] range'.format(
297 length
298 )
299 )
300
301 field_class_ptr = native_bt.field_class_bit_array_create(self._ptr, length)
302 self._check_field_class_create_status(field_class_ptr, 'bit array')
5783664e
PP
303 fc = bt2_field_class._BitArrayFieldClass._create_from_ptr(field_class_ptr)
304 self._set_field_class_user_attrs(fc, user_attributes)
305 return fc
ead8c3d4 306
cfbd7cf3 307 def _create_integer_field_class(
5783664e
PP
308 self,
309 create_func,
310 py_cls,
311 type_name,
312 field_value_range,
313 preferred_display_base,
314 user_attributes,
cfbd7cf3 315 ):
af4bbfc7 316 field_class_ptr = create_func(self._ptr)
aae30e61 317 self._check_field_class_create_status(field_class_ptr, type_name)
af4bbfc7
SM
318
319 field_class = py_cls._create_from_ptr(field_class_ptr)
320
d47b87ac
SM
321 if field_value_range is not None:
322 field_class._field_value_range = field_value_range
af4bbfc7 323
d47b87ac
SM
324 if preferred_display_base is not None:
325 field_class._preferred_display_base = preferred_display_base
af4bbfc7 326
5783664e 327 self._set_field_class_user_attrs(field_class, user_attributes)
af4bbfc7
SM
328 return field_class
329
cfbd7cf3 330 def create_signed_integer_field_class(
5783664e 331 self, field_value_range=None, preferred_display_base=None, user_attributes=None
cfbd7cf3
FD
332 ):
333 return self._create_integer_field_class(
9c08c816 334 native_bt.field_class_integer_signed_create,
3fb99a22 335 bt2_field_class._SignedIntegerFieldClass,
cfbd7cf3
FD
336 'signed integer',
337 field_value_range,
338 preferred_display_base,
5783664e 339 user_attributes,
cfbd7cf3
FD
340 )
341
342 def create_unsigned_integer_field_class(
5783664e 343 self, field_value_range=None, preferred_display_base=None, user_attributes=None
cfbd7cf3
FD
344 ):
345 return self._create_integer_field_class(
9c08c816 346 native_bt.field_class_integer_unsigned_create,
3fb99a22 347 bt2_field_class._UnsignedIntegerFieldClass,
cfbd7cf3
FD
348 'unsigned integer',
349 field_value_range,
350 preferred_display_base,
5783664e 351 user_attributes,
cfbd7cf3
FD
352 )
353
354 def create_signed_enumeration_field_class(
5783664e 355 self, field_value_range=None, preferred_display_base=None, user_attributes=None
cfbd7cf3
FD
356 ):
357 return self._create_integer_field_class(
9c08c816 358 native_bt.field_class_enumeration_signed_create,
3fb99a22 359 bt2_field_class._SignedEnumerationFieldClass,
cfbd7cf3
FD
360 'signed enumeration',
361 field_value_range,
362 preferred_display_base,
5783664e 363 user_attributes,
cfbd7cf3
FD
364 )
365
366 def create_unsigned_enumeration_field_class(
5783664e 367 self, field_value_range=None, preferred_display_base=None, user_attributes=None
cfbd7cf3
FD
368 ):
369 return self._create_integer_field_class(
9c08c816 370 native_bt.field_class_enumeration_unsigned_create,
3fb99a22 371 bt2_field_class._UnsignedEnumerationFieldClass,
cfbd7cf3
FD
372 'unsigned enumeration',
373 field_value_range,
374 preferred_display_base,
5783664e 375 user_attributes,
cfbd7cf3 376 )
2ae9f48c 377
fe4df857
FD
378 def create_single_precision_real_field_class(self, user_attributes=None):
379 field_class_ptr = native_bt.field_class_real_single_precision_create(self._ptr)
380 self._check_field_class_create_status(field_class_ptr, 'single-precision real')
2ae9f48c 381
fe4df857
FD
382 field_class = bt2_field_class._SinglePrecisionRealFieldClass._create_from_ptr(
383 field_class_ptr
384 )
385
386 self._set_field_class_user_attrs(field_class, user_attributes)
387
388 return field_class
389
390 def create_double_precision_real_field_class(self, user_attributes=None):
391 field_class_ptr = native_bt.field_class_real_double_precision_create(self._ptr)
392 self._check_field_class_create_status(field_class_ptr, 'double-precision real')
393
394 field_class = bt2_field_class._DoublePrecisionRealFieldClass._create_from_ptr(
395 field_class_ptr
396 )
2ae9f48c 397
5783664e 398 self._set_field_class_user_attrs(field_class, user_attributes)
2ae9f48c
SM
399
400 return field_class
401
5783664e 402 def create_structure_field_class(self, user_attributes=None):
3cdfbaea 403 field_class_ptr = native_bt.field_class_structure_create(self._ptr)
aae30e61 404 self._check_field_class_create_status(field_class_ptr, 'structure')
5783664e
PP
405 fc = bt2_field_class._StructureFieldClass._create_from_ptr(field_class_ptr)
406 self._set_field_class_user_attrs(fc, user_attributes)
407 return fc
3cdfbaea 408
5783664e 409 def create_string_field_class(self, user_attributes=None):
3cdfbaea 410 field_class_ptr = native_bt.field_class_string_create(self._ptr)
aae30e61 411 self._check_field_class_create_status(field_class_ptr, 'string')
5783664e
PP
412 fc = bt2_field_class._StringFieldClass._create_from_ptr(field_class_ptr)
413 self._set_field_class_user_attrs(fc, user_attributes)
414 return fc
3cdfbaea 415
5783664e 416 def create_static_array_field_class(self, elem_fc, length, user_attributes=None):
3fb99a22 417 utils._check_type(elem_fc, bt2_field_class._FieldClass)
d47b87ac 418 utils._check_uint64(length)
9c08c816 419 ptr = native_bt.field_class_array_static_create(self._ptr, elem_fc._ptr, length)
aae30e61 420 self._check_field_class_create_status(ptr, 'static array')
5783664e
PP
421 fc = bt2_field_class._StaticArrayFieldClass._create_from_ptr_and_get_ref(ptr)
422 self._set_field_class_user_attrs(fc, user_attributes)
423 return fc
d47b87ac 424
5783664e
PP
425 def create_dynamic_array_field_class(
426 self, elem_fc, length_fc=None, user_attributes=None
427 ):
3fb99a22 428 utils._check_type(elem_fc, bt2_field_class._FieldClass)
1367bc7c 429 length_fc_ptr = None
d47b87ac
SM
430
431 if length_fc is not None:
3fb99a22 432 utils._check_type(length_fc, bt2_field_class._UnsignedIntegerFieldClass)
1367bc7c 433 length_fc_ptr = length_fc._ptr
d47b87ac 434
9c08c816 435 ptr = native_bt.field_class_array_dynamic_create(
cfbd7cf3
FD
436 self._ptr, elem_fc._ptr, length_fc_ptr
437 )
aae30e61 438 self._check_field_class_create_status(ptr, 'dynamic array')
81b8fa44 439 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
5783664e
PP
440 self._set_field_class_user_attrs(fc, user_attributes)
441 return fc
d47b87ac 442
0aa006b7
PP
443 def create_option_without_selector_field_class(
444 self, content_fc, user_attributes=None
5783664e 445 ):
cec0261d 446 utils._check_type(content_fc, bt2_field_class._FieldClass)
0aa006b7
PP
447 ptr = native_bt.field_class_option_without_selector_create(
448 self._ptr, content_fc._ptr
449 )
450 self._check_field_class_create_status(ptr, 'option')
451 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
452 self._set_field_class_user_attrs(fc, user_attributes)
453 return fc
cec0261d 454
0aa006b7
PP
455 def create_option_with_bool_selector_field_class(
456 self, content_fc, selector_fc, selector_is_reversed=False, user_attributes=None
457 ):
458 utils._check_type(content_fc, bt2_field_class._FieldClass)
459 utils._check_bool(selector_is_reversed)
460 utils._check_type(selector_fc, bt2_field_class._BoolFieldClass)
de821fe5 461 ptr = native_bt.field_class_option_with_selector_field_bool_create(
0aa006b7
PP
462 self._ptr, content_fc._ptr, selector_fc._ptr
463 )
464 self._check_field_class_create_status(ptr, 'option')
465 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
466 self._set_field_class_user_attrs(fc, user_attributes)
467 fc._selector_is_reversed = selector_is_reversed
468 return fc
cec0261d 469
0aa006b7
PP
470 def create_option_with_integer_selector_field_class(
471 self, content_fc, selector_fc, ranges, user_attributes=None
472 ):
473 utils._check_type(content_fc, bt2_field_class._FieldClass)
474 utils._check_type(selector_fc, bt2_field_class._IntegerFieldClass)
475
476 if len(ranges) == 0:
477 raise ValueError('integer range set is empty')
478
479 if isinstance(selector_fc, bt2_field_class._UnsignedIntegerFieldClass):
480 utils._check_type(ranges, bt2_integer_range_set.UnsignedIntegerRangeSet)
de821fe5 481 ptr = native_bt.field_class_option_with_selector_field_integer_unsigned_create(
0aa006b7
PP
482 self._ptr, content_fc._ptr, selector_fc._ptr, ranges._ptr
483 )
484 else:
485 utils._check_type(ranges, bt2_integer_range_set.SignedIntegerRangeSet)
de821fe5 486 ptr = native_bt.field_class_option_with_selector_field_integer_signed_create(
0aa006b7
PP
487 self._ptr, content_fc._ptr, selector_fc._ptr, ranges._ptr
488 )
cec0261d 489
cec0261d 490 self._check_field_class_create_status(ptr, 'option')
5783664e
PP
491 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
492 self._set_field_class_user_attrs(fc, user_attributes)
493 return fc
cec0261d 494
5783664e 495 def create_variant_field_class(self, selector_fc=None, user_attributes=None):
45c51519 496 selector_fc_ptr = None
d47b87ac
SM
497
498 if selector_fc is not None:
3fb99a22 499 utils._check_type(selector_fc, bt2_field_class._IntegerFieldClass)
45c51519 500 selector_fc_ptr = selector_fc._ptr
d47b87ac 501
45c51519 502 ptr = native_bt.field_class_variant_create(self._ptr, selector_fc_ptr)
aae30e61 503 self._check_field_class_create_status(ptr, 'variant')
5783664e
PP
504 fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
505 self._set_field_class_user_attrs(fc, user_attributes)
506 return fc
This page took 0.073998 seconds and 4 git commands to generate.