Clean-up: tests: bt2 plug-ins: modernize the plug-ins
[lttng-tools.git] / tests / utils / bt2_plugins / event_name / event_name.cpp
index 6c8e1c5b2b133b826098eb62b642e6a6ee008896..170e375924b5a72e8abee303d2a684323cded093 100644 (file)
  *
  */
 
+#include "../utils.hpp"
 #include "event_name.hpp"
 
+#include <common/container-wrapper.hpp>
+#include <common/macros.hpp>
+#include <common/make-unique.hpp>
+
 #include <assert.h>
 #include <babeltrace2/babeltrace.h>
+#include <cstdint>
+#include <exception>
 #include <stdlib.h>
 #include <string.h>
 #include <string>
 #include <unordered_set>
 
-struct event_name {
-       std::unordered_set<std::string> 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<const bt_value *,
+                                                              const char *,
+                                                              event_name_set_operations> {
+public:
+       friend event_name_set_operations;
+
+       event_name_set() :
+               lttng::utils::random_access_container_wrapper<const bt_value *,
+                                                             const char *,
+                                                             event_name_set_operations>(nullptr)
+       {
+       }
+
+       event_name_set(event_name_set&& original) :
+               lttng::utils::random_access_container_wrapper<const bt_value *,
+                                                             const char *,
+                                                             event_name_set_operations>(
+                       std::move(original._container))
+       {
+       }
+
+       event_name_set(const bt_value *names) :
+               lttng::utils::random_access_container_wrapper<const bt_value *,
+                                                             const char *,
+                                                             event_name_set_operations>(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<std::string> _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<class event_name_filter> 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<class event_name_filter>(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<class event_name_filter *>(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<event_name_iterator_data> iter_data;
+       try {
+               iter_data = lttng::make_unique<event_name_iterator_data>(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<event_name_iterator_data *>(
+               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<std::string>& 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<event_name_iterator_data *>(
+               bt_self_message_iterator_get_data(self_message_iterator));
+       const auto& event_name_filter =
+               *static_cast<class event_name_filter *>(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<bt_message_iterator_class_next_method_status>(
+                       return static_cast<bt_message_iterator_class_next_method_status>(
                                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;
 }
This page took 0.028508 seconds and 4 git commands to generate.