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 uptream 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
) {
157 /* Borrow the event message's event and its class */
158 const bt_event
*event
=
159 bt_message_event_borrow_event_const(message
);
160 const bt_event_class
*event_class
= bt_event_borrow_class_const(event
);
162 /* Get the event class's name */
163 const char *name
= bt_event_class_get_name(event_class
);
165 for (uint64_t i
= 0; i
< bt_value_array_get_length(
166 distill_iter
->distill
->names_value
); i
++) {
167 const char *discard_name
= bt_value_string_get(
168 bt_value_array_borrow_element_by_index_const(
169 distill_iter
->distill
->names_value
, i
));
171 if (strcmp(name
, discard_name
) == 0) {
182 * Returns the next message to the message iterator's user.
184 * This method can fill the `messages` array with up to `capacity`
187 * To keep this example simple, we put a single message into `messages`
188 * and set `*count` to 1 (if the message iterator is not ended).
191 bt_message_iterator_class_next_method_status
distill_message_iterator_next(
192 bt_self_message_iterator
*self_message_iterator
,
193 bt_message_array_const messages
, uint64_t capacity
,
196 /* Retrieve our private data from the message iterator's user data */
197 struct distill_message_iterator
*distill_iter
=
198 bt_self_message_iterator_get_data(self_message_iterator
);
200 /* Consume a batch of messages from the upstream message iterator */
201 bt_message_array_const upstream_messages
;
202 uint64_t upstream_message_count
;
203 bt_message_iterator_next_status next_status
;
205 consume_upstream_messages
:
206 next_status
= bt_message_iterator_next(distill_iter
->message_iterator
,
207 &upstream_messages
, &upstream_message_count
);
209 /* Initialize the return status to a success */
210 bt_message_iterator_class_next_method_status status
=
211 BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK
;
213 switch (next_status
) {
214 case BT_MESSAGE_ITERATOR_NEXT_STATUS_END
:
215 /* End of iteration: put the message iterator's reference */
216 bt_message_iterator_put_ref(distill_iter
->message_iterator
);
217 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END
;
219 case BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN
:
220 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN
;
222 case BT_MESSAGE_ITERATOR_NEXT_STATUS_MEMORY_ERROR
:
223 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR
;
225 case BT_MESSAGE_ITERATOR_NEXT_STATUS_ERROR
:
226 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR
;
232 /* Output message array index */
235 /* For each consumed message */
236 for (uint64_t upstream_i
= 0; upstream_i
< upstream_message_count
;
238 /* Current message */
239 const bt_message
*upstream_message
= upstream_messages
[upstream_i
];
241 /* Check if the upstream message passes */
242 if (message_passes(distill_iter
, upstream_message
)) {
243 /* Move upstream message to output message array */
244 messages
[i
] = upstream_message
;
249 /* Discard upstream message: put its reference */
250 bt_message_put_ref(upstream_message
);
255 * We discarded all the upstream messages: get a new batch of
256 * messages, because this method _cannot_ return
257 * `BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK` and put no
258 * messages into its output message array.
260 goto consume_upstream_messages
;
272 /* Define the `distill` plugin */
275 /* Define the `theone` filter component class */
276 BT_PLUGIN_FILTER_COMPONENT_CLASS(theone
, distill_message_iterator_next
);
278 /* Set some of the `theone` filter component class's optional methods */
279 BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD(theone
, distill_initialize
);
280 BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD(theone
, distill_finalize
);
281 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD(
282 theone
, distill_message_iterator_initialize
);
283 BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD(theone
,
284 distill_message_iterator_finalize
);