metababel 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +60 -0
- data/bin/metababel +233 -0
- data/lib/metababel/bt2_generator_utils.rb +38 -0
- data/lib/metababel/bt2_stream_classes_generator.rb +716 -0
- data/lib/metababel/bt2_values_generator.rb +132 -0
- data/lib/metababel/version.rb +3 -0
- data/lib/metababel.rb +4 -0
- data/template/component.c.erb +69 -0
- data/template/component.h.erb +160 -0
- data/template/downstream.c.erb +119 -0
- data/template/downstream.h.erb +34 -0
- data/template/filter.c.erb +400 -0
- data/template/metababel.h.erb +7 -0
- data/template/sink.c.erb +166 -0
- data/template/source.c.erb +200 -0
- data/template/upstream.c.erb +47 -0
- data/template/upstream.h.erb +22 -0
- metadata +62 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
#include "uthash.h"
|
|
2
|
+
#include "utlist.h"
|
|
3
|
+
#include <babeltrace2/babeltrace.h>
|
|
4
|
+
#include <metababel/metababel.h>
|
|
5
|
+
#include <stdio.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
|
|
8
|
+
/* Loosely inspired by
|
|
9
|
+
* https://babeltrace.org/docs/v2.0/libbabeltrace2/example-simple-flt-cmp-cls.html
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
static const char *get_port_name(uint64_t current) {
|
|
13
|
+
int num_len = snprintf(NULL, 0, "in%ld", current);
|
|
14
|
+
char *result = (char *)malloc(num_len + 1);
|
|
15
|
+
sprintf(result, "in%ld", current);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* Handle Upstream Messages
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
static inline bt_message_iterator_class_next_method_status
|
|
24
|
+
filter_message_iterator_next_initializing(
|
|
25
|
+
bt_self_message_iterator *self_message_iterator,
|
|
26
|
+
bt_message_array_const messages, uint64_t capacity, uint64_t *count) {
|
|
27
|
+
/* Retrieve our private data from the message iterator's user data */
|
|
28
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
29
|
+
bt_self_message_iterator_get_data(self_message_iterator);
|
|
30
|
+
|
|
31
|
+
/* Call Initialize user callback */
|
|
32
|
+
btx_call_callbacks_initialize_usr_data(
|
|
33
|
+
message_iterator_private_data->common_data,
|
|
34
|
+
&message_iterator_private_data->common_data->usr_data);
|
|
35
|
+
/* Call read callbacks */
|
|
36
|
+
btx_call_callbacks_read_params(
|
|
37
|
+
message_iterator_private_data->common_data,
|
|
38
|
+
message_iterator_private_data->common_data->usr_data,
|
|
39
|
+
message_iterator_private_data->common_data->btx_params);
|
|
40
|
+
|
|
41
|
+
// We need to transition in the procesing state
|
|
42
|
+
message_iterator_private_data->state = BTX_FILTER_STATE_PROCESSING;
|
|
43
|
+
if (message_iterator_private_data->queue)
|
|
44
|
+
message_iterator_private_data->processing_state =
|
|
45
|
+
BTX_FILTER_PROCESSING_STATE_SENDING;
|
|
46
|
+
|
|
47
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static inline bt_message_iterator_class_next_method_status
|
|
51
|
+
filter_message_iterator_next_processing_sending(
|
|
52
|
+
bt_self_message_iterator *self_message_iterator,
|
|
53
|
+
bt_message_array_const messages, uint64_t capacity, uint64_t *count) {
|
|
54
|
+
/* Retrieve our private data from the message iterator's user data */
|
|
55
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
56
|
+
bt_self_message_iterator_get_data(self_message_iterator);
|
|
57
|
+
|
|
58
|
+
btx_downstream_move_messages(message_iterator_private_data, messages,
|
|
59
|
+
capacity, count);
|
|
60
|
+
|
|
61
|
+
if (!message_iterator_private_data->queue) {
|
|
62
|
+
message_iterator_private_data->processing_state =
|
|
63
|
+
BTX_FILTER_PROCESSING_STATE_READING;
|
|
64
|
+
}
|
|
65
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static inline bt_message_iterator_class_next_method_status
|
|
69
|
+
filter_message_iterator_next_processing_reading(
|
|
70
|
+
bt_self_message_iterator *self_message_iterator,
|
|
71
|
+
bt_message_array_const messages, uint64_t capacity, uint64_t *count) {
|
|
72
|
+
/* Retrieve our private data from the message iterator's user data */
|
|
73
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
74
|
+
bt_self_message_iterator_get_data(self_message_iterator);
|
|
75
|
+
|
|
76
|
+
common_data_t *common_data = message_iterator_private_data->common_data;
|
|
77
|
+
|
|
78
|
+
/* Consume a batch of messages from the upstream message iterator */
|
|
79
|
+
uint64_t upstream_message_count;
|
|
80
|
+
bt_message_array_const upstream_messages;
|
|
81
|
+
|
|
82
|
+
bt_message_iterator_next_status next_status = bt_message_iterator_next(
|
|
83
|
+
message_iterator_private_data->head_mi->message_iterator,
|
|
84
|
+
&upstream_messages, &upstream_message_count);
|
|
85
|
+
|
|
86
|
+
/* We cannot have any message left in the downstream queue
|
|
87
|
+
* Hence it's safe to pass any error messages downstream.
|
|
88
|
+
*/
|
|
89
|
+
switch (next_status) {
|
|
90
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_END:
|
|
91
|
+
/* We are setting the state, so this function will never being call twice */
|
|
92
|
+
bt_message_iterator_put_ref(
|
|
93
|
+
message_iterator_private_data->head_mi->message_iterator);
|
|
94
|
+
|
|
95
|
+
CDL_DELETE(message_iterator_private_data->head_mi,
|
|
96
|
+
message_iterator_private_data->head_mi);
|
|
97
|
+
if (!message_iterator_private_data->head_mi) {
|
|
98
|
+
/* Call Finalize user callback */
|
|
99
|
+
btx_call_callbacks_finalize_usr_data(
|
|
100
|
+
message_iterator_private_data->common_data,
|
|
101
|
+
message_iterator_private_data->common_data->usr_data);
|
|
102
|
+
message_iterator_private_data->state = BTX_FILTER_STATE_FINALIZING;
|
|
103
|
+
message_iterator_private_data->processing_state =
|
|
104
|
+
BTX_FILTER_PROCESSING_STATE_FINISHED;
|
|
105
|
+
}
|
|
106
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
|
|
107
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN:
|
|
108
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
|
|
109
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_MEMORY_ERROR:
|
|
110
|
+
message_iterator_private_data->state = BTX_FILTER_STATE_ERROR;
|
|
111
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR;
|
|
112
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_ERROR:
|
|
113
|
+
message_iterator_private_data->state = BTX_FILTER_STATE_ERROR;
|
|
114
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
|
|
115
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_OK:
|
|
116
|
+
break;
|
|
117
|
+
default:
|
|
118
|
+
message_iterator_private_data->state = BTX_FILTER_STATE_ERROR;
|
|
119
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* For each consumed message */
|
|
123
|
+
for (uint64_t upstream_i = 0; upstream_i < upstream_message_count;
|
|
124
|
+
upstream_i++) {
|
|
125
|
+
/* Current message */
|
|
126
|
+
const bt_message *upstream_message = upstream_messages[upstream_i];
|
|
127
|
+
/* Move as is if it's not an event message */
|
|
128
|
+
if (bt_message_get_type(upstream_message) != BT_MESSAGE_TYPE_EVENT) {
|
|
129
|
+
bt_message_put_ref(upstream_message);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
/* Borrow the event message's event and its class */
|
|
133
|
+
const bt_event *event =
|
|
134
|
+
bt_message_event_borrow_event_const(upstream_message);
|
|
135
|
+
const bt_event_class *event_class = bt_event_borrow_class_const(event);
|
|
136
|
+
|
|
137
|
+
/* Call dispatcher or forward message downstream */
|
|
138
|
+
name_to_dispatcher_t *s = NULL;
|
|
139
|
+
const char *class_name = bt_event_class_get_name(event_class);
|
|
140
|
+
HASH_FIND_STR(common_data->name_to_dispatcher, class_name, s);
|
|
141
|
+
if (s) {
|
|
142
|
+
(*((dispatcher_t(*))(s->dispatcher)))(s->callbacks, common_data, event);
|
|
143
|
+
/* The message have been consumed, we can discard it */
|
|
144
|
+
bt_message_put_ref(upstream_message);
|
|
145
|
+
} else {
|
|
146
|
+
btx_downstream_push_message(message_iterator_private_data,
|
|
147
|
+
upstream_message);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Round Robin between Upstream MessageIterator */
|
|
152
|
+
message_iterator_private_data->head_mi =
|
|
153
|
+
message_iterator_private_data->head_mi->next;
|
|
154
|
+
|
|
155
|
+
if (message_iterator_private_data->queue) {
|
|
156
|
+
message_iterator_private_data->processing_state =
|
|
157
|
+
BTX_FILTER_PROCESSING_STATE_SENDING;
|
|
158
|
+
/* optimization */
|
|
159
|
+
return filter_message_iterator_next_processing_sending(
|
|
160
|
+
self_message_iterator, messages, capacity, count);
|
|
161
|
+
} else
|
|
162
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_AGAIN;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static inline bt_message_iterator_class_next_method_status
|
|
166
|
+
filter_message_iterator_next_processing(
|
|
167
|
+
bt_self_message_iterator *self_message_iterator,
|
|
168
|
+
bt_message_array_const messages, uint64_t capacity, uint64_t *count) {
|
|
169
|
+
/* Retrieve our private data from the message iterator's user data */
|
|
170
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
171
|
+
bt_self_message_iterator_get_data(self_message_iterator);
|
|
172
|
+
|
|
173
|
+
switch (message_iterator_private_data->processing_state) {
|
|
174
|
+
case BTX_FILTER_PROCESSING_STATE_READING:
|
|
175
|
+
return filter_message_iterator_next_processing_reading(
|
|
176
|
+
self_message_iterator, messages, capacity, count);
|
|
177
|
+
case BTX_FILTER_PROCESSING_STATE_SENDING:
|
|
178
|
+
return filter_message_iterator_next_processing_sending(
|
|
179
|
+
self_message_iterator, messages, capacity, count);
|
|
180
|
+
case BTX_FILTER_PROCESSING_STATE_FINISHED:
|
|
181
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
|
|
182
|
+
default:
|
|
183
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static inline bt_message_iterator_class_next_method_status
|
|
188
|
+
filter_message_iterator_next_finalizing(
|
|
189
|
+
bt_self_message_iterator *self_message_iterator,
|
|
190
|
+
bt_message_array_const messages, uint64_t capacity, uint64_t *count) {
|
|
191
|
+
/* Retrieve our private data from the message iterator's user data */
|
|
192
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
193
|
+
bt_self_message_iterator_get_data(self_message_iterator);
|
|
194
|
+
|
|
195
|
+
// assert(message_iterator_private_data->processing_state ==
|
|
196
|
+
// BTX_FILTER_PROCESSING_STATE_FINISHED);
|
|
197
|
+
if (!message_iterator_private_data->queue) {
|
|
198
|
+
message_iterator_private_data->state = BTX_FILTER_STATE_FINISHED;
|
|
199
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
btx_downstream_move_messages(message_iterator_private_data, messages,
|
|
203
|
+
capacity, count);
|
|
204
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
static bt_message_iterator_class_next_method_status
|
|
208
|
+
filter_message_iterator_next(bt_self_message_iterator *self_message_iterator,
|
|
209
|
+
bt_message_array_const messages, uint64_t capacity,
|
|
210
|
+
uint64_t *count) {
|
|
211
|
+
|
|
212
|
+
/* Retrieve our private data from the message iterator's user data */
|
|
213
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
214
|
+
bt_self_message_iterator_get_data(self_message_iterator);
|
|
215
|
+
|
|
216
|
+
switch (message_iterator_private_data->state) {
|
|
217
|
+
case BTX_FILTER_STATE_INITIALIZING:
|
|
218
|
+
return filter_message_iterator_next_initializing(self_message_iterator,
|
|
219
|
+
messages, capacity, count);
|
|
220
|
+
case BTX_FILTER_STATE_PROCESSING:
|
|
221
|
+
return filter_message_iterator_next_processing(self_message_iterator,
|
|
222
|
+
messages, capacity, count);
|
|
223
|
+
case BTX_FILTER_STATE_FINALIZING:
|
|
224
|
+
return filter_message_iterator_next_finalizing(self_message_iterator,
|
|
225
|
+
messages, capacity, count);
|
|
226
|
+
case BTX_FILTER_STATE_FINISHED:
|
|
227
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_END;
|
|
228
|
+
default:
|
|
229
|
+
return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_ERROR;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/*
|
|
234
|
+
* Initializes the filter component.
|
|
235
|
+
*/
|
|
236
|
+
static bt_component_class_initialize_method_status
|
|
237
|
+
filter_initialize(bt_self_component_filter *self_component_filter,
|
|
238
|
+
bt_self_component_filter_configuration *configuration,
|
|
239
|
+
const bt_value *params, void *initialize_method_data) {
|
|
240
|
+
|
|
241
|
+
/* Allocate a private data structure */
|
|
242
|
+
common_data_t *common_data = calloc(1, sizeof(common_data_t));
|
|
243
|
+
common_data->params = params;
|
|
244
|
+
// Read parameters
|
|
245
|
+
btx_populate_params(common_data);
|
|
246
|
+
bt_value_get_ref(common_data->params);
|
|
247
|
+
|
|
248
|
+
/* Register User Callbacks */
|
|
249
|
+
btx_register_usr_callbacks((void *)common_data);
|
|
250
|
+
|
|
251
|
+
/* Set the component's user data to our private data structure */
|
|
252
|
+
bt_self_component_set_data(
|
|
253
|
+
bt_self_component_filter_as_self_component(self_component_filter),
|
|
254
|
+
common_data);
|
|
255
|
+
|
|
256
|
+
/*
|
|
257
|
+
* Add an input port named `in` to the filter component.
|
|
258
|
+
*
|
|
259
|
+
* This is needed so that this filter component can be connected to
|
|
260
|
+
* a filter or a source component. With a connected upstream
|
|
261
|
+
* component, this filter component's message iterator can create a
|
|
262
|
+
* message iterator to consume messages.
|
|
263
|
+
*
|
|
264
|
+
* Add an output port named `out` to the filter component.
|
|
265
|
+
*
|
|
266
|
+
* This is needed so that this filter component can be connected to
|
|
267
|
+
* a filter or a sink component. Once a downstream component is
|
|
268
|
+
* connected, it can create our message iterator.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
common_data->component =
|
|
272
|
+
bt_self_component_filter_as_component_filter(self_component_filter);
|
|
273
|
+
|
|
274
|
+
const uint64_t current =
|
|
275
|
+
bt_component_filter_get_input_port_count(common_data->component);
|
|
276
|
+
|
|
277
|
+
bt_self_component_filter_add_input_port(self_component_filter,
|
|
278
|
+
get_port_name(current), NULL, NULL);
|
|
279
|
+
|
|
280
|
+
bt_self_component_filter_add_output_port(self_component_filter, "out", NULL,
|
|
281
|
+
NULL);
|
|
282
|
+
|
|
283
|
+
/* Create message that will be used by the filter */
|
|
284
|
+
bt_self_component *self_component =
|
|
285
|
+
bt_self_component_filter_as_self_component(self_component_filter);
|
|
286
|
+
/* Create a `trace_class` and all the children classes (stream and events) */
|
|
287
|
+
bt_trace_class *trace_class =
|
|
288
|
+
btx_downstream_trace_class_create_rec(self_component);
|
|
289
|
+
/* Instantiate a `downstream_trace` of `trace_class` and all the children
|
|
290
|
+
* stream */
|
|
291
|
+
common_data->downstream_trace = btx_downstream_trace_create_rec(trace_class);
|
|
292
|
+
return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
bt_component_class_port_connected_method_status
|
|
296
|
+
filter_input_port_connected(bt_self_component_filter *self_comp,
|
|
297
|
+
bt_self_component_port_input *self_port,
|
|
298
|
+
const bt_port_output *other_port) {
|
|
299
|
+
const uint64_t current = bt_component_filter_get_input_port_count(
|
|
300
|
+
bt_self_component_filter_as_component_filter(self_comp));
|
|
301
|
+
bt_self_component_filter_add_input_port(self_comp, get_port_name(current),
|
|
302
|
+
NULL, NULL);
|
|
303
|
+
return BT_COMPONENT_CLASS_PORT_CONNECTED_METHOD_STATUS_OK;
|
|
304
|
+
}
|
|
305
|
+
/*
|
|
306
|
+
* Initializes the message iterator.
|
|
307
|
+
*/
|
|
308
|
+
static bt_message_iterator_class_initialize_method_status
|
|
309
|
+
filter_message_iterator_initialize(
|
|
310
|
+
bt_self_message_iterator *self_message_iterator,
|
|
311
|
+
bt_self_message_iterator_configuration *configuration,
|
|
312
|
+
bt_self_component_port_output *self_port) {
|
|
313
|
+
/* Allocate a private data structure */
|
|
314
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
315
|
+
calloc(1, sizeof(btx_message_iterator_t));
|
|
316
|
+
|
|
317
|
+
/* Retrieve the component's private data from its user data */
|
|
318
|
+
common_data_t *common_data = bt_self_component_get_data(
|
|
319
|
+
bt_self_message_iterator_borrow_component(self_message_iterator));
|
|
320
|
+
|
|
321
|
+
/* Save a link to the self_message_iterator */
|
|
322
|
+
common_data->self_message_iterator = self_message_iterator;
|
|
323
|
+
|
|
324
|
+
/* Keep a link to the component's private data */
|
|
325
|
+
message_iterator_private_data->common_data = common_data;
|
|
326
|
+
|
|
327
|
+
/* Create the upstream message iterators */
|
|
328
|
+
for (uint64_t i = 0;
|
|
329
|
+
i < bt_component_filter_get_input_port_count(common_data->component);
|
|
330
|
+
i++) {
|
|
331
|
+
bt_self_component_port_input *self_port =
|
|
332
|
+
bt_self_component_filter_borrow_input_port_by_index(
|
|
333
|
+
(bt_self_component_filter *)common_data->component, i);
|
|
334
|
+
|
|
335
|
+
const bt_port *port = bt_self_component_port_as_port(
|
|
336
|
+
bt_self_component_port_input_as_self_component_port(self_port));
|
|
337
|
+
|
|
338
|
+
/* Skip non-connected port */
|
|
339
|
+
if (!bt_port_is_connected(port))
|
|
340
|
+
continue;
|
|
341
|
+
|
|
342
|
+
el_mi *mi = (el_mi *)malloc(sizeof *mi);
|
|
343
|
+
bt_message_iterator_create_from_message_iterator(
|
|
344
|
+
self_message_iterator, self_port, &mi->message_iterator);
|
|
345
|
+
CDL_APPEND(message_iterator_private_data->head_mi, mi);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Set the message iterator's user data to our private data structure */
|
|
349
|
+
bt_self_message_iterator_set_data(self_message_iterator,
|
|
350
|
+
message_iterator_private_data);
|
|
351
|
+
|
|
352
|
+
message_iterator_private_data->state = BTX_FILTER_STATE_INITIALIZING;
|
|
353
|
+
message_iterator_private_data->processing_state =
|
|
354
|
+
BTX_FILTER_PROCESSING_STATE_READING;
|
|
355
|
+
|
|
356
|
+
return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
static void filter_finalize(bt_self_component_filter *self_component_filter) {
|
|
360
|
+
common_data_t *common_data = bt_self_component_get_data(
|
|
361
|
+
bt_self_component_filter_as_self_component(self_component_filter));
|
|
362
|
+
// We allocate it, we need to free it
|
|
363
|
+
free(common_data->btx_params);
|
|
364
|
+
bt_value_put_ref(common_data->params);
|
|
365
|
+
free(common_data);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
static void filter_message_iterator_finalize(
|
|
369
|
+
bt_self_message_iterator *self_message_iterator) {
|
|
370
|
+
/* Retrieve our private data from the message iterator's user data */
|
|
371
|
+
btx_message_iterator_t *message_iterator_private_data =
|
|
372
|
+
bt_self_message_iterator_get_data(self_message_iterator);
|
|
373
|
+
|
|
374
|
+
struct el *elt, *tmp;
|
|
375
|
+
DL_FOREACH_SAFE(message_iterator_private_data->pool, elt, tmp) {
|
|
376
|
+
DL_DELETE(message_iterator_private_data->pool, elt);
|
|
377
|
+
free(elt);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/* Free the allocated structure */
|
|
381
|
+
free(message_iterator_private_data);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/* Mandatory */
|
|
385
|
+
BT_PLUGIN_MODULE();
|
|
386
|
+
|
|
387
|
+
BT_PLUGIN(<%= options[:plugin_name] %>);
|
|
388
|
+
BT_PLUGIN_FILTER_COMPONENT_CLASS(<%= options[:component_name] %>,
|
|
389
|
+
filter_message_iterator_next);
|
|
390
|
+
|
|
391
|
+
BT_PLUGIN_FILTER_COMPONENT_CLASS_INITIALIZE_METHOD(<%= options[:component_name] %>,
|
|
392
|
+
filter_initialize);
|
|
393
|
+
BT_PLUGIN_FILTER_COMPONENT_CLASS_FINALIZE_METHOD(<%= options[:component_name] %>,
|
|
394
|
+
filter_finalize);
|
|
395
|
+
BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD(
|
|
396
|
+
<%= options[:component_name] %>, filter_message_iterator_initialize);
|
|
397
|
+
BT_PLUGIN_FILTER_COMPONENT_CLASS_MESSAGE_ITERATOR_CLASS_FINALIZE_METHOD(
|
|
398
|
+
<%= options[:component_name] %>, filter_message_iterator_finalize);
|
|
399
|
+
BT_PLUGIN_FILTER_COMPONENT_CLASS_INPUT_PORT_CONNECTED_METHOD(
|
|
400
|
+
<%= options[:component_name] %>, filter_input_port_connected);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#include <metababel/btx_component.h>
|
|
2
|
+
<% if ['SOURCE', 'FILTER'].include?(options[:component_type]) %>
|
|
3
|
+
#include <metababel/btx_downstream.h>
|
|
4
|
+
<% end %>
|
|
5
|
+
<% if ['FILTER', 'SINK'].include?(options[:component_type]) %>
|
|
6
|
+
#include <metababel/btx_upstream.h>
|
|
7
|
+
<% end %>
|
data/template/sink.c.erb
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#include "uthash.h"
|
|
2
|
+
#include <babeltrace2/babeltrace.h>
|
|
3
|
+
#include <metababel/metababel.h>
|
|
4
|
+
#include <stdio.h>
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
|
|
7
|
+
/* Loosely based by
|
|
8
|
+
* https://babeltrace.org/docs/v2.0/libbabeltrace2/example-simple-sink-cmp-cls.html
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* Consume Message
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
static bt_component_class_sink_consume_method_status
|
|
16
|
+
sink_consume(bt_self_component_sink *self_component_sink) {
|
|
17
|
+
bt_component_class_sink_consume_method_status status =
|
|
18
|
+
BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
|
|
19
|
+
|
|
20
|
+
/* Retrieve our private data from the component's user data */
|
|
21
|
+
/* This containt user data and the message iterator */
|
|
22
|
+
common_data_t *common_data = bt_self_component_get_data(
|
|
23
|
+
bt_self_component_sink_as_self_component(self_component_sink));
|
|
24
|
+
|
|
25
|
+
/* Consume a batch of messages from the upstream message iterator */
|
|
26
|
+
bt_message_array_const messages;
|
|
27
|
+
uint64_t message_count;
|
|
28
|
+
bt_message_iterator_next_status next_status = bt_message_iterator_next(
|
|
29
|
+
common_data->message_iterator, &messages, &message_count);
|
|
30
|
+
|
|
31
|
+
switch (next_status) {
|
|
32
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_END:
|
|
33
|
+
/* End of iteration: put the message iterator's reference */
|
|
34
|
+
bt_message_iterator_put_ref(common_data->message_iterator);
|
|
35
|
+
status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
|
|
36
|
+
goto end;
|
|
37
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN:
|
|
38
|
+
status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
|
|
39
|
+
goto end;
|
|
40
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_MEMORY_ERROR:
|
|
41
|
+
status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
|
|
42
|
+
goto end;
|
|
43
|
+
case BT_MESSAGE_ITERATOR_NEXT_STATUS_ERROR:
|
|
44
|
+
status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
|
|
45
|
+
goto end;
|
|
46
|
+
default:
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
/* For each consumed message */
|
|
50
|
+
for (uint64_t i = 0; i < message_count; i++) {
|
|
51
|
+
const bt_message *message = messages[i];
|
|
52
|
+
if (bt_message_get_type(message) != BT_MESSAGE_TYPE_EVENT) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Borrow the event message's event and its class */
|
|
57
|
+
const bt_event *event = bt_message_event_borrow_event_const(message);
|
|
58
|
+
const bt_event_class *event_class = bt_event_borrow_class_const(event);
|
|
59
|
+
|
|
60
|
+
/* Call dispatcher */
|
|
61
|
+
name_to_dispatcher_t *s = NULL;
|
|
62
|
+
const char *class_name = bt_event_class_get_name(event_class);
|
|
63
|
+
HASH_FIND_STR(common_data->name_to_dispatcher, class_name, s);
|
|
64
|
+
if (s)
|
|
65
|
+
(*((dispatcher_t(*))(s->dispatcher)))(s->callbacks, common_data, event);
|
|
66
|
+
|
|
67
|
+
bt_message_put_ref(message);
|
|
68
|
+
}
|
|
69
|
+
end:
|
|
70
|
+
return status;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* Initializes the sink component.
|
|
75
|
+
*/
|
|
76
|
+
static bt_component_class_initialize_method_status
|
|
77
|
+
sink_initialize(bt_self_component_sink *self_component_sink,
|
|
78
|
+
bt_self_component_sink_configuration *configuration,
|
|
79
|
+
const bt_value *params, void *initialize_method_data) {
|
|
80
|
+
/* Allocate a private data structure */
|
|
81
|
+
common_data_t *common_data = calloc(1, sizeof(common_data_t));
|
|
82
|
+
common_data->params = params;
|
|
83
|
+
// Read parameters
|
|
84
|
+
btx_populate_params(common_data);
|
|
85
|
+
|
|
86
|
+
bt_value_get_ref(common_data->params);
|
|
87
|
+
|
|
88
|
+
/* Register User Callbacks */
|
|
89
|
+
btx_register_usr_callbacks((void *)common_data);
|
|
90
|
+
|
|
91
|
+
/* Call Initialize user callback */
|
|
92
|
+
btx_call_callbacks_initialize_usr_data(common_data, &common_data->usr_data);
|
|
93
|
+
/* Call read callbacks */
|
|
94
|
+
btx_call_callbacks_read_params(common_data, common_data->usr_data,
|
|
95
|
+
common_data->btx_params);
|
|
96
|
+
|
|
97
|
+
/* Set the component's user data to our private data structure */
|
|
98
|
+
bt_self_component_set_data(
|
|
99
|
+
bt_self_component_sink_as_self_component(self_component_sink),
|
|
100
|
+
common_data);
|
|
101
|
+
|
|
102
|
+
/*
|
|
103
|
+
* Add an input port named `in` to the sink component.
|
|
104
|
+
*
|
|
105
|
+
* This is needed so that this sink component can be connected to a
|
|
106
|
+
* filter or a source component. With a connected upstream
|
|
107
|
+
* component, this sink component can create a message iterator
|
|
108
|
+
* to consume messages.
|
|
109
|
+
*/
|
|
110
|
+
bt_self_component_sink_add_input_port(self_component_sink, "in", NULL, NULL);
|
|
111
|
+
return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static void sink_finalize(bt_self_component_sink *self_component_sink) {
|
|
115
|
+
common_data_t *common_data = bt_self_component_get_data(
|
|
116
|
+
bt_self_component_sink_as_self_component(self_component_sink));
|
|
117
|
+
|
|
118
|
+
/* Finalize User Data */
|
|
119
|
+
/* Call Finalize user callback */
|
|
120
|
+
btx_call_callbacks_finalize_usr_data(common_data, common_data->usr_data);
|
|
121
|
+
// We allocate it, we need to free it
|
|
122
|
+
free(common_data->btx_params);
|
|
123
|
+
bt_value_put_ref(common_data->params);
|
|
124
|
+
|
|
125
|
+
/* Free the allocated structure */
|
|
126
|
+
free(common_data);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/*
|
|
130
|
+
* Called when the trace processing graph containing the sink component
|
|
131
|
+
* is configured.
|
|
132
|
+
*
|
|
133
|
+
* This is where we can create our upstream message iterator.
|
|
134
|
+
*/
|
|
135
|
+
static bt_component_class_sink_graph_is_configured_method_status
|
|
136
|
+
sink_graph_is_configured(bt_self_component_sink *self_component_sink) {
|
|
137
|
+
/* Retrieve our private data from the component's user data */
|
|
138
|
+
common_data_t *common_data = bt_self_component_get_data(
|
|
139
|
+
bt_self_component_sink_as_self_component(self_component_sink));
|
|
140
|
+
|
|
141
|
+
/* Borrow our unique port */
|
|
142
|
+
bt_self_component_port_input *in_port =
|
|
143
|
+
bt_self_component_sink_borrow_input_port_by_index(self_component_sink, 0);
|
|
144
|
+
|
|
145
|
+
/* Create the uptream message iterator */
|
|
146
|
+
bt_message_iterator_create_from_sink_component(
|
|
147
|
+
self_component_sink, in_port, &common_data->message_iterator);
|
|
148
|
+
|
|
149
|
+
return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Mandatory */
|
|
153
|
+
BT_PLUGIN_MODULE();
|
|
154
|
+
|
|
155
|
+
BT_PLUGIN(<%= options[:plugin_name] %>);
|
|
156
|
+
// Maybe we should createonly one pluging
|
|
157
|
+
/* Add the output component class */
|
|
158
|
+
BT_PLUGIN_SINK_COMPONENT_CLASS(<%= options[:component_name] %>, sink_consume);
|
|
159
|
+
|
|
160
|
+
BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD(<%= options[:component_name] %>,
|
|
161
|
+
sink_initialize);
|
|
162
|
+
BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(<%= options[:component_name] %>,
|
|
163
|
+
sink_finalize);
|
|
164
|
+
|
|
165
|
+
BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD(
|
|
166
|
+
<%= options[:component_name] %>, sink_graph_is_configured);
|