Set private port's user data on creation
[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;
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,
3e9b0023 280 DEFAULT_OUTPUT_PORT_NAME, NULL);
72b913fb
PP
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,
3e9b0023 293 DEFAULT_INPUT_PORT_NAME, NULL);
72b913fb
PP
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(
3e9b0023
PP
495 struct bt_component *component, const char *name,
496 void *user_data)
72b913fb
PP
497{
498 return bt_component_add_port(component, component->input_ports,
3e9b0023 499 BT_PORT_TYPE_INPUT, name, user_data);
72b913fb 500}
366e034f 501
72b913fb
PP
502BT_HIDDEN
503struct bt_port *bt_component_add_output_port(
3e9b0023
PP
504 struct bt_component *component, const char *name,
505 void *user_data)
72b913fb
PP
506{
507 return bt_component_add_port(component, component->output_ports,
3e9b0023 508 BT_PORT_TYPE_OUTPUT, name, user_data);
72b913fb
PP
509}
510
511static
9ac68eb1 512void bt_component_remove_port_by_index(struct bt_component *component,
72b913fb
PP
513 GPtrArray *ports, size_t index)
514{
515 struct bt_port *port;
1bf957a0 516 struct bt_graph *graph;
72b913fb
PP
517
518 assert(ports);
519 assert(index < ports->len);
520 port = g_ptr_array_index(ports, index);
521
522 /* Disconnect both ports of this port's connection, if any */
523 if (port->connection) {
2038affb 524 bt_connection_disconnect_ports(port->connection);
f60c8b34
JG
525 }
526
72b913fb
PP
527 /* Remove from parent's array of ports (weak refs) */
528 g_ptr_array_remove_index(ports, index);
529
530 /* Detach port from its component parent */
531 BT_PUT(port->base.parent);
532
1bf957a0
PP
533 /*
534 * Notify the graph's creator that a port is removed.
535 */
536 graph = bt_component_get_graph(component);
537 if (graph) {
538 bt_graph_notify_port_removed(graph, component, port);
539 BT_PUT(graph);
540 }
366e034f
JG
541}
542
543BT_HIDDEN
544enum bt_component_status bt_component_remove_port(
72b913fb 545 struct bt_component *component, struct bt_port *port)
366e034f
JG
546{
547 size_t i;
548 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
72b913fb 549 GPtrArray *ports = NULL;
366e034f 550
72b913fb 551 if (!component || !port) {
366e034f
JG
552 status = BT_COMPONENT_STATUS_INVALID;
553 goto end;
554 }
555
72b913fb
PP
556 if (bt_port_get_type(port) == BT_PORT_TYPE_INPUT) {
557 ports = component->input_ports;
558 } else if (bt_port_get_type(port) == BT_PORT_TYPE_OUTPUT) {
559 ports = component->output_ports;
560 }
366e034f 561
72b913fb 562 assert(ports);
366e034f 563
72b913fb
PP
564 for (i = 0; i < ports->len; i++) {
565 struct bt_port *cur_port = g_ptr_array_index(ports, i);
566
567 if (cur_port == port) {
9ac68eb1 568 bt_component_remove_port_by_index(component,
72b913fb 569 ports, i);
366e034f
JG
570 goto end;
571 }
572 }
72b913fb 573
366e034f
JG
574 status = BT_COMPONENT_STATUS_NOT_FOUND;
575end:
576 return status;
577}
f60c8b34
JG
578
579BT_HIDDEN
72b913fb 580enum bt_component_status bt_component_accept_port_connection(
8f4799f7
PP
581 struct bt_component *comp, struct bt_port *self_port,
582 struct bt_port *other_port)
f60c8b34
JG
583{
584 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
585
72b913fb 586 assert(comp);
8f4799f7
PP
587 assert(self_port);
588 assert(other_port);
72b913fb
PP
589
590 if (comp->class->methods.accept_port_connection) {
591 status = comp->class->methods.accept_port_connection(
890882ef 592 bt_private_component_from_component(comp),
8f4799f7
PP
593 bt_private_port_from_port(self_port),
594 other_port);
f60c8b34
JG
595 }
596
597 return status;
598}
72b913fb 599
0d8b4d8e
PP
600BT_HIDDEN
601void bt_component_port_connected(struct bt_component *comp,
602 struct bt_port *self_port, struct bt_port *other_port)
603{
604 assert(comp);
605 assert(self_port);
606 assert(other_port);
607
608 if (comp->class->methods.port_connected) {
609 comp->class->methods.port_connected(
610 bt_private_component_from_component(comp),
611 bt_private_port_from_port(self_port), other_port);
612 }
613}
614
72b913fb
PP
615BT_HIDDEN
616void bt_component_port_disconnected(struct bt_component *comp,
617 struct bt_port *port)
618{
619 assert(comp);
620 assert(port);
621
622 if (comp->class->methods.port_disconnected) {
890882ef
PP
623 comp->class->methods.port_disconnected(
624 bt_private_component_from_component(comp),
625 bt_private_port_from_port(port));
72b913fb
PP
626 }
627}
3230ee6b
PP
628
629BT_HIDDEN
630void bt_component_add_destroy_listener(struct bt_component *component,
631 bt_component_destroy_listener_func func, void *data)
632{
633 struct bt_component_destroy_listener listener;
634
635 assert(component);
636 assert(func);
637 listener.func = func;
638 listener.data = data;
639 g_array_append_val(component->destroy_listeners, listener);
640}
641
642BT_HIDDEN
643void bt_component_remove_destroy_listener(struct bt_component *component,
644 bt_component_destroy_listener_func func, void *data)
645{
646 size_t i;
647
648 assert(component);
649 assert(func);
650
651 for (i = 0; i < component->destroy_listeners->len; i++) {
652 struct bt_component_destroy_listener *listener =
653 &g_array_index(component->destroy_listeners,
654 struct bt_component_destroy_listener, i);
655
656 if (listener->func == func && listener->data == data) {
657 g_array_remove_index(component->destroy_listeners, i);
658 i--;
659 }
660 }
661}
This page took 0.059539 seconds and 4 git commands to generate.