Remove bt_ctf_stream_class_get_event_class_by_name()
[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,
138 enum bt_port_type port_type, const char *name)
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
165 new_port = bt_port_create(component, port_type, name);
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;
72b913fb 212 struct bt_port *default_port = NULL;
38b48196 213
0df078e5
PP
214 bt_get(params);
215
38b48196
JG
216 if (!component_class) {
217 goto end;
218 }
219
7c7c0433 220 type = bt_component_class_get_type(component_class);
d3e4dcd8
PP
221 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
222 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
7c7c0433
JG
223 goto end;
224 }
225
0df078e5
PP
226 /*
227 * Parameters must be a map value, but we create a convenient
228 * empty one if it's NULL.
229 */
230 if (params) {
231 if (!bt_value_is_map(params)) {
232 goto end;
233 }
234 } else {
235 params = bt_value_map_create();
236 if (!params) {
237 goto end;
238 }
239 }
240
7c7c0433
JG
241 component = component_create_funcs[type](component_class, params);
242 if (!component) {
243 goto end;
244 }
245
246 bt_object_init(component, bt_component_destroy);
72b913fb
PP
247 component->class = bt_get(component_class);
248 component->destroy = component_destroy_funcs[type];
7c7c0433 249 component->name = g_string_new(name);
4b70dd83 250 if (!component->name) {
7c7c0433
JG
251 BT_PUT(component);
252 goto end;
253 }
254
72b913fb
PP
255 component->input_ports = g_ptr_array_new_with_free_func(
256 bt_object_release);
257 if (!component->input_ports) {
258 BT_PUT(component);
259 goto end;
260 }
261
262 component->output_ports = g_ptr_array_new_with_free_func(
263 bt_object_release);
264 if (!component->output_ports) {
265 BT_PUT(component);
266 goto end;
267 }
268
3230ee6b
PP
269 component->destroy_listeners = g_array_new(FALSE, TRUE,
270 sizeof(struct bt_component_destroy_listener));
271 if (!component->destroy_listeners) {
272 BT_PUT(component);
273 goto end;
274 }
275
72b913fb
PP
276 if (type == BT_COMPONENT_CLASS_TYPE_SOURCE ||
277 type == BT_COMPONENT_CLASS_TYPE_FILTER) {
278 default_port = bt_component_add_port(component,
279 component->output_ports, BT_PORT_TYPE_OUTPUT,
280 DEFAULT_OUTPUT_PORT_NAME);
281 if (!default_port) {
282 BT_PUT(component);
283 goto end;
284 }
285
286 BT_PUT(default_port);
287 }
288
289 if (type == BT_COMPONENT_CLASS_TYPE_FILTER ||
290 type == BT_COMPONENT_CLASS_TYPE_SINK) {
291 default_port = bt_component_add_port(component,
292 component->input_ports, BT_PORT_TYPE_INPUT,
293 DEFAULT_INPUT_PORT_NAME);
294 if (!default_port) {
295 BT_PUT(component);
296 goto end;
297 }
298
299 BT_PUT(default_port);
300 }
301
302 component->initializing = true;
303
d3e4dcd8 304 if (component_class->methods.init) {
890882ef
PP
305 ret = component_class->methods.init(
306 bt_private_component_from_component(component), params,
6358c163 307 init_method_data);
d3e4dcd8
PP
308 component->initializing = false;
309 if (ret != BT_COMPONENT_STATUS_OK) {
310 BT_PUT(component);
311 goto end;
312 }
528debdf 313 }
d3e4dcd8
PP
314
315 component->initializing = false;
7c7c0433 316 ret = component_validation_funcs[type](component);
692b38d2 317 if (ret != BT_COMPONENT_STATUS_OK) {
7c7c0433 318 BT_PUT(component);
38b48196
JG
319 goto end;
320 }
1e4d8103
PP
321
322 bt_component_class_freeze(component->class);
38b48196 323end:
0df078e5 324 bt_put(params);
72b913fb 325 bt_put(default_port);
38b48196
JG
326 return component;
327}
328
6358c163
PP
329struct bt_component *bt_component_create(
330 struct bt_component_class *component_class, const char *name,
331 struct bt_value *params)
332{
333 return bt_component_create_with_init_method_data(component_class, name,
334 params, NULL);
335}
336
de713ce0
JG
337const char *bt_component_get_name(struct bt_component *component)
338{
339 const char *ret = NULL;
340
341 if (!component) {
342 goto end;
343 }
344
f1222e7d 345 ret = component->name->len == 0 ? NULL : component->name->str;
de713ce0
JG
346end:
347 return ret;
348}
349
350enum bt_component_status bt_component_set_name(struct bt_component *component,
351 const char *name)
352{
353 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
354
355 if (!component || !name || name[0] == '\0') {
30d619df 356 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
357 goto end;
358 }
359
360 g_string_assign(component->name, name);
361end:
362 return ret;
363}
364
38b48196
JG
365struct bt_component_class *bt_component_get_class(
366 struct bt_component *component)
de713ce0 367{
38b48196 368 return component ? bt_get(component->class) : NULL;
de713ce0
JG
369}
370
890882ef
PP
371void *bt_private_component_get_user_data(
372 struct bt_private_component *private_component)
de713ce0 373{
890882ef
PP
374 struct bt_component *component =
375 bt_component_from_private(private_component);
376
38b48196 377 return component ? component->user_data : NULL;
de713ce0
JG
378}
379
890882ef
PP
380enum bt_component_status bt_private_component_set_user_data(
381 struct bt_private_component *private_component,
de713ce0
JG
382 void *data)
383{
890882ef
PP
384 struct bt_component *component =
385 bt_component_from_private(private_component);
de713ce0
JG
386 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
387
fec2a9f2 388 if (!component || !component->initializing) {
30d619df 389 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
390 goto end;
391 }
392
393 component->user_data = data;
394end:
395 return ret;
396}
366e034f
JG
397
398BT_HIDDEN
f60c8b34 399void bt_component_set_graph(struct bt_component *component,
366e034f
JG
400 struct bt_graph *graph)
401{
f60c8b34
JG
402 struct bt_object *parent = bt_object_get_parent(&component->base);
403
404 assert(!parent || parent == &graph->base);
405 if (!parent) {
406 bt_object_set_parent(component, &graph->base);
407 }
408 bt_put(parent);
366e034f
JG
409}
410
411struct bt_graph *bt_component_get_graph(
412 struct bt_component *component)
413{
414 return (struct bt_graph *) bt_object_get_parent(&component->base);
415}
416
72b913fb 417static
9ac68eb1
PP
418struct bt_port *bt_component_get_port_by_name(GPtrArray *ports,
419 const char *name)
366e034f
JG
420{
421 size_t i;
422 struct bt_port *ret_port = NULL;
423
72b913fb
PP
424 assert(name);
425
366e034f
JG
426 for (i = 0; i < ports->len; i++) {
427 struct bt_port *port = g_ptr_array_index(ports, i);
428 const char *port_name = bt_port_get_name(port);
429
430 if (!port_name) {
431 continue;
432 }
433
434 if (!strcmp(name, port_name)) {
435 ret_port = bt_get(port);
436 break;
437 }
438 }
439
440 return ret_port;
441}
442
443BT_HIDDEN
9ac68eb1 444struct bt_port *bt_component_get_input_port_by_name(struct bt_component *comp,
72b913fb
PP
445 const char *name)
446{
447 assert(comp);
448
9ac68eb1 449 return bt_component_get_port_by_name(comp->input_ports, name);
72b913fb
PP
450}
451
452BT_HIDDEN
9ac68eb1 453struct bt_port *bt_component_get_output_port_by_name(struct bt_component *comp,
72b913fb
PP
454 const char *name)
455{
456 assert(comp);
457
9ac68eb1 458 return bt_component_get_port_by_name(comp->output_ports, name);
72b913fb
PP
459}
460
461static
9ac68eb1 462struct bt_port *bt_component_get_port_by_index(GPtrArray *ports, uint64_t index)
366e034f
JG
463{
464 struct bt_port *port = NULL;
465
9ac68eb1 466 if (index >= ports->len) {
366e034f
JG
467 goto end;
468 }
469
470 port = bt_get(g_ptr_array_index(ports, index));
471end:
472 return port;
473}
474
475BT_HIDDEN
9ac68eb1
PP
476struct bt_port *bt_component_get_input_port_by_index(struct bt_component *comp,
477 uint64_t index)
366e034f 478{
72b913fb 479 assert(comp);
366e034f 480
9ac68eb1 481 return bt_component_get_port_by_index(comp->input_ports, index);
72b913fb 482}
366e034f 483
72b913fb 484BT_HIDDEN
9ac68eb1
PP
485struct bt_port *bt_component_get_output_port_by_index(struct bt_component *comp,
486 uint64_t index)
72b913fb
PP
487{
488 assert(comp);
366e034f 489
9ac68eb1 490 return bt_component_get_port_by_index(comp->output_ports, index);
72b913fb 491}
366e034f 492
72b913fb
PP
493BT_HIDDEN
494struct bt_port *bt_component_add_input_port(
495 struct bt_component *component, const char *name)
496{
497 return bt_component_add_port(component, component->input_ports,
498 BT_PORT_TYPE_INPUT, name);
499}
366e034f 500
72b913fb
PP
501BT_HIDDEN
502struct bt_port *bt_component_add_output_port(
503 struct bt_component *component, const char *name)
504{
505 return bt_component_add_port(component, component->output_ports,
506 BT_PORT_TYPE_OUTPUT, name);
507}
508
509static
9ac68eb1 510void bt_component_remove_port_by_index(struct bt_component *component,
72b913fb
PP
511 GPtrArray *ports, size_t index)
512{
513 struct bt_port *port;
1bf957a0 514 struct bt_graph *graph;
72b913fb
PP
515
516 assert(ports);
517 assert(index < ports->len);
518 port = g_ptr_array_index(ports, index);
519
520 /* Disconnect both ports of this port's connection, if any */
521 if (port->connection) {
2038affb 522 bt_connection_disconnect_ports(port->connection);
f60c8b34
JG
523 }
524
72b913fb
PP
525 /* Remove from parent's array of ports (weak refs) */
526 g_ptr_array_remove_index(ports, index);
527
528 /* Detach port from its component parent */
529 BT_PUT(port->base.parent);
530
1bf957a0
PP
531 /*
532 * Notify the graph's creator that a port is removed.
533 */
534 graph = bt_component_get_graph(component);
535 if (graph) {
536 bt_graph_notify_port_removed(graph, component, port);
537 BT_PUT(graph);
538 }
366e034f
JG
539}
540
541BT_HIDDEN
542enum bt_component_status bt_component_remove_port(
72b913fb 543 struct bt_component *component, struct bt_port *port)
366e034f
JG
544{
545 size_t i;
546 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
72b913fb 547 GPtrArray *ports = NULL;
366e034f 548
72b913fb 549 if (!component || !port) {
366e034f
JG
550 status = BT_COMPONENT_STATUS_INVALID;
551 goto end;
552 }
553
72b913fb
PP
554 if (bt_port_get_type(port) == BT_PORT_TYPE_INPUT) {
555 ports = component->input_ports;
556 } else if (bt_port_get_type(port) == BT_PORT_TYPE_OUTPUT) {
557 ports = component->output_ports;
558 }
366e034f 559
72b913fb 560 assert(ports);
366e034f 561
72b913fb
PP
562 for (i = 0; i < ports->len; i++) {
563 struct bt_port *cur_port = g_ptr_array_index(ports, i);
564
565 if (cur_port == port) {
9ac68eb1 566 bt_component_remove_port_by_index(component,
72b913fb 567 ports, i);
366e034f
JG
568 goto end;
569 }
570 }
72b913fb 571
366e034f
JG
572 status = BT_COMPONENT_STATUS_NOT_FOUND;
573end:
574 return status;
575}
f60c8b34
JG
576
577BT_HIDDEN
72b913fb 578enum bt_component_status bt_component_accept_port_connection(
8f4799f7
PP
579 struct bt_component *comp, struct bt_port *self_port,
580 struct bt_port *other_port)
f60c8b34
JG
581{
582 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
583
72b913fb 584 assert(comp);
8f4799f7
PP
585 assert(self_port);
586 assert(other_port);
72b913fb
PP
587
588 if (comp->class->methods.accept_port_connection) {
589 status = comp->class->methods.accept_port_connection(
890882ef 590 bt_private_component_from_component(comp),
8f4799f7
PP
591 bt_private_port_from_port(self_port),
592 other_port);
f60c8b34
JG
593 }
594
595 return status;
596}
72b913fb 597
0d8b4d8e
PP
598BT_HIDDEN
599void bt_component_port_connected(struct bt_component *comp,
600 struct bt_port *self_port, struct bt_port *other_port)
601{
602 assert(comp);
603 assert(self_port);
604 assert(other_port);
605
606 if (comp->class->methods.port_connected) {
607 comp->class->methods.port_connected(
608 bt_private_component_from_component(comp),
609 bt_private_port_from_port(self_port), other_port);
610 }
611}
612
72b913fb
PP
613BT_HIDDEN
614void bt_component_port_disconnected(struct bt_component *comp,
615 struct bt_port *port)
616{
617 assert(comp);
618 assert(port);
619
620 if (comp->class->methods.port_disconnected) {
890882ef
PP
621 comp->class->methods.port_disconnected(
622 bt_private_component_from_component(comp),
623 bt_private_port_from_port(port));
72b913fb
PP
624 }
625}
3230ee6b
PP
626
627BT_HIDDEN
628void bt_component_add_destroy_listener(struct bt_component *component,
629 bt_component_destroy_listener_func func, void *data)
630{
631 struct bt_component_destroy_listener listener;
632
633 assert(component);
634 assert(func);
635 listener.func = func;
636 listener.data = data;
637 g_array_append_val(component->destroy_listeners, listener);
638}
639
640BT_HIDDEN
641void bt_component_remove_destroy_listener(struct bt_component *component,
642 bt_component_destroy_listener_func func, void *data)
643{
644 size_t i;
645
646 assert(component);
647 assert(func);
648
649 for (i = 0; i < component->destroy_listeners->len; i++) {
650 struct bt_component_destroy_listener *listener =
651 &g_array_index(component->destroy_listeners,
652 struct bt_component_destroy_listener, i);
653
654 if (listener->func == func && listener->data == data) {
655 g_array_remove_index(component->destroy_listeners, i);
656 i--;
657 }
658 }
659}
This page took 0.057239 seconds and 4 git commands to generate.