2 * SPDX-License-Identifier: MIT
4 * Copyright (c) 2019 Philippe Proulx <pproulx@efficios.com>
7 #define BT_LOG_TAG "LIB/ERROR"
8 #include "lib/logging.h"
12 #include <babeltrace2/babeltrace.h>
15 #include "graph/component.h"
16 #include "graph/component-class.h"
17 #include "graph/iterator.h"
18 #include "common/assert.h"
19 #include "common/common.h"
20 #include "lib/assert-cond.h"
21 #include "lib/func-status.h"
23 #define BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(_cause, _exp_type_name, _exp_type) \
24 BT_ASSERT_PRE("error-cause-has-" _exp_type_name "-actor", \
25 ((const struct bt_error_cause *) (_cause))->actor_type == _exp_type, \
26 "Unexpected error cause's actor type: type=%s, exp-type=%s", \
27 bt_error_cause_actor_type_string(((const struct bt_error_cause *) (_cause))->actor_type), \
28 bt_error_cause_actor_type_string(_exp_type))
31 void fini_component_class_id(
32 struct bt_error_cause_component_class_id
*comp_class_id
)
34 BT_ASSERT(comp_class_id
);
36 if (comp_class_id
->name
) {
37 g_string_free(comp_class_id
->name
, TRUE
);
38 comp_class_id
->name
= NULL
;
41 if (comp_class_id
->plugin_name
) {
42 g_string_free(comp_class_id
->plugin_name
, TRUE
);
43 comp_class_id
->plugin_name
= NULL
;
48 void fini_error_cause(struct bt_error_cause
*cause
)
51 BT_LIB_LOGD("Finalizing error cause: %!+r", cause
);
53 if (cause
->module_name
) {
54 g_string_free(cause
->module_name
, TRUE
);
55 cause
->module_name
= NULL
;
58 if (cause
->file_name
) {
59 g_string_free(cause
->file_name
, TRUE
);
60 cause
->file_name
= NULL
;
64 g_string_free(cause
->message
, TRUE
);
65 cause
->message
= NULL
;
70 void destroy_error_cause(struct bt_error_cause
*cause
)
76 BT_LIB_LOGD("Destroying error cause: %!+r", cause
);
78 switch (cause
->actor_type
) {
79 case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
:
81 struct bt_error_cause_component_actor
*spec_cause
=
84 if (spec_cause
->comp_name
) {
85 g_string_free(spec_cause
->comp_name
, TRUE
);
86 spec_cause
->comp_name
= NULL
;
89 fini_component_class_id(&spec_cause
->comp_class_id
);
92 case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
:
94 struct bt_error_cause_component_class_actor
*spec_cause
=
97 fini_component_class_id(&spec_cause
->comp_class_id
);
100 case BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
:
102 struct bt_error_cause_message_iterator_actor
*spec_cause
=
105 if (spec_cause
->comp_name
) {
106 g_string_free(spec_cause
->comp_name
, TRUE
);
107 spec_cause
->comp_name
= NULL
;
110 if (spec_cause
->output_port_name
) {
111 g_string_free(spec_cause
->output_port_name
, TRUE
);
112 spec_cause
->output_port_name
= NULL
;
115 fini_component_class_id(&spec_cause
->comp_class_id
);
122 fini_error_cause(cause
);
130 int init_error_cause(struct bt_error_cause
*cause
,
131 enum bt_error_cause_actor_type actor_type
)
136 BT_LIB_LOGD("Initializing error cause: %!+r", cause
);
137 cause
->actor_type
= actor_type
;
138 cause
->module_name
= g_string_new(NULL
);
139 if (!cause
->module_name
) {
140 BT_LOGE_STR("Failed to allocate one GString.");
145 cause
->message
= g_string_new(NULL
);
146 if (!cause
->message
) {
147 BT_LOGE_STR("Failed to allocate one GString.");
152 cause
->file_name
= g_string_new(NULL
);
153 if (!cause
->file_name
) {
154 BT_LOGE_STR("Failed to allocate one GString.");
164 int init_component_class_id(
165 struct bt_error_cause_component_class_id
*comp_class_id
,
166 struct bt_component_class
*comp_cls
)
170 BT_ASSERT(comp_class_id
);
171 comp_class_id
->type
= comp_cls
->type
;
172 comp_class_id
->name
= g_string_new(comp_cls
->name
->str
);
173 if (!comp_class_id
->name
) {
174 BT_LOGE_STR("Failed to allocate one GString.");
179 comp_class_id
->plugin_name
= g_string_new(comp_cls
->plugin_name
->str
);
180 if (!comp_class_id
->plugin_name
) {
181 BT_LOGE_STR("Failed to allocate one GString.");
191 void set_error_cause_props(struct bt_error_cause
*cause
,
192 const char *file_name
, uint64_t line_no
)
195 g_string_assign(cause
->file_name
, file_name
);
196 cause
->line_no
= line_no
;
200 struct bt_error_cause
*create_error_cause(const char *module_name
,
201 const char *file_name
, uint64_t line_no
)
203 struct bt_error_cause
*cause
= g_new0(struct bt_error_cause
, 1);
206 BT_LOGD_STR("Creating error cause (unknown actor).");
209 BT_LOGE_STR("Failed to allocate one error cause.");
213 ret
= init_error_cause(cause
, BT_ERROR_CAUSE_ACTOR_TYPE_UNKNOWN
);
218 g_string_assign(cause
->module_name
, module_name
);
219 set_error_cause_props(cause
, file_name
, line_no
);
220 BT_LIB_LOGD("Created error cause: %!+r", cause
);
224 destroy_error_cause(cause
);
232 void append_component_class_id_str(GString
*str
,
233 struct bt_error_cause_component_class_id
*comp_class_id
)
235 const char *type_str
= NULL
;
237 switch (comp_class_id
->type
) {
238 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
241 case BT_COMPONENT_CLASS_TYPE_FILTER
:
244 case BT_COMPONENT_CLASS_TYPE_SINK
:
251 if (comp_class_id
->plugin_name
->len
> 0) {
252 g_string_append_printf(str
, "%s.%s.%s",
253 type_str
, comp_class_id
->plugin_name
->str
,
254 comp_class_id
->name
->str
);
256 g_string_append_printf(str
, "%s.%s",
257 type_str
, comp_class_id
->name
->str
);
262 struct bt_error_cause_component_actor
*create_error_cause_component_actor(
263 struct bt_component
*comp
, const char *file_name
,
266 struct bt_error_cause_component_actor
*cause
=
267 g_new0(struct bt_error_cause_component_actor
, 1);
270 BT_LOGD_STR("Creating error cause object (component actor).");
276 ret
= init_error_cause(&cause
->base
,
277 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
282 set_error_cause_props(&cause
->base
, file_name
, line_no
);
283 cause
->comp_name
= g_string_new(comp
->name
->str
);
284 if (!cause
->comp_name
) {
285 BT_LOGE_STR("Failed to allocate one GString.");
289 ret
= init_component_class_id(&cause
->comp_class_id
, comp
->class);
294 g_string_append_printf(cause
->base
.module_name
, "%s: ",
296 append_component_class_id_str(cause
->base
.module_name
,
297 &cause
->comp_class_id
);
298 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
303 destroy_error_cause(&cause
->base
);
312 struct bt_error_cause_component_class_actor
*
313 create_error_cause_component_class_actor(struct bt_component_class
*comp_cls
,
314 const char *file_name
, uint64_t line_no
)
316 struct bt_error_cause_component_class_actor
*cause
=
317 g_new0(struct bt_error_cause_component_class_actor
, 1);
320 BT_LOGD_STR("Creating error cause object (component class actor).");
323 BT_LOGE_STR("Failed to allocate one error cause object.");
327 ret
= init_error_cause(&cause
->base
,
328 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
333 set_error_cause_props(&cause
->base
, file_name
, line_no
);
334 ret
= init_component_class_id(&cause
->comp_class_id
, comp_cls
);
339 append_component_class_id_str(cause
->base
.module_name
,
340 &cause
->comp_class_id
);
341 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
346 destroy_error_cause(&cause
->base
);
355 struct bt_error_cause_message_iterator_actor
*
356 create_error_cause_message_iterator_actor(struct bt_message_iterator
*iter
,
357 const char *file_name
, uint64_t line_no
)
359 struct bt_error_cause_message_iterator_actor
*cause
;
360 struct bt_message_iterator
*input_port_iter
;
363 BT_LOGD_STR("Creating error cause object (message iterator actor).");
366 * This can only be created from within a graph, from a user
367 * message iterator, which is a self component port input
370 input_port_iter
= (void *) iter
;
371 cause
= g_new0(struct bt_error_cause_message_iterator_actor
, 1);
373 BT_LOGE_STR("Failed to allocate one error cause object.");
377 ret
= init_error_cause(&cause
->base
,
378 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
383 set_error_cause_props(&cause
->base
, file_name
, line_no
);
384 cause
->comp_name
= g_string_new(
385 input_port_iter
->upstream_component
->name
->str
);
386 if (!cause
->comp_name
) {
387 BT_LOGE_STR("Failed to allocate one GString.");
391 cause
->output_port_name
= g_string_new(
392 input_port_iter
->upstream_port
->name
->str
);
393 if (!cause
->output_port_name
) {
394 BT_LOGE_STR("Failed to allocate one GString.");
398 ret
= init_component_class_id(&cause
->comp_class_id
,
399 input_port_iter
->upstream_component
->class);
404 g_string_append_printf(cause
->base
.module_name
, "%s (%s): ",
405 input_port_iter
->upstream_component
->name
->str
,
406 input_port_iter
->upstream_port
->name
->str
);
407 append_component_class_id_str(cause
->base
.module_name
,
408 &cause
->comp_class_id
);
409 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
414 destroy_error_cause(&cause
->base
);
422 struct bt_error
*bt_error_create(void)
424 struct bt_error
*error
;
426 BT_LOGD_STR("Creating error object.");
427 error
= g_new0(struct bt_error
, 1);
429 BT_LOGE_STR("Failed to allocate one error object.");
433 error
->causes
= g_ptr_array_new_with_free_func(
434 (GDestroyNotify
) destroy_error_cause
);
435 if (!error
->causes
) {
436 BT_LOGE_STR("Failed to allocate one GPtrArray.");
440 BT_LOGD("Created error object: addr=%p", error
);
444 bt_error_destroy(error
);
451 void bt_error_destroy(struct bt_error
*error
)
458 g_ptr_array_free(error
->causes
, TRUE
);
459 error
->causes
= NULL
;
468 int bt_error_append_cause_from_unknown(struct bt_error
*error
,
469 const char *module_name
, const char *file_name
,
470 uint64_t line_no
, const char *msg_fmt
, va_list args
)
472 struct bt_error_cause
*cause
= NULL
;
473 int status
= BT_FUNC_STATUS_OK
;
476 BT_ASSERT(module_name
);
477 BT_ASSERT(file_name
);
479 BT_LOGD("Appending error cause from unknown actor: "
480 "module-name=\"%s\", func-name=\"%s\", line-no=%" PRIu64
,
481 module_name
, file_name
, line_no
);
482 cause
= create_error_cause(module_name
, file_name
, line_no
);
484 /* create_error_cause() logs errors */
485 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
489 g_string_append_vprintf(cause
->message
, msg_fmt
, args
);
490 g_ptr_array_add(error
->causes
, cause
);
491 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
498 int bt_error_append_cause_from_component(
499 struct bt_error
*error
, bt_self_component
*self_comp
,
500 const char *file_name
, uint64_t line_no
,
501 const char *msg_fmt
, va_list args
)
503 struct bt_error_cause_component_actor
*cause
= NULL
;
504 int status
= BT_FUNC_STATUS_OK
;
507 BT_ASSERT(self_comp
);
508 BT_ASSERT(file_name
);
510 BT_LIB_LOGD("Appending error cause from component actor: %![comp-]+c",
512 cause
= create_error_cause_component_actor((void *) self_comp
,
515 /* create_error_cause_component_actor() logs errors */
516 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
520 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
521 g_ptr_array_add(error
->causes
, cause
);
522 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
529 int bt_error_append_cause_from_component_class(
530 struct bt_error
*error
,
531 bt_self_component_class
*self_comp_class
,
532 const char *file_name
, uint64_t line_no
,
533 const char *msg_fmt
, va_list args
)
535 struct bt_error_cause_component_class_actor
*cause
= NULL
;
536 int status
= BT_FUNC_STATUS_OK
;
539 BT_ASSERT(self_comp_class
);
540 BT_ASSERT(file_name
);
542 BT_LIB_LOGD("Appending error cause from component class actor: "
543 "%![comp-cls-]+C", self_comp_class
);
544 cause
= create_error_cause_component_class_actor(
545 (void *) self_comp_class
, file_name
, line_no
);
547 /* create_error_cause_component_class_actor() logs errors */
548 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
552 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
553 g_ptr_array_add(error
->causes
, cause
);
554 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
561 int bt_error_append_cause_from_message_iterator(
562 struct bt_error
*error
, bt_self_message_iterator
*self_iter
,
563 const char *file_name
, uint64_t line_no
,
564 const char *msg_fmt
, va_list args
)
566 struct bt_error_cause_message_iterator_actor
*cause
= NULL
;
567 int status
= BT_FUNC_STATUS_OK
;
570 BT_ASSERT(self_iter
);
571 BT_ASSERT(file_name
);
573 BT_LIB_LOGD("Appending error cause from message iterator actor: "
574 "%![comp-]+i", self_iter
);
575 cause
= create_error_cause_message_iterator_actor(
576 (void *) self_iter
, file_name
, line_no
);
578 /* create_error_cause_message_iterator_actor() logs errors */
579 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
583 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
584 g_ptr_array_add(error
->causes
, cause
);
585 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
593 uint64_t error_cause_count(const bt_error
*error
)
595 return error
->causes
? error
->causes
->len
: 0;
599 uint64_t bt_error_get_cause_count(const bt_error
*error
)
601 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
602 return error_cause_count(error
);
606 void bt_error_release(const struct bt_error
*error
)
608 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
609 bt_error_destroy((void *) error
);
613 const struct bt_error_cause
*bt_error_borrow_cause_by_index(
614 const bt_error
*error
, uint64_t index
)
616 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
617 BT_ASSERT_PRE_VALID_INDEX(index
, error_cause_count(error
));
618 return error
->causes
->pdata
[index
];
622 enum bt_error_cause_actor_type
bt_error_cause_get_actor_type(
623 const struct bt_error_cause
*cause
)
625 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
626 return cause
->actor_type
;
630 const char *bt_error_cause_get_message(const struct bt_error_cause
*cause
)
632 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
633 return cause
->message
->str
;
637 const char *bt_error_cause_get_module_name(const struct bt_error_cause
*cause
)
639 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
640 return cause
->module_name
->str
;
644 const char *bt_error_cause_get_file_name(const struct bt_error_cause
*cause
)
646 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
647 return cause
->file_name
->str
;
651 uint64_t bt_error_cause_get_line_number(const bt_error_cause
*cause
)
653 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
654 return cause
->line_no
;
658 const char *bt_error_cause_component_actor_get_component_name(
659 const struct bt_error_cause
*cause
)
661 const struct bt_error_cause_component_actor
*spec_cause
=
662 (const void *) cause
;
664 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
665 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
666 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
667 return spec_cause
->comp_name
->str
;
671 bt_component_class_type
bt_error_cause_component_actor_get_component_class_type(
672 const struct bt_error_cause
*cause
)
674 const struct bt_error_cause_component_actor
*spec_cause
=
675 (const void *) cause
;
677 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
678 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
679 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
680 return spec_cause
->comp_class_id
.type
;
684 const char *bt_error_cause_component_actor_get_component_class_name(
685 const struct bt_error_cause
*cause
)
687 const struct bt_error_cause_component_actor
*spec_cause
=
688 (const void *) cause
;
690 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
691 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
692 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
693 return spec_cause
->comp_class_id
.name
->str
;
697 const char *bt_error_cause_component_actor_get_plugin_name(
698 const struct bt_error_cause
*cause
)
700 const struct bt_error_cause_component_actor
*spec_cause
=
701 (const void *) cause
;
703 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
704 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
705 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
706 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
707 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
711 bt_component_class_type
712 bt_error_cause_component_class_actor_get_component_class_type(
713 const struct bt_error_cause
*cause
)
715 const struct bt_error_cause_component_class_actor
*spec_cause
=
716 (const void *) cause
;
718 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
719 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
720 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
721 return spec_cause
->comp_class_id
.type
;
725 const char *bt_error_cause_component_class_actor_get_component_class_name(
726 const struct bt_error_cause
*cause
)
728 const struct bt_error_cause_component_class_actor
*spec_cause
=
729 (const void *) cause
;
731 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
732 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
733 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
734 return spec_cause
->comp_class_id
.name
->str
;
738 const char *bt_error_cause_component_class_actor_get_plugin_name(
739 const struct bt_error_cause
*cause
)
741 const struct bt_error_cause_component_class_actor
*spec_cause
=
742 (const void *) cause
;
744 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
745 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
746 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
747 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
748 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
752 const char *bt_error_cause_message_iterator_actor_get_component_name(
753 const struct bt_error_cause
*cause
)
755 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
756 (const void *) cause
;
758 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
759 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
760 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
761 return spec_cause
->comp_name
->str
;
766 bt_error_cause_message_iterator_actor_get_component_output_port_name(
767 const struct bt_error_cause
*cause
)
769 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
770 (const void *) cause
;
772 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
773 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
774 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
775 return spec_cause
->output_port_name
->str
;
779 bt_component_class_type
780 bt_error_cause_message_iterator_actor_get_component_class_type(
781 const struct bt_error_cause
*cause
)
783 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
784 (const void *) cause
;
786 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
787 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
788 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
789 return spec_cause
->comp_class_id
.type
;
793 const char *bt_error_cause_message_iterator_actor_get_component_class_name(
794 const struct bt_error_cause
*cause
)
796 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
797 (const void *) cause
;
799 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
800 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
801 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
802 return spec_cause
->comp_class_id
.name
->str
;
806 const char *bt_error_cause_message_iterator_actor_get_plugin_name(
807 const struct bt_error_cause
*cause
)
809 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
810 (const void *) cause
;
812 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
813 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
814 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
815 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
816 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;