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 "common/common.h"
13 #include "lib/assert-cond.h"
14 #include "compat/compiler.h"
15 #include <babeltrace2/graph/component-class.h>
16 #include <babeltrace2/types.h>
19 #include "component-class.h"
20 #include "lib/func-status.h"
21 #include "lib/graph/message-iterator-class.h"
23 #define BT_ASSERT_PRE_DEV_COMP_CLS_HOT(_cc) \
24 BT_ASSERT_PRE_DEV_HOT("component-class", \
25 ((const struct bt_component_class *) (_cc)), \
26 "Component class", ": %!+C", (_cc))
29 void destroy_component_class(struct bt_object
*obj
)
31 struct bt_component_class
*class;
35 class = container_of(obj
, struct bt_component_class
, base
);
37 BT_LIB_LOGI("Destroying component class: %!+C", class);
39 /* Call destroy listeners in reverse registration order */
40 if (class->destroy_listeners
) {
41 for (i
= class->destroy_listeners
->len
- 1; i
>= 0; i
--) {
42 struct bt_component_class_destroy_listener
*listener
=
43 &bt_g_array_index(class->destroy_listeners
,
44 struct bt_component_class_destroy_listener
,
47 BT_LOGD("Calling destroy listener: func-addr=%p, data-addr=%p",
48 listener
->func
, listener
->data
);
49 listener
->func(class, listener
->data
);
54 g_string_free(class->name
, TRUE
);
58 if (class->description
) {
59 g_string_free(class->description
, TRUE
);
60 class->description
= NULL
;
64 g_string_free(class->help
, TRUE
);
68 if (class->plugin_name
) {
69 g_string_free(class->plugin_name
, TRUE
);
70 class->plugin_name
= NULL
;
73 if (class->destroy_listeners
) {
74 g_array_free(class->destroy_listeners
, TRUE
);
75 class->destroy_listeners
= NULL
;
78 if (bt_component_class_has_message_iterator_class(class)) {
79 struct bt_component_class_with_iterator_class
*class_with_iter_class
=
80 container_of(class, struct bt_component_class_with_iterator_class
, parent
);
82 BT_ASSERT(class_with_iter_class
->msg_iter_cls
);
83 bt_message_iterator_class_put_ref(class_with_iter_class
->msg_iter_cls
);
84 class_with_iter_class
->msg_iter_cls
= NULL
;
91 int bt_component_class_init(struct bt_component_class
*class,
92 enum bt_component_class_type type
, const char *name
)
96 bt_object_init_shared(&class->base
, destroy_component_class
);
98 class->name
= g_string_new(name
);
100 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
104 class->description
= g_string_new(NULL
);
105 if (!class->description
) {
106 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
110 class->help
= g_string_new(NULL
);
112 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
116 class->plugin_name
= g_string_new(NULL
);
117 if (!class->plugin_name
) {
118 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
122 class->destroy_listeners
= g_array_new(FALSE
, TRUE
,
123 sizeof(struct bt_component_class_destroy_listener
));
124 if (!class->destroy_listeners
) {
125 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
132 BT_OBJECT_PUT_REF_AND_RESET(class);
140 int bt_component_class_with_iterator_class_init(
141 struct bt_component_class_with_iterator_class
*class,
142 enum bt_component_class_type type
, const char *name
,
143 struct bt_message_iterator_class
*message_iterator_class
)
147 ret
= bt_component_class_init(&class->parent
, type
, name
);
152 class->msg_iter_cls
= message_iterator_class
;
153 bt_message_iterator_class_get_ref(class->msg_iter_cls
);
154 bt_message_iterator_class_freeze(class->msg_iter_cls
);
161 struct bt_component_class_source
*bt_component_class_source_create(
163 struct bt_message_iterator_class
*message_iterator_class
)
165 struct bt_component_class_source
*source_class
= NULL
;
168 BT_ASSERT_PRE_NO_ERROR();
169 BT_ASSERT_PRE_NAME_NON_NULL(name
);
170 BT_ASSERT_PRE_MSG_ITER_CLS_NON_NULL(message_iterator_class
);
171 BT_LIB_LOGI("Creating source component class: "
172 "name=\"%s\", %![msg-iter-cls-]+I",
173 name
, message_iterator_class
);
174 source_class
= g_new0(struct bt_component_class_source
, 1);
176 BT_LIB_LOGE_APPEND_CAUSE(
177 "Failed to allocate one source component class.");
181 /* bt_component_class_init() logs errors */
182 ret
= bt_component_class_with_iterator_class_init(&source_class
->parent
,
183 BT_COMPONENT_CLASS_TYPE_SOURCE
, name
, message_iterator_class
);
186 * If bt_component_class_init() fails, the component
187 * class is put, therefore its memory is already
194 BT_LIB_LOGI("Created source component class: %!+C", source_class
);
197 return (void *) source_class
;
201 struct bt_component_class_filter
*bt_component_class_filter_create(
203 struct bt_message_iterator_class
*message_iterator_class
)
205 struct bt_component_class_filter
*filter_class
= NULL
;
208 BT_ASSERT_PRE_NO_ERROR();
209 BT_ASSERT_PRE_NAME_NON_NULL(name
);
210 BT_ASSERT_PRE_MSG_ITER_CLS_NON_NULL(message_iterator_class
);
211 BT_LIB_LOGI("Creating filter component class: "
212 "name=\"%s\", %![msg-iter-cls-]+I",
213 name
, message_iterator_class
);
214 filter_class
= g_new0(struct bt_component_class_filter
, 1);
216 BT_LIB_LOGE_APPEND_CAUSE(
217 "Failed to allocate one filter component class.");
221 /* bt_component_class_init() logs errors */
222 ret
= bt_component_class_with_iterator_class_init(&filter_class
->parent
,
223 BT_COMPONENT_CLASS_TYPE_FILTER
, name
, message_iterator_class
);
226 * If bt_component_class_init() fails, the component
227 * class is put, therefore its memory is already
234 BT_LIB_LOGI("Created filter component class: %!+C", filter_class
);
237 return (void *) filter_class
;
241 struct bt_component_class_sink
*bt_component_class_sink_create(
242 const char *name
, bt_component_class_sink_consume_method method
)
244 struct bt_component_class_sink
*sink_class
= NULL
;
247 BT_ASSERT_PRE_NO_ERROR();
248 BT_ASSERT_PRE_NAME_NON_NULL(name
);
249 BT_ASSERT_PRE_NON_NULL("consume-method", method
, "Consume next method");
250 BT_LOGI("Creating sink component class: "
251 "name=\"%s\", consume-method-addr=%p",
253 sink_class
= g_new0(struct bt_component_class_sink
, 1);
255 BT_LIB_LOGE_APPEND_CAUSE(
256 "Failed to allocate one sink component class.");
260 /* bt_component_class_init() logs errors */
261 ret
= bt_component_class_init(&sink_class
->parent
,
262 BT_COMPONENT_CLASS_TYPE_SINK
, name
);
265 * If bt_component_class_init() fails, the component
266 * class is put, therefore its memory is already
273 sink_class
->methods
.consume
= method
;
274 BT_LIB_LOGI("Created sink component class: %!+C", sink_class
);
277 return (void *) sink_class
;
281 enum bt_component_class_set_method_status
282 bt_component_class_source_set_get_supported_mip_versions_method(
283 struct bt_component_class_source
*comp_cls
,
284 bt_component_class_source_get_supported_mip_versions_method method
)
286 BT_ASSERT_PRE_NO_ERROR();
287 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
288 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
289 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
290 comp_cls
->methods
.get_supported_mip_versions
= method
;
291 BT_LIB_LOGD("Set source component class's \"get supported MIP versions\" method: "
293 return BT_FUNC_STATUS_OK
;
297 enum bt_component_class_set_method_status
298 bt_component_class_filter_set_get_supported_mip_versions_method(
299 struct bt_component_class_filter
*comp_cls
,
300 bt_component_class_filter_get_supported_mip_versions_method method
)
302 BT_ASSERT_PRE_NO_ERROR();
303 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
304 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
305 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
306 comp_cls
->methods
.get_supported_mip_versions
= method
;
307 BT_LIB_LOGD("Set filter component class's \"get supported MIP versions\" method: "
309 return BT_FUNC_STATUS_OK
;
313 enum bt_component_class_set_method_status
314 bt_component_class_sink_set_get_supported_mip_versions_method(
315 struct bt_component_class_sink
*comp_cls
,
316 bt_component_class_sink_get_supported_mip_versions_method method
)
318 BT_ASSERT_PRE_NO_ERROR();
319 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
320 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
321 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
322 comp_cls
->methods
.get_supported_mip_versions
= method
;
323 BT_LIB_LOGD("Set sink component class's \"get supported MIP versions\" method: "
325 return BT_FUNC_STATUS_OK
;
329 enum bt_component_class_set_method_status
330 bt_component_class_source_set_initialize_method(
331 struct bt_component_class_source
*comp_cls
,
332 bt_component_class_source_initialize_method method
)
334 BT_ASSERT_PRE_NO_ERROR();
335 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
336 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
337 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
338 comp_cls
->methods
.init
= method
;
339 BT_LIB_LOGD("Set source component class's initialization method: "
341 return BT_FUNC_STATUS_OK
;
345 enum bt_component_class_set_method_status
346 bt_component_class_filter_set_initialize_method(
347 struct bt_component_class_filter
*comp_cls
,
348 bt_component_class_filter_initialize_method method
)
350 BT_ASSERT_PRE_NO_ERROR();
351 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
352 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
353 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
354 comp_cls
->methods
.init
= method
;
355 BT_LIB_LOGD("Set filter component class's initialization method: "
357 return BT_FUNC_STATUS_OK
;
361 enum bt_component_class_set_method_status
362 bt_component_class_sink_set_initialize_method(
363 struct bt_component_class_sink
*comp_cls
,
364 bt_component_class_sink_initialize_method method
)
366 BT_ASSERT_PRE_NO_ERROR();
367 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
368 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
369 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
370 comp_cls
->methods
.init
= method
;
371 BT_LIB_LOGD("Set sink component class's initialization method: "
373 return BT_FUNC_STATUS_OK
;
377 enum bt_component_class_set_method_status
378 bt_component_class_source_set_finalize_method(
379 struct bt_component_class_source
*comp_cls
,
380 bt_component_class_source_finalize_method method
)
382 BT_ASSERT_PRE_NO_ERROR();
383 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
384 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
385 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
386 comp_cls
->methods
.finalize
= method
;
387 BT_LIB_LOGD("Set source component class's finalization method: "
389 return BT_FUNC_STATUS_OK
;
393 enum bt_component_class_set_method_status
394 bt_component_class_filter_set_finalize_method(
395 struct bt_component_class_filter
*comp_cls
,
396 bt_component_class_filter_finalize_method method
)
398 BT_ASSERT_PRE_NO_ERROR();
399 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
400 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
401 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
402 comp_cls
->methods
.finalize
= method
;
403 BT_LIB_LOGD("Set filter component class's finalization method: "
405 return BT_FUNC_STATUS_OK
;
409 enum bt_component_class_set_method_status
410 bt_component_class_sink_set_finalize_method(
411 struct bt_component_class_sink
*comp_cls
,
412 bt_component_class_sink_finalize_method method
)
414 BT_ASSERT_PRE_NO_ERROR();
415 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
416 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
417 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
418 comp_cls
->methods
.finalize
= method
;
419 BT_LIB_LOGD("Set sink component class's finalization method: "
421 return BT_FUNC_STATUS_OK
;
425 enum bt_component_class_set_method_status
426 bt_component_class_source_set_query_method(
427 struct bt_component_class_source
*comp_cls
,
428 bt_component_class_source_query_method method
)
430 BT_ASSERT_PRE_NO_ERROR();
431 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
432 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
433 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
434 comp_cls
->methods
.query
= method
;
435 BT_LIB_LOGD("Set source component class's query method: "
437 return BT_FUNC_STATUS_OK
;
441 enum bt_component_class_set_method_status
442 bt_component_class_filter_set_query_method(
443 struct bt_component_class_filter
*comp_cls
,
444 bt_component_class_filter_query_method method
)
446 BT_ASSERT_PRE_NO_ERROR();
447 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
448 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
449 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
450 comp_cls
->methods
.query
= method
;
451 BT_LIB_LOGD("Set filter component class's query method: "
453 return BT_FUNC_STATUS_OK
;
457 enum bt_component_class_set_method_status
458 bt_component_class_sink_set_query_method(
459 struct bt_component_class_sink
*comp_cls
,
460 bt_component_class_sink_query_method method
)
462 BT_ASSERT_PRE_NO_ERROR();
463 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
464 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
465 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
466 comp_cls
->methods
.query
= method
;
467 BT_LIB_LOGD("Set sink component class's query method: "
469 return BT_FUNC_STATUS_OK
;
473 enum bt_component_class_set_method_status
474 bt_component_class_filter_set_input_port_connected_method(
475 struct bt_component_class_filter
*comp_cls
,
476 bt_component_class_filter_input_port_connected_method method
)
478 BT_ASSERT_PRE_NO_ERROR();
479 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
480 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
481 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
482 comp_cls
->methods
.input_port_connected
= method
;
483 BT_LIB_LOGD("Set filter component class's \"input port connected\" method"
485 return BT_FUNC_STATUS_OK
;
489 enum bt_component_class_set_method_status
490 bt_component_class_sink_set_input_port_connected_method(
491 struct bt_component_class_sink
*comp_cls
,
492 bt_component_class_sink_input_port_connected_method method
)
494 BT_ASSERT_PRE_NO_ERROR();
495 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
496 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
497 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
498 comp_cls
->methods
.input_port_connected
= method
;
499 BT_LIB_LOGD("Set sink component class's \"input port connected\" method"
501 return BT_FUNC_STATUS_OK
;
505 enum bt_component_class_set_method_status
506 bt_component_class_source_set_output_port_connected_method(
507 struct bt_component_class_source
*comp_cls
,
508 bt_component_class_source_output_port_connected_method method
)
510 BT_ASSERT_PRE_NO_ERROR();
511 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
512 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
513 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
514 comp_cls
->methods
.output_port_connected
= method
;
515 BT_LIB_LOGD("Set source component class's \"output port connected\" method"
517 return BT_FUNC_STATUS_OK
;
521 enum bt_component_class_set_method_status
522 bt_component_class_filter_set_output_port_connected_method(
523 struct bt_component_class_filter
*comp_cls
,
524 bt_component_class_filter_output_port_connected_method method
)
526 BT_ASSERT_PRE_NO_ERROR();
527 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
528 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
529 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
530 comp_cls
->methods
.output_port_connected
= method
;
531 BT_LIB_LOGD("Set filter component class's \"output port connected\" method"
533 return BT_FUNC_STATUS_OK
;
537 enum bt_component_class_set_method_status
538 bt_component_class_sink_set_graph_is_configured_method(
539 struct bt_component_class_sink
*comp_cls
,
540 bt_component_class_sink_graph_is_configured_method method
)
542 BT_ASSERT_PRE_NO_ERROR();
543 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
544 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
545 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
546 comp_cls
->methods
.graph_is_configured
= method
;
547 BT_LIB_LOGD("Set sink component class's \"graph is configured\" method"
549 return BT_FUNC_STATUS_OK
;
553 enum bt_component_class_set_description_status
554 bt_component_class_set_description(
555 struct bt_component_class
*comp_cls
,
556 const char *description
)
558 BT_ASSERT_PRE_NO_ERROR();
559 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
560 BT_ASSERT_PRE_DESCR_NON_NULL(description
);
561 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
562 g_string_assign(comp_cls
->description
, description
);
563 BT_LIB_LOGD("Set component class's description: "
564 "addr=%p, name=\"%s\", type=%s",
566 bt_component_class_get_name(comp_cls
),
567 bt_common_component_class_type_string(comp_cls
->type
));
568 return BT_FUNC_STATUS_OK
;
572 enum bt_component_class_set_help_status
bt_component_class_set_help(
573 struct bt_component_class
*comp_cls
,
576 BT_ASSERT_PRE_NO_ERROR();
577 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
578 BT_ASSERT_PRE_NON_NULL("help-text", help
, "Help text");
579 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
580 g_string_assign(comp_cls
->help
, help
);
581 BT_LIB_LOGD("Set component class's help text: %!+C", comp_cls
);
582 return BT_FUNC_STATUS_OK
;
586 const char *bt_component_class_get_name(const struct bt_component_class
*comp_cls
)
588 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
589 return comp_cls
->name
->str
;
593 enum bt_component_class_type
bt_component_class_get_type(
594 const struct bt_component_class
*comp_cls
)
596 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
597 return comp_cls
->type
;
601 const char *bt_component_class_get_description(
602 const struct bt_component_class
*comp_cls
)
604 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
605 return comp_cls
->description
&&
606 comp_cls
->description
->str
[0] != '\0' ?
607 comp_cls
->description
->str
: NULL
;
611 const char *bt_component_class_get_help(
612 const struct bt_component_class
*comp_cls
)
614 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
615 return comp_cls
->help
&&
616 comp_cls
->help
->str
[0] != '\0' ? comp_cls
->help
->str
: NULL
;
619 void bt_component_class_add_destroy_listener(
620 struct bt_component_class
*comp_cls
,
621 bt_component_class_destroy_listener_func func
, void *data
)
623 struct bt_component_class_destroy_listener listener
;
627 listener
.func
= func
;
628 listener
.data
= data
;
629 g_array_append_val(comp_cls
->destroy_listeners
, listener
);
630 BT_LIB_LOGD("Added destroy listener to component class: "
631 "%![cc-]+C, listener-func-addr=%p", comp_cls
, func
);
634 void _bt_component_class_freeze(const struct bt_component_class
*comp_cls
)
637 BT_LIB_LOGD("Freezing component class: %!+C", comp_cls
);
638 ((struct bt_component_class
*) comp_cls
)->frozen
= true;
642 void bt_component_class_get_ref(
643 const struct bt_component_class
*component_class
)
645 bt_object_get_ref(component_class
);
649 void bt_component_class_put_ref(
650 const struct bt_component_class
*component_class
)
652 bt_object_put_ref(component_class
);
656 void bt_component_class_source_get_ref(
657 const struct bt_component_class_source
*component_class_source
)
659 bt_object_get_ref(component_class_source
);
663 void bt_component_class_source_put_ref(
664 const struct bt_component_class_source
*component_class_source
)
666 bt_object_put_ref(component_class_source
);
670 void bt_component_class_filter_get_ref(
671 const struct bt_component_class_filter
*component_class_filter
)
673 bt_object_get_ref(component_class_filter
);
677 void bt_component_class_filter_put_ref(
678 const struct bt_component_class_filter
*component_class_filter
)
680 bt_object_put_ref(component_class_filter
);
684 void bt_component_class_sink_get_ref(
685 const struct bt_component_class_sink
*component_class_sink
)
687 bt_object_get_ref(component_class_sink
);
691 void bt_component_class_sink_put_ref(
692 const struct bt_component_class_sink
*component_class_sink
)
694 bt_object_put_ref(component_class_sink
);