2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #define BT_LOG_TAG "COMP-CLASS"
25 #include <babeltrace/lib-logging-internal.h>
27 #include <babeltrace/compiler-internal.h>
28 #include <babeltrace/graph/component-class.h>
29 #include <babeltrace/graph/component-class-const.h>
30 #include <babeltrace/graph/component-class-source.h>
31 #include <babeltrace/graph/component-class-source-const.h>
32 #include <babeltrace/graph/component-class-filter.h>
33 #include <babeltrace/graph/component-class-filter-const.h>
34 #include <babeltrace/graph/component-class-sink.h>
35 #include <babeltrace/graph/component-class-sink-const.h>
36 #include <babeltrace/graph/component-class-internal.h>
37 #include <babeltrace/object.h>
38 #include <babeltrace/types.h>
39 #include <babeltrace/assert-internal.h>
40 #include <babeltrace/assert-pre-internal.h>
43 #define BT_ASSERT_PRE_COMP_CLS_HOT(_cc) \
44 BT_ASSERT_PRE_HOT(((const struct bt_component_class *) (_cc)), \
45 "Component class", ": %!+C", (_cc))
48 void destroy_component_class(struct bt_object
*obj
)
50 struct bt_component_class
*class;
54 class = container_of(obj
, struct bt_component_class
, base
);
56 BT_LIB_LOGD("Destroying component class: %!+C", class);
58 /* Call destroy listeners in reverse registration order */
59 for (i
= class->destroy_listeners
->len
- 1; i
>= 0; i
--) {
60 struct bt_component_class_destroy_listener
*listener
=
61 &g_array_index(class->destroy_listeners
,
62 struct bt_component_class_destroy_listener
,
65 BT_LOGD("Calling destroy listener: func-addr=%p, data-addr=%p",
66 listener
->func
, listener
->data
);
67 listener
->func(class, listener
->data
);
71 g_string_free(class->name
, TRUE
);
75 if (class->description
) {
76 g_string_free(class->description
, TRUE
);
77 class->description
= NULL
;
81 g_string_free(class->help
, TRUE
);
85 if (class->destroy_listeners
) {
86 g_array_free(class->destroy_listeners
, TRUE
);
87 class->destroy_listeners
= NULL
;
94 int bt_component_class_init(struct bt_component_class
*class,
95 enum bt_component_class_type type
, const char *name
)
99 bt_object_init_shared(&class->base
, destroy_component_class
);
101 class->name
= g_string_new(name
);
103 BT_LOGE_STR("Failed to allocate a GString.");
107 class->description
= g_string_new(NULL
);
108 if (!class->description
) {
109 BT_LOGE_STR("Failed to allocate a GString.");
113 class->help
= g_string_new(NULL
);
115 BT_LOGE_STR("Failed to allocate a GString.");
119 class->destroy_listeners
= g_array_new(FALSE
, TRUE
,
120 sizeof(struct bt_component_class_destroy_listener
));
121 if (!class->destroy_listeners
) {
122 BT_LOGE_STR("Failed to allocate a GArray.");
129 BT_OBJECT_PUT_REF_AND_RESET(class);
136 struct bt_component_class_source
*bt_component_class_source_create(
138 bt_component_class_source_notification_iterator_next_method method
)
140 struct bt_component_class_source
*source_class
= NULL
;
143 BT_ASSERT_PRE_NON_NULL(name
, "Name");
144 BT_ASSERT_PRE_NON_NULL(method
, "Notification iterator next method");
145 BT_LOGD("Creating source component class: "
146 "name=\"%s\", notif-iter-next-method-addr=%p",
148 source_class
= g_new0(struct bt_component_class_source
, 1);
150 BT_LOGE_STR("Failed to allocate one source component class.");
154 /* bt_component_class_init() logs errors */
155 ret
= bt_component_class_init(&source_class
->parent
,
156 BT_COMPONENT_CLASS_TYPE_SOURCE
, name
);
159 * If bt_component_class_init() fails, the component
160 * class is put, therefore its memory is already
167 source_class
->methods
.notif_iter_next
= method
;
168 BT_LIB_LOGD("Created source component class: %!+C", source_class
);
171 return (void *) source_class
;
174 struct bt_component_class_filter
*bt_component_class_filter_create(
176 bt_component_class_filter_notification_iterator_next_method method
)
178 struct bt_component_class_filter
*filter_class
= NULL
;
181 BT_ASSERT_PRE_NON_NULL(name
, "Name");
182 BT_ASSERT_PRE_NON_NULL(method
, "Notification iterator next method");
183 BT_LOGD("Creating filter component class: "
184 "name=\"%s\", notif-iter-next-method-addr=%p",
186 filter_class
= g_new0(struct bt_component_class_filter
, 1);
188 BT_LOGE_STR("Failed to allocate one filter component class.");
192 /* bt_component_class_init() logs errors */
193 ret
= bt_component_class_init(&filter_class
->parent
,
194 BT_COMPONENT_CLASS_TYPE_FILTER
, name
);
197 * If bt_component_class_init() fails, the component
198 * class is put, therefore its memory is already
205 filter_class
->methods
.notif_iter_next
= method
;
206 BT_LIB_LOGD("Created filter component class: %!+C", filter_class
);
209 return (void *) filter_class
;
212 struct bt_component_class_sink
*bt_component_class_sink_create(
213 const char *name
, bt_component_class_sink_consume_method method
)
215 struct bt_component_class_sink
*sink_class
= NULL
;
218 BT_ASSERT_PRE_NON_NULL(name
, "Name");
219 BT_ASSERT_PRE_NON_NULL(method
, "Consume next method");
220 BT_LOGD("Creating sink component class: "
221 "name=\"%s\", consume-method-addr=%p",
223 sink_class
= g_new0(struct bt_component_class_sink
, 1);
225 BT_LOGE_STR("Failed to allocate one sink component class.");
229 /* bt_component_class_init() logs errors */
230 ret
= bt_component_class_init(&sink_class
->parent
,
231 BT_COMPONENT_CLASS_TYPE_SINK
, name
);
234 * If bt_component_class_init() fails, the component
235 * class is put, therefore its memory is already
242 sink_class
->methods
.consume
= method
;
243 BT_LIB_LOGD("Created sink component class: %!+C", sink_class
);
246 return (void *) sink_class
;
249 int bt_component_class_source_set_init_method(
250 struct bt_component_class_source
*comp_cls
,
251 bt_component_class_source_init_method method
)
253 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
254 BT_ASSERT_PRE_NON_NULL(method
, "Method");
255 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
256 comp_cls
->methods
.init
= method
;
257 BT_LIB_LOGV("Set source component class's initialization method: "
262 int bt_component_class_filter_set_init_method(
263 struct bt_component_class_filter
*comp_cls
,
264 bt_component_class_filter_init_method method
)
266 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
267 BT_ASSERT_PRE_NON_NULL(method
, "Method");
268 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
269 comp_cls
->methods
.init
= method
;
270 BT_LIB_LOGV("Set filter component class's initialization method: "
275 int bt_component_class_sink_set_init_method(
276 struct bt_component_class_sink
*comp_cls
,
277 bt_component_class_sink_init_method method
)
279 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
280 BT_ASSERT_PRE_NON_NULL(method
, "Method");
281 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
282 comp_cls
->methods
.init
= method
;
283 BT_LIB_LOGV("Set sink component class's initialization method: "
288 int bt_component_class_source_set_finalize_method(
289 struct bt_component_class_source
*comp_cls
,
290 bt_component_class_source_finalize_method method
)
292 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
293 BT_ASSERT_PRE_NON_NULL(method
, "Method");
294 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
295 comp_cls
->methods
.finalize
= method
;
296 BT_LIB_LOGV("Set source component class's finalization method: "
301 int bt_component_class_filter_set_finalize_method(
302 struct bt_component_class_filter
*comp_cls
,
303 bt_component_class_filter_finalize_method method
)
305 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
306 BT_ASSERT_PRE_NON_NULL(method
, "Method");
307 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
308 comp_cls
->methods
.finalize
= method
;
309 BT_LIB_LOGV("Set filter component class's finalization method: "
314 int bt_component_class_sink_set_finalize_method(
315 struct bt_component_class_sink
*comp_cls
,
316 bt_component_class_sink_finalize_method method
)
318 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
319 BT_ASSERT_PRE_NON_NULL(method
, "Method");
320 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
321 comp_cls
->methods
.finalize
= method
;
322 BT_LIB_LOGV("Set sink component class's finalization method: "
327 int bt_component_class_source_set_query_method(
328 struct bt_component_class_source
*comp_cls
,
329 bt_component_class_source_query_method method
)
331 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
332 BT_ASSERT_PRE_NON_NULL(method
, "Method");
333 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
334 comp_cls
->methods
.query
= method
;
335 BT_LIB_LOGV("Set source component class's query method: "
340 int bt_component_class_filter_set_query_method(
341 struct bt_component_class_filter
*comp_cls
,
342 bt_component_class_filter_query_method method
)
344 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
345 BT_ASSERT_PRE_NON_NULL(method
, "Method");
346 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
347 comp_cls
->methods
.query
= method
;
348 BT_LIB_LOGV("Set filter component class's query method: "
353 int bt_component_class_sink_set_query_method(
354 struct bt_component_class_sink
*comp_cls
,
355 bt_component_class_sink_query_method method
)
357 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
358 BT_ASSERT_PRE_NON_NULL(method
, "Method");
359 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
360 comp_cls
->methods
.query
= method
;
361 BT_LIB_LOGV("Set sink component class's query method: "
366 int bt_component_class_filter_set_accept_input_port_connection_method(
367 struct bt_component_class_filter
*comp_cls
,
368 bt_component_class_filter_accept_input_port_connection_method method
)
370 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
371 BT_ASSERT_PRE_NON_NULL(method
, "Method");
372 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
373 comp_cls
->methods
.accept_input_port_connection
= method
;
374 BT_LIB_LOGV("Set filter component class's \"accept input port connection\" method"
379 int bt_component_class_sink_set_accept_input_port_connection_method(
380 struct bt_component_class_sink
*comp_cls
,
381 bt_component_class_sink_accept_input_port_connection_method method
)
383 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
384 BT_ASSERT_PRE_NON_NULL(method
, "Method");
385 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
386 comp_cls
->methods
.accept_input_port_connection
= method
;
387 BT_LIB_LOGV("Set sink component class's \"accept input port connection\" method"
392 int bt_component_class_source_set_accept_output_port_connection_method(
393 struct bt_component_class_source
*comp_cls
,
394 bt_component_class_source_accept_output_port_connection_method method
)
396 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
397 BT_ASSERT_PRE_NON_NULL(method
, "Method");
398 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
399 comp_cls
->methods
.accept_output_port_connection
= method
;
400 BT_LIB_LOGV("Set source component class's \"accept output port connection\" method"
405 int bt_component_class_filter_set_accept_output_port_connection_method(
406 struct bt_component_class_filter
*comp_cls
,
407 bt_component_class_filter_accept_output_port_connection_method method
)
409 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
410 BT_ASSERT_PRE_NON_NULL(method
, "Method");
411 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
412 comp_cls
->methods
.accept_output_port_connection
= method
;
413 BT_LIB_LOGV("Set filter component class's \"accept output port connection\" method"
418 int bt_component_class_filter_set_input_port_connected_method(
419 struct bt_component_class_filter
*comp_cls
,
420 bt_component_class_filter_input_port_connected_method method
)
422 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
423 BT_ASSERT_PRE_NON_NULL(method
, "Method");
424 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
425 comp_cls
->methods
.input_port_connected
= method
;
426 BT_LIB_LOGV("Set filter component class's \"input port connected\" method"
431 int bt_component_class_sink_set_input_port_connected_method(
432 struct bt_component_class_sink
*comp_cls
,
433 bt_component_class_sink_input_port_connected_method method
)
435 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
436 BT_ASSERT_PRE_NON_NULL(method
, "Method");
437 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
438 comp_cls
->methods
.input_port_connected
= method
;
439 BT_LIB_LOGV("Set sink component class's \"input port connected\" method"
444 int bt_component_class_source_set_output_port_connected_method(
445 struct bt_component_class_source
*comp_cls
,
446 bt_component_class_source_output_port_connected_method method
)
448 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
449 BT_ASSERT_PRE_NON_NULL(method
, "Method");
450 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
451 comp_cls
->methods
.output_port_connected
= method
;
452 BT_LIB_LOGV("Set source component class's \"output port connected\" method"
457 int bt_component_class_filter_set_output_port_connected_method(
458 struct bt_component_class_filter
*comp_cls
,
459 bt_component_class_filter_output_port_connected_method method
)
461 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
462 BT_ASSERT_PRE_NON_NULL(method
, "Method");
463 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
464 comp_cls
->methods
.output_port_connected
= method
;
465 BT_LIB_LOGV("Set filter component class's \"output port connected\" method"
470 int bt_component_class_filter_set_input_port_disconnected_method(
471 struct bt_component_class_filter
*comp_cls
,
472 bt_component_class_filter_input_port_disconnected_method method
)
474 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
475 BT_ASSERT_PRE_NON_NULL(method
, "Method");
476 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
477 comp_cls
->methods
.input_port_disconnected
= method
;
478 BT_LIB_LOGV("Set filter component class's \"input port disconnected\" method"
483 int bt_component_class_sink_set_input_port_disconnected_method(
484 struct bt_component_class_sink
*comp_cls
,
485 bt_component_class_sink_input_port_disconnected_method method
)
487 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
488 BT_ASSERT_PRE_NON_NULL(method
, "Method");
489 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
490 comp_cls
->methods
.input_port_disconnected
= method
;
491 BT_LIB_LOGV("Set sink component class's \"input port disconnected\" method"
496 int bt_component_class_source_set_output_port_disconnected_method(
497 struct bt_component_class_source
*comp_cls
,
498 bt_component_class_source_output_port_disconnected_method method
)
500 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
501 BT_ASSERT_PRE_NON_NULL(method
, "Method");
502 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
503 comp_cls
->methods
.output_port_disconnected
= method
;
504 BT_LIB_LOGV("Set source component class's \"output port disconnected\" method"
509 int bt_component_class_filter_set_output_port_disconnected_method(
510 struct bt_component_class_filter
*comp_cls
,
511 bt_component_class_filter_output_port_disconnected_method method
)
513 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
514 BT_ASSERT_PRE_NON_NULL(method
, "Method");
515 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
516 comp_cls
->methods
.output_port_disconnected
= method
;
517 BT_LIB_LOGV("Set filter component class's \"output port disconnected\" method"
522 int bt_component_class_source_set_notification_iterator_init_method(
523 struct bt_component_class_source
*comp_cls
,
524 bt_component_class_source_notification_iterator_init_method method
)
526 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
527 BT_ASSERT_PRE_NON_NULL(method
, "Method");
528 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
529 comp_cls
->methods
.notif_iter_init
= method
;
530 BT_LIB_LOGV("Set source component class's notification iterator initialization method"
535 int bt_component_class_filter_set_notification_iterator_init_method(
536 struct bt_component_class_filter
*comp_cls
,
537 bt_component_class_filter_notification_iterator_init_method method
)
539 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
540 BT_ASSERT_PRE_NON_NULL(method
, "Method");
541 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
542 comp_cls
->methods
.notif_iter_init
= method
;
543 BT_LIB_LOGV("Set filter component class's notification iterator initialization method"
548 int bt_component_class_source_set_notification_iterator_finalize_method(
549 struct bt_component_class_source
*comp_cls
,
550 bt_component_class_source_notification_iterator_finalize_method method
)
552 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
553 BT_ASSERT_PRE_NON_NULL(method
, "Method");
554 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
555 comp_cls
->methods
.notif_iter_finalize
= method
;
556 BT_LIB_LOGV("Set source component class's notification iterator finalization method"
561 int bt_component_class_filter_set_notification_iterator_finalize_method(
562 struct bt_component_class_filter
*comp_cls
,
563 bt_component_class_filter_notification_iterator_finalize_method method
)
565 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
566 BT_ASSERT_PRE_NON_NULL(method
, "Method");
567 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
568 comp_cls
->methods
.notif_iter_finalize
= method
;
569 BT_LIB_LOGV("Set filter component class's notification iterator finalization method"
574 int bt_component_class_set_description(
575 struct bt_component_class
*comp_cls
,
576 const char *description
)
578 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
579 BT_ASSERT_PRE_NON_NULL(description
, "Description");
580 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
581 g_string_assign(comp_cls
->description
, description
);
582 BT_LIB_LOGV("Set component class's description: "
583 "addr=%p, name=\"%s\", type=%s",
585 bt_component_class_get_name(comp_cls
),
586 bt_component_class_type_string(comp_cls
->type
));
590 int bt_component_class_set_help(
591 struct bt_component_class
*comp_cls
,
594 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
595 BT_ASSERT_PRE_NON_NULL(help
, "Help");
596 BT_ASSERT_PRE_COMP_CLS_HOT(comp_cls
);
597 g_string_assign(comp_cls
->help
, help
);
598 BT_LIB_LOGV("Set component class's help text: %!+C", comp_cls
);
602 const char *bt_component_class_get_name(const struct bt_component_class
*comp_cls
)
604 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
605 return comp_cls
->name
->str
;
608 enum bt_component_class_type
bt_component_class_get_type(
609 const struct bt_component_class
*comp_cls
)
611 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
612 return comp_cls
->type
;
615 const char *bt_component_class_get_description(
616 const struct bt_component_class
*comp_cls
)
618 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
619 return comp_cls
->description
&&
620 comp_cls
->description
->str
[0] != '\0' ?
621 comp_cls
->description
->str
: NULL
;
624 const char *bt_component_class_get_help(
625 const struct bt_component_class
*comp_cls
)
627 BT_ASSERT_PRE_NON_NULL(comp_cls
, "Component class");
628 return comp_cls
->help
&&
629 comp_cls
->help
->str
[0] != '\0' ? comp_cls
->help
->str
: NULL
;
633 void bt_component_class_add_destroy_listener(
634 struct bt_component_class
*comp_cls
,
635 bt_component_class_destroy_listener_func func
, void *data
)
637 struct bt_component_class_destroy_listener listener
;
641 listener
.func
= func
;
642 listener
.data
= data
;
643 g_array_append_val(comp_cls
->destroy_listeners
, listener
);
644 BT_LIB_LOGV("Added destroy listener to component class: "
645 "%![cc-]+C, listener-func-addr=%p", comp_cls
, func
);
649 void _bt_component_class_freeze(const struct bt_component_class
*comp_cls
)
652 BT_LIB_LOGD("Freezing component class: %!+C", comp_cls
);
653 ((struct bt_component_class
*) comp_cls
)->frozen
= true;