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-cond.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("component-class", \
24 ((const struct bt_component_class *) (_cc)), \
25 "Component class", ": %!+C", (_cc))
28 void destroy_component_class(struct bt_object
*obj
)
30 struct bt_component_class
*class;
34 class = container_of(obj
, struct bt_component_class
, base
);
36 BT_LIB_LOGI("Destroying component class: %!+C", class);
38 /* Call destroy listeners in reverse registration order */
39 if (class->destroy_listeners
) {
40 for (i
= class->destroy_listeners
->len
- 1; i
>= 0; i
--) {
41 struct bt_component_class_destroy_listener
*listener
=
42 &g_array_index(class->destroy_listeners
,
43 struct bt_component_class_destroy_listener
,
46 BT_LOGD("Calling destroy listener: func-addr=%p, data-addr=%p",
47 listener
->func
, listener
->data
);
48 listener
->func(class, listener
->data
);
53 g_string_free(class->name
, TRUE
);
57 if (class->description
) {
58 g_string_free(class->description
, TRUE
);
59 class->description
= NULL
;
63 g_string_free(class->help
, TRUE
);
67 if (class->plugin_name
) {
68 g_string_free(class->plugin_name
, TRUE
);
69 class->plugin_name
= NULL
;
72 if (class->destroy_listeners
) {
73 g_array_free(class->destroy_listeners
, TRUE
);
74 class->destroy_listeners
= NULL
;
77 if (bt_component_class_has_message_iterator_class(class)) {
78 struct bt_component_class_with_iterator_class
*class_with_iter_class
=
79 container_of(class, struct bt_component_class_with_iterator_class
, parent
);
81 BT_ASSERT(class_with_iter_class
->msg_iter_cls
);
82 bt_message_iterator_class_put_ref(class_with_iter_class
->msg_iter_cls
);
83 class_with_iter_class
->msg_iter_cls
= NULL
;
90 int bt_component_class_init(struct bt_component_class
*class,
91 enum bt_component_class_type type
, const char *name
)
95 bt_object_init_shared(&class->base
, destroy_component_class
);
97 class->name
= g_string_new(name
);
99 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
103 class->description
= g_string_new(NULL
);
104 if (!class->description
) {
105 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
109 class->help
= g_string_new(NULL
);
111 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
115 class->plugin_name
= g_string_new(NULL
);
116 if (!class->plugin_name
) {
117 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
121 class->destroy_listeners
= g_array_new(FALSE
, TRUE
,
122 sizeof(struct bt_component_class_destroy_listener
));
123 if (!class->destroy_listeners
) {
124 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
131 BT_OBJECT_PUT_REF_AND_RESET(class);
139 int bt_component_class_with_iterator_class_init(
140 struct bt_component_class_with_iterator_class
*class,
141 enum bt_component_class_type type
, const char *name
,
142 struct bt_message_iterator_class
*message_iterator_class
)
146 ret
= bt_component_class_init(&class->parent
, type
, name
);
151 class->msg_iter_cls
= message_iterator_class
;
152 bt_message_iterator_class_get_ref(class->msg_iter_cls
);
153 bt_message_iterator_class_freeze(class->msg_iter_cls
);
160 struct bt_component_class_source
*bt_component_class_source_create(
162 struct bt_message_iterator_class
*message_iterator_class
)
164 struct bt_component_class_source
*source_class
= NULL
;
167 BT_ASSERT_PRE_NO_ERROR();
168 BT_ASSERT_PRE_NAME_NON_NULL(name
);
169 BT_ASSERT_PRE_MSG_ITER_CLS_NON_NULL(message_iterator_class
);
170 BT_LIB_LOGI("Creating source component class: "
171 "name=\"%s\", %![msg-iter-cls-]+I",
172 name
, message_iterator_class
);
173 source_class
= g_new0(struct bt_component_class_source
, 1);
175 BT_LIB_LOGE_APPEND_CAUSE(
176 "Failed to allocate one source component class.");
180 /* bt_component_class_init() logs errors */
181 ret
= bt_component_class_with_iterator_class_init(&source_class
->parent
,
182 BT_COMPONENT_CLASS_TYPE_SOURCE
, name
, message_iterator_class
);
185 * If bt_component_class_init() fails, the component
186 * class is put, therefore its memory is already
193 BT_LIB_LOGI("Created source component class: %!+C", source_class
);
196 return (void *) source_class
;
200 struct bt_component_class_filter
*bt_component_class_filter_create(
202 struct bt_message_iterator_class
*message_iterator_class
)
204 struct bt_component_class_filter
*filter_class
= NULL
;
207 BT_ASSERT_PRE_NO_ERROR();
208 BT_ASSERT_PRE_NAME_NON_NULL(name
);
209 BT_ASSERT_PRE_MSG_ITER_CLS_NON_NULL(message_iterator_class
);
210 BT_LIB_LOGI("Creating filter component class: "
211 "name=\"%s\", %![msg-iter-cls-]+I",
212 name
, message_iterator_class
);
213 filter_class
= g_new0(struct bt_component_class_filter
, 1);
215 BT_LIB_LOGE_APPEND_CAUSE(
216 "Failed to allocate one filter component class.");
220 /* bt_component_class_init() logs errors */
221 ret
= bt_component_class_with_iterator_class_init(&filter_class
->parent
,
222 BT_COMPONENT_CLASS_TYPE_FILTER
, name
, message_iterator_class
);
225 * If bt_component_class_init() fails, the component
226 * class is put, therefore its memory is already
233 BT_LIB_LOGI("Created filter component class: %!+C", filter_class
);
236 return (void *) filter_class
;
240 struct bt_component_class_sink
*bt_component_class_sink_create(
241 const char *name
, bt_component_class_sink_consume_method method
)
243 struct bt_component_class_sink
*sink_class
= NULL
;
246 BT_ASSERT_PRE_NO_ERROR();
247 BT_ASSERT_PRE_NAME_NON_NULL(name
);
248 BT_ASSERT_PRE_NON_NULL("consume-method", method
, "Consume next method");
249 BT_LOGI("Creating sink component class: "
250 "name=\"%s\", consume-method-addr=%p",
252 sink_class
= g_new0(struct bt_component_class_sink
, 1);
254 BT_LIB_LOGE_APPEND_CAUSE(
255 "Failed to allocate one sink component class.");
259 /* bt_component_class_init() logs errors */
260 ret
= bt_component_class_init(&sink_class
->parent
,
261 BT_COMPONENT_CLASS_TYPE_SINK
, name
);
264 * If bt_component_class_init() fails, the component
265 * class is put, therefore its memory is already
272 sink_class
->methods
.consume
= method
;
273 BT_LIB_LOGI("Created sink component class: %!+C", sink_class
);
276 return (void *) sink_class
;
280 enum bt_component_class_set_method_status
281 bt_component_class_source_set_get_supported_mip_versions_method(
282 struct bt_component_class_source
*comp_cls
,
283 bt_component_class_source_get_supported_mip_versions_method method
)
285 BT_ASSERT_PRE_NO_ERROR();
286 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
287 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
288 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
289 comp_cls
->methods
.get_supported_mip_versions
= method
;
290 BT_LIB_LOGD("Set source component class's \"get supported MIP versions\" method: "
292 return BT_FUNC_STATUS_OK
;
296 enum bt_component_class_set_method_status
297 bt_component_class_filter_set_get_supported_mip_versions_method(
298 struct bt_component_class_filter
*comp_cls
,
299 bt_component_class_filter_get_supported_mip_versions_method method
)
301 BT_ASSERT_PRE_NO_ERROR();
302 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
303 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
304 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
305 comp_cls
->methods
.get_supported_mip_versions
= method
;
306 BT_LIB_LOGD("Set filter component class's \"get supported MIP versions\" method: "
308 return BT_FUNC_STATUS_OK
;
312 enum bt_component_class_set_method_status
313 bt_component_class_sink_set_get_supported_mip_versions_method(
314 struct bt_component_class_sink
*comp_cls
,
315 bt_component_class_sink_get_supported_mip_versions_method method
)
317 BT_ASSERT_PRE_NO_ERROR();
318 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
319 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
320 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
321 comp_cls
->methods
.get_supported_mip_versions
= method
;
322 BT_LIB_LOGD("Set sink component class's \"get supported MIP versions\" method: "
324 return BT_FUNC_STATUS_OK
;
328 enum bt_component_class_set_method_status
329 bt_component_class_source_set_initialize_method(
330 struct bt_component_class_source
*comp_cls
,
331 bt_component_class_source_initialize_method method
)
333 BT_ASSERT_PRE_NO_ERROR();
334 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
335 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
336 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
337 comp_cls
->methods
.init
= method
;
338 BT_LIB_LOGD("Set source component class's initialization method: "
340 return BT_FUNC_STATUS_OK
;
344 enum bt_component_class_set_method_status
345 bt_component_class_filter_set_initialize_method(
346 struct bt_component_class_filter
*comp_cls
,
347 bt_component_class_filter_initialize_method method
)
349 BT_ASSERT_PRE_NO_ERROR();
350 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
351 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
352 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
353 comp_cls
->methods
.init
= method
;
354 BT_LIB_LOGD("Set filter component class's initialization method: "
356 return BT_FUNC_STATUS_OK
;
360 enum bt_component_class_set_method_status
361 bt_component_class_sink_set_initialize_method(
362 struct bt_component_class_sink
*comp_cls
,
363 bt_component_class_sink_initialize_method method
)
365 BT_ASSERT_PRE_NO_ERROR();
366 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
367 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
368 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
369 comp_cls
->methods
.init
= method
;
370 BT_LIB_LOGD("Set sink component class's initialization method: "
372 return BT_FUNC_STATUS_OK
;
376 enum bt_component_class_set_method_status
377 bt_component_class_source_set_finalize_method(
378 struct bt_component_class_source
*comp_cls
,
379 bt_component_class_source_finalize_method method
)
381 BT_ASSERT_PRE_NO_ERROR();
382 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
383 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
384 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
385 comp_cls
->methods
.finalize
= method
;
386 BT_LIB_LOGD("Set source component class's finalization method: "
388 return BT_FUNC_STATUS_OK
;
392 enum bt_component_class_set_method_status
393 bt_component_class_filter_set_finalize_method(
394 struct bt_component_class_filter
*comp_cls
,
395 bt_component_class_filter_finalize_method method
)
397 BT_ASSERT_PRE_NO_ERROR();
398 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
399 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
400 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
401 comp_cls
->methods
.finalize
= method
;
402 BT_LIB_LOGD("Set filter component class's finalization method: "
404 return BT_FUNC_STATUS_OK
;
408 enum bt_component_class_set_method_status
409 bt_component_class_sink_set_finalize_method(
410 struct bt_component_class_sink
*comp_cls
,
411 bt_component_class_sink_finalize_method method
)
413 BT_ASSERT_PRE_NO_ERROR();
414 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
415 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
416 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
417 comp_cls
->methods
.finalize
= method
;
418 BT_LIB_LOGD("Set sink component class's finalization method: "
420 return BT_FUNC_STATUS_OK
;
424 enum bt_component_class_set_method_status
425 bt_component_class_source_set_query_method(
426 struct bt_component_class_source
*comp_cls
,
427 bt_component_class_source_query_method method
)
429 BT_ASSERT_PRE_NO_ERROR();
430 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
431 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
432 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
433 comp_cls
->methods
.query
= method
;
434 BT_LIB_LOGD("Set source component class's query method: "
436 return BT_FUNC_STATUS_OK
;
440 enum bt_component_class_set_method_status
441 bt_component_class_filter_set_query_method(
442 struct bt_component_class_filter
*comp_cls
,
443 bt_component_class_filter_query_method method
)
445 BT_ASSERT_PRE_NO_ERROR();
446 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
447 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
448 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
449 comp_cls
->methods
.query
= method
;
450 BT_LIB_LOGD("Set filter component class's query method: "
452 return BT_FUNC_STATUS_OK
;
456 enum bt_component_class_set_method_status
457 bt_component_class_sink_set_query_method(
458 struct bt_component_class_sink
*comp_cls
,
459 bt_component_class_sink_query_method method
)
461 BT_ASSERT_PRE_NO_ERROR();
462 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
463 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
464 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
465 comp_cls
->methods
.query
= method
;
466 BT_LIB_LOGD("Set sink component class's query method: "
468 return BT_FUNC_STATUS_OK
;
472 enum bt_component_class_set_method_status
473 bt_component_class_filter_set_input_port_connected_method(
474 struct bt_component_class_filter
*comp_cls
,
475 bt_component_class_filter_input_port_connected_method method
)
477 BT_ASSERT_PRE_NO_ERROR();
478 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
479 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
480 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
481 comp_cls
->methods
.input_port_connected
= method
;
482 BT_LIB_LOGD("Set filter component class's \"input port connected\" method"
484 return BT_FUNC_STATUS_OK
;
488 enum bt_component_class_set_method_status
489 bt_component_class_sink_set_input_port_connected_method(
490 struct bt_component_class_sink
*comp_cls
,
491 bt_component_class_sink_input_port_connected_method method
)
493 BT_ASSERT_PRE_NO_ERROR();
494 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
495 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
496 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
497 comp_cls
->methods
.input_port_connected
= method
;
498 BT_LIB_LOGD("Set sink component class's \"input port connected\" method"
500 return BT_FUNC_STATUS_OK
;
504 enum bt_component_class_set_method_status
505 bt_component_class_source_set_output_port_connected_method(
506 struct bt_component_class_source
*comp_cls
,
507 bt_component_class_source_output_port_connected_method method
)
509 BT_ASSERT_PRE_NO_ERROR();
510 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
511 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
512 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
513 comp_cls
->methods
.output_port_connected
= method
;
514 BT_LIB_LOGD("Set source component class's \"output port connected\" method"
516 return BT_FUNC_STATUS_OK
;
520 enum bt_component_class_set_method_status
521 bt_component_class_filter_set_output_port_connected_method(
522 struct bt_component_class_filter
*comp_cls
,
523 bt_component_class_filter_output_port_connected_method method
)
525 BT_ASSERT_PRE_NO_ERROR();
526 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
527 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
528 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
529 comp_cls
->methods
.output_port_connected
= method
;
530 BT_LIB_LOGD("Set filter component class's \"output port connected\" method"
532 return BT_FUNC_STATUS_OK
;
536 enum bt_component_class_set_method_status
537 bt_component_class_sink_set_graph_is_configured_method(
538 struct bt_component_class_sink
*comp_cls
,
539 bt_component_class_sink_graph_is_configured_method method
)
541 BT_ASSERT_PRE_NO_ERROR();
542 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
543 BT_ASSERT_PRE_METHOD_NON_NULL(method
);
544 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
545 comp_cls
->methods
.graph_is_configured
= method
;
546 BT_LIB_LOGD("Set sink component class's \"graph is configured\" method"
548 return BT_FUNC_STATUS_OK
;
552 enum bt_component_class_set_description_status
553 bt_component_class_set_description(
554 struct bt_component_class
*comp_cls
,
555 const char *description
)
557 BT_ASSERT_PRE_NO_ERROR();
558 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
559 BT_ASSERT_PRE_DESCR_NON_NULL(description
);
560 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
561 g_string_assign(comp_cls
->description
, description
);
562 BT_LIB_LOGD("Set component class's description: "
563 "addr=%p, name=\"%s\", type=%s",
565 bt_component_class_get_name(comp_cls
),
566 bt_common_component_class_type_string(comp_cls
->type
));
567 return BT_FUNC_STATUS_OK
;
571 enum bt_component_class_set_help_status
bt_component_class_set_help(
572 struct bt_component_class
*comp_cls
,
575 BT_ASSERT_PRE_NO_ERROR();
576 BT_ASSERT_PRE_COMP_CLS_NON_NULL(comp_cls
);
577 BT_ASSERT_PRE_NON_NULL("help-text", help
, "Help text");
578 BT_ASSERT_PRE_DEV_COMP_CLS_HOT(comp_cls
);
579 g_string_assign(comp_cls
->help
, help
);
580 BT_LIB_LOGD("Set component class's help text: %!+C", comp_cls
);
581 return BT_FUNC_STATUS_OK
;
585 const char *bt_component_class_get_name(const struct bt_component_class
*comp_cls
)
587 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
588 return comp_cls
->name
->str
;
592 enum bt_component_class_type
bt_component_class_get_type(
593 const struct bt_component_class
*comp_cls
)
595 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
596 return comp_cls
->type
;
600 const char *bt_component_class_get_description(
601 const struct bt_component_class
*comp_cls
)
603 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
604 return comp_cls
->description
&&
605 comp_cls
->description
->str
[0] != '\0' ?
606 comp_cls
->description
->str
: NULL
;
610 const char *bt_component_class_get_help(
611 const struct bt_component_class
*comp_cls
)
613 BT_ASSERT_PRE_DEV_COMP_CLS_NON_NULL(comp_cls
);
614 return comp_cls
->help
&&
615 comp_cls
->help
->str
[0] != '\0' ? comp_cls
->help
->str
: NULL
;
618 void bt_component_class_add_destroy_listener(
619 struct bt_component_class
*comp_cls
,
620 bt_component_class_destroy_listener_func func
, void *data
)
622 struct bt_component_class_destroy_listener listener
;
626 listener
.func
= func
;
627 listener
.data
= data
;
628 g_array_append_val(comp_cls
->destroy_listeners
, listener
);
629 BT_LIB_LOGD("Added destroy listener to component class: "
630 "%![cc-]+C, listener-func-addr=%p", comp_cls
, func
);
633 void _bt_component_class_freeze(const struct bt_component_class
*comp_cls
)
636 BT_LIB_LOGD("Freezing component class: %!+C", comp_cls
);
637 ((struct bt_component_class
*) comp_cls
)->frozen
= true;
641 void bt_component_class_get_ref(
642 const struct bt_component_class
*component_class
)
644 bt_object_get_ref(component_class
);
648 void bt_component_class_put_ref(
649 const struct bt_component_class
*component_class
)
651 bt_object_put_ref(component_class
);
655 void bt_component_class_source_get_ref(
656 const struct bt_component_class_source
*component_class_source
)
658 bt_object_get_ref(component_class_source
);
662 void bt_component_class_source_put_ref(
663 const struct bt_component_class_source
*component_class_source
)
665 bt_object_put_ref(component_class_source
);
669 void bt_component_class_filter_get_ref(
670 const struct bt_component_class_filter
*component_class_filter
)
672 bt_object_get_ref(component_class_filter
);
676 void bt_component_class_filter_put_ref(
677 const struct bt_component_class_filter
*component_class_filter
)
679 bt_object_put_ref(component_class_filter
);
683 void bt_component_class_sink_get_ref(
684 const struct bt_component_class_sink
*component_class_sink
)
686 bt_object_get_ref(component_class_sink
);
690 void bt_component_class_sink_put_ref(
691 const struct bt_component_class_sink
*component_class_sink
)
693 bt_object_put_ref(component_class_sink
);