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