3 # Babeltrace writer interface Python module
5 # Copyright 2012-2017 EfficiOS Inc.
7 # Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 # Permission is hereby granted, free of charge, to any person obtaining a copy
10 # of this software and associated documentation files (the "Software"), to deal
11 # in the Software without restriction, including without limitation the rights
12 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 # copies of the Software, and to permit persons to whom the Software is
14 # furnished to do so, subject to the following conditions:
16 # The above copyright notice and this permission notice shall be included in
17 # all copies or substantial portions of the Software.
19 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 import babeltrace
.common
as common
30 class EnumerationMapping
:
32 Mapping from an enumeration label to a range of integers.
35 def __init__(self
, name
, start
, end
):
37 Creates an enumeration mapping, where label *name* is mapped to
38 the [*start*, *end*] range of integers (*end* is included).
40 Set *start* and *end* to the same value to create an enumeration
41 mapping to a single value.
44 self
._enum
_mapping
= bt2
._EnumerationFieldTypeMapping(self
, start
, end
)
48 return self
._enum
_mapping
.name
52 return self
._enum
_mapping
.lower
56 return self
._enum
_mapping
.upper
61 A CTF clock allows the description of the system's clock topology, as
62 well as the definition of each clock's parameters.
64 :class:`Clock` objects must be registered to a :class:`Writer`
65 object (see :meth:`Writer.add_clock`), as well as be registered to
66 a :class:`StreamClass` object (see :attr:`StreamClass.clock`).
69 def __init__(self
, name
):
71 Creates a default CTF clock named *name*.
73 :exc:`ValueError` is raised on error.
77 self
._clock
= bt2
.CtfWriterClock(name
)
79 raise ValueError("Invalid clock name.")
87 Set this attribute to change the clock's name.
89 :exc:`ValueError` is raised on error.
93 return self
._clock
.name
95 raise ValueError("Invalid clock instance.")
98 def description(self
):
100 Clock description (string).
102 Set this attribute to change the clock's description.
104 :exc:`ValueError` is raised on error.
108 return self
._clock
.description
110 raise ValueError("Invalid clock instance.")
113 def description(self
, desc
):
115 self
._clock
.description
= desc
117 raise ValueError("Invalid clock description.")
122 Clock frequency in Hz (integer).
124 Set this attribute to change the clock's frequency.
126 :exc:`ValueError` is raised on error.
130 return self
._clock
.frequency
132 raise ValueError("Invalid clock instance.")
135 def frequency(self
, freq
):
137 self
._clock
.frequency
= freq
139 raise ValueError("Invalid frequency value.")
144 Clock precision in clock ticks (integer).
146 Set this attribute to change the clock's precision.
148 :exc:`ValueError` is raised on error.
152 return self
._clock
.precision
154 raise ValueError("Invalid clock instance.")
157 def precision(self
, precision
):
159 self
._clock
.precision
= precision
161 raise ValueError("Invalid precision value.")
164 def offset_seconds(self
):
166 Clock offset in seconds since POSIX.1 Epoch (integer).
168 Set this attribute to change the clock's offset in seconds.
170 :exc:`ValueError` is raised on error.
174 return self
._clock
.offset
.seconds
176 raise ValueError("Invalid clock instance.")
178 @offset_seconds.setter
179 def offset_seconds(self
, offset_s
):
181 self
._clock
.offset
= bt2
.ClockClassOffet(offset_s
,
182 self
._clock
.offset
.cycles
)
184 raise ValueError("Invalid offset value.")
189 Clock offset in ticks since (POSIX.1 Epoch +
190 :attr:`offset_seconds`).
192 Set this attribute to change the clock's offset.
194 :exc:`ValueError` is raised on error.
198 return self
._clock
.offset
.cycles
200 raise ValueError("Invalid clock instance.")
203 def offset(self
, offset
):
205 self
._clock
.offset
= bt2
.ClockClassOffet(
206 self
._clock
.offset
.seconds
, offset
)
208 raise ValueError("Invalid offset value.")
213 ``True`` if this clock is absolute, i.e. if the clock is a
214 global reference across the other clocks of the trace.
216 Set this attribute to change the clock's absolute state
219 :exc:`ValueError` is raised on error.
223 return self
._clock
.is_absolute
225 raise ValueError("Invalid clock instance.")
228 def absolute(self
, is_absolute
):
230 self
._clock
.is_absolute
= is_absolute
232 raise ValueError("Could not set the clock absolute attribute.")
237 Clock UUID (an :class:`uuid.UUID` object).
239 Set this attribute to change the clock's UUID.
241 :exc:`ValueError` is raised on error.
245 return self
._clock
.uuid
247 raise ValueError("Invalid clock instance.")
250 def uuid(self
, uuid
):
251 uuid_bytes
= uuid
.bytes
253 if len(uuid_bytes
) != 16:
255 "Invalid UUID provided. UUID length must be 16 bytes")
258 self
._clock
.uuid
= uuid
260 raise ValueError("Invalid clock instance.")
265 Clock current time; nanoseconds (integer) since clock origin
266 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
268 Set this attribute to change the clock's current time.
270 :exc:`ValueError` is raised on error.
273 raise NotImplementedError("Getter not implemented.")
276 def time(self
, time
):
278 self
._clock
.time
= time
280 raise ValueError("Invalid time value.")
285 Display base of an integer.
303 # keep this for backward compatibility
304 INTEGER_BASE_UNKNOWN
= -1
305 INTEGER_BASE_BINARY
= 2
306 INTEGER_BASE_OCTAL
= 8
307 INTEGER_BASE_DECIMAL
= 10
308 INTEGER_BASE_HEXADECIMAL
= 16
311 _BT2_BYTE_ORDER_TO_BYTE_ORDER
= {
312 bt2
.ByteOrder
.NATIVE
: common
.ByteOrder
.BYTE_ORDER_NATIVE
,
313 bt2
.ByteOrder
.LITTLE_ENDIAN
: common
.ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
,
314 bt2
.ByteOrder
.BIG_ENDIAN
: common
.ByteOrder
.BYTE_ORDER_BIG_ENDIAN
,
315 bt2
.ByteOrder
.NETWORK
: common
.ByteOrder
.BYTE_ORDER_NETWORK
,
318 _BYTE_ORDER_TO_BT2_BYTE_ORDER
= {
319 common
.ByteOrder
.BYTE_ORDER_NATIVE
: bt2
.ByteOrder
.NATIVE
,
320 common
.ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
: bt2
.ByteOrder
.LITTLE_ENDIAN
,
321 common
.ByteOrder
.BYTE_ORDER_BIG_ENDIAN
: bt2
.ByteOrder
.BIG_ENDIAN
,
322 common
.ByteOrder
.BYTE_ORDER_NETWORK
: bt2
.ByteOrder
.NETWORK
,
325 _BT2_ENCODING_TO_ENCODING
= {
326 bt2
.Encoding
.NONE
: common
.CTFStringEncoding
.NONE
,
327 bt2
.Encoding
.ASCII
: common
.CTFStringEncoding
.ASCII
,
328 bt2
.Encoding
.UTF8
: common
.CTFStringEncoding
.UTF8
,
331 _ENCODING_TO_BT2_ENCODING
= {
332 common
.CTFStringEncoding
.NONE
: bt2
.Encoding
.NONE
,
333 common
.CTFStringEncoding
.ASCII
: bt2
.Encoding
.ASCII
,
334 common
.CTFStringEncoding
.UTF8
: bt2
.Encoding
.UTF8
,
337 class FieldDeclaration
:
339 Base class of all field declarations. This class is not meant to
340 be instantiated by the user; use one of the concrete field
341 declaration subclasses instead.
344 class IntegerBase(IntegerBase
):
348 if self
._field
_type
is None:
349 raise ValueError("FieldDeclaration creation failed.")
352 def _create_field_declaration(field_type
):
354 if type(field_type
) not in _BT2_FIELD_TYPE_TO_BT_DECLARATION
:
355 raise TypeError("Invalid field declaration instance.")
357 declaration
= Field
.__new
__(Field
)
358 declaration
._field
_type
= field_type
359 declaration
.__class
__ = _BT2_FIELD_TYPE_TO_BT_DECLARATION
[
366 Field alignment in bits (integer).
368 Set this attribute to change this field's alignment.
370 :exc:`ValueError` is raised on error.
374 return self
._field
_type
.alignment
377 "Could not get alignment field declaration attribute.")
380 def alignment(self
, alignment
):
382 self
._field
_type
.alignment
= alignment
384 raise ValueError("Invalid alignment value.")
387 def byte_order(self
):
389 Field byte order (one of :class:`babeltrace.common.ByteOrder`
392 Set this attribute to change this field's byte order.
394 :exc:`ValueError` is raised on error.
398 return _BT2_BYTE_ORDER_TO_BYTE_ORDER
[self
._field
_type
.byte_order
]
401 "Could not get byte order field declaration attribute.")
404 def byte_order(self
, byte_order
):
406 self
._field
_type
.byte_order
= _BYTE_ORDER_TO_BT2_BYTE_ORDER
[byte_order
]
408 raise ValueError("Could not set byte order value.")
415 Integer encoding (one of
416 :class:`babeltrace.common.CTFStringEncoding` constants).
418 Set this attribute to change this field's encoding.
420 :exc:`ValueError` is raised on error.
424 return _BT2_ENCODING_TO_ENCODING
[self
._field
_type
.encoding
]
426 raise ValueError("Could not get field encoding.")
429 def encoding(self
, encoding
):
431 self
._field
_type
.encoding
= _ENCODING_TO_BT2_ENCODING
[encoding
]
433 raise ValueError("Could not set field encoding.")
436 class IntegerFieldDeclaration(FieldDeclaration
, _EncodingProp
):
438 Integer field declaration.
441 def __init__(self
, size
):
443 Creates an integer field declaration of size *size* bits.
445 :exc:`ValueError` is raised on error.
448 self
._field
_type
= bt2
.IntegerFieldType(size
)
454 Integer size in bits (integer).
456 Set this attribute to change this integer's size.
458 :exc:`ValueError` is raised on error.
462 return self
._field
_type
.size
464 raise ValueError("Could not get Integer size attribute.")
469 ``True`` if this integer is signed.
471 Set this attribute to change this integer's signedness
474 :exc:`ValueError` is raised on error.
478 return self
._field
_type
.is_signed
480 raise ValueError("Could not get Integer signed attribute.")
483 def signed(self
, signed
):
485 self
._field
_type
.is_signed
= signed
487 raise ValueError("Could not set Integer signed attribute.")
492 Integer display base (one of :class:`IntegerBase` constants).
494 Set this attribute to change this integer's display base.
496 :exc:`ValueError` is raised on error.
500 return self
._field
_type
.base
502 raise ValueError("Could not get Integer base attribute.")
505 def base(self
, base
):
507 self
._field
_type
.base
= base
509 raise ValueError("Could not set Integer base.")
512 class EnumerationFieldDeclaration(FieldDeclaration
):
514 Enumeration field declaration. A CTF enumeration maps labels to
518 def __init__(self
, integer_type
):
520 Creates an enumeration field declaration, with *integer_type*
521 being the underlying :class:`IntegerFieldDeclaration` for storing
524 :exc:`ValueError` is raised on error.
527 isinst
= isinstance(integer_type
, IntegerFieldDeclaration
)
529 if integer_type
is None or not isinst
:
530 raise TypeError("Invalid integer container.")
532 self
._field
_type
= bt2
.EnumerationFieldType(integer_type
._field
_type
)
538 Underlying container (:class:`IntegerFieldDeclaration`).
540 :exc:`TypeError` is raised on error.
544 return FieldDeclaration
._create
_field
_declaration
(
545 self
._field
_type
.integer_field_type
)
547 raise TypeError("Invalid enumeration declaration")
549 def add_mapping(self
, name
, range_start
, range_end
):
551 Adds a mapping to the enumeration field declaration, from the
552 label named *name* to range [*range_start*, *range_end*], where
553 *range_start* and *range_end* are integers included in the
556 :exc:`ValueError` is raised on error.
560 self
._field
_type
.append_mapping(name
, range_start
, range_end
)
563 "Could not add mapping to enumeration declaration.")
568 Generates the mappings of this enumeration field declaration
569 (:class:`EnumerationMapping` objects).
571 :exc:`TypeError` is raised on error.
574 for mapping
in self
._field
_type
:
575 yield EnumerationMapping(mapping
.name
, mapping
.lower
,
578 def get_mapping_by_name(self
, name
):
580 Returns the :class:`EnumerationMapping` object for the label
583 :exc:`TypeError` is raised on error.
587 mappings
= list(self
._field
_type
.mappings_by_name(name
))
590 'Could not get enumeration mappings by name \'{}\''.format(
596 mapping
= mappings
[0]
597 return EnumerationMapping(mapping
.name
, mapping
.lower
, mapping
.upper
)
599 def get_mapping_by_value(self
, value
):
601 Returns the :class:`EnumerationMapping` object for the value
604 :exc:`TypeError` is raised on error.
608 mappings
= list(self
._field
_type
.mappings_by_value(value
))
611 'Could not get enumeration mappings by value \'{}\''.format(
617 mapping
= mappings
[0]
618 return EnumerationMapping(mapping
.name
, mapping
.lower
, mapping
.upper
)
621 class FloatingPointFieldDeclaration(FieldDeclaration
):
623 Floating point number field declaration.
625 A CTF floating point number is a made of three sections: the sign
626 bit, the exponent bits, and the mantissa bits. The most significant
627 bit of the resulting binary word is the sign bit, and is included
628 in the number of mantissa bits.
631 `IEEE 754 <http://en.wikipedia.org/wiki/IEEE_floating_point>`_
632 single precision floating point number is represented on a 32-bit
633 word using an 8-bit exponent (``e``) and a 24-bit mantissa (``m``),
634 the latter count including the sign bit (``s``)::
636 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
638 The IEEE 754 double precision floating point number uses an
639 11-bit exponent and a 53-bit mantissa.
642 #: IEEE 754 single precision floating point number exponent size
645 #: IEEE 754 double precision floating point number exponent size
648 #: IEEE 754 single precision floating point number mantissa size
651 #: IEEE 754 double precision floating point number mantissa size
656 Creates a floating point number field declaration.
658 :exc:`ValueError` is raised on error.
661 self
._field
_type
= bt2
.FloatingPointNumberFieldType()
665 def exponent_digits(self
):
667 Floating point number exponent section size in bits (integer).
669 Set this attribute to change the floating point number's
670 exponent section's size. You may use :attr:`FLT_EXP_DIG` or
671 :attr:`DBL_EXP_DIG` for IEEE 754 floating point numbers.
673 :exc:`ValueError` is raised on error.
677 return self
._field
_type
.exponent_size
680 "Could not get Floating point exponent digit count")
683 @exponent_digits.setter
684 def exponent_digits(self
, exponent_digits
):
686 self
._field
_type
.exponent_size
= exponent_digits
688 raise ValueError("Could not set exponent digit count.")
691 def mantissa_digits(self
):
693 Floating point number mantissa section size in bits (integer).
695 Set this attribute to change the floating point number's
696 mantissa section's size. You may use :attr:`FLT_MANT_DIG` or
697 :attr:`DBL_MANT_DIG` for IEEE 754 floating point numbers.
699 :exc:`ValueError` is raised on error.
703 return self
._field
_type
.mantissa_size
706 "Could not get Floating point mantissa digit count")
709 @mantissa_digits.setter
710 def mantissa_digits(self
, mantissa_digits
):
712 self
._field
_type
.mantissa_size
= mantissa_digits
714 raise ValueError("Could not set mantissa digit count.")
717 class FloatFieldDeclaration(FloatingPointFieldDeclaration
):
721 class StructureFieldDeclaration(FieldDeclaration
):
723 Structure field declaration, i.e. an ordered mapping from field
724 names to field declarations.
729 Creates an empty structure field declaration.
731 :exc:`ValueError` is raised on error.
734 self
._field
_type
= bt2
.StructureFieldType()
737 def add_field(self
, field_type
, field_name
):
739 Appends one :class:`FieldDeclaration` *field_type* named
740 *field_name* to the structure's ordered map.
742 :exc:`ValueError` is raised on error.
746 self
._field
_type
.append_field(field_name
, field_type
._field
_type
)
748 raise ValueError("Could not add field to structure.")
753 Generates the (field name, :class:`FieldDeclaration`) pairs
756 :exc:`TypeError` is raised on error.
759 for name
, field_type
in self
._field
_type
.items():
761 FieldDeclaration
._create
_field
_declaration
(
764 def get_field_by_name(self
, name
):
766 Returns the :class:`FieldDeclaration` mapped to the field name
767 *name* in this structure.
769 :exc:`TypeError` is raised on error.
772 if name
not in self
._field
_type
:
773 msg
= "Could not find Structure field with name {}".format(name
)
776 field_type
= self
._field
_type
[name
]
777 return FieldDeclaration
._create
_field
_declaration
(
781 class VariantFieldDeclaration(FieldDeclaration
):
783 Variant field declaration.
785 A CTF variant is a dynamic selection between different fields.
786 The value of a *tag* (a CTF enumeration) determines what is the
787 current selected field. All the possible fields must be added to
788 its field declaration before using an actual variant field.
791 def __init__(self
, enum_tag
, tag_name
):
793 Creates an empty variant field declaration with tag field
794 declaration *enum_tag* (instance of
795 :class:`EnumerationFieldDeclaration`) named *tag_name*
798 :exc:`ValueError` is raised on error.
801 isinst
= isinstance(enum_tag
, EnumerationFieldDeclaration
)
802 if enum_tag
is None or not isinst
:
803 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
805 self
._field
_type
= bt2
.VariantFieldType(tag_name
=tag_name
,
806 tag_field_type
=enum_tag
._field
_type
)
812 Variant field declaration tag name.
814 :exc:`TypeError` is raised on error.
818 self
._field
_type
.tag_name
820 raise TypeError("Could not get Variant tag name")
825 Variant field declaration tag field declaration
826 (:class:`EnumerationFieldDeclaration` object).
828 :exc:`TypeError` is raised on error.
832 return FieldDeclaration
._create
_field
_declaration
(
833 self
._field
_type
.tag_field_type
)
835 raise TypeError("Could not get Variant tag type")
837 def add_field(self
, field_type
, field_name
):
839 Registers the :class:`FieldDeclaration` object *field_type*
840 as the variant's selected type when the variant's tag's current
841 label is *field_name*.
843 :exc:`ValueError` is raised on error.
847 self
._field
_type
.append_field(name
=field_name
, field_type
=field_type
._field
_type
)
849 raise ValueError("Could not add field to variant.")
854 Generates the (field name, :class:`FieldDeclaration`) pairs
855 of this variant field declaration.
857 :exc:`TypeError` is raised on error.
860 for name
, member
in self
._field
_type
.items():
861 yield (name
, FieldDeclaration
._create
_field
_declaration
(member
))
863 def get_field_by_name(self
, name
):
865 Returns the :class:`FieldDeclaration` selected when the
866 variant's tag's current label is *name*.
868 :exc:`TypeError` is raised on error.
871 if name
not in self
._field
_type
:
873 'Could not find Variant field with name {}'.format(name
))
875 field_type
= self
._field
_type
[name
]
876 return FieldDeclaration
._create
_field
_declaration
(field_type
)
878 def get_field_from_tag(self
, tag
):
880 Returns the :class:`FieldDeclaration` selected by the current
881 label of the :class:`EnumerationField` *tag*.
883 :exc:`TypeError` is raised on error.
887 return create_field(self
).field(tag
).declaration
889 raise TypeError('Could not get Variant field declaration.')
892 class ArrayFieldDeclaration(FieldDeclaration
):
894 Static array field declaration.
897 def __init__(self
, element_type
, length
):
899 Creates a static array field declaration of *length*
900 elements of type *element_type* (:class:`FieldDeclaration`).
902 :exc:`ValueError` is raised on error.
906 self
._field
_type
= bt2
.ArrayFieldType(element_type
._field
_type
, length
)
908 raise ValueError('Failed to create ArrayFieldDeclaration.')
912 def element_type(self
):
914 Type of the elements of this this static array (subclass of
915 :class:`FieldDeclaration`).
917 :exc:`TypeError` is raised on error.
921 return FieldDeclaration
._create
_field
_declaration
(
922 self
._field
_type
.element_field_type
)
924 raise TypeError("Could not get Array element type")
929 Length of this static array (integer).
931 :exc:`TypeError` is raised on error.
935 return self
._field
_type
.length
937 raise TypeError("Could not get Array length")
940 class SequenceFieldDeclaration(FieldDeclaration
):
942 Sequence (dynamic array) field declaration.
945 def __init__(self
, element_type
, length_field_name
):
947 Creates a sequence field declaration of
948 elements of type *element_type* (:class:`FieldDeclaration`).
949 The length of a sequence field based on this sequence field
950 declaration is obtained by retrieving the dynamic integer
951 value of the field named *length_field_name*.
953 :exc:`ValueError` is raised on error.
957 self
._field
_type
= bt2
.SequenceFieldType(element_type
, length_field_name
)
959 raise ValueError('Failed to create SequenceFieldDeclaration.')
963 def element_type(self
):
965 Type of the elements of this sequence (subclass of
966 :class:`FieldDeclaration`).
968 :exc:`TypeError` is raised on error.
972 return FieldDeclaration
._create
_field
_declaration
(
973 self
._field
_type
.element_field_type
)
975 raise TypeError("Could not get Sequence element type")
978 def length_field_name(self
):
980 Name of the integer field defining the dynamic length of
981 sequence fields based on this sequence field declaration.
983 :exc:`TypeError` is raised on error.
987 return self
._field
_type
.length_name
989 raise TypeError("Could not get Sequence element type")
992 class StringFieldDeclaration(FieldDeclaration
, _EncodingProp
):
994 String (NULL-terminated array of bytes) field declaration.
999 Creates a string field declaration.
1001 :exc:`ValueError` is raised on error.
1004 self
._field
_type
= bt2
.StringFieldType()
1009 def create_field(field_type
):
1011 Create an instance of a field.
1013 isinst
= isinstance(field_type
, FieldDeclaration
)
1015 if field_type
is None or not isinst
:
1016 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1018 if isinstance(field_type
, IntegerFieldDeclaration
):
1019 return IntegerField(field_type
)
1020 elif isinstance(field_type
, EnumerationFieldDeclaration
):
1021 return EnumerationField(field_type
)
1022 elif isinstance(field_type
, FloatFieldDeclaration
):
1023 return FloatingPointField(field_type
)
1024 elif isinstance(field_type
, StructureFieldDeclaration
):
1025 return StructureField(field_type
)
1026 elif isinstance(field_type
, VariantFieldDeclaration
):
1027 return VariantField(field_type
)
1028 elif isinstance(field_type
, ArrayFieldDeclaration
):
1029 return ArrayField(field_type
)
1030 elif isinstance(field_type
, SequenceFieldDeclaration
):
1031 return SequenceField(field_type
)
1032 elif isinstance(field_type
, StringFieldDeclaration
):
1033 return StringField(field_type
)
1038 Base class of all fields. This class is not meant to be
1039 instantiated by the user, and neither are its subclasses. Use
1040 :meth:`Event.payload` to access specific, concrete fields of
1044 def __init__(self
, field_type
):
1045 if not isinstance(field_type
, FieldDeclaration
):
1046 raise TypeError("Invalid field_type argument.")
1049 self
._f
= field_type
._field
_type
()
1051 raise ValueError("Field creation failed.")
1054 def _create_field(bt2_field
):
1056 bt2
._IntegerField
: IntegerField
,
1057 bt2
._FloatingPointNumberField
: FloatingPointField
,
1058 bt2
._EnumerationField
: EnumerationField
,
1059 bt2
._StringField
: StringField
,
1060 bt2
._StructureField
: StructureField
,
1061 bt2
._VariantField
: VariantField
,
1062 bt2
._ArrayField
: ArrayField
,
1063 bt2
._SequenceField
: SequenceField
1066 if type(bt2_field
) not in type_dict
:
1067 raise TypeError("Invalid field instance.")
1069 field
= Field
.__new
__(Field
)
1070 field
._f
= bt2_field
1071 field
.__class
__ = type_dict
[type(bt2_field
)]
1076 def declaration(self
):
1078 Field declaration (subclass of :class:`FieldDeclaration`).
1080 :exc:`TypeError` is raised on error.
1083 return FieldDeclaration
._create
_field
_declaration
(self
._f
.field_type
)
1086 class IntegerField(Field
):
1088 Integer field, based on an :class:`IntegerFieldDeclaration` object.
1094 Integer value (:class:`int`).
1096 Set this attribute to change the integer field's value.
1098 :exc:`ValueError` or :exc:`TypeError` are raised on error.
1104 ValueError('Could not get integer field value.')
1107 def value(self
, value
):
1109 self
._f
.value
= value
1111 raise ValueError("Could not set integer field value.")
1114 class EnumerationField(Field
):
1116 Enumeration field, based on an
1117 :class:`EnumerationFieldDeclaration` object.
1121 def container(self
):
1123 Underlying container (:class:`IntegerField`).
1125 :exc:`TypeError` is raised on error.
1129 return Field
._create
_field
(self
._f
.integer_field
)
1131 raise TypeError("Invalid enumeration field type.")
1136 Current label of this enumeration field (:class:`str`).
1138 Set this attribute to an integer (:class:`int`) to change the
1139 enumeration field's value.
1141 :exc:`ValueError` is raised on error.
1145 bt2_enum_ft
= self
._f
.field_type
1146 mappings
= list(bt2_enum_ft
.mappings_by_value(self
._f
.value
))
1147 return mappings
[0].name
1149 raise ValueError("Could not get enumeration mapping name.")
1152 def value(self
, value
):
1153 if not isinstance(value
, int):
1154 raise TypeError("EnumerationField value must be an int")
1156 self
._f
.value
= value
1159 class FloatingPointField(Field
):
1161 Floating point number field, based on a
1162 :class:`FloatingPointFieldDeclaration` object.
1168 Floating point number value (:class:`float`).
1170 Set this attribute to change the floating point number field's
1173 :exc:`ValueError` or :exc:`TypeError` are raised on error.
1179 raise ValueError("Could not get floating point field value.")
1182 def value(self
, value
):
1184 self
._f
.value
= value
1186 raise ValueError("Could not set floating point field value.")
1189 # This class is provided to ensure backward-compatibility since a stable
1190 # release publicly exposed this... abomination.
1191 class FloatFieldingPoint(FloatingPointField
):
1195 class StructureField(Field
):
1197 Structure field, based on a
1198 :class:`StructureFieldDeclaration` object.
1201 def field(self
, field_name
):
1203 Returns the structure :class:`Field` named *field_name*.
1205 :exc:`ValueError` is raised on error.
1209 return Field
._create
_field
(self
._f
[field_name
])
1211 raise ValueError("Invalid field_name provided.")
1214 class VariantField(Field
):
1216 Variant field, based on a
1217 :class:`VariantFieldDeclaration` object.
1220 def field(self
, tag
):
1222 Returns the :class:`Field` selected by the current label of
1223 *tag* (:class:`EnumerationField`).
1225 :exc:`ValueError` is raised on error.
1229 return Field
._create
_field
(self
._f
.field(tag
._f
))
1231 raise ValueError("Invalid tag provided.")
1234 class ArrayField(Field
):
1236 Static array field, based on an
1237 :class:`ArrayFieldDeclaration` object.
1240 def field(self
, index
):
1242 Returns the :class:`Field` at index *index* in this static
1245 :exc:`IndexError` is raised on error.
1249 return Field
._create
_field
(self
._f
[index
])
1251 raise IndexError("Invalid index provided.")
1254 class SequenceField(Field
):
1256 Sequence (dynamic array) field, based on a
1257 :class:`SequenceFieldDeclaration` object.
1263 Sequence length (:class:`IntegerField`).
1265 Set this attribute to change the sequence length's integer
1266 field (integer must be unsigned).
1268 :exc:`ValueError` or :exc:`TypeError` are raised on error.
1272 length_field
= self
._f
.length_field
1273 if length_field
is None:
1275 return Field
._create
_field
(length_field
)
1277 raise ValueError('Invalid sequence field.')
1280 def length(self
, length_field
):
1281 if not isinstance(length_field
, IntegerField
):
1282 raise TypeError("Invalid length field.")
1284 if length_field
.declaration
.signed
:
1285 raise TypeError("Sequence field length must be unsigned")
1288 self
._f
.length_field
= length_field
._f
1290 raise ValueError("Could not set sequence length.")
1292 def field(self
, index
):
1294 Returns the :class:`Field` at index *index* in this sequence.
1296 :exc:`ValueError` is raised on error.
1300 return Field
._create
_field
(self
._f
[index
])
1302 raise IndexError("Invalid index provided.")
1305 class StringField(Field
):
1307 String (NULL-terminated array of bytes) field.
1313 String value (:class:`str`).
1315 Set this attribute to change the string's value.
1317 :exc:`ValueError` or :exc:`TypeError` are raised on error.
1323 raise ValueError('Could not get string field value.')
1326 def value(self
, value
):
1328 self
._f
.value
= value
1330 raise ValueError("Could not set string field value.")
1335 An event class contains the properties of specific
1336 events (:class:`Event`). Any concrete event must be linked with an
1337 :class:`EventClass`.
1339 Some attributes are automatically set when creating an event class.
1340 For example, if no numeric ID is explicitly set using the
1341 :attr:`id` attribute, a default, unique ID within the stream class
1342 containing this event class will be created when needed.
1345 def __init__(self
, name
):
1347 Creates an event class named *name*.
1349 :exc:`ValueError` is raised on error.
1352 self
._ec
= bt2
.EventClass(name
)
1354 if self
._ec
is None:
1355 raise ValueError("Event class creation failed.")
1357 def add_field(self
, field_type
, field_name
):
1359 Adds a field declaration *field_type* named *field_name* to
1362 *field_type* must be one of:
1364 * :class:`IntegerFieldDeclaration`
1365 * :class:`FloatingPointFieldDeclaration`
1366 * :class:`EnumerationFieldDeclaration`
1367 * :class:`StringFieldDeclaration`
1368 * :class:`ArrayFieldDeclaration`
1369 * :class:`SequenceFieldDeclaration`
1370 * :class:`StructureFieldDeclaration`
1371 * :class:`VariantFieldDeclaration`
1373 :exc:`ValueError` is raised on error.
1377 self
._ec
.payload_field_type
.append_field(field_name
,
1378 field_type
._field
_type
)
1380 raise ValueError("Could not add field to event class.")
1389 return self
._ec
.name
1391 raise TypeError("Could not get EventClass name")
1396 Event class' numeric ID.
1398 Set this attribute to assign a numeric ID to this event class.
1399 This ID must be unique amongst all the event class IDs of a
1402 :exc:`TypeError` is raised on error.
1408 raise TypeError("Could not get EventClass id")
1415 raise TypeError("Can't change an EventClass id after it has been assigned to a stream class.")
1418 def stream_class(self
):
1420 :class:`StreamClass` object containing this event class,
1421 or ``None`` if not set.
1424 bt2_stream_class
= self
._ec
.stream_class
1425 if bt2_stream_class
is None:
1428 stream_class
= StreamClass
.__new
__(StreamClass
)
1429 stream_class
._stream
_class
= bt2_stream_class
1436 Generates the (field name, :class:`FieldDeclaration`) pairs of
1439 :exc:`TypeError` is raised on error.
1442 return FieldDeclaration
._create
_field
_declaration
(
1443 self
._ec
.payload_field_type
).fields
1445 def get_field_by_name(self
, name
):
1447 Returns the :class:`FieldDeclaration` object named *name* in
1450 :exc:`TypeError` is raised on error.
1453 return FieldDeclaration
._create
_field
_declaration
(
1454 self
._ec
.payload_field_type
)[name
]
1459 Events are specific instances of event classes
1460 (:class:`EventClass`), which means they may contain actual,
1461 concrete field values.
1464 def __init__(self
, event_class
):
1466 Creates an event linked with the :class:`EventClass`
1469 :exc:`ValueError` is raised on error.
1472 if not isinstance(event_class
, EventClass
):
1473 raise TypeError("Invalid event_class argument.")
1476 self
._e
= event_class
._ec
()
1478 raise ValueError("Event creation failed.")
1481 def event_class(self
):
1483 :class:`EventClass` object to which this event is linked.
1486 event_class
= EventClass
.__new
__(EventClass
)
1487 event_class
._ec
= self
._e
.event_class
1492 :class:`Clock` object used by this object, or ``None`` if
1493 the event class is not registered to a stream class.
1497 bt2_clock
= self
._e
.event_class
.stream_class
.clock
1501 clock
= Clock
.__new
__(Clock
)
1502 clock
._c
= bt2_clock
1505 def payload(self
, field_name
):
1507 Returns the :class:`Field` object named *field_name* in this
1510 The returned field object is created using the event class'
1511 field declaration named *field_name*.
1513 The return type is one of:
1515 * :class:`IntegerField`
1516 * :class:`FloatingPointField`
1517 * :class:`EnumerationField`
1518 * :class:`StringField`
1519 * :class:`ArrayField`
1520 * :class:`SequenceField`
1521 * :class:`StructureField`
1522 * :class:`VariantField`
1524 :exc:`TypeError` is raised on error.
1528 return Field
._create
_field
(self
._e
.payload_field
[field_name
])
1530 raise TypeError('Could not get field from event.')
1532 def set_payload(self
, field_name
, value_field
):
1534 Set the event's field named *field_name* to the manually
1535 created :class:`Field` object *value_field*.
1537 *value_field*'s type must be one of:
1539 * :class:`IntegerField`
1540 * :class:`FloatingPointField`
1541 * :class:`EnumerationField`
1542 * :class:`StringField`
1543 * :class:`ArrayField`
1544 * :class:`SequenceField`
1545 * :class:`StructureField`
1546 * :class:`VariantField`
1548 :exc:`ValueError` is raised on error.
1551 if not isinstance(value_field
, Field
):
1552 raise TypeError("Invalid value type.")
1555 self
._e
.payload_field
[field_name
] = value_field
._f
1557 raise ValueError("Could not set event field payload.")
1560 def stream_context(self
):
1562 Stream event context field (instance of
1563 :class:`StructureField`).
1565 Set this attribute to assign a stream event context field
1568 :exc:`ValueError` is raised on error.
1572 return Field
._create
_field
(self
._e
.context_field
)
1574 raise ValueError("Invalid Stream.")
1576 @stream_context.setter
1577 def stream_context(self
, field
):
1578 if not isinstance(field
, StructureField
):
1579 raise TypeError("Argument field must be of type StructureField")
1582 self
._e
.context_field
= field
._f
1584 raise ValueError("Invalid stream context field.")
1588 A stream class contains the properties of specific
1589 streams (:class:`Stream`). Any concrete stream must be linked with
1590 a :class:`StreamClass`, usually by calling
1591 :meth:`Writer.create_stream`.
1593 Some attributes are automatically set when creating a stream class.
1594 For example, if no clock is explicitly set using the
1595 :attr:`clock` attribute, a default clock will be created
1599 def __init__(self
, name
):
1601 Creates a stream class named *name*.
1603 :exc:`ValueError` is raised on error.
1607 # Set default event header and packet context.
1608 event_header_type
= bt2
.StructureFieldType()
1609 uint32_ft
= bt2
.IntegerFieldType(32, is_signed
=False)
1610 uint64_ft
= bt2
.IntegerFieldType(32, is_signed
=False)
1611 event_header_type
.append_field('id', uint32_ft
)
1612 event_header_type
.append_field('timestamp', uint64_ft
)
1614 packet_context_type
= bt2
.StructureFieldType()
1615 packet_context_type
.append_field('timestamp_begin', uint64_ft
)
1616 packet_context_type
.append_field('timestamp_end', uint64_ft
)
1617 packet_context_type
.append_field('content_size', uint64_ft
)
1618 packet_context_type
.append_field('packet_size', uint64_ft
)
1619 packet_context_type
.append_field('events_discarded', uint64_ft
)
1620 sc
= bt2
.StreamClass(name
,
1621 event_header_field_type
=event_header_type
,
1622 packet_context_field_type
=packet_context_type
)
1623 self
._stream
_class
= sc
1625 raise ValueError("Stream class creation failed.")
1632 :exc:`TypeError` is raised on error.
1636 return self
._stream
_class
.name
1638 raise TypeError("Could not get StreamClass name")
1643 Stream class' clock (:class:`Clock` object).
1645 Set this attribute to change the clock of this stream class.
1647 :exc:`ValueError` is raised on error.
1650 if self
._stream
_class
.clock
is None:
1653 clock
= Clock
.__new
__(Clock
)
1654 clock
._c
= self
._stream
_class
.clock
1658 def clock(self
, clock
):
1659 if not isinstance(clock
, Clock
):
1660 raise TypeError("Invalid clock type.")
1663 self
._stream
_class
.clock
= clock
._clock
1665 raise ValueError("Could not set stream class clock.")
1670 Stream class' numeric ID.
1672 Set this attribute to change the ID of this stream class.
1674 :exc:`ValueError` is raised on error.
1678 return self
._stream
_class
.id
1680 raise TypeError("Could not get StreamClass id")
1685 self
._stream
_class
.id = id
1687 raise TypeError("Could not set stream class id.")
1690 def event_classes(self
):
1692 Generates the event classes (:class:`EventClass` objects) of
1695 :exc:`TypeError` is raised on error.
1698 for bt2_ec
in self
._stream
_class
.values():
1699 event_class
= EventClass
.__new
__(EventClass
)
1700 event_class
._ec
= bt2_ec
1703 def add_event_class(self
, event_class
):
1705 Registers the :class:`EventClass` *event_class* to this stream
1708 Once the event class is registered, it will be generated as one
1709 of the event classes generated by :attr:`event_classes`.
1711 :exc:`ValueError` is raised on error.
1714 if not isinstance(event_class
, EventClass
):
1715 raise TypeError("Invalid event_class type.")
1718 self
._stream
_class
.add_event_class(event_class
._ec
)
1720 raise ValueError("Could not add event class.")
1723 def packet_context_type(self
):
1725 Stream packet context declaration.
1727 Set this attribute to change the stream packet context
1728 declaration (must be an instance of
1729 :class:`StructureFieldDeclaration`).
1731 :exc:`ValueError` is raised on error.
1736 bt2_field_type
= self
._stream
_class
.packet_context_field_type
1737 if bt2_field_type
is None:
1738 raise ValueError("Invalid StreamClass")
1740 field_type
= FieldDeclaration
._create
_field
_declaration
(
1744 raise ValueError("Invalid StreamClass")
1746 @packet_context_type.setter
1747 def packet_context_type(self
, field_type
):
1748 if field_type
is not None and not isinstance(field_type
,
1749 StructureFieldDeclaration
):
1750 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1752 bt2_field_type
= None if field_type
is None else field_type
._field
_type
1754 self
._stream
_class
.packet_context_field_type
= bt2_field_type
1756 raise ValueError("Failed to set packet context type.")
1759 def event_context_type(self
):
1761 Stream event context declaration.
1763 Set this attribute to change the stream event context
1764 declaration (must be an instance of
1765 :class:`StructureFieldDeclaration`).
1767 :exc:`ValueError` is raised on error.
1772 bt2_field_type
= self
._stream
_class
.event_context_field_type
1773 if bt2_field_type
is None:
1774 raise ValueError("Invalid StreamClass")
1776 field_type
= FieldDeclaration
._create
_field
_declaration
(
1780 raise ValueError("Invalid StreamClass")
1782 @event_context_type.setter
1783 def event_context_type(self
, field_type
):
1784 if field_type
is not None and not isinstance(field_type
,
1785 StructureFieldDeclaration
):
1786 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1788 bt2_field_type
= None if field_type
is None else field_type
._field
_type
1790 self
._stream
_class
.event_context_field_type
= bt2_field_type
1792 raise ValueError("Failed to set event context type.")
1797 Streams are specific instances of stream classes, which means they
1798 may contain actual, concrete events.
1800 :class:`Stream` objects are returned by
1801 :meth:`Writer.create_stream`; they are not meant to be
1802 instantiated by the user.
1804 Concrete :class:`Event` objects are appended to
1805 :class:`Stream` objects using :meth:`append_event`.
1807 When :meth:`flush` is called, a CTF packet is created, containing
1808 all the appended events since the last flush. Although the stream
1809 is flushed on object destruction, it is **strongly recommended**
1810 that the user call :meth:`flush` manually before exiting the
1811 script, as :meth:`__del__` is not always reliable.
1815 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1818 def discarded_events(self
):
1820 Number of discarded (lost) events in this stream so far.
1822 :exc:`ValueError` is raised on error.
1826 return self
._s
.discarded_events_count
1828 raise ValueError("Could not get the stream discarded events count")
1830 def append_discarded_events(self
, event_count
):
1832 Appends *event_count* discarded events to this stream.
1835 self
._s
.append_discarded_events(event_count
)
1837 def append_event(self
, event
):
1839 Appends event *event* (:class:`Event` object) to this stream.
1841 The stream's associated clock will be sampled during this call.
1842 *event* **shall not** be modified after being appended to this
1845 :exc:`ValueError` is raised on error.
1849 self
._s
.append_event(event
._e
)
1851 raise ValueError("Could not append event to stream.")
1854 def packet_context(self
):
1856 Stream packet context field (instance of
1857 :class:`StructureField`).
1859 Set this attribute to assign a stream packet context field
1862 :exc:`ValueError` is raised on error.
1865 bt2_field
= self
._s
.packet_context_field
1866 if bt2_field
is None:
1867 raise ValueError("Invalid Stream.")
1869 return Field
._create
_field
(bt2_field
)
1871 @packet_context.setter
1872 def packet_context(self
, field
):
1873 if not isinstance(field
, StructureField
):
1874 raise TypeError("Argument field must be of type StructureField")
1877 self
._s
.packet_context_field
= field
._f
1879 raise ValueError("Invalid packet context field.")
1883 Flushes the current packet of this stream to disk. Events
1884 subsequently appended to the stream will be added to a new
1887 :exc:`ValueError` is raised on error.
1895 This object is the CTF writer API context. It oversees its streams
1896 and clocks, and is responsible for writing one CTF trace.
1899 def __init__(self
, path
):
1901 Creates a CTF writer, initializing a new CTF trace at path
1904 *path* must be an existing directory, since a CTF trace is
1905 made of multiple files.
1907 :exc:`ValueError` is raised if the creation fails.
1911 self
._w
= bt2
.CtfWriter(path
)
1913 raise ValueError("Writer creation failed.")
1915 def create_stream(self
, stream_class
):
1917 Creates and registers a new stream based on stream class
1920 This is the standard way of creating a :class:`Stream` object:
1921 the user is not allowed to instantiate this class.
1923 Returns a new :class:`Stream` object.
1926 if not isinstance(stream_class
, StreamClass
):
1927 raise TypeError("Invalid stream_class type.")
1929 if stream_class
._stream
_class
.trace
is None:
1930 self
._w
.trace
.add_stream_class(stream_class
._stream
_class
)
1932 stream
= Stream
.__new
__(Stream
)
1933 stream
._s
= stream_class
._stream
_class
()
1934 stream
.__class
__ = Stream
1937 def add_environment_field(self
, name
, value
):
1939 Sets the CTF environment variable named *name* to value *value*
1940 (converted to a string).
1942 :exc:`ValueError` or `TypeError` is raised on error.
1945 if type(name
) != str:
1946 raise TypeError("Field name must be a string.")
1950 if type(value
) != str and type(value
) != int:
1951 raise TypeError("Value type is not supported.")
1954 self
._w
.trace
.env
+= {name
: value
}
1956 raise ValueError("Could not add environment field to trace.")
1958 def add_clock(self
, clock
):
1960 Registers :class:`Clock` object *clock* to the writer.
1962 You *must* register CTF clocks assigned to stream classes
1965 :exc:`ValueError` is raised if the creation fails.
1969 self
._w
.add_clock(clock
._clock
)
1971 raise ValueError("Could not add clock to Writer.")
1976 Current metadata of this trace (:class:`str`).
1979 return self
._w
.metadata_string
1981 def flush_metadata(self
):
1983 Flushes the trace's metadata to the metadata file.
1986 self
._w
.flush_metadata()
1989 def byte_order(self
):
1991 Native byte order of this trace (one of
1992 :class:`babeltrace.common.ByteOrder` constants).
1994 This is the actual byte order that is used when a field
1996 :attr:`babeltrace.common.ByteOrder.BYTE_ORDER_NATIVE`
1999 Set this attribute to change the trace's native byte order.
2001 Defaults to the host machine's endianness.
2003 :exc:`ValueError` is raised on error.
2005 raise NotImplementedError("Getter not implemented.")
2008 def byte_order(self
, byte_order
):
2010 self
._w
.trace
.native_byte_order
= _BYTE_ORDER_TO_BT2_BYTE_ORDER
[byte_order
]
2012 raise ValueError("Could not set trace byte order.")
2015 _BT2_FIELD_TYPE_TO_BT_DECLARATION
= {
2016 bt2
.IntegerFieldType
: IntegerFieldDeclaration
,
2017 bt2
.FloatingPointNumberFieldType
: FloatFieldDeclaration
,
2018 bt2
.EnumerationFieldType
: EnumerationFieldDeclaration
,
2019 bt2
.StringFieldType
: StringFieldDeclaration
,
2020 bt2
.StructureFieldType
: StructureFieldDeclaration
,
2021 bt2
.ArrayFieldType
: ArrayFieldDeclaration
,
2022 bt2
.SequenceFieldType
: SequenceFieldDeclaration
,
2023 bt2
.VariantFieldType
: VariantFieldDeclaration
,