From d73aeddd1b4de7fadc7b6f6f5004c6298208602a Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Fri, 8 Mar 2024 16:18:29 -0500 Subject: [PATCH] Clean-up: tests: bt2 plug-ins: modernize the plug-ins MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit By virtue of their use of the C Babeltrace 2 APIs, the test plug-ins perform a fair amount of manual resource management. To make it possible to adopt a more modern C++ style in those plug-ins, a number of helpers are introduced. Introduce reference wrappers for the Babeltrace 2 interface: - value_ref: wraps a bt_value reference using std::unique_ptr - message_const_ref: wraps a constant message reference using a unique_ptr - message_iterator_ref: wraps a message iterator reference using a unique_ptr - event_class_const_ref: wraps a constant event class reference using a unique_ptr A specialized random_access_container_wrapper is specialized to wrap bt_value arrays of strings. In doing so, it is possible to eliminate the use of gotos and manual reference management on error paths. Some struct/classes are renamed to eliminate ambiguities that arose over the refactoring. The changes allow some simplifications of the code flow in places which are applied directly. Change-Id: I25c148d7970cb89add55a86f2c162973d3d27e4a Signed-off-by: Jérémie Galarneau --- src/common/container-wrapper.hpp | 7 +- tests/utils/bt2_plugins/Makefile.am | 4 +- .../bt2_plugins/event_name/event_name.cpp | 327 ++++++---- .../bt2_plugins/event_name/event_name.hpp | 6 +- .../bt2_plugins/field_stats/field_stats.cpp | 599 +++++++++--------- .../bt2_plugins/field_stats/field_stats.hpp | 6 +- tests/utils/bt2_plugins/utils.hpp | 49 ++ 7 files changed, 561 insertions(+), 437 deletions(-) create mode 100644 tests/utils/bt2_plugins/utils.hpp diff --git a/src/common/container-wrapper.hpp b/src/common/container-wrapper.hpp index 7f9678d08..20642a8d2 100644 --- a/src/common/container-wrapper.hpp +++ b/src/common/container-wrapper.hpp @@ -117,6 +117,11 @@ public: return ContainerOperations::size(_container); } + bool empty() const + { + return size() == 0; + } + typename std::conditional::value, ElementType, ElementType&>::type operator[](std::size_t index) { @@ -144,7 +149,7 @@ public: operator[](std::size_t index) const { if (index >= ContainerOperations::size(_container)) { - LTTNG_THROW_INVALID_ARGUMENT_ERROR(lttng::format( + throw std::invalid_argument(lttng::format( "Out of bound access through random_access_container_wrapper: index={}, size={}", index, size())); diff --git a/tests/utils/bt2_plugins/Makefile.am b/tests/utils/bt2_plugins/Makefile.am index 59fdbcb83..ce6697e27 100644 --- a/tests/utils/bt2_plugins/Makefile.am +++ b/tests/utils/bt2_plugins/Makefile.am @@ -16,7 +16,9 @@ lttngtest_la_CXXFLAGS = \ -fvisibility=default lttngtest_la_SOURCES = \ - lttngtest-plugin.cpp + lttngtest-plugin.cpp \ + fmt.hpp \ + utils.hpp lttngtest_la_LDFLAGS = \ $(AM_LDFLAGS) \ diff --git a/tests/utils/bt2_plugins/event_name/event_name.cpp b/tests/utils/bt2_plugins/event_name/event_name.cpp index 6c8e1c5b2..170e37592 100644 --- a/tests/utils/bt2_plugins/event_name/event_name.cpp +++ b/tests/utils/bt2_plugins/event_name/event_name.cpp @@ -5,111 +5,193 @@ * */ +#include "../utils.hpp" #include "event_name.hpp" +#include +#include +#include + #include #include +#include +#include #include #include #include #include -struct event_name { - std::unordered_set names; - const bt_value *names_value; +class event_name_set_operations { +public: + static const char *get(const bt_value *array, std::size_t index) + { + const auto *names_entry = + bt_value_array_borrow_element_by_index_const(array, index); + + if (bt_value_get_type(names_entry) != BT_VALUE_TYPE_STRING) { + throw std::runtime_error( + "All members of the 'names' parameter array must be strings"); + } + + return bt_value_string_get(names_entry); + } + + static std::size_t size(const bt_value *array) + { + return bt_value_array_get_length(array); + } +}; + +class event_name_set + : public lttng::utils::random_access_container_wrapper { +public: + friend event_name_set_operations; + + event_name_set() : + lttng::utils::random_access_container_wrapper(nullptr) + { + } + + event_name_set(event_name_set&& original) : + lttng::utils::random_access_container_wrapper( + std::move(original._container)) + { + } + + event_name_set(const bt_value *names) : + lttng::utils::random_access_container_wrapper(names) + { + if (bt_value_get_type(names) != BT_VALUE_TYPE_ARRAY) { + throw std::invalid_argument("'names' parameter must be an array"); + } + } +}; + +class event_name_filter { +public: + event_name_filter(bt_self_component_port_input *input_port_, + const event_name_set& name_set) : + input_port{ input_port_ }, _names{ name_set.begin(), name_set.end() } + { + } + + bool event_name_is_allowed(const char *event_name) const noexcept + { + return _names.find(event_name) != _names.end(); + } + /* weak reference */ - bt_self_component_port_input *input_port; + bt_self_component_port_input *const input_port; + +private: + const std::unordered_set _names; }; struct event_name_iterator_data { - struct event_name *event_name; - bt_message_iterator *iterator; + event_name_iterator_data(lttng::bt2::message_iterator_ref iterator_, + const class event_name_filter& event_name_filter_) : + upstream_iterator{ std::move(iterator_) }, event_name_filter{ event_name_filter_ } + { + } + + ~event_name_iterator_data() + { + } + + const lttng::bt2::message_iterator_ref upstream_iterator; + const class event_name_filter& event_name_filter; }; +namespace { +bool message_passes(const bt_message *message, const event_name_filter& event_name_filter) +{ + if (bt_message_get_type(message) != BT_MESSAGE_TYPE_EVENT) { + return true; + } + + const bt_event *event = bt_message_event_borrow_event_const(message); + const bt_event_class *event_class = bt_event_borrow_class_const(event); + const char *event_name = bt_event_class_get_name(event_class); + + if (event_name == nullptr) { + return false; + } + + return event_name_filter.event_name_is_allowed(event_name); +} +} /* namespace */ + bt_component_class_initialize_method_status event_name_initialize(bt_self_component_filter *self_comp, bt_self_component_filter_configuration *, const bt_value *params, void *) { - bt_component_class_initialize_method_status status; bt_self_component_port_input *input_port; - struct event_name *event_name; + std::unique_ptr event_name_filter; + auto self = bt_self_component_filter_as_self_component(self_comp); if (bt_self_component_filter_add_input_port(self_comp, "in", nullptr, &input_port) != BT_SELF_COMPONENT_ADD_PORT_STATUS_OK) { BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self, "Failed to add input port"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto end; + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } if (bt_self_component_filter_add_output_port(self_comp, "out", nullptr, nullptr) != BT_SELF_COMPONENT_ADD_PORT_STATUS_OK) { BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self, "Failed to add output port"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto end; - } - - event_name = new (std::nothrow) struct event_name; - if (event_name == nullptr) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - self, "Failed to allocate memory for private component data"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; - goto end; + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } - event_name->input_port = input_port; - event_name->names_value = bt_value_map_borrow_entry_value_const(params, "names"); - if (event_name->names_value == nullptr) { + const auto names_param = bt_value_map_borrow_entry_value_const(params, "names"); + if (names_param == nullptr) { BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( self, "'names' parameter is required"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto err_free; + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } - if (bt_value_get_type(event_name->names_value) != BT_VALUE_TYPE_ARRAY) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - self, "'names' parameter must be an array"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto err_free; - } - if (bt_value_array_is_empty(event_name->names_value)) { - BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - bt_self_component_filter_as_self_component(self_comp), - "'names' parameter must not be empty"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto err_free; - } - for (uint64_t index = 0; index < bt_value_array_get_length(event_name->names_value); - index++) { - const bt_value *names_entry = bt_value_array_borrow_element_by_index_const( - event_name->names_value, index); - if (bt_value_get_type(names_entry) != BT_VALUE_TYPE_STRING) { + + try { + event_name_set event_names{ names_param }; + if (event_names.empty()) { BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( - self, "All members of the 'names' parameter array must be strings"); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - goto err_free; + bt_self_component_filter_as_self_component(self_comp), + "'names' parameter must not be empty"); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } - event_name->names.emplace(bt_value_string_get(names_entry)); + + event_name_filter = + lttng::make_unique(input_port, event_names); + } catch (const std::bad_alloc&) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT( + self, "Failed to allocate memory for private component data"); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR; + } catch (const std::exception& ex) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self, "%s", ex.what()); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } - bt_value_get_ref(event_name->names_value); - bt_self_component_set_data(self, event_name); - status = BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; - goto end; -err_free: - delete event_name; -end: - return status; + /* Ownership of event_name is transferred to the component. */ + bt_self_component_set_data(self, event_name_filter.release()); + return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK; } void event_name_finalize(bt_self_component_filter *self_comp) { - struct event_name *event_name = (struct event_name *) bt_self_component_get_data( - bt_self_component_filter_as_self_component(self_comp)); - bt_value_put_ref(event_name->names_value); - delete event_name; + class event_name_filter *event_name_filter = + (class event_name_filter *) bt_self_component_get_data( + bt_self_component_filter_as_self_component(self_comp)); + + delete event_name_filter; } bt_message_iterator_class_initialize_method_status @@ -117,104 +199,87 @@ event_name_message_iterator_initialize(bt_self_message_iterator *self_message_it bt_self_message_iterator_configuration *, bt_self_component_port_output *) { - struct event_name *event_name = (struct event_name *) bt_self_component_get_data( - bt_self_message_iterator_borrow_component(self_message_iterator)); - assert(event_name); - - struct event_name_iterator_data *iter_data = - (struct event_name_iterator_data *) malloc(sizeof(struct event_name_iterator_data)); - - if (iter_data == nullptr) { - return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR; - } - iter_data->event_name = event_name; + const auto& event_name_filter = + *static_cast(bt_self_component_get_data( + bt_self_message_iterator_borrow_component(self_message_iterator))); + bt_message_iterator *raw_iterator; if (bt_message_iterator_create_from_message_iterator( - self_message_iterator, event_name->input_port, &iter_data->iterator) != + self_message_iterator, event_name_filter.input_port, &raw_iterator) != BT_MESSAGE_ITERATOR_CREATE_FROM_MESSAGE_ITERATOR_STATUS_OK) { - free(iter_data); return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR; } - bt_self_message_iterator_set_data(self_message_iterator, iter_data); + lttng::bt2::message_iterator_ref iterator(raw_iterator); + raw_iterator = nullptr; + + std::unique_ptr iter_data; + try { + iter_data = lttng::make_unique(std::move(iterator), + event_name_filter); + } catch (const std::bad_alloc&) { + BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR( + self_message_iterator, "Failed to allocate event_name iterator data"); + return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR; + } + /* Transfer the ownership of iter_data to the iterator. */ + bt_self_message_iterator_set_data(self_message_iterator, iter_data.release()); return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK; } void event_name_message_iterator_finalize(bt_self_message_iterator *self_message) { - struct event_name_iterator_data *iter_data = - (struct event_name_iterator_data *) bt_self_message_iterator_get_data(self_message); + event_name_iterator_data *iter_data = static_cast( + bt_self_message_iterator_get_data(self_message)); - assert(iter_data); - bt_message_iterator_put_ref(iter_data->iterator); - free(iter_data); -} - -static bool message_passes(const bt_message *message, const std::unordered_set& names) -{ - if (bt_message_get_type(message) != BT_MESSAGE_TYPE_EVENT) { - return true; - } - - const bt_event *event = bt_message_event_borrow_event_const(message); - const bt_event_class *event_class = bt_event_borrow_class_const(event); - const char *event_name = bt_event_class_get_name(event_class); - - if (event_name == nullptr) { - return false; - } - - if (names.find(event_name) != names.end()) { - return true; - } - - return false; + LTTNG_ASSERT(iter_data); + delete iter_data; } bt_message_iterator_class_next_method_status event_name_message_iterator_next(bt_self_message_iterator *self_message_iterator, - bt_message_array_const messages, + bt_message_array_const messages_to_deliver_downstream, uint64_t, - uint64_t *count) + uint64_t *_messages_to_deliver_count) { - bt_message_array_const upstream_messages; - uint64_t upstream_message_count; - uint64_t index = 0; - bt_message_iterator_next_status next_status; - bt_message_iterator_class_next_method_status status = - BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK; - struct event_name_iterator_data *iter_data = - (struct event_name_iterator_data *) bt_self_message_iterator_get_data( - self_message_iterator); - struct event_name *event_name = (struct event_name *) bt_self_component_get_data( - bt_self_message_iterator_borrow_component(self_message_iterator)); - - assert(event_name); - assert(iter_data); - - while (index == 0) { - next_status = bt_message_iterator_next( - iter_data->iterator, &upstream_messages, &upstream_message_count); + std::uint64_t messages_to_deliver_count = 0; + auto *iter_data = static_cast( + bt_self_message_iterator_get_data(self_message_iterator)); + const auto& event_name_filter = + *static_cast(bt_self_component_get_data( + bt_self_message_iterator_borrow_component(self_message_iterator))); + + LTTNG_ASSERT(iter_data); + + /* Retry until we have at least one message to deliver downstream. */ + while (messages_to_deliver_count == 0) { + bt_message_array_const upstream_messages; + bt_message_iterator_next_status next_status; + uint64_t upstream_message_count; + + next_status = bt_message_iterator_next(iter_data->upstream_iterator.get(), + &upstream_messages, + &upstream_message_count); if (next_status != BT_MESSAGE_ITERATOR_NEXT_STATUS_OK) { - status = static_cast( + return static_cast( next_status); - goto end; } - for (uint64_t upstream_index = 0; upstream_index < upstream_message_count; + for (std::uint64_t upstream_index = 0; upstream_index < upstream_message_count; upstream_index++) { - const bt_message *upstream_message = upstream_messages[upstream_index]; - if (message_passes(upstream_message, event_name->names)) { - messages[index] = upstream_message; - index++; - } else { - bt_message_put_ref(upstream_message); + lttng::bt2::message_const_ref upstream_message( + upstream_messages[upstream_index]); + + if (message_passes(upstream_message.get(), event_name_filter)) { + /* Reference transferred to downstream message batch. */ + messages_to_deliver_downstream[messages_to_deliver_count] = + upstream_message.release(); + messages_to_deliver_count++; } } } - *count = index; -end: - return status; + *_messages_to_deliver_count = messages_to_deliver_count; + return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK; } diff --git a/tests/utils/bt2_plugins/event_name/event_name.hpp b/tests/utils/bt2_plugins/event_name/event_name.hpp index 65513b286..9798b66f5 100644 --- a/tests/utils/bt2_plugins/event_name/event_name.hpp +++ b/tests/utils/bt2_plugins/event_name/event_name.hpp @@ -5,8 +5,8 @@ * */ -#ifndef EVENT_NAME_H -#define EVENT_NAME_H +#ifndef LTTNG_TEST_UTILS_BT2_PLUGIN_EVENT_NAME_HPP +#define LTTNG_TEST_UTILS_BT2_PLUGIN_EVENT_NAME_HPP #include @@ -31,4 +31,4 @@ event_name_message_iterator_next(bt_self_message_iterator *self_message_iterator uint64_t capacity, uint64_t *count); -#endif /* EVENT_NAME_H */ +#endif /* LTTNG_TEST_UTILS_BT2_PLUGIN_EVENT_NAME_HPP */ 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; } diff --git a/tests/utils/bt2_plugins/field_stats/field_stats.hpp b/tests/utils/bt2_plugins/field_stats/field_stats.hpp index 833a4cfaf..b1977af04 100644 --- a/tests/utils/bt2_plugins/field_stats/field_stats.hpp +++ b/tests/utils/bt2_plugins/field_stats/field_stats.hpp @@ -5,8 +5,8 @@ * */ -#ifndef FIELD_STATS_H -#define FIELD_STATS_H +#ifndef LTTNG_TEST_UTILS_BT2_PLUGIN_FIELD_STATS_HPP +#define LTTNG_TEST_UTILS_BT2_PLUGIN_FIELD_STATS_HPP #include @@ -24,4 +24,4 @@ field_stats_graph_is_configured(bt_self_component_sink *self_component_sink); bt_component_class_sink_consume_method_status field_stats_consume(bt_self_component_sink *self_component_sink); -#endif /* FIELD_STATS_H */ +#endif /* LTTNG_TEST_UTILS_BT2_PLUGIN_FIELD_STATS_HPP */ diff --git a/tests/utils/bt2_plugins/utils.hpp b/tests/utils/bt2_plugins/utils.hpp new file mode 100644 index 000000000..fcf76371c --- /dev/null +++ b/tests/utils/bt2_plugins/utils.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_TEST_UTILS_BT2_PLUGIN_UTILS_HPP +#define LTTNG_TEST_UTILS_BT2_PLUGIN_UTILS_HPP + +#include + +#include + +namespace lttng { +namespace bt2 { +namespace internal { +static inline void bt_value_put_ref(bt_value *value) +{ + bt_value_put_ref(const_cast(value)); +} +} /* namespace internal */ + +using value_ref = std::unique_ptr< + bt_value, + lttng::memory::create_deleter_class::deleter>; + +using event_class_const_ref = std::unique_ptr< + const bt_event_class, + lttng::memory::create_deleter_class::deleter>; + +static inline value_ref make_value_ref(bt_value *instance) +{ + const memory::create_deleter_class unique_deleter; + return unique_deleter(instance); +} + +using message_const_ref = std::unique_ptr< + const bt_message, + lttng::memory::create_deleter_class::deleter>; + +using message_iterator_ref = + std::unique_ptr::deleter>; +} /* namespace bt2 */ +} /* namespace lttng */ + +#endif /* LTTNG_TEST_UTILS_BT2_PLUGIN_UTILS_HPP */ -- 2.34.1