X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=tests%2Futils%2Fbt2_plugins%2Fevent_name%2Fevent_name.cpp;h=170e375924b5a72e8abee303d2a684323cded093;hb=d73aeddd1b4de7fadc7b6f6f5004c6298208602a;hp=6c8e1c5b2b133b826098eb62b642e6a6ee008896;hpb=74021af62434d042d27e010d62d6b6a0717f246b;p=lttng-tools.git 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; }