fix: relayd: unaligned access in trace_chunk_registry_ht_key_hash
[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) :
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
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()
106 {
107 }
108
109 const lttng::bt2::message_iterator_ref upstream_iterator;
110 const class event_name_filter& event_name_filter;
111 };
112
113 namespace {
114 bool 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
132 bt_component_class_initialize_method_status
133 event_name_initialize(bt_self_component_filter *self_comp,
134 bt_self_component_filter_configuration *,
135 const bt_value *params,
136 void *)
137 {
138 bt_self_component_port_input *input_port;
139 std::unique_ptr<class event_name_filter> event_name_filter;
140
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");
146 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
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");
153 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
154 }
155
156 const auto names_param = bt_value_map_borrow_entry_value_const(params, "names");
157 if (names_param == nullptr) {
158 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
159 self, "'names' parameter is required");
160 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
161 }
162
163 try {
164 event_name_set event_names{ names_param };
165 if (event_names.empty()) {
166 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
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;
170 }
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;
181 }
182
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;
186 }
187
188 void event_name_finalize(bt_self_component_filter *self_comp)
189 {
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;
195 }
196
197 bt_message_iterator_class_initialize_method_status
198 event_name_message_iterator_initialize(bt_self_message_iterator *self_message_iterator,
199 bt_self_message_iterator_configuration *,
200 bt_self_component_port_output *)
201 {
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)));
205
206 bt_message_iterator *raw_iterator;
207 if (bt_message_iterator_create_from_message_iterator(
208 self_message_iterator, event_name_filter.input_port, &raw_iterator) !=
209 BT_MESSAGE_ITERATOR_CREATE_FROM_MESSAGE_ITERATOR_STATUS_OK) {
210 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR;
211 }
212
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 }
225
226 /* Transfer the ownership of iter_data to the iterator. */
227 bt_self_message_iterator_set_data(self_message_iterator, iter_data.release());
228 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK;
229 }
230
231 void event_name_message_iterator_finalize(bt_self_message_iterator *self_message)
232 {
233 event_name_iterator_data *iter_data = static_cast<event_name_iterator_data *>(
234 bt_self_message_iterator_get_data(self_message));
235
236 LTTNG_ASSERT(iter_data);
237 delete iter_data;
238 }
239
240 bt_message_iterator_class_next_method_status
241 event_name_message_iterator_next(bt_self_message_iterator *self_message_iterator,
242 bt_message_array_const messages_to_deliver_downstream,
243 uint64_t,
244 uint64_t *_messages_to_deliver_count)
245 {
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);
264 if (next_status != BT_MESSAGE_ITERATOR_NEXT_STATUS_OK) {
265 return static_cast<bt_message_iterator_class_next_method_status>(
266 next_status);
267 }
268
269 for (std::uint64_t upstream_index = 0; upstream_index < upstream_message_count;
270 upstream_index++) {
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++;
279 }
280 }
281 }
282
283 *_messages_to_deliver_count = messages_to_deliver_count;
284 return BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK;
285 }
This page took 0.038482 seconds and 4 git commands to generate.