Babeltrace 2 C API  2.0.0
Open-source trace manipulation framework
Simple filter component class

This example shows a basic filter component class packaged as a shared object plugin.

The name of the plugin is distill and the name of the filter component class is theone. Therefore the component class is identified in the babeltrace2 command-line tool as filter.distill.theone.

A filter.distill.theone component removes specific event messages from a stream based on their event class's name.

A filter.distill.theone component accepts a single initialization parameter, names, which is an array value of string values. The array value contains the names of the classes of the events to discard.

A filter.distill.theone component creates a single input port named in and a single output port named out.

To simplify this example, a filter.distill.theone component is not resilient and needs a valid input and valid initialization parameters. The code also doesn't check the return status codes of API functions for simplicity, but you must check them in production code.

The filter component class implementation and the shared object plugin macros are in the same file, distill.c:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdbool.h>
#include <babeltrace2/babeltrace.h>
/* Filter component's private data */
struct distill {
/* Names of the classes of the events to discard (owned by this) */
const bt_value *names_value;
/* Component's input port (weak) */
};
/*
* Initializes the filter component.
*/
static
bt_self_component_filter *self_component_filter,
const bt_value *params, void *initialize_method_data)
{
/* Allocate a private data structure */
struct distill *distill = malloc(sizeof(*distill));
/*
* Keep a reference of the `names` array value parameter so that the
* "next" method of a message iterator can access it to decide
* whether or not to discard an event message.
*/
distill->names_value =
bt_value_get_ref(distill->names_value);
/* Set the component's user data to our private data structure */
distill);
/*
* Add an input port named `in` to the filter component.
*
* This is needed so that this filter component can be connected to
* a filter or a source component. With a connected upstream
* component, this filter component's message iterator can create a
* message iterator to consume messages.
*
* Add an output port named `out` to the filter component.
*
* This is needed so that this filter component can be connected to
* a filter or a sink component. Once a downstream component is
* connected, it can create our message iterator.
*/
"in", NULL, &distill->in_port);
"out", NULL, NULL);
}
/*
* Finalizes the filter component.
*/
static
void distill_finalize(bt_self_component_filter *self_component_filter)
{
/* Retrieve our private data from the component's user data */
struct distill *distill = bt_self_component_get_data(
/* Put all references */
bt_value_put_ref(distill->names_value);
/* Free the allocated structure */
free(distill);
}
/* Message iterator's private data */
struct distill_message_iterator {
/* (Weak) link to the component's private data */
struct distill *distill;
/* Upstream message iterator (owned by this) */
bt_message_iterator *message_iterator;
};
/*
* Initializes the message iterator.
*/
static
distill_message_iterator_initialize(
bt_self_message_iterator *self_message_iterator,
{
/* Allocate a private data structure */
struct distill_message_iterator *distill_iter =
malloc(sizeof(*distill_iter));
/* Retrieve the component's private data from its user data */
struct distill *distill = bt_self_component_get_data(
/* Keep a link to the component's private data */
distill_iter->distill = distill;
/* Create the uptream message iterator */
distill->in_port, &distill_iter->message_iterator);
/* Set the message iterator's user data to our private data structure */
bt_self_message_iterator_set_data(self_message_iterator, distill_iter);
}
/*
* Finalizes the message iterator.
*/
static
void distill_message_iterator_finalize(
bt_self_message_iterator *self_message_iterator)
{
/* Retrieve our private data from the message iterator's user data */
struct distill_message_iterator *distill_iter =
bt_self_message_iterator_get_data(self_message_iterator);
/* Free the allocated structure */
free(distill_iter);
}
/*
* Returns `true` if `message` passes, that is, one of:
*
* * It's not an event message.
* * The event message does not need to be discarded based on its event
* class's name.
*/
static
bool message_passes(struct distill_message_iterator *distill_iter,
const bt_message *message)
{
bool passes = true;
/* Move as is if it's not an event message */
passes = false;
goto end;
}
/* Borrow the event message's event and its class */
const bt_event *event =
const bt_event_class *event_class = bt_event_borrow_class_const(event);
/* Get the event class's name */
const char *name = bt_event_class_get_name(event_class);
for (uint64_t i = 0; i < bt_value_array_get_length(
distill_iter->distill->names_value); i++) {
const char *discard_name = bt_value_string_get(
distill_iter->distill->names_value, i));
if (strcmp(name, discard_name) == 0) {
passes = false;
goto end;
}
}
end:
return passes;
}
/*
* Returns the next message to the message iterator's user.
*
* This method can fill the `messages` array with up to `capacity`
* messages.
*
* To keep this example simple, we put a single message into `messages`
* and set `*count` to 1 (if the message iterator is not ended).
*/
static
bt_message_iterator_class_next_method_status distill_message_iterator_next(
bt_self_message_iterator *self_message_iterator,
bt_message_array_const messages, uint64_t capacity,
uint64_t *count)
{
/* Retrieve our private data from the message iterator's user data */
struct distill_message_iterator *distill_iter =
bt_self_message_iterator_get_data(self_message_iterator);
/* Consume a batch of messages from the upstream message iterator */
bt_message_array_const upstream_messages;
uint64_t upstream_message_count;
consume_upstream_messages:
next_status = bt_message_iterator_next(distill_iter->message_iterator,
&upstream_messages, &upstream_message_count);
/* Initialize the return status to a success */
switch (next_status) {
/* End of iteration: put the message iterator's reference */
bt_message_iterator_put_ref(distill_iter->message_iterator);
goto end;
goto end;
goto end;
goto end;
default:
break;
}
/* Output message array index */
uint64_t i = 0;
/* For each consumed message */
for (uint64_t upstream_i = 0; upstream_i < upstream_message_count;
upstream_i++) {
/* Current message */
const bt_message *upstream_message = upstream_messages[upstream_i];
/* Check if the upstream message passes */
if (message_passes(distill_iter, upstream_message)) {
/* Move upstream message to output message array */
messages[i] = upstream_message;
i++;
continue;
}
/* Discard upstream message: put its reference */
bt_message_put_ref(upstream_message);
}
if (i == 0) {
/*
* We discarded all the upstream messages: get a new batch of
* messages, because this method _cannot_ return
* `BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK` and put no
* messages into its output message array.
*/
goto consume_upstream_messages;
}
*count = i;
end:
return status;
}
/* Mandatory */
/* Define the `distill` plugin */
BT_PLUGIN(distill);
/* Define the `theone` filter component class */
BT_PLUGIN_FILTER_COMPONENT_CLASS(theone, distill_message_iterator_next);
/* Set some of the `theone` filter component class's optional methods */
theone, distill_message_iterator_initialize);
distill_message_iterator_finalize);

As per the Compile and link a Babeltrace 2 shared object plugin guide, you can build the shared object plugin as such:

$ cc distill.c -fPIC -c $(pkg-config --cflags babeltrace2)
$ ld distill.o -o distill.so -shared $(pkg-config --libs babeltrace2)

With the babeltrace2 tool, you can use a filter.distill.theone component, reading a CTF trace (see babeltrace2-source.ctf.fs(7)) for example:

$ babeltrace2 --plugin-path=. /path/to/ctf/trace \
--component=filter.distill.theone \
--params='names=["sched_switch", "rcu_utilization", "kmem_kfree"]'
BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK
Success.
Definition: message-iterator-class.h:736
bt_value
struct bt_value bt_value
Value.
Definition: types.h:107
bt_self_message_iterator
struct bt_self_message_iterator bt_self_message_iterator
Self message iterator.
Definition: types.h:100
BT_PLUGIN_FILTER_COMPONENT_CLASS
#define BT_PLUGIN_FILTER_COMPONENT_CLASS(_name, _message_iterator_class_next_method)
Alias of BT_PLUGIN_FILTER_COMPONENT_CLASS_WITH_ID() with the _plugin_id parameter set to auto,...
Definition: plugin-dev.h:839
bt_self_component_filter_add_output_port
bt_self_component_add_port_status bt_self_component_filter_add_output_port(bt_self_component_filter *self_component, const char *name, void *user_data, bt_self_component_port_output **self_component_port)
Adds an output port named name and having the user data user_data to the filter component self_compon...
bt_self_component_set_data
void bt_self_component_set_data(bt_self_component *self_component, void *user_data)
Sets the user data of the component self_component to data.
bt_value_array_get_length
uint64_t bt_value_array_get_length(const bt_value *value)
Returns the length of the array value value.
BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN
Try again.
Definition: message-iterator.h:400
bt_self_component_get_data
void * bt_self_component_get_data(const bt_self_component *self_component)
Returns the user data of the component self_component.
bt_message_iterator_class_initialize_method_status
bt_message_iterator_class_initialize_method_status
Status codes for bt_message_iterator_class_initialize_method.
Definition: message-iterator-class.h:674
bt_component_class_initialize_method_status
bt_component_class_initialize_method_status
Status codes for bt_component_class_source_initialize_method, bt_component_class_filter_initialize_me...
Definition: component-class-dev.h:881
BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD
#define BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD(_name, _method)
Alias of BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_WITH_ID() with the...
Definition: plugin-dev.h:1923
bt_self_component_filter_configuration
struct bt_self_component_filter_configuration bt_self_component_filter_configuration
Self filter component configuration.
Definition: types.h:91
bt_value_get_ref
void bt_value_get_ref(const bt_value *value)
Increments the reference count of the value value.
bt_message_iterator
struct bt_message_iterator bt_message_iterator
Message iterator.
Definition: types.h:72
BT_PLUGIN_MODULE
#define BT_PLUGIN_MODULE()
Defines a plugin module.
Definition: plugin-dev.h:338
BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN
Try again.
Definition: message-iterator-class.h:748
BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END
End of iteration.
Definition: message-iterator-class.h:742
bt_self_component_port_output
struct bt_self_component_port_output bt_self_component_port_output
Self component output port.
Definition: types.h:95
bt_message_iterator_create_from_message_iterator
bt_message_iterator_create_from_message_iterator_status bt_message_iterator_create_from_message_iterator(bt_self_message_iterator *self_message_iterator, bt_self_component_port_input *port, bt_message_iterator **message_iterator)
Creates a message iterator on the input port port from another message iterator self_message_iterator...
bt_self_component_filter_as_self_component
static bt_self_component * bt_self_component_filter_as_self_component(bt_self_component_filter *self_component)
Upcasts the self filter component self_component to the common bt_self_component type.
Definition: self-component.h:846
BT_MESSAGE_TYPE_EVENT
Event message.
Definition: message.h:997
bt_message_array_const
const bt_message ** bt_message_array_const
Array of constant messages.
Definition: types.h:196
BT_MESSAGE_ITERATOR_NEXT_STATUS_MEMORY_ERROR
Out of memory.
Definition: message-iterator.h:406
bt_value_array_borrow_element_by_index_const
const bt_value * bt_value_array_borrow_element_by_index_const(const bt_value *value, uint64_t index)
Borrows the element at index index from the array value value (const version).
BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD
#define BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD(_name, _method)
Alias of BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD_WITH_ID() with the _plugin_id parameter s...
Definition: plugin-dev.h:1785
bt_message_iterator_next
bt_message_iterator_next_status bt_message_iterator_next(bt_message_iterator *message_iterator, bt_message_array_const *messages, uint64_t *count)
Returns the next messages of the message iterator message_iterator into the *messages array of size *...
bt_message_iterator_put_ref
void bt_message_iterator_put_ref(const bt_message_iterator *message_iterator)
Decrements the reference count of the message iterator message_iterator.
bt_event_class_get_name
const char * bt_event_class_get_name(const bt_event_class *event_class)
Returns the name of the event class event_class.
BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD
#define BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD(_name, _method)
Alias of BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD_WITH_ID() with the _plugin_id parameter set...
Definition: plugin-dev.h:1694
bt_value_map_borrow_entry_value_const
const bt_value * bt_value_map_borrow_entry_value_const(const bt_value *value, const char *key)
Borrows the value of the entry with the key key in the map value value (const version).
bt_event_borrow_class_const
const bt_event_class * bt_event_borrow_class_const(const bt_event *event)
Borrows the class of the event event (const version).
BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR
Out of memory.
Definition: message-iterator-class.h:754
bt_event
struct bt_event bt_event
Event.
Definition: types.h:50
bt_message_event_borrow_event_const
const bt_event * bt_message_event_borrow_event_const(const bt_message *message)
Borrows the event of the event message message (const version).
bt_self_message_iterator_borrow_component
bt_self_component * bt_self_message_iterator_borrow_component(bt_self_message_iterator *self_message_iterator)
Borrows the component which provides the message iterator self_message_iterator.
BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
Success.
Definition: component-class-dev.h:886
bt_self_message_iterator_get_data
void * bt_self_message_iterator_get_data(const bt_self_message_iterator *self_message_iterator)
Returns the user data of the message iterator self_message_iterator.
bt_event_class
struct bt_event_class bt_event_class
Event class.
Definition: types.h:51
bt_message_iterator_next_status
bt_message_iterator_next_status
Status code for bt_message_iterator_next().
Definition: message-iterator.h:383
BT_MESSAGE_ITERATOR_NEXT_STATUS_ERROR
Other error.
Definition: message-iterator.h:412
BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD
#define BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD(_name, _method)
Alias of BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD_WITH_ID() with the _...
Definition: plugin-dev.h:1877
bt_self_component_filter
struct bt_self_component_filter bt_self_component_filter
Self filter component.
Definition: types.h:90
bt_message_put_ref
void bt_message_put_ref(const bt_message *message)
Decrements the reference count of the message message.
BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK
Success.
Definition: message-iterator-class.h:679
BT_MESSAGE_ITERATOR_NEXT_STATUS_END
End of iteration.
Definition: message-iterator.h:394
BT_PLUGIN
#define BT_PLUGIN(_name)
Alias of BT_PLUGIN_WITH_ID() with the _id parameter set to auto.
Definition: plugin-dev.h:426
bt_message_get_type
bt_message_type bt_message_get_type(const bt_message *message)
Returns the type enumerator of the message message.
bt_value_string_get
const char * bt_value_string_get(const bt_value *value)
Returns the raw value of the string value value.
bt_self_component_port_input
struct bt_self_component_port_input bt_self_component_port_input
Self component input port.
Definition: types.h:93
bt_message
struct bt_message bt_message
Message.
Definition: types.h:71
bt_message_iterator_class_next_method_status
bt_message_iterator_class_next_method_status
Status codes for bt_message_iterator_class_next_method.
Definition: message-iterator-class.h:731
bt_self_message_iterator_set_data
void bt_self_message_iterator_set_data(bt_self_message_iterator *self_message_iterator, void *user_data)
Sets the user data of the message iterator self_message_iterator to data.
BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR
User error.
Definition: message-iterator-class.h:760
bt_value_put_ref
void bt_value_put_ref(const bt_value *value)
Decrements the reference count of the value value.
bt_self_message_iterator_configuration
struct bt_self_message_iterator_configuration bt_self_message_iterator_configuration
Self message iterator configuration.
Definition: types.h:101
bt_self_component_filter_add_input_port
bt_self_component_add_port_status bt_self_component_filter_add_input_port(bt_self_component_filter *self_component, const char *name, void *user_data, bt_self_component_port_input **self_component_port)
Adds an input port named name and having the user data user_data to the filter component self_compone...