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
);
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
);
452 void bt_error_destroy(struct bt_error
*error
)
459 g_ptr_array_free(error
->causes
, TRUE
);
460 error
->causes
= NULL
;
470 int bt_error_append_cause_from_unknown(struct bt_error
*error
,
471 const char *module_name
, const char *file_name
,
472 uint64_t line_no
, const char *msg_fmt
, va_list args
)
474 struct bt_error_cause
*cause
= NULL
;
475 int status
= BT_FUNC_STATUS_OK
;
478 BT_ASSERT(module_name
);
479 BT_ASSERT(file_name
);
481 BT_LOGD("Appending error cause from unknown actor: "
482 "module-name=\"%s\", func-name=\"%s\", line-no=%" PRIu64
,
483 module_name
, file_name
, line_no
);
484 cause
= create_error_cause(module_name
, file_name
, line_no
);
486 /* create_error_cause() logs errors */
487 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
491 g_string_append_vprintf(cause
->message
, msg_fmt
, args
);
492 g_ptr_array_add(error
->causes
, cause
);
493 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
497 destroy_error_cause(cause
);
502 int bt_error_append_cause_from_component(
503 struct bt_error
*error
, bt_self_component
*self_comp
,
504 const char *file_name
, uint64_t line_no
,
505 const char *msg_fmt
, va_list args
)
507 struct bt_error_cause_component_actor
*cause
= NULL
;
508 int status
= BT_FUNC_STATUS_OK
;
511 BT_ASSERT(self_comp
);
512 BT_ASSERT(file_name
);
514 BT_LIB_LOGD("Appending error cause from component actor: %![comp-]+c",
516 cause
= create_error_cause_component_actor((void *) self_comp
,
519 /* create_error_cause_component_actor() logs errors */
520 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
524 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
525 g_ptr_array_add(error
->causes
, cause
);
526 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
531 destroy_error_cause(&cause
->base
);
538 int bt_error_append_cause_from_component_class(
539 struct bt_error
*error
,
540 bt_self_component_class
*self_comp_class
,
541 const char *file_name
, uint64_t line_no
,
542 const char *msg_fmt
, va_list args
)
544 struct bt_error_cause_component_class_actor
*cause
= NULL
;
545 int status
= BT_FUNC_STATUS_OK
;
548 BT_ASSERT(self_comp_class
);
549 BT_ASSERT(file_name
);
551 BT_LIB_LOGD("Appending error cause from component class actor: "
552 "%![comp-cls-]+C", self_comp_class
);
553 cause
= create_error_cause_component_class_actor(
554 (void *) self_comp_class
, file_name
, line_no
);
556 /* create_error_cause_component_class_actor() logs errors */
557 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
561 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
562 g_ptr_array_add(error
->causes
, cause
);
563 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
568 destroy_error_cause(&cause
->base
);
575 int bt_error_append_cause_from_message_iterator(
576 struct bt_error
*error
, bt_self_message_iterator
*self_iter
,
577 const char *file_name
, uint64_t line_no
,
578 const char *msg_fmt
, va_list args
)
580 struct bt_error_cause_message_iterator_actor
*cause
= NULL
;
581 int status
= BT_FUNC_STATUS_OK
;
584 BT_ASSERT(self_iter
);
585 BT_ASSERT(file_name
);
587 BT_LIB_LOGD("Appending error cause from message iterator actor: "
588 "%![comp-]+i", self_iter
);
589 cause
= create_error_cause_message_iterator_actor(
590 (void *) self_iter
, file_name
, line_no
);
592 /* create_error_cause_message_iterator_actor() logs errors */
593 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
597 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
598 g_ptr_array_add(error
->causes
, cause
);
599 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
604 destroy_error_cause(&cause
->base
);
611 uint64_t error_cause_count(const bt_error
*error
)
613 return error
->causes
? error
->causes
->len
: 0;
616 uint64_t bt_error_get_cause_count(const bt_error
*error
)
618 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
619 return error_cause_count(error
);
622 void bt_error_release(const struct bt_error
*error
)
624 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
625 bt_error_destroy((void *) error
);
628 const struct bt_error_cause
*bt_error_borrow_cause_by_index(
629 const bt_error
*error
, uint64_t index
)
631 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
632 BT_ASSERT_PRE_VALID_INDEX(index
, error_cause_count(error
));
633 return error
->causes
->pdata
[index
];
636 enum bt_error_cause_actor_type
bt_error_cause_get_actor_type(
637 const struct bt_error_cause
*cause
)
639 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
640 return cause
->actor_type
;
643 const char *bt_error_cause_get_message(const struct bt_error_cause
*cause
)
645 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
646 return cause
->message
->str
;
649 const char *bt_error_cause_get_module_name(const struct bt_error_cause
*cause
)
651 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
652 return cause
->module_name
->str
;
655 const char *bt_error_cause_get_file_name(const struct bt_error_cause
*cause
)
657 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
658 return cause
->file_name
->str
;
661 uint64_t bt_error_cause_get_line_number(const bt_error_cause
*cause
)
663 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
664 return cause
->line_no
;
667 const char *bt_error_cause_component_actor_get_component_name(
668 const struct bt_error_cause
*cause
)
670 const struct bt_error_cause_component_actor
*spec_cause
=
671 (const void *) cause
;
673 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
674 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
675 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
676 return spec_cause
->comp_name
->str
;
679 bt_component_class_type
bt_error_cause_component_actor_get_component_class_type(
680 const struct bt_error_cause
*cause
)
682 const struct bt_error_cause_component_actor
*spec_cause
=
683 (const void *) cause
;
685 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
686 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
687 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
688 return spec_cause
->comp_class_id
.type
;
691 const char *bt_error_cause_component_actor_get_component_class_name(
692 const struct bt_error_cause
*cause
)
694 const struct bt_error_cause_component_actor
*spec_cause
=
695 (const void *) cause
;
697 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
698 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
699 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
700 return spec_cause
->comp_class_id
.name
->str
;
703 const char *bt_error_cause_component_actor_get_plugin_name(
704 const struct bt_error_cause
*cause
)
706 const struct bt_error_cause_component_actor
*spec_cause
=
707 (const void *) cause
;
709 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
710 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
711 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
712 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
713 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
716 bt_component_class_type
717 bt_error_cause_component_class_actor_get_component_class_type(
718 const struct bt_error_cause
*cause
)
720 const struct bt_error_cause_component_class_actor
*spec_cause
=
721 (const void *) cause
;
723 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
724 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
725 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
726 return spec_cause
->comp_class_id
.type
;
729 const char *bt_error_cause_component_class_actor_get_component_class_name(
730 const struct bt_error_cause
*cause
)
732 const struct bt_error_cause_component_class_actor
*spec_cause
=
733 (const void *) cause
;
735 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
736 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
737 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
738 return spec_cause
->comp_class_id
.name
->str
;
741 const char *bt_error_cause_component_class_actor_get_plugin_name(
742 const struct bt_error_cause
*cause
)
744 const struct bt_error_cause_component_class_actor
*spec_cause
=
745 (const void *) cause
;
747 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
748 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
749 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
750 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
751 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
754 const char *bt_error_cause_message_iterator_actor_get_component_name(
755 const struct bt_error_cause
*cause
)
757 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
758 (const void *) cause
;
760 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
761 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
762 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
763 return spec_cause
->comp_name
->str
;
767 bt_error_cause_message_iterator_actor_get_component_output_port_name(
768 const struct bt_error_cause
*cause
)
770 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
771 (const void *) cause
;
773 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
774 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
775 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
776 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
;
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
;
804 const char *bt_error_cause_message_iterator_actor_get_plugin_name(
805 const struct bt_error_cause
*cause
)
807 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
808 (const void *) cause
;
810 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
811 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
812 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
813 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
814 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;