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) \
23 BT_ASSERT_PRE(((const struct bt_error_cause *) (_cause))->actor_type == _exp_type, \
24 "Unexpected error cause's actor type: type=%s, exp-type=%s", \
25 bt_error_cause_actor_type_string(((const struct bt_error_cause *) (_cause))->actor_type), \
26 bt_error_cause_actor_type_string(_exp_type))
29 void fini_component_class_id(
30 struct bt_error_cause_component_class_id
*comp_class_id
)
32 BT_ASSERT(comp_class_id
);
34 if (comp_class_id
->name
) {
35 g_string_free(comp_class_id
->name
, TRUE
);
36 comp_class_id
->name
= NULL
;
39 if (comp_class_id
->plugin_name
) {
40 g_string_free(comp_class_id
->plugin_name
, TRUE
);
41 comp_class_id
->plugin_name
= NULL
;
46 void fini_error_cause(struct bt_error_cause
*cause
)
49 BT_LIB_LOGD("Finalizing error cause: %!+r", cause
);
51 if (cause
->module_name
) {
52 g_string_free(cause
->module_name
, TRUE
);
53 cause
->module_name
= NULL
;
56 if (cause
->file_name
) {
57 g_string_free(cause
->file_name
, TRUE
);
58 cause
->file_name
= NULL
;
62 g_string_free(cause
->message
, TRUE
);
63 cause
->message
= NULL
;
68 void destroy_error_cause(struct bt_error_cause
*cause
)
74 BT_LIB_LOGD("Destroying error cause: %!+r", cause
);
76 switch (cause
->actor_type
) {
77 case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
:
79 struct bt_error_cause_component_actor
*spec_cause
=
82 if (spec_cause
->comp_name
) {
83 g_string_free(spec_cause
->comp_name
, TRUE
);
84 spec_cause
->comp_name
= NULL
;
87 fini_component_class_id(&spec_cause
->comp_class_id
);
90 case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
:
92 struct bt_error_cause_component_class_actor
*spec_cause
=
95 fini_component_class_id(&spec_cause
->comp_class_id
);
98 case BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
:
100 struct bt_error_cause_message_iterator_actor
*spec_cause
=
103 if (spec_cause
->comp_name
) {
104 g_string_free(spec_cause
->comp_name
, TRUE
);
105 spec_cause
->comp_name
= NULL
;
108 if (spec_cause
->output_port_name
) {
109 g_string_free(spec_cause
->output_port_name
, TRUE
);
110 spec_cause
->output_port_name
= NULL
;
113 fini_component_class_id(&spec_cause
->comp_class_id
);
120 fini_error_cause(cause
);
128 int init_error_cause(struct bt_error_cause
*cause
,
129 enum bt_error_cause_actor_type actor_type
)
134 BT_LIB_LOGD("Initializing error cause: %!+r", cause
);
135 cause
->actor_type
= actor_type
;
136 cause
->module_name
= g_string_new(NULL
);
137 if (!cause
->module_name
) {
138 BT_LOGE_STR("Failed to allocate one GString.");
143 cause
->message
= g_string_new(NULL
);
144 if (!cause
->message
) {
145 BT_LOGE_STR("Failed to allocate one GString.");
150 cause
->file_name
= g_string_new(NULL
);
151 if (!cause
->file_name
) {
152 BT_LOGE_STR("Failed to allocate one GString.");
157 BT_LIB_LOGD("Initialized error cause: %!+r", cause
);
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
);
302 destroy_error_cause(&cause
->base
);
310 struct bt_error_cause_component_class_actor
*
311 create_error_cause_component_class_actor(struct bt_component_class
*comp_cls
,
312 const char *file_name
, uint64_t line_no
)
314 struct bt_error_cause_component_class_actor
*cause
=
315 g_new0(struct bt_error_cause_component_class_actor
, 1);
318 BT_LOGD_STR("Creating error cause object (component class actor).");
321 BT_LOGE_STR("Failed to allocate one error cause object.");
325 ret
= init_error_cause(&cause
->base
,
326 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
331 set_error_cause_props(&cause
->base
, file_name
, line_no
);
332 ret
= init_component_class_id(&cause
->comp_class_id
, comp_cls
);
337 append_component_class_id_str(cause
->base
.module_name
,
338 &cause
->comp_class_id
);
339 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
343 destroy_error_cause(&cause
->base
);
351 struct bt_error_cause_message_iterator_actor
*
352 create_error_cause_message_iterator_actor(struct bt_message_iterator
*iter
,
353 const char *file_name
, uint64_t line_no
)
355 struct bt_error_cause_message_iterator_actor
*cause
;
356 struct bt_message_iterator
*input_port_iter
;
359 BT_LOGD_STR("Creating error cause object (message iterator actor).");
362 * This can only be created from within a graph, from a user
363 * message iterator, which is a self component port input
366 input_port_iter
= (void *) iter
;
367 cause
= g_new0(struct bt_error_cause_message_iterator_actor
, 1);
369 BT_LOGE_STR("Failed to allocate one error cause object.");
373 ret
= init_error_cause(&cause
->base
,
374 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
379 set_error_cause_props(&cause
->base
, file_name
, line_no
);
380 cause
->comp_name
= g_string_new(
381 input_port_iter
->upstream_component
->name
->str
);
382 if (!cause
->comp_name
) {
383 BT_LOGE_STR("Failed to allocate one GString.");
387 cause
->output_port_name
= g_string_new(
388 input_port_iter
->upstream_port
->name
->str
);
389 if (!cause
->output_port_name
) {
390 BT_LOGE_STR("Failed to allocate one GString.");
394 ret
= init_component_class_id(&cause
->comp_class_id
,
395 input_port_iter
->upstream_component
->class);
400 g_string_append_printf(cause
->base
.module_name
, "%s (%s): ",
401 input_port_iter
->upstream_component
->name
->str
,
402 input_port_iter
->upstream_port
->name
->str
);
403 append_component_class_id_str(cause
->base
.module_name
,
404 &cause
->comp_class_id
);
405 BT_LIB_LOGD("Created error cause object: %!+r", cause
);
409 destroy_error_cause(&cause
->base
);
417 struct bt_error
*bt_error_create(void)
419 struct bt_error
*error
;
421 BT_LOGD_STR("Creating error object.");
422 error
= g_new0(struct bt_error
, 1);
424 BT_LOGE_STR("Failed to allocate one error object.");
428 error
->causes
= g_ptr_array_new_with_free_func(
429 (GDestroyNotify
) destroy_error_cause
);
430 if (!error
->causes
) {
431 BT_LOGE_STR("Failed to allocate one GPtrArray.");
435 BT_LOGD("Created error object: addr=%p", error
);
439 bt_error_destroy(error
);
447 void bt_error_destroy(struct bt_error
*error
)
454 g_ptr_array_free(error
->causes
, TRUE
);
455 error
->causes
= NULL
;
465 int bt_error_append_cause_from_unknown(struct bt_error
*error
,
466 const char *module_name
, const char *file_name
,
467 uint64_t line_no
, const char *msg_fmt
, va_list args
)
469 struct bt_error_cause
*cause
= NULL
;
470 int status
= BT_FUNC_STATUS_OK
;
473 BT_ASSERT(module_name
);
474 BT_ASSERT(file_name
);
476 BT_LOGD("Appending error cause from unknown actor: "
477 "module-name=\"%s\", func-name=\"%s\", line-no=%" PRIu64
,
478 module_name
, file_name
, line_no
);
479 cause
= create_error_cause(module_name
, file_name
, line_no
);
481 /* create_error_cause() logs errors */
482 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
486 g_string_append_vprintf(cause
->message
, msg_fmt
, args
);
487 g_ptr_array_add(error
->causes
, cause
);
488 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
492 destroy_error_cause(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
);
525 destroy_error_cause(&cause
->base
);
530 int bt_error_append_cause_from_component_class(
531 struct bt_error
*error
,
532 bt_self_component_class
*self_comp_class
,
533 const char *file_name
, uint64_t line_no
,
534 const char *msg_fmt
, va_list args
)
536 struct bt_error_cause_component_class_actor
*cause
= NULL
;
537 int status
= BT_FUNC_STATUS_OK
;
540 BT_ASSERT(self_comp_class
);
541 BT_ASSERT(file_name
);
543 BT_LIB_LOGD("Appending error cause from component class actor: "
544 "%![comp-cls-]+C", self_comp_class
);
545 cause
= create_error_cause_component_class_actor(
546 (void *) self_comp_class
, file_name
, line_no
);
548 /* create_error_cause_component_class_actor() logs errors */
549 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
553 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
554 g_ptr_array_add(error
->causes
, cause
);
555 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
559 destroy_error_cause(&cause
->base
);
564 int bt_error_append_cause_from_message_iterator(
565 struct bt_error
*error
, bt_self_message_iterator
*self_iter
,
566 const char *file_name
, uint64_t line_no
,
567 const char *msg_fmt
, va_list args
)
569 struct bt_error_cause_message_iterator_actor
*cause
= NULL
;
570 int status
= BT_FUNC_STATUS_OK
;
573 BT_ASSERT(self_iter
);
574 BT_ASSERT(file_name
);
576 BT_LIB_LOGD("Appending error cause from message iterator actor: "
577 "%![comp-]+i", self_iter
);
578 cause
= create_error_cause_message_iterator_actor(
579 (void *) self_iter
, file_name
, line_no
);
581 /* create_error_cause_message_iterator_actor() logs errors */
582 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
586 g_string_append_vprintf(cause
->base
.message
, msg_fmt
, args
);
587 g_ptr_array_add(error
->causes
, cause
);
588 BT_LIB_LOGD("Appended error cause: %!+r", cause
);
592 destroy_error_cause(&cause
->base
);
597 uint64_t error_cause_count(const bt_error
*error
)
599 return error
->causes
? error
->causes
->len
: 0;
602 uint64_t bt_error_get_cause_count(const bt_error
*error
)
604 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
605 return error_cause_count(error
);
608 void bt_error_release(const struct bt_error
*error
)
610 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
611 bt_error_destroy((void *) error
);
614 const struct bt_error_cause
*bt_error_borrow_cause_by_index(
615 const bt_error
*error
, uint64_t index
)
617 BT_ASSERT_PRE_ERROR_NON_NULL(error
);
618 BT_ASSERT_PRE_VALID_INDEX(index
, error_cause_count(error
));
619 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
;
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
;
635 const char *bt_error_cause_get_module_name(const struct bt_error_cause
*cause
)
637 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
638 return cause
->module_name
->str
;
641 const char *bt_error_cause_get_file_name(const struct bt_error_cause
*cause
)
643 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
644 return cause
->file_name
->str
;
647 uint64_t bt_error_cause_get_line_number(const bt_error_cause
*cause
)
649 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
650 return cause
->line_no
;
653 const char *bt_error_cause_component_actor_get_component_name(
654 const struct bt_error_cause
*cause
)
656 const struct bt_error_cause_component_actor
*spec_cause
=
657 (const void *) cause
;
659 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
660 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
661 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
662 return spec_cause
->comp_name
->str
;
665 bt_component_class_type
bt_error_cause_component_actor_get_component_class_type(
666 const struct bt_error_cause
*cause
)
668 const struct bt_error_cause_component_actor
*spec_cause
=
669 (const void *) cause
;
671 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
672 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
673 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
674 return spec_cause
->comp_class_id
.type
;
677 const char *bt_error_cause_component_actor_get_component_class_name(
678 const struct bt_error_cause
*cause
)
680 const struct bt_error_cause_component_actor
*spec_cause
=
681 (const void *) cause
;
683 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
684 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
685 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
686 return spec_cause
->comp_class_id
.name
->str
;
689 const char *bt_error_cause_component_actor_get_plugin_name(
690 const struct bt_error_cause
*cause
)
692 const struct bt_error_cause_component_actor
*spec_cause
=
693 (const void *) cause
;
695 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
696 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
697 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT
);
698 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
699 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
702 bt_component_class_type
703 bt_error_cause_component_class_actor_get_component_class_type(
704 const struct bt_error_cause
*cause
)
706 const struct bt_error_cause_component_class_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
,
711 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
712 return spec_cause
->comp_class_id
.type
;
715 const char *bt_error_cause_component_class_actor_get_component_class_name(
716 const struct bt_error_cause
*cause
)
718 const struct bt_error_cause_component_class_actor
*spec_cause
=
719 (const void *) cause
;
721 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
722 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
723 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
724 return spec_cause
->comp_class_id
.name
->str
;
727 const char *bt_error_cause_component_class_actor_get_plugin_name(
728 const struct bt_error_cause
*cause
)
730 const struct bt_error_cause_component_class_actor
*spec_cause
=
731 (const void *) cause
;
733 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
734 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
735 BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS
);
736 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
737 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;
740 const char *bt_error_cause_message_iterator_actor_get_component_name(
741 const struct bt_error_cause
*cause
)
743 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
744 (const void *) cause
;
746 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
747 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
748 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
749 return spec_cause
->comp_name
->str
;
753 bt_error_cause_message_iterator_actor_get_component_output_port_name(
754 const struct bt_error_cause
*cause
)
756 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
757 (const void *) cause
;
759 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
760 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
761 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
762 return spec_cause
->output_port_name
->str
;
765 bt_component_class_type
766 bt_error_cause_message_iterator_actor_get_component_class_type(
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
,
774 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
775 return spec_cause
->comp_class_id
.type
;
778 const char *bt_error_cause_message_iterator_actor_get_component_class_name(
779 const struct bt_error_cause
*cause
)
781 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
782 (const void *) cause
;
784 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
785 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
786 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
787 return spec_cause
->comp_class_id
.name
->str
;
790 const char *bt_error_cause_message_iterator_actor_get_plugin_name(
791 const struct bt_error_cause
*cause
)
793 const struct bt_error_cause_message_iterator_actor
*spec_cause
=
794 (const void *) cause
;
796 BT_ASSERT_PRE_ERROR_CAUSE_NON_NULL(cause
);
797 BT_ASSERT_PRE_CAUSE_HAS_ACTOR_TYPE(cause
,
798 BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR
);
799 return spec_cause
->comp_class_id
.plugin_name
->len
> 0 ?
800 spec_cause
->comp_class_id
.plugin_name
->str
: NULL
;