2 * Copyright (C) 2023 Kienan Stewart <kstewart@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include "event_name.hpp"
11 #include <babeltrace2/babeltrace.h>
15 #include <unordered_set>
18 std::unordered_set
<std::string
> names
;
19 const bt_value
*names_value
;
21 bt_self_component_port_input
*input_port
;
24 struct event_name_iterator_data
{
25 struct event_name
*event_name
;
26 bt_message_iterator
*iterator
;
29 bt_component_class_initialize_method_status
30 event_name_initialize(bt_self_component_filter
*self_comp
,
31 bt_self_component_filter_configuration
*,
32 const bt_value
*params
,
35 bt_component_class_initialize_method_status status
;
36 bt_self_component_port_input
*input_port
;
37 struct event_name
*event_name
;
38 auto self
= bt_self_component_filter_as_self_component(self_comp
);
39 if (bt_self_component_filter_add_input_port(self_comp
, "in", nullptr, &input_port
) !=
40 BT_SELF_COMPONENT_ADD_PORT_STATUS_OK
) {
41 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self
,
42 "Failed to add input port");
43 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
47 if (bt_self_component_filter_add_output_port(self_comp
, "out", nullptr, nullptr) !=
48 BT_SELF_COMPONENT_ADD_PORT_STATUS_OK
) {
49 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(self
,
50 "Failed to add output port");
51 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
55 event_name
= new (std::nothrow
) struct event_name
;
56 if (event_name
== nullptr) {
57 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
58 self
, "Failed to allocate memory for private component data");
59 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR
;
63 event_name
->input_port
= input_port
;
64 event_name
->names_value
= bt_value_map_borrow_entry_value_const(params
, "names");
65 if (event_name
->names_value
== nullptr) {
66 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
67 self
, "'names' parameter is required");
68 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
71 if (bt_value_get_type(event_name
->names_value
) != BT_VALUE_TYPE_ARRAY
) {
72 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
73 self
, "'names' parameter must be an array");
74 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
77 if (bt_value_array_is_empty(event_name
->names_value
)) {
78 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
79 bt_self_component_filter_as_self_component(self_comp
),
80 "'names' parameter must not be empty");
81 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
84 for (uint64_t index
= 0; index
< bt_value_array_get_length(event_name
->names_value
);
86 const bt_value
*names_entry
= bt_value_array_borrow_element_by_index_const(
87 event_name
->names_value
, index
);
88 if (bt_value_get_type(names_entry
) != BT_VALUE_TYPE_STRING
) {
89 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
90 self
, "All members of the 'names' parameter array must be strings");
91 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
94 event_name
->names
.emplace(bt_value_string_get(names_entry
));
96 bt_value_get_ref(event_name
->names_value
);
97 bt_self_component_set_data(self
, event_name
);
98 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
107 void event_name_finalize(bt_self_component_filter
*self_comp
)
109 struct event_name
*event_name
= (struct event_name
*) bt_self_component_get_data(
110 bt_self_component_filter_as_self_component(self_comp
));
111 bt_value_put_ref(event_name
->names_value
);
115 bt_message_iterator_class_initialize_method_status
116 event_name_message_iterator_initialize(bt_self_message_iterator
*self_message_iterator
,
117 bt_self_message_iterator_configuration
*,
118 bt_self_component_port_output
*)
120 struct event_name
*event_name
= (struct event_name
*) bt_self_component_get_data(
121 bt_self_message_iterator_borrow_component(self_message_iterator
));
124 struct event_name_iterator_data
*iter_data
=
125 (struct event_name_iterator_data
*) malloc(sizeof(struct event_name_iterator_data
));
127 if (iter_data
== nullptr) {
128 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
130 iter_data
->event_name
= event_name
;
132 if (bt_message_iterator_create_from_message_iterator(
133 self_message_iterator
, event_name
->input_port
, &iter_data
->iterator
) !=
134 BT_MESSAGE_ITERATOR_CREATE_FROM_MESSAGE_ITERATOR_STATUS_OK
) {
136 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
139 bt_self_message_iterator_set_data(self_message_iterator
, iter_data
);
141 return BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK
;
144 void event_name_message_iterator_finalize(bt_self_message_iterator
*self_message
)
146 struct event_name_iterator_data
*iter_data
=
147 (struct event_name_iterator_data
*) bt_self_message_iterator_get_data(self_message
);
150 bt_message_iterator_put_ref(iter_data
->iterator
);
154 static bool message_passes(const bt_message
*message
, const std::unordered_set
<std::string
>& names
)
156 if (bt_message_get_type(message
) != BT_MESSAGE_TYPE_EVENT
) {
160 const bt_event
*event
= bt_message_event_borrow_event_const(message
);
161 const bt_event_class
*event_class
= bt_event_borrow_class_const(event
);
162 const char *event_name
= bt_event_class_get_name(event_class
);
164 if (event_name
== nullptr) {
168 if (names
.find(event_name
) != names
.end()) {
175 bt_message_iterator_class_next_method_status
176 event_name_message_iterator_next(bt_self_message_iterator
*self_message_iterator
,
177 bt_message_array_const messages
,
181 bt_message_array_const upstream_messages
;
182 uint64_t upstream_message_count
;
184 bt_message_iterator_next_status next_status
;
185 bt_message_iterator_class_next_method_status status
=
186 BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK
;
187 struct event_name_iterator_data
*iter_data
=
188 (struct event_name_iterator_data
*) bt_self_message_iterator_get_data(
189 self_message_iterator
);
190 struct event_name
*event_name
= (struct event_name
*) bt_self_component_get_data(
191 bt_self_message_iterator_borrow_component(self_message_iterator
));
197 next_status
= bt_message_iterator_next(
198 iter_data
->iterator
, &upstream_messages
, &upstream_message_count
);
199 if (next_status
!= BT_MESSAGE_ITERATOR_NEXT_STATUS_OK
) {
200 status
= static_cast<bt_message_iterator_class_next_method_status
>(
205 for (uint64_t upstream_index
= 0; upstream_index
< upstream_message_count
;
207 const bt_message
*upstream_message
= upstream_messages
[upstream_index
];
208 if (message_passes(upstream_message
, event_name
->names
)) {
209 messages
[index
] = upstream_message
;
212 bt_message_put_ref(upstream_message
);