Update include/babeltrace/babeltrace.h
[babeltrace.git] / lib / graph / 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
b2e0c907
PP
29#include <babeltrace/graph/private-component.h>
30#include <babeltrace/graph/component.h>
31#include <babeltrace/graph/component-internal.h>
32#include <babeltrace/graph/component-class-internal.h>
33#include <babeltrace/graph/component-source-internal.h>
34#include <babeltrace/graph/component-filter-internal.h>
35#include <babeltrace/graph/component-sink-internal.h>
36#include <babeltrace/graph/private-connection.h>
37#include <babeltrace/graph/connection-internal.h>
38#include <babeltrace/graph/graph-internal.h>
39#include <babeltrace/graph/notification-iterator-internal.h>
40#include <babeltrace/graph/private-notification-iterator.h>
de713ce0 41#include <babeltrace/babeltrace-internal.h>
3d9990ac 42#include <babeltrace/compiler-internal.h>
b8a06801 43#include <babeltrace/ref.h>
9ac68eb1 44#include <stdint.h>
de713ce0 45
7c7c0433
JG
46static
47struct bt_component * (* const component_create_funcs[])(
48 struct bt_component_class *, struct bt_value *) = {
d3e4dcd8
PP
49 [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_create,
50 [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_create,
51 [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_create,
7c7c0433
JG
52};
53
72b913fb
PP
54static
55void (*component_destroy_funcs[])(struct bt_component *) = {
56 [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_destroy,
57 [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_destroy,
58 [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_destroy,
59};
60
7c7c0433
JG
61static
62enum bt_component_status (* const component_validation_funcs[])(
63 struct bt_component *) = {
d3e4dcd8
PP
64 [BT_COMPONENT_CLASS_TYPE_SOURCE] = bt_component_source_validate,
65 [BT_COMPONENT_CLASS_TYPE_SINK] = bt_component_sink_validate,
66 [BT_COMPONENT_CLASS_TYPE_FILTER] = bt_component_filter_validate,
7c7c0433
JG
67};
68
b8a06801
JG
69static
70void bt_component_destroy(struct bt_object *obj)
71{
72 struct bt_component *component = NULL;
73 struct bt_component_class *component_class = NULL;
3230ee6b 74 int i;
b8a06801
JG
75
76 if (!obj) {
77 return;
78 }
79
80 component = container_of(obj, struct bt_component, base);
3230ee6b
PP
81
82 /* Call destroy listeners in reverse registration order */
83 for (i = component->destroy_listeners->len - 1; i >= 0; i--) {
84 struct bt_component_destroy_listener *listener =
85 &g_array_index(component->destroy_listeners,
86 struct bt_component_destroy_listener, i);
87
88 listener->func(component, listener->data);
89 }
90
7c7c0433
JG
91 component_class = component->class;
92
93 /*
b8a06801
JG
94 * User data is destroyed first, followed by the concrete component
95 * instance.
96 */
64cadc66
PP
97 if (component->class->methods.finalize) {
98 component->class->methods.finalize(
890882ef 99 bt_private_component_from_component(component));
7c7c0433 100 }
b8a06801 101
ab09f844
JG
102 if (component->destroy) {
103 component->destroy(component);
104 }
105
72b913fb
PP
106 if (component->input_ports) {
107 g_ptr_array_free(component->input_ports, TRUE);
108 }
b8a06801 109
72b913fb
PP
110 if (component->output_ports) {
111 g_ptr_array_free(component->output_ports, TRUE);
b8a06801
JG
112 }
113
3230ee6b
PP
114 if (component->destroy_listeners) {
115 g_array_free(component->destroy_listeners, TRUE);
116 }
117
72b913fb
PP
118 g_string_free(component->name, TRUE);
119 bt_put(component_class);
120 g_free(component);
b8a06801 121}
de713ce0 122
890882ef
PP
123struct bt_component *bt_component_from_private_component(
124 struct bt_private_component *private_component)
38b48196 125{
890882ef 126 return bt_get(bt_component_from_private(private_component));
38b48196
JG
127}
128
890882ef
PP
129enum bt_component_class_type bt_component_get_class_type(
130 struct bt_component *component)
5645cd95 131{
890882ef 132 return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
5645cd95
JG
133}
134
72b913fb
PP
135static
136struct bt_port *bt_component_add_port(
137 struct bt_component *component, GPtrArray *ports,
3e9b0023 138 enum bt_port_type port_type, const char *name, void *user_data)
72b913fb
PP
139{
140 size_t i;
141 struct bt_port *new_port = NULL;
1bf957a0 142 struct bt_graph *graph = NULL;
72b913fb
PP
143
144 if (!name || strlen(name) == 0) {
145 goto end;
146 }
147
148 /* Look for a port having the same name. */
149 for (i = 0; i < ports->len; i++) {
150 const char *port_name;
151 struct bt_port *port = g_ptr_array_index(
152 ports, i);
153
154 port_name = bt_port_get_name(port);
155 if (!port_name) {
156 continue;
157 }
158
159 if (!strcmp(name, port_name)) {
160 /* Port name clash, abort. */
161 goto end;
162 }
163 }
164
3e9b0023 165 new_port = bt_port_create(component, port_type, name, user_data);
72b913fb
PP
166 if (!new_port) {
167 goto end;
168 }
169
170 /*
171 * No name clash, add the port.
172 * The component is now the port's parent; it should _not_
173 * hold a reference to the port since the port's lifetime
174 * is now protected by the component's own lifetime.
175 */
176 g_ptr_array_add(ports, new_port);
1bf957a0
PP
177
178 /*
179 * Notify the graph's creator that a new port was added.
180 */
181 graph = bt_component_get_graph(component);
182 if (graph) {
183 bt_graph_notify_port_added(graph, new_port);
184 BT_PUT(graph);
185 }
186
72b913fb
PP
187end:
188 return new_port;
189}
190
191BT_HIDDEN
544d0515 192int64_t bt_component_get_input_port_count(struct bt_component *comp)
72b913fb
PP
193{
194 assert(comp);
9ac68eb1 195 return (int64_t) comp->input_ports->len;
72b913fb
PP
196}
197
198BT_HIDDEN
544d0515 199int64_t bt_component_get_output_port_count(struct bt_component *comp)
72b913fb
PP
200{
201 assert(comp);
9ac68eb1 202 return (int64_t) comp->output_ports->len;
72b913fb
PP
203}
204
6358c163 205struct bt_component *bt_component_create_with_init_method_data(
7c7c0433 206 struct bt_component_class *component_class, const char *name,
6358c163 207 struct bt_value *params, void *init_method_data)
38b48196 208{
7c7c0433 209 int ret;
38b48196 210 struct bt_component *component = NULL;
d3e4dcd8 211 enum bt_component_class_type type;
38b48196 212
0df078e5
PP
213 bt_get(params);
214
38b48196
JG
215 if (!component_class) {
216 goto end;
217 }
218
7c7c0433 219 type = bt_component_class_get_type(component_class);
d3e4dcd8
PP
220 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
221 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
7c7c0433
JG
222 goto end;
223 }
224
0df078e5
PP
225 /*
226 * Parameters must be a map value, but we create a convenient
227 * empty one if it's NULL.
228 */
229 if (params) {
230 if (!bt_value_is_map(params)) {
231 goto end;
232 }
233 } else {
234 params = bt_value_map_create();
235 if (!params) {
236 goto end;
237 }
238 }
239
7c7c0433
JG
240 component = component_create_funcs[type](component_class, params);
241 if (!component) {
242 goto end;
243 }
244
245 bt_object_init(component, bt_component_destroy);
72b913fb
PP
246 component->class = bt_get(component_class);
247 component->destroy = component_destroy_funcs[type];
7c7c0433 248 component->name = g_string_new(name);
4b70dd83 249 if (!component->name) {
7c7c0433
JG
250 BT_PUT(component);
251 goto end;
252 }
253
72b913fb
PP
254 component->input_ports = g_ptr_array_new_with_free_func(
255 bt_object_release);
256 if (!component->input_ports) {
257 BT_PUT(component);
258 goto end;
259 }
260
261 component->output_ports = g_ptr_array_new_with_free_func(
262 bt_object_release);
263 if (!component->output_ports) {
264 BT_PUT(component);
265 goto end;
266 }
267
3230ee6b
PP
268 component->destroy_listeners = g_array_new(FALSE, TRUE,
269 sizeof(struct bt_component_destroy_listener));
270 if (!component->destroy_listeners) {
271 BT_PUT(component);
272 goto end;
273 }
274
72b913fb
PP
275 component->initializing = true;
276
d3e4dcd8 277 if (component_class->methods.init) {
890882ef
PP
278 ret = component_class->methods.init(
279 bt_private_component_from_component(component), params,
6358c163 280 init_method_data);
d3e4dcd8
PP
281 component->initializing = false;
282 if (ret != BT_COMPONENT_STATUS_OK) {
283 BT_PUT(component);
284 goto end;
285 }
528debdf 286 }
d3e4dcd8
PP
287
288 component->initializing = false;
7c7c0433 289 ret = component_validation_funcs[type](component);
692b38d2 290 if (ret != BT_COMPONENT_STATUS_OK) {
7c7c0433 291 BT_PUT(component);
38b48196
JG
292 goto end;
293 }
1e4d8103
PP
294
295 bt_component_class_freeze(component->class);
38b48196 296end:
0df078e5 297 bt_put(params);
38b48196
JG
298 return component;
299}
300
6358c163
PP
301struct bt_component *bt_component_create(
302 struct bt_component_class *component_class, const char *name,
303 struct bt_value *params)
304{
305 return bt_component_create_with_init_method_data(component_class, name,
306 params, NULL);
307}
308
de713ce0
JG
309const char *bt_component_get_name(struct bt_component *component)
310{
311 const char *ret = NULL;
312
313 if (!component) {
314 goto end;
315 }
316
f1222e7d 317 ret = component->name->len == 0 ? NULL : component->name->str;
de713ce0
JG
318end:
319 return ret;
320}
321
322enum bt_component_status bt_component_set_name(struct bt_component *component,
323 const char *name)
324{
325 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
326
327 if (!component || !name || name[0] == '\0') {
30d619df 328 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
329 goto end;
330 }
331
332 g_string_assign(component->name, name);
333end:
334 return ret;
335}
336
38b48196
JG
337struct bt_component_class *bt_component_get_class(
338 struct bt_component *component)
de713ce0 339{
38b48196 340 return component ? bt_get(component->class) : NULL;
de713ce0
JG
341}
342
890882ef
PP
343void *bt_private_component_get_user_data(
344 struct bt_private_component *private_component)
de713ce0 345{
890882ef
PP
346 struct bt_component *component =
347 bt_component_from_private(private_component);
348
38b48196 349 return component ? component->user_data : NULL;
de713ce0
JG
350}
351
890882ef
PP
352enum bt_component_status bt_private_component_set_user_data(
353 struct bt_private_component *private_component,
de713ce0
JG
354 void *data)
355{
890882ef
PP
356 struct bt_component *component =
357 bt_component_from_private(private_component);
de713ce0
JG
358 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
359
fec2a9f2 360 if (!component || !component->initializing) {
30d619df 361 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
362 goto end;
363 }
364
365 component->user_data = data;
366end:
367 return ret;
368}
366e034f
JG
369
370BT_HIDDEN
f60c8b34 371void bt_component_set_graph(struct bt_component *component,
366e034f
JG
372 struct bt_graph *graph)
373{
f60c8b34
JG
374 struct bt_object *parent = bt_object_get_parent(&component->base);
375
376 assert(!parent || parent == &graph->base);
377 if (!parent) {
378 bt_object_set_parent(component, &graph->base);
379 }
380 bt_put(parent);
366e034f
JG
381}
382
383struct bt_graph *bt_component_get_graph(
384 struct bt_component *component)
385{
386 return (struct bt_graph *) bt_object_get_parent(&component->base);
387}
388
72b913fb 389static
9ac68eb1
PP
390struct bt_port *bt_component_get_port_by_name(GPtrArray *ports,
391 const char *name)
366e034f
JG
392{
393 size_t i;
394 struct bt_port *ret_port = NULL;
395
72b913fb
PP
396 assert(name);
397
366e034f
JG
398 for (i = 0; i < ports->len; i++) {
399 struct bt_port *port = g_ptr_array_index(ports, i);
400 const char *port_name = bt_port_get_name(port);
401
402 if (!port_name) {
403 continue;
404 }
405
406 if (!strcmp(name, port_name)) {
407 ret_port = bt_get(port);
408 break;
409 }
410 }
411
412 return ret_port;
413}
414
415BT_HIDDEN
9ac68eb1 416struct bt_port *bt_component_get_input_port_by_name(struct bt_component *comp,
72b913fb
PP
417 const char *name)
418{
419 assert(comp);
420
9ac68eb1 421 return bt_component_get_port_by_name(comp->input_ports, name);
72b913fb
PP
422}
423
424BT_HIDDEN
9ac68eb1 425struct bt_port *bt_component_get_output_port_by_name(struct bt_component *comp,
72b913fb
PP
426 const char *name)
427{
428 assert(comp);
429
9ac68eb1 430 return bt_component_get_port_by_name(comp->output_ports, name);
72b913fb
PP
431}
432
433static
9ac68eb1 434struct bt_port *bt_component_get_port_by_index(GPtrArray *ports, uint64_t index)
366e034f
JG
435{
436 struct bt_port *port = NULL;
437
9ac68eb1 438 if (index >= ports->len) {
366e034f
JG
439 goto end;
440 }
441
442 port = bt_get(g_ptr_array_index(ports, index));
443end:
444 return port;
445}
446
447BT_HIDDEN
9ac68eb1
PP
448struct bt_port *bt_component_get_input_port_by_index(struct bt_component *comp,
449 uint64_t index)
366e034f 450{
72b913fb 451 assert(comp);
366e034f 452
9ac68eb1 453 return bt_component_get_port_by_index(comp->input_ports, index);
72b913fb 454}
366e034f 455
72b913fb 456BT_HIDDEN
9ac68eb1
PP
457struct bt_port *bt_component_get_output_port_by_index(struct bt_component *comp,
458 uint64_t index)
72b913fb
PP
459{
460 assert(comp);
366e034f 461
9ac68eb1 462 return bt_component_get_port_by_index(comp->output_ports, index);
72b913fb 463}
366e034f 464
72b913fb
PP
465BT_HIDDEN
466struct bt_port *bt_component_add_input_port(
3e9b0023
PP
467 struct bt_component *component, const char *name,
468 void *user_data)
72b913fb
PP
469{
470 return bt_component_add_port(component, component->input_ports,
3e9b0023 471 BT_PORT_TYPE_INPUT, name, user_data);
72b913fb 472}
366e034f 473
72b913fb
PP
474BT_HIDDEN
475struct bt_port *bt_component_add_output_port(
3e9b0023
PP
476 struct bt_component *component, const char *name,
477 void *user_data)
72b913fb
PP
478{
479 return bt_component_add_port(component, component->output_ports,
3e9b0023 480 BT_PORT_TYPE_OUTPUT, name, user_data);
72b913fb
PP
481}
482
483static
9ac68eb1 484void bt_component_remove_port_by_index(struct bt_component *component,
72b913fb
PP
485 GPtrArray *ports, size_t index)
486{
487 struct bt_port *port;
1bf957a0 488 struct bt_graph *graph;
72b913fb
PP
489
490 assert(ports);
491 assert(index < ports->len);
492 port = g_ptr_array_index(ports, index);
493
494 /* Disconnect both ports of this port's connection, if any */
495 if (port->connection) {
2038affb 496 bt_connection_disconnect_ports(port->connection);
f60c8b34
JG
497 }
498
72b913fb
PP
499 /* Remove from parent's array of ports (weak refs) */
500 g_ptr_array_remove_index(ports, index);
501
502 /* Detach port from its component parent */
503 BT_PUT(port->base.parent);
504
1bf957a0
PP
505 /*
506 * Notify the graph's creator that a port is removed.
507 */
508 graph = bt_component_get_graph(component);
509 if (graph) {
510 bt_graph_notify_port_removed(graph, component, port);
511 BT_PUT(graph);
512 }
366e034f
JG
513}
514
515BT_HIDDEN
516enum bt_component_status bt_component_remove_port(
72b913fb 517 struct bt_component *component, struct bt_port *port)
366e034f
JG
518{
519 size_t i;
520 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
72b913fb 521 GPtrArray *ports = NULL;
366e034f 522
72b913fb 523 if (!component || !port) {
366e034f
JG
524 status = BT_COMPONENT_STATUS_INVALID;
525 goto end;
526 }
527
72b913fb
PP
528 if (bt_port_get_type(port) == BT_PORT_TYPE_INPUT) {
529 ports = component->input_ports;
530 } else if (bt_port_get_type(port) == BT_PORT_TYPE_OUTPUT) {
531 ports = component->output_ports;
532 }
366e034f 533
72b913fb 534 assert(ports);
366e034f 535
72b913fb
PP
536 for (i = 0; i < ports->len; i++) {
537 struct bt_port *cur_port = g_ptr_array_index(ports, i);
538
539 if (cur_port == port) {
9ac68eb1 540 bt_component_remove_port_by_index(component,
72b913fb 541 ports, i);
366e034f
JG
542 goto end;
543 }
544 }
72b913fb 545
366e034f
JG
546 status = BT_COMPONENT_STATUS_NOT_FOUND;
547end:
548 return status;
549}
f60c8b34
JG
550
551BT_HIDDEN
72b913fb 552enum bt_component_status bt_component_accept_port_connection(
8f4799f7
PP
553 struct bt_component *comp, struct bt_port *self_port,
554 struct bt_port *other_port)
f60c8b34
JG
555{
556 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
557
72b913fb 558 assert(comp);
8f4799f7
PP
559 assert(self_port);
560 assert(other_port);
72b913fb
PP
561
562 if (comp->class->methods.accept_port_connection) {
563 status = comp->class->methods.accept_port_connection(
890882ef 564 bt_private_component_from_component(comp),
8f4799f7
PP
565 bt_private_port_from_port(self_port),
566 other_port);
f60c8b34
JG
567 }
568
569 return status;
570}
72b913fb 571
0d8b4d8e
PP
572BT_HIDDEN
573void bt_component_port_connected(struct bt_component *comp,
574 struct bt_port *self_port, struct bt_port *other_port)
575{
576 assert(comp);
577 assert(self_port);
578 assert(other_port);
579
580 if (comp->class->methods.port_connected) {
581 comp->class->methods.port_connected(
582 bt_private_component_from_component(comp),
583 bt_private_port_from_port(self_port), other_port);
584 }
585}
586
72b913fb
PP
587BT_HIDDEN
588void bt_component_port_disconnected(struct bt_component *comp,
589 struct bt_port *port)
590{
591 assert(comp);
592 assert(port);
593
594 if (comp->class->methods.port_disconnected) {
890882ef
PP
595 comp->class->methods.port_disconnected(
596 bt_private_component_from_component(comp),
597 bt_private_port_from_port(port));
72b913fb
PP
598 }
599}
3230ee6b
PP
600
601BT_HIDDEN
602void bt_component_add_destroy_listener(struct bt_component *component,
603 bt_component_destroy_listener_func func, void *data)
604{
605 struct bt_component_destroy_listener listener;
606
607 assert(component);
608 assert(func);
609 listener.func = func;
610 listener.data = data;
611 g_array_append_val(component->destroy_listeners, listener);
612}
613
614BT_HIDDEN
615void bt_component_remove_destroy_listener(struct bt_component *component,
616 bt_component_destroy_listener_func func, void *data)
617{
618 size_t i;
619
620 assert(component);
621 assert(func);
622
623 for (i = 0; i < component->destroy_listeners->len; i++) {
624 struct bt_component_destroy_listener *listener =
625 &g_array_index(component->destroy_listeners,
626 struct bt_component_destroy_listener, i);
627
628 if (listener->func == func && listener->data == data) {
629 g_array_remove_index(component->destroy_listeners, i);
630 i--;
631 }
632 }
633}
This page took 0.058738 seconds and 4 git commands to generate.