Rename text.text sink CC to text.pretty
[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
JG
197
198 if (!component_class) {
199 goto end;
200 }
201
7c7c0433 202 type = bt_component_class_get_type(component_class);
d3e4dcd8
PP
203 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
204 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
7c7c0433
JG
205 goto end;
206 }
207
208 component = component_create_funcs[type](component_class, params);
209 if (!component) {
210 goto end;
211 }
212
213 bt_object_init(component, bt_component_destroy);
72b913fb
PP
214 component->class = bt_get(component_class);
215 component->destroy = component_destroy_funcs[type];
7c7c0433 216 component->name = g_string_new(name);
4b70dd83 217 if (!component->name) {
7c7c0433
JG
218 BT_PUT(component);
219 goto end;
220 }
221
72b913fb
PP
222 component->input_ports = g_ptr_array_new_with_free_func(
223 bt_object_release);
224 if (!component->input_ports) {
225 BT_PUT(component);
226 goto end;
227 }
228
229 component->output_ports = g_ptr_array_new_with_free_func(
230 bt_object_release);
231 if (!component->output_ports) {
232 BT_PUT(component);
233 goto end;
234 }
235
236 if (type == BT_COMPONENT_CLASS_TYPE_SOURCE ||
237 type == BT_COMPONENT_CLASS_TYPE_FILTER) {
238 default_port = bt_component_add_port(component,
239 component->output_ports, BT_PORT_TYPE_OUTPUT,
240 DEFAULT_OUTPUT_PORT_NAME);
241 if (!default_port) {
242 BT_PUT(component);
243 goto end;
244 }
245
246 BT_PUT(default_port);
247 }
248
249 if (type == BT_COMPONENT_CLASS_TYPE_FILTER ||
250 type == BT_COMPONENT_CLASS_TYPE_SINK) {
251 default_port = bt_component_add_port(component,
252 component->input_ports, BT_PORT_TYPE_INPUT,
253 DEFAULT_INPUT_PORT_NAME);
254 if (!default_port) {
255 BT_PUT(component);
256 goto end;
257 }
258
259 BT_PUT(default_port);
260 }
261
262 component->initializing = true;
263
d3e4dcd8 264 if (component_class->methods.init) {
890882ef
PP
265 ret = component_class->methods.init(
266 bt_private_component_from_component(component), params,
6358c163 267 init_method_data);
d3e4dcd8
PP
268 component->initializing = false;
269 if (ret != BT_COMPONENT_STATUS_OK) {
270 BT_PUT(component);
271 goto end;
272 }
528debdf 273 }
d3e4dcd8
PP
274
275 component->initializing = false;
7c7c0433 276 ret = component_validation_funcs[type](component);
692b38d2 277 if (ret != BT_COMPONENT_STATUS_OK) {
7c7c0433 278 BT_PUT(component);
38b48196
JG
279 goto end;
280 }
1e4d8103
PP
281
282 bt_component_class_freeze(component->class);
38b48196 283end:
72b913fb 284 bt_put(default_port);
38b48196
JG
285 return component;
286}
287
6358c163
PP
288struct bt_component *bt_component_create(
289 struct bt_component_class *component_class, const char *name,
290 struct bt_value *params)
291{
292 return bt_component_create_with_init_method_data(component_class, name,
293 params, NULL);
294}
295
de713ce0
JG
296const char *bt_component_get_name(struct bt_component *component)
297{
298 const char *ret = NULL;
299
300 if (!component) {
301 goto end;
302 }
303
f1222e7d 304 ret = component->name->len == 0 ? NULL : component->name->str;
de713ce0
JG
305end:
306 return ret;
307}
308
309enum bt_component_status bt_component_set_name(struct bt_component *component,
310 const char *name)
311{
312 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
313
314 if (!component || !name || name[0] == '\0') {
30d619df 315 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
316 goto end;
317 }
318
319 g_string_assign(component->name, name);
320end:
321 return ret;
322}
323
38b48196
JG
324struct bt_component_class *bt_component_get_class(
325 struct bt_component *component)
de713ce0 326{
38b48196 327 return component ? bt_get(component->class) : NULL;
de713ce0
JG
328}
329
890882ef
PP
330void *bt_private_component_get_user_data(
331 struct bt_private_component *private_component)
de713ce0 332{
890882ef
PP
333 struct bt_component *component =
334 bt_component_from_private(private_component);
335
38b48196 336 return component ? component->user_data : NULL;
de713ce0
JG
337}
338
890882ef
PP
339enum bt_component_status bt_private_component_set_user_data(
340 struct bt_private_component *private_component,
de713ce0
JG
341 void *data)
342{
890882ef
PP
343 struct bt_component *component =
344 bt_component_from_private(private_component);
de713ce0
JG
345 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
346
fec2a9f2 347 if (!component || !component->initializing) {
30d619df 348 ret = BT_COMPONENT_STATUS_INVALID;
de713ce0
JG
349 goto end;
350 }
351
352 component->user_data = data;
353end:
354 return ret;
355}
366e034f
JG
356
357BT_HIDDEN
f60c8b34 358void bt_component_set_graph(struct bt_component *component,
366e034f
JG
359 struct bt_graph *graph)
360{
f60c8b34
JG
361 struct bt_object *parent = bt_object_get_parent(&component->base);
362
363 assert(!parent || parent == &graph->base);
364 if (!parent) {
365 bt_object_set_parent(component, &graph->base);
366 }
367 bt_put(parent);
366e034f
JG
368}
369
370struct bt_graph *bt_component_get_graph(
371 struct bt_component *component)
372{
373 return (struct bt_graph *) bt_object_get_parent(&component->base);
374}
375
72b913fb 376static
366e034f
JG
377struct bt_port *bt_component_get_port(GPtrArray *ports, const char *name)
378{
379 size_t i;
380 struct bt_port *ret_port = NULL;
381
72b913fb
PP
382 assert(name);
383
366e034f
JG
384 for (i = 0; i < ports->len; i++) {
385 struct bt_port *port = g_ptr_array_index(ports, i);
386 const char *port_name = bt_port_get_name(port);
387
388 if (!port_name) {
389 continue;
390 }
391
392 if (!strcmp(name, port_name)) {
393 ret_port = bt_get(port);
394 break;
395 }
396 }
397
398 return ret_port;
399}
400
401BT_HIDDEN
72b913fb
PP
402struct bt_port *bt_component_get_input_port(struct bt_component *comp,
403 const char *name)
404{
405 assert(comp);
406
407 return bt_component_get_port(comp->input_ports, name);
408}
409
410BT_HIDDEN
411struct bt_port *bt_component_get_output_port(struct bt_component *comp,
412 const char *name)
413{
414 assert(comp);
415
416 return bt_component_get_port(comp->output_ports, name);
417}
418
419static
366e034f
JG
420struct bt_port *bt_component_get_port_at_index(GPtrArray *ports, int index)
421{
422 struct bt_port *port = NULL;
423
424 if (index < 0 || index >= ports->len) {
425 goto end;
426 }
427
428 port = bt_get(g_ptr_array_index(ports, index));
429end:
430 return port;
431}
432
433BT_HIDDEN
72b913fb
PP
434struct bt_port *bt_component_get_input_port_at_index(struct bt_component *comp,
435 int index)
366e034f 436{
72b913fb 437 assert(comp);
366e034f 438
72b913fb
PP
439 return bt_component_get_port_at_index(comp->input_ports, index);
440}
366e034f 441
72b913fb
PP
442BT_HIDDEN
443struct bt_port *bt_component_get_output_port_at_index(struct bt_component *comp,
444 int index)
445{
446 assert(comp);
366e034f 447
72b913fb
PP
448 return bt_component_get_port_at_index(comp->output_ports, index);
449}
366e034f 450
72b913fb
PP
451BT_HIDDEN
452struct bt_port *bt_component_add_input_port(
453 struct bt_component *component, const char *name)
454{
455 return bt_component_add_port(component, component->input_ports,
456 BT_PORT_TYPE_INPUT, name);
457}
366e034f 458
72b913fb
PP
459BT_HIDDEN
460struct bt_port *bt_component_add_output_port(
461 struct bt_component *component, const char *name)
462{
463 return bt_component_add_port(component, component->output_ports,
464 BT_PORT_TYPE_OUTPUT, name);
465}
466
467static
468void bt_component_remove_port_at_index(struct bt_component *component,
469 GPtrArray *ports, size_t index)
470{
471 struct bt_port *port;
1bf957a0 472 struct bt_graph *graph;
72b913fb
PP
473
474 assert(ports);
475 assert(index < ports->len);
476 port = g_ptr_array_index(ports, index);
477
478 /* Disconnect both ports of this port's connection, if any */
479 if (port->connection) {
2038affb 480 bt_connection_disconnect_ports(port->connection);
f60c8b34
JG
481 }
482
72b913fb
PP
483 /* Remove from parent's array of ports (weak refs) */
484 g_ptr_array_remove_index(ports, index);
485
486 /* Detach port from its component parent */
487 BT_PUT(port->base.parent);
488
1bf957a0
PP
489 /*
490 * Notify the graph's creator that a port is removed.
491 */
492 graph = bt_component_get_graph(component);
493 if (graph) {
494 bt_graph_notify_port_removed(graph, component, port);
495 BT_PUT(graph);
496 }
366e034f
JG
497}
498
499BT_HIDDEN
500enum bt_component_status bt_component_remove_port(
72b913fb 501 struct bt_component *component, struct bt_port *port)
366e034f
JG
502{
503 size_t i;
504 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
72b913fb 505 GPtrArray *ports = NULL;
366e034f 506
72b913fb 507 if (!component || !port) {
366e034f
JG
508 status = BT_COMPONENT_STATUS_INVALID;
509 goto end;
510 }
511
72b913fb
PP
512 if (bt_port_get_type(port) == BT_PORT_TYPE_INPUT) {
513 ports = component->input_ports;
514 } else if (bt_port_get_type(port) == BT_PORT_TYPE_OUTPUT) {
515 ports = component->output_ports;
516 }
366e034f 517
72b913fb 518 assert(ports);
366e034f 519
72b913fb
PP
520 for (i = 0; i < ports->len; i++) {
521 struct bt_port *cur_port = g_ptr_array_index(ports, i);
522
523 if (cur_port == port) {
524 bt_component_remove_port_at_index(component,
525 ports, i);
366e034f
JG
526 goto end;
527 }
528 }
72b913fb 529
366e034f
JG
530 status = BT_COMPONENT_STATUS_NOT_FOUND;
531end:
532 return status;
533}
f60c8b34
JG
534
535BT_HIDDEN
72b913fb 536enum bt_component_status bt_component_accept_port_connection(
8f4799f7
PP
537 struct bt_component *comp, struct bt_port *self_port,
538 struct bt_port *other_port)
f60c8b34
JG
539{
540 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
541
72b913fb 542 assert(comp);
8f4799f7
PP
543 assert(self_port);
544 assert(other_port);
72b913fb
PP
545
546 if (comp->class->methods.accept_port_connection) {
547 status = comp->class->methods.accept_port_connection(
890882ef 548 bt_private_component_from_component(comp),
8f4799f7
PP
549 bt_private_port_from_port(self_port),
550 other_port);
f60c8b34
JG
551 }
552
553 return status;
554}
72b913fb
PP
555
556BT_HIDDEN
557void bt_component_port_disconnected(struct bt_component *comp,
558 struct bt_port *port)
559{
560 assert(comp);
561 assert(port);
562
563 if (comp->class->methods.port_disconnected) {
890882ef
PP
564 comp->class->methods.port_disconnected(
565 bt_private_component_from_component(comp),
566 bt_private_port_from_port(port));
72b913fb
PP
567 }
568}
This page took 0.052629 seconds and 4 git commands to generate.