babeltrace.git
4 years agoCTF IR -> Trace IR
Philippe Proulx [Thu, 15 Nov 2018 13:20:23 +0000 (08:20 -0500)] 
CTF IR -> Trace IR

Also, keep an `include/babeltrace/ctf-ir` directory of which the headers
are only including corresponding CTF writer headers for backward
compatibility.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoMake API CTF-agnostic
Philippe Proulx [Thu, 23 Aug 2018 15:43:54 +0000 (11:43 -0400)] 
Make API CTF-agnostic

The main purpose of this patch is to make the Babeltrace 2 API unrelated
to the Common Trace Format. This makes the Babeltrace 2 API easier to
use and data structures are more compact: you don't need to know the
implicit and explicit CTF rules to use the Babeltrace 2 API. It also
prepares the Babeltrace 2 API to be ready, as much as possible, for the
upcoming CTF 2.

General API changes
-------------------
* To make the API simpler, most object properties are optional. This
  includes the names of event classes, stream classes, traces, and
  clock classes, for example.

  Event classes and stream classes still have unique IDs. This makes it
  easier to deterministically identify metadata objects. You can call
  one of:

  bt_event_class_create():
      Create an event class with an automatic ID. I believe most sources
      will use this version.

  bt_event_class_create_with_id():
      Create an event class with an explicit unique ID (within its
      parent stream class).

  You cannot call bt_event_class_create() and
  bt_event_class_create_with_id() to create event classes which belong
  to the same stream class: the stream class has a manual or automatic
  event class ID assignment mode (automatic by default) which you can
  change with bt_stream_class_set_assigns_automatic_event_class_id()
  before adding any event class. The same strategy is used for a stream
  class and a stream (its parents being a trace).

* All API functions return some status code (sometimes a simple `int`
  which can be 0 (success) or negative (error)) IF and only if they can
  fail. Simple property getters never fail, so they return the
  property's value directly. This means that many functions now return
  the `uint64_t` type: the caller does not need to check for an error
  (for example, bt_stream_class_get_id(), because a stream class always
  has an ID).

  Just in case, all property setters can still fail (although most won't
  currently; they always return 0), so they return a status code. This
  could help us add caches and create lazy setters eventually.

  When a function returns a pointer, for example, `const char *` or
  `struct bt_field_type *`, `NULL` does NOT indicate an error: it means
  the property is absent. A function which could fail and which needs to
  return a pointer sets an output parameter instead and returns a status
  code.

  A function can return `enum bt_property_availability` and set (or not)
  an output parameter for non-pointer optional properties. An example is
  bt_event_class_get_log_level(): it is possible that an event class has
  no log level.

  This also means that all `*_UNKNOWN` enumeration labels set to -1 are
  gone.

* The public metadata visitor API is removed as it is not used anywhere.
  We could reintroduce it later, with care, if need be.

* The `babeltrace/ctf-ir/utils.h` file is removed completely. It only
  contained a function to check if a given string is a valid CTF
  identifier.

* Terminology: "nanoseconds from Epoch" becomes "nanoseconds from
  origin". When a clock class is not absolute, it has an offset from a
  given origin, not from the Unix Epoch.

* New `bt_uuid` type alias for `const uint8_t *`.

* All API functions which increment an object's reference count
  ("getting" functions) are removed, as it is preferred and encouraged
  to use borrowing functions. You can still do, for example:

      struct bt_stream_class *sc =
          bt_get(bt_event_class_borrow_stream_class(ec));

* Conditional precondition checking (BT_ASSERT_PRE()) is used at many
  more places now, even in the metadata API, as you could call this API
  on the fast path anyway.

* Various functions are renamed for consistency and terminology
  accuracy.

* Most of the API documentation is removed because it is not accurate
  anymore.

Clock class API changes
-----------------------
* bt_clock_class_create() has no parameters: the name property is
  optional (not set by default), and the default frequency is 1 GHz.

* You set and get both offsets at the same time because you often need
  both of them any: bt_clock_class_set_offset() and
  bt_clock_class_get_offset().

* The name property can have any value: it is not limited to CTF
  identifiers anymore.

* The absolute property is true by default: a default clock class's
  origin is the Unix Epoch.

* The cycle part of the offset MUST be less than the frequency. The
  library validates this in developer mode when calling both
  bt_clock_class_set_offset() and bt_clock_class_set_frequency().

  This makes some time conversion easier to compute and more precise.

Clock value API changes
-----------------------
* A clock value can be known or unknown. As of Babeltrace 2.0, there's
  no function to make a clock value unknown, but the API to get this
  state exists (returned by bt_event_borrow_default_clock_value(), for
  example).

  The bt_stream_class_default_clock_is_always_known() function indicates
  if, for all the streams created from this stream class, their default
  clocks are always known (the default clock value accessors never
  return `BT_CLOCK_VALUE_STATUS_UNKNOWN`). As of this patch, this
  function always returns `BT_TRUE`.

Event class API changes
-----------------------
* Terminology: "context field type" becomes "specific context field
  type" to differentiate this scope from the "common context field type"
  defined at the stream class level.

Event class, stream class, and trace API changes
------------------------------------------------
* You need to pass a trace object to bt_stream_class_create() and a
  stream class object to bt_event_class_create(). In other words, you
  cannot create a "free" stream class, add event classes to it, and then
  add the stream class object to a trace object. This makes validation a
  lot easier and a great quantity of code was sent to the Recycle Bin
  thanks to this contraint.

  bt_trace_add_stream_class() and bt_stream_class_add_event_class() are
  removed because creating an event class or a stream class
  automatically adds it to its parent.

Event header field API changes
------------------------------
* Replace bt_stream_class_create_event_header_field() with
  bt_event_header_field_create(). This is more consistent with this API
  where you typically create an object with its own API an pass whatever
  is needed (e.g., bt_event_class_create() instead of
  bt_stream_class_create_event_class()).

Event API changes
-----------------
* Terminology: "context field type" becomes "specific context field" to
  differentiate this scope from the "common context field".

* New bt_event_set_default_clock_value() and
  bt_event_borrow_default_clock_value() to set and get the event's
  default clock value.

  You MUST set an event's default clock value if its stream class has a
  default clock class (see bt_stream_class_set_default_clock_class()).

  With bt_event_set_default_clock_value(), you don't need to specify the
  clock class as this function uses the stream class's default clock
  class. When multiple clock classes per stream class become supported
  eventually, we'll introduce bt_event_set_clock_value() where you
  specify a clock class for which to set a clock value.

Field type API and concept changes
----------------------------------
* Field types do not have any attached semantics anymore. This includes:

  * Special fields identified by name. Examples are `uuid`, `id`,
    `packet_size`, and `events_discarded`.

    This removes some redundancy between fields and metadata objects,
    for example a packet's header field's `uuid` field always contains
    the same value as the trace object's UUID property (if any). The
    same goes for the stream class ID, the stream ID, the event class
    ID, etc.

  * Mapped clock classes. Mapping an integer field type to a clock class
    makes things complicated because of the CTF clock updating mechanism
    (with automatic wrapping for compression). Instead, packet and event
    objects have a "default clock value" property which the source or
    filter explicitly sets. Therefore, the CTF clock updating mechanism
    is part of the CTF plugin now (in `notif-iter.c`).

* All field type objects, within a given trace object (recursively),
  MUST be unique. The library validates this in developer mode. This
  means you cannot create a single integer field type, for example, and
  add it more than one time to a given structure field type.

  This makes it possible to uniquely identify a field type by its
  address, and it makes validation easier. Also, weird side effects like
  variant or sequence field types being copied during validation are
  gone with this constraint.

  Field type objects are still shared, although most components should
  only need to borrow them.

* The byte order, alignment, and integer/string field type encoding
  properties are removed. They are not needed by the IR API: they are
  CTF concepts.

* bt_field_type_integer_create(), bt_field_type_integer_set_is_signed(),
  and bt_field_type_integer_is_signed() are removed. Now there's an
  unsigned and a signed integer type:
  `BT_FIELD_TYPE_ID_UNSIGNED_INTEGER` and
  `BT_FIELD_TYPE_ID_SIGNED_INTEGER`. This is because integer field type
  and field APIs can be different depending on the signedness (return
  types, for example).

  bt_field_type_unsigned_integer_create() and
  bt_field_type_signed_integer_create() have no parameters: they create
  default integer field types with a 64-bit equivalent value range.

* An enumeration field type is now conceptually an integer field type.

* bt_field_type_enumeration_create() is removed. Now there's an unsigned
  and a signed enumeration type: `BT_FIELD_TYPE_ID_UNSIGNED_ENUMERATION`
  and `BT_FIELD_TYPE_ID_SIGNED_ENUMERATION`. This is because enumeration
  field type and field APIs can be different depending on the signedness
  (return types, for example).

  bt_field_type_unsigned_enumeration_create() and
  bt_field_type_signed_enumeration_create() have no parameters: they
  don't need an "underlying" integer field type because they ARE integer
  field types.

* Functions named bt_field_type_integer_*() apply to any integer
  (including enumeration) field type (unsigned or signed).

* Functions named bt_field_type_enumeration_*() apply to any enumeration
  field type (unsigned or signed).

* Terminology: the "size" integer field type property becomes "field
  value range". This property indicates the expected minimum and maximum
  values of fields created from a given integer field type. The
  bt_field_type_integer_set_field_value_range() function accepts a
  parameter which is N in the following formulas:

  * Unsigned integer range: [0, 2^N - 1]
  * Signed integer range: [-2^(N - 1), 2^(N - 1) - 1]

* Terminology: "base" becomes "preferred display base". The default
  preferred display base is 10. It is kept as a property to satisfy the
  CTF 1.8 use case, although it should eventually be part of a custom
  user attribute when we change the API to support CTF 2 features.

* Terminology: "floating point number field type" becomes "real field
  type" (as in _real number_).

* The only property of a real field type is if it's single precision or
  not (double precision). The accessors are
  bt_field_type_real_is_single_precision() and
  bt_field_type_real_set_is_single_precision().

  We don't need explicit exponent and mantissa sizes as those are
  CTF/encoding concepts.

* The concept of an enumeration field type mapping iterator is removed.
  Instead:

  * We change the "mapping" concept: an enumeration field type mapping
    is a label and a set of ranges. Mapping labels are unique within
    an enumeration field type, but the same ranges can exist in
    different mappings (overlaps).

    The functions to get mappings are
    bt_field_type_enumeration_get_mapping_count(),
    bt_field_type_unsigned_enumeration_borrow_mapping_by_index(), and
    bt_field_type_signed_enumeration_borrow_mapping_by_index(),
    depending on the enumeration field type's signedness.

    The functions to add mappings look similar to what they used to:
    bt_field_type_unsigned_enumeration_map_range() and
    bt_field_type_signed_enumeration_map_range(). Those functions find
    any existing mapping sharing the label and add the given range to it
    (or create a new mapping).

    Then it becomes trivial to get all the ranges of a given mapping
    by label: they are already stored as such in the object.

  * To get all the mapping labels which contain a given value within
    their ranges, call
    bt_field_type_unsigned_enumeration_get_mapping_labels_by_value() or
    bt_field_type_signed_enumeration_get_mapping_labels_by_value().

    Those functions accept a
    `bt_field_type_enumeration_mapping_label_array` parameter which is
    `const char * const *`. There's no copy to the user here: the
    functions fill an array internal to the enumeration field type
    object and return its address. Then the array is valid as long as
    you don't call those functions again for the same object.

    This should be enough as what you want is often all the labels,
    not just the first one, and use cases where there are thousands of
    labels matching a given value are nonexistent AFAIK.

* Terminology: "structure field type field" becomes "structure field
  type member".

* Terminology: "variant field type field" becomes "variant field type
  option".

* Structure field type member and variant field type option names can
  have any value (as long as they are unique within their parent): they
  are not limited by CTF identifiers anymore.

* Terminology: "adding a structure field type member" becomes "appending
  a structure field type member". Members are ordered, so "append" makes
  sense here (like Python's list's append() method). The same goes for
  variant field types.

* bt_field_type_array_create() and bt_field_type_sequence_create() are
  remove.

  Conceptually, with this patch, there are static and dynamic array
  field types. Both are array field types, although you cannot create
  an (abstract) array field type.

  Use bt_field_type_static_array_create() and
  bt_field_type_dynamic_array_create() to create static and dynamic
  field types. Both require an element field type, and
  bt_field_type_static_array_create() also requires the static length.

  The common API is bt_field_type_array_borrow_element_field_type().

* Terminology: "variant field type tag" becomes "variant field type
  selector". This is more in line with the concept of a "selected
  field", for example.

* For both the dynamic array and variant field types, the
  length/selector field type is now optional. This is a CTF concept: a
  source can create dynamic array fields without having another field
  which contains its length. You set a dynamic array field's length with
  bt_field_dynamic_array_set_length(). Having another field contain its
  length is just an encoding concept. The same is true for a variant
  field and its selector field.

  You can still link a dynamic array or variant field type to its length
  of selector field type with
  bt_field_type_dynamic_array_set_length_field_type() or
  bt_field_type_variant_set_selector_field_type(). Those functions take
  the linked field type and set the field paths automatically. This is
  possible now because an event class is always within a stream class
  which is always within a trace, so the linked field type should be
  visible (validated in developer mode).

Field API changes
-----------------
* In general, field type API changes are reflected on the field API. For
  example, since an enumeration field type is conceptually an integer
  field type, an enumeration field is conceptually an integer field.
  This means that you can call bt_field_signed_integer_get_value() to
  get the integer value of a signed enumeration field.

* bt_field_array_get_length() is a common array field API which applies
  to both static and dynamic array fields. When you call it with a
  static array field, it returns its field type's static length.

* bt_field_array_borrow_element_field_by_index() is a common array
  field API which applies to both static and dynamic array fields.

* Because a variant field has no link to its selector field now (it is
  optional), you need to set the selected option by index with
  bt_field_variant_select_option_field(). Then you can get the selected
  option with bt_field_variant_borrow_selected_option_field() (and its
  index with bt_field_variant_get_selected_option_field_index()).

Packet context field API changes
--------------------------------
* Replace bt_stream_class_create_packet_context_field() with
  bt_packet_context_field_create(). This is more consistent with this
  API where you typically create an object with its own API an pass
  whatever is needed (e.g., bt_event_class_create() instead of
  bt_stream_class_create_event_class()).

Packet header field API changes
-------------------------------
* Replace bt_trace_create_packet_header_field() with
  bt_packet_header_field_create(). This is more consistent with this API
  where you typically create an object with its own API an pass whatever
  is needed (e.g., bt_event_class_create() instead of
  bt_stream_class_create_event_class()).

Packet API changes
------------------
* A packet does not contain its previous packet's properties anymore.
  Any component which needs to compute the difference between the
  properties of two consecutive packets needs to keep the previous one
  manually.

  Therefore, everything related to the previous packet in the API is
  removed.

* A packet contains _snapshots_ of stream properties:

  * Default clock value at beginning of packet.
  * Default clock value at end of packet.
  * Discarded event counter at end of packet.
  * Packet counter (sequence number) at end of packet.

  You MUST set those snapshot properties if the packet's stream class
  has them enabled: see
  bt_stream_class_packets_have_discarded_event_counter_snapshot(),
  bt_stream_class_packets_have_packet_counter_snapshot(),
  bt_stream_class_packets_have_default_beginning_clock_value(), and
  bt_stream_class_packets_have_default_end_clock_value(). All those
  functions return `BT_FALSE` by default.

Stream class API changes
------------------------
* Terminology: "event context field type" becomes "event common context
  field type".

* Use bt_stream_class_set_default_clock_class() to set a stream class's
  default clock class. When a stream class has a default clock class,
  all the events which belong to a stream created from this stream class
  MUST have default clock values (bt_event_set_default_clock_value()).

* There are new properties which indicate if packets which belong to a
  stream created from a given stream class have specific stream property
  snapshots:
  bt_stream_class_packets_have_discarded_event_counter_snapshot(),
  bt_stream_class_packets_have_packet_counter_snapshot(),
  bt_stream_class_packets_have_default_beginning_clock_value(), and
  bt_stream_class_packets_have_default_end_clock_value(). All those
  functions return `BT_FALSE` by default.

Trace API changes
-----------------
* The native byte order property is removed. Is is not needed by the IR
  API: it is a CTF concept.

* Terminology: "environment field" becomes "environment entry".

Inactivity notification API changes
-----------------------------------
* bt_notification_inactivity_create() accepts a default clock class
  parameter so that you can call
  bt_notification_inactivity_set_default_clock_value() without
  specifying a clock class.

Stream notification API changes
-------------------------------
* bt_notification_stream_begin_set_default_clock_value() and
  bt_notification_stream_end_set_default_clock_value() do not accept a
  clock class parameter anymore: you set the default clock class at the
  stream class level.

Internal API changes
--------------------
* BT_LIB_LOG*(): the `%!u` conversion specifier formats a UUID
  (`bt_uuid`). `%!l` is now used to format a plugin object. `%!r` is
  removed (reference count) in favor of `%!O` which now formats any
  Babeltrace object (`struct bt_object *`).

* All freezing functions are only enabled in developer mode.

* New `include/babeltrace/property-internal.h` file with data structures
  and functions to deal with object properties (used for optional
  properties, like an event class's log level).

* `clock-class-internal.h`: new base offset value (ns) to compute
  nanoseconds from origin in clock values more efficiently.

* `field-types-internal.h`: new BT_ASSERT_PRE_FT_IS_*() macros to deal
  with integer, enumeration, and array field types which now have more
  than one field type ID.

* `fields-internal.h`: new BT_ASSERT_PRE_FIELD_IS_*() macros to deal
  with integer, enumeration, and array field which now have more than
  one field type ID.

* `utils-internal.h`: prefix function names with `bt_util_`.

* `validation-internal.h`: removed because all field types are valid
  since they have no attached semantics. Scoped validations are
  performed in property setters instead (developer mode).

* `visitor-internal.h`: removed because the visitor API is removed.

`ctf` plugin update
-------------------
Because the library's IR now misses important properties for decoding
purposes (alignment, byte order, linked field), the `ctf` plugin has its
own CTF metadata IR in `ctf-meta.h`. This file contains raw data
structures for:

* Field types
* Field path
* Event class
* Stream class
* Trace class

The IR generator AST visitor `visitor-generate-ir.c` converts the AST to
those data structures. All objects are uniquely allocated (no reference
count; they are not Babeltrace objects). Once the visitor has built a
basic CTF IR trace class, a sequence of filters are applied over it to
make it work for decoding purposes:

1. ctf_trace_class_update_default_clock_classes(): Set any stream
   class's default clock class based on integer field types mapped to
   clock classes within it.

2. ctf_trace_class_update_meanings(): Attaches meanings to specific
   integer field types.

   A meaning is a special quality which is needed to properly decode a
   data stream, for example, `CTF_FIELD_TYPE_MEANING_EVENT_CLASS_ID`,
   `CTF_FIELD_TYPE_MEANING_MAGIC`, and
   `CTF_FIELD_TYPE_MEANING_EXP_PACKET_TOTAL_SIZE`.

   For CTF 1.8, field types with meanings are found by name in specific
   scopes.

   When a field type has a meaning, it is not considered as an important
   value for subsequent filters and sinks, so the field type is marked
   as not having its equivalent library IR object. For example, the
   `packet_size` field type does not need to exist for connected filters
   and sinks because it's not holding trace information. If all the
   members of a structure field type, or all the options of a variant
   field type, recursively have no equivalent library IR objects, then
   this structure/variant field type has no equivalent library IR object
   either. Therefore, because the typical CTF packet header field type
   contains only the `magic` (magic number), `uuid` (UUID), `stream_id`
   (stream class ID), and `stream_instance_id` (stream ID) members, they
   all have meanings, thus the corresponding `bt_trace` object has no
   packet header field type.

3. ctf_trace_class_update_text_array_sequence(): Marks array and
   sequence field types containing only 8-bit aligned 8-bit integer
   field types with an encoding as being _text_ array and sequences.
   The equivalent library IR field types will be string field types.

4. ctf_trace_class_resolve_field_types(): Does what `resolve.c` used
   to do, but at the CTF IR level.

5. ctf_trace_class_update_in_ir(): Sets whether or not, depending on
   some conditions (meanings, mapped clock classes, etc.), CTF IR field
   types have equivalent library IR field types.

6. ctf_trace_class_update_value_storing_indexes(): Sets the indexes
   where to store decoded integer values, and from where to read those
   values for sequence lengths and variant tags.

   During decoding, when we need the length of a sequence or the tag of
   a variant, we don't look into existing `bt_field` objects. Instead,
   the length or tag was already stored at a specific index within an
   array of `uint64_t`/`int64_t` values, and we get this value back by
   index.

7. ctf_trace_class_validate(): Validates the whole trace class.

8. ctf_trace_class_translate(): Translates the CTF IR trace class into
   a `bt_trace` and marks translated CTF IR objects.

It is possible to add event classes or stream classes to an existing
trace class, and call all those functions again: they only update what's
not translated yet, and ctf_trace_class_translate() only translates
what's not translated yet.

When decoding (`notif-iter.c`), the bt_btr_start() function reads a CTF
IR field type to decode a data stream. When it calls back
bt_notif_iter_*() functions, they only set `bt_field` objects if they
need to. Of particular interest is the btr_unsigned_int_cb() callback:

This one:

1. Applies the meaning action if its CTF IR field type has a meaning.
   For example, if its meaning is `CTF_FIELD_TYPE_MEANING_DATA_STREAM_ID`,
   it sets the current data stream ID:

       case CTF_FIELD_TYPE_MEANING_DATA_STREAM_ID:
           notit->cur_data_stream_id = value;
           break;

2. If the integer field type has a mapped clock class, it updates the
   stream's default clock value using the CTF clock update mechanism.

3. If the integer field type has a storing index, it stores the decoded
   integer value to a specific location within the stored values:

       g_array_index(notit->stored_values, uint64_t,
           (uint64_t) int_ft->storing_index) = value;

4. If the integer field type has an equivalent library IR field type, it
   sets the appropriate `bt_field` object with the decoded value.

Other plugin updates
--------------------
`src.text.dmesg`, `sink.text.pretty`, and `flt.utils.muxer` are adapted
to the new API.

Test updates
------------
* `tests/lib/test_bt_ctf_field_type_validation.c`: removed because it is
  now a precondition that the metadata be valid now. What's left to
  validate is still done in developer mode.

* `tests/plugins/test-utils-muxer.c`: removed because it will be easier
  to test with the Python bindings once they are updated instead of
  wasting time adapting this one.

* Other tests are adapted to the new API.

Performance update
------------------
This patch makes the performance of Babeltrace 2 go from 40 % to 82 %
the Babeltrace 1's performance with:

    babeltrace /path/to/trace -o dummy

with a 1.4 GiB LTTng kernel trace (four streams) and configured as such:

    BABELTRACE_DEV_MODE=0 BABELTRACE_DEBUG_MODE=0 \
    BABELTRACE_MINIMAL_LOG_LEVEL=INFO CFLAGS='-O3 -DNDEBUG' ./configure

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoassert-pre-internal.h: add BT_ASSERT_PRE_VALID_INDEX()
Philippe Proulx [Thu, 23 Aug 2018 15:42:52 +0000 (11:42 -0400)] 
assert-pre-internal.h: add BT_ASSERT_PRE_VALID_INDEX()

This new precondition assertion macro asserts that a given index is less
than a given length.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: bt_g_hash_table_contains(): handle `NULL`/0 values
Philippe Proulx [Thu, 23 Aug 2018 15:35:43 +0000 (11:35 -0400)] 
Fix: bt_g_hash_table_contains(): handle `NULL`/0 values

Issue
=====
g_hash_table_lookup() returns `NULL` if the key is not found, but also
when the value is actually `NULL` (or 0). Therefore
bt_g_hash_table_contains() returns false when there's actually a
`NULL`/0 value for the given key.

Solution
========
Use g_hash_table_lookup_extended() which truly returns whether or not
the given key was found, and discard the returned value.

Known drawbacks
===============
None.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoassert-pre-internal.h: move include at correct line
Philippe Proulx [Thu, 23 Aug 2018 15:35:06 +0000 (11:35 -0400)] 
assert-pre-internal.h: move include at correct line

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: merge common CTF IR part with the remaining implementation
Philippe Proulx [Thu, 16 Aug 2018 19:53:25 +0000 (15:53 -0400)] 
lib: merge common CTF IR part with the remaining implementation

This patch merges the common part of the CTF IR implementation with the
rest of it, making it one. This will make it easier to modify this
implementation since it's not split in two.

Support for common CTF IR conversion specifiers is removed in
`lib-logging.c` (see updated `lib-logging-internal.h` documentation).

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: fully detach CTF IR and CTF writer implementations
Philippe Proulx [Wed, 15 Aug 2018 22:42:03 +0000 (18:42 -0400)] 
lib: fully detach CTF IR and CTF writer implementations

This patch makes the CTF IR and CTF writer implementations completely
independent. To achieve this, files were partly or fully copied from CTF
IR to CTF writer directories, and everything part of the copied "common"
part was prefixed with `bt_ctf_` or `BT_CTF_` instead of `bt_` or `BT_`.

For the moment, both CTF IR and CTF writer implementations have their
own common part, each of which is only common to its own implementation
now.

Having independent implementations makes it easier to modify one,
sometimes drastically, without caring about not changing the common part
too much.

The BT_LIB_LOG*() macros do not accept the `w` category anymore, making
the CTF writer objects not supported by them. The `_` category is still
accepted for the common part of the CTF IR objects.

The CTF writer clock class API is hidden instead of being public as of
this patch because this was faster to implement and it does not break
backward compatibility with Babeltrace 1.

For some reason, `plugins/text/pretty/print.c` used some `BT_CTF_*`
enumeration members, so this is fixed too.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agosink.text.pretty: print discarded events/packets warning
Philippe Proulx [Wed, 8 Aug 2018 00:08:54 +0000 (20:08 -0400)] 
sink.text.pretty: print discarded events/packets warning

Add back the discarded element message when a packet beginning's packet
object has non-zero discarded event or packet counts.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: bt_packet_create(): accept previous packet to set properties
Philippe Proulx [Wed, 8 Aug 2018 00:00:52 +0000 (20:00 -0400)] 
lib: bt_packet_create(): accept previous packet to set properties

This patch changes the signature of the bt_packet_create() function
from:

    struct bt_packet *bt_packet_create(struct bt_stream *stream);

to:

    struct bt_packet *bt_packet_create(struct bt_stream *stream,
        enum bt_packet_previous_packet_availability prev_packet_avail,
        struct bt_packet *prev_packet);

bt_packet_create() now accepts the previous packet in the same stream
and its availability to automatically set some properties on the created
packet which depend on the properties of the previous packets. Those
properties are:

* The number of discarded events, by the original tracer, between the
  previous packet's end time and the current packet's end time.
* The number of discarded packets, by the original tracer, between the
  previous packet's end time and the current packet's end time.

"Automatically" here means from the packet's context subfields.

The availability parameter's purpose is to provide a reason for a
missing previous packet:

* Not available (will be used after seeking when this is implemented).
* None (first packet of its data stream).

When the previous packet is passed, you must pass
`BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE`.

bt_packet_create() does not keep a reference to the passed previous
packet object: this would create a potentially huge reference chain.
Instead, the function keeps snapshots the needed previous packet's
properties.

bt_packet_create() does not automatically set the created packet's
properties right away: this is the purpose of the internal
bt_packet_set_properties() function. This is because you borrow and set
the packet context subfields after you create the packet, so the
automatic setting must happen at the same location the packet would be
frozen in developer mode. Thus bt_notification_event_create(),
bt_notification_packet_begin_create(), and
bt_notification_packet_end_create() call bt_packet_set_properties().

bt_packet_set_properties() sets, from the context subfields, when
available:

* Discarded event _counter_ (free running counter, not the difference)
  from `events_discarded`.
* Sequence number from `packet_seq_num`.
* Default beginning clock value from `timestamp_begin`.
* Default end clock value from `timestamp_end`.

Because bt_notification_event_create() calls bt_packet_set_properties(),
and we don't want to do all this work every time we call
bt_notification_event_create(), there's a "validation" flag for the
property cache. So we can call bt_packet_set_properties() and
eventually, when we're sure that the context field won't change until
the packet is recycled (reset), we call
bt_packet_invalidate_properties().

Each packet property can be available or not: each property getter
returns its availability and the function sets a user variable to the
property's value. The getters are:

    enum bt_packet_property_availability
    bt_packet_borrow_default_beginning_clock_value(struct bt_packet *packet,
        struct bt_clock_value **clock_value);

    enum bt_packet_property_availability
    bt_packet_borrow_default_end_clock_value(struct bt_packet *packet,
        struct bt_clock_value **clock_value);

    enum bt_packet_property_availability
    bt_packet_borrow_previous_packet_default_end_clock_value(
        struct bt_packet *packet, struct bt_clock_value **clock_value);

    enum bt_packet_property_availability
    bt_packet_get_discarded_event_counter(
        struct bt_packet *packet, uint64_t *counter);

    enum bt_packet_property_availability
    bt_packet_get_sequence_number(
        struct bt_packet *packet, uint64_t *sequence_number);

    enum bt_packet_property_availability
    bt_packet_get_discarded_event_count(
        struct bt_packet *packet, uint64_t *count);

    enum bt_packet_property_availability
    bt_packet_get_discarded_packet_count(
        struct bt_packet *packet, uint64_t *count);

Source plugins are updated to keep the previous packet's reference when
needed and call bt_packet_create() correctly.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years ago_bt_packet_set_is_frozen(): fix logging statements
Philippe Proulx [Tue, 7 Aug 2018 23:37:01 +0000 (19:37 -0400)] 
_bt_packet_set_is_frozen(): fix logging statements

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: lib: do not check the frozen state in bt_X_set_is_frozen()
Philippe Proulx [Tue, 7 Aug 2018 23:32:16 +0000 (19:32 -0400)] 
Fix: lib: do not check the frozen state in bt_X_set_is_frozen()

Some freezing functions were called bt_X_freeze() and were transformed
into freezing/thawing functions bt_X_set_is_frozen(), accepting the
frozen state as a parameter. The optimization checks to avoid refreezing
when the object is already frozen were left, but we can thaw now, so we
must not check this.

It could be optimized again, but those specific freezing functions are
only enabled in developer mode, so it's not a complete catastrophe.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: make bt_field_is_*() and bt_field_type_is_*() static inline
Philippe Proulx [Wed, 1 Aug 2018 21:11:22 +0000 (17:11 -0400)] 
lib: make bt_field_is_*() and bt_field_type_is_*() static inline

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: use priv connection priv notif iterator to create notif, not graph
Philippe Proulx [Wed, 1 Aug 2018 20:43:10 +0000 (16:43 -0400)] 
lib: use priv connection priv notif iterator to create notif, not graph

The only valid location to create a notification object is within the
"next" method of a user private connection notification iterator. To
enforce this, make the notification creation functions accept a
`bt_private_connection_private_notification_iterator` object instead of
a `bt_graph` object to find the appropriate notification object pool
(still located within the graph object).

As of this patch, you cannot create a notification object outside the
implementation of a user private connection notification iterator.

This should also help the adaptation of the Python bindings to create a
notification object using a method from `self` when implementing a user
notification iterator:

    class MyIter(bt2._UserNotificationIterator):
        # ...

        def __next__(self):
            # ...
            event_notif = self._create_event_notification(...)
            # ...

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: remove clock class priority map, use default clock value
Philippe Proulx [Tue, 31 Jul 2018 21:31:50 +0000 (17:31 -0400)] 
lib: remove clock class priority map, use default clock value

This patch removes the concept (and associated files and functions) of
clock class priority maps. We're setting plain clock values to objects
which have a time (event, packet, some notifications) instead and using
a _default_ clock value. This is an easier API, and after all, all we
need is a clock value to sort notifications, not custom priorities
assigned to clock classes.

The purpose of the default clock value is to mux (sort) or trim
notifications, and also to seek eventually.

For an event object, the API is now:

    int bt_event_set_clock_value(struct bt_event *event,
        struct bt_clock_class *clock_class, uint64_t raw_value,
        bt_bool is_default);

    struct bt_clock_value *bt_event_borrow_default_clock_value(
        struct bt_event *event);

As of this version, when calling bt_event_set_clock_value() (or any
clock value setter), you must pass `BT_TRUE` as the `is_default`
parameter. That is, individual objects support at most a single, default
clock value. This is simpler now and can still change in the future.

Like before this patch, clock value objects are unique, that is, you
cannot get or put a clock value reference, but you can borrow it. You
cannot set a clock value object's raw value directly
(bt_clock_value_set_value()) anymore because this is done through
specific clock value setter functions.

Behind the scenes, all the objects with a clock value setter and
borrower function use an internal clock value set object. This is an
array of clock values with a pointer to the default one. Its API is:

    static inline
    int bt_clock_value_set_initialize(struct bt_clock_value_set *cv_set);

    static inline
    void bt_clock_value_set_reset(struct bt_clock_value_set *cv_set);

    static inline
    void bt_clock_value_set_finalize(struct bt_clock_value_set *cv_set);

    static inline
    int bt_clock_value_set_set_clock_value(
        struct bt_clock_value_set *cv_set,
        struct bt_clock_class *cc, uint64_t raw_value,
        bt_bool is_default);

You can reset a clock value set if it's located within a resettable
(poolable) object (e.g., event, packet).

The `bt_packet` object now has two clock value sets: its beginning and
end times. Although there is no developer mode check as of this patch,
the beginning and end times must match the `timestamp_begin` and
`timestamp_end` field values if they exist.

The stream beginning and end notification APIs have clock value setter
and borrower functions so that you can (optionally, if possible)
indicate the beginning and end times of a stream.

An `flt.utils.muxer` component now uses the default clock value of event
and inactivity notifications to sort notifications.

Discarded element (event, packet) notification types are removed because
they rely on the clock class priority map concept too and we're about to
remove them anyway and replace them with a new concept. Their usage is
temporarily removed from specific plugin component classes
(`src.text.pretty`, `sink.utils.counter`).

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: make the "port connected" method return a status
Philippe Proulx [Tue, 26 Jun 2018 17:48:36 +0000 (13:48 -0400)] 
lib: make the "port connected" method return a status

Even if both components accept a port connection with their "accept port
connection" methods, an error-triggering task can still be performed
during the "port connected" method's execution, in which case the whole
component could be considered unusable, or at least this connection
cannot exist. The typical case is that the "port connected" method tries
to create a private connection notification iterator using the new
connection and this can fail for many reasons.

Without the "port connected" method returning a status code, the
mechanism to signal an error is to set an error flag on the component's
private data and check this flag at every "consume" or "next" method
call. This is inefficient when the "port connected" method can simply
return an error status.

The connection order in bt_graph_connect_ports() is to call the
upstream component's "port connected" method and then the downstream
component's.

* If the upstream component's method does not return
  `BT_COMPONENT_STATUS_OK`, then the connection is ended and
  bt_graph_connect_ports() returns an error. The graph creator's "ports
  connected" listener is not called.

* If the downstream component's method does not return
  `BT_COMPONENT_STATUS_OK`, then the connection is ended, notifying the
  upstream component that its previously connected port is now
  disconnected, and bt_graph_connect_ports() returns an error. The graph
  creator's "ports connected" listener is not called.

This patch adds new tests to `test_graph_topo.c` to make sure the
appropriate methods/listeners are called or not, and in which order,
when either the upstream or downstream component's "port connected"
method returns an error status.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: notification iterator: transfer a batch of notifications
Philippe Proulx [Fri, 22 Jun 2018 20:54:27 +0000 (16:54 -0400)] 
lib: notification iterator: transfer a batch of notifications

This patch makes each notification iterator's "next" operation return a
batch of notifications intead of a single one. This has a positive
effect on performance as we're decreasing the number of executed
instructions because there are fewer function calls per notification.

The batch size is arbitrarily set to 15 here as a value between 10 and
50 experimentally showed to be beneficial, and there's usually more than
one active stream on a typical graph configuration. As the batch size
increases, the performance eventually degrades, as I suspect that
(pooled) notification objects are constantly getting into and out of CPU
cache. The goal of hiding the batch size in the library's implementation
is to eventually determine a value at run time depending on the
situation, and even change it when needed between consuming sinks.

Each notification iterator contains a fixed-sized array of notification
pointers. This array is allocated when the iterator is created and freed
when it is destroyed. For convenience, I'm adding this typedef:

    typedef struct bt_notification **bt_notification_array;

Consumer side
=============
The consuming side API is now:

    enum bt_notification_iterator_status
    bt_private_connection_notification_iterator_next(
        struct bt_notification_iterator *iterator,
        bt_notification_array *notifs, uint64_t *count);

    enum bt_notification_iterator_status
    bt_output_port_notification_iterator_next(
        struct bt_notification_iterator *iterator,
        bt_notification_array *notifs, uint64_t *count);

In English: the function sets `notifs` to the address of a notification
array containing `*count` notifications when the returned status is
`BT_NOTIFICATION_ITERATOR_STATUS_OK`. In this case, the caller is
responsible for putting each notification in the array (the array's
content is owned by the caller, but not the array itself), as the
functions above do not put what's already in the iterator's array before
filling it. If the status is not `BT_NOTIFICATION_ITERATOR_STATUS_OK`,
then the function does not set `*notifs` and `*count`.

Because the `utils.flt.muxer` component class kept each upstream
notification iterator's current notification, it now keeps a queue of
notifications, and the upstream iterator is now considered invalid if
its notification queue is empty.

If less than `*count` notifications are required, the caller can either:

* Discard (put) unneeded notifications: they are lost forever.

* Keep a queue (or other data structure) of notifications by keeping the
  references. The caller must NOT keep the array itself in this case,
  but each contained notification object, copying the pointer values to
  its territory.

Producer side
=============
The "next" method signature is now:

    enum bt_notification_iterator_status next_method(
        struct bt_private_connection_private_notification_iterator *notif_iter,
        bt_notification_array notifs, uint64_t capacity,
        uint64_t *count);

The callback must either:

* Fill `notifs` with up to `capacity` notifications (notification's
  ownership is transfered to the array), set `*count` to how many
  notifications were transfered (at least one), and return
  `BT_NOTIFICATION_ITERATOR_STATUS_OK`.

  `capacity` is always greater than zero.

* Return something else than `BT_NOTIFICATION_ITERATOR_STATUS_OK`,
  not touching `notifs` and `count`.

IMPORTANT: The callback must NOT transfer one or more notifications to
`notifs` and return something else than
`BT_NOTIFICATION_ITERATOR_STATUS_OK`.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: remove internal stream destroy listener API
Philippe Proulx [Wed, 13 Jun 2018 15:39:07 +0000 (11:39 -0400)] 
lib: remove internal stream destroy listener API

This API is not used anymore.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: graph: remove useless checks, make functions inline on fast path
Philippe Proulx [Tue, 12 Jun 2018 21:47:12 +0000 (17:47 -0400)] 
lib: graph: remove useless checks, make functions inline on fast path

This patch:

* Removes a few useless checks on the fast path for everything related
  to the graph object.

* Makes the "can consume" flag only written and read in developer mode.

* Makes fast path functions `static inline` within `graph.c`.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: remove useless checks, make functions inline on fast path
Philippe Proulx [Tue, 12 Jun 2018 20:33:14 +0000 (16:33 -0400)] 
lib: remove useless checks, make functions inline on fast path

This patch:

* Removes a few useless checks on the fast path with the help of
  bt_object_put_no_null_check(), bt_object_get_no_null_check(),
  and bt_object_get_no_null_check_no_parent_check() when it's possible.

* Makes setting any frozen flag on the fast path only happen in
  developer mode.

* Makes fast path functions `static inline` (specific creating and
  recycling functions).

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: If40b5f8dea9a085e8e30e25a9542767f3eb9815e

4 years agolib: update and simplify the `bt_object` API
Philippe Proulx [Tue, 12 Jun 2018 19:47:05 +0000 (15:47 -0400)] 
lib: update and simplify the `bt_object` API

This patch merges `ref-internal.h` into `object-internal.h` so as to
simplify the `bt_object` API and ease the future addition of specialized
inline functions (e.g., no specific checks).

Notable changes:

* There's no specific reference count structure; the reference count is
  directly within `struct bt_object`.

* Most functions of `object-internal.h` accept and return the
  `struct bt_object *` type instead of `void *`.

* The `struct bt_object` structure contains two release function:

  `release_func`:
      Called when the reference count falls to zero by the new
     bt_object_put_no_null_check() function.

  `spec_release_func`:
      Called by bt_object_try_spec_release() (formerly
     bt_object_release()).

* You can initialize a unique object (no reference count) with
  bt_object_init_unique(), a shared object that will _never_ have any
  parent with bt_object_init_shared(), and a shared object which could
  have a parent in the future with bt_object_init_shared_with_parent().

  bt_object_init_shared_with_parent() calls bt_object_init_shared() with
  the special `bt_object_with_parent_release_func` callback as the
  object's release function. This function used to be called
  generic_release(): it puts the parent if there is one, or releases the
  object itself (with bt_object_try_spec_release()) when there's none.

  The whole job of bt_object_with_parent_release_func() is unnecessary
  for shared objects which will never have a parent: in this case, we
  can call a single release function as soon as the object's reference
  count falls to zero. This can render the whole system faster as
  notification objects are shared, but without a parent, for example.
  Packet objects are another example, albeit less significant.

* There are two new, internal versions of bt_get() and bt_put() which do
  not check if the parameter is null: bt_object_get_no_null_check() and
  bt_object_put_no_null_check(). We can use those functions internally
  on the fast path where it is known that a given Babeltrace object
  pointer is never null. This is what the public bt_get() and bt_put()
  function use internally now, after checking some preconditions.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agotest_ctf_writer.c: put statements outside BT_ASSERT()
Philippe Proulx [Mon, 11 Jun 2018 20:07:44 +0000 (16:07 -0400)] 
test_ctf_writer.c: put statements outside BT_ASSERT()

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: freeze field type unconditionally
Philippe Proulx [Mon, 11 Jun 2018 20:00:21 +0000 (16:00 -0400)] 
Fix: freeze field type unconditionally

Issue
=====
Field types should always be frozen (in both developer or production
modes) because they are metadata objects. Currently, they are only
frozen in developer mode.

Solution
========
Make the bt_field_type_common_freeze() and bt_field_type_freeze()
functions always called, not through a macro which is only enabled in
developer mode.

Known drawbacks
===============
Very small performance impact because we're trying to freeze a field
type every time bt_field_create() is called, but bt_field_create() is
not called often anyway due to field object pooling. The impact could
become noticeable eventually if we limit the sizes of object pools.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoUse "growing" `GArray` to store string field's payload
Philippe Proulx [Thu, 7 Jun 2018 00:45:08 +0000 (20:45 -0400)] 
Use "growing" `GArray` to store string field's payload

Minimize the number of required operations for functions such as
bt_field_string_set_value(), bt_field_string_append(),
bt_field_string_append_len(), and bt_field_string_clear().

This patch makes the string field object use the same principle that the
sequence field uses, but with a `GArray` of characters instead of a
`GPtrArray` of fields.

Preliminary benchmarks show that this approach is faster than using a
`GString` object.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: simplify the public notification iterator interfaces
Philippe Proulx [Wed, 6 Jun 2018 20:52:03 +0000 (16:52 -0400)] 
lib: simplify the public notification iterator interfaces

Simplify the public notification iterator interfaces so as to remove:

* bt_notification_iterator_borrow_notification()
* bt_notification_iterator_get_notification()
* bt_notification_iterator_next()

in favor of:

    enum bt_notification_iterator_status
    bt_output_port_notification_iterator_next(struct
        bt_notification_iterator *iterator,
        struct bt_notification **notification);

    enum bt_notification_iterator_status
    bt_private_connection_notification_iterator_next(
        struct bt_notification_iterator *iterator,
        struct bt_notification **notification);

Those two new functions:

* Move the notification received from the user method to the
  `notification` output variable directly without modifying the
  reference count.

* Do not need to check the notification iterator type of notification to
  perform the appropriate specific operation and have precondition
  checks to ensure `iterator` has the right type.

This API is also in line with some popular iterator interfaces where the
"next" function returns the iteration status and the element at the same
time, for example:

* g_hash_table_iter_next()
* Python's next()

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: bt_graph_consume(): return status
Philippe Proulx [Tue, 5 Jun 2018 21:56:33 +0000 (17:56 -0400)] 
Fix: bt_graph_consume(): return status

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: CTF writer: use appropriate enumerators
Philippe Proulx [Tue, 5 Jun 2018 21:56:05 +0000 (17:56 -0400)] 
Fix: CTF writer: use appropriate enumerators

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: bt_field*_reset_recursive() returns nothing
Philippe Proulx [Tue, 5 Jun 2018 21:55:38 +0000 (17:55 -0400)] 
Fix: bt_field*_reset_recursive() returns nothing

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agotests: use BT_ASSERT() instead of assert()
Philippe Proulx [Tue, 5 Jun 2018 21:53:32 +0000 (17:53 -0400)] 
tests: use BT_ASSERT() instead of assert()

This is more desirable because BT_ASSERT() "uses" the condition without
evaluating it to avoid unused variable compiler warnings.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: bt_event_common_initialize(): use appropriate callback types
Philippe Proulx [Tue, 5 Jun 2018 21:52:19 +0000 (17:52 -0400)] 
Fix: bt_event_common_initialize(): use appropriate callback types

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoBT_ASSERT_PRE(): when disabled, use the expression anyway
Philippe Proulx [Tue, 5 Jun 2018 21:50:45 +0000 (17:50 -0400)] 
BT_ASSERT_PRE(): when disabled, use the expression anyway

Apply to the BT_ASSERT_PRE() macro (and its derivatives) the same trick
used for BT_ASSERT() to use the condition without evaluating it when the
macro is disabled. This avoids unused variable compiler warnings in a
production build.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: set BT object's shared flag in all modes
Philippe Proulx [Tue, 5 Jun 2018 21:43:28 +0000 (17:43 -0400)] 
Fix: set BT object's shared flag in all modes

Issue
=====
The bt_object_set_is_shared() function is only effective in a developer
mode build. Since the shared flag is 0 when allocated, and
bt_object_init() calls bt_object_set_is_shared() to make the object
shared initially, all objects are non-shared in non-developer mode.

This was the initial goal, because the only purpose of this shared
flag was to check if the developer is calling bt_get() or bt_put()
with a non-shared object. This check is only performed in developer
mode anyway. However, the object pool system resets the object's
reference count to 1 only when it is shared.

Solution
========
Make bt_object_set_is_shared() always effective, and make the object
pool unconditionally reset the reference count to 1 when recycling. This
avoids a check and the reference count is always 1 for a unique object
anyway (the test was superfluous).

I leave bt_object_set_is_shared() to be always enabled for future use
cases: it does not cost a lot to have it executed in non-developer mode
as its execution cost is amortized anyway for recycled objects.

Known drawbacks
===============
Unnoticeable performance impact.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoctf: notif-iter: avoid reallocation in stack
Philippe Proulx [Tue, 5 Jun 2018 20:01:42 +0000 (16:01 -0400)] 
ctf: notif-iter: avoid reallocation in stack

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoctf: btr: avoid reallocation in stack
Philippe Proulx [Tue, 5 Jun 2018 19:55:51 +0000 (15:55 -0400)] 
ctf: btr: avoid reallocation in stack

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: use object pool for event and packet notifications
Philippe Proulx [Mon, 4 Jun 2018 21:00:10 +0000 (17:00 -0400)] 
lib: use object pool for event and packet notifications

This patch adds object pooling for event, packet beginning, and packet
end notifications.

The object pools are located in graph objects: there is one for each
notification type. All the notification creation functions (in case we
want to recycle other types of notification objects in the future) take
a graph object so that a notification recycling function can find the
appropriate object pool. I'm adding the convenient
bt_private_connection_private_notification_iterator_borrow_graph()
function for a notification iterator user function to borrow its graph
easily.

If the notification has a reference to its "creating" graph, there's a
possible reference cycle, for example:

* Graph -> connection -> notification iterator -> notification -> graph
* Graph -> component -> notification -> graph

To avoid this, the notification's graph link is weak, and the
notification creation function adds the notification to the graph's
array of notifications (also weak). While the graph is alive,
notification recycling functions are free to use the appropriate graph's
pool. When the graph is destroyed, all the notifications which have a
link to it are notified so that they "unlink" the graph. In this case,
notification recycling functions destroy the notification instead of
recycling it.

Some `bt_X_from_private()` functions are renamed to
`bt_X_borrow_from_private()` and do not return a new reference to make
it clearer.

Everything related to the notification heap API is removed because it is
not used anywhere and not needed since the `flt.utils.muxer` component
class does this.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: add internal object pool API and use it; adapt plugins/tests
Philippe Proulx [Fri, 18 May 2018 17:32:37 +0000 (13:32 -0400)] 
lib: add internal object pool API and use it; adapt plugins/tests

Pooling
=======
This patch adds the `bt_object_pool` (object pool) internal API.

From <https://en.wikipedia.org/wiki/Object_pool_pattern>:

> The object pool pattern is a software creational design pattern that
> uses a set of initialized objects kept ready to use – a "pool" –
> rather than allocating and destroying them on demand. A client of the
> pool will request an object from the pool and perform operations on
> the returned object. When the client has finished, it returns the
> object to the pool rather than destroying it; this can be done
> manually or automatically.
>
> Object pools are primarily used for performance: in some
> circumstances, object pools significantly improve performance.

When initializing an object pool with bt_object_pool_initialize(), you
provide a function which can allocate a brand new object from memory, as
well as a function which can destroy and deallocate an existing object.
As of this patch, the destroy function is only used when you call
bt_object_pool_finalize() to finalize an object pool: all the objects
in the pool are destroyed.

The object pool API is:

bt_object_pool_create_object():
    Creates an object from an object pool. If the pool is empty, this
    function calls the "new" user function to allocate a new object
    before returning it. Otherwise this function returns a recycled
    object, removing it from the pool. The returned object is owned by
    the caller.

bt_object_pool_recycle_object():
    Recycles an object, that is, puts it back into the pool. The pool
    becomes the sole owner of the object to recycle.

There is not upper limit for the number of objects in the pool as of
this patch: the pool can grow infinitely, it never shrinks.

Within the library, the function naming convention for a recyclable, or
"poolable" object `bt_X` is as such:

bt_X_new():
    Allocates an object from memory. The object created by this function
    might be incomplete: the object is not always ready to use after
    calling this. This is the function which is passed as the "new"
    function when calling bt_object_pool_initialize().

bt_X_create():
    Creates an object from a pool and makes it useable, setting again
    the references that were reset during bt_X_recycle(), for example.
    Which pool to use is explicitly known by the function. It is part of
    an object received as a parameter. This could call bt_X_new()
    indirectly if the pool is empty.

bt_X_recycle():
    Resets the received object and recycles it within the appropriate
    pool. This function puts any reference which would keep the shared
    object alive even if the owner is now partially dead, part of a
    pool.

bt_X_destroy():
    Finalizes and deallocates the received object.

The following objects are recyclable as of this patch:

* `bt_event`; pool belongs to its event class, recycling happens when
  the event notification is destroyed.

* `bt_clock_value`; pool belongs to its clock class.

* `bt_packet`; pool belongs to its stream, recycling happens when its
  reference count reaches 0.

* `bt_packet_header_field`; pool belongs to a trace (more about this
  new object below).

* `bt_packet_context_field`; pool belongs to a stream class (more about
  this new object below).

* `bt_event_header_field`; pool belongs to a stream class (more about
  this new object below).

Unique objects
==============
Having a pool of event objects means that an event object must make sure
that everything under it which could be modified per instance is not
shared. In this case, the four `bt_field` objects (header, stream event
context, context, and payload) must not be shared.

Therefore this patch introduces unique objects (non-shared). By default,
bt_object_init() initializes a shared object. A function which creates a
unique object can mark it as unique thanks to bt_object_set_is_shared().
This is only used in developer mode to verify that the developer does
not call bt_get() or bt_put() on a unique object.

As a library user, you cannot create a unique object. It is created (and
destroyed) internally: you can only borrow the already-created object
from another object.

As of this patch, bt_event_create() and bt_field_create() are internal
functions. When you create an event notification with
bt_notification_event_create(), you pass the event class and packet to
use for the internal creation of the event object. Then you can borrow
the created (unique, non-shared) event with
bt_notification_event_borrow_event(), and its fields with
bt_event_borrow_header(), bt_event_borrow_stream_event_context(),
bt_event_borrow_context(), and bt_event_borrow_payload().

Then, recursively, you can borrow fields from compound fields
(structure, array, sequence, variant) and set their values.

On creation, the structure, variant, and array fields recursively create
all their subfields. This can't be done with the sequence field because
we need to know its length: subfields are created lazily when the
sequence's length increases; they are never destroyed until the sequence
field itself is destroyed (the sequence field's length is not
necessarily its field pointer array's length). A variant field has a
current field member which points to one of its subfields depending on
the current selection.

A packet object is still shared, as it needs to be shared between
multiple event objects. Its header and context fields, however, are
unique. Like the event object, the packet object creates its own unique
fields and you can borrow them with bt_packet_borrow_header() and
bt_packet_borrow_context().

Clock values are also unique (bt_clock_value_create() is now internal).
They are created when an event or an inactivity notification is created.
Once you borrow a clock value object using a clock class, you can set
its value with the new bt_clock_value_set_value() function. Clock value
objects now have the concepts of being set and frozen (like field
objects) because they are not immutable anymore.

CTF IR field API changes
========================
* bt_field_integer_*() functions now apply to both integer and
  enumeration fields, as an enumeration field is considered to be
  an integer field.

  For this to be efficient (no branches), an enumeration field is
  nothing more than an integer field and the functions just cast the
  given `struct bt_field *` object to a common integer field:

      struct bt_field_enumeration {
          struct bt_field_common_integer common;
      };

* bt_field_string_clear(): new function to clear an existing string
  field object.

  Because field objects are reused and they are not reset when an event
  is recycled (for performance), you must call bt_field_string_clear()
  before you initially call bt_field_string_append() or
  bt_field_string_append_len(). You don't need to call
  bt_field_string_clear() before initially calling
  bt_field_string_set_value().

* bt_field_sequence_get_length() returns an integer (`int64_t`), not a
  field object. It is useless for the user to have the actual length
  integer field.

* bt_field_sequence_set_length() accepts an integer (`uint64_t`), not a
  field, for the same reason as the previous point.

* bt_field_variant_get_field() is removed. This function had a dual
  role where it would select the current field using the value of
  a tag field, and then return the current field. It is a vestige of
  the CTF writer API.

  Now, you set the tag value (plain integer) with
  bt_field_variant_set_tag_signed() or
  bt_field_variant_set_tag_unsigned(), and then you can borrow the
  variant field's current (selected) field with
  bt_field_variant_borrow_current_field().

  You can still get the variant field's current tag value with
  bt_field_variant_get_tag_signed() and
  bt_field_variant_get_tag_unsigned(). Combined with
  bt_field_type_enumeration_signed_find_mappings_by_value() and
  bt_field_type_enumeration_unsigned_find_mappings_by_value(), you can
  get the variant field's tag's mappings, so really there's no value
  keeping the actual tag enumeration field.

The CTF writer field API is unchanged and still backward compatible.

Free packet header, packet context, and event header fields
===========================================================
It is possible to create a "free" packet header field (wrapper). This is
useful to fill a packet header field without creating the packet that
would create it, because in order to create this packet, you need a
stream, which is created from a stream class, and the stream class's ID
is found in the packet header field data.

The API is:

bt_trace_create_packet_header_field():
    Creates a free packet header field
    (`struct bt_packet_header_field *`).

bt_packet_header_field_borrow_field():
    Borrows the underlying field object to fill it.

bt_packet_move_header():
    Moves the free packet header field object to a given packet,
    replacing its current packet header field. After calling this, and
    on success, the object is considered to belong to the packet object:
    you can discard it.

    What happens here is that bt_packet_move_header() first recycles its
    current packet header field wrapper object to the trace's packet
    header field pool, and then replaces it with the provided object.

bt_packet_header_field_release():
    Releases the given packet header field. This function exists for
    error handling, to discard a packet header field without leaking
    when you called bt_trace_create_packet_header_field(), but you
    cannot call bt_packet_move_header().

Analogous functions exist for a packet context field:

* bt_stream_class_create_packet_context_field()
* bt_packet_context_field_borrow_field()
* bt_packet_move_context()
* bt_packet_context_field_release()

Having free packet header and packet context fields is necessary for a
`src.ctf.fs` component to work because it needs to know some field
values of both packet header and context fields before even creating a
stream object (to have a single stream for multiple data stream files,
for example), thus also before creating a packet.

Analogous functions exist for an event header field:

* bt_stream_class_create_event_header_field()
* bt_event_header_field_borrow_field()
* bt_event_move_header()
* bt_event_header_field_release()

Those three new (unique, non-shared) objects use the internal
`bt_field_wrapper` API.

Other changes
=============
* bt_clock_class_cycles_to_ns(): new public function to transform cycles
  to nanoseconds from Epoch using a specific clock class. The
  `src.ctf.fs` component used to create a clock value just to have this
  through bt_clock_value_get_value_ns_from_epoch(), and then destroy it.
  With this patch, you cannot create a free clock value anymore,
  therefore this new function satisfies the existing use case.

* BT_LIB_LOG*() now accepts the `%!o` specifier to log the details of
  an object pool.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoctf plugin: notif iter: use "borrow" functions for metadata where possible
Philippe Proulx [Tue, 17 Apr 2018 05:38:07 +0000 (01:38 -0400)] 
ctf plugin: notif iter: use "borrow" functions for metadata where possible

Use "borrow" API functions when possible to avoid useless reference
count changes for metadata objects.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoctf plugin: BTR: use "borrow" functions where possible
Philippe Proulx [Tue, 17 Apr 2018 02:58:11 +0000 (22:58 -0400)] 
ctf plugin: BTR: use "borrow" functions where possible

Use "borrow" API functions when possible to avoid useless reference
count changes.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agosrc.ctf.fs: use "borrow" functions where possible
Philippe Proulx [Tue, 17 Apr 2018 00:25:31 +0000 (20:25 -0400)] 
src.ctf.fs: use "borrow" functions where possible

Use "borrow" API functions when possible to avoid useless reference
count changes.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agosink.utils.counter: use "borrow" functions where possible
Philippe Proulx [Mon, 16 Apr 2018 23:18:06 +0000 (19:18 -0400)] 
sink.utils.counter: use "borrow" functions where possible

Use "borrow" API functions when possible to avoid useless reference
count changes.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agosink.text.pretty: use "borrow" functions where possible
Philippe Proulx [Mon, 16 Apr 2018 23:15:33 +0000 (19:15 -0400)] 
sink.text.pretty: use "borrow" functions where possible

Use "borrow" API functions when possible to avoid useless reference
count changes.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agocli: add short option `-l` for `--log-level`
Philippe Proulx [Mon, 16 Apr 2018 22:56:26 +0000 (18:56 -0400)] 
cli: add short option `-l` for `--log-level`

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: bt_stream_common_finalize(): check `stream->destroy_listeners`
Philippe Proulx [Mon, 16 Apr 2018 22:47:39 +0000 (18:47 -0400)] 
Fix: bt_stream_common_finalize(): check `stream->destroy_listeners`

Issue
=====
In bt_stream_common_finalize(), `stream->destroy_listeners` is not
checked before calling iterating the array to call the destroy
listeners. This can happen if the stream is partially initialized and
then destroyed when there's an error in bt_stream_common_initialize().

Solution
========
Check `stream->destroy_listeners` before iterating the destroy listener
array.

Known drawbacks
===============
None.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoflt.utils.muxer: use "borrow" functions where possible
Philippe Proulx [Mon, 16 Apr 2018 22:45:40 +0000 (18:45 -0400)] 
flt.utils.muxer: use "borrow" functions where possible

Use "borrow" API functions when possible to avoid useless reference
count changes.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: add "borrow" functions where "get" functions exist
Philippe Proulx [Fri, 13 Apr 2018 06:54:35 +0000 (02:54 -0400)] 
lib: add "borrow" functions where "get" functions exist

The new bt_*_borrow_*() functions return a "borrowed reference" instead
of a new reference like the bt_*_get_*() functions return.

Use the "borrow" functions as much as possible internally.

This can improve performance, especially for objects which are obtained
often, and for a short time, in the fast path (fields, events, packets,
notifications, some metadata objects), as it avoids one bt_get() and one
bt_put() call for each function call.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoinclude/babeltrace/graph: fix some include guards
Philippe Proulx [Fri, 13 Apr 2018 20:27:33 +0000 (16:27 -0400)] 
include/babeltrace/graph: fix some include guards

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agobt2: by-pass distutils changed file check
Francis Deslauriers [Wed, 11 Apr 2018 21:20:40 +0000 (17:20 -0400)] 
bt2: by-pass distutils changed file check

Changes made to a SWIG interface file (.i) that is included in
native_bt.i would not trigger rebuilding of the extension on `make`
as the main source file (native_bt.i) has not changed.

The Makefile is already tracking when files changed and need to be
recompiled so we can simply bypass the setup.py checks by using the
--force flag.

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
4 years agoSilence unused variable warnings caused by BT_ASSERT() in non-debug mode
Francis Deslauriers [Tue, 3 Apr 2018 20:24:49 +0000 (16:24 -0400)] 
Silence unused variable warnings caused by BT_ASSERT() in non-debug mode

When building with the BABELTRACE_DEBUG_MODE configure option _not_ set,
multiple set-but-not-used warnings are emitted by the compiler. Most of
the time this happens because BT_ASSERT() is used to verify the return
value of functions and when not in DEBUG_MODE those return value are not
used.

The solution is to explicitly tell the compiler that we don't care about
this value so that it does not emit warning when building in non-debug
mode. This approach also makes sure not to evaluate the expression using
the `sizeof` operator, thus preventing any side effects.

See this post for further details [1].

[1]: https://stackoverflow.com/questions/37411809/how-to-elegantly-fix-this-unused-variable-warning/37412551#37412551

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
4 years agobt2: typo staitc -> static
Francis Deslauriers [Mon, 2 Apr 2018 14:05:07 +0000 (10:05 -0400)] 
bt2: typo staitc -> static

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
4 years agoCleanup: remove GCC precompiled header leftover
Francis Deslauriers [Thu, 12 Apr 2018 15:19:29 +0000 (11:19 -0400)] 
Cleanup: remove GCC precompiled header leftover

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
4 years agoSplit CTF IR and CTF writer APIs and implementations
Philippe Proulx [Sat, 7 Apr 2018 17:20:16 +0000 (13:20 -0400)] 
Split CTF IR and CTF writer APIs and implementations

This patch splits the CTF IR and CTF writer APIs, previously implemented
at a single place with aliases to make CTF writer functions and types be
synonymous to CTF IR ones, with as much common code as possible for both
APIs.

The goal of this change is to be able to modify one API/implementation
without disturbing the other, optimization being one major use case.

Common API
==========
Most of the CTF IR and CTF writer functions perform the exact same
tasks. Some functions, however, have minor differences. For example,
bt_trace_add_stream_class() tries to automatically map specific integer
field types to the stream class's CTF writer clock's class if the trace
object was created by a CTF writer object.

To keep as much common code as possible, `struct bt_*_common` types and
bt_*_common() functions are introduced. A common structure contains the
common data needed for both CTF IR and CTF writer, while actual
CTF IR/writer structures "inherit" this one. For example:

    struct bt_stream_common {
        struct bt_object base;
        int64_t id;
        struct bt_stream_class_common *stream_class;
        GString *name;
        GArray *destroy_listeners;
    };

    struct bt_stream {
        struct bt_stream_common common;
    };

    struct bt_ctf_stream {
        struct bt_stream_common common;
        struct bt_ctf_field *packet_header;
        struct bt_ctf_field *packet_context;
        GPtrArray *events;
        struct bt_ctf_stream_pos pos;
        unsigned int flushed_packet_count;
        uint64_t discarded_events;
        uint64_t size;
        uint64_t last_ts_end;
    };

All bt_stream_common_*() functions require a pointer to
`struct bt_stream_common`. You can use the BT_TO_COMMON() and
BT_FROM_COMMON() macros of `include/babeltrace/ctf-ir/utils-internal.h`
to statically cast the pointers in each direction. BT_TO_COMMON() needs
the concrete (non-common) structure to have a common structure member
named `common`.

A concrete implementation is responsible for the allocation and
deallocation of its objects, but the common API provides internal
functions to initialize and finalize the common parts. Examples are
bt_event_common_initialize(), bt_event_class_common_finalize(), and
bt_field_type_common_floating_point_initialize(). Those initialization
functions take a `release_func` parameter which is the concrete object
destruction function. The latter is responsible for finalizing the
specific part, calling bt_*_common_finalize() to finalize the common
part, and deallocating the object.

Most of the concrete functions look like this:

    struct bt_field_type *bt_event_class_get_payload_field_type(
            struct bt_event_class *event_class)
    {
        return BT_FROM_COMMON(bt_event_class_common_get_payload_field_type(
            BT_TO_COMMON(event_class)));
    }

Some common functions are more complicated and can be considered
template methods: they take various options and callback functions to be
called at specific places within the procedure.
bt_event_common_initialize() and bt_trace_common_add_stream_class() are
obvious examples.

The cases of field types and fields are special because those structures
already use inheritance: an integer field type structure inherits the
field type structure. In order for all the APIs to be able to statically
cast to the appropriate types, here's how a concrete field type is
arranged:

    +------------------------------------+
    | Common field type                  | <- bt_field_type_common_*()
    +------------------------------------+
    | Concrete common field type (union) | <- bt_(ctf_)field_type_*()
    +------------------------------------+
    | Common specific field type         | <- bt_field_type_common_integer_*()
    +------------------------------------+
    | Specific field type                | <- bt_(ctf_)field_type_integer_*()
    +------------------------------------+

The four parts are at a fixed offset.

Field objects follow the same structure.

As of this patch, `struct bt_field_type`, `struct bt_ctf_field_type`,
`struct bt_field`, and `struct bt_ctf_field` are only forward-declared
and always `(void *)` casted to and from the appropriate common type for
public APIs because they don't add specific data. For example:

    int bt_ctf_field_type_set_alignment(struct bt_ctf_field_type *ft,
            unsigned int alignment)
    {
        return bt_field_type_common_set_alignment((void *) ft, alignment);
    }

Also of interest is `struct bt_ctf_clock_class` which includes
`struct bt_clock_class`: there's no `struct bt_clock_class_common`
because as of this patch we don't expect a CTF IR clock class property
to be absent from a CTF writer clock class.

As of this patch, the common API and implementation are in the same
source and header files as CTF IR. Fast path common functions (most
getters and almost everything related to fields and events) are
implemented in internal header files as `static inline` functions.

Logging
=======
BT_LIB_LOG(), and consequently BT_ASSERT_PRE() and its variants, is
modified with an added prefix character to distinguish a CTF IR object
from a CTF writer object and from a common object. The prefix character
is inserted just before the format specifier: `_` means a common object
(underscore as in low as in base), and `w` means a CTF writer object. No
prefix means a CTF IR or other object (graph objects, value objects,
etc.).

Using `%!+_t` with a CTF IR trace object, for example, is correct
because it inherits the common part, but using `%!+t` with a common
trace object could eventually lead to bad data or to a segmentation
fault.

See the updated description in
`include/babeltrace/lib-logging-internal.h` for more details.

Testing
=======
Some tests in `tests/lib` are modified because they used a mix of CTF IR
and CTF writer APIs. Also there is a new precondition that a CTF IR
event class must be part of a trace before you can create an event from
it (the CTF writer API does not have this restriction for backward
compatibility reasons): this guarantee could make things easier in the
future and it is acceptable for a CTF IR user.

Some CTF writer tests are removed because they were in fact CTF IR
tests. In the future we should create specific CTF IR tests and reuse
the removed tests.

Limitations
===========
This patch does not address, and reserves for future work:

* Python bindings
* Python bindings tests
* `src.ctf.lttng-live`, `sink.ctf.fs`, `flt.utils.trimmer`,
  `flt.lttng-utils.debug-info`, and `src.text.dmesg` component classes

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: metadata: transform fast path precond. checks to BT_ASSERT_PRE()
Philippe Proulx [Wed, 7 Mar 2018 00:25:48 +0000 (19:25 -0500)] 
lib: metadata: transform fast path precond. checks to BT_ASSERT_PRE()

Use BT_ASSERT_PRE() to assert that trace, stream, stream class, event
class, and field type preconditions are satisfied instead of
unconditional run-time checks for typical fast path API functions
(getters).

Update `tests/lib/test_ctf_writer.c` accordingly to remove unit tests
which expect a specific return value when preconditions are not
satisfied.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoNotification iterator: transform precondition checks to BT_ASSERT_PRE()
Philippe Proulx [Fri, 2 Mar 2018 00:08:30 +0000 (19:08 -0500)] 
Notification iterator: transform precondition checks to BT_ASSERT_PRE()

Use BT_ASSERT_PRE() to assert that notification iterator preconditions
are satisfied instead of unconditional run-time checks.

A notification iterator now expects, for a given stream, that a
BT_NOTIFICATION_TYPE_STREAM_BEGIN notification is received as the first
notification, and a BT_NOTIFICATION_TYPE_PACKET_END notification as the
last one. It also expects that, for a given sequence of
BT_NOTIFICATION_TYPE_EVENT notifications which belong to the same
packet, a BT_NOTIFICATION_TYPE_PACKET_BEGIN notification is received
before and a BT_NOTIFICATION_TYPE_PACKET_END notification after.

A notification iterator does not automatically generate
BT_NOTIFICATION_TYPE_STREAM_BEGIN, BT_NOTIFICATION_TYPE_STREAM_END,
BT_NOTIFICATION_TYPE_PACKET_BEGIN, and BT_NOTIFICATION_TYPE_PACKET_END
notifications anymore. In developer mode, the iterator validates that
those notifications were emitted in the correct order and that no
notification is missing for the stream. This is made possible by a
notification sequence number. The first time a notification is received
by an iterator, the iterator sets its sequence number to the expected
one (previous sequence number for this stream plus one). Other iterators
validate that, for a given stream, the received notification's sequence
number is expected.

Because BT_NOTIFICATION_TYPE_STREAM_BEGIN,
BT_NOTIFICATION_TYPE_STREAM_END, BT_NOTIFICATION_TYPE_PACKET_BEGIN, and
BT_NOTIFICATION_TYPE_PACKET_END notifications are expected to be
manually emitted now, the concept of notification subscription is
removed. Each notification iterator user receives all the emitted
notifications, and either forwards the whole notification sequence (for
a given stream) as is or use them to create its own stream and
notifications.

Thanks to the notification sequence number, the stream's current
component port hash table is removed. A component can send notifications
from the same stream to two different ports now, but both streams of
notifications must be complete.

A notification iterator also checks that, when requested to be ended,
its stream is finished (BT_NOTIFICATION_TYPE_STREAM_END received). This
confirms that the iterator's user (consumer) received all the
notifications for a given stream and that nothing is discarded.

`plugins/ctf/common/notif-iter/notif-iter.c` is modified so that it
emits the required BT_NOTIFICATION_TYPE_STREAM_BEGIN notification as its
first one and BT_NOTIFICATION_TYPE_STREAM_END as its last one (when the
medium returns "end of stream"). In order to support multiple stream
files which contain packets of the same logical stream (LTTng's trace
file rotation), `plugins/ctf/fs-src/fs.c` is changed to ignore
"intermediate" BT_NOTIFICATION_TYPE_STREAM_BEGIN and
BT_NOTIFICATION_TYPE_STREAM_END notifications when it resets its CTF
notification iterator (`notif-iter`) between stream files.

Python bindings, some plugins, and some tests are not updated and could
not work as of this patch because further changes in the same patch set
will significantly change them anyway. The changes also do not deal with
BT_NOTIFICATION_TYPE_DISCARDED_EVENTS and
BT_NOTIFICATION_TYPE_DISCARDED_PACKETS notification types as I plan to
remove those types and make this information part of the
BT_NOTIFICATION_TYPE_PACKET_BEGIN type.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoReplace assert() -> BT_ASSERT() and some preconditions with BT_ASSERT_PRE()
Philippe Proulx [Wed, 28 Feb 2018 23:37:29 +0000 (18:37 -0500)] 
Replace assert() -> BT_ASSERT() and some preconditions with BT_ASSERT_PRE()

In the whole project: replace assert() with BT_ASSERT(), and include
<babeltrace/assert-internal.h> instead of <assert.h>. This means that,
from now on, logic/postcondition assertions are disabled by default: you
need to enable them explicitly with `BABELTRACE_DEBUG_MODE=1` when
configuring the project.

In the library: replace the precondition checks which actively occur
while a graph is running with BT_ASSERT_PRE() or other helpers that are
only enabled in developer mode. Those are mostly checks for `bt_event`,
`bt_packet`, `bt_field`, `bt_notification`, and `bt_value` objects.

Frozen and validation flags for those objects are now only handled in
developer mode. The concept of set/unset fields is also only handled in
developer mode. This is why some internal functions have their name
prefixed with `_` and a macro is used instead to do nothing when in
non-developer mode (e.g., bt_field_freeze() calls _bt_field_freeze() in
developer mode and does nothing in non-developer mode).

The transformation of unconditional run-time precondition checks to
using BT_ASSERT_PRE() is not done for the notification iterator object.
This is a separate concern with different challenges which will be
implemented in a subsequent patch.

Tests which check that API functions fail when preconditions are not
satisfied in `tests/lib/test_bt_values.c` and
`tests/lib/test_ctf_writer.c` are removed. From my point of view,
checking for those preconditions is not part of the API now: it is only
a service provided for developers in developer mode. In other words,
because a library user cannot expect a specific reaction when not
satisfying the required preconditions, you cannot unit-test them either.
What is important is to validate that the library works as expected when
used as expected.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoAdd internal BT_ASSERT() and BT_ASSERT_PRE() helpers
Philippe Proulx [Wed, 28 Feb 2018 23:37:08 +0000 (18:37 -0500)] 
Add internal BT_ASSERT() and BT_ASSERT_PRE() helpers

This patch adds new internal assertion macros to control what is
asserted. The ultimate purpose of this is to disable logic/postcondition
assertions and run-time precondition checks in a production build to
optimize the project.

`configure.ac` is modified so that it handles two new environment
variables:

`BABELTRACE_DEBUG_MODE`:
    When set to `1`: enables the Babeltrace debugging mode. This enables
    internal assertions which validate logic and postconditions with the
    BT_ASSERT() macro. This defines `BT_DEBUG_MODE` in sources.

    As of this patch, when in debugging mode, BT_ASSERT() is the
    equivalent of assert(). However, assert() is enabled by not passing
    `-DNDEBUG` to the compiler, while BT_ASSERT() is enabled by passing
    `-DBT_DEBUG_MODE`.

    Because the build is not in debugging mode by default, even if
    `-DNDEBUG` is not passed to the compiler (thus not enabling
    assert()), neither is `-DBT_DEBUG_MODE`, so all logic/postcondition
    assertions are disabled in production.

    You can use BT_ASSERT() anywhere in the whole project by including
    <babeltrace/assert-internal.h>.

    If a function is to be used only within a BT_ASSERT() context,
    then the compiler would complain that it is unused in non-debugging
    mode. You can tag the function with `BT_ASSERT_FUNC` for this.

`BABELTRACE_DEV_MODE`:
    When set to `1`: enables the Babeltrace developer mode. This enables
    precondition assertions in the library. This defines `BT_DEV_MODE`
    in sources.

    A lot of run-time checks can be avoided in production once you know
    that the code is correct, i.e. that it won't perform anything
    illegal, whatever the end user does. Some examples are NULL checks,
    frozen checks, and bound checks.

    The developer mode allows run-time precondition checks to be
    performed with BT_ASSERT_PRE(). This macro expects the condition to
    check as well as a message. In developer mode, when the condition is
    false, the message is printed with BT_LIB_LOGF(), indicating that a
    library precondition was not satisfied at this point, and then
    abort() is called.

    The developer mode is a trade-off between strictness and
    performance: you can get a very strict library with a developer mode
    build, and a more efficient library with a non-developer mode build.

    If a function is to be used only within a BT_ASSERT_PRE() context,
    then the compiler would complain that it is unused in non-developer
    mode. You can tag the function with `BT_ASSERT_PRE_FUNC` for this.
    In such a function, use BT_ASSERT_PRE_MSG() to log any additional
    information without aborting (since you know the process will abort
    thanks to BT_ASSERT_PRE()).

    BT_ASSERT_PRE_NON_NULL() is a helper which does a non-NULL
    precondition check.

    BT_ASSERT_PRE_HOT() is a helper which does a non-frozen precondition
    check.

    `lib/logging.c` is modified so that, in developer mode, the
    library's default log level is FATAL and you cannot set it to NONE.
    This is important because BT_ASSERT_PRE() and BT_ASSERT_PRE_MSG()
    use BT_LIB_LOGF() to print messages.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: add BT_LIB_LOG*() macros to log/serialize library objects
Philippe Proulx [Fri, 23 Feb 2018 03:14:11 +0000 (22:14 -0500)] 
lib: add BT_LIB_LOG*() macros to log/serialize library objects

Add specialized, internal logging macros to log Babeltrace library
objects. Those macros expand to calling bt_lib_log(), which calls
bt_common_custom_vsnprintf() to support custom conversion specifiers.

Almost all Babeltrace objects are supported. The CTF writer object is
supported with the `%!w` specifier, but its formatting remains to be
done. There is no conversion specifier to format a clock class priority
map.

See `include/babeltrace/lib-logging-internal.h` for more details,
limitations, and for the list of custom conversion specifiers.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoCommon: add internal bt_common_custom_vsnprintf()
Philippe Proulx [Fri, 23 Feb 2018 03:01:15 +0000 (22:01 -0500)] 
Common: add internal bt_common_custom_vsnprintf()

This new utility function (and its corresponding
bt_common_custom_snprintf()) is like vsnprintf(), but it also allows to
use custom conversion specifiers with the help of a user callback which
consumes one or more variadic arguments and writes to the current output
buffer position according to the custom conversion specifier.

For example, it allows the following:

    bt_common_custom_snprintf(buf, buf_size, '@', handle_specifier,
                              NULL, "hello %d world %@s (%02x-%@+d)",
                              -23, my_object, 17.5, "meow", my_fd);

Here, the `%d` and `%02x` conversion specifiers are used to consume the
`-23` and `17.5` arguments as you would expect, but the custom `%@s` and
`%@+d` specifiers consume the `my_object`, `"meow"`, and `my_fd`
parameters thanks to the user-provided handle_specifier() callback.

See the block comment above the bt_common_custom_vsnprintf() declaration
for more details and for limitations regarding the format string.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoLogging: use a TLS buffer and increase its size
Philippe Proulx [Fri, 23 Feb 2018 02:57:30 +0000 (21:57 -0500)] 
Logging: use a TLS buffer and increase its size

The logging system's line buffer is on the stack, and its current size
is 512. This means any log line which is larger than 512 bytes (this can
happen with some warnings/errors with a lot of information) gets
truncated.

In order to make this buffer size arbitrarily large, use a TLS global
buffer instead.

Increase the logging system's line buffer to 16 kiB (per thread).

Drawback: the logging system had a static assertion which ensured that
the line buffer size was not greater than PIPE_BUF so that individual
write operations were atomic. With a line buffer size larger than
PIPE_BUF, different threads could write to the output stream at the same
time which could result in interlaced data. We need to add some locking
to support multithreaded logging.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agobt2: InactivityNotification, _Event: use mapping protocol for clock values
Philippe Proulx [Mon, 19 Feb 2018 23:25:05 +0000 (18:25 -0500)] 
bt2: InactivityNotification, _Event: use mapping protocol for clock values

The bt2._Event and bt2.InactivityNotification classes both have the
clock_value() and add_clock_value() methods to get and add clock values
associated to clock classes. This can be replaced with a mapping
protocol accessible with the `clock_value` property.

The mapping's add() method can be used to add a clock value to the
mapping (instead of using __setitem__() because the clock value has a
reference to its clock class (the key) anyway).

Tests are updated accordingly.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agobt2: EnumerationFieldType: rename append_mapping() -> add_mapping()
Philippe Proulx [Mon, 19 Feb 2018 22:40:46 +0000 (17:40 -0500)] 
bt2: EnumerationFieldType: rename append_mapping() -> add_mapping()

We're not _appending_ anything in bt2.EnumerationFieldType here, as
opposed to bt2.StructureFieldType (which contains ordered fields), so
the method should be named add_mapping(), like a Python set has the
add() method, whereas a Python list has the append() method.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: call bt_stream_class_map_clock_class() in bt_event_create()
Philippe Proulx [Mon, 19 Feb 2018 22:32:52 +0000 (17:32 -0500)] 
Fix: call bt_stream_class_map_clock_class() in bt_event_create()

Issue
=====
It is possible, for backward compatibility, to create an event before it
is appended to a CTF writer stream. This means that, when
bt_ctf_writer_create_stream() is called, bt_event_create() is already
called. Because bt_ctf_writer_create_stream() calls
bt_trace_add_stream_class(), which calls
bt_stream_class_map_clock_class() to map selected fields to the stream
class's clock's class, this is skipped in this use case and selected
fields are never mapped.

The problematic sequence is:

1. Create a stream class.
2. Set this stream class's CTF writer clock.
3. Create an event with bt_event_create().
4. Create a CTF writer stream with bt_ctf_writer_create_stream().
5. Append the event (3.) to the CTF writer stream (4.) with
   bt_stream_append_event().

In 5., the event header's `timestamp` field is not automatically
populated from the current value of the stream class's clock because its
field type was not automatically mapped to a clock class.

Solution
========
After validating the field types in bt_event_create(), call
bt_stream_class_map_clock_class() on the validated packet context and
event header field types. bt_stream_class_map_clock_class() only
performs automatic mapping when the stream class has a registered CTF
writer clock, which eventually guarantees that this is a CTF writer
stream class because it is forbidden to call bt_trace_add_stream_class()
with such a stream class when the trace was not created by a CTF writer.

In other words, this additional bt_stream_class_map_clock_class() in
bt_event_create() does NOT affect non-CTF writer objects.

Known drawbacks
===============
None.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoAdd tests: CTF writer: `timestamp_begin`/`timestamp_end` autopopulation
Philippe Proulx [Mon, 19 Feb 2018 21:45:55 +0000 (16:45 -0500)] 
Add tests: CTF writer: `timestamp_begin`/`timestamp_end` autopopulation

Those new tests validate that the automatic population of the
`timestamp_begin` and `timestamp_end` fields in CTF writer work as
expected.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: bt_stream_class_map_clock_class(): copy field type when mapping
Philippe Proulx [Wed, 14 Feb 2018 19:54:39 +0000 (14:54 -0500)] 
Fix: bt_stream_class_map_clock_class(): copy field type when mapping

Issue
=====
When a CTF writer stream class's packet context type contains the
special field types `timestamp_begin`, `timestamp_end`, and `timestamp`,
they are automatically mapped to the stream class's clock's class when
the stream class is about to be frozen in bt_trace_add_stream_class().
However, because the field type is mapped as is without a prior copy, it
is possible that this field type is shared with other locations in the
metadata tree which should not be mapped to a clock class.

Solution
========
Before automatically mapping any field type to a clock class, or more
generally, before modifying any field type, make a copy and replace the
original within its parent.

Known drawbacks
===============
None.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: add internal bt_field_type_structure_replace_field()
Philippe Proulx [Wed, 14 Feb 2018 19:53:36 +0000 (14:53 -0500)] 
lib: add internal bt_field_type_structure_replace_field()

This new internal function replaces the field type of a field identified
by name within a structure field type.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: logging: change warnings from BT_LOGE to BT_LOGW
Philippe Proulx [Tue, 13 Feb 2018 23:39:28 +0000 (18:39 -0500)] 
lib: logging: change warnings from BT_LOGE to BT_LOGW

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: CTF writer: validate and set `timestamp_begin`/`timestamp_end`
Philippe Proulx [Tue, 13 Feb 2018 22:19:00 +0000 (17:19 -0500)] 
Fix: CTF writer: validate and set `timestamp_begin`/`timestamp_end`

Issue
=====
A CTF writer stream's packet context's `timestamp_begin` and
`timestamp_end` fields are not correctly automatically set and not
validated. There are many issues:

1. There's no validation that the `timestamp_begin` value of flushed
   packet N is greater than or equal to the `timestamp_end` value of
   packet (N - 1).

2. The automatic values are the event header's `timestamp` field of the
   first appended event for `timestamp_begin` and of the last appended
   event for `timestamp_end`. A field updating the stream's clock could
   exist in the payload of the last appended event, for example, making
   the automatic `timestamp_end` value too small.

   Also, the current code does not consider mapped integer fields with a
   size which is less than the size of the `timestamp_begin` field. In
   this case, the CTF clock update mechanism must be used.

3. Because of 2., a CTF writer stream cannot flush an empty packet (no
   appended events) without providing `timestamp_begin` and
   `timestamp_end` because there's no event to extract the automatic
   values.

4. There's no validation that `timestamp_end` is greater than or equal
   to `timestamp_begin`.

Solution
========
When flushing a CTF writer stream:

1. Set the initial packet's timestamp to one of:

   * The value of `timestamp_begin`, if the field is set.
   * The previous packet's last timestamp, if available. The stream
     object contains this value. It's not available before the first
     flush.
   * Zero.

2. Set the current clock value to the value computed in 1. It is correct
   to have a single current clock value because the library guarantees
   that a given stream class contains at most a single clock class.

3. Visit all the fields of the packet context (except the special fields
   which could not be set at this point), and then all the fields of all
   the appended events, in order, to update the current clock value.
   Apply the CTF clock update mechanism to handle updating fields which
   have a wrapping value.

4. If `timestamp_end` is set, validate that its value is greater than
   or equal to the computed current clock value. This is a validation
   step.

5. If `timestamp_end` is not set, set it to the current clock value.

6. If `timestamp_begin` is not set, set it to the initial timestamp.

7. Set the stream's last final timestamp to the value of
   `timestamp_end`.

Those steps perform validation and automatic field value setting at the
same time.

Known drawbacks
===============
This solution makes the stream flushing process slower. However, there's
room for optimization. For example, there's no need to visit all the
fields: we just need to visit the fields which are mapped to a clock
class. Moreover, if all the types of the mapped fields have a size which
is at least the size of the `timestamp_begin` field, then there's no
need to visit them at all: we can use the last event's last mapped
field's value directly because the mapped fields always overwriting the
current clock value anyway.

Tests for the `succeed/lttng-modules-2.0-pre5` trace are removed because
this solution reveals an invalid trace: the `timestamp_begin` value of
the second packet in `channel0_5` is less than the `timestamp_end` value
of the first packet. This was produced by the LTTng-modules 2.0-pre5
tracer, so it can be considered an invalid trace as per CTF.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: add internal bt_field_sequence_get_int_length()
Philippe Proulx [Tue, 13 Feb 2018 22:17:31 +0000 (17:17 -0500)] 
lib: add internal bt_field_sequence_get_int_length()

This new internal helper returns a sequence field's length as an
`int64_t` value instead of returning the integer field. Returns a
negative value on error or if the sequence fields's length field is not
set.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoAdd stream class's single clock class tests
Philippe Proulx [Wed, 7 Feb 2018 20:05:27 +0000 (15:05 -0500)] 
Add stream class's single clock class tests

Those new tests verify that:

* You cannot have a clock class in one of the stream class's field types
  and a different one in one of its event classes.
* You cannot have two different clock classes in two different event
  classes of the same event class.
* You cannot set a stream class's CTF writer clock and have a clock
  class within this stream class which is not the stream class's clock's
  class.

The tests check those conditions when calling specific API functions and
in the expected order:

* bt_trace_add_stream_class()
* bt_event_create()
* bt_stream_class_add_event_class()

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: allow a single mapped clock class within a stream class
Philippe Proulx [Wed, 31 Jan 2018 21:17:19 +0000 (16:17 -0500)] 
lib: allow a single mapped clock class within a stream class

This patch makes it illegal to have more than one mapped clock class
within the field types of a stream class and all its event classes. Many
field types can map to the same, unique clock class.

Multiple clock classes within a given stream class is not a well-defined
nor well-supported feature, if it is one in the first place, of CTF.
Considering the known use cases we have in the field, it is not used
either. A clock's value should be reset to the value of the
`timestamp_begin` field of the packet's context for each packet, but
this field can only be mapped to a single clock class anyway. What
should its initial value be in this case? The specification is silent on
this matter.

We keep an "expected" clock class in the stream class object. This is
only valid when the stream class is frozen; otherwise, the stream
class's field types can change, even when event classes are already part
of it. If the stream class is already frozen, then if the expected clock
class is still NULL (no mapped clock class at this point), an added
event class can set it (for future added event classes).

If the stream class is eventually part of a trace which was created by a
CTF writer, we make sure that the expected clock class is the stream
class's clock's class, if any. This is important because, in
bt_trace_add_stream_class(), on success, we try to map some special
fields to the stream's clock's class. Because we know at this point that
the stream's clock's class is also the stream class's expected clock
class, it is safe to perform this mapping once the single clock class
validation is already done.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoFix: libctfcopytrace: replace clock classes in copies
Philippe Proulx [Fri, 2 Feb 2018 21:35:07 +0000 (16:35 -0500)] 
Fix: libctfcopytrace: replace clock classes in copies

Issue
=====
Using the functions of libctfcopytrace, some field types are reused as
is in the copied event class/stream class. For example, when we copy a
stream class, we set the copy's packet context field type to the
original packet context field type, without copying it. However, we copy
the clock classes from the original trace to the copy. The result of
this is that the copied packet context field type can contain a mapped
clock class which is not registered to its stream class's trace. This is
considered invalid.

Solution
========
This patch makes those functions systematically copy the all the field
types and then replace the original mapped clock classes to their copy
with replace_clock_classes().

Known drawbacks
===============
None.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agobt_field_type_compare(): deep-compare mapped clock classes
Philippe Proulx [Fri, 2 Feb 2018 21:31:37 +0000 (16:31 -0500)] 
bt_field_type_compare(): deep-compare mapped clock classes

Deep-compare mapped clock classes in bt_field_type_integer_compare()
instead of just comparing the pointers. Given the same contexts, two
integer field types which have equal properties and equal mapped clock
classes (not just equal clock class pointers) are considered equal.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agoAdd test: no clock class in trace's packet header field type
Philippe Proulx [Fri, 22 Dec 2017 00:00:31 +0000 (19:00 -0500)] 
Add test: no clock class in trace's packet header field type

This patch adds a test case which uses the Python bindings to test that
it is not possible to set a trace's packet header field type containing
an integer field type mapped to a clock class.

The new tests/lib/ctf-ir directory is set so that future CTF IR test
cases can be added easily if need be instead of going to
tests/lib/test_ctf_writer.c.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agolib: do not allow any mapped clock class in trace's packet header FT
Philippe Proulx [Wed, 20 Dec 2017 22:33:15 +0000 (17:33 -0500)] 
lib: do not allow any mapped clock class in trace's packet header FT

Do not allow any integer field type to be mapped to a clock class within
the packet header field type of a trace.

This is one of the steps to ensure that a given stream class has only
one (if any) mapped clock class, recursively. More than one clock class
for a given stream class was never well supported anyway in CTF 1.8
because you cannot have multiple `timestamp_begin` and `timestamp_end`
fields.

It's also weird to have a clock value update in the packet header
because we don't have the value of `timestamp_begin` yet. Where would
this value be "located" on the timeline if `timestamp_begin` is the
absolute beginning timestamp of the packet containing said header?
Unless it is always the exact same value as `timestamp_begin` (which is
useless), it does not fit with the clock value update mechanism where,
as fields are decoded (or encoded), a given clock's value must be
updated monotonically: if the clock value found in the packet header is
less than `timestamp_begin`, then its lower bound is not
`timestamp_begin`.

The check is performed whenever the trace is about to be frozen (this
freezes the packet header field type) on success, that is:

* bt_trace_add_stream_class()
* bt_trace_set_is_static()

The check uses the new bt_validate_single_clock_class() internal
function. This one makes sure that a given field type recursively
contains only one clock class. You pass the expected clock class to the
function, or NULL so that the function sets it for you. In the trace
packet header field type case, even if this function returns 0
(success), that is, the field contains _at most_ one clock class, we
check that the returned expected clock class is still NULL to make sure
the field type in fact contains none.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agotests/plugins/test_lttng_utils_debug_info.in: use specific pattern
Philippe Proulx [Mon, 18 Dec 2017 23:31:39 +0000 (18:31 -0500)] 
tests/plugins/test_lttng_utils_debug_info.in: use specific pattern

If this new pattern is not passed to the test runner, then any new `.py`
file would also be discovered by this test.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
4 years agotests/utils/python/testrunner.py: add optional pattern argument
Philippe Proulx [Mon, 18 Dec 2017 23:29:40 +0000 (18:29 -0500)] 
tests/utils/python/testrunner.py: add optional pattern argument

Add an optional command-line argument (second) to `testrunner.py`: the
test file name pattern. You can use this argument to run only specific
files in a given test directory, instead of the default which is
`test*.py`.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
5 years agoFix: invalid alignment of enumeration fields
Jérémie Galarneau [Tue, 30 Oct 2018 23:19:14 +0000 (00:19 +0100)] 
Fix: invalid alignment of enumeration fields

Issue
---

According to the CTF specification, the alignment of an enumeration is
that of its container integer field type. However, ctf-ir does not
forward the alignment of an enumeration field type's alignment in
bt_field_type_get_alignment().

This causes babeltrace to fail to read traces produced by lttng-ust
following a fix that causes it to generate extended event headers. The
problem is observed on ARM platforms since lttng-ust will produce
a layout that does not result in unaligned memory accesses.

Solution
---

The alignment of the enumeration field type's container is sampled
when the enumeration field type is frozen.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 years agoAdd git version string
Michael Jeanson [Tue, 1 May 2018 18:30:02 +0000 (14:30 -0400)] 
Add git version string

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 years agoFix live-comm: merge TCP socket write-write sequence in a single write
Jonathan Rajotte [Fri, 24 Nov 2017 20:48:31 +0000 (15:48 -0500)] 
Fix live-comm: merge TCP socket write-write sequence in a single write

The live protocol implementation is often sending content
on TCP sockets in two separate writes. One to send a command header,
and the second one sending the command's payload. This was presumably
done under the assumption that it would not result in two separate
TCP packets being sent on the network (or that it would not matter).

Delayed ACK-induced delays were observed [1] on the second write of the
"write header, write payload" sequence and result in problematic
latency build-ups for live clients connected to moderately/highly
active sessions.

Fundamentally, this problem arises due to the combination of Nagle's
algorithm and the delayed ACK mechanism which make write-write-read
sequences on TCP sockets problematic as near-constant latency is
expected when clients can keep-up with the event production rate.

In such a write-write-read sequence, the second write is held up until
the first write is acknowledged (TCP ACK). The solution implemented
by this patch bundles the writes into a single one [2].

[1] https://github.com/tbricks/wireshark-lttng-plugin
Basic Wireshark dissector for lttng-live by Anto Smyk from Itiviti
[2] https://lists.freebsd.org/pipermail/freebsd-net/2006-January/009527.html

Reported-by: Anton Smyk <anton.smyk@itiviti.com>
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 years agoFix: wrong type specifier used with long argument
Jérémie Galarneau [Fri, 18 May 2018 17:58:31 +0000 (13:58 -0400)] 
Fix: wrong type specifier used with long argument

clang reports "format specifies type 'long long' but the argument has
type 'long' [-Wformat]" which is correct. retry_duration has
changed types from long long to long in the previous commit.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 years agoFix: POPT_ARG_LONGLONG does not exist in popt 1.13
Jérémie Galarneau [Thu, 17 May 2018 19:35:17 +0000 (15:35 -0400)] 
Fix: POPT_ARG_LONGLONG does not exist in popt 1.13

The retry duration parameter is currently declared as a long long,
which popt 1.13 does not support. The support for that type was only
added in popt 1.14.

Using POPT_ARG_LONG instead of the 'long long' variant makes no real
difference in this case (or at least, not enough to justify bumping
the minimal popt version).

This fixes a build failure that was reported on Red Hat 7 where
1.13 is the default version.

Reported-by: Abderrahmane Benbachir <abenbach@ciena.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoFix: Use bash for all test scripts
Michael Jeanson [Mon, 26 Mar 2018 15:47:44 +0000 (11:47 -0400)] 
Fix: Use bash for all test scripts

We already use bash in most test scripts shebang and the sh binary on
Solaris 10 doesn't like some of our "modern" scripts syntax.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoAdd missing clock.h compatiblity header under ctf-ir
Jérémie Galarneau [Tue, 30 Jan 2018 15:51:59 +0000 (10:51 -0500)] 
Add missing clock.h compatiblity header under ctf-ir

Babeltrace 1.5 exposes a clock.h header under ctf-ir which
is equivalent to what is now ctf-writer/clock.h.

This commit adds a compatiblity header which includes
ctf-writer/clock.h in order to maintain the backward
compatibility with the 1.x API.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agobabeltrace-filter.lttng-utils.debug-info(7): fix LTTng prerequisites
Philippe Proulx [Wed, 29 Nov 2017 17:02:29 +0000 (12:02 -0500)] 
babeltrace-filter.lttng-utils.debug-info(7): fix LTTng prerequisites

Add:

* Enable LTTng-UST state dump events.
* Enable LTTng-UST dynamic linker tracing helper events.

Convert some prose to procedures.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agobt2 tests: add unit tests for __str__ implementation of Fields
Jérémie Galarneau [Sat, 2 Dec 2017 13:41:15 +0000 (14:41 +0100)] 
bt2 tests: add unit tests for __str__ implementation of Fields

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoImplement __repr__ instead of __str__ for python Value
Jérémie Galarneau [Sun, 26 Nov 2017 10:46:19 +0000 (11:46 +0100)] 
Implement __repr__ instead of __str__ for python Value

Implement the __repr__ method for the various Value classes
as it provides a fallback for __str__ and provides both a
non-ambiguous and human-readable string representation of those
objects.

The Array and Map values' implementation is made more compact by
using list comprehensions, as is done for the Fields API.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoReturn 'Unset' on unset field __repr__()
Jérémie Galarneau [Thu, 23 Nov 2017 20:39:29 +0000 (15:39 -0500)] 
Return 'Unset' on unset field __repr__()

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoImplement __repr__ for _StringField
Jérémie Galarneau [Thu, 23 Nov 2017 19:43:04 +0000 (14:43 -0500)] 
Implement __repr__ for _StringField

Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoImplement __repr__ instead of __str__ for _NumericField
Jérémie Galarneau [Thu, 23 Nov 2017 19:41:25 +0000 (14:41 -0500)] 
Implement __repr__ instead of __str__ for _NumericField

__repr__ provides a generic fallback for __str__ and, in the
case of IntegerFields the representation is both human readable
and unambiguous.

Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoImplement __repr__ for _ArraySequenceField
Jérémie Galarneau [Thu, 23 Nov 2017 16:57:26 +0000 (11:57 -0500)] 
Implement __repr__ for _ArraySequenceField

Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoImplement __repr__ for _VariantField
Jérémie Galarneau [Thu, 23 Nov 2017 16:57:02 +0000 (11:57 -0500)] 
Implement __repr__ for _VariantField

Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoImplement __repr__ for _StructureField
Jérémie Galarneau [Thu, 23 Nov 2017 16:56:46 +0000 (11:56 -0500)] 
Implement __repr__ for _StructureField

Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoImplement __repr__ for _EnumerationField
Jérémie Galarneau [Thu, 23 Nov 2017 16:56:23 +0000 (11:56 -0500)] 
Implement __repr__ for _EnumerationField

Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Reviewed-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoFix: typo using bt2.ClockClassOffset constructor
Francis Deslauriers [Tue, 21 Nov 2017 19:29:35 +0000 (14:29 -0500)] 
Fix: typo using bt2.ClockClassOffset constructor

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoAdd bindings/python/babeltrace/test_ctf_writer.py test
Philippe Proulx [Thu, 9 Nov 2017 17:38:40 +0000 (12:38 -0500)] 
Add bindings/python/babeltrace/test_ctf_writer.py test

This test ensures that we can use the legacy Python bindings to create a
CTF trace without caring about timestamp fields (they should be
automatically updated from the stream's class's clock value).

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoFix: stream.c: autopopulate timestamp fields even when not mapped to CC
Philippe Proulx [Thu, 9 Nov 2017 17:35:27 +0000 (12:35 -0500)] 
Fix: stream.c: autopopulate timestamp fields even when not mapped to CC

To remain backward compatible with Babeltrace 1's CTF writer,
automatically set the event header `timestamp` fields (when appending
the event) and packet context `timestamp_begin` and `timestamp_end`
fields (on stream flush) when the stream's class has a registered CTF
writer clock, even if the field's types are not mapped to a clock class.

If the field is mapped to a clock class, then it is automatically set
when this mapped clock class is the same as the stream's class's clock's
class.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoFix: writer.py: make `uint64_ft` a 64-bit (instead of 32-bit) int FT
Philippe Proulx [Thu, 9 Nov 2017 16:24:30 +0000 (11:24 -0500)] 
Fix: writer.py: make `uint64_ft` a 64-bit (instead of 32-bit) int FT

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoFix: Replace bt_timegm with a thread-safe implementation
Michael Jeanson [Mon, 13 Nov 2017 20:17:47 +0000 (15:17 -0500)] 
Fix: Replace bt_timegm with a thread-safe implementation

The current compat wrapper for timegm is not thread-safe, it modifies
the process wide time settings with tzset. This was not a problem in bt1
as it was only used in the cli binary but it is now used in the trimmer
plugin which is used by the library.

Replace the wrapper with a basic implementation and add more tests.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoTypo: informations -> information
Michael Jeanson [Mon, 13 Nov 2017 23:23:56 +0000 (18:23 -0500)] 
Typo: informations -> information

Information is an uncountable noun in english.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoTypo: paramater -> parameter
Michael Jeanson [Mon, 13 Nov 2017 23:22:42 +0000 (18:22 -0500)] 
Typo: paramater -> parameter

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoTypo: priorty -> priority
Michael Jeanson [Thu, 12 Oct 2017 21:15:25 +0000 (17:15 -0400)] 
Typo: priorty -> priority

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 years agoFix: uninitialized variable may be used warning
Jérémie Galarneau [Wed, 8 Nov 2017 15:55:16 +0000 (10:55 -0500)] 
Fix: uninitialized variable may be used warning

gcc 7.2 warns of potentially uninitialized variables being
used as the callers rely on output parameters being
initialized by the callees on error. This behaviour is not
specified as part of the API so relying on this is iffy.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
This page took 0.059602 seconds and 4 git commands to generate.