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.");
158 BT_LIB_LOGD("Initialized error cause: %!+r", cause
);
165 int init_component_class_id(
166 struct bt_error_cause_component_class_id
*comp_class_id
,
167 struct bt_component_class
*comp_cls
)
171 BT_ASSERT(comp_class_id
);
172 comp_class_id
->type
= comp_cls
->type
;
173 comp_class_id
->name
= g_string_new(comp_cls
->name
->str
);
174 if (!comp_class_id
->name
) {
175 BT_LOGE_STR("Failed to allocate one GString.");
180 comp_class_id
->plugin_name
= g_string_new(comp_cls
->plugin_name
->str
);
181 if (!comp_class_id
->plugin_name
) {
182 BT_LOGE_STR("Failed to allocate one GString.");
192 void set_error_cause_props(struct bt_error_cause
*cause
,
193 const char *file_name
, uint64_t line_no
)
196 g_string_assign(cause
->file_name
, file_name
);
197 cause
->line_no
= line_no
;
201 struct bt_error_cause
*create_error_cause(const char *module_name
,
202 const char *file_name
, uint64_t line_no
)
204 struct bt_error_cause
*cause
= g_new0(struct bt_error_cause
, 1);
207 BT_LOGD_STR("Creating error cause (unknown actor).");
210 BT_LOGE_STR("Failed to allocate one error cause.");
214 ret
= init_error_cause(cause
, BT_ERROR_CAUSE_ACTOR_TYPE_UNKNOWN
);
219 g_string_assign(cause
->module_name
, module_name
);
220 set_error_cause_props(cause
, file_name
, line_no
);
221 BT_LIB_LOGD("Created error cause: %!+r", cause
);
225 destroy_error_cause(cause
);
233 void append_component_class_id_str(GString
*str
,
234 struct bt_error_cause_component_class_id
*comp_class_id
)
236 const char *type_str
= NULL
;
238 switch (comp_class_id
->type
) {
239 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
242 case BT_COMPONENT_CLASS_TYPE_FILTER
:
245 case BT_COMPONENT_CLASS_TYPE_SINK
:
252 if (comp_class_id
->plugin_name
->len
> 0) {
253 g_string_append_printf(str
, "%s.%s.%s",
254 type_str
, comp_class_id
->plugin_name
->str
,
255 comp_class_id
->name
->str
);
257 g_string_append_printf(str
, "%s.%s",
258 type_str
, comp_class_id
->name
->str
);
263 struct bt_error_cause_component_actor
*create_error_cause_component_actor(
264 struct bt_component
*comp
, const char *file_name
,
267 struct bt_error_cause_component_actor
*cause
=
268 g_new0(struct bt_error_cause_component_actor
, 1);
271 BT_LOGD_STR("Creating error cause object (component actor).");
277 ret
= init_error_cause(&cause
->base
,
278 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
283 set_error_cause_props(&cause
->base
, file_name
, line_no
);
284 cause
->comp_name
= g_string_new(comp
->name
->str
);
285 if (!cause
->comp_name
) {
286 BT_LOGE_STR("Failed to allocate one GString.");
290 ret
= init_component_class_id(&cause
->comp_class_id
, comp
->class);
295 g_string_append_printf(cause
->base
.module_name
, "%s: ",
297 append_component_class_id_str(cause
->base
.module_name
,
298 &cause
->comp_class_id
);
299 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
303 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
);
344 destroy_error_cause(&cause
->base
);
352 struct bt_error_cause_message_iterator_actor
*
353 create_error_cause_message_iterator_actor(struct bt_message_iterator
*iter
,
354 const char *file_name
, uint64_t line_no
)
356 struct bt_error_cause_message_iterator_actor
*cause
;
357 struct bt_message_iterator
*input_port_iter
;
360 BT_LOGD_STR("Creating error cause object (message iterator actor).");
363 * This can only be created from within a graph, from a user
364 * message iterator, which is a self component port input
367 input_port_iter
= (void *) iter
;
368 cause
= g_new0(struct bt_error_cause_message_iterator_actor
, 1);
370 BT_LOGE_STR("Failed to allocate one error cause object.");
374 ret
= init_error_cause(&cause
->base
,
375 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
380 set_error_cause_props(&cause
->base
, file_name
, line_no
);
381 cause
->comp_name
= g_string_new(
382 input_port_iter
->upstream_component
->name
->str
);
383 if (!cause
->comp_name
) {
384 BT_LOGE_STR("Failed to allocate one GString.");
388 cause
->output_port_name
= g_string_new(
389 input_port_iter
->upstream_port
->name
->str
);
390 if (!cause
->output_port_name
) {
391 BT_LOGE_STR("Failed to allocate one GString.");
395 ret
= init_component_class_id(&cause
->comp_class_id
,
396 input_port_iter
->upstream_component
->class);
401 g_string_append_printf(cause
->base
.module_name
, "%s (%s): ",
402 input_port_iter
->upstream_component
->name
->str
,
403 input_port_iter
->upstream_port
->name
->str
);
404 append_component_class_id_str(cause
->base
.module_name
,
405 &cause
->comp_class_id
);
406 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
410 destroy_error_cause(&cause
->base
);
418 struct bt_error
*bt_error_create(void)
420 struct bt_error
*error
;
422 BT_LOGD_STR("Creating error object.");
423 error
= g_new0(struct bt_error
, 1);
425 BT_LOGE_STR("Failed to allocate one error object.");
429 error
->causes
= g_ptr_array_new_with_free_func(
430 (GDestroyNotify
) destroy_error_cause
);
431 if (!error
->causes
) {
432 BT_LOGE_STR("Failed to allocate one GPtrArray.");
436 BT_LOGD("Created error object: addr=%p", error
);
440 bt_error_destroy(error
);
448 void bt_error_destroy(struct bt_error
*error
)
455 g_ptr_array_free(error
->causes
, TRUE
);
456 error
->causes
= NULL
;
466 int bt_error_append_cause_from_unknown(struct bt_error
*error
,
467 const char *module_name
, const char *file_name
,
468 uint64_t line_no
, const char *msg_fmt
, va_list args
)
470 struct bt_error_cause
*cause
= NULL
;
471 int status
= BT_FUNC_STATUS_OK
;
474 BT_ASSERT(module_name
);
475 BT_ASSERT(file_name
);
477 BT_LOGD("Appending error cause from unknown actor: "
478 "module-name=\"%s\", func-name=\"%s\", line-no=%" PRIu64
,
479 module_name
, file_name
, line_no
);
480 cause
= create_error_cause(module_name
, file_name
, line_no
);
482 /* create_error_cause() logs errors */
483 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
487 g_string_append_vprintf(cause
->message
, msg_fmt
, args
);
488 g_ptr_array_add(error
->causes
, cause
);
489 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
493 destroy_error_cause(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
);
526 destroy_error_cause(&cause
->base
);
531 int bt_error_append_cause_from_component_class(
532 struct bt_error
*error
,
533 bt_self_component_class
*self_comp_class
,
534 const char *file_name
, uint64_t line_no
,
535 const char *msg_fmt
, va_list args
)
537 struct bt_error_cause_component_class_actor
*cause
= NULL
;
538 int status
= BT_FUNC_STATUS_OK
;
541 BT_ASSERT(self_comp_class
);
542 BT_ASSERT(file_name
);
544 BT_LIB_LOGD("Appending error cause from component class actor: "
545 "%![comp-cls-]+C", self_comp_class
);
546 cause
= create_error_cause_component_class_actor(
547 (void *) self_comp_class
, file_name
, line_no
);
549 /* create_error_cause_component_class_actor() logs errors */
550 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
554 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
555 g_ptr_array_add(error
->causes
, cause
);
556 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
560 destroy_error_cause(&cause
->base
);
565 int bt_error_append_cause_from_message_iterator(
566 struct bt_error
*error
, bt_self_message_iterator
*self_iter
,
567 const char *file_name
, uint64_t line_no
,
568 const char *msg_fmt
, va_list args
)
570 struct bt_error_cause_message_iterator_actor
*cause
= NULL
;
571 int status
= BT_FUNC_STATUS_OK
;
574 BT_ASSERT(self_iter
);
575 BT_ASSERT(file_name
);
577 BT_LIB_LOGD("Appending error cause from message iterator actor: "
578 "%![comp-]+i", self_iter
);
579 cause
= create_error_cause_message_iterator_actor(
580 (void *) self_iter
, file_name
, line_no
);
582 /* create_error_cause_message_iterator_actor() logs errors */
583 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
587 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
588 g_ptr_array_add(error
->causes
, cause
);
589 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
593 destroy_error_cause(&cause
->base
);
598 uint64_t error_cause_count(const bt_error
*error
)
600 return error
->causes
? error
->causes
->len
: 0;
603 uint64_t bt_error_get_cause_count(const bt_error
*error
)
605 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
606 return error_cause_count(error
);
609 void bt_error_release(const struct bt_error
*error
)
611 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
612 bt_error_destroy((void *) error
);
615 const struct bt_error_cause
*bt_error_borrow_cause_by_index(
616 const bt_error
*error
, uint64_t index
)
618 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
619 BT_ASSERT_PRE_VALID_INDEX(index
, error_cause_count(error
));
620 return error
->causes
->pdata
[index
];
623 enum bt_error_cause_actor_type
bt_error_cause_get_actor_type(
624 const struct bt_error_cause
*cause
)
626 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
627 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
;
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
;
642 const char *bt_error_cause_get_file_name(const struct bt_error_cause
*cause
)
644 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
645 return cause
->file_name
->str
;
648 uint64_t bt_error_cause_get_line_number(const bt_error_cause
*cause
)
650 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
651 return cause
->line_no
;
654 const char *bt_error_cause_component_actor_get_component_name(
655 const struct bt_error_cause
*cause
)
657 const struct bt_error_cause_component_actor
*spec_cause
=
658 (const void *) cause
;
660 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
661 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
662 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
663 return spec_cause
->comp_name
->str
;
666 bt_component_class_type
bt_error_cause_component_actor_get_component_class_type(
667 const struct bt_error_cause
*cause
)
669 const struct bt_error_cause_component_actor
*spec_cause
=
670 (const void *) cause
;
672 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
673 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
674 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
675 return spec_cause
->comp_class_id
.type
;
678 const char *bt_error_cause_component_actor_get_component_class_name(
679 const struct bt_error_cause
*cause
)
681 const struct bt_error_cause_component_actor
*spec_cause
=
682 (const void *) cause
;
684 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
685 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
686 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
687 return spec_cause
->comp_class_id
.name
->str
;
690 const char *bt_error_cause_component_actor_get_plugin_name(
691 const struct bt_error_cause
*cause
)
693 const struct bt_error_cause_component_actor
*spec_cause
=
694 (const void *) cause
;
696 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
697 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component",
698 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
699 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
700 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
703 bt_component_class_type
704 bt_error_cause_component_class_actor_get_component_class_type(
705 const struct bt_error_cause
*cause
)
707 const struct bt_error_cause_component_class_actor
*spec_cause
=
708 (const void *) cause
;
710 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
711 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
712 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
713 return spec_cause
->comp_class_id
.type
;
716 const char *bt_error_cause_component_class_actor_get_component_class_name(
717 const struct bt_error_cause
*cause
)
719 const struct bt_error_cause_component_class_actor
*spec_cause
=
720 (const void *) cause
;
722 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
723 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
724 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
725 return spec_cause
->comp_class_id
.name
->str
;
728 const char *bt_error_cause_component_class_actor_get_plugin_name(
729 const struct bt_error_cause
*cause
)
731 const struct bt_error_cause_component_class_actor
*spec_cause
=
732 (const void *) cause
;
734 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
735 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "component-class",
736 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
737 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
738 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
741 const char *bt_error_cause_message_iterator_actor_get_component_name(
742 const struct bt_error_cause
*cause
)
744 const struct bt_error_cause_message_iterator_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
, "message-iterator",
749 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
750 return spec_cause
->comp_name
->str
;
754 bt_error_cause_message_iterator_actor_get_component_output_port_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
->output_port_name
->str
;
766 bt_component_class_type
767 bt_error_cause_message_iterator_actor_get_component_class_type(
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
->comp_class_id
.type
;
779 const char *bt_error_cause_message_iterator_actor_get_component_class_name(
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
.name
->str
;
791 const char *bt_error_cause_message_iterator_actor_get_plugin_name(
792 const struct bt_error_cause
*cause
)
794 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
795 (const void *) cause
;
797 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
798 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
, "message-iterator",
799 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
800 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
801 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;