Clean-up: tests: bt2 plug-ins: modernize the plug-ins
[lttng-tools.git] / tests / utils / bt2_plugins / event_name / event_name.cpp
CommitLineData
9f263671
KS
1/*
2 * Copyright (C) 2023 Kienan Stewart <kstewart@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
d73aeddd 8#include "../utils.hpp"
9f263671
KS
9#include "event_name.hpp"
10
d73aeddd
JG
11#include <common/container-wrapper.hpp>
12#include <common/macros.hpp>
13#include <common/make-unique.hpp>
14
9f263671
KS
15#include <assert.h>
16#include <babeltrace2/babeltrace.h>
d73aeddd
JG
17#include <cstdint>
18#include <exception>
9f263671
KS
19#include <stdlib.h>
20#include <string.h>
21#include <string>
22#include <unordered_set>
23
d73aeddd
JG
24class event_name_set_operations {
25public:
26 static const char *get(const bt_value *array, std::size_t index)
27 {
28 const auto *names_entry =
29 bt_value_array_borrow_element_by_index_const(array, index);
30
31 if (bt_value_get_type(names_entry) != BT_VALUE_TYPE_STRING) {
32 throw std::runtime_error(
33 "All members of the 'names' parameter array must be strings");
34 }
35
36 return bt_value_string_get(names_entry);
37 }
38
39 static std::size_t size(const bt_value *array)
40 {
41 return bt_value_array_get_length(array);
42 }
43};
44
45class event_name_set
46 : public lttng::utils::random_access_container_wrapper<const bt_value *,
47 const char *,
48 event_name_set_operations> {
49public:
50 friend event_name_set_operations;
51
52 event_name_set() :
53 lttng::utils::random_access_container_wrapper<const bt_value *,
54 const char *,
55 event_name_set_operations>(nullptr)
56 {
57 }
58
59 event_name_set(event_name_set&& original) :
60 lttng::utils::random_access_container_wrapper<const bt_value *,
61 const char *,
62 event_name_set_operations>(
63 std::move(original._container))
64 {
65 }
66
67 event_name_set(const bt_value *names) :
68 lttng::utils::random_access_container_wrapper<const bt_value *,
69 const char *,
70 event_name_set_operations>(names)
71 {
72 if (bt_value_get_type(names) != BT_VALUE_TYPE_ARRAY) {
73 throw std::invalid_argument("'names' parameter must be an array");
74 }
75 }
76};
77
78class event_name_filter {
79public:
80 event_name_filter(bt_self_component_port_input *input_port_,
81 const event_name_set& name_set) :
82 input_port{ input_port_ }, _names{ name_set.begin(), name_set.end() }
83 {
84 }
85
86 bool event_name_is_allowed(const char *event_name) const noexcept
87 {
88 return _names.find(event_name) != _names.end();
89 }
90
9f263671 91 /* weak reference */
d73aeddd
JG
92 bt_self_component_port_input *const input_port;
93
94private:
95 const std::unordered_set<std::string> _names;
9f263671
KS
96};
97
98struct event_name_iterator_data {
d73aeddd
JG
99 event_name_iterator_data(lttng::bt2::message_iterator_ref iterator_,
100 const class event_name_filter& event_name_filter_) :
101 upstream_iterator{ std::move(iterator_) }, event_name_filter{ event_name_filter_ }
102 {
103 }
104
105 ~event_name_iterator_data()
106 {
107 }
108
109 const lttng::bt2::message_iterator_ref upstream_iterator;
110 const class event_name_filter& event_name_filter;
9f263671
KS
111};
112
d73aeddd
JG
113namespace {
114bool message_passes(const bt_message *message, const event_name_filter& event_name_filter)
115{
116 if (bt_message_get_type(message) != BT_MESSAGE_TYPE_EVENT) {
117 return true;
118 }
119
120 const bt_event *event = bt_message_event_borrow_event_const(message);
121 const bt_event_class *event_class = bt_event_borrow_class_const(event);
122 const char *event_name = bt_event_class_get_name(event_class);
123
124 if (event_name == nullptr) {
125 return false;
126 }
127
128 return event_name_filter.event_name_is_allowed(event_name);
129}
130} /* namespace */
131
9f263671
KS
132bt_component_class_initialize_method_status
133event_name_initialize(bt_self_component_filter *self_comp,
134 bt_self_component_filter_configuration *,
135 const bt_value *params,
136 void *)
137{
9f263671 138 bt_self_component_port_input *input_port;
d73aeddd
JG
139 std::unique_ptr<class event_name_filter> event_name_filter;
140
9f263671
KS
141 auto self = bt_self_component_filter_as_self_component(self_comp);
142 if (bt_self_component_filter_add_input_port(self_comp, "in", nullptr, &input_port) !=
143 BT_SELF_COMPONENT_ADD_PORT_STATUS_OK) {
144 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self,
145 "Failed to add input port");
d73aeddd 146 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
9f263671
KS
147 }
148
149 if (bt_self_component_filter_add_output_port(self_comp, "out", nullptr, nullptr) !=
150 BT_SELF_COMPONENT_ADD_PORT_STATUS_OK) {
151 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self,
152 "Failed to add output port");
d73aeddd 153 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
9f263671
KS
154 }
155
d73aeddd
JG
156 const auto names_param = bt_value_map_borrow_entry_value_const(params, "names");
157 if (names_param == nullptr) {
9f263671
KS
158 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
159 self, "'names' parameter is required");
d73aeddd 160 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
9f263671 161 }
d73aeddd
JG
162
163 try {
164 event_name_set event_names{ names_param };
165 if (event_names.empty()) {
9f263671 166 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
d73aeddd
JG
167 bt_self_component_filter_as_self_component(self_comp),
168 "'names' parameter must not be empty");
169 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
9f263671 170 }
d73aeddd
JG
171
172 event_name_filter =
173 lttng::make_unique<class event_name_filter>(input_port, event_names);
174 } catch (const std::bad_alloc&) {
175 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
176 self, "Failed to allocate memory for private component data");
177 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR;
178 } catch (const std::exception& ex) {
179 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self, "%s", ex.what());
180 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
9f263671 181 }
9f263671 182
d73aeddd
JG
183 /* Ownership of event_name is transferred to the component. */
184 bt_self_component_set_data(self, event_name_filter.release());
185 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
9f263671
KS
186}
187
188void event_name_finalize(bt_self_component_filter *self_comp)
189{
d73aeddd
JG
190 class event_name_filter *event_name_filter =
191 (class event_name_filter *) bt_self_component_get_data(
192 bt_self_component_filter_as_self_component(self_comp));
193
194 delete event_name_filter;
9f263671
KS
195}
196
197bt_message_iterator_class_initialize_method_status
198event_name_message_iterator_initialize(bt_self_message_iterator *self_message_iterator,
199 bt_self_message_iterator_configuration *,
200 bt_self_component_port_output *)
201{
d73aeddd
JG
202 const auto& event_name_filter =
203 *static_cast<class event_name_filter *>(bt_self_component_get_data(
204 bt_self_message_iterator_borrow_component(self_message_iterator)));
9f263671 205
d73aeddd 206 bt_message_iterator *raw_iterator;
9f263671 207 if (bt_message_iterator_create_from_message_iterator(
d73aeddd 208 self_message_iterator, event_name_filter.input_port, &raw_iterator) !=
9f263671 209 BT_MESSAGE_ITERATOR_CREATE_FROM_MESSAGE_ITERATOR_STATUS_OK) {
9f263671
KS
210 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
211 }
212
d73aeddd
JG
213 lttng::bt2::message_iterator_ref iterator(raw_iterator);
214 raw_iterator = nullptr;
215
216 std::unique_ptr<event_name_iterator_data> iter_data;
217 try {
218 iter_data = lttng::make_unique<event_name_iterator_data>(std::move(iterator),
219 event_name_filter);
220 } catch (const std::bad_alloc&) {
221 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
222 self_message_iterator, "Failed to allocate event_name iterator data");
223 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
224 }
9f263671 225
d73aeddd
JG
226 /* Transfer the ownership of iter_data to the iterator. */
227 bt_self_message_iterator_set_data(self_message_iterator, iter_data.release());
9f263671
KS
228 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
229}
230
231void event_name_message_iterator_finalize(bt_self_message_iterator *self_message)
232{
d73aeddd
JG
233 event_name_iterator_data *iter_data = static_cast<event_name_iterator_data *>(
234 bt_self_message_iterator_get_data(self_message));
9f263671 235
d73aeddd
JG
236 LTTNG_ASSERT(iter_data);
237 delete iter_data;
9f263671
KS
238}
239
240bt_message_iterator_class_next_method_status
241event_name_message_iterator_next(bt_self_message_iterator *self_message_iterator,
d73aeddd 242 bt_message_array_const messages_to_deliver_downstream,
9f263671 243 uint64_t,
d73aeddd 244 uint64_t *_messages_to_deliver_count)
9f263671 245{
d73aeddd
JG
246 std::uint64_t messages_to_deliver_count = 0;
247 auto *iter_data = static_cast<event_name_iterator_data *>(
248 bt_self_message_iterator_get_data(self_message_iterator));
249 const auto& event_name_filter =
250 *static_cast<class event_name_filter *>(bt_self_component_get_data(
251 bt_self_message_iterator_borrow_component(self_message_iterator)));
252
253 LTTNG_ASSERT(iter_data);
254
255 /* Retry until we have at least one message to deliver downstream. */
256 while (messages_to_deliver_count == 0) {
257 bt_message_array_const upstream_messages;
258 bt_message_iterator_next_status next_status;
259 uint64_t upstream_message_count;
260
261 next_status = bt_message_iterator_next(iter_data->upstream_iterator.get(),
262 &upstream_messages,
263 &upstream_message_count);
9f263671 264 if (next_status != BT_MESSAGE_ITERATOR_NEXT_STATUS_OK) {
d73aeddd 265 return static_cast<bt_message_iterator_class_next_method_status>(
9f263671 266 next_status);
9f263671
KS
267 }
268
d73aeddd 269 for (std::uint64_t upstream_index = 0; upstream_index < upstream_message_count;
9f263671 270 upstream_index++) {
d73aeddd
JG
271 lttng::bt2::message_const_ref upstream_message(
272 upstream_messages[upstream_index]);
273
274 if (message_passes(upstream_message.get(), event_name_filter)) {
275 /* Reference transferred to downstream message batch. */
276 messages_to_deliver_downstream[messages_to_deliver_count] =
277 upstream_message.release();
278 messages_to_deliver_count++;
9f263671
KS
279 }
280 }
281 }
282
d73aeddd
JG
283 *_messages_to_deliver_count = messages_to_deliver_count;
284 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
9f263671 285}
This page took 0.035416 seconds and 4 git commands to generate.