7 #include <babeltrace2/babeltrace.h>
9 /* Filter component's private data */
11 /* Names of the classes of the events to discard (owned by this) */
12 const bt_value
*names_value
;
14 /* Component's input port (weak) */
15 bt_self_component_port_input
*in_port
;
19 * Initializes the filter component.
22 bt_component_class_initialize_method_status
distill_initialize(
23 bt_self_component_filter
*self_component_filter
,
24 bt_self_component_filter_configuration
*configuration
,
25 const bt_value
*params
, void *initialize_method_data
)
27 /* Allocate a private data structure */
28 struct distill
*distill
= malloc(sizeof(*distill
));
31 * Keep a reference of the `names` array value parameter so that the
32 * "next" method of a message iterator can access it to decide
33 * whether or not to discard an event message.
35 distill
->names_value
=
36 bt_value_map_borrow_entry_value_const(params
, "names");
37 bt_value_get_ref(distill
->names_value
);
39 /* Set the component's user data to our private data structure */
40 bt_self_component_set_data(
41 bt_self_component_filter_as_self_component(self_component_filter
),
45 * Add an input port named `in` to the filter component.
47 * This is needed so that this filter component can be connected to
48 * a filter or a source component. With a connected upstream
49 * component, this filter component's message iterator can create a
50 * message iterator to consume messages.
52 * Add an output port named `out` to the filter component.
54 * This is needed so that this filter component can be connected to
55 * a filter or a sink component. Once a downstream component is
56 * connected, it can create our message iterator.
58 bt_self_component_filter_add_input_port(self_component_filter
,
59 "in", NULL
, &distill
->in_port
);
60 bt_self_component_filter_add_output_port(self_component_filter
,
63 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
67 * Finalizes the filter component.
70 void distill_finalize(bt_self_component_filter
*self_component_filter
)
72 /* Retrieve our private data from the component's user data */
73 struct distill
*distill
= bt_self_component_get_data(
74 bt_self_component_filter_as_self_component(self_component_filter
));
76 /* Put all references */
77 bt_value_put_ref(distill
->names_value
);
79 /* Free the allocated structure */
83 /* Message iterator's private data */
84 struct distill_message_iterator
{
85 /* (Weak) link to the component's private data */
86 struct distill
*distill
;
88 /* Upstream message iterator (owned by this) */
89 bt_message_iterator
*message_iterator
;
93 * Initializes the message iterator.
96 bt_message_iterator_class_initialize_method_status
97 distill_message_iterator_initialize(
98 bt_self_message_iterator
*self_message_iterator
,
99 bt_self_message_iterator_configuration
*configuration
,
100 bt_self_component_port_output
*self_port
)
102 /* Allocate a private data structure */
103 struct distill_message_iterator
*distill_iter
=
104 malloc(sizeof(*distill_iter
));
106 /* Retrieve the component's private data from its user data */
107 struct distill
*distill
= bt_self_component_get_data(
108 bt_self_message_iterator_borrow_component(self_message_iterator
));
110 /* Keep a link to the component's private data */
111 distill_iter
->distill
= distill
;
113 /* Create the upstream message iterator */
114 bt_message_iterator_create_from_message_iterator(self_message_iterator
,
115 distill
->in_port
, &distill_iter
->message_iterator
);
117 /* Set the message iterator's user data to our private data structure */
118 bt_self_message_iterator_set_data(self_message_iterator
, distill_iter
);
120 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK
;
124 * Finalizes the message iterator.
127 void distill_message_iterator_finalize(
128 bt_self_message_iterator
*self_message_iterator
)
130 /* Retrieve our private data from the message iterator's user data */
131 struct distill_message_iterator
*distill_iter
=
132 bt_self_message_iterator_get_data(self_message_iterator
);
134 /* Free the allocated structure */
139 * Returns `true` if `message` passes, that is, one of:
141 * * It's not an event message.
142 * * The event message does not need to be discarded based on its event
146 bool message_passes(struct distill_message_iterator
*distill_iter
,
147 const bt_message
*message
)
151 /* Move as is if it's not an event message */
152 if (bt_message_get_type(message
) != BT_MESSAGE_TYPE_EVENT
) {
156 /* Borrow the event message's event and its class */
157 const bt_event
*event
=
158 bt_message_event_borrow_event_const(message
);
159 const bt_event_class
*event_class
= bt_event_borrow_class_const(event
);
161 /* Get the event class's name */
162 const char *name
= bt_event_class_get_name(event_class
);
164 for (uint64_t i
= 0; i
< bt_value_array_get_length(
165 distill_iter
->distill
->names_value
); i
++) {
166 const char *discard_name
= bt_value_string_get(
167 bt_value_array_borrow_element_by_index_const(
168 distill_iter
->distill
->names_value
, i
));
170 if (strcmp(name
, discard_name
) == 0) {
181 * Returns the next message to the message iterator's user.
183 * This method can fill the `messages` array with up to `capacity`
186 * To keep this example simple, we put a single message into `messages`
187 * and set `*count` to 1 (if the message iterator is not ended).
190 bt_message_iterator_class_next_method_status
distill_message_iterator_next(
191 bt_self_message_iterator
*self_message_iterator
,
192 bt_message_array_const messages
, uint64_t capacity
,
195 /* Retrieve our private data from the message iterator's user data */
196 struct distill_message_iterator
*distill_iter
=
197 bt_self_message_iterator_get_data(self_message_iterator
);
199 /* Consume a batch of messages from the upstream message iterator */
200 bt_message_array_const upstream_messages
;
201 uint64_t upstream_message_count
;
202 bt_message_iterator_next_status next_status
;
204 consume_upstream_messages
:
205 next_status
= bt_message_iterator_next(distill_iter
->message_iterator
,
206 &upstream_messages
, &upstream_message_count
);
208 /* Initialize the return status to a success */
209 bt_message_iterator_class_next_method_status status
=
210 BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK
;
212 switch (next_status
) {
213 case BT_MESSAGE_ITERATOR_NEXT_STATUS_END
:
214 /* End of iteration: put the message iterator's reference */
215 bt_message_iterator_put_ref(distill_iter
->message_iterator
);
216 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END
;
218 case BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN
:
219 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN
;
221 case BT_MESSAGE_ITERATOR_NEXT_STATUS_MEMORY_ERROR
:
222 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR
;
224 case BT_MESSAGE_ITERATOR_NEXT_STATUS_ERROR
:
225 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR
;
231 /* Output message array index */
234 /* For each consumed message */
235 for (uint64_t upstream_i
= 0; upstream_i
< upstream_message_count
;
237 /* Current message */
238 const bt_message
*upstream_message
= upstream_messages
[upstream_i
];
240 /* Check if the upstream message passes */
241 if (message_passes(distill_iter
, upstream_message
)) {
242 /* Move upstream message to output message array */
243 messages
[i
] = upstream_message
;
248 /* Discard upstream message: put its reference */
249 bt_message_put_ref(upstream_message
);
254 * We discarded all the upstream messages: get a new batch of
255 * messages, because this method _cannot_ return
256 * `BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK` and put no
257 * messages into its output message array.
259 goto consume_upstream_messages
;
271 /* Define the `distill` plugin */
274 /* Define the `theone` filter component class */
275 BT_PLUGIN_FILTER_COMPONENT_CLASS(theone
, distill_message_iterator_next
);
277 /* Set some of the `theone` filter component class's optional methods */
278 BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD(theone
, distill_initialize
);
279 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD(theone
, distill_finalize
);
280 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD(
281 theone
, distill_message_iterator_initialize
);
282 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD(theone
,
283 distill_message_iterator_finalize
);