Hide bt_component_sink_consume
[babeltrace.git] / lib / component / component.c
CommitLineData
de713ce0
JG
1/*
2 * component.c
3 *
4 * Babeltrace Plugin Component
5 *
6 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
33b34c43
PP
29#include <babeltrace/component/component.h>
30#include <babeltrace/component/component-internal.h>
d3e4dcd8 31#include <babeltrace/component/component-class-internal.h>
d71dcf2c
PP
32#include <babeltrace/component/component-source-internal.h>
33#include <babeltrace/component/component-filter-internal.h>
34#include <babeltrace/component/component-sink-internal.h>
366e034f 35#include <babeltrace/component/component-graph-internal.h>
33b34c43 36#include <babeltrace/component/notification/iterator-internal.h>
de713ce0
JG
37#include <babeltrace/babeltrace-internal.h>
38#include <babeltrace/compiler.h>
b8a06801 39#include <babeltrace/ref.h>
de713ce0 40
7c7c0433
JG
41static
42struct bt_component * (* const component_create_funcs[])(
43 struct bt_component_class *, struct bt_value *) = {
d3e4dcd8
PP
44 [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_create,
45 [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_create,
46 [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_create,
7c7c0433
JG
47};
48
49static
50enum bt_component_status (* const component_validation_funcs[])(
51 struct bt_component *) = {
d3e4dcd8
PP
52 [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_validate,
53 [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_validate,
54 [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_validate,
7c7c0433
JG
55};
56
b8a06801
JG
57static
58void bt_component_destroy(struct bt_object *obj)
59{
60 struct bt_component *component = NULL;
61 struct bt_component_class *component_class = NULL;
62
63 if (!obj) {
64 return;
65 }
66
67 component = container_of(obj, struct bt_component, base);
7c7c0433
JG
68 component_class = component->class;
69
70 /*
b8a06801
JG
71 * User data is destroyed first, followed by the concrete component
72 * instance.
73 */
d3e4dcd8
PP
74 if (component->class->methods.destroy) {
75 component->class->methods.destroy(component);
7c7c0433 76 }
b8a06801 77
ab09f844
JG
78 if (component->destroy) {
79 component->destroy(component);
80 }
81
7c7c0433 82 g_string_free(component->name, TRUE);
b8a06801 83 bt_put(component_class);
7c7c0433 84 g_free(component);
b8a06801
JG
85}
86
87BT_HIDDEN
88enum bt_component_status bt_component_init(struct bt_component *component,
d3e4dcd8 89 bt_component_class_destroy_method destroy)
b8a06801
JG
90{
91 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
92
ab09f844 93 if (!component) {
30d619df 94 ret = BT_COMPONENT_STATUS_INVALID;
b8a06801
JG
95 goto end;
96 }
97
b8a06801
JG
98 component->destroy = destroy;
99end:
100 return ret;
101}
de713ce0 102
d3e4dcd8
PP
103enum bt_component_class_type bt_component_get_class_type(
104 struct bt_component *component)
38b48196 105{
d3e4dcd8 106 return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
38b48196
JG
107}
108
5645cd95
JG
109BT_HIDDEN
110struct bt_notification_iterator *bt_component_create_iterator(
8b0ce102 111 struct bt_component *component, void *init_method_data)
5645cd95
JG
112{
113 enum bt_notification_iterator_status ret_iterator;
d3e4dcd8 114 enum bt_component_class_type type;
5645cd95 115 struct bt_notification_iterator *iterator = NULL;
d3e4dcd8 116 struct bt_component_class *class = component->class;
5645cd95
JG
117
118 if (!component) {
119 goto error;
120 }
121
d3e4dcd8
PP
122 type = bt_component_get_class_type(component);
123 if (type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
124 type != BT_COMPONENT_CLASS_TYPE_FILTER) {
5645cd95
JG
125 /* Unsupported operation. */
126 goto error;
127 }
128
129 iterator = bt_notification_iterator_create(component);
130 if (!iterator) {
131 goto error;
132 }
133
d3e4dcd8
PP
134 switch (type) {
135 case BT_COMPONENT_CLASS_TYPE_SOURCE:
5645cd95 136 {
d3e4dcd8 137 struct bt_component_class_source *source_class;
d3eb6e8f 138 enum bt_notification_iterator_status status;
5645cd95 139
d3e4dcd8 140 source_class = container_of(class, struct bt_component_class_source, parent);
5964a444
PP
141
142 if (source_class->methods.iterator.init) {
143 status = source_class->methods.iterator.init(component,
144 iterator, init_method_data);
145 if (status < 0) {
146 goto error;
147 }
5645cd95
JG
148 }
149 break;
5645cd95 150 }
d3e4dcd8 151 case BT_COMPONENT_CLASS_TYPE_FILTER:
5645cd95 152 {
d3e4dcd8 153 struct bt_component_class_filter *filter_class;
d3eb6e8f 154 enum bt_notification_iterator_status status;
5645cd95 155
d3e4dcd8 156 filter_class = container_of(class, struct bt_component_class_filter, parent);
5964a444
PP
157
158 if (filter_class->methods.iterator.init) {
159 status = filter_class->methods.iterator.init(component,
160 iterator, init_method_data);
161 if (status < 0) {
162 goto error;
163 }
5645cd95
JG
164 }
165 break;
166 }
167 default:
168 /* Unreachable. */
169 assert(0);
170 }
171
172 ret_iterator = bt_notification_iterator_validate(iterator);
173 if (ret_iterator != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
174 goto error;
175 }
176
177 return iterator;
178error:
179 BT_PUT(iterator);
180 return iterator;
181}
182
6358c163 183struct bt_component *bt_component_create_with_init_method_data(
7c7c0433 184 struct bt_component_class *component_class, const char *name,
6358c163 185 struct bt_value *params, void *init_method_data)
38b48196 186{
7c7c0433 187 int ret;
38b48196 188 struct bt_component *component = NULL;
d3e4dcd8 189 enum bt_component_class_type type;
38b48196
JG
190
191 if (!component_class) {
192 goto end;
193 }
194
7c7c0433 195 type = bt_component_class_get_type(component_class);
d3e4dcd8
PP
196 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
197 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
7c7c0433
JG
198 goto end;
199 }
200
201 component = component_create_funcs[type](component_class, params);
202 if (!component) {
203 goto end;
204 }
205
206 bt_object_init(component, bt_component_destroy);
7c7c0433 207 component->name = g_string_new(name);
4b70dd83 208 if (!component->name) {
7c7c0433
JG
209 BT_PUT(component);
210 goto end;
211 }
212
fec2a9f2 213 component->initializing = true;
d3e4dcd8
PP
214
215 if (component_class->methods.init) {
6358c163
PP
216 ret = component_class->methods.init(component, params,
217 init_method_data);
d3e4dcd8
PP
218 component->initializing = false;
219 if (ret != BT_COMPONENT_STATUS_OK) {
220 BT_PUT(component);
221 goto end;
222 }
528debdf 223 }
d3e4dcd8
PP
224
225 component->initializing = false;
7c7c0433 226 ret = component_validation_funcs[type](component);
692b38d2 227 if (ret != BT_COMPONENT_STATUS_OK) {
7c7c0433 228 BT_PUT(component);
38b48196
JG
229 goto end;
230 }
1e4d8103
PP
231
232 bt_component_class_freeze(component->class);
38b48196
JG
233end:
234 return component;
235}
236
6358c163
PP
237struct bt_component *bt_component_create(
238 struct bt_component_class *component_class, const char *name,
239 struct bt_value *params)
240{
241 return bt_component_create_with_init_method_data(component_class, name,
242 params, NULL);
243}
244
de713ce0
JG
245const char *bt_component_get_name(struct bt_component *component)
246{
247 const char *ret = NULL;
248
249 if (!component) {
250 goto end;
251 }
252
f1222e7d 253 ret = component->name->len == 0 ? NULL : component->name->str;
de713ce0
JG
254end:
255 return ret;
256}
257
258enum bt_component_status bt_component_set_name(struct bt_component *component,
259 const char *name)
260{
261 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
262
263 if (!component || !name || name[0] == '\0') {
30d619df 264 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
265 goto end;
266 }
267
268 g_string_assign(component->name, name);
269end:
270 return ret;
271}
272
38b48196
JG
273struct bt_component_class *bt_component_get_class(
274 struct bt_component *component)
de713ce0 275{
38b48196 276 return component ? bt_get(component->class) : NULL;
de713ce0
JG
277}
278
de713ce0
JG
279void *bt_component_get_private_data(struct bt_component *component)
280{
38b48196 281 return component ? component->user_data : NULL;
de713ce0
JG
282}
283
284enum bt_component_status
285bt_component_set_private_data(struct bt_component *component,
286 void *data)
287{
288 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
289
fec2a9f2 290 if (!component || !component->initializing) {
30d619df 291 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
292 goto end;
293 }
294
295 component->user_data = data;
296end:
297 return ret;
298}
366e034f
JG
299
300BT_HIDDEN
301enum bt_component_status bt_component_set_graph(struct bt_component *component,
302 struct bt_graph *graph)
303{
304 bt_object_set_parent(component, &graph->base);
305 return BT_COMPONENT_STATUS_OK;
306}
307
308struct bt_graph *bt_component_get_graph(
309 struct bt_component *component)
310{
311 return (struct bt_graph *) bt_object_get_parent(&component->base);
312}
313
314BT_HIDDEN
315int bt_component_init_input_ports(struct bt_component *component,
316 GPtrArray **input_ports)
317{
318 int ret = 0;
319 struct bt_port *default_port;
320
321 *input_ports = g_ptr_array_new_with_free_func(bt_object_release);
322 if (*input_ports) {
323 ret = -1;
324 goto end;
325 }
326
327 default_port = bt_port_create(component, BT_PORT_TYPE_INPUT,
328 DEFAULT_INPUT_PORT_NAME);
329 if (!default_port) {
330 ret = -1;
331 goto end;
332 }
333
334 g_ptr_array_add(*input_ports, default_port);
335end:
336 return ret;
337}
338
339BT_HIDDEN
340int bt_component_init_output_ports(struct bt_component *component,
341 GPtrArray **output_ports)
342{
343 int ret = 0;
344 struct bt_port *default_port;
345
346 *output_ports = g_ptr_array_new_with_free_func(bt_object_release);
347 if (*output_ports) {
348 ret = -1;
349 goto end;
350 }
351
352 default_port = bt_port_create(component, BT_PORT_TYPE_OUTPUT,
353 DEFAULT_OUTPUT_PORT_NAME);
354 if (!default_port) {
355 ret = -1;
356 goto end;
357 }
358
359 g_ptr_array_add(*output_ports, default_port);
360end:
361 return ret;
362}
363
364BT_HIDDEN
365struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name)
366{
367 size_t i;
368 struct bt_port *ret_port = NULL;
369
370 for (i = 0; i < ports->len; i++) {
371 struct bt_port *port = g_ptr_array_index(ports, i);
372 const char *port_name = bt_port_get_name(port);
373
374 if (!port_name) {
375 continue;
376 }
377
378 if (!strcmp(name, port_name)) {
379 ret_port = bt_get(port);
380 break;
381 }
382 }
383
384 return ret_port;
385}
386
387BT_HIDDEN
388struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index)
389{
390 struct bt_port *port = NULL;
391
392 if (index < 0 || index >= ports->len) {
393 goto end;
394 }
395
396 port = bt_get(g_ptr_array_index(ports, index));
397end:
398 return port;
399}
400
401BT_HIDDEN
402struct bt_port *bt_component_add_port(
403 struct bt_component *component,GPtrArray *ports,
404 enum bt_port_type port_type, const char *name)
405{
406 size_t i;
407 struct bt_port *new_port;
408
409 if (!component->initializing || !name || *name == '\0') {
410 new_port = NULL;
411 goto end;
412 }
413
414 new_port = bt_port_create(component, port_type, name);
415 if (!new_port) {
416 goto end;
417 }
418
419 /* Look for a port having the same name. */
420 for (i = 0; i < ports->len; i++) {
421 const char *port_name;
422 struct bt_port *port = g_ptr_array_index(
423 ports, i);
424
425 port_name = bt_port_get_name(port);
426 if (!port_name) {
427 continue;
428 }
429
430 if (!strcmp(name, port_name)) {
431 /* Port name clash, abort. */
432 goto error;
433 }
434 }
435
436 /* No name clash, add the port. */
437 g_ptr_array_add(ports, bt_get(new_port));
438end:
439 return new_port;
440error:
441 BT_PUT(new_port);
442 goto end;
443}
444
445BT_HIDDEN
446enum bt_component_status bt_component_remove_port(
447 struct bt_component *component, GPtrArray *ports,
448 const char *name)
449{
450 size_t i;
451 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
452
453 if (!component->initializing || !name) {
454 status = BT_COMPONENT_STATUS_INVALID;
455 goto end;
456 }
457
458 for (i = 0; i < ports->len; i++) {
459 const char *port_name;
460 struct bt_port *port = g_ptr_array_index(ports, i);
461
462 port_name = bt_port_get_name(port);
463 if (!port_name) {
464 continue;
465 }
466
467 if (!strcmp(name, port_name)) {
468 g_ptr_array_remove_index(ports, i);
469 goto end;
470 }
471 }
472 status = BT_COMPONENT_STATUS_NOT_FOUND;
473end:
474 return status;
475}
This page took 0.04756 seconds and 4 git commands to generate.