Run clang-format on the whole tree
[lttng-tools.git] / src / bin / lttng-sessiond / ust-registry-channel.cpp
CommitLineData
d7bfb9b0
JG
1/*
2 * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
d7bfb9b0 8#include "ust-app.hpp"
28ab034a 9#include "ust-registry-channel.hpp"
d7bfb9b0
JG
10#include "ust-registry-event.hpp"
11
12#include <common/error.hpp>
13#include <common/exception.hpp>
14#include <common/hashtable/utils.hpp>
15#include <common/make-unique-wrapper.hpp>
24ed18f2 16#include <common/make-unique.hpp>
d7bfb9b0
JG
17#include <common/urcu.hpp>
18
19namespace lst = lttng::sessiond::trace;
20namespace lsu = lttng::sessiond::ust;
21
22namespace {
23bool is_max_event_id(uint32_t id)
24{
25 return id == UINT32_MAX;
26}
27
28unsigned long ht_hash_event(const void *_key, unsigned long seed)
29{
30 uint64_t hashed_key;
31 const lttng::sessiond::ust::registry_event *key =
28ab034a 32 (lttng::sessiond::ust::registry_event *) _key;
d7bfb9b0
JG
33
34 LTTNG_ASSERT(key);
35
36 hashed_key = (uint64_t) hash_key_str(key->name.c_str(), seed);
37
38 return hash_key_u64(&hashed_key, seed);
39}
40
41/*
42 * Hash table match function for event in the registry.
43 */
44int ht_match_event(struct cds_lfht_node *node, const void *_key)
45{
46 const lttng::sessiond::ust::registry_event *key;
47 lttng::sessiond::ust::registry_event *event;
48
49 LTTNG_ASSERT(node);
50 LTTNG_ASSERT(_key);
51
f139a4f9 52 event = lttng::utils::container_of(node, &lttng::sessiond::ust::registry_event::_node);
d7bfb9b0
JG
53 key = (lttng::sessiond::ust::registry_event *) _key;
54
55 /* It has to be a perfect match. First, compare the event names. */
56 if (event->name != key->name) {
57 goto no_match;
58 }
59
60 /* Compare log levels. */
61 if (event->log_level != key->log_level) {
62 goto no_match;
63 }
64
65 /* Compare the arrays of fields. */
66 if (*event->payload != *key->payload) {
67 goto no_match;
68 }
69
70 /* Compare model URI. */
71 if (event->model_emf_uri != key->model_emf_uri) {
72 goto no_match;
73 }
74
75 /* Match */
76 return 1;
77
78no_match:
79 return 0;
80}
24ed18f2 81
28ab034a
JG
82lst::type::cuptr create_event_header(const lst::abi& trace_abi,
83 lst::stream_class::header_type header_type)
24ed18f2
JG
84{
85 lst::structure_type::fields event_header_fields;
86
87 if (header_type == lst::stream_class::header_type::COMPACT) {
88 auto enum_mappings = std::make_shared<lst::unsigned_enumeration_type::mappings>();
45110cdd 89 lst::unsigned_enumeration_type::mapping compact_mapping{
28ab034a
JG
90 "compact", lst::unsigned_enumeration_type::mapping::range_t(0, 30)
91 };
92 lst::unsigned_enumeration_type::mapping extended_mapping{ "extended", 31 };
24ed18f2 93
45110cdd
JG
94 enum_mappings->emplace_back(compact_mapping);
95 enum_mappings->emplace_back(extended_mapping);
24ed18f2 96
28ab034a
JG
97 lst::type::cuptr choice_enum = lttng::make_unique<lst::unsigned_enumeration_type>(
98 1,
99 trace_abi.byte_order,
100 5,
101 lst::integer_type::base::DECIMAL,
102 std::move(enum_mappings),
103 std::initializer_list<lst::integer_type::role>(
104 { lst::integer_type::role::EVENT_RECORD_CLASS_ID }));
24ed18f2 105
28ab034a
JG
106 lst::variant_type<
107 lst::unsigned_enumeration_type::mapping::range_t::range_integer_t>::choices
108 variant_choices;
24ed18f2
JG
109
110 lst::structure_type::fields compact_fields;
28ab034a
JG
111 compact_fields.emplace_back(lttng::make_unique<lst::field>(
112 "timestamp",
113 lttng::make_unique<lst::integer_type>(
114 1,
115 trace_abi.byte_order,
116 27,
117 lst::integer_type::signedness::UNSIGNED,
118 lst::integer_type::base::DECIMAL,
119 std::initializer_list<lst::integer_type::role>(
120 { lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP }))));
121
122 auto compact_type =
123 lttng::make_unique<lst::structure_type>(0, std::move(compact_fields));
45110cdd 124 variant_choices.emplace_back(std::move(compact_mapping), std::move(compact_type));
24ed18f2
JG
125
126 lst::structure_type::fields extended_fields;
28ab034a
JG
127 extended_fields.emplace_back(lttng::make_unique<lst::field>(
128 "id",
129 lttng::make_unique<lst::integer_type>(
130 trace_abi.uint32_t_alignment,
131 trace_abi.byte_order,
132 32,
133 lst::integer_type::signedness::UNSIGNED,
134 lst::integer_type::base::DECIMAL,
135 std::initializer_list<lst::integer_type::role>(
136 { lst::integer_type::role::EVENT_RECORD_CLASS_ID }))));
137 extended_fields.emplace_back(lttng::make_unique<lst::field>(
138 "timestamp",
139 lttng::make_unique<lst::integer_type>(
140 trace_abi.uint64_t_alignment,
141 trace_abi.byte_order,
142 64,
143 lst::integer_type::signedness::UNSIGNED,
144 lst::integer_type::base::DECIMAL,
145 std::initializer_list<lst::integer_type::role>(
146 { lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP }))));
147
148 lst::type::cuptr extended_type =
149 lttng::make_unique<lst::structure_type>(0, std::move(extended_fields));
45110cdd 150 variant_choices.emplace_back(std::move(extended_mapping), std::move(extended_type));
24ed18f2 151
45110cdd 152 auto variant = lttng::make_unique<lst::variant_type<
28ab034a
JG
153 lst::unsigned_enumeration_type::mapping::range_t::range_integer_t>>(
154 0,
155 lst::field_location(lst::field_location::root::EVENT_RECORD_HEADER,
156 { "id" }),
157 std::move(variant_choices));
24ed18f2 158
24ed18f2 159 event_header_fields.emplace_back(
28ab034a
JG
160 lttng::make_unique<lst::field>("id", std::move(choice_enum)));
161 event_header_fields.emplace_back(
162 lttng::make_unique<lst::field>("v", std::move(variant)));
24ed18f2
JG
163 } else {
164 auto enum_mappings = std::make_shared<lst::unsigned_enumeration_type::mappings>();
28ab034a
JG
165 lst::unsigned_enumeration_type::mapping compact_mapping{
166 "compact", lst::unsigned_enumeration_type::mapping::range_t(0, 65534)
167 };
168 lst::unsigned_enumeration_type::mapping extended_mapping{ "extended", 65535 };
45110cdd
JG
169 enum_mappings->emplace_back(compact_mapping);
170 enum_mappings->emplace_back(extended_mapping);
24ed18f2 171
45110cdd 172 auto choice_enum = lttng::make_unique<lst::unsigned_enumeration_type>(
28ab034a
JG
173 trace_abi.uint16_t_alignment,
174 trace_abi.byte_order,
175 16,
176 lst::integer_type::base::DECIMAL,
177 std::move(enum_mappings),
178 std::initializer_list<lst::integer_type::role>(
179 { lst::integer_type::role::EVENT_RECORD_CLASS_ID }));
180
181 lst::variant_type<
182 lst::unsigned_enumeration_type::mapping::range_t::range_integer_t>::choices
183 variant_choices;
24ed18f2
JG
184
185 lst::structure_type::fields compact_fields;
28ab034a
JG
186 compact_fields.emplace_back(lttng::make_unique<lst::field>(
187 "timestamp",
188 lttng::make_unique<lst::integer_type>(
189 trace_abi.uint32_t_alignment,
190 trace_abi.byte_order,
191 32,
192 lst::integer_type::signedness::UNSIGNED,
193 lst::integer_type::base::DECIMAL,
194 std::initializer_list<lst::integer_type::role>(
195 { lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP }))));
196
197 lst::type::cuptr compact_type =
198 lttng::make_unique<lst::structure_type>(0, std::move(compact_fields));
45110cdd 199 variant_choices.emplace_back(std::move(compact_mapping), std::move(compact_type));
24ed18f2
JG
200
201 lst::structure_type::fields extended_fields;
28ab034a
JG
202 extended_fields.emplace_back(lttng::make_unique<lst::field>(
203 "id",
204 lttng::make_unique<lst::integer_type>(
205 trace_abi.uint32_t_alignment,
206 trace_abi.byte_order,
207 32,
208 lst::integer_type::signedness::UNSIGNED,
209 lst::integer_type::base::DECIMAL,
210 std::initializer_list<lst::integer_type::role>(
211 { lst::integer_type::role::EVENT_RECORD_CLASS_ID }))));
212 extended_fields.emplace_back(lttng::make_unique<lst::field>(
213 "timestamp",
214 lttng::make_unique<lst::integer_type>(
215 trace_abi.uint64_t_alignment,
216 trace_abi.byte_order,
217 64,
218 lst::integer_type::signedness::UNSIGNED,
219 lst::integer_type::base::DECIMAL,
220 std::initializer_list<lst::integer_type::role>(
221 { lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP }))));
222
223 auto extended_type =
224 lttng::make_unique<lst::structure_type>(0, std::move(extended_fields));
45110cdd 225 variant_choices.emplace_back(std::move(extended_mapping), std::move(extended_type));
24ed18f2 226
45110cdd 227 auto variant = lttng::make_unique<lst::variant_type<
28ab034a
JG
228 lst::unsigned_enumeration_type::mapping::range_t::range_integer_t>>(
229 0,
230 lst::field_location(lst::field_location::root::EVENT_RECORD_HEADER,
231 { "id" }),
232 std::move(variant_choices));
24ed18f2 233
45110cdd 234 event_header_fields.emplace_back(
28ab034a 235 lttng::make_unique<lst::field>("id", std::move(choice_enum)));
24ed18f2 236 event_header_fields.emplace_back(
28ab034a 237 lttng::make_unique<lst::field>("v", std::move(variant)));
24ed18f2
JG
238 }
239
240 return lttng::make_unique<lst::structure_type>(0, std::move(event_header_fields));
241}
242
243lst::type::cuptr create_packet_context(const lst::abi& trace_abi)
244{
245 lst::structure_type::fields packet_context_fields;
246
247 /* uint64_t timestamp_begin */
28ab034a
JG
248 packet_context_fields.emplace_back(lttng::make_unique<lst::field>(
249 "timestamp_begin",
250 lttng::make_unique<lst::integer_type>(
251 trace_abi.uint64_t_alignment,
252 trace_abi.byte_order,
253 64,
254 lst::integer_type::signedness::UNSIGNED,
255 lst::integer_type::base::DECIMAL,
256 std::initializer_list<lst::integer_type::role>(
257 { lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP }))));
24ed18f2
JG
258
259 /* uint64_t timestamp_end */
28ab034a
JG
260 packet_context_fields.emplace_back(lttng::make_unique<lst::field>(
261 "timestamp_end",
262 lttng::make_unique<lst::integer_type>(
263 trace_abi.uint64_t_alignment,
264 trace_abi.byte_order,
265 64,
266 lst::integer_type::signedness::UNSIGNED,
267 lst::integer_type::base::DECIMAL,
268 std::initializer_list<lst::integer_type::role>(
269 { lst::integer_type::role::PACKET_END_DEFAULT_CLOCK_TIMESTAMP }))));
24ed18f2
JG
270
271 /* uint64_t content_size */
28ab034a
JG
272 packet_context_fields.emplace_back(lttng::make_unique<lst::field>(
273 "content_size",
274 lttng::make_unique<lst::integer_type>(
275 trace_abi.uint64_t_alignment,
276 trace_abi.byte_order,
277 64,
278 lst::integer_type::signedness::UNSIGNED,
279 lst::integer_type::base::DECIMAL,
280 std::initializer_list<lst::integer_type::role>(
281 { lst::integer_type::role::PACKET_CONTENT_LENGTH }))));
24ed18f2
JG
282
283 /* uint64_t packet_size */
28ab034a
JG
284 packet_context_fields.emplace_back(lttng::make_unique<lst::field>(
285 "packet_size",
286 lttng::make_unique<lst::integer_type>(
287 trace_abi.uint64_t_alignment,
288 trace_abi.byte_order,
289 64,
290 lst::integer_type::signedness::UNSIGNED,
291 lst::integer_type::base::DECIMAL,
292 std::initializer_list<lst::integer_type::role>(
293 { lst::integer_type::role::PACKET_TOTAL_LENGTH }))));
24ed18f2
JG
294
295 /* uint64_t packet_seq_num */
28ab034a
JG
296 packet_context_fields.emplace_back(lttng::make_unique<lst::field>(
297 "packet_seq_num",
298 lttng::make_unique<lst::integer_type>(
299 trace_abi.uint64_t_alignment,
300 trace_abi.byte_order,
301 64,
302 lst::integer_type::signedness::UNSIGNED,
303 lst::integer_type::base::DECIMAL,
304 std::initializer_list<lst::integer_type::role>(
305 { lst::integer_type::role::PACKET_SEQUENCE_NUMBER }))));
24ed18f2
JG
306
307 /* unsigned long events_discarded */
28ab034a
JG
308 packet_context_fields.emplace_back(lttng::make_unique<lst::field>(
309 "events_discarded",
310 lttng::make_unique<lst::integer_type>(
311 trace_abi.long_alignment,
312 trace_abi.byte_order,
313 trace_abi.bits_per_long,
314 lst::integer_type::signedness::UNSIGNED,
315 lst::integer_type::base::DECIMAL,
316 std::initializer_list<lst::integer_type::role>(
317 { lst::integer_type::role::
318 DISCARDED_EVENT_RECORD_COUNTER_SNAPSHOT }))));
24ed18f2
JG
319
320 /* uint32_t cpu_id */
28ab034a
JG
321 packet_context_fields.emplace_back(lttng::make_unique<lst::field>(
322 "cpu_id",
323 lttng::make_unique<lst::integer_type>(trace_abi.uint32_t_alignment,
324 trace_abi.byte_order,
325 32,
326 lst::integer_type::signedness::UNSIGNED,
327 lst::integer_type::base::DECIMAL)));
24ed18f2
JG
328
329 return lttng::make_unique<lst::structure_type>(0, std::move(packet_context_fields));
330}
d7bfb9b0
JG
331}; /* namespace */
332
28ab034a
JG
333lsu::registry_channel::registry_channel(
334 unsigned int channel_id,
335 const lst::abi& trace_abi,
336 std::string in_default_clock_class_name,
337 lsu::registry_channel::registered_listener_fn channel_registered_listener,
338 lsu::registry_channel::event_added_listener_fn event_added_listener) :
24ed18f2 339 lst::stream_class(channel_id,
28ab034a
JG
340 lst::stream_class::header_type::LARGE,
341 std::move(in_default_clock_class_name)),
342 _key{ -1ULL },
343 _consumer_key{ -1ULL },
344 _next_event_id{ 0 },
345 _is_registered_listener{ channel_registered_listener },
346 _event_added_listener{ event_added_listener },
347 _is_registered{ false }
d7bfb9b0
JG
348{
349 _events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING);
350 if (!_events) {
351 LTTNG_THROW_POSIX("Failed to allocate urcu events hash table", ENOMEM);
352 }
353
354 /* Set custom match function. */
355 _events->match_fct = ht_match_event;
356 _events->hash_fct = ht_hash_event;
36038679
JG
357
358 _rcu_head = {};
359 /*
360 * Node's key is initialized by the channel's parent session. Its value is irrelevant to the
361 * channel object itself.
362 */
363 _node = {};
24ed18f2
JG
364
365 _packet_context = create_packet_context(trace_abi);
366 _event_header = create_event_header(trace_abi, header_type_);
d7bfb9b0
JG
367}
368
28ab034a
JG
369void lsu::registry_channel::add_event(int session_objd,
370 int channel_objd,
371 std::string name,
372 std::string signature,
373 std::vector<lst::field::cuptr> event_fields,
374 int loglevel_value,
375 nonstd::optional<std::string> model_emf_uri,
376 lttng_buffer_type buffer_type,
377 const ust_app& app,
378 uint32_t& out_event_id)
d7bfb9b0
JG
379{
380 uint32_t event_id;
381 struct cds_lfht_node *nptr;
382 lttng::urcu::read_lock_guard read_lock_guard;
383
384 /*
385 * This should not happen but since it comes from the UST tracer, an
386 * external party, don't assert and simply validate values.
387 */
388 if (session_objd < 0) {
389 LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format(
28ab034a
JG
390 "Invalid session object descriptor provided by application: session descriptor = {}, app = {}",
391 session_objd,
392 app));
d7bfb9b0
JG
393 }
394
395 if (channel_objd < 0) {
396 LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format(
28ab034a
JG
397 "Invalid channel object descriptor provided by application: channel descriptor = {}, app = {}",
398 channel_objd,
399 app));
d7bfb9b0
JG
400 }
401
402 /* Check if we've reached the maximum possible id. */
403 if (is_max_event_id(_next_event_id)) {
404 LTTNG_THROW_ERROR(fmt::format(
28ab034a 405 "Failed to allocate new event id (id would overflow): app = {}", app));
d7bfb9b0
JG
406 }
407
408 auto event = lttng::make_unique_wrapper<lsu::registry_event, registry_event_destroy>(
28ab034a
JG
409 new lsu::registry_event(_next_event_id,
410 id,
411 session_objd,
412 channel_objd,
413 std::move(name),
414 std::move(signature),
415 std::move(event_fields),
416 loglevel_value,
d7bfb9b0
JG
417 std::move(model_emf_uri)));
418
419 DBG3("%s", fmt::format("UST registry creating event: event = {}", *event).c_str());
420
421 /*
422 * This is an add unique with a custom match function for event. The node
423 * are matched using the event name and signature.
424 */
28ab034a
JG
425 nptr = cds_lfht_add_unique(_events->ht,
426 _events->hash_fct(event.get(), lttng_ht_seed),
427 _events->match_fct,
428 event.get(),
429 &event->_node);
f139a4f9 430 if (nptr != &event->_node) {
d7bfb9b0
JG
431 if (buffer_type == LTTNG_BUFFER_PER_UID) {
432 /*
433 * This is normal, we just have to send the event id of the
434 * returned node.
435 */
f139a4f9 436 const auto existing_event = lttng::utils::container_of(
28ab034a 437 nptr, &lttng::sessiond::ust::registry_event::_node);
d7bfb9b0
JG
438 event_id = existing_event->id;
439 } else {
440 LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format(
28ab034a
JG
441 "UST registry create event add unique failed for event: event = {}",
442 *event));
d7bfb9b0
JG
443 }
444 } else {
445 const auto& event_ref = *event;
446
447 /* Ownership transferred to _events hash table. */
448 event.release();
449
450 /* Request next event id if the node was successfully added. */
451 event_id = event_ref.id;
452
453 /*
454 * Only increment the next id here since we don't want to waste an ID when the event
455 * matches an existing one.
456 */
457 _next_event_id++;
458 _event_added_listener(*this, event_ref);
459 }
460
461 out_event_id = event_id;
462}
463
464lsu::registry_channel::~registry_channel()
465{
466 lttng_ht_destroy(_events);
467}
468
28ab034a 469const lttng::sessiond::trace::type *lsu::registry_channel::event_context() const
d7bfb9b0
JG
470{
471 LTTNG_ASSERT(_is_registered);
4bcf2294 472 return lst::stream_class::event_context();
d7bfb9b0
JG
473}
474
4bcf2294 475void lsu::registry_channel::event_context(lttng::sessiond::trace::type::cuptr context)
d7bfb9b0
JG
476{
477 /* Must only be set once, on the first channel registration provided by an application. */
24ed18f2
JG
478 LTTNG_ASSERT(!_event_context);
479 _event_context = std::move(context);
d7bfb9b0
JG
480}
481
482bool lsu::registry_channel::is_registered() const
483{
484 return _is_registered;
485}
486
487void lsu::registry_channel::set_as_registered()
488{
489 if (!_is_registered) {
490 _is_registered = true;
491 _is_registered_listener(*this);
492 }
493}
494
495void lsu::registry_channel::_accept_on_event_classes(
28ab034a 496 lttng::sessiond::trace::trace_class_visitor& visitor) const
d7bfb9b0
JG
497{
498 std::vector<const lttng::sessiond::ust::registry_event *> sorted_event_classes;
499
500 {
501 lttng::urcu::read_lock_guard read_lock_guard;
502 struct lttng_ht_iter iter;
503 const lttng::sessiond::ust::registry_event *event;
504
505 DIAGNOSTIC_PUSH
506 DIAGNOSTIC_IGNORE_INVALID_OFFSETOF
28ab034a 507 cds_lfht_for_each_entry (_events->ht, &iter.iter, event, _node) {
d7bfb9b0
JG
508 sorted_event_classes.emplace_back(event);
509 }
510 DIAGNOSTIC_POP
511 }
512
28ab034a
JG
513 std::sort(sorted_event_classes.begin(),
514 sorted_event_classes.end(),
515 [](const lttng::sessiond::ust::registry_event *a,
516 const lttng::sessiond::ust::registry_event *b) { return a->id < b->id; });
d7bfb9b0
JG
517
518 for (const auto event : sorted_event_classes) {
519 event->accept(visitor);
520 }
521}
This page took 0.047726 seconds and 4 git commands to generate.