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/message/iterator.h"
16 #include "graph/component.h"
17 #include "graph/component-class.h"
18 #include "common/assert.h"
19 #include "lib/assert-cond.h"
20 #include "lib/func-status.h"
22 #define BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(_cause, _exp_type_name, _exp_type) \
23 BT_ASSERT_PRE("error-cause-has-" _exp_type_name "-actor", \
24 ((const struct bt_error_cause *) (_cause))->actor_type == _exp_type, \
25 "Unexpected error cause's actor type: type=%s, exp-type=%s", \
26 bt_error_cause_actor_type_string(((const struct bt_error_cause *) (_cause))->actor_type), \
27 bt_error_cause_actor_type_string(_exp_type))
30 void fini_component_class_id(
31 struct bt_error_cause_component_class_id
*comp_class_id
)
33 BT_ASSERT(comp_class_id
);
35 if (comp_class_id
->name
) {
36 g_string_free(comp_class_id
->name
, TRUE
);
37 comp_class_id
->name
= NULL
;
40 if (comp_class_id
->plugin_name
) {
41 g_string_free(comp_class_id
->plugin_name
, TRUE
);
42 comp_class_id
->plugin_name
= NULL
;
47 void fini_error_cause(struct bt_error_cause
*cause
)
50 BT_LIB_LOGD("Finalizing error cause: %!+r", cause
);
52 if (cause
->module_name
) {
53 g_string_free(cause
->module_name
, TRUE
);
54 cause
->module_name
= NULL
;
57 if (cause
->file_name
) {
58 g_string_free(cause
->file_name
, TRUE
);
59 cause
->file_name
= NULL
;
63 g_string_free(cause
->message
, TRUE
);
64 cause
->message
= NULL
;
69 void destroy_error_cause(struct bt_error_cause
*cause
)
75 BT_LIB_LOGD("Destroying error cause: %!+r", cause
);
77 switch (cause
->actor_type
) {
78 case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
:
80 struct bt_error_cause_component_actor
*spec_cause
=
83 if (spec_cause
->comp_name
) {
84 g_string_free(spec_cause
->comp_name
, TRUE
);
85 spec_cause
->comp_name
= NULL
;
88 fini_component_class_id(&spec_cause
->comp_class_id
);
91 case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
:
93 struct bt_error_cause_component_class_actor
*spec_cause
=
96 fini_component_class_id(&spec_cause
->comp_class_id
);
99 case BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
:
101 struct bt_error_cause_message_iterator_actor
*spec_cause
=
104 if (spec_cause
->comp_name
) {
105 g_string_free(spec_cause
->comp_name
, TRUE
);
106 spec_cause
->comp_name
= NULL
;
109 if (spec_cause
->output_port_name
) {
110 g_string_free(spec_cause
->output_port_name
, TRUE
);
111 spec_cause
->output_port_name
= NULL
;
114 fini_component_class_id(&spec_cause
->comp_class_id
);
121 fini_error_cause(cause
);
129 int init_error_cause(struct bt_error_cause
*cause
,
130 enum bt_error_cause_actor_type actor_type
)
135 BT_LIB_LOGD("Initializing error cause: %!+r", cause
);
136 cause
->actor_type
= actor_type
;
137 cause
->module_name
= g_string_new(NULL
);
138 if (!cause
->module_name
) {
139 BT_LOGE_STR("Failed to allocate one GString.");
144 cause
->message
= g_string_new(NULL
);
145 if (!cause
->message
) {
146 BT_LOGE_STR("Failed to allocate one GString.");
151 cause
->file_name
= g_string_new(NULL
);
152 if (!cause
->file_name
) {
153 BT_LOGE_STR("Failed to allocate one GString.");
163 int init_component_class_id(
164 struct bt_error_cause_component_class_id
*comp_class_id
,
165 struct bt_component_class
*comp_cls
)
169 BT_ASSERT(comp_class_id
);
170 comp_class_id
->type
= comp_cls
->type
;
171 comp_class_id
->name
= g_string_new(comp_cls
->name
->str
);
172 if (!comp_class_id
->name
) {
173 BT_LOGE_STR("Failed to allocate one GString.");
178 comp_class_id
->plugin_name
= g_string_new(comp_cls
->plugin_name
->str
);
179 if (!comp_class_id
->plugin_name
) {
180 BT_LOGE_STR("Failed to allocate one GString.");
190 void set_error_cause_props(struct bt_error_cause
*cause
,
191 const char *file_name
, uint64_t line_no
)
194 g_string_assign(cause
->file_name
, file_name
);
195 cause
->line_no
= line_no
;
199 struct bt_error_cause
*create_error_cause(const char *module_name
,
200 const char *file_name
, uint64_t line_no
)
202 struct bt_error_cause
*cause
= g_new0(struct bt_error_cause
, 1);
205 BT_LOGD_STR("Creating error cause (unknown actor).");
208 BT_LOGE_STR("Failed to allocate one error cause.");
212 ret
= init_error_cause(cause
, BT_ERROR_CAUSE_ACTOR_TYPE_UNKNOWN
);
217 g_string_assign(cause
->module_name
, module_name
);
218 set_error_cause_props(cause
, file_name
, line_no
);
219 BT_LIB_LOGD("Created error cause: %!+r", cause
);
223 destroy_error_cause(cause
);
231 void append_component_class_id_str(GString
*str
,
232 struct bt_error_cause_component_class_id
*comp_class_id
)
234 const char *type_str
= NULL
;
236 switch (comp_class_id
->type
) {
237 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
240 case BT_COMPONENT_CLASS_TYPE_FILTER
:
243 case BT_COMPONENT_CLASS_TYPE_SINK
:
250 if (comp_class_id
->plugin_name
->len
> 0) {
251 g_string_append_printf(str
, "%s.%s.%s",
252 type_str
, comp_class_id
->plugin_name
->str
,
253 comp_class_id
->name
->str
);
255 g_string_append_printf(str
, "%s.%s",
256 type_str
, comp_class_id
->name
->str
);
261 struct bt_error_cause_component_actor
*create_error_cause_component_actor(
262 struct bt_component
*comp
, const char *file_name
,
265 struct bt_error_cause_component_actor
*cause
=
266 g_new0(struct bt_error_cause_component_actor
, 1);
269 BT_LOGD_STR("Creating error cause object (component actor).");
275 ret
= init_error_cause(&cause
->base
,
276 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
281 set_error_cause_props(&cause
->base
, file_name
, line_no
);
282 cause
->comp_name
= g_string_new(comp
->name
->str
);
283 if (!cause
->comp_name
) {
284 BT_LOGE_STR("Failed to allocate one GString.");
288 ret
= init_component_class_id(&cause
->comp_class_id
, comp
->class);
293 g_string_append_printf(cause
->base
.module_name
, "%s: ",
295 append_component_class_id_str(cause
->base
.module_name
,
296 &cause
->comp_class_id
);
297 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
302 destroy_error_cause(&cause
->base
);
311 struct bt_error_cause_component_class_actor
*
312 create_error_cause_component_class_actor(struct bt_component_class
*comp_cls
,
313 const char *file_name
, uint64_t line_no
)
315 struct bt_error_cause_component_class_actor
*cause
=
316 g_new0(struct bt_error_cause_component_class_actor
, 1);
319 BT_LOGD_STR("Creating error cause object (component class actor).");
322 BT_LOGE_STR("Failed to allocate one error cause object.");
326 ret
= init_error_cause(&cause
->base
,
327 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
332 set_error_cause_props(&cause
->base
, file_name
, line_no
);
333 ret
= init_component_class_id(&cause
->comp_class_id
, comp_cls
);
338 append_component_class_id_str(cause
->base
.module_name
,
339 &cause
->comp_class_id
);
340 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
345 destroy_error_cause(&cause
->base
);
354 struct bt_error_cause_message_iterator_actor
*
355 create_error_cause_message_iterator_actor(struct bt_message_iterator
*iter
,
356 const char *file_name
, uint64_t line_no
)
358 struct bt_error_cause_message_iterator_actor
*cause
;
359 struct bt_message_iterator
*input_port_iter
;
362 BT_LOGD_STR("Creating error cause object (message iterator actor).");
365 * This can only be created from within a graph, from a user
366 * message iterator, which is a self component port input
369 input_port_iter
= (void *) iter
;
370 cause
= g_new0(struct bt_error_cause_message_iterator_actor
, 1);
372 BT_LOGE_STR("Failed to allocate one error cause object.");
376 ret
= init_error_cause(&cause
->base
,
377 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
382 set_error_cause_props(&cause
->base
, file_name
, line_no
);
383 cause
->comp_name
= g_string_new(
384 input_port_iter
->upstream_component
->name
->str
);
385 if (!cause
->comp_name
) {
386 BT_LOGE_STR("Failed to allocate one GString.");
390 cause
->output_port_name
= g_string_new(
391 input_port_iter
->upstream_port
->name
->str
);
392 if (!cause
->output_port_name
) {
393 BT_LOGE_STR("Failed to allocate one GString.");
397 ret
= init_component_class_id(&cause
->comp_class_id
,
398 input_port_iter
->upstream_component
->class);
403 g_string_append_printf(cause
->base
.module_name
, "%s (%s): ",
404 input_port_iter
->upstream_component
->name
->str
,
405 input_port_iter
->upstream_port
->name
->str
);
406 append_component_class_id_str(cause
->base
.module_name
,
407 &cause
->comp_class_id
);
408 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
413 destroy_error_cause(&cause
->base
);
421 struct bt_error
*bt_error_create(void)
423 struct bt_error
*error
;
425 BT_LOGD_STR("Creating error object.");
426 error
= g_new0(struct bt_error
, 1);
428 BT_LOGE_STR("Failed to allocate one error object.");
432 error
->causes
= g_ptr_array_new_with_free_func(
433 (GDestroyNotify
) destroy_error_cause
);
434 if (!error
->causes
) {
435 BT_LOGE_STR("Failed to allocate one GPtrArray.");
439 BT_LOGD("Created error object: addr=%p", error
);
443 bt_error_destroy(error
);
450 void bt_error_destroy(struct bt_error
*error
)
457 g_ptr_array_free(error
->causes
, TRUE
);
458 error
->causes
= NULL
;
467 int bt_error_append_cause_from_unknown(struct bt_error
*error
,
468 const char *module_name
, const char *file_name
,
469 uint64_t line_no
, const char *msg_fmt
, va_list args
)
471 struct bt_error_cause
*cause
= NULL
;
472 int status
= BT_FUNC_STATUS_OK
;
475 BT_ASSERT(module_name
);
476 BT_ASSERT(file_name
);
478 BT_LOGD("Appending error cause from unknown actor: "
479 "module-name=\"%s\", func-name=\"%s\", line-no=%" PRIu64
,
480 module_name
, file_name
, line_no
);
481 cause
= create_error_cause(module_name
, file_name
, line_no
);
483 /* create_error_cause() logs errors */
484 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
488 g_string_append_vprintf(cause
->message
, msg_fmt
, args
);
489 g_ptr_array_add(error
->causes
, cause
);
490 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
497 int bt_error_append_cause_from_component(
498 struct bt_error
*error
, bt_self_component
*self_comp
,
499 const char *file_name
, uint64_t line_no
,
500 const char *msg_fmt
, va_list args
)
502 struct bt_error_cause_component_actor
*cause
= NULL
;
503 int status
= BT_FUNC_STATUS_OK
;
506 BT_ASSERT(self_comp
);
507 BT_ASSERT(file_name
);
509 BT_LIB_LOGD("Appending error cause from component actor: %![comp-]+c",
511 cause
= create_error_cause_component_actor((void *) self_comp
,
514 /* create_error_cause_component_actor() logs errors */
515 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
519 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
520 g_ptr_array_add(error
->causes
, cause
);
521 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
528 int bt_error_append_cause_from_component_class(
529 struct bt_error
*error
,
530 bt_self_component_class
*self_comp_class
,
531 const char *file_name
, uint64_t line_no
,
532 const char *msg_fmt
, va_list args
)
534 struct bt_error_cause_component_class_actor
*cause
= NULL
;
535 int status
= BT_FUNC_STATUS_OK
;
538 BT_ASSERT(self_comp_class
);
539 BT_ASSERT(file_name
);
541 BT_LIB_LOGD("Appending error cause from component class actor: "
542 "%![comp-cls-]+C", self_comp_class
);
543 cause
= create_error_cause_component_class_actor(
544 (void *) self_comp_class
, file_name
, line_no
);
546 /* create_error_cause_component_class_actor() logs errors */
547 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
551 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
552 g_ptr_array_add(error
->causes
, cause
);
553 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
560 int bt_error_append_cause_from_message_iterator(
561 struct bt_error
*error
, bt_self_message_iterator
*self_iter
,
562 const char *file_name
, uint64_t line_no
,
563 const char *msg_fmt
, va_list args
)
565 struct bt_error_cause_message_iterator_actor
*cause
= NULL
;
566 int status
= BT_FUNC_STATUS_OK
;
569 BT_ASSERT(self_iter
);
570 BT_ASSERT(file_name
);
572 BT_LIB_LOGD("Appending error cause from message iterator actor: "
573 "%![comp-]+i", self_iter
);
574 cause
= create_error_cause_message_iterator_actor(
575 (void *) self_iter
, file_name
, line_no
);
577 /* create_error_cause_message_iterator_actor() logs errors */
578 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
582 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
583 g_ptr_array_add(error
->causes
, cause
);
584 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
592 uint64_t error_cause_count(const bt_error
*error
)
594 return error
->causes
? error
->causes
->len
: 0;
598 uint64_t bt_error_get_cause_count(const bt_error
*error
)
600 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
601 return error_cause_count(error
);
605 void bt_error_release(const struct bt_error
*error
)
607 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
608 bt_error_destroy((void *) error
);
612 const struct bt_error_cause
*bt_error_borrow_cause_by_index(
613 const bt_error
*error
, uint64_t index
)
615 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
616 BT_ASSERT_PRE_VALID_INDEX(index
, error_cause_count(error
));
617 return error
->causes
->pdata
[index
];
621 enum bt_error_cause_actor_type
bt_error_cause_get_actor_type(
622 const struct bt_error_cause
*cause
)
624 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
625 return cause
->actor_type
;
629 const char *bt_error_cause_get_message(const struct bt_error_cause
*cause
)
631 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
632 return cause
->message
->str
;
636 const char *bt_error_cause_get_module_name(const struct bt_error_cause
*cause
)
638 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
639 return cause
->module_name
->str
;
643 const char *bt_error_cause_get_file_name(const struct bt_error_cause
*cause
)
645 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
646 return cause
->file_name
->str
;
650 uint64_t bt_error_cause_get_line_number(const bt_error_cause
*cause
)
652 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
653 return cause
->line_no
;
657 const char *bt_error_cause_component_actor_get_component_name(
658 const struct bt_error_cause
*cause
)
660 const struct bt_error_cause_component_actor
*spec_cause
=
661 (const void *) cause
;
663 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
664 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
665 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
666 return spec_cause
->comp_name
->str
;
670 bt_component_class_type
bt_error_cause_component_actor_get_component_class_type(
671 const struct bt_error_cause
*cause
)
673 const struct bt_error_cause_component_actor
*spec_cause
=
674 (const void *) cause
;
676 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
677 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
678 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
679 return spec_cause
->comp_class_id
.type
;
683 const char *bt_error_cause_component_actor_get_component_class_name(
684 const struct bt_error_cause
*cause
)
686 const struct bt_error_cause_component_actor
*spec_cause
=
687 (const void *) cause
;
689 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
690 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
691 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
692 return spec_cause
->comp_class_id
.name
->str
;
696 const char *bt_error_cause_component_actor_get_plugin_name(
697 const struct bt_error_cause
*cause
)
699 const struct bt_error_cause_component_actor
*spec_cause
=
700 (const void *) cause
;
702 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
703 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
704 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
705 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
706 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
710 bt_component_class_type
711 bt_error_cause_component_class_actor_get_component_class_type(
712 const struct bt_error_cause
*cause
)
714 const struct bt_error_cause_component_class_actor
*spec_cause
=
715 (const void *) cause
;
717 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
718 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
719 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
720 return spec_cause
->comp_class_id
.type
;
724 const char *bt_error_cause_component_class_actor_get_component_class_name(
725 const struct bt_error_cause
*cause
)
727 const struct bt_error_cause_component_class_actor
*spec_cause
=
728 (const void *) cause
;
730 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
731 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
732 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
733 return spec_cause
->comp_class_id
.name
->str
;
737 const char *bt_error_cause_component_class_actor_get_plugin_name(
738 const struct bt_error_cause
*cause
)
740 const struct bt_error_cause_component_class_actor
*spec_cause
=
741 (const void *) cause
;
743 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
744 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
745 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
746 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
747 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
751 const char *bt_error_cause_message_iterator_actor_get_component_name(
752 const struct bt_error_cause
*cause
)
754 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
755 (const void *) cause
;
757 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
758 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
759 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
760 return spec_cause
->comp_name
->str
;
765 bt_error_cause_message_iterator_actor_get_component_output_port_name(
766 const struct bt_error_cause
*cause
)
768 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
769 (const void *) cause
;
771 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
772 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
773 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
774 return spec_cause
->output_port_name
->str
;
778 bt_component_class_type
779 bt_error_cause_message_iterator_actor_get_component_class_type(
780 const struct bt_error_cause
*cause
)
782 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
783 (const void *) cause
;
785 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
786 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
787 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
788 return spec_cause
->comp_class_id
.type
;
792 const char *bt_error_cause_message_iterator_actor_get_component_class_name(
793 const struct bt_error_cause
*cause
)
795 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
796 (const void *) cause
;
798 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
799 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
800 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
801 return spec_cause
->comp_class_id
.name
->str
;
805 const char *bt_error_cause_message_iterator_actor_get_plugin_name(
806 const struct bt_error_cause
*cause
)
808 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
809 (const void *) cause
;
811 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
812 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
813 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
814 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
815 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;