Philippe Proulx [Mon, 10 Dec 2018 13:03:58 +0000 (08:03 -0500)]
bt_trace_class_create(): accept mandatory self component
This patch makes bt_trace_class_create() accept a mandatory self
component. The self component parameter is not used now, but it could be
in the future to control allocation (object pooling) and for
bookkeeping, as well as to have a system where a new trace class within
the graph can lead to notifying other components about it so they can
prepare associated data.
The `ctf` plugin is changed so that it does not require a trace class to
create packet indexes. This is required because the `trace-info` query
requires packet indexes to exist, but there's no self component in this
context to create a trace class.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 21:29:36 +0000 (16:29 -0500)]
Component class API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 21:09:46 +0000 (16:09 -0500)]
lib: add aliases for Babeltrace enumeration types
And uses aliases in CLI, plugins, and tests.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:47:12 +0000 (15:47 -0500)]
Plugin development API: use self enumeration and plugin types
This is similar to a component class method accepting a self component
object.
The self plugin API is empty for the moment, but we might want to add
functions which do not apply to plugin or const plugin objects later
(for example, a function to set a self plugin's private data).
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:38:21 +0000 (15:38 -0500)]
lib: remove unused public `enum bt_plugin_status`
Also:
* Make the plugin's user exit function return nothing. It's not like we
can cancel this anyway.
* Make the plugin's user init function return
`enum bt_plugin_init_status`, an enumeration reserved for this
function, in case `enum bt_plugin_status` becomes public in the
future.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:26:46 +0000 (15:26 -0500)]
Trace API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:23:57 +0000 (15:23 -0500)]
Stream API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:23:48 +0000 (15:23 -0500)]
Trace class API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:17:58 +0000 (15:17 -0500)]
Stream class API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:13:56 +0000 (15:13 -0500)]
Packet API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:11:23 +0000 (15:11 -0500)]
Field API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 20:05:08 +0000 (15:05 -0500)]
Field class API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 19:58:30 +0000 (14:58 -0500)]
Event API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 19:54:23 +0000 (14:54 -0500)]
Event class API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 19:47:56 +0000 (14:47 -0500)]
Clock snapshot API: use status
`enum bt_clock_snapshot_status` is renamed to `enum
bt_clock_snapshot_state` (known or unknown), while `enum
bt_clock_snapshot_status` is the API status enumeration like with other
APIs.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 19:23:13 +0000 (14:23 -0500)]
Clock class API: use status
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 19:00:41 +0000 (14:00 -0500)]
Remove unused lib/graph/message/discarded-{events,packets}.c
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 18:46:17 +0000 (13:46 -0500)]
lib: rename "clock value" -> "clock snapshot"
This is more consistent with the current counter snapshots in the packet
API.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 18:07:25 +0000 (13:07 -0500)]
lib: rename "notification" -> "message"
The term "notification" is usually used, in APIs, for asynchronous
alerts of some sort. You get notified for something that you were not
actively waiting for, like an interrupt.
From Merriam-Webster, a _message_ is:
> a communication in writing, in speech, or by signals
and a _communication_ is:
> information communicated : information transmitted or conveyed
Therefore, "message" seems more adapted than "notification" for
Babeltrace's API, where you actively iterate messages which are
communications from an upstream component to a downstream component.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 17:44:10 +0000 (12:44 -0500)]
lib: rename bt_plugin_create_all_*() -> bt_plugin_find_all_*()
Those functions return a const plugin set anyway, so we're not really
creating private objects as other *_create() functions do.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Sat, 8 Dec 2018 17:30:25 +0000 (12:30 -0500)]
lib: add aliases for Babeltrace structure types
And uses aliases in CLI, plugins, and tests.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 22:33:41 +0000 (17:33 -0500)]
lib: make public reference count functions have strict types
Instead of having generic bt_object_get_ref() and bt_object_put_ref()
accepting `const void *`, have one pair of such functions for each
shared object API.
This can help catch reference count bugs (not putting or getting the
correct object type) and makes it illegal at build time to get or put a
unique object's reference.
Each shared object API also has its own BT_X_PUT_REF_AND_RESET() and
BT_X_MOVE_REF() macros.
bt_object_get_ref() and bt_object_put_ref() are now internal and only
used by the library's implementation.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 21:44:13 +0000 (16:44 -0500)]
lib: update copyrights
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 21:23:29 +0000 (16:23 -0500)]
lib: rename plural file names to singular
For example, the object is `struct bt_value` so name the header file
`value.h`.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 20:46:36 +0000 (15:46 -0500)]
lib: rename "begin" to "beginning" when used as a noun
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 20:33:02 +0000 (15:33 -0500)]
bt_value_copy(): put output parameter as last parameter
To remain consistent, make the first parameter the main object on which
we're working.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 20:30:01 +0000 (15:30 -0500)]
bt_value_map_extend(): put output parameter as last parameter
To remain consistent, make the first parameter the main object on which
we're working.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 20:23:05 +0000 (15:23 -0500)]
Fix typo: "field classe" -> "field class"
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 7 Dec 2018 20:02:41 +0000 (15:02 -0500)]
lib: split trace API into trace class and trace APIs
This patch adds the _trace class_ object and its API, moving some trace
API functions to this one instead.
The trace object was the only one holding both metadata and data objects
(stream classes and streams, for example). To be more consistent, a
trace class now deals with metadata only (no streams, no static state)
and a trace with data only. A trace is an instance (data streams) of a
trace class: you can have many traces described by the same trace class.
You create a trace class with no parameters, while you create a trace
with an existing trace class.
Like for the trace object, the trace class API has both const and
non-const APIs.
Both a trace and a trace class can have a name (optional), just like
both a stream and a stream class can have a name, and so on. With this
patch, I chose to set the name of the trace object in both src.ctf.fs
and src.text.dmesg, and to display the trace object's name in
sink.text.pretty.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Tue, 4 Dec 2018 22:07:29 +0000 (17:07 -0500)]
lib: make graph API const-correct
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Tue, 4 Dec 2018 22:03:22 +0000 (17:03 -0500)]
lib: make plugin API const-correct
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Tue, 4 Dec 2018 21:32:13 +0000 (16:32 -0500)]
Fix: notif-iter.c: handle single/implicit SC/EC correctly
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Tue, 4 Dec 2018 21:31:45 +0000 (16:31 -0500)]
Fix: ctf-meta-update-meanings.c: only update if root struct FC exists
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Tue, 4 Dec 2018 20:29:10 +0000 (15:29 -0500)]
lib: make trace IR API const-correct
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Mon, 3 Dec 2018 23:39:58 +0000 (18:39 -0500)]
lib: make values API const-correct
This patch sets out the ground for subsequent const-correctness patches.
The rules are:
* Convert private API to non-const API, without any `private` prefix,
including in the file name. A non-const API function accept a
non-const object.
Put common enumerations in this header.
* Convert public API to const API:
* Use `-const.h` suffix in file name.
* Use `_const` suffix to borrowing functions and callback type
definitions.
In this particular patch, the `bt_value_null` singleton object is
non-const because you can use it with bt_value_array_append_element()
and bt_value_map_insert_entry().
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Mon, 3 Dec 2018 21:43:05 +0000 (16:43 -0500)]
lib: bt_object_{get,put}_ref(): accept a `const` parameter
This is the first step to make the whole API const-correct.
bt_object_get_ref() and bt_object_put_ref() are not considered to
logically modify the object: they change the reference count, but the
object's readable properties remain unchanged. Considering this, it is
simpler to have a single version of each of them accepting a const
object so as to be able to get and put const objects (eventually).
bt_object_put_ref() can have the effect of destroying/freeing the
object, just like Linux's kfree() does while accepting a `const void *`
parameter.
It is safe to cast away `const` in this library because the user only
passes opaque handles to functions (`struct bt_X *` types) pointing to
non-const objects defined by the library itself in writable memory
(usually through g_new0()).
In C++11, the equivalent of having a `const struct bt_X *` object on
which you can increment and decrement the reference count would be
having an `std::shared_ptr<const bt_X>` object: the wrapper is mutable,
but the contained object is const.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Mon, 3 Dec 2018 21:08:48 +0000 (16:08 -0500)]
CTF writer: use own `bt_ctf_object` and `bt_ctf_value` internal APIs
Removing CTF writer's implementation's dependency on `bt_object` and
`bt_value` makes it even more independent so as to be free to change the
`bt_object` and `bt_value` APIs without having to update the CTF writer
part.
Both APIs are not public as of this patch, so I'm hiding the public CTF
writer functions to get a trace's environment field (and their tests),
which is a `bt_ctf_value` object. This is not breaking backward
compatibility with Babeltrace 1.5.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 22:22:43 +0000 (17:22 -0500)]
lib: move plugin set API declarations to `babeltrace/plugin/plugin-set.h`
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 22:15:03 +0000 (17:15 -0500)]
lib: have separate `BT_QUERY_EXECUTOR_STATUS` and `BT_QUERY_STATUS`
The former is for the query executor API, the latter is returned by an
actual user-defined query method. `BT_QUERY_STATUS` does not have
"canceled" and "unsupported" entries, so we can remove those checks from
bt_private_query_executor_query() after calling the user method.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 22:00:02 +0000 (17:00 -0500)]
lib: remove BT_NOTIFICATION_TYPE_{UNKNOWN,NR}
`BT_NOTIFICATION_TYPE_UNKNOWN` is not needed because we never return it.
`BT_NOTIFICATION_TYPE_NR` is an implementation detail, so we use the
last value instead.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 21:56:16 +0000 (16:56 -0500)]
bt_port_output_notification_iterator_create(): remove colander comp. name
This is an implementation detail. Just use a UUID that I just generated
to make it unique enough.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 21:42:13 +0000 (16:42 -0500)]
lib: rename transforming bt_X_borrow_Y() -> bt_X_as_Y()
We're not borrowing anything, we're just converting the type.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 20:55:33 +0000 (15:55 -0500)]
lib: plugin: reset pointers to `NULL` on destruction
When an object's member is destroyed, internally, reset its pointer
to `NULL` immediately. This makes it possible to log partial objects
during destruction while keeping Valgrind's memcheck happy.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 20:51:42 +0000 (15:51 -0500)]
lib: trace IR, values: reset pointers to `NULL` on destruction
When an object's member is destroyed, internally, reset its pointer
to `NULL` immediately. This makes it possible to log partial objects
during destruction while keeping Valgrind's memcheck happy.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 30 Nov 2018 20:31:39 +0000 (15:31 -0500)]
lib: return `void` when setting a simple value with no side effects
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Wed, 21 Nov 2018 22:30:33 +0000 (17:30 -0500)]
lib: graph: add "self" and some "private" APIs
The main purpose of this patch is to create different "views" of the
same graph objects. The terms are as such:
Public API:
You can only read properties of the object.
Example: bt_graph_is_canceled().
Private API:
You can create the object and set properties.
Example: bt_private_graph_create().
Self API:
You conceptually inherit this object.
Example: bt_self_component_set_data().
This means that component user method now accepts a "self component",
on which:
* You can set and get user data (bt_self_component_set_data() and
bt_self_component_get_data()).
* You can add ports (for example,
bt_self_component_source_add_output_port()).
* You can borrow "self component ports", on which you can get
user data (bt_self_component_port_get_data()) that you set previously
with a port adding function.
A notification iterator method now accepts a
"self notification iterator", on which:
* You can set and get user data (bt_self_notification_iterator_set_data()
and bt_self_notification_iterator_get_data()).
* You can borrow your "self component"
(bt_self_notification_iterator_borrow_component()) or "self component
output port" (bt_self_notification_iterator_borrow_port()).
Also, you now use the private component class API to create component
classes and set optional methods, a description, and the rest.
Also in this patch:
* Component class and component APIs are split into source, filter, and
sink parts. This makes everything more type safe considering that:
* We don't need any polymorphism like we do, for example, for field
classes, for component classes and components: you always know,
contextually, with which type you're dealing.
* We don't need to have collections of components or component classes
of different types: we can just use three collections each time.
This means that the private graph API, for example, now has the three
distinct bt_private_graph_add_source_component(),
bt_private_graph_add_filter_component(), and
bt_private_graph_add_sink_component(), each of them accepting the
appropriate component class type and returning the corresponding
component type.
No function exists to borrow a source component's input port
or a sink component's output port.
* The port API is split into input and output parts, with the new
`struct bt_port_in` and `struct bt_port_out` types.
An interesting consequence is that, as a component class developer,
there are different methods for input and output ports, so that a
fitler component class, for example, can have both an "input port
connected" and an "output port connected". The `flt.utils.muxer`
component class is an example which takes advantage of this, not
having to check the port's type in its "input port connected" method
now.
* Functions to go from one type to another (private to public, self to
public, input port to port, and so on) are now `static inline` to
avoid any performance hit.
Those functions are now universally named bt_X_borrow_Y(), where `X`
is the API's prefix (for example, `private_component_class`) and `Y`
is the transformed type name (for example, `component_class`).
* The query executor API is split into private (create, query, cancel)
and public (is canceled?) parts.
A user's query method accepts a "self component class" of the
appropriate type.
* "Private connection private notification iterator" is removed in favor
of "self component input port notification iterator": you need to call
bt_self_component_port_input_notification_iterator_create() with a
self component input port (which you can only borrow from your own
self component).
Because of this, `enum bt_connection_status` is removed because it's
not needed anymore.
* `enum bt_component_status` is removed because it's not needed anymore.
Most statuses are moved to `enum bt_self_component_status` (what a
component class method returns).
* `bt_output_port_notification_iterator` is renamed to
`bt_port_output_notification_iterator` to be consistent with
`bt_self_component_port_input_notification_iterator`.
* Graph and plugin API status values are standardized.
* Precondition assertion macros are used to validate preconditions in
developer mode across the whole graph and plugin APIs.
Consequences:
* bt_plugin_get_version() returns `enum bt_property_availability`
instead of `enum bt_plugin_status`.
* Functions which return a count return `uint64_t` instead of
`int64_t`.
* Status ending with `_INVALID` are removed (not needed anymore).
* Types ending with `_UNKNOWN` are removed (not needed anymore).
* All "getting" functions in the graph/plugin APIs are removed in favor
of "borrowing" functions.
Interesting changes needed to be made to bt_connection_end() and
remove_port_by_index() to support this.
* bt_plugin_find_component_class() is removed. Let's not encourage this
because it creates a plugin object each time, whereas the recommended
approach is to create a plugin first (with bt_plugin_find() for
example), and then borrow the required component classes.
* Graph API: when an object's member is destroyed, internally, its
pointer is set to `NULL` immediately. This makes it possible to log
partial objects during destruction while keeping Valgrind's memcheck
happy.
* Generic logging is replaced by library logging in the graph and plugin
API implementations.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Wed, 21 Nov 2018 15:39:48 +0000 (10:39 -0500)]
lib: private functions: do not repeat `private` word
Some private function names look ridiculous. Because a private function
name already starts with `bt_private`, do not repeat the `private` word
elsewhere in the function name: we already know we're dealing with a
private function and private objects.
For example:
* Before this patch: bt_private_event_class_set_payload_private_field_class
* After this patch: bt_private_event_class_set_payload_field_class()
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Wed, 21 Nov 2018 13:34:20 +0000 (08:34 -0500)]
Graph API: split into private and public APIs
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Wed, 21 Nov 2018 04:55:52 +0000 (23:55 -0500)]
Trace IR and notification APIs: split into private and public APIs
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Mon, 19 Nov 2018 19:59:54 +0000 (14:59 -0500)]
bt_value_map_extend(): make base/extension objects `const`
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Mon, 19 Nov 2018 19:50:47 +0000 (14:50 -0500)]
Values API: standardize parameters and return values
Changes:
* Remove `BT_VALUE_STATUS_ERROR`: the only possible error in this API is
`BT_VALUE_STATUS_NOMEM`.
* `BT_VALUE_STATUS_CANCELED` is not considered an error: the loop did
not finish, but it was explicitly canceled by the user.
* bt_value_copy(): return by parameter (first one, like strcpy()), and
return status.
* bt_value_bool_get(), bt_value_integer_get(), bt_value_real_get(), and
bt_value_string_get(): return value directly. Those functions cannot
fail.
* bt_value_array_get_size() and bt_value_map_get_size(): return
`uint64_t`.
* bt_value_array_is_empty() and bt_value_map_is_empty(): make them
`static inline`.
* bt_value_map_extend(): return by parameter (like bt_value_copy()), and
return status.
* bt_private_value_bool_set(), bt_private_value_integer_set(), and
bt_private_value_real_set(): return `void`. Those functions cannot
fail.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Fri, 16 Nov 2018 17:59:13 +0000 (12:59 -0500)]
Values API: split into private and public APIs
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Thu, 15 Nov 2018 20:48:09 +0000 (15:48 -0500)]
Update `include/babeltrace/babeltrace.h`
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Thu, 15 Nov 2018 20:44:29 +0000 (15:44 -0500)]
Rename: bt_put(), bt_get() -> bt_object_put_ref(), bt_object_get_ref()
Because those function apply to any (shared) Babeltrace object, let's
put them under the `bt_object` namespace and make it clear what we're
putting and getting.
Also, reference counting macros are renamed:
* BT_PUT() -> BT_OBJECT_PUT_REF_AND_RESET()
* BT_MOVE() -> BT_OBJECT_MOVE_REF()
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Thu, 15 Nov 2018 20:34:32 +0000 (15:34 -0500)]
Values API: standardize function names
Make them look more like the rest of the API.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Thu, 15 Nov 2018 19:46:13 +0000 (14:46 -0500)]
Rename: "float value" -> "real value"
This is more consistent with field classes and fields.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Thu, 15 Nov 2018 19:31:08 +0000 (14:31 -0500)]
Remove unneeded `BT_VALUE_TYPE_UNKNOWN`
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Thu, 15 Nov 2018 19:28:32 +0000 (14:28 -0500)]
Rename: "field class ID" -> "field class type"
We use "type" everywhere else to hold a numeric type identifier. The
only reason we used "ID" for field classes was because they were named
"field types" before.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Philippe Proulx [Thu, 15 Nov 2018 17:22:29 +0000 (12:22 -0500)]
Rename: field type -> field class
This patch renames everything named "field type" to "field class",
including function names, variable names, file names, metadata AST
names, code comments, log messages, and more.
Since everything else in the API is named "class" rather than "type"
(event class, stream class, component class, clock class, etc.), this
makes the API more consistent and easier to document. This is also in
line with CTF 2's terminology.
API documentation, man pages, Python bindings, and some plugins are left
untouched because they will change in the future anyway.
The CTF writer still uses the "field type" terminology.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
This page took 0.055164 seconds and 5 git commands to generate.