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