Put Python plugin support in a separate shared object
[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>
7d55361f 35#include <babeltrace/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
f60c8b34 98 component->initializing = true;
b8a06801
JG
99 component->destroy = destroy;
100end:
101 return ret;
102}
de713ce0 103
d3e4dcd8
PP
104enum bt_component_class_type bt_component_get_class_type(
105 struct bt_component *component)
38b48196 106{
d3e4dcd8 107 return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
38b48196
JG
108}
109
5645cd95
JG
110BT_HIDDEN
111struct bt_notification_iterator *bt_component_create_iterator(
8b0ce102 112 struct bt_component *component, void *init_method_data)
5645cd95
JG
113{
114 enum bt_notification_iterator_status ret_iterator;
d3e4dcd8 115 enum bt_component_class_type type;
5645cd95 116 struct bt_notification_iterator *iterator = NULL;
d3e4dcd8 117 struct bt_component_class *class = component->class;
5645cd95
JG
118
119 if (!component) {
120 goto error;
121 }
122
d3e4dcd8
PP
123 type = bt_component_get_class_type(component);
124 if (type != BT_COMPONENT_CLASS_TYPE_SOURCE &&
125 type != BT_COMPONENT_CLASS_TYPE_FILTER) {
5645cd95
JG
126 /* Unsupported operation. */
127 goto error;
128 }
129
130 iterator = bt_notification_iterator_create(component);
131 if (!iterator) {
132 goto error;
133 }
134
d3e4dcd8
PP
135 switch (type) {
136 case BT_COMPONENT_CLASS_TYPE_SOURCE:
5645cd95 137 {
d3e4dcd8 138 struct bt_component_class_source *source_class;
d3eb6e8f 139 enum bt_notification_iterator_status status;
5645cd95 140
d3e4dcd8 141 source_class = container_of(class, struct bt_component_class_source, parent);
5964a444
PP
142
143 if (source_class->methods.iterator.init) {
144 status = source_class->methods.iterator.init(component,
145 iterator, init_method_data);
146 if (status < 0) {
147 goto error;
148 }
5645cd95
JG
149 }
150 break;
5645cd95 151 }
d3e4dcd8 152 case BT_COMPONENT_CLASS_TYPE_FILTER:
5645cd95 153 {
d3e4dcd8 154 struct bt_component_class_filter *filter_class;
d3eb6e8f 155 enum bt_notification_iterator_status status;
5645cd95 156
d3e4dcd8 157 filter_class = container_of(class, struct bt_component_class_filter, parent);
5964a444
PP
158
159 if (filter_class->methods.iterator.init) {
160 status = filter_class->methods.iterator.init(component,
161 iterator, init_method_data);
162 if (status < 0) {
163 goto error;
164 }
5645cd95
JG
165 }
166 break;
167 }
168 default:
169 /* Unreachable. */
170 assert(0);
171 }
172
173 ret_iterator = bt_notification_iterator_validate(iterator);
174 if (ret_iterator != BT_NOTIFICATION_ITERATOR_STATUS_OK) {
175 goto error;
176 }
177
178 return iterator;
179error:
180 BT_PUT(iterator);
181 return iterator;
182}
183
6358c163 184struct bt_component *bt_component_create_with_init_method_data(
7c7c0433 185 struct bt_component_class *component_class, const char *name,
6358c163 186 struct bt_value *params, void *init_method_data)
38b48196 187{
7c7c0433 188 int ret;
38b48196 189 struct bt_component *component = NULL;
d3e4dcd8 190 enum bt_component_class_type type;
38b48196
JG
191
192 if (!component_class) {
193 goto end;
194 }
195
7c7c0433 196 type = bt_component_class_get_type(component_class);
d3e4dcd8
PP
197 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
198 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
7c7c0433
JG
199 goto end;
200 }
201
202 component = component_create_funcs[type](component_class, params);
203 if (!component) {
204 goto end;
205 }
206
207 bt_object_init(component, bt_component_destroy);
7c7c0433 208 component->name = g_string_new(name);
4b70dd83 209 if (!component->name) {
7c7c0433
JG
210 BT_PUT(component);
211 goto end;
212 }
213
d3e4dcd8 214 if (component_class->methods.init) {
6358c163
PP
215 ret = component_class->methods.init(component, params,
216 init_method_data);
d3e4dcd8
PP
217 component->initializing = false;
218 if (ret != BT_COMPONENT_STATUS_OK) {
219 BT_PUT(component);
220 goto end;
221 }
528debdf 222 }
d3e4dcd8
PP
223
224 component->initializing = false;
7c7c0433 225 ret = component_validation_funcs[type](component);
692b38d2 226 if (ret != BT_COMPONENT_STATUS_OK) {
7c7c0433 227 BT_PUT(component);
38b48196
JG
228 goto end;
229 }
1e4d8103
PP
230
231 bt_component_class_freeze(component->class);
38b48196
JG
232end:
233 return component;
234}
235
6358c163
PP
236struct bt_component *bt_component_create(
237 struct bt_component_class *component_class, const char *name,
238 struct bt_value *params)
239{
240 return bt_component_create_with_init_method_data(component_class, name,
241 params, NULL);
242}
243
de713ce0
JG
244const char *bt_component_get_name(struct bt_component *component)
245{
246 const char *ret = NULL;
247
248 if (!component) {
249 goto end;
250 }
251
f1222e7d 252 ret = component->name->len == 0 ? NULL : component->name->str;
de713ce0
JG
253end:
254 return ret;
255}
256
257enum bt_component_status bt_component_set_name(struct bt_component *component,
258 const char *name)
259{
260 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
261
262 if (!component || !name || name[0] == '\0') {
30d619df 263 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
264 goto end;
265 }
266
267 g_string_assign(component->name, name);
268end:
269 return ret;
270}
271
38b48196
JG
272struct bt_component_class *bt_component_get_class(
273 struct bt_component *component)
de713ce0 274{
38b48196 275 return component ? bt_get(component->class) : NULL;
de713ce0
JG
276}
277
de713ce0
JG
278void *bt_component_get_private_data(struct bt_component *component)
279{
38b48196 280 return component ? component->user_data : NULL;
de713ce0
JG
281}
282
283enum bt_component_status
284bt_component_set_private_data(struct bt_component *component,
285 void *data)
286{
287 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
288
fec2a9f2 289 if (!component || !component->initializing) {
30d619df 290 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
291 goto end;
292 }
293
294 component->user_data = data;
295end:
296 return ret;
297}
366e034f
JG
298
299BT_HIDDEN
f60c8b34 300void bt_component_set_graph(struct bt_component *component,
366e034f
JG
301 struct bt_graph *graph)
302{
f60c8b34
JG
303 struct bt_object *parent = bt_object_get_parent(&component->base);
304
305 assert(!parent || parent == &graph->base);
306 if (!parent) {
307 bt_object_set_parent(component, &graph->base);
308 }
309 bt_put(parent);
366e034f
JG
310}
311
312struct bt_graph *bt_component_get_graph(
313 struct bt_component *component)
314{
315 return (struct bt_graph *) bt_object_get_parent(&component->base);
316}
317
318BT_HIDDEN
319int bt_component_init_input_ports(struct bt_component *component,
320 GPtrArray **input_ports)
321{
322 int ret = 0;
323 struct bt_port *default_port;
324
325 *input_ports = g_ptr_array_new_with_free_func(bt_object_release);
f60c8b34 326 if (!*input_ports) {
366e034f
JG
327 ret = -1;
328 goto end;
329 }
330
f60c8b34
JG
331 default_port = bt_component_add_port(component, *input_ports,
332 BT_PORT_TYPE_INPUT, DEFAULT_INPUT_PORT_NAME);
366e034f
JG
333 if (!default_port) {
334 ret = -1;
335 goto end;
336 }
f60c8b34 337 bt_put(default_port);
366e034f
JG
338end:
339 return ret;
340}
341
342BT_HIDDEN
343int bt_component_init_output_ports(struct bt_component *component,
344 GPtrArray **output_ports)
345{
346 int ret = 0;
347 struct bt_port *default_port;
348
349 *output_ports = g_ptr_array_new_with_free_func(bt_object_release);
f60c8b34 350 if (!*output_ports) {
366e034f
JG
351 ret = -1;
352 goto end;
353 }
354
f60c8b34
JG
355 default_port = bt_component_add_port(component, *output_ports,
356 BT_PORT_TYPE_OUTPUT, DEFAULT_OUTPUT_PORT_NAME);
366e034f
JG
357 if (!default_port) {
358 ret = -1;
359 goto end;
360 }
f60c8b34 361 bt_put(default_port);
366e034f
JG
362end:
363 return ret;
364}
365
366BT_HIDDEN
367struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name)
368{
369 size_t i;
370 struct bt_port *ret_port = NULL;
371
372 for (i = 0; i < ports->len; i++) {
373 struct bt_port *port = g_ptr_array_index(ports, i);
374 const char *port_name = bt_port_get_name(port);
375
376 if (!port_name) {
377 continue;
378 }
379
380 if (!strcmp(name, port_name)) {
381 ret_port = bt_get(port);
382 break;
383 }
384 }
385
386 return ret_port;
387}
388
389BT_HIDDEN
390struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index)
391{
392 struct bt_port *port = NULL;
393
394 if (index < 0 || index >= ports->len) {
395 goto end;
396 }
397
398 port = bt_get(g_ptr_array_index(ports, index));
399end:
400 return port;
401}
402
403BT_HIDDEN
404struct bt_port *bt_component_add_port(
405 struct bt_component *component,GPtrArray *ports,
406 enum bt_port_type port_type, const char *name)
407{
408 size_t i;
f60c8b34 409 struct bt_port *new_port = NULL;
366e034f
JG
410
411 if (!component->initializing || !name || *name == '\0') {
366e034f
JG
412 goto end;
413 }
414
415 /* Look for a port having the same name. */
416 for (i = 0; i < ports->len; i++) {
417 const char *port_name;
418 struct bt_port *port = g_ptr_array_index(
419 ports, i);
420
421 port_name = bt_port_get_name(port);
422 if (!port_name) {
423 continue;
424 }
425
426 if (!strcmp(name, port_name)) {
427 /* Port name clash, abort. */
f60c8b34 428 goto end;
366e034f
JG
429 }
430 }
431
f60c8b34
JG
432 new_port = bt_port_create(component, port_type, name);
433 if (!new_port) {
434 goto end;
435 }
436
437 /*
438 * No name clash, add the port.
439 * The component is now the port's parent; it should _not_
440 * hold a reference to the port since the port's lifetime
441 * is now protected by the component's own lifetime.
442 */
443 g_ptr_array_add(ports, new_port);
366e034f
JG
444end:
445 return new_port;
366e034f
JG
446}
447
448BT_HIDDEN
449enum bt_component_status bt_component_remove_port(
450 struct bt_component *component, GPtrArray *ports,
451 const char *name)
452{
453 size_t i;
454 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
455
456 if (!component->initializing || !name) {
457 status = BT_COMPONENT_STATUS_INVALID;
458 goto end;
459 }
460
461 for (i = 0; i < ports->len; i++) {
462 const char *port_name;
463 struct bt_port *port = g_ptr_array_index(ports, i);
464
465 port_name = bt_port_get_name(port);
466 if (!port_name) {
467 continue;
468 }
469
470 if (!strcmp(name, port_name)) {
471 g_ptr_array_remove_index(ports, i);
472 goto end;
473 }
474 }
475 status = BT_COMPONENT_STATUS_NOT_FOUND;
476end:
477 return status;
478}
f60c8b34
JG
479
480BT_HIDDEN
481enum bt_component_status bt_component_new_connection(
482 struct bt_component *component, struct bt_port *own_port,
483 struct bt_connection *connection)
484{
485 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
486
487 if (component->class->methods.new_connection_method) {
488 status = component->class->methods.new_connection_method(
489 own_port, connection);
490 }
491
492 return status;
493}
This page took 0.048265 seconds and 4 git commands to generate.