X-Git-Url: http://git.liburcu.org/?p=lttng-tools.git;a=blobdiff_plain;f=tests%2Futils%2Fbt2_plugins%2Ffield_stats%2Ffield_stats.cpp;h=dc8894fd8a0b2ac594407d7c64f7480b086f6bc3;hp=0dc59fcacd35323ad7bdffd1aa13371627ca9728;hb=d73aeddd1b4de7fadc7b6f6f5004c6298208602a;hpb=74021af62434d042d27e010d62d6b6a0717f246b diff --git a/tests/utils/bt2_plugins/field_stats/field_stats.cpp b/tests/utils/bt2_plugins/field_stats/field_stats.cpp index 0dc59fcac..dc8894fd8 100644 --- a/tests/utils/bt2_plugins/field_stats/field_stats.cpp +++ b/tests/utils/bt2_plugins/field_stats/field_stats.cpp @@ -6,447 +6,450 @@ */ #include "../fmt.hpp" +#include "../utils.hpp" #include "field_stats.hpp" +#include +#include + #include #include +#include #include +#include #include #include -struct field_stats { - bt_message_iterator *iterator; - bt_value *stats_value; - const bt_event_class *event_class; -}; - -bt_component_class_initialize_method_status -field_stats_initialize(bt_self_component_sink *self_component_sink, - bt_self_component_sink_configuration *, - const bt_value *, - void *) -{ - bt_component_class_initialize_method_status status; - struct field_stats *field_stats = nullptr; - - if (bt_self_component_sink_add_input_port(self_component_sink, "in", nullptr, nullptr) != - BT_SELF_COMPONENT_ADD_PORT_STATUS_OK) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "Failed to add input port"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto error; +class bad_alloc_with_msg : public std::bad_alloc { +public: + explicit bad_alloc_with_msg(const std::string& msg) : _msg(msg) + { } - field_stats = (struct field_stats *) malloc(sizeof(*field_stats)); - if (field_stats == nullptr) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "Failed to allocate memory for private data"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; - goto error; + virtual const char *what() const noexcept override + { + return _msg.c_str(); } - field_stats->iterator = nullptr; - field_stats->stats_value = bt_value_map_create(); - field_stats->event_class = nullptr; - if (field_stats->stats_value == nullptr) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "Failed to allocate memory for field_stats.stats map"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto error; +private: + std::string _msg; +}; + +struct field_stats { +public: + field_stats() : stats_value{ lttng::bt2::make_value_ref(bt_value_map_create()) } + { + if (!stats_value) { + throw bad_alloc_with_msg( + "Failed to allocate memory for field_stats.stats map"); + } } - bt_self_component_set_data(bt_self_component_sink_as_self_component(self_component_sink), - field_stats); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; - goto end; -error: - if (field_stats) { - free(field_stats); + ~field_stats() + { } -end: - return status; -} -static bt_value_map_foreach_entry_const_func_status + lttng::bt2::message_iterator_ref upstream_iterator; + lttng::bt2::event_class_const_ref event_class; + const lttng::bt2::value_ref stats_value; +}; + +namespace { +bt_value_map_foreach_entry_const_func_status stats_value_print_summary(const char *key, const bt_value *value, void *) { - assert(bt_value_is_map(value)); + LTTNG_ASSERT(bt_value_is_map(value)); + + const auto *min = bt_value_map_borrow_entry_value_const(value, "min"); + LTTNG_ASSERT(min != nullptr); + const auto *max = bt_value_map_borrow_entry_value_const(value, "max"); + LTTNG_ASSERT(max != nullptr); - const bt_value *min = bt_value_map_borrow_entry_value_const(value, "min"); - const bt_value *max = bt_value_map_borrow_entry_value_const(value, "max"); - const bt_value *display_base = bt_value_map_borrow_entry_value_const(value, "display_base"); - enum bt_field_class_integer_preferred_display_base display_base_value = - BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; + const auto *display_base = bt_value_map_borrow_entry_value_const(value, "display_base"); + auto display_base_value = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL; if (display_base != nullptr) { display_base_value = (enum bt_field_class_integer_preferred_display_base) bt_value_integer_unsigned_get(display_base); } - assert(min != nullptr); - assert(max != nullptr); - if (bt_value_is_string(min)) { + LTTNG_ASSERT(bt_value_get_type(min) == bt_value_get_type(max)); + + switch (bt_value_get_type(min)) { + case BT_VALUE_TYPE_STRING: fmt::print("{} \"{}\" \"{}\"\n", key, bt_value_string_get(min), bt_value_string_get(max)); - } else if (bt_value_is_unsigned_integer(min)) { + break; + case BT_VALUE_TYPE_UNSIGNED_INTEGER: switch (display_base_value) { case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL: - fmt::print("{} 0x{:X} 0x{:X}\n", - key, - bt_value_integer_unsigned_get(min), - bt_value_integer_unsigned_get(max)); + std::cout << lttng::format("{} 0x{:X} 0x{:X}\n", + key, + bt_value_integer_unsigned_get(min), + bt_value_integer_unsigned_get(max)); break; default: - fmt::print("{} {} {}\n", - key, - bt_value_integer_unsigned_get(min), - bt_value_integer_unsigned_get(max)); + std::cout << lttng::format("{} {} {}\n", + key, + bt_value_integer_unsigned_get(min), + bt_value_integer_unsigned_get(max)); break; } - } else if (bt_value_is_signed_integer(min)) { + + break; + case BT_VALUE_TYPE_SIGNED_INTEGER: switch (display_base_value) { case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL: - fmt::print("{} 0x{:X} 0x{:X}\n", - key, - (uint64_t) bt_value_integer_signed_get(min), - (uint64_t) bt_value_integer_signed_get(max)); + std::cout << lttng::format("{} 0x{:X} 0x{:X}\n", + key, + std::uint64_t(bt_value_integer_signed_get(min)), + std::uint64_t(bt_value_integer_signed_get(max))); break; default: - fmt::print("{} {} {}\n", - key, - bt_value_integer_signed_get(min), - bt_value_integer_signed_get(max)); + std::cout << lttng::format("{} {} {}\n", + key, + bt_value_integer_signed_get(min), + bt_value_integer_signed_get(max)); break; } - } else if (bt_value_is_real(min)) { - fmt::print("{} {:0g} {:0g}\n", key, bt_value_real_get(min), bt_value_real_get(max)); - } else { - assert(BT_FALSE); - } - return BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK; -} -void field_stats_finalize(bt_self_component_sink *self_component_sink) -{ - struct field_stats *field_stats = (struct field_stats *) bt_self_component_get_data( - bt_self_component_sink_as_self_component(self_component_sink)); - bt_value_put_ref(field_stats->stats_value); - free(field_stats); -} - -bt_component_class_sink_graph_is_configured_method_status -field_stats_graph_is_configured(bt_self_component_sink *self_component_sink) -{ - struct field_stats *field_stats = (struct field_stats *) bt_self_component_get_data( - bt_self_component_sink_as_self_component(self_component_sink)); - bt_self_component_port_input *input_port = - bt_self_component_sink_borrow_input_port_by_index(self_component_sink, 0); - if (bt_message_iterator_create_from_sink_component( - self_component_sink, input_port, &field_stats->iterator) != - BT_MESSAGE_ITERATOR_CREATE_FROM_SINK_COMPONENT_STATUS_OK) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "input port message iterator creation failed"); - return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR; + break; + case BT_VALUE_TYPE_REAL: + std::cout << lttng::format( + "{} {:0g} {:0g}\n", key, bt_value_real_get(min), bt_value_real_get(max)); + break; + default: + abort(); } - return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK; + return BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK; } -static bt_component_class_sink_consume_method_status -member_stats_set_min_max(bt_value *member_map, - const bt_field_class_structure_member *member, - const bt_field *member_field, - const bt_field_class *member_class, - const bt_field_class_type *member_class_type, - bt_self_component_sink *self_component_sink) +void member_stats_set_min_max(bt_value *member_map, + const bt_field_class_structure_member *member, + const bt_field *member_field, + const bt_field_class *member_class, + const bt_field_class_type *member_class_type) { - bt_value *min, *max, *display_base = bt_value_null; + lttng::bt2::value_ref min, max, display_base; const char *name = bt_field_class_structure_member_get_name(member); if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)) { - min = bt_value_integer_unsigned_create_init( - bt_field_integer_unsigned_get_value(member_field)); - max = bt_value_integer_unsigned_create_init( - bt_field_integer_unsigned_get_value(member_field)); - display_base = bt_value_integer_unsigned_create_init( - bt_field_class_integer_get_preferred_display_base(member_class)); + min = lttng::bt2::make_value_ref(bt_value_integer_unsigned_create_init( + bt_field_integer_unsigned_get_value(member_field))); + max = lttng::bt2::make_value_ref(bt_value_integer_unsigned_create_init( + bt_field_integer_unsigned_get_value(member_field))); + display_base = lttng::bt2::make_value_ref(bt_value_integer_unsigned_create_init( + bt_field_class_integer_get_preferred_display_base(member_class))); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_SIGNED_INTEGER)) { - min = bt_value_integer_signed_create_init( - bt_field_integer_signed_get_value(member_field)); - max = bt_value_integer_signed_create_init( - bt_field_integer_signed_get_value(member_field)); - display_base = bt_value_integer_unsigned_create_init( - bt_field_class_integer_get_preferred_display_base(member_class)); + min = lttng::bt2::make_value_ref(bt_value_integer_signed_create_init( + bt_field_integer_signed_get_value(member_field))); + max = lttng::bt2::make_value_ref(bt_value_integer_signed_create_init( + bt_field_integer_signed_get_value(member_field))); + display_base = lttng::bt2::make_value_ref(bt_value_integer_unsigned_create_init( + bt_field_class_integer_get_preferred_display_base(member_class))); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_STRING)) { - min = bt_value_string_create_init(bt_field_string_get_value(member_field)); - max = bt_value_string_create_init(bt_field_string_get_value(member_field)); + min = lttng::bt2::make_value_ref( + bt_value_string_create_init(bt_field_string_get_value(member_field))); + max = lttng::bt2::make_value_ref( + bt_value_string_create_init(bt_field_string_get_value(member_field))); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL)) { - min = bt_value_real_create_init( - bt_field_real_double_precision_get_value(member_field)); - max = bt_value_real_create_init( - bt_field_real_double_precision_get_value(member_field)); + min = lttng::bt2::make_value_ref(bt_value_real_create_init( + bt_field_real_double_precision_get_value(member_field))); + max = lttng::bt2::make_value_ref(bt_value_real_create_init( + bt_field_real_double_precision_get_value(member_field))); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL)) { - min = bt_value_real_create_init( - bt_field_real_single_precision_get_value(member_field)); - max = bt_value_real_create_init( - bt_field_real_single_precision_get_value(member_field)); + min = lttng::bt2::make_value_ref(bt_value_real_create_init( + bt_field_real_single_precision_get_value(member_field))); + max = lttng::bt2::make_value_ref(bt_value_real_create_init( + bt_field_real_single_precision_get_value(member_field))); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_BIT_ARRAY)) { - min = bt_value_integer_unsigned_create_init( - bt_field_bit_array_get_value_as_integer(member_field)); - max = bt_value_integer_unsigned_create_init( - bt_field_bit_array_get_value_as_integer(member_field)); + min = lttng::bt2::make_value_ref(bt_value_integer_unsigned_create_init( + bt_field_bit_array_get_value_as_integer(member_field))); + max = lttng::bt2::make_value_ref(bt_value_integer_unsigned_create_init( + bt_field_bit_array_get_value_as_integer(member_field))); } else { - const auto field_class_type_name = fmt::to_string(*member_class_type); - - fmt::print("Unsupported field type for '{}': {}\n", name, field_class_type_name); - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "Unsupported field type '%s' for member '%s'", - field_class_type_name.c_str(), - name); - - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; + throw std::runtime_error(lttng::format( + "Unsupported field type '{}' for member '{}'", *member_class_type, name)); } - if (min != nullptr) { - bt_value_map_insert_entry(member_map, "min", min); - bt_value_put_ref(min); + if (min) { + bt_value_map_insert_entry(member_map, "min", min.get()); } else { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "No minimum value for member '%s'", - name); - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; + throw std::runtime_error(lttng::format("No minimum value for member '{}'", name)); } - if (max != nullptr) { - bt_value_map_insert_entry(member_map, "max", max); - bt_value_put_ref(max); + + if (max) { + bt_value_map_insert_entry(member_map, "max", max.get()); } else { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "No maximum value for member '%s'", - name); - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; + throw std::runtime_error(lttng::format("No maximum value for member '{}'", name)); } - if (display_base != bt_value_null) { - bt_value_map_insert_entry(member_map, "display_base", display_base); - bt_value_put_ref(display_base); + + if (display_base) { + bt_value_map_insert_entry(member_map, "display_base", display_base.get()); } - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; } -static bt_component_class_sink_consume_method_status -member_stats_update_min_max(bt_value *member_map, - const bt_field_class_structure_member *member, - const bt_field *member_field, - const bt_field_class_type *member_class_type, - bt_self_component_sink *self_component_sink) +void member_stats_update_min_max(bt_value *member_map, + const bt_field_class_structure_member *member, + const bt_field *member_field, + const bt_field_class_type *member_class_type) { const char *name = bt_field_class_structure_member_get_name(member); bt_value *min = bt_value_map_borrow_entry_value(member_map, "min"); bt_value *max = bt_value_map_borrow_entry_value(member_map, "max"); if (min == nullptr || max == nullptr) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "Missing min or max value for member '%s'", - name); - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; + throw std::runtime_error( + lttng::format("Missing min or max value for member '{}'", name)); } if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)) { - bt_value *value = bt_value_integer_unsigned_create_init( - bt_field_integer_unsigned_get_value(member_field)); - if (bt_value_integer_unsigned_get(value) < bt_value_integer_unsigned_get(min)) { - bt_value_integer_unsigned_set(min, bt_value_integer_unsigned_get(value)); + const auto value = bt_field_integer_unsigned_get_value(member_field); + + if (value < bt_value_integer_unsigned_get(min)) { + bt_value_integer_unsigned_set(min, value); } - if (bt_value_integer_unsigned_get(value) > bt_value_integer_unsigned_get(max)) { - bt_value_integer_unsigned_set(max, bt_value_integer_unsigned_get(value)); + + if (value > bt_value_integer_unsigned_get(max)) { + bt_value_integer_unsigned_set(max, value); } - bt_value_put_ref(value); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_SIGNED_INTEGER)) { - bt_value *value = bt_value_integer_signed_create_init( - bt_field_integer_signed_get_value(member_field)); - if (bt_value_integer_signed_get(value) < bt_value_integer_signed_get(min)) { - bt_value_integer_signed_set(min, bt_value_integer_signed_get(value)); + const auto value = bt_field_integer_signed_get_value(member_field); + + if (value < bt_value_integer_signed_get(min)) { + bt_value_integer_signed_set(min, value); } - if (bt_value_integer_signed_get(value) > bt_value_integer_signed_get(max)) { - bt_value_integer_signed_set(max, bt_value_integer_signed_get(value)); + + if (value > bt_value_integer_signed_get(max)) { + bt_value_integer_signed_set(max, value); } - bt_value_put_ref(value); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_STRING)) { - bt_value *value = - bt_value_string_create_init(bt_field_string_get_value(member_field)); - if (strcmp(bt_value_string_get(value), bt_value_string_get(min)) < 0) { - bt_value_string_set(min, bt_value_string_get(value)); + const auto value = bt_field_string_get_value(member_field); + + if (strcmp(value, bt_value_string_get(min)) < 0) { + bt_value_string_set(min, value); } - if (strcmp(bt_value_string_get(value), bt_value_string_get(max)) > 0) { - bt_value_string_set(max, bt_value_string_get(value)); + + if (strcmp(value, bt_value_string_get(max)) > 0) { + bt_value_string_set(max, value); } - bt_value_put_ref(value); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL)) { - bt_value *value = bt_value_real_create_init( - bt_field_real_double_precision_get_value(member_field)); - if (bt_value_real_get(value) < bt_value_real_get(min)) { - bt_value_real_set(min, bt_value_real_get(value)); + const auto value = bt_field_real_double_precision_get_value(member_field); + + if (value < bt_value_real_get(min)) { + bt_value_real_set(min, value); } - if (bt_value_real_get(value) > bt_value_real_get(max)) { - bt_value_real_set(max, bt_value_real_get(value)); + + if (value > bt_value_real_get(max)) { + bt_value_real_set(max, value); } - bt_value_put_ref(value); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL)) { - bt_value *value = bt_value_real_create_init( - (double) bt_field_real_single_precision_get_value(member_field)); - if (bt_value_real_get(value) < bt_value_real_get(min)) { - bt_value_real_set(min, bt_value_real_get(value)); + const auto value = double(bt_field_real_single_precision_get_value(member_field)); + + if (value < bt_value_real_get(min)) { + bt_value_real_set(min, value); } - if (bt_value_real_get(value) > bt_value_real_get(max)) { - bt_value_real_set(max, bt_value_real_get(value)); + + if (value > bt_value_real_get(max)) { + bt_value_real_set(max, value); } - bt_value_put_ref(value); } else if (bt_field_class_type_is(*member_class_type, BT_FIELD_CLASS_TYPE_BIT_ARRAY)) { - bt_value *value = bt_value_integer_unsigned_create_init( - bt_field_bit_array_get_value_as_integer(member_field)); - if (bt_value_integer_unsigned_get(value) < bt_value_integer_unsigned_get(min)) { - bt_value_integer_unsigned_set(min, bt_value_integer_unsigned_get(value)); + const auto value = bt_field_bit_array_get_value_as_integer(member_field); + + if (value < bt_value_integer_unsigned_get(min)) { + bt_value_integer_unsigned_set(min, value); } - if (bt_value_integer_unsigned_get(value) > bt_value_integer_unsigned_get(max)) { - bt_value_integer_unsigned_set(max, bt_value_integer_unsigned_get(value)); + + if (value > bt_value_integer_unsigned_get(max)) { + bt_value_integer_unsigned_set(max, value); } - bt_value_put_ref(value); } else { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component(self_component_sink), - "Unsupported field type '%ld' for member '%s'", - *member_class_type, - name); - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; + throw std::runtime_error(lttng::format( + "Unsupported field type '%{}' for member '{}'", *member_class_type, name)); } - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; } -static bt_component_class_sink_consume_method_status +bt_component_class_sink_consume_method_status update_stats(const bt_message *message, - field_stats *field_stats, + field_stats& field_stats, bt_self_component_sink *self_component_sink) { if (bt_message_get_type(message) != BT_MESSAGE_TYPE_EVENT) { - /* It's not an error to get non-EVENT messages */ + /* It's not an error to get non-EVENT messages. */ return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; } - bt_component_class_sink_consume_method_status status; - const bt_event *event = bt_message_event_borrow_event_const(message); - const bt_field *event_payload = bt_event_borrow_payload_field_const(event); - const bt_event_class *event_class = bt_event_borrow_class_const(event); - const bt_field_class *event_payload_class = + const auto *event = bt_message_event_borrow_event_const(message); + const auto *event_payload = bt_event_borrow_payload_field_const(event); + const auto *event_class = bt_event_borrow_class_const(event); + const auto *event_payload_class = bt_event_class_borrow_payload_field_class_const(event_class); - if (field_stats->event_class != nullptr) { - assert(event_class == field_stats->event_class); + if (field_stats.event_class != nullptr) { + LTTNG_ASSERT(event_class == field_stats.event_class.get()); } else { - field_stats->event_class = event_class; + bt_event_class_get_ref(event_class); + field_stats.event_class.reset(event_class); } /* Iterate over each field in the event payload */ - for (uint64_t index = 0; + for (std::uint64_t index = 0; index < bt_field_class_structure_get_member_count(event_payload_class); index++) { const bt_field_class_structure_member *member = bt_field_class_structure_borrow_member_by_index_const(event_payload_class, index); - const char *name = bt_field_class_structure_member_get_name(member); - const bt_field *member_field = + const auto *name = bt_field_class_structure_member_get_name(member); + const auto *member_field = bt_field_structure_borrow_member_field_by_name_const(event_payload, name); - const bt_field_class *member_class = + const auto *member_class = bt_field_class_structure_member_borrow_field_class_const(member); - const bt_field_class_type member_class_type = bt_field_class_get_type(member_class); + const auto member_class_type = bt_field_class_get_type(member_class); - /* Ignore array and structure field types. */ if (bt_field_class_type_is(member_class_type, BT_FIELD_CLASS_TYPE_ARRAY) || bt_field_class_type_is(member_class_type, BT_FIELD_CLASS_TYPE_STRUCTURE)) { + /* Ignore array and structure field types. */ continue; } - bt_value *member_map = - bt_value_map_borrow_entry_value(field_stats->stats_value, name); - if (member_map == nullptr) { - if (bt_value_map_insert_empty_map_entry( - field_stats->stats_value, name, &member_map) != - BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_sink_as_self_component( - self_component_sink), - "Failed to insert new empty map entry for field '%s'", - name); - return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; - } - - status = member_stats_set_min_max(member_map, - member, - member_field, - member_class, - &member_class_type, - self_component_sink); - if (status != BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK) { - return status; - } - } else { - status = member_stats_update_min_max(member_map, - member, - member_field, - &member_class_type, - self_component_sink); - if (status != BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK) { - return status; + try { + auto *member_map = bt_value_map_borrow_entry_value( + field_stats.stats_value.get(), name); + if (member_map == nullptr) { + /* Initial creation of the value. */ + if (bt_value_map_insert_empty_map_entry( + field_stats.stats_value.get(), name, &member_map) != + BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) { + throw std::runtime_error(lttng::format( + "Failed to insert new empty map entry for field '{}'", + name)); + } + + member_stats_set_min_max(member_map, + member, + member_field, + member_class, + &member_class_type); + } else { + /* Update the value with min/max values. */ + member_stats_update_min_max( + member_map, member, member_field, &member_class_type); } + } catch (const std::exception& ex) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( + bt_self_component_sink_as_self_component(self_component_sink), + "%s", + ex.what()); + return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR; } } + return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; } +} /* namespace */ + +bt_component_class_initialize_method_status +field_stats_initialize(bt_self_component_sink *self_component_sink, + bt_self_component_sink_configuration *, + const bt_value *, + void *) +{ + if (bt_self_component_sink_add_input_port(self_component_sink, "in", nullptr, nullptr) != + BT_SELF_COMPONENT_ADD_PORT_STATUS_OK) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( + bt_self_component_sink_as_self_component(self_component_sink), + "Failed to add input port"); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; + } + + std::unique_ptr field_stats; + try { + field_stats = lttng::make_unique(); + } catch (const bad_alloc_with_msg& ex) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( + bt_self_component_sink_as_self_component(self_component_sink), + "%s", + ex.what()); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; + } catch (const std::bad_alloc&) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( + bt_self_component_sink_as_self_component(self_component_sink), + "Failed to allocate memory for private data"); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; + } + + /* Transfer ownership to the component. */ + bt_self_component_set_data(bt_self_component_sink_as_self_component(self_component_sink), + field_stats.release()); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; +} + +void field_stats_finalize(bt_self_component_sink *self_component_sink) +{ + auto *field_stats = static_cast(bt_self_component_get_data( + bt_self_component_sink_as_self_component(self_component_sink))); + + delete field_stats; +} + +bt_component_class_sink_graph_is_configured_method_status +field_stats_graph_is_configured(bt_self_component_sink *self_component_sink) +{ + auto& field_stats = *static_cast(bt_self_component_get_data( + bt_self_component_sink_as_self_component(self_component_sink))); + auto *input_port = + bt_self_component_sink_borrow_input_port_by_index(self_component_sink, 0); + + bt_message_iterator *raw_iterator; + if (bt_message_iterator_create_from_sink_component( + self_component_sink, input_port, &raw_iterator) != + BT_MESSAGE_ITERATOR_CREATE_FROM_SINK_COMPONENT_STATUS_OK) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( + bt_self_component_sink_as_self_component(self_component_sink), + "input port message iterator creation failed"); + return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR; + } + + field_stats.upstream_iterator.reset(raw_iterator); + return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK; +} bt_component_class_sink_consume_method_status field_stats_consume(bt_self_component_sink *self_component_sink) { - bt_component_class_sink_consume_method_status status; - struct field_stats *field_stats = (struct field_stats *) bt_self_component_get_data( - bt_self_component_sink_as_self_component(self_component_sink)); - bt_message_array_const messages; - uint64_t message_count; - bt_message_iterator_next_status next_status; + auto& field_stats = *static_cast(bt_self_component_get_data( + bt_self_component_sink_as_self_component(self_component_sink))); - assert(field_stats); - next_status = bt_message_iterator_next(field_stats->iterator, &messages, &message_count); + std::uint64_t message_count; + bt_message_array_const messages; + const auto next_status = bt_message_iterator_next( + field_stats.upstream_iterator.get(), &messages, &message_count); if (next_status != BT_MESSAGE_ITERATOR_NEXT_STATUS_OK) { if (next_status == BT_MESSAGE_ITERATOR_NEXT_STATUS_END) { + /* End reached, print the summary. */ bt_value_map_foreach_entry_const( - field_stats->stats_value, stats_value_print_summary, nullptr); - bt_message_iterator_put_ref(field_stats->iterator); + field_stats.stats_value.get(), stats_value_print_summary, nullptr); } - status = static_cast(next_status); - goto end; + + return static_cast(next_status); } - for (uint64_t index = 0; index < message_count; index++) { - const bt_message *message = messages[index]; - status = update_stats(message, field_stats, self_component_sink); - bt_message_put_ref(message); + for (std::uint64_t index = 0; index < message_count; index++) { + const auto message = lttng::bt2::message_const_ref(messages[index]); + + const auto status = update_stats(message.get(), field_stats, self_component_sink); if (status != BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK) { - goto end; + return status; } } - status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; -end: - return status; + + return BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK; }