Fix: sessiond: tsdl: don't prepend underscore for stream_id
[lttng-tools.git] / src / bin / lttng-sessiond / ust-field-convert.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
8#include "ust-field-convert.hpp"
9
10#include <common/make-unique.hpp>
11
12#include <unordered_map>
13
14namespace lst = lttng::sessiond::trace;
15namespace lsu = lttng::sessiond::ust;
16namespace {
17
18/*
19 * Type enclosing the session information that may be required during the decoding
20 * of the lttng_ust_ctl_field array provided by applications on registration of
21 * an event.
22 */
23class session_attributes {
24public:
25 using registry_enum_getter_fn =
26 std::function<lsu::registry_enum::const_rcu_protected_reference(
27 const char *name, uint64_t id)>;
28
29 session_attributes(registry_enum_getter_fn reg_enum_getter,
30 lst::byte_order native_trace_byte_order) :
31 get_registry_enum{reg_enum_getter}, _native_trace_byte_order{native_trace_byte_order}
32 {
33 }
34
35 const registry_enum_getter_fn get_registry_enum;
36 const lst::byte_order _native_trace_byte_order;
37};
38
39/* Used to publish fields on which a field being decoded has an implicit dependency. */
40using publish_field_fn = std::function<void(lst::field::cuptr)>;
41
42lst::type::cuptr create_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
43 const lttng_ust_ctl_field *end,
44 const session_attributes& session_attributes,
45 const lttng_ust_ctl_field **next_ust_ctl_field,
46 publish_field_fn publish_field);
47
48void create_field_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
49 const lttng_ust_ctl_field *end,
50 const session_attributes& session_attributes,
51 const lttng_ust_ctl_field **next_ust_ctl_field,
52 publish_field_fn publish_field);
53
54template <class UstCtlEncodingType>
55enum lst::null_terminated_string_type::encoding ust_ctl_encoding_to_string_field_encoding(UstCtlEncodingType encoding)
56{
57 static const std::unordered_map<UstCtlEncodingType, enum lst::null_terminated_string_type::encoding>
58 encoding_conversion_map = {
59 {(UstCtlEncodingType) lttng_ust_ctl_encode_ASCII,
60 lst::null_terminated_string_type::encoding::ASCII},
61 {(UstCtlEncodingType) lttng_ust_ctl_encode_UTF8,
62 lst::null_terminated_string_type::encoding::UTF8},
63 };
64
65 const auto encoding_it = encoding_conversion_map.find(encoding);
66 if (encoding_it == encoding_conversion_map.end()) {
67 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
68 "Unknown lttng_ust_ctl_string_encodings value `{}` encountered when decoding integer field",
69 encoding));
70 }
71
72 return encoding_it->second;
73}
74
75template <class UstCtlBaseType>
76enum lst::integer_type::base ust_ctl_base_to_integer_field_base(UstCtlBaseType base)
77{
78 static const std::unordered_map<UstCtlBaseType, enum lst::integer_type::base>
79 base_conversion_map = {{2, lst::integer_type::base::BINARY},
80 {8, lst::integer_type::base::OCTAL},
81 {10, lst::integer_type::base::DECIMAL},
82 {16, lst::integer_type::base::HEXADECIMAL}};
83
84 const auto base_it = base_conversion_map.find(base);
85 if (base_it == base_conversion_map.end()) {
86 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
87 "Unknown integer base value `{}` encountered when decoding integer field",
88 base));
89 }
90
91 return base_it->second;
92}
93
94lst::type::cuptr create_integer_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
95 const lttng_ust_ctl_field *end,
96 const session_attributes& session_attributes,
97 const lttng_ust_ctl_field **next_ust_ctl_field)
98{
99 if (current >= end) {
100 LTTNG_THROW_PROTOCOL_ERROR(
101 fmt::format("End of {} array reached unexpectedly during decoding",
102 typeid(*current)));
103 }
104
105 const auto base = ust_ctl_base_to_integer_field_base(current->type.u.integer.base);
106 const auto signedness = current->type.u.integer.signedness ?
107 lst::integer_type::signedness::SIGNED :
108 lst::integer_type::signedness::UNSIGNED;
109 const auto byte_order = current->type.u.integer.reverse_byte_order ?
110 lst::type::reverse_byte_order(session_attributes._native_trace_byte_order) :
111 session_attributes._native_trace_byte_order;
112
113 *next_ust_ctl_field = current + 1;
114
115 return lttng::make_unique<const lst::integer_type>(current->type.u.integer.alignment,
116 byte_order, current->type.u.integer.size, signedness, base);
117}
118
119lst::type::cuptr create_floating_point_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
120 const lttng_ust_ctl_field *end,
121 const session_attributes& session_attributes,
122 const lttng_ust_ctl_field **next_ust_ctl_field)
123{
124 if (current >= end) {
125 LTTNG_THROW_PROTOCOL_ERROR(
126 fmt::format("End of {} array reached unexpectedly during decoding",
127 typeid(*current)));
128 }
129
130 *next_ust_ctl_field = current + 1;
131
132 const auto byte_order = current->type.u._float.reverse_byte_order ?
133 lst::type::reverse_byte_order(session_attributes._native_trace_byte_order) :
134 session_attributes._native_trace_byte_order;
135
136 try {
137 return lttng::make_unique<const lst::floating_point_type>(
138 current->type.u._float.alignment, byte_order,
139 current->type.u._float.exp_dig, current->type.u._float.mant_dig);
140 } catch (lttng::invalid_argument_error& ex) {
141 LTTNG_THROW_PROTOCOL_ERROR(fmt::format("Invalid floating point attribute in {}: {}",
142 typeid(*current), ex.what()));
143 }
144}
145
146lst::type::cuptr create_enumeration_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
147 const lttng_ust_ctl_field *end,
148 const session_attributes& session_attributes,
149 const lttng_ust_ctl_field **next_ust_ctl_field)
150{
151 if (current >= end) {
152 LTTNG_THROW_PROTOCOL_ERROR(
153 fmt::format("End of {} array reached unexpectedly during decoding",
154 typeid(*current)));
155 }
156
157 uint64_t enumeration_id;
158 const auto& enum_uctl_field = *current;
159 const char *enumeration_name;
160 const auto *enum_container_uctl_type =
161 &current->type.u.legacy.basic.enumeration.container_type;
162
163 if (enum_uctl_field.type.atype == lttng_ust_ctl_atype_enum_nestable) {
164 /* Nestable enumeration fields are followed by their container type. */
165 ++current;
166 if (current >= end) {
167 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
168 "Array of {} is too short to contain nestable enumeration's container",
169 typeid(*current)));
170 }
171
172 if (current->type.atype != lttng_ust_ctl_atype_integer) {
173 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
174 "Invalid type of nestable enum container: type id = {}",
175 current->type.atype));
176 }
177
178 enum_container_uctl_type = &current->type.u.integer;
179 enumeration_id = enum_uctl_field.type.u.enum_nestable.id;
180 enumeration_name = enum_uctl_field.type.u.enum_nestable.name;
181 } else {
182 enumeration_id = enum_uctl_field.type.u.legacy.basic.enumeration.id;
183 enumeration_name = enum_uctl_field.type.u.legacy.basic.enumeration.name;
184 }
185
186 *next_ust_ctl_field = current + 1;
187
188 const auto base = ust_ctl_base_to_integer_field_base(enum_container_uctl_type->base);
189 const auto byte_order = enum_container_uctl_type->reverse_byte_order ?
190 lst::integer_type::reverse_byte_order(
191 session_attributes._native_trace_byte_order) :
192 session_attributes._native_trace_byte_order;
d7bfb9b0
JG
193
194 if (enum_container_uctl_type->signedness) {
195 const auto& enum_registry = static_cast<const lsu::registry_signed_enum&>(
196 *session_attributes.get_registry_enum(
197 enumeration_name, enumeration_id));
198
199 return lttng::make_unique<const lst::signed_enumeration_type>(
200 enum_container_uctl_type->alignment, byte_order,
e7360180 201 enum_container_uctl_type->size, base,
d7bfb9b0
JG
202 enum_registry._mappings);
203 } else {
204 const auto& enum_registry = static_cast<const lsu::registry_unsigned_enum&>(
205 *session_attributes.get_registry_enum(
206 enumeration_name, enumeration_id));
207
208 return lttng::make_unique<const lst::unsigned_enumeration_type>(
209 enum_container_uctl_type->alignment, byte_order,
e7360180 210 enum_container_uctl_type->size, base,
d7bfb9b0
JG
211 enum_registry._mappings);
212 }
213}
214
215lst::type::cuptr create_string_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
216 const lttng_ust_ctl_field *end,
217 const session_attributes& session_attributes __attribute__((unused)),
218 const lttng_ust_ctl_field **next_ust_ctl_field)
219{
220 if (current >= end) {
221 LTTNG_THROW_PROTOCOL_ERROR(
222 fmt::format("End of {} array reached unexpectedly during decoding",
223 typeid(*current)));
224 }
225
226 const auto& string_uctl_field = *current;
227 *next_ust_ctl_field = current + 1;
228
229 const auto encoding = ust_ctl_encoding_to_string_field_encoding(
230 string_uctl_field.type.u.string.encoding);
231
232 return lttng::make_unique<const lst::null_terminated_string_type>(1, encoding);
233}
234
235lst::type::cuptr create_integer_type_from_ust_ctl_basic_type(
236 const lttng_ust_ctl_basic_type& type, const session_attributes& session_attributes)
237{
238 /* Checked by caller. */
239 LTTNG_ASSERT(type.atype == lttng_ust_ctl_atype_integer);
240
241 const auto byte_order = type.u.basic.integer.reverse_byte_order ?
242 lst::integer_type::reverse_byte_order(
243 session_attributes._native_trace_byte_order) :
244 session_attributes._native_trace_byte_order;
245 const auto signedness = type.u.basic.integer.signedness ?
246 lst::integer_type::signedness::SIGNED :
247 lst::integer_type::signedness::UNSIGNED;
248 const auto base = ust_ctl_base_to_integer_field_base(type.u.basic.integer.base);
249 const auto size = type.u.basic.integer.size;
250 const auto alignment = type.u.basic.integer.alignment;
251
252 return lttng::make_unique<const lst::integer_type>(
253 alignment, byte_order, size, signedness, base);
254}
255
256lst::type::cuptr create_array_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
257 const lttng_ust_ctl_field *end,
258 const session_attributes& session_attributes,
259 const lttng_ust_ctl_field **next_ust_ctl_field)
260{
261 if (current >= end) {
262 LTTNG_THROW_PROTOCOL_ERROR(
263 fmt::format("End of {} array reached unexpectedly during decoding",
264 typeid(*current)));
265 }
266
267 const auto& array_uctl_field = *current;
268 uint32_t array_alignment, array_length;
269 lst::type::cuptr element_type;
270 nonstd::optional<enum lst::string_type::encoding> element_encoding;
271
272 array_length = array_uctl_field.type.u.legacy.array.length;
273 array_alignment = 0;
274
275 const auto& element_uctl_type = array_uctl_field.type.u.legacy.array.elem_type;
276 if (element_uctl_type.atype != lttng_ust_ctl_atype_integer) {
277 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
278 "Unexpected legacy array element type: atype = {}, expected atype = lttng_ust_ctl_atype_integer ({})",
279 element_uctl_type.atype, lttng_ust_ctl_atype_integer));
280 }
281
282 element_type = create_integer_type_from_ust_ctl_basic_type(
283 element_uctl_type, session_attributes);
284 if (element_uctl_type.atype == lttng_ust_ctl_atype_integer &&
285 element_uctl_type.u.basic.integer.encoding != lttng_ust_ctl_encode_none) {
286 /* Element represents a text character. */
287 element_encoding = ust_ctl_encoding_to_string_field_encoding(
288 element_uctl_type.u.basic.integer.encoding);
289 }
290
291 *next_ust_ctl_field = current + 1;
292
293 if (element_encoding) {
294 const auto integer_element_size =
295 static_cast<const lst::integer_type&>(*element_type).size;
296
297 if (integer_element_size != 8) {
298 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
299 "Unexpected legacy array element type: integer has encoding but size is not 8: size = {}",
300 integer_element_size));
301 }
302
303 /* Array is a static-length string. */
304 return lttng::make_unique<lst::static_length_string_type>(
305 array_alignment, *element_encoding, array_length);
306 }
307
308 return lttng::make_unique<lst::static_length_array_type>(
309 array_alignment, std::move(element_type), array_length);
310}
311
312lst::type::cuptr create_array_nestable_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
313 const lttng_ust_ctl_field *end,
314 const session_attributes& session_attributes,
315 const lttng_ust_ctl_field **next_ust_ctl_field,
316 publish_field_fn publish_field)
317{
318 if (current >= end) {
319 LTTNG_THROW_PROTOCOL_ERROR(
320 fmt::format("End of {} array reached unexpectedly during decoding",
321 typeid(*current)));
322 }
323
324 const auto& array_uctl_field = *current;
325 uint32_t array_alignment, array_length;
326 lst::type::cuptr element_type;
327 nonstd::optional<enum lst::string_type::encoding> element_encoding;
328
329 array_length = array_uctl_field.type.u.array_nestable.length;
330 array_alignment = array_uctl_field.type.u.array_nestable.alignment;
331
332 /* Nestable array fields are followed by their element type. */
333 const auto& element_uctl_field = *(current + 1);
334
335 /* next_ust_ctl_field is updated as needed. */
336 element_type = create_type_from_ust_ctl_fields(&element_uctl_field, end, session_attributes,
337 next_ust_ctl_field, publish_field);
338 if (element_uctl_field.type.atype == lttng_ust_ctl_atype_integer &&
339 element_uctl_field.type.u.integer.encoding != lttng_ust_ctl_encode_none) {
340 /* Element represents a text character. */
341 element_encoding = ust_ctl_encoding_to_string_field_encoding(
342 element_uctl_field.type.u.integer.encoding);
343 }
344
345 if (element_encoding) {
346 const auto integer_element_size =
347 static_cast<const lst::integer_type&>(*element_type).size;
348
349 if (integer_element_size != 8) {
350 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
351 "Unexpected array element type: integer has encoding but size is not 8: size = {}",
352 integer_element_size));
353 }
354
355 /* Array is a static-length string. */
356 return lttng::make_unique<lst::static_length_string_type>(
357 array_alignment, *element_encoding, array_length);
358 }
359
360 return lttng::make_unique<lst::static_length_array_type>(
361 array_alignment, std::move(element_type), array_length);
362}
363
364/*
365 * For legacy sequence types, LTTng-UST expresses both the sequence and sequence
366 * length as part of the same lttng_ust_ctl_field entry.
367 */
368lst::type::cuptr create_sequence_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
369 const lttng_ust_ctl_field *end,
370 const session_attributes& session_attributes,
371 const lttng_ust_ctl_field **next_ust_ctl_field,
372 publish_field_fn publish_field)
373{
374 if (current >= end) {
375 LTTNG_THROW_PROTOCOL_ERROR(
376 fmt::format("End of {} array reached unexpectedly during decoding",
377 typeid(*current)));
378 }
379
380 const auto& sequence_uctl_field = *current;
381 const auto& element_uctl_type = sequence_uctl_field.type.u.legacy.sequence.elem_type;
382 const auto& length_uctl_type = sequence_uctl_field.type.u.legacy.sequence.length_type;
383 const auto sequence_alignment = 0U;
384
385 if (element_uctl_type.atype != lttng_ust_ctl_atype_integer) {
386 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
387 "Unexpected legacy sequence element type: atype = {}, expected atype = lttng_ust_ctl_atype_integer ({})",
388 element_uctl_type.atype, lttng_ust_ctl_atype_integer));
389 }
390
391 if (length_uctl_type.atype != lttng_ust_ctl_atype_integer) {
392 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
393 "Unexpected legacy sequence length field type: atype = {}, expected atype = lttng_ust_ctl_atype_integer ({})",
394 length_uctl_type.atype, lttng_ust_ctl_atype_integer));
395 }
396
397 nonstd::optional<enum lst::string_type::encoding> element_encoding;
398 if (element_uctl_type.atype == lttng_ust_ctl_atype_integer &&
399 element_uctl_type.u.basic.integer.encoding != lttng_ust_ctl_encode_none) {
400 /* Element represents a text character. */
401 element_encoding = ust_ctl_encoding_to_string_field_encoding(
402 element_uctl_type.u.basic.integer.encoding);
403 }
404
405 const auto length_field_name = fmt::format("_{}_length", sequence_uctl_field.name);
406 auto element_type = create_integer_type_from_ust_ctl_basic_type(
407 element_uctl_type, session_attributes);
408 auto length_type = create_integer_type_from_ust_ctl_basic_type(
409 length_uctl_type, session_attributes);
410
411 /* Publish an implicit length field _before_ the sequence field. */
412 publish_field(lttng::make_unique<lst::field>(length_field_name, std::move(length_type)));
413
414 *next_ust_ctl_field = current + 1;
415
416 if (element_encoding) {
417 const auto integer_element_size =
418 static_cast<const lst::integer_type&>(*element_type).size;
419
420 if (integer_element_size != 8) {
421 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
422 "Unexpected legacy array element type: integer has encoding but size is not 8: size = {}",
423 integer_element_size));
424 }
425
426 /* Sequence is a dynamic-length string. */
427 return lttng::make_unique<lst::dynamic_length_string_type>(sequence_alignment,
428 *element_encoding, std::move(length_field_name));
429 }
430
431 return lttng::make_unique<lst::dynamic_length_array_type>(
432 sequence_alignment, std::move(element_type), std::move(length_field_name));
433}
434
435lst::type::cuptr create_sequence_nestable_type_from_ust_ctl_fields(
436 const lttng_ust_ctl_field *current,
437 const lttng_ust_ctl_field *end,
438 const session_attributes& session_attributes,
439 const lttng_ust_ctl_field **next_ust_ctl_field,
440 publish_field_fn publish_field)
441{
442 if (current >= end) {
443 LTTNG_THROW_PROTOCOL_ERROR(
444 fmt::format("End of {} array reached unexpectedly during decoding",
445 typeid(*current)));
446 }
447
448 const auto& sequence_uctl_field = *current;
449 const auto sequence_alignment = sequence_uctl_field.type.u.sequence_nestable.alignment;
450 const auto *length_field_name = sequence_uctl_field.type.u.sequence_nestable.length_name;
451
452 /* Nestable sequence fields are followed by their element type. */
453 const auto& element_uctl_field = *(current + 1);
454
455 nonstd::optional<enum lst::string_type::encoding> element_encoding;
456 if (element_uctl_field.type.atype == lttng_ust_ctl_atype_integer &&
457 element_uctl_field.type.u.integer.encoding != lttng_ust_ctl_encode_none) {
458 /* Element represents a text character. */
459 element_encoding = ust_ctl_encoding_to_string_field_encoding(
460 element_uctl_field.type.u.integer.encoding);
461 }
462
463 /* next_ust_ctl_field is updated as needed. */
464 auto element_type = create_type_from_ust_ctl_fields(&element_uctl_field, end,
465 session_attributes, next_ust_ctl_field, publish_field);
466
467 if (lttng_strnlen(sequence_uctl_field.type.u.sequence_nestable.length_name,
468 sizeof(sequence_uctl_field.type.u.sequence_nestable.length_name)) ==
469 sizeof(sequence_uctl_field.type.u.sequence_nestable.length_name)) {
470 LTTNG_THROW_PROTOCOL_ERROR("Sequence length field name is not null terminated");
471 }
472
473 if (element_encoding) {
474 const auto integer_element_size =
475 static_cast<const lst::integer_type&>(*element_type).size;
476
477 if (integer_element_size != 8) {
478 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
479 "Unexpected array element type: integer has encoding but size is not 8: size = {}",
480 integer_element_size));
481 }
482
483 /* Sqeuence is a dynamic-length string. */
484 return lttng::make_unique<lst::dynamic_length_string_type>(sequence_alignment,
485 *element_encoding, std::move(length_field_name));
486 }
487
488 return lttng::make_unique<lst::dynamic_length_array_type>(
489 sequence_alignment, std::move(element_type), std::move(length_field_name));
490}
491
492lst::type::cuptr create_structure_field_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
493 const lttng_ust_ctl_field *end,
494 const session_attributes& session_attributes __attribute__((unused)),
495 const lttng_ust_ctl_field **next_ust_ctl_field)
496{
497 if (current >= end) {
498 LTTNG_THROW_PROTOCOL_ERROR(
499 fmt::format("End of {} array reached unexpectedly during decoding",
500 typeid(*current)));
501 }
502
503 uint32_t field_count;
504 uint32_t alignment;
505 const auto& structure_uctl_field = *current;
506
507 if (structure_uctl_field.type.atype == lttng_ust_ctl_atype_struct) {
508 field_count = structure_uctl_field.type.u.legacy._struct.nr_fields;
509 alignment = 0;
510 } else {
511 field_count = structure_uctl_field.type.u.struct_nestable.nr_fields;
512 alignment = structure_uctl_field.type.u.struct_nestable.alignment;
513 }
514
515 if (field_count != 0) {
516 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
517 "Only empty structures are supported by LTTng-UST: nr_fields = {}",
518 field_count));
519 }
520
521 *next_ust_ctl_field = current + 1;
522 return lttng::make_unique<lst::structure_type>(alignment, lst::structure_type::fields());
523}
524
525lst::type::cuptr create_variant_field_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
526 const lttng_ust_ctl_field *end,
527 const session_attributes& session_attributes,
528 const lttng_ust_ctl_field **next_ust_ctl_field)
529{
530 if (current >= end) {
531 LTTNG_THROW_PROTOCOL_ERROR(
532 fmt::format("End of {} array reached unexpectedly during decoding",
533 typeid(*current)));
534 }
535
536 const auto& variant_uctl_field = *current;
537 current++;
538
539 uint32_t alignment;
540 uint32_t choice_count;
541 const char *tag_name;
542
543 if (variant_uctl_field.type.atype == lttng_ust_ctl_atype_variant) {
544 alignment = 0;
545 choice_count = variant_uctl_field.type.u.legacy.variant.nr_choices;
546 tag_name = variant_uctl_field.type.u.legacy.variant.tag_name;
547 } else {
548 alignment = variant_uctl_field.type.u.variant_nestable.alignment;
549 choice_count = variant_uctl_field.type.u.variant_nestable.nr_choices;
550 tag_name = variant_uctl_field.type.u.variant_nestable.tag_name;
551 }
552
553 /* Choices follow. next_ust_ctl_field is updated as needed. */
554 lst::variant_type::choices choices;
555 for (unsigned int i = 0; i < choice_count; i++) {
556 create_field_from_ust_ctl_fields(current, end, session_attributes,
557 next_ust_ctl_field, [&choices](lst::field::cuptr field) {
558 choices.emplace_back(std::move(field));
559 });
560
561 current = *next_ust_ctl_field;
562 }
563
564 return lttng::make_unique<lst::variant_type>(alignment, tag_name, std::move(choices));
565}
566
567lst::type::cuptr create_type_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
568 const lttng_ust_ctl_field *end,
569 const session_attributes& session_attributes,
570 const lttng_ust_ctl_field **next_ust_ctl_field,
571 publish_field_fn publish_field)
572{
573 switch (current->type.atype) {
574 case lttng_ust_ctl_atype_integer:
575 return create_integer_type_from_ust_ctl_fields(
576 current, end, session_attributes, next_ust_ctl_field);
577 case lttng_ust_ctl_atype_enum:
578 case lttng_ust_ctl_atype_enum_nestable:
579 return create_enumeration_type_from_ust_ctl_fields(
580 current, end, session_attributes, next_ust_ctl_field);
581 case lttng_ust_ctl_atype_float:
582 return create_floating_point_type_from_ust_ctl_fields(
583 current, end, session_attributes, next_ust_ctl_field);
584 case lttng_ust_ctl_atype_string:
585 return create_string_type_from_ust_ctl_fields(
586 current, end, session_attributes, next_ust_ctl_field);
587 case lttng_ust_ctl_atype_array:
588 return create_array_type_from_ust_ctl_fields(current, end, session_attributes,
589 next_ust_ctl_field);
590 case lttng_ust_ctl_atype_array_nestable:
591 return create_array_nestable_type_from_ust_ctl_fields(current, end,
592 session_attributes, next_ust_ctl_field, publish_field);
593 case lttng_ust_ctl_atype_sequence:
594 return create_sequence_type_from_ust_ctl_fields(current, end, session_attributes,
595 next_ust_ctl_field, publish_field);
596 case lttng_ust_ctl_atype_sequence_nestable:
597 return create_sequence_nestable_type_from_ust_ctl_fields(current, end,
598 session_attributes, next_ust_ctl_field, publish_field);
599 case lttng_ust_ctl_atype_struct:
600 case lttng_ust_ctl_atype_struct_nestable:
601 return create_structure_field_from_ust_ctl_fields(
602 current, end, session_attributes, next_ust_ctl_field);
603 case lttng_ust_ctl_atype_variant:
604 case lttng_ust_ctl_atype_variant_nestable:
605 return create_variant_field_from_ust_ctl_fields(
606 current, end, session_attributes, next_ust_ctl_field);
607 default:
608 LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
609 "Unknown {} value `{}` encountered while converting {} to {}",
610 typeid(current->type.atype), current->type.atype, typeid(*current),
611 typeid(lst::type::cuptr::element_type)));
612 }
613}
614
615void create_field_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
616 const lttng_ust_ctl_field *end,
617 const session_attributes& session_attributes,
618 const lttng_ust_ctl_field **next_ust_ctl_field,
619 publish_field_fn publish_field)
620{
621 LTTNG_ASSERT(current < end);
622
623 if (lttng_strnlen(current->name, sizeof(current->name)) == sizeof(current->name)) {
624 LTTNG_THROW_PROTOCOL_ERROR(
625 fmt::format("Name of {} is not null-terminated", typeid(*current)));
626 }
627
628 publish_field(lttng::make_unique<lst::field>(current->name,
629 create_type_from_ust_ctl_fields(current, end, session_attributes,
630 next_ust_ctl_field, publish_field)));
631}
632
633/*
634 * `lttng_ust_ctl_field`s can be nested, in which case creating a field will consume
635 * more than one lttng_ust_ctl_field. create_field_from_ust_ctl_fields returns the
636 * position of the next lttng_ust_ctl_field to consume or `end` when the last field
637 * is consumed.
638 *
639 * Always returns a new field, throws on error.
640 */
641std::vector<lst::field::cuptr> create_fields_from_ust_ctl_fields(
b0f2e8db 642 const lsu::registry_session& session,
d7bfb9b0
JG
643 const lttng_ust_ctl_field *current,
644 const lttng_ust_ctl_field *end)
645{
646 std::vector<lst::field::cuptr> fields;
647 const auto trace_native_byte_order = session.abi.byte_order;
648 const session_attributes session_attributes{
649 [&session](const char *enum_name, uint64_t enum_id) {
97f630d4 650 return session.get_enumeration(enum_name, enum_id);
d7bfb9b0
JG
651 },
652 trace_native_byte_order};
653
654 while (current < end) {
655 auto *next_field = current;
656
657 /*
658 * create_field_from_ust_ctl_fields will consume one field at a time.
659 * However, some fields expressed by LTTng-UST's protocol are expended
660 * to multiple event fields (legacy sequence fields implicitly define
661 * their length field).
662 *
663 * The lambda allows the factory functions to push as many fields as
664 * needed depending on the decoded field's type.
665 */
666 create_field_from_ust_ctl_fields(current, end, session_attributes, &next_field,
667 [&fields](lst::field::cuptr field) {
668 fields.emplace_back(std::move(field));
669 });
670
671 current = next_field;
672 }
673
674 return fields;
675}
676} /* namespace */
677
678std::vector<lst::field::cuptr> lsu::create_trace_fields_from_ust_ctl_fields(
b0f2e8db 679 const lsu::registry_session& session,
d7bfb9b0
JG
680 const lttng_ust_ctl_field *fields,
681 std::size_t field_count)
682{
683 return create_fields_from_ust_ctl_fields(session, fields, fields + field_count);
684}
This page took 0.053406 seconds and 4 git commands to generate.