2 * SPDX-License-Identifier: MIT
4 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 #define BT_LOG_TAG "LIB/COMPONENT-CLASS"
9 #include "lib/logging.h"
11 #include "common/assert.h"
12 #include "lib/assert-pre.h"
13 #include "compat/compiler.h"
14 #include <babeltrace2/graph/component-class.h>
15 #include <babeltrace2/types.h>
18 #include "component-class.h"
19 #include "lib/func-status.h"
20 #include "lib/graph/message-iterator-class.h"
22 #define BT_ASSERT_PRE_DEV_COMP_CLS_HOT(_cc) \
23 BT_ASSERT_PRE_DEV_HOT(((const struct bt_component_class *) (_cc)), \
24 "Component class", ": %!+C", (_cc))
27 void destroy_component_class(struct bt_object
*obj
)
29 struct bt_component_class
*class;
33 class = container_of(obj
, struct bt_component_class
, base
);
35 BT_LIB_LOGI("Destroying component class: %!+C", class);
37 /* Call destroy listeners in reverse registration order */
38 for (i
= class->destroy_listeners
->len
- 1; i
>= 0; i
--) {
39 struct bt_component_class_destroy_listener
*listener
=
40 &g_array_index(class->destroy_listeners
,
41 struct bt_component_class_destroy_listener
,
44 BT_LOGD("Calling destroy listener: func-addr=%p, data-addr=%p",
45 listener
->func
, listener
->data
);
46 listener
->func(class, listener
->data
);
50 g_string_free(class->name
, TRUE
);
54 if (class->description
) {
55 g_string_free(class->description
, TRUE
);
56 class->description
= NULL
;
60 g_string_free(class->help
, TRUE
);
64 if (class->plugin_name
) {
65 g_string_free(class->plugin_name
, TRUE
);
66 class->plugin_name
= NULL
;
69 if (class->destroy_listeners
) {
70 g_array_free(class->destroy_listeners
, TRUE
);
71 class->destroy_listeners
= NULL
;
74 if (bt_component_class_has_message_iterator_class(class)) {
75 struct bt_component_class_with_iterator_class
*class_with_iter_class
=
76 container_of(class, struct bt_component_class_with_iterator_class
, parent
);
78 BT_ASSERT(class_with_iter_class
->msg_iter_cls
);
79 bt_message_iterator_class_put_ref(class_with_iter_class
->msg_iter_cls
);
80 class_with_iter_class
->msg_iter_cls
= NULL
;
87 int bt_component_class_init(struct bt_component_class
*class,
88 enum bt_component_class_type type
, const char *name
)
92 bt_object_init_shared(&class->base
, destroy_component_class
);
94 class->name
= g_string_new(name
);
96 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
100 class->description
= g_string_new(NULL
);
101 if (!class->description
) {
102 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
106 class->help
= g_string_new(NULL
);
108 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
112 class->plugin_name
= g_string_new(NULL
);
113 if (!class->plugin_name
) {
114 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
118 class->destroy_listeners
= g_array_new(FALSE
, TRUE
,
119 sizeof(struct bt_component_class_destroy_listener
));
120 if (!class->destroy_listeners
) {
121 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
128 BT_OBJECT_PUT_REF_AND_RESET(class);
136 int bt_component_class_with_iterator_class_init(
137 struct bt_component_class_with_iterator_class
*class,
138 enum bt_component_class_type type
, const char *name
,
139 struct bt_message_iterator_class
*message_iterator_class
)
143 ret
= bt_component_class_init(&class->parent
, type
, name
);
148 class->msg_iter_cls
= message_iterator_class
;
149 bt_message_iterator_class_get_ref(class->msg_iter_cls
);
150 bt_message_iterator_class_freeze(class->msg_iter_cls
);
156 struct bt_component_class_source
*bt_component_class_source_create(
158 struct bt_message_iterator_class
*message_iterator_class
)
160 struct bt_component_class_source
*source_class
= NULL
;
163 BT_ASSERT_PRE_NO_ERROR();
164 BT_ASSERT_PRE_NON_NULL(name
, "Name");
165 BT_ASSERT_PRE_NON_NULL(message_iterator_class
, "Message iterator class");
166 BT_LIB_LOGI("Creating source component class: "
167 "name=\"%s\", %![msg-iter-cls-]+I",
168 name
, message_iterator_class
);
169 source_class
= g_new0(struct bt_component_class_source
, 1);
171 BT_LIB_LOGE_APPEND_CAUSE(
172 "Failed to allocate one source component class.");
176 /* bt_component_class_init() logs errors */
177 ret
= bt_component_class_with_iterator_class_init(&source_class
->parent
,
178 BT_COMPONENT_CLASS_TYPE_SOURCE
, name
, message_iterator_class
);
181 * If bt_component_class_init() fails, the component
182 * class is put, therefore its memory is already
189 BT_LIB_LOGI("Created source component class: %!+C", source_class
);
192 return (void *) source_class
;
195 struct bt_component_class_filter
*bt_component_class_filter_create(
197 struct bt_message_iterator_class
*message_iterator_class
)
199 struct bt_component_class_filter
*filter_class
= NULL
;
202 BT_ASSERT_PRE_NO_ERROR();
203 BT_ASSERT_PRE_NON_NULL(name
, "Name");
204 BT_ASSERT_PRE_NON_NULL(message_iterator_class
, "Message iterator class");
205 BT_LIB_LOGI("Creating filter component class: "
206 "name=\"%s\", %![msg-iter-cls-]+I",
207 name
, message_iterator_class
);
208 filter_class
= g_new0(struct bt_component_class_filter
, 1);
210 BT_LIB_LOGE_APPEND_CAUSE(
211 "Failed to allocate one filter component class.");
215 /* bt_component_class_init() logs errors */
216 ret
= bt_component_class_with_iterator_class_init(&filter_class
->parent
,
217 BT_COMPONENT_CLASS_TYPE_FILTER
, name
, message_iterator_class
);
220 * If bt_component_class_init() fails, the component
221 * class is put, therefore its memory is already
228 BT_LIB_LOGI("Created filter component class: %!+C", filter_class
);
231 return (void *) filter_class
;
234 struct bt_component_class_sink
*bt_component_class_sink_create(
235 const char *name
, bt_component_class_sink_consume_method method
)
237 struct bt_component_class_sink
*sink_class
= NULL
;
240 BT_ASSERT_PRE_NO_ERROR();
241 BT_ASSERT_PRE_NON_NULL(name
, "Name");
242 BT_ASSERT_PRE_NON_NULL(method
, "Consume next method");
243 BT_LOGI("Creating sink component class: "
244 "name=\"%s\", consume-method-addr=%p",
246 sink_class
= g_new0(struct bt_component_class_sink
, 1);
248 BT_LIB_LOGE_APPEND_CAUSE(
249 "Failed to allocate one sink component class.");
253 /* bt_component_class_init() logs errors */
254 ret
= bt_component_class_init(&sink_class
->parent
,
255 BT_COMPONENT_CLASS_TYPE_SINK
, name
);
258 * If bt_component_class_init() fails, the component
259 * class is put, therefore its memory is already
266 sink_class
->methods
.consume
= method
;
267 BT_LIB_LOGI("Created sink component class: %!+C", sink_class
);
270 return (void *) sink_class
;
273 enum bt_component_class_set_method_status
274 bt_component_class_source_set_get_supported_mip_versions_method(
275 struct bt_component_class_source
*comp_cls
,
276 bt_component_class_source_get_supported_mip_versions_method method
)
278 BT_ASSERT_PRE_NO_ERROR();
279 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
280 BT_ASSERT_PRE_NON_NULL(method
, "Method");
281 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
282 comp_cls
->methods
.get_supported_mip_versions
= method
;
283 BT_LIB_LOGD("Set source component class's \"get supported MIP versions\" method: "
285 return BT_FUNC_STATUS_OK
;
288 enum bt_component_class_set_method_status
289 bt_component_class_filter_set_get_supported_mip_versions_method(
290 struct bt_component_class_filter
*comp_cls
,
291 bt_component_class_filter_get_supported_mip_versions_method method
)
293 BT_ASSERT_PRE_NO_ERROR();
294 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
295 BT_ASSERT_PRE_NON_NULL(method
, "Method");
296 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
297 comp_cls
->methods
.get_supported_mip_versions
= method
;
298 BT_LIB_LOGD("Set filter component class's \"get supported MIP versions\" method: "
300 return BT_FUNC_STATUS_OK
;
303 enum bt_component_class_set_method_status
304 bt_component_class_sink_set_get_supported_mip_versions_method(
305 struct bt_component_class_sink
*comp_cls
,
306 bt_component_class_sink_get_supported_mip_versions_method method
)
308 BT_ASSERT_PRE_NO_ERROR();
309 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
310 BT_ASSERT_PRE_NON_NULL(method
, "Method");
311 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
312 comp_cls
->methods
.get_supported_mip_versions
= method
;
313 BT_LIB_LOGD("Set sink component class's \"get supported MIP versions\" method: "
315 return BT_FUNC_STATUS_OK
;
318 enum bt_component_class_set_method_status
319 bt_component_class_source_set_initialize_method(
320 struct bt_component_class_source
*comp_cls
,
321 bt_component_class_source_initialize_method method
)
323 BT_ASSERT_PRE_NO_ERROR();
324 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
325 BT_ASSERT_PRE_NON_NULL(method
, "Method");
326 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
327 comp_cls
->methods
.init
= method
;
328 BT_LIB_LOGD("Set source component class's initialization method: "
330 return BT_FUNC_STATUS_OK
;
333 enum bt_component_class_set_method_status
334 bt_component_class_filter_set_initialize_method(
335 struct bt_component_class_filter
*comp_cls
,
336 bt_component_class_filter_initialize_method method
)
338 BT_ASSERT_PRE_NO_ERROR();
339 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
340 BT_ASSERT_PRE_NON_NULL(method
, "Method");
341 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
342 comp_cls
->methods
.init
= method
;
343 BT_LIB_LOGD("Set filter component class's initialization method: "
345 return BT_FUNC_STATUS_OK
;
348 enum bt_component_class_set_method_status
349 bt_component_class_sink_set_initialize_method(
350 struct bt_component_class_sink
*comp_cls
,
351 bt_component_class_sink_initialize_method method
)
353 BT_ASSERT_PRE_NO_ERROR();
354 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
355 BT_ASSERT_PRE_NON_NULL(method
, "Method");
356 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
357 comp_cls
->methods
.init
= method
;
358 BT_LIB_LOGD("Set sink component class's initialization method: "
360 return BT_FUNC_STATUS_OK
;
363 enum bt_component_class_set_method_status
364 bt_component_class_source_set_finalize_method(
365 struct bt_component_class_source
*comp_cls
,
366 bt_component_class_source_finalize_method method
)
368 BT_ASSERT_PRE_NO_ERROR();
369 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
370 BT_ASSERT_PRE_NON_NULL(method
, "Method");
371 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
372 comp_cls
->methods
.finalize
= method
;
373 BT_LIB_LOGD("Set source component class's finalization method: "
375 return BT_FUNC_STATUS_OK
;
378 enum bt_component_class_set_method_status
379 bt_component_class_filter_set_finalize_method(
380 struct bt_component_class_filter
*comp_cls
,
381 bt_component_class_filter_finalize_method method
)
383 BT_ASSERT_PRE_NO_ERROR();
384 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
385 BT_ASSERT_PRE_NON_NULL(method
, "Method");
386 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
387 comp_cls
->methods
.finalize
= method
;
388 BT_LIB_LOGD("Set filter component class's finalization method: "
390 return BT_FUNC_STATUS_OK
;
393 enum bt_component_class_set_method_status
394 bt_component_class_sink_set_finalize_method(
395 struct bt_component_class_sink
*comp_cls
,
396 bt_component_class_sink_finalize_method method
)
398 BT_ASSERT_PRE_NO_ERROR();
399 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
400 BT_ASSERT_PRE_NON_NULL(method
, "Method");
401 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
402 comp_cls
->methods
.finalize
= method
;
403 BT_LIB_LOGD("Set sink component class's finalization method: "
405 return BT_FUNC_STATUS_OK
;
408 enum bt_component_class_set_method_status
409 bt_component_class_source_set_query_method(
410 struct bt_component_class_source
*comp_cls
,
411 bt_component_class_source_query_method method
)
413 BT_ASSERT_PRE_NO_ERROR();
414 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
415 BT_ASSERT_PRE_NON_NULL(method
, "Method");
416 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
417 comp_cls
->methods
.query
= method
;
418 BT_LIB_LOGD("Set source component class's query method: "
420 return BT_FUNC_STATUS_OK
;
423 enum bt_component_class_set_method_status
424 bt_component_class_filter_set_query_method(
425 struct bt_component_class_filter
*comp_cls
,
426 bt_component_class_filter_query_method method
)
428 BT_ASSERT_PRE_NO_ERROR();
429 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
430 BT_ASSERT_PRE_NON_NULL(method
, "Method");
431 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
432 comp_cls
->methods
.query
= method
;
433 BT_LIB_LOGD("Set filter component class's query method: "
435 return BT_FUNC_STATUS_OK
;
438 enum bt_component_class_set_method_status
439 bt_component_class_sink_set_query_method(
440 struct bt_component_class_sink
*comp_cls
,
441 bt_component_class_sink_query_method method
)
443 BT_ASSERT_PRE_NO_ERROR();
444 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
445 BT_ASSERT_PRE_NON_NULL(method
, "Method");
446 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
447 comp_cls
->methods
.query
= method
;
448 BT_LIB_LOGD("Set sink component class's query method: "
450 return BT_FUNC_STATUS_OK
;
453 enum bt_component_class_set_method_status
454 bt_component_class_filter_set_input_port_connected_method(
455 struct bt_component_class_filter
*comp_cls
,
456 bt_component_class_filter_input_port_connected_method method
)
458 BT_ASSERT_PRE_NO_ERROR();
459 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
460 BT_ASSERT_PRE_NON_NULL(method
, "Method");
461 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
462 comp_cls
->methods
.input_port_connected
= method
;
463 BT_LIB_LOGD("Set filter component class's \"input port connected\" method"
465 return BT_FUNC_STATUS_OK
;
468 enum bt_component_class_set_method_status
469 bt_component_class_sink_set_input_port_connected_method(
470 struct bt_component_class_sink
*comp_cls
,
471 bt_component_class_sink_input_port_connected_method method
)
473 BT_ASSERT_PRE_NO_ERROR();
474 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
475 BT_ASSERT_PRE_NON_NULL(method
, "Method");
476 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
477 comp_cls
->methods
.input_port_connected
= method
;
478 BT_LIB_LOGD("Set sink component class's \"input port connected\" method"
480 return BT_FUNC_STATUS_OK
;
483 enum bt_component_class_set_method_status
484 bt_component_class_source_set_output_port_connected_method(
485 struct bt_component_class_source
*comp_cls
,
486 bt_component_class_source_output_port_connected_method method
)
488 BT_ASSERT_PRE_NO_ERROR();
489 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
490 BT_ASSERT_PRE_NON_NULL(method
, "Method");
491 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
492 comp_cls
->methods
.output_port_connected
= method
;
493 BT_LIB_LOGD("Set source component class's \"output port connected\" method"
495 return BT_FUNC_STATUS_OK
;
498 enum bt_component_class_set_method_status
499 bt_component_class_filter_set_output_port_connected_method(
500 struct bt_component_class_filter
*comp_cls
,
501 bt_component_class_filter_output_port_connected_method method
)
503 BT_ASSERT_PRE_NO_ERROR();
504 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
505 BT_ASSERT_PRE_NON_NULL(method
, "Method");
506 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
507 comp_cls
->methods
.output_port_connected
= method
;
508 BT_LIB_LOGD("Set filter component class's \"output port connected\" method"
510 return BT_FUNC_STATUS_OK
;
513 enum bt_component_class_set_method_status
514 bt_component_class_sink_set_graph_is_configured_method(
515 struct bt_component_class_sink
*comp_cls
,
516 bt_component_class_sink_graph_is_configured_method method
)
518 BT_ASSERT_PRE_NO_ERROR();
519 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
520 BT_ASSERT_PRE_NON_NULL(method
, "Method");
521 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
522 comp_cls
->methods
.graph_is_configured
= method
;
523 BT_LIB_LOGD("Set sink component class's \"graph is configured\" method"
525 return BT_FUNC_STATUS_OK
;
528 enum bt_component_class_set_description_status
529 bt_component_class_set_description(
530 struct bt_component_class
*comp_cls
,
531 const char *description
)
533 BT_ASSERT_PRE_NO_ERROR();
534 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
535 BT_ASSERT_PRE_NON_NULL(description
, "Description");
536 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
537 g_string_assign(comp_cls
->description
, description
);
538 BT_LIB_LOGD("Set component class's description: "
539 "addr=%p, name=\"%s\", type=%s",
541 bt_component_class_get_name(comp_cls
),
542 bt_component_class_type_string(comp_cls
->type
));
543 return BT_FUNC_STATUS_OK
;
546 enum bt_component_class_set_help_status
bt_component_class_set_help(
547 struct bt_component_class
*comp_cls
,
550 BT_ASSERT_PRE_NO_ERROR();
551 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
552 BT_ASSERT_PRE_NON_NULL(help
, "Help");
553 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
554 g_string_assign(comp_cls
->help
, help
);
555 BT_LIB_LOGD("Set component class's help text: %!+C", comp_cls
);
556 return BT_FUNC_STATUS_OK
;
559 const char *bt_component_class_get_name(const struct bt_component_class
*comp_cls
)
561 BT_ASSERT_PRE_DEV_NON_NULL(comp_cls
, "Component class");
562 return comp_cls
->name
->str
;
565 enum bt_component_class_type
bt_component_class_get_type(
566 const struct bt_component_class
*comp_cls
)
568 BT_ASSERT_PRE_DEV_NON_NULL(comp_cls
, "Component class");
569 return comp_cls
->type
;
572 const char *bt_component_class_get_description(
573 const struct bt_component_class
*comp_cls
)
575 BT_ASSERT_PRE_DEV_NON_NULL(comp_cls
, "Component class");
576 return comp_cls
->description
&&
577 comp_cls
->description
->str
[0] != '\0' ?
578 comp_cls
->description
->str
: NULL
;
581 const char *bt_component_class_get_help(
582 const struct bt_component_class
*comp_cls
)
584 BT_ASSERT_PRE_DEV_NON_NULL(comp_cls
, "Component class");
585 return comp_cls
->help
&&
586 comp_cls
->help
->str
[0] != '\0' ? comp_cls
->help
->str
: NULL
;
590 void bt_component_class_add_destroy_listener(
591 struct bt_component_class
*comp_cls
,
592 bt_component_class_destroy_listener_func func
, void *data
)
594 struct bt_component_class_destroy_listener listener
;
598 listener
.func
= func
;
599 listener
.data
= data
;
600 g_array_append_val(comp_cls
->destroy_listeners
, listener
);
601 BT_LIB_LOGD("Added destroy listener to component class: "
602 "%![cc-]+C, listener-func-addr=%p", comp_cls
, func
);
606 void _bt_component_class_freeze(const struct bt_component_class
*comp_cls
)
609 BT_LIB_LOGD("Freezing component class: %!+C", comp_cls
);
610 ((struct bt_component_class
*) comp_cls
)->frozen
= true;
613 void bt_component_class_get_ref(
614 const struct bt_component_class
*component_class
)
616 bt_object_get_ref(component_class
);
619 void bt_component_class_put_ref(
620 const struct bt_component_class
*component_class
)
622 bt_object_put_ref(component_class
);
625 void bt_component_class_source_get_ref(
626 const struct bt_component_class_source
*component_class_source
)
628 bt_object_get_ref(component_class_source
);
631 void bt_component_class_source_put_ref(
632 const struct bt_component_class_source
*component_class_source
)
634 bt_object_put_ref(component_class_source
);
637 void bt_component_class_filter_get_ref(
638 const struct bt_component_class_filter
*component_class_filter
)
640 bt_object_get_ref(component_class_filter
);
643 void bt_component_class_filter_put_ref(
644 const struct bt_component_class_filter
*component_class_filter
)
646 bt_object_put_ref(component_class_filter
);
649 void bt_component_class_sink_get_ref(
650 const struct bt_component_class_sink
*component_class_sink
)
652 bt_object_get_ref(component_class_sink
);
655 void bt_component_class_sink_put_ref(
656 const struct bt_component_class_sink
*component_class_sink
)
658 bt_object_put_ref(component_class_sink
);