Standardize *get_*() functions
[babeltrace.git] / lib / graph / component.c
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
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>
41 #include <babeltrace/babeltrace-internal.h>
42 #include <babeltrace/compiler-internal.h>
43 #include <babeltrace/ref.h>
44 #include <stdint.h>
45
46 static
47 struct bt_component * (* const component_create_funcs[])(
48 struct bt_component_class *, struct bt_value *) = {
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,
52 };
53
54 static
55 void (*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
61 static
62 enum bt_component_status (* const component_validation_funcs[])(
63 struct bt_component *) = {
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,
67 };
68
69 static
70 void bt_component_destroy(struct bt_object *obj)
71 {
72 struct bt_component *component = NULL;
73 struct bt_component_class *component_class = NULL;
74 int i;
75
76 if (!obj) {
77 return;
78 }
79
80 component = container_of(obj, struct bt_component, base);
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
91 component_class = component->class;
92
93 /*
94 * User data is destroyed first, followed by the concrete component
95 * instance.
96 */
97 if (component->class->methods.finalize) {
98 component->class->methods.finalize(
99 bt_private_component_from_component(component));
100 }
101
102 if (component->destroy) {
103 component->destroy(component);
104 }
105
106 if (component->input_ports) {
107 g_ptr_array_free(component->input_ports, TRUE);
108 }
109
110 if (component->output_ports) {
111 g_ptr_array_free(component->output_ports, TRUE);
112 }
113
114 if (component->destroy_listeners) {
115 g_array_free(component->destroy_listeners, TRUE);
116 }
117
118 g_string_free(component->name, TRUE);
119 bt_put(component_class);
120 g_free(component);
121 }
122
123 struct bt_component *bt_component_from_private_component(
124 struct bt_private_component *private_component)
125 {
126 return bt_get(bt_component_from_private(private_component));
127 }
128
129 enum bt_component_class_type bt_component_get_class_type(
130 struct bt_component *component)
131 {
132 return component ? component->class->type : BT_COMPONENT_CLASS_TYPE_UNKNOWN;
133 }
134
135 static
136 struct 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;
142 struct bt_graph *graph = NULL;
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);
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
187 end:
188 return new_port;
189 }
190
191 BT_HIDDEN
192 int64_t bt_component_get_input_port_count(struct bt_component *comp)
193 {
194 assert(comp);
195 return (int64_t) comp->input_ports->len;
196 }
197
198 BT_HIDDEN
199 int64_t bt_component_get_output_port_count(struct bt_component *comp)
200 {
201 assert(comp);
202 return (int64_t) comp->output_ports->len;
203 }
204
205 struct bt_component *bt_component_create_with_init_method_data(
206 struct bt_component_class *component_class, const char *name,
207 struct bt_value *params, void *init_method_data)
208 {
209 int ret;
210 struct bt_component *component = NULL;
211 enum bt_component_class_type type;
212 struct bt_port *default_port = NULL;
213
214 bt_get(params);
215
216 if (!component_class) {
217 goto end;
218 }
219
220 type = bt_component_class_get_type(component_class);
221 if (type <= BT_COMPONENT_CLASS_TYPE_UNKNOWN ||
222 type > BT_COMPONENT_CLASS_TYPE_FILTER) {
223 goto end;
224 }
225
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
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);
247 component->class = bt_get(component_class);
248 component->destroy = component_destroy_funcs[type];
249 component->name = g_string_new(name);
250 if (!component->name) {
251 BT_PUT(component);
252 goto end;
253 }
254
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
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
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
304 if (component_class->methods.init) {
305 ret = component_class->methods.init(
306 bt_private_component_from_component(component), params,
307 init_method_data);
308 component->initializing = false;
309 if (ret != BT_COMPONENT_STATUS_OK) {
310 BT_PUT(component);
311 goto end;
312 }
313 }
314
315 component->initializing = false;
316 ret = component_validation_funcs[type](component);
317 if (ret != BT_COMPONENT_STATUS_OK) {
318 BT_PUT(component);
319 goto end;
320 }
321
322 bt_component_class_freeze(component->class);
323 end:
324 bt_put(params);
325 bt_put(default_port);
326 return component;
327 }
328
329 struct 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
337 const char *bt_component_get_name(struct bt_component *component)
338 {
339 const char *ret = NULL;
340
341 if (!component) {
342 goto end;
343 }
344
345 ret = component->name->len == 0 ? NULL : component->name->str;
346 end:
347 return ret;
348 }
349
350 enum 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') {
356 ret = BT_COMPONENT_STATUS_INVALID;
357 goto end;
358 }
359
360 g_string_assign(component->name, name);
361 end:
362 return ret;
363 }
364
365 struct bt_component_class *bt_component_get_class(
366 struct bt_component *component)
367 {
368 return component ? bt_get(component->class) : NULL;
369 }
370
371 void *bt_private_component_get_user_data(
372 struct bt_private_component *private_component)
373 {
374 struct bt_component *component =
375 bt_component_from_private(private_component);
376
377 return component ? component->user_data : NULL;
378 }
379
380 enum bt_component_status bt_private_component_set_user_data(
381 struct bt_private_component *private_component,
382 void *data)
383 {
384 struct bt_component *component =
385 bt_component_from_private(private_component);
386 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
387
388 if (!component || !component->initializing) {
389 ret = BT_COMPONENT_STATUS_INVALID;
390 goto end;
391 }
392
393 component->user_data = data;
394 end:
395 return ret;
396 }
397
398 BT_HIDDEN
399 void bt_component_set_graph(struct bt_component *component,
400 struct bt_graph *graph)
401 {
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);
409 }
410
411 struct 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
417 static
418 struct bt_port *bt_component_get_port_by_name(GPtrArray *ports,
419 const char *name)
420 {
421 size_t i;
422 struct bt_port *ret_port = NULL;
423
424 assert(name);
425
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
443 BT_HIDDEN
444 struct bt_port *bt_component_get_input_port_by_name(struct bt_component *comp,
445 const char *name)
446 {
447 assert(comp);
448
449 return bt_component_get_port_by_name(comp->input_ports, name);
450 }
451
452 BT_HIDDEN
453 struct bt_port *bt_component_get_output_port_by_name(struct bt_component *comp,
454 const char *name)
455 {
456 assert(comp);
457
458 return bt_component_get_port_by_name(comp->output_ports, name);
459 }
460
461 static
462 struct bt_port *bt_component_get_port_by_index(GPtrArray *ports, uint64_t index)
463 {
464 struct bt_port *port = NULL;
465
466 if (index >= ports->len) {
467 goto end;
468 }
469
470 port = bt_get(g_ptr_array_index(ports, index));
471 end:
472 return port;
473 }
474
475 BT_HIDDEN
476 struct bt_port *bt_component_get_input_port_by_index(struct bt_component *comp,
477 uint64_t index)
478 {
479 assert(comp);
480
481 return bt_component_get_port_by_index(comp->input_ports, index);
482 }
483
484 BT_HIDDEN
485 struct bt_port *bt_component_get_output_port_by_index(struct bt_component *comp,
486 uint64_t index)
487 {
488 assert(comp);
489
490 return bt_component_get_port_by_index(comp->output_ports, index);
491 }
492
493 BT_HIDDEN
494 struct 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 }
500
501 BT_HIDDEN
502 struct 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
509 static
510 void bt_component_remove_port_by_index(struct bt_component *component,
511 GPtrArray *ports, size_t index)
512 {
513 struct bt_port *port;
514 struct bt_graph *graph;
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) {
522 bt_connection_disconnect_ports(port->connection);
523 }
524
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
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 }
539 }
540
541 BT_HIDDEN
542 enum bt_component_status bt_component_remove_port(
543 struct bt_component *component, struct bt_port *port)
544 {
545 size_t i;
546 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
547 GPtrArray *ports = NULL;
548
549 if (!component || !port) {
550 status = BT_COMPONENT_STATUS_INVALID;
551 goto end;
552 }
553
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 }
559
560 assert(ports);
561
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) {
566 bt_component_remove_port_by_index(component,
567 ports, i);
568 goto end;
569 }
570 }
571
572 status = BT_COMPONENT_STATUS_NOT_FOUND;
573 end:
574 return status;
575 }
576
577 BT_HIDDEN
578 enum bt_component_status bt_component_accept_port_connection(
579 struct bt_component *comp, struct bt_port *self_port,
580 struct bt_port *other_port)
581 {
582 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
583
584 assert(comp);
585 assert(self_port);
586 assert(other_port);
587
588 if (comp->class->methods.accept_port_connection) {
589 status = comp->class->methods.accept_port_connection(
590 bt_private_component_from_component(comp),
591 bt_private_port_from_port(self_port),
592 other_port);
593 }
594
595 return status;
596 }
597
598 BT_HIDDEN
599 void 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
613 BT_HIDDEN
614 void 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) {
621 comp->class->methods.port_disconnected(
622 bt_private_component_from_component(comp),
623 bt_private_port_from_port(port));
624 }
625 }
626
627 BT_HIDDEN
628 void 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
640 BT_HIDDEN
641 void 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.057216 seconds and 4 git commands to generate.