Common Trace Format 2 generation
[deliverable/lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.cpp
CommitLineData
d0b96690 1/*
d0b96690
DG
2 * Copyright (C) 2010-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
d0b96690 5 *
d0b96690
DG
6 */
7
7532fa3b
MD
8#include "common/bytecode/bytecode.hpp"
9#include "common/macros.hpp"
10#include "common/uuid.hpp"
11#include <endian.h>
6c1c0768 12#define _LGPL_SOURCE
d0b96690
DG
13#include <stdint.h>
14#include <string.h>
15#include <stdarg.h>
16#include <stdio.h>
17#include <limits.h>
18#include <unistd.h>
19#include <inttypes.h>
7532fa3b
MD
20#include <common/common.hpp>
21#include <common/time.hpp>
22#include <vector>
23#include <vendor/nlohmann/json.hpp>
d0b96690 24
7532fa3b
MD
25#include "ust-registry.hpp"
26#include "ust-clock.hpp"
27#include "ust-app.hpp"
d0b96690 28
8c645bb0
MD
29#define NR_CLOCK_OFFSET_SAMPLES 10
30
7532fa3b
MD
31using json = nlohmann::json;
32
8c645bb0 33struct offset_sample {
c2636b57 34 int64_t offset; /* correlation offset */
8c645bb0
MD
35 uint64_t measure_delta; /* lower is better */
36};
37
7532fa3b
MD
38enum class byte_order
39{
40 BIG,
41 LITTLE,
42};
43
44enum class display_base
45{
46 BINARY,
47 OCTAL,
48 DECIMAL,
49 HEXADECIMAL,
50};
51
52struct metadata_generation_exception : public std::runtime_error
53{
54 metadata_generation_exception(const char *what)
55 : std::runtime_error(what)
56 {}
57};
58
59struct lttng_ust_ctl_field_iterator
60{
61 lttng_ust_ctl_field_iterator(const lttng_ust_ctl_field *array,
62 size_t len)
63 : _array(array), _len(len)
64 {}
65
66 /* Make sure we don't pass it by value, by mistake. */
67 lttng_ust_ctl_field_iterator(const lttng_ust_ctl_field_iterator &) = delete;
68 void operator=(const lttng_ust_ctl_field_iterator &) = delete;
69
70 const lttng_ust_ctl_field &get_next()
71 {
72 if (done()) {
73 throw metadata_generation_exception(
74 "Field iterator overflow");
75 };
76
77 return _array[_cur++];
78 }
79
80 bool done() const
81 {
82 return _cur >= _len;
83 }
84
85private:
86 const lttng_ust_ctl_field *_array;
87 size_t _cur = 0;
88 size_t _len;
89};
90
91static
92byte_order get_byte_order(const ust_registry_session &session, bool reverse)
93{
94 if (session.byte_order == BIG_ENDIAN) {
95 return reverse ? byte_order::LITTLE : byte_order::BIG;
96 } else {
97 return reverse ? byte_order::BIG : byte_order::LITTLE;
98 }
99}
100
101struct bits
102{
103 using underlying_type = uint64_t;
104 explicit bits(uint64_t val)
105 : _val(val)
106 {}
107
108 underlying_type to_underlying() const
109 {
110 return static_cast<underlying_type>(_val);
111 }
112
113 bool operator==(bits other)
114 {
115 return to_underlying() == other.to_underlying();
116 }
117
118 bool operator!=(bits other)
119 {
120 return to_underlying() != other.to_underlying();
121 }
122
123private:
124 const uint64_t _val;
125};
126
127static
128bits operator"" _bits(unsigned long long val)
129{
130 return bits(val);
131}
132
133static
134json make_fragment(const char *type)
135{
136 return {
137 { "type", type }
138 };
139}
140
141static
142json make_field_class(const char *type, const char *role)
143{
144 json fc {
145 { "type", type },
146 };
147
148 if (role) {
149 fc["roles"] = {role};
150 }
151
152 return fc;
153}
154
155static
156const char *make_byte_order(byte_order byte_order)
157{
158 switch (byte_order) {
159 case byte_order::BIG:
160 return "big-endian";
161 case byte_order::LITTLE:
162 return "little-endian";
163 default:
164 abort();
165 }
166}
167
168static
169json make_fixed_length_bit_array_field_class(const char *type, bits length,
170 byte_order byte_order, bits alignment, const char *role)
171{
172 json fc = make_field_class(type, role);
173
174 fc.update ({
175 { "length", length.to_underlying() },
176 { "byte-order", make_byte_order(byte_order) },
177 });
178
179 if (alignment != 0_bits) {
180 fc["alignment"] = alignment.to_underlying();
181 }
182
183 return fc;
184}
185
186static
187json make_display_base(display_base display_base)
188{
189 switch (display_base) {
190 case display_base::BINARY:
191 return 2;
192 case display_base::OCTAL:
193 return 8;
194 case display_base::DECIMAL:
195 return 10;
196 case display_base::HEXADECIMAL:
197 return 16;
198 default:
199 abort();
200 }
201}
202
203static
204json make_abstract_integer_field_class(display_base preferred_display_base)
205{
206 json base = json::object();
207 if (preferred_display_base != display_base::DECIMAL) {
208 base = {
209 { "preferred-display-base",
210 make_display_base(preferred_display_base)},
211
212 };
213 }
214 return base;
215}
216
217static
218json make_fixed_length_unsigned_integer_field_class(const char *type,
219 bits length, byte_order byte_order, bits alignment,
220 display_base preferred_display_base, const char *role)
221{
222 json fc = make_fixed_length_bit_array_field_class(type, length,
223 byte_order, alignment, role);
224 fc.update(make_abstract_integer_field_class(preferred_display_base));
225 return fc;
226}
227
228static
229json make_fixed_length_signed_integer_field_class(const char *type,
230 bits length, byte_order byte_order, bits alignment,
231 display_base preferred_display_base, const char *role)
232{
233 json fc = make_fixed_length_bit_array_field_class(type, length,
234 byte_order, alignment, role);
235 fc.update(make_abstract_integer_field_class(preferred_display_base));
236 return fc;
237}
238
239static
240json make_fixed_length_unsigned_integer_field_class(bits length,
241 byte_order byte_order, bits alignment,
242 display_base preferred_display_base, const char *role)
243{
244 return make_fixed_length_unsigned_integer_field_class(
245 "fixed-length-unsigned-integer", length, byte_order,
246 alignment, preferred_display_base, role);
247}
248
249static
250json make_fixed_length_signed_integer_field_class(bits length,
251 byte_order byte_order, bits alignment,
252 display_base preferred_display_base, const char *role)
253{
254 return make_fixed_length_signed_integer_field_class(
255 "fixed-length-signed-integer", length, byte_order,
256 alignment, preferred_display_base, role);
257}
258
259static
260json make_fixed_length_floating_point_number_field_class(
261 bits length, byte_order byte_order, bits alignment) {
262 return make_fixed_length_bit_array_field_class(
263 "fixed-length-floating-point-number",
264 length, byte_order, alignment, nullptr);
265}
266
267struct integer_range
268{
269 integer_range(int64_t lower_bound_, int64_t upper_bound_)
270 : is_signed(true), lower_bound(lower_bound_), upper_bound(upper_bound_)
271 {}
272
273 integer_range(uint64_t lower_bound_, uint64_t upper_bound_)
274 : is_signed(false), lower_bound(lower_bound_), upper_bound(upper_bound_)
275 {}
276
277 const bool is_signed;
278 const int64_t lower_bound, upper_bound;
279};
280
281struct integer_range_set
282{
283 using vec_type = std::vector<integer_range>;
284 using const_iterator = vec_type::const_iterator;
285
286 integer_range_set() = default;
287 DISABLE_COPY_AND_ASSIGN(integer_range_set);
288 integer_range_set(integer_range_set &&) = default;
289
290 void add_range(int64_t lower_bound, int64_t upper_bound)
291 {
292 _ranges.emplace_back(lower_bound, upper_bound);
293 }
294
295 void add_range(uint64_t lower_bound, uint64_t upper_bound)
296 {
297 _ranges.emplace_back(lower_bound, upper_bound);
298 }
299
300 const_iterator begin() const
301 { return _ranges.begin(); }
302
303 const_iterator end() const
304 { return _ranges.end(); }
305
306private:
307 vec_type _ranges;
308};
309
310struct enumeration_mapping
311{
312 enumeration_mapping(const char *name_, json ranges_)
313 : name(name_), ranges(std::move(ranges_))
314 {}
315
316 const char *const name;
317 json ranges;
318};
319
320struct enumeration_mappings
321{
322 using vec_type = std::vector<enumeration_mapping>;
323 using const_iterator = vec_type::const_iterator;
324
325 enumeration_mappings() = default;
326 DISABLE_COPY_AND_ASSIGN(enumeration_mappings);
327 enumeration_mappings(enumeration_mappings &&) = default;
328
329 void add_mapping(const char *name_, json ranges_)
330 {
331 _mappings.emplace_back(name_, std::move(ranges_));
332 }
333
334 const_iterator begin() const
335 { return _mappings.begin(); }
336
337 const_iterator end() const
338 { return _mappings.end(); }
339
340private:
341 vec_type _mappings;
342};
343
344static
345json make_integer_range_set(const integer_range_set &ranges)
346{
347 json rs = json::array();
348
349 for (const integer_range &range : ranges) {
350 rs.push_back({ range.lower_bound, range.upper_bound });
351 }
352
353 return rs;
354}
355
356static json
357make_enumeration_mappings(enumeration_mappings mappings)
358{
359 json mappings_obj = json::object();
360
361 for (const enumeration_mapping &mapping : mappings) {
362 mappings_obj[mapping.name] = std::move(mapping.ranges);
363 }
364
365 return mappings_obj;
366}
367
da860cab 368static
7532fa3b
MD
369json make_abstract_enumeration_field_class(display_base preferred_display_base,
370 enumeration_mappings mappings)
371{
372 json fc = make_abstract_integer_field_class(preferred_display_base);
373 fc["mappings"] = make_enumeration_mappings(std::move(mappings));
374 return fc;
375}
376
377
378static
379json make_fixed_length_unsigned_enumeration_field_class(bits length,
380 byte_order byte_order, bits alignment,
381 display_base preferred_display_base, const char *role,
382 enumeration_mappings mappings)
383{
384 json fc = make_fixed_length_unsigned_integer_field_class(
385 "fixed-length-unsigned-enumeration", length, byte_order,
386 alignment, preferred_display_base, role);
387 fc.update(make_abstract_enumeration_field_class(preferred_display_base,
388 std::move(mappings)));
389 return fc;
390}
391
392static
393json make_fixed_length_signed_enumeration_field_class(bits length,
394 byte_order byte_order, bits alignment,
395 display_base preferred_display_base, const char *role,
396 enumeration_mappings mappings)
397{
398 json fc = make_fixed_length_signed_integer_field_class(
399 "fixed-length-signed-enumeration", length, byte_order,
400 alignment, preferred_display_base, role);
401 fc.update(make_abstract_enumeration_field_class(preferred_display_base,
402 std::move(mappings)));
403 return fc;
404}
405
406static
407json make_fixed_length_enumeration_field_class(bool signedness,
408 bits length, byte_order byte_order, bits alignment,
409 display_base preferred_display_base,
410 enumeration_mappings mappings)
411{
412 if (signedness) {
413 return make_fixed_length_signed_enumeration_field_class(
414 length, byte_order, alignment, preferred_display_base,
415 nullptr, std::move(mappings));
416 } else {
417 return make_fixed_length_unsigned_enumeration_field_class(
418 length, byte_order, alignment, preferred_display_base,
419 nullptr, std::move(mappings));
420 }
421}
422
423static
424json make_static_length_blob_field_class(uint64_t length, const char *role)
425{
426 json fc = make_field_class("static-length-blob", role);
427
428 fc.update({
429 { "length", length },
430 });
431
432 return fc;
433}
434
435static
436json make_uuid_field_class(const char *role)
437{
438 return make_static_length_blob_field_class(16, role);
439}
440
441struct structure_member
442{
443 structure_member(const char *name_, json field_class_)
444 : name(name_), field_class(std::move(field_class_))
445 {}
446
447 DISABLE_COPY_AND_ASSIGN(structure_member);
448 structure_member(structure_member &&) = default;
449
450 const char *const name;
451 json field_class;
452};
453
454struct structure_members
455{
456 using vec_type = std::vector<structure_member>;
457
458 structure_members() = default;
459 structure_members(const structure_members &) = delete;
460 structure_members(structure_members &&) = default;
461 structure_members &operator=(const structure_members &) = delete;
462
463 void add_member(const char *name, json field_class)
464 {
465 _members.emplace_back(structure_member(
466 name, std::move(field_class)
467 ));
468 }
469
470 vec_type::iterator begin()
471 { return _members.begin (); }
472
473 vec_type::iterator end()
474 { return _members.end (); }
475
476private:
477 vec_type _members;
478};
479
480static
481json make_struct_member(structure_member member)
482{
483 return {
484 { "name", member.name },
485 { "field-class", std::move(member.field_class) },
486 };
487}
488
489static
490json make_structure_members(structure_members members)
491{
492 json members_obj = json::array();
493
494 for (structure_member &member : members) {
495 members_obj.push_back(make_struct_member(std::move(member)));
496 }
497
498 return members_obj;
499}
500
501static
502json make_structure_field_class(bits minimum_alignment,
503 structure_members members)
504{
505 json fc = make_field_class("structure", nullptr);
506
507 fc["member-classes"] = make_structure_members(std::move(members));
508
509 if (minimum_alignment != 0_bits) {
510 fc["minimum-alignment"] = minimum_alignment.to_underlying();
511 }
512
513 return fc;
514}
515
516
517struct variant_option
518{
519 variant_option(const char *name_,
520 json selector_field_ranges_,
521 json field_class_)
522 : name(name_),
523 selector_field_ranges(std::move(selector_field_ranges_)),
524 field_class(std::move(field_class_))
525 {}
526
527 variant_option(std::string name_,
528 json selector_field_ranges_,
529 json field_class_)
530 : _name_buf(std::move(name_)),
531 name(_name_buf.c_str()),
532 selector_field_ranges(std::move(selector_field_ranges_)),
533 field_class(std::move(field_class_))
534 {}
535
536 DISABLE_COPY_AND_ASSIGN(variant_option);
537
538 variant_option(variant_option &&other)
539 : _name_buf(std::move(other._name_buf)),
540 /*
541 * If `_name_buf` is empty, `name` is not managed by us,
542 * just copy the pointer. If `_name_buf` is not empty,
543 * make `name` point to our local copy.
544 */
545 name(_name_buf.empty() ? other.name : _name_buf.c_str()),
546 selector_field_ranges(other.selector_field_ranges),
547 field_class(other.field_class)
548
549 {}
550
551private:
552 /*
553 * Buffer for `name`, if it is dynamically allocated andmanaged by us.
554 */
555 const std::string _name_buf;
556
557public:
558 const char *name;
559 json selector_field_ranges;
560 json field_class;
561};
562
563struct variant_options
564{
565 using vec_type = std::vector<variant_option>;
566 using iterator = vec_type::iterator;
567 using const_iterator = vec_type::const_iterator;
568
569 variant_options() = default;
570 DISABLE_COPY_AND_ASSIGN(variant_options);
571 variant_options(variant_options &&) = default;
572
573 void add_option(const char *name, json selector_field_ranges,
574 json field_class)
575 {
576 _options.emplace_back(variant_option(
577 name, std::move(selector_field_ranges),
578 std::move(field_class)
579 ));
580 }
581
582 void add_option(std::string name, json selector_field_ranges,
583 json field_class)
584 {
585 _options.emplace_back(variant_option(
586 std::move(name), std::move(selector_field_ranges),
587 std::move(field_class)
588 ));
589 }
590
591 iterator begin()
592 { return _options.begin(); }
593
594 iterator end()
595 { return _options.end(); }
596
597 const_iterator begin() const
598 { return _options.begin(); }
599
600 const_iterator end() const
601 { return _options.end(); }
602
603private:
604 vec_type _options;
605};
606
607struct field_path
608{
609 using vec_type = std::vector<const char *>;
610
611 struct popper
612 {
613 popper(struct field_path &path)
614 : _path(path)
615 {}
616
617 popper(const popper &) = delete;
618 popper(popper &&) = default;
619 void operator=(const popper &) = delete;
620
621 ~popper()
622 {
623 _path._path.pop_back();
624
625 }
626
627 private:
628 field_path &_path;
629 };
630
631 field_path(const char *root)
632 : _path({root})
633 {}
634
635 field_path(std::initializer_list<const char *> list)
636 : _path(list)
637 {}
638
639 const vec_type &path() const
640 {
641 return _path;
642 }
643
644 popper push(const char *element)
645 {
646 _path.push_back(element);
647 return popper(*this);
648 }
649
650private:
651 vec_type _path;
652};
653
654static
655json make_variant_option(variant_option option)
656{
657 return {
658 { "name", option.name },
659 { "selector-field-ranges", std::move(option.selector_field_ranges) },
660 { "field-class", std::move(option.field_class ) },
661 };
662}
663
664static
665json make_variant_options(variant_options options)
666{
667 json options_obj = json::array();
668
669 for (variant_option &option : options) {
670 options_obj.push_back(make_variant_option(std::move(option)));
671 }
672
673 return options_obj;
674}
675
676static
677json make_field_location(const field_path &field_location)
678{
679 return field_location.path();
680}
681
682static
683json make_variant_field_class(variant_options options,
684 const field_path &selector_field_location)
685{
686 json fc = make_field_class("variant", nullptr);
687
688 fc["options"] = make_variant_options(std::move(options));
689 fc["selector-field-location"] =
690 make_field_location(selector_field_location);
691
692 return fc;
693}
694
695static
696json make_array_field_class(const char *type, json element_field_class,
697 bits minimum_alignment)
698{
699 json fc = make_field_class(type, nullptr);
700
701 fc["element-field-class"] = std::move(element_field_class);
702
703 if (minimum_alignment != 0_bits) {
704 fc["minimum-alignment"] = minimum_alignment.to_underlying();
705 }
706
707 return fc;
708}
709
710static
711json make_static_length_array_field_class(json element_field_class,
712 uint64_t length, bits minimum_alignment)
713{
714 json fc = make_array_field_class("static-length-array",
715 element_field_class, minimum_alignment);
716
717 fc["length"] = length;
718
719 return fc;
720}
721
722static
723json make_dynamic_length_array_field_class(json element_field_class,
724 const field_path &length_field_location, bits minimum_alignment)
725{
726 json fc = make_array_field_class("dynamic-length-array",
727 element_field_class, minimum_alignment);
728
729 fc["length-field-location"] =
730 make_field_location(length_field_location);
731
732 return fc;
733}
734
735static
736json make_string_field_class()
737{
738 return make_field_class("null-terminated-string", nullptr);
739}
740
741static
742json make_packet_header_field_class(const ust_registry_session &session)
743{
744 byte_order bo = get_byte_order(session, false);
745
746 structure_members members;
747
748 members.add_member("magic",
749 make_fixed_length_unsigned_integer_field_class(
750 32_bits, bo, 8_bits, display_base::HEXADECIMAL,
751 "packet-magic-number"));
752 members.add_member("uuid",
753 make_uuid_field_class("trace-class-uuid"));
754 members.add_member("stream_id",
755 make_fixed_length_unsigned_integer_field_class(
756 32_bits, bo, 8_bits, display_base::DECIMAL,
757 "data-stream-class-id"));
758 members.add_member("stream_instance_id",
759 make_fixed_length_unsigned_integer_field_class(
760 64_bits, bo, 8_bits, display_base::DECIMAL,
761 "data-stream-id"));
762
763 return make_structure_field_class(0_bits, std::move(members));
764}
765
766static
767json make_uuid(uint8_t uuid_bytes[LTTNG_UUID_LEN])
768{
769 json uuid = json::array();
770
771 for (size_t i = 0; i < LTTNG_UUID_LEN; ++i) {
772 uuid.push_back(uuid_bytes[i]);
773 }
774
775 return uuid;
776}
777
778static
779json make_clock_offset(int64_t offset_cycles, uint64_t freq)
780{
781 // FIXME: not tested at all, especially not for negative values of offset
782
783 /* Whole seconds. */
784 int64_t s = offset_cycles / freq;
785
786 /* Remaining cycles. */
787 int64_t cycles = offset_cycles % freq;
788
789 return {
790 { "seconds", s },
791 { "cycles", cycles },
792 };
793}
da860cab 794
d0b96690
DG
795static inline
796int get_count_order(unsigned int count)
797{
798 int order;
799
78ddfe55 800 order = lttng_fls(count) - 1;
46b4dda6 801 if (count & (count - 1)) {
d0b96690 802 order++;
46b4dda6 803 }
a0377dfe 804 LTTNG_ASSERT(order >= 0);
d0b96690
DG
805 return order;
806}
807
808/*
809 * Returns offset where to write in metadata array, or negative error value on error.
810 */
811static
7532fa3b 812ssize_t metadata_reserve(ust_registry_session &session, size_t len)
d0b96690 813{
7532fa3b 814 size_t new_len = session.metadata_len + len;
d0b96690 815 size_t new_alloc_len = new_len;
7532fa3b 816 size_t old_alloc_len = session.metadata_alloc_len;
d0b96690
DG
817 ssize_t ret;
818
819 if (new_alloc_len > (UINT32_MAX >> 1))
820 return -EINVAL;
821 if ((old_alloc_len << 1) > (UINT32_MAX >> 1))
822 return -EINVAL;
823
824 if (new_alloc_len > old_alloc_len) {
825 char *newptr;
826
827 new_alloc_len =
7532fa3b
MD
828 std::max<size_t>(1U << get_count_order(new_alloc_len), old_alloc_len << 1);
829 newptr = (char *) realloc(session.metadata, new_alloc_len);
d0b96690
DG
830 if (!newptr)
831 return -ENOMEM;
7532fa3b 832 session.metadata = newptr;
d0b96690 833 /* We zero directly the memory from start of allocation. */
7532fa3b
MD
834 memset(&session.metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len);
835 session.metadata_alloc_len = new_alloc_len;
d0b96690 836 }
7532fa3b
MD
837 ret = session.metadata_len;
838 session.metadata_len += len;
d0b96690
DG
839 return ret;
840}
841
d7ba1388 842static
7532fa3b 843int metadata_file_append(ust_registry_session &session,
d7ba1388
MD
844 const char *str, size_t len)
845{
846 ssize_t written;
847
7532fa3b 848 if (session.metadata_fd < 0) {
d7ba1388
MD
849 return 0;
850 }
851 /* Write to metadata file */
7532fa3b 852 written = lttng_write(session.metadata_fd, str, len);
d7ba1388
MD
853 if (written != len) {
854 return -1;
855 }
856 return 0;
857}
858
d0b96690
DG
859/*
860 * We have exclusive access to our metadata buffer (protected by the
861 * ust_lock), so we can do racy operations such as looking for
862 * remaining space left in packet and write, since mutual exclusion
863 * protects us from concurrent writes.
864 */
d22ad5f8 865static ATTR_FORMAT_PRINTF(2, 3)
7532fa3b 866int lttng_metadata_printf(ust_registry_session &session,
d0b96690
DG
867 const char *fmt, ...)
868{
869 char *str = NULL;
870 size_t len;
871 va_list ap;
872 ssize_t offset;
873 int ret;
874
875 va_start(ap, fmt);
876 ret = vasprintf(&str, fmt, ap);
877 va_end(ap);
878 if (ret < 0)
879 return -ENOMEM;
880
881 len = strlen(str);
882 offset = metadata_reserve(session, len);
883 if (offset < 0) {
884 ret = offset;
885 goto end;
886 }
7532fa3b 887 memcpy(&session.metadata[offset], str, len);
d7ba1388
MD
888 ret = metadata_file_append(session, str, len);
889 if (ret) {
890 PERROR("Error appending to metadata file");
891 goto end;
892 }
d0b96690
DG
893 DBG3("Append to metadata: \"%s\"", str);
894 ret = 0;
895
896end:
897 free(str);
898 return ret;
899}
900
7532fa3b 901
da860cab 902static
7532fa3b
MD
903void lttng_metadata_print_fragment(ust_registry_session &session,
904 const json &fragment)
da860cab 905{
7532fa3b 906 lttng_metadata_printf(session, "\x1e%s", fragment.dump(2).c_str());
da860cab
MD
907}
908
a1f68b22 909static
7532fa3b 910display_base int_to_display_base(int base)
a1f68b22 911{
7532fa3b
MD
912 /* If we ever get an invalid value, default to 10. */
913 switch (base) {
914 case 2:
915 return display_base::BINARY;
916 case 8:
917 return display_base::OCTAL;
918 default:
919 case 10:
920 return display_base::DECIMAL;
921 case 16:
922 return display_base::HEXADECIMAL;
a1f68b22
MD
923 }
924}
925
8de88061 926static
7532fa3b
MD
927json make_ust_integer_field_class(const ust_registry_session &session,
928 const lttng_ust_ctl_integer_type &type)
929{
930 if (type.signedness) {
931 return make_fixed_length_signed_integer_field_class(
932 bits(type.size), get_byte_order(session, type.reverse_byte_order),
933 bits(type.alignment), int_to_display_base(type.base),
934 nullptr);
935 } else {
936 return make_fixed_length_unsigned_integer_field_class(
937 bits(type.size), get_byte_order(session, type.reverse_byte_order),
938 bits(type.alignment), int_to_display_base(type.base),
939 nullptr);
8de88061 940 }
8de88061
JR
941}
942
10b56aef
MD
943/* Called with session registry mutex held. */
944static
7532fa3b
MD
945json make_ust_enum_field_class(const ust_registry_session &session,
946 const char *name, uint64_t id,
947 const lttng_ust_ctl_integer_type &container)
948{
10b56aef 949 rcu_read_lock();
7532fa3b
MD
950 const ust_registry_enum *reg_enum = ust_registry_lookup_enum_by_id(
951 session, name, id);
10b56aef 952 rcu_read_unlock();
7532fa3b 953
10b56aef
MD
954 /* reg_enum can still be used because session registry mutex is held. */
955 if (!reg_enum) {
7532fa3b 956 return -ENOENT;
10b56aef 957 }
10b56aef 958
7532fa3b
MD
959 bool is_signed = container.signedness;
960 enumeration_mappings mappings;
961
962 const lttng_ust_ctl_enum_entry *entries = reg_enum->entries;
963
964 union {
965 int64_t sign;
966 uint64_t nosign;
967 } next_auto_low_bound;
968
969 if (is_signed) {
970 next_auto_low_bound.sign = 0;
971 } else {
972 next_auto_low_bound.nosign = 0;
10b56aef 973 }
3b016e58 974
7532fa3b
MD
975 for (size_t i = 0; i < reg_enum->nr_entries; ++i) {
976 const lttng_ust_ctl_enum_entry &entry = entries[i];
3b016e58 977
7532fa3b 978 //len = strlen(entry->string);
e85e3723 979
7532fa3b
MD
980 if (entry.u.extra.options &
981 LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
982 if (is_signed) {
983 integer_range_set rs;
984 rs.add_range(next_auto_low_bound.sign, next_auto_low_bound.sign);
985 mappings.add_mapping(entry.string, make_integer_range_set(rs));
986 ++next_auto_low_bound.sign;
e85e3723 987 } else {
7532fa3b
MD
988 integer_range_set rs;
989 rs.add_range(next_auto_low_bound.nosign, next_auto_low_bound.nosign);
990 mappings.add_mapping(entry.string, make_integer_range_set(rs));
991 ++next_auto_low_bound.nosign;
e85e3723 992 }
7532fa3b
MD
993 } else {
994 if (is_signed) {
995 integer_range_set rs;
996 // FIXME: not sure if those casts work as intended.
997 rs.add_range((int64_t) entry.start.value, (int64_t) entry.end.value);
998 mappings.add_mapping(entry.string, make_integer_range_set(rs));
999 } else {
1000 integer_range_set rs;
1001 rs.add_range(entry.start.value, entry.end.value);
1002 mappings.add_mapping(entry.string, make_integer_range_set(rs));
3b016e58 1003 }
10b56aef
MD
1004 }
1005 }
7532fa3b
MD
1006
1007 return make_fixed_length_enumeration_field_class(
1008 is_signed, bits(container.size),
1009 get_byte_order(session, container.reverse_byte_order),
1010 bits(container.alignment), int_to_display_base(container.base),
1011 std::move(mappings));
da860cab
MD
1012}
1013
da860cab 1014static
7532fa3b
MD
1015void make_ust_field_class(const ust_registry_session &session,
1016 lttng_ust_ctl_field_iterator &field_iterator,
1017 field_path &current_field_path,
1018 std::function<void(const char *, json)> add_field,
1019 std::function<const json &(const char *)> get_last_field);
da860cab 1020
7532fa3b
MD
1021static
1022void make_ust_variant_field_class(
1023 const ust_registry_session &session,
1024 lttng_ust_ctl_field_iterator &field_iterator,
1025 field_path &current_field_path,
1026 const char *field_name,
1027 uint32_t nr_options,
1028 const char *selector_name,
1029 std::function<void(const char *, json)> add_field,
1030 std::function<const json &(const char *)> lookup_field)
1031{
1032 variant_options options;
1033 const json &selector_field = lookup_field (selector_name);
1034 const json &mappings = selector_field["mappings"];
1035
1036 auto this_add_field = [&options, &mappings] (const char *option_name, json option_fc) {
1037 /* UST prefixes the enumerators with and underscore. */
1038 std::string option_name_prefixed = std::string("_") + option_name;
1039 const json &ranges = mappings[option_name_prefixed];
1040 /*
1041 * In CTF 1.8, the variant options were prefixed with an
1042 * underscore to match the enumerator names. It is not
1043 * necessary to do it in CTF 2, as variant options don't rely
1044 * on their names matchin an enumerator name. But do it anyway
1045 * to keep the old names, which may help readers migrating from
1046 * 1.8 to 2.
1047 */
1048 options.add_option(std::move(option_name_prefixed), ranges, option_fc);
1049 };
da860cab 1050
7532fa3b
MD
1051 {
1052 auto field_location_popper = current_field_path.push(field_name);
1053
1054 for (uint32_t i = 0; i < nr_options; i++) {
1055 make_ust_field_class(session, field_iterator,
1056 current_field_path, this_add_field, lookup_field);
dc6403f3 1057 }
da860cab 1058 }
7532fa3b
MD
1059
1060 auto field_location_popper = current_field_path.push(selector_name);
1061 add_field(field_name,
1062 make_variant_field_class(std::move(options), current_field_path));
10b56aef
MD
1063}
1064
d0b96690 1065static
7532fa3b
MD
1066void make_ust_field_class(const ust_registry_session &session,
1067 lttng_ust_ctl_field_iterator &field_iterator,
1068 field_path &current_field_path,
1069 std::function<void(const char *, json)> add_field,
1070 std::function<const json &(const char *)> lookup_field)
1071{
1072 const lttng_ust_ctl_field &field = field_iterator.get_next();
d0b96690 1073
7532fa3b 1074 switch (field.type.atype) {
b623cb6a 1075 case lttng_ust_ctl_atype_integer:
7532fa3b
MD
1076 add_field(field.name,
1077 make_ust_integer_field_class(session,
1078 field.type.u.integer));
d0b96690 1079 break;
7532fa3b 1080
b623cb6a 1081 case lttng_ust_ctl_atype_enum:
7532fa3b
MD
1082 {
1083 const auto &enumeration = field.type.u.legacy.basic.enumeration;
1084 add_field(field.name,
1085 make_ust_enum_field_class(session,
1086 enumeration.name, enumeration.id,
1087 enumeration.container_type));
10b56aef 1088 break;
7532fa3b
MD
1089 }
1090
b623cb6a 1091 case lttng_ust_ctl_atype_float:
7532fa3b
MD
1092 {
1093 const lttng_ust_ctl_float_type &t = field.type.u._float;
1094
1095 add_field(field.name,
1096 make_fixed_length_floating_point_number_field_class(
1097 bits(t.exp_dig + t.mant_dig),
1098 get_byte_order(session, t.reverse_byte_order), bits(t.alignment)));
1099
d0b96690 1100 break;
7532fa3b
MD
1101 }
1102
b623cb6a 1103 case lttng_ust_ctl_atype_array:
d0b96690 1104 {
7532fa3b 1105 const auto &array_type = field.type.u.legacy.array;
d0b96690 1106
0d32d1a9 1107 /* Only integers are currently supported in arrays. */
7532fa3b
MD
1108 if (array_type.elem_type.atype != lttng_ust_ctl_atype_integer) {
1109 throw metadata_generation_exception(
1110 "array element type not supported");
0d32d1a9 1111 }
7532fa3b
MD
1112
1113 add_field(field.name, make_static_length_array_field_class(
1114 make_ust_integer_field_class(
1115 session, array_type.elem_type.u.basic.integer),
1116 array_type.length, 0_bits));
1117
0d32d1a9
MD
1118 break;
1119 }
7532fa3b 1120
b623cb6a 1121 case lttng_ust_ctl_atype_array_nestable:
0d32d1a9 1122 {
7532fa3b
MD
1123 const struct lttng_ust_ctl_type &element_type =
1124 field_iterator.get_next().type;
0d32d1a9
MD
1125
1126 /* Only integers are currently supported in arrays. */
7532fa3b
MD
1127 if (element_type.atype != lttng_ust_ctl_atype_integer) {
1128 throw metadata_generation_exception(
1129 "array element type not supported");
0d32d1a9
MD
1130 }
1131
7532fa3b 1132 const auto &array_type = field.type.u.array_nestable;
0d32d1a9 1133
7532fa3b
MD
1134 /* The array alignment value we receive is in bytes. */
1135 add_field(field.name,
1136 make_static_length_array_field_class(
1137 make_ust_integer_field_class(
1138 session, element_type.u.integer),
1139 array_type.length, bits(array_type.alignment * 8)));
d0b96690
DG
1140 break;
1141 }
7532fa3b 1142
b623cb6a 1143 case lttng_ust_ctl_atype_sequence:
d0b96690 1144 {
7532fa3b 1145 const auto &t = field.type.u.legacy.sequence;
0d32d1a9
MD
1146
1147 /* Only integers are currently supported in sequences. */
7532fa3b
MD
1148 if (t.elem_type.atype != lttng_ust_ctl_atype_integer) {
1149 throw metadata_generation_exception(
1150 "sequence element type not supported");
0d32d1a9
MD
1151 }
1152
7532fa3b
MD
1153 const lttng_ust_ctl_integer_type &length_type
1154 = t.length_type.u.basic.integer;
d0b96690 1155
7532fa3b
MD
1156 std::stringstream sstream;
1157 sstream << "__" << field.name << "_length";
1158 add_field(sstream.str().c_str(),
1159 make_ust_integer_field_class(session, length_type));
1160
1161 auto popper = current_field_path.push(sstream.str().c_str());
1162 add_field(field.name,
1163 make_dynamic_length_array_field_class(
1164 make_ust_integer_field_class(
1165 session, t.elem_type.u.basic.integer),
1166 current_field_path, 0_bits));
d0b96690
DG
1167 break;
1168 }
b623cb6a 1169 case lttng_ust_ctl_atype_sequence_nestable:
0d32d1a9 1170 {
7532fa3b
MD
1171 const struct lttng_ust_ctl_type &element_type =
1172 field_iterator.get_next().type;
0d32d1a9
MD
1173
1174 /* Only integers are currently supported in sequences. */
7532fa3b
MD
1175 if (element_type.atype != lttng_ust_ctl_atype_integer) {
1176 throw metadata_generation_exception(
1177 "sequence element type not supported");
0d32d1a9
MD
1178 }
1179
7532fa3b
MD
1180 const auto &array_type = field.type.u.sequence_nestable;
1181 auto popper = current_field_path.push(
1182 array_type.length_name);
1183
1184 /* The array alignment value we receive is in bytes. */
1185 add_field(field.name,
1186 make_dynamic_length_array_field_class(
1187 make_ust_integer_field_class(
1188 session, element_type.u.integer),
1189 current_field_path,
1190 bits(array_type.alignment * 8)));
0d32d1a9
MD
1191 break;
1192 }
7532fa3b 1193
b623cb6a 1194 case lttng_ust_ctl_atype_string:
7532fa3b 1195 add_field(field.name, make_string_field_class());
da860cab 1196 break;
7532fa3b 1197
b623cb6a 1198 case lttng_ust_ctl_atype_variant:
7532fa3b
MD
1199 {
1200 const decltype(field.type.u.legacy.variant) &variant_type =
1201 field.type.u.legacy.variant;
1202
1203 make_ust_variant_field_class(session, field_iterator,
1204 current_field_path, field.name, variant_type.nr_choices,
1205 variant_type.tag_name, add_field, lookup_field);
0d32d1a9 1206 break;
7532fa3b
MD
1207 }
1208
b623cb6a 1209 case lttng_ust_ctl_atype_variant_nestable:
7532fa3b
MD
1210 {
1211 const decltype(field.type.u.variant_nestable) &variant_type =
1212 field.type.u.variant_nestable;
1213
1214 make_ust_variant_field_class(session, field_iterator,
1215 current_field_path, field.name, variant_type.nr_choices,
1216 variant_type.tag_name, add_field, lookup_field);
da860cab 1217 break;
7532fa3b
MD
1218 }
1219
b623cb6a 1220 case lttng_ust_ctl_atype_struct:
7532fa3b 1221 if (field.type.u.legacy._struct.nr_fields != 0) {
0d32d1a9 1222 /* Currently only 0-length structures are supported. */
7532fa3b 1223 throw metadata_generation_exception("Only 0-length structures are supported");
0d32d1a9 1224 }
7532fa3b
MD
1225
1226 /* Don't emit anything */
d0b96690 1227 break;
7532fa3b 1228
b623cb6a 1229 case lttng_ust_ctl_atype_struct_nestable:
7532fa3b 1230 if (field.type.u.struct_nestable.nr_fields != 0) {
0d32d1a9 1231 /* Currently only 0-length structures are supported. */
7532fa3b 1232 throw metadata_generation_exception("Only 0-length structures are supported");
0d32d1a9 1233 }
7532fa3b
MD
1234
1235 /* Don't emit anything */
0d32d1a9 1236 break;
7532fa3b 1237
b623cb6a 1238 case lttng_ust_ctl_atype_enum_nestable:
0d32d1a9 1239 {
7532fa3b
MD
1240 const lttng_ust_ctl_field &container =
1241 field_iterator.get_next();
0d32d1a9
MD
1242
1243 /* Only integers are supported as container types. */
7532fa3b
MD
1244 if (container.type.atype != lttng_ust_ctl_atype_integer) {
1245 throw metadata_generation_exception(
1246 "Enumeration container type not an integer");
0d32d1a9 1247 }
7532fa3b
MD
1248
1249 const auto &enumeration = field.type.u.enum_nestable;
1250 add_field(field.name,
1251 make_ust_enum_field_class(session,
1252 enumeration.name, enumeration.id,
1253 container.type.u.integer));
0d32d1a9
MD
1254 break;
1255 }
d0b96690 1256 default:
7532fa3b
MD
1257 throw metadata_generation_exception(
1258 "Unhandled lttng-ust field type");
d0b96690 1259 }
d0b96690
DG
1260}
1261
1262static
7532fa3b
MD
1263json make_record_common_context_field_class(
1264 const ust_registry_session &session,
1265 const ust_registry_channel &chan)
d0b96690 1266{
7532fa3b
MD
1267 lttng_ust_ctl_field_iterator iter(chan.ctx_fields, chan.nr_ctx_fields);
1268 field_path fp("event-record-common-context");
1269 structure_members members;
d0b96690 1270
7532fa3b
MD
1271 auto add_field = [&members] (const char *name, json field_class) {
1272 members.add_member(name, field_class);
1273 };
1274
1275 auto lookup_field = [&members] (const char *name) -> const json & {
1276 for (const structure_member &member : members) {
1277 if (strcmp(member.name, name) == 0) {
1278 return member.field_class;
1279 }
da860cab 1280 }
7532fa3b
MD
1281
1282 throw metadata_generation_exception("failed to look up field");
1283 };
1284
1285 while (!iter.done()) {
1286 make_ust_field_class(session, iter, fp, add_field,
1287 lookup_field);
d0b96690 1288 }
7532fa3b
MD
1289
1290 return make_structure_field_class(0_bits, std::move(members));
d0b96690
DG
1291}
1292
1293static
7532fa3b
MD
1294json make_event_record_class_payload_field_class(
1295 const ust_registry_session &session,
1296 const ust_registry_event &event)
d0b96690 1297{
7532fa3b
MD
1298 lttng_ust_ctl_field_iterator iter(event.fields, event.nr_fields);
1299 field_path fp("event-record-payload");
1300 structure_members members;
d0b96690 1301
7532fa3b
MD
1302 auto add_field = [&members] (const char *name, json field_class) {
1303 members.add_member(name, field_class);
1304 };
1305
1306 auto lookup_field = [&members] (const char *name) {
1307 for (const structure_member &member : members) {
1308 if (strcmp(member.name, name) == 0) {
1309 return member.field_class;
1310 }
da860cab 1311 }
7532fa3b
MD
1312
1313 throw metadata_generation_exception("failed to look up field");
1314 };
1315
1316 while (!iter.done()) {
1317 make_ust_field_class(session, iter, fp, add_field,
1318 lookup_field);
d0b96690 1319 }
7532fa3b
MD
1320
1321 return make_structure_field_class(0_bits, std::move(members));
1322}
1323
1324static
1325json make_user_attributes(json attributes)
1326{
1327 return {
1328 { "lttng.org,2009", attributes }
1329 };
1330}
1331
1332static
1333json make_event_record_class_user_attributes(const ust_registry_event &event)
1334{
1335 json user_attributes = make_user_attributes({
1336 { "log-level", event.loglevel_value },
1337 });
1338
1339 if (event.model_emf_uri) {
1340 user_attributes["emf-uri"] = event.model_emf_uri;
1341 }
1342
1343 return user_attributes;
d0b96690
DG
1344}
1345
1346/*
1347 * Should be called with session registry mutex held.
1348 */
1349int ust_metadata_event_statedump(struct ust_registry_session *session,
1350 struct ust_registry_channel *chan,
1351 struct ust_registry_event *event)
1352{
d0b96690
DG
1353 /* Don't dump metadata events */
1354 if (chan->chan_id == -1U)
1355 return 0;
1356
7532fa3b
MD
1357 /*
1358 * We don't want to output an event's metadata before its parent
1359 * stream's metadata. If the stream's metadata hasn't been output yet,
1360 * skip this event. Its metadata will be output when we output the
1361 * stream's metadata.
1362 */
1363 if (!chan->metadata_dumped) {
1364 return 0;
0d32d1a9 1365 }
d0b96690 1366
7532fa3b
MD
1367 LTTNG_ASSERT(!event->metadata_dumped);
1368
1369 try {
1370 json event_record_class = make_fragment("event-record-class");
1371 event_record_class.update({
1372 { "name", event->name },
1373 { "id", event->id },
1374 { "data-stream-class-id", chan->chan_id },
1375 { "user-attributes", make_event_record_class_user_attributes(*event) },
1376 });
d0b96690 1377
7532fa3b
MD
1378 if (event->nr_fields) {
1379 event_record_class["payload-field-class"] =
1380 make_event_record_class_payload_field_class(*session, *event);
0d32d1a9 1381 }
d0b96690 1382
7532fa3b 1383 lttng_metadata_print_fragment(*session, event_record_class);
d0b96690 1384
7532fa3b 1385 event->metadata_dumped = 1;
d0b96690 1386
7532fa3b
MD
1387 return 0;
1388 } catch (const std::exception &error) {
1389 ERR("%s", error.what());
1390 return -LTTNG_ERR_UNK;
1391 } catch (...) {
1392 return -LTTNG_ERR_UNK;
0d32d1a9 1393 }
7532fa3b 1394}
d0b96690 1395
7532fa3b
MD
1396static
1397json make_packet_context_field_class(const ust_registry_session &session)
1398{
1399 byte_order bo = get_byte_order(session, false);
1400 structure_members members;
1401
1402 members.add_member("timestamp_begin",
1403 make_fixed_length_unsigned_integer_field_class(
1404 64_bits, bo, 8_bits, display_base::DECIMAL,
1405 "packet-beginning-default-clock-timestamp"));
1406 members.add_member("timestamp_end",
1407 make_fixed_length_unsigned_integer_field_class(
1408 64_bits, bo, 8_bits, display_base::DECIMAL,
1409 "packet-end-default-clock-timestamp"));
1410 members.add_member("content_size",
1411 make_fixed_length_unsigned_integer_field_class(
1412 64_bits, bo, 8_bits, display_base::DECIMAL,
1413 "packet-content-size"));
1414 members.add_member("packet_size",
1415 make_fixed_length_unsigned_integer_field_class(
1416 64_bits, bo, 8_bits, display_base::DECIMAL,
1417 "packet-total-size"));
1418 members.add_member("packet_seq_num",
1419 make_fixed_length_unsigned_integer_field_class(
1420 64_bits, bo, 8_bits, display_base::DECIMAL,
1421 "packet-sequence-number"));
1422 members.add_member("events_discarded",
1423 make_fixed_length_unsigned_integer_field_class(
1424 bits(session.bits_per_long), bo,
1425 bits(session.long_alignment),
1426 display_base::DECIMAL,
1427 "discarded-event-record-counter-snapshot"));
1428 members.add_member("cpu_id",
1429 make_fixed_length_unsigned_integer_field_class(
1430 32_bits, bo, 8_bits, display_base::DECIMAL, nullptr));
1431
1432 return make_structure_field_class(0_bits, std::move(members));
1433}
1434
1435static
1436json make_record_header_compact_field_class(const ust_registry_session &session)
1437{
1438 byte_order bo = get_byte_order(session, false);
1439
1440 structure_members compact_members;
1441 compact_members.add_member("timestamp",
1442 make_fixed_length_unsigned_integer_field_class(
1443 27_bits, bo, 1_bits, display_base::DECIMAL,
1444 "default-clock-timestamp"));
1445
1446 structure_members extended_members;
1447 extended_members.add_member("id",
1448 make_fixed_length_unsigned_integer_field_class(
1449 32_bits, bo, 8_bits, display_base::DECIMAL,
1450 "event-record-class-id"));
1451 extended_members.add_member("timestamp",
1452 make_fixed_length_unsigned_integer_field_class(
1453 64_bits, bo, 8_bits, display_base::DECIMAL,
1454 "default-clock-timestamp"));
1455
1456 integer_range_set compact_ranges, extended_ranges;
1457 compact_ranges.add_range(UINT64_C(0), 30);
1458 extended_ranges.add_range(UINT64_C(31), 31);
1459
1460 variant_options options;
1461 options.add_option("compact",
1462 make_integer_range_set(compact_ranges),
1463 make_structure_field_class(0_bits, std::move(compact_members)));
1464 options.add_option("extended",
1465 make_integer_range_set(extended_ranges),
1466 make_structure_field_class(0_bits, std::move(extended_members)));
1467
1468 enumeration_mappings id_mappings;
1469 id_mappings.add_mapping("compact",
1470 make_integer_range_set(compact_ranges));
1471 id_mappings.add_mapping("extended",
1472 make_integer_range_set(extended_ranges));
1473
1474 structure_members members;
1475 members.add_member("id",
1476 make_fixed_length_unsigned_enumeration_field_class(
1477 5_bits, bo, 8_bits, display_base::DECIMAL,
1478 "event-record-class-id", std::move(id_mappings)));
1479 members.add_member("v",
1480 make_variant_field_class(std::move(options),
1481 {"event-record-header", "id"}));
1482
1483 return make_structure_field_class(8_bits, std::move(members));
1484}
1485
1486static
1487json make_record_header_large_field_class(const ust_registry_session &session)
1488{
1489 byte_order bo = get_byte_order(session, false);
1490
1491 structure_members compact_members;
1492 compact_members.add_member("timestamp",
1493 make_fixed_length_unsigned_integer_field_class(
1494 32_bits, bo, 8_bits, display_base::DECIMAL,
1495 "default-clock-timestamp"));
1496
1497 structure_members extended_members;
1498 extended_members.add_member("id",
1499 make_fixed_length_unsigned_integer_field_class(
1500 32_bits, bo, 8_bits, display_base::DECIMAL,
1501 "event-record-class-id"));
1502 extended_members.add_member("timestamp",
1503 make_fixed_length_unsigned_integer_field_class(
1504 64_bits, bo, 8_bits, display_base::DECIMAL,
1505 "default-clock-timestamp"));
1506
1507 integer_range_set compact_ranges, extended_ranges;
1508 compact_ranges.add_range(UINT64_C(0), 65534);
1509 extended_ranges.add_range(UINT64_C(65535), 65535);
1510
1511 variant_options options;
1512 options.add_option("compact",
1513 make_integer_range_set(compact_ranges),
1514 make_structure_field_class(0_bits, std::move(compact_members)));
1515 options.add_option("extended",
1516 make_integer_range_set(extended_ranges),
1517 make_structure_field_class(0_bits, std::move(extended_members)));
1518
1519 enumeration_mappings id_mappings;
1520 id_mappings.add_mapping("compact",
1521 make_integer_range_set(compact_ranges));
1522 id_mappings.add_mapping("extended",
1523 make_integer_range_set(extended_ranges));
1524
1525 structure_members members;
1526 members.add_member("id",
1527 make_fixed_length_unsigned_enumeration_field_class(
1528 16_bits, bo, 8_bits, display_base::DECIMAL,
1529 "event-record-class-id", std::move(id_mappings)));
1530 members.add_member("v",
1531 make_variant_field_class(std::move(options),
1532 { "event-record-header", "id" }));
1533
1534 return make_structure_field_class(8_bits, std::move(members));
1535}
1536
1537static
1538json make_record_header_field_class(const ust_registry_session &session,
1539 const ust_registry_channel &chan)
1540{
1541 if (chan.header_type == LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT) {
1542 return make_record_header_compact_field_class(session);
1543 } else {
1544 return make_record_header_large_field_class(session);
1545 }
d0b96690
DG
1546}
1547
1548/*
1549 * Should be called with session registry mutex held.
1550 */
1551int ust_metadata_channel_statedump(struct ust_registry_session *session,
1552 struct ust_registry_channel *chan)
1553{
d0b96690
DG
1554 /* Don't dump metadata events */
1555 if (chan->chan_id == -1U)
1556 return 0;
1557
1558 if (!chan->header_type)
1559 return -EINVAL;
1560
7532fa3b
MD
1561 try {
1562 json data_stream_class = make_fragment("data-stream-class");
1563 data_stream_class.update({
1564 { "id", chan->chan_id },
1565 { "packet-context-field-class",
1566 make_packet_context_field_class(*session) },
1567 { "event-record-header-field-class",
1568 make_record_header_field_class(*session, *chan) },
1569 });
1570
1571 if (chan->ctx_fields) {
1572 data_stream_class.update({
1573 { "event-record-common-context-field-class",
1574 make_record_common_context_field_class(*session, *chan) }
1575 });
0d32d1a9 1576 }
d0b96690 1577
7532fa3b 1578 lttng_metadata_print_fragment(*session, data_stream_class);
d0b96690 1579
7532fa3b
MD
1580 /* Flag success of metadata dump. */
1581 chan->metadata_dumped = 1;
d0b96690 1582
7532fa3b
MD
1583 /*
1584 * Output the metadata of any existing event.
1585 *
1586 * Sort the events by id. This is not necessary, but it's nice to have
1587 * a more predictable order in the metadata file.
1588 */
1589 std::vector<ust_registry_event *> events;
1590 {
1591 cds_lfht_iter event_iter;
1592 ust_registry_event *event;
1593 cds_lfht_for_each_entry(chan->events->ht, &event_iter, event,
1594 node.node) {
1595 events.push_back(event);
1596 }
1597 }
d0b96690 1598
7532fa3b
MD
1599 std::sort(events.begin(), events.end(),
1600 [] (ust_registry_event *a, ust_registry_event *b) {
1601 return a->id < b->id;
1602 });
1603
1604 for (ust_registry_event *event : events) {
1605 ust_metadata_event_statedump(session, chan, event);
1606 }
1607
1608 return 0;
1609 } catch (const std::exception &error) {
1610 ERR("%s", error.what());
1611 return -LTTNG_ERR_UNK;
1612 } catch (...) {
1613 return -LTTNG_ERR_UNK;
1614 }
d0b96690
DG
1615}
1616
dc113ec7
MD
1617/*
1618 * The offset between monotonic and realtime clock can be negative if
1619 * the system sets the REALTIME clock to 0 after boot.
dc113ec7 1620 */
d0b96690 1621static
8c645bb0 1622int measure_single_clock_offset(struct offset_sample *sample)
d0b96690 1623{
dc113ec7 1624 uint64_t monotonic_avg, monotonic[2], measure_delta, realtime;
fc0bb9fa 1625 uint64_t tcf = trace_clock_freq();
d0b96690
DG
1626 struct timespec rts = { 0, 0 };
1627 int ret;
1628
1629 monotonic[0] = trace_clock_read64();
389fbf04 1630 ret = lttng_clock_gettime(CLOCK_REALTIME, &rts);
8c645bb0
MD
1631 if (ret < 0) {
1632 return ret;
1633 }
d0b96690 1634 monotonic[1] = trace_clock_read64();
8c645bb0
MD
1635 measure_delta = monotonic[1] - monotonic[0];
1636 if (measure_delta > sample->measure_delta) {
1637 /*
1638 * Discard value if it took longer to read than the best
1639 * sample so far.
1640 */
1641 return 0;
1642 }
dc113ec7 1643 monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
6e1b0543
MD
1644 realtime = (uint64_t) rts.tv_sec * tcf;
1645 if (tcf == NSEC_PER_SEC) {
1646 realtime += rts.tv_nsec;
1647 } else {
1648 realtime += (uint64_t) rts.tv_nsec * tcf / NSEC_PER_SEC;
fc0bb9fa 1649 }
c2636b57 1650 sample->offset = (int64_t) realtime - monotonic_avg;
8c645bb0
MD
1651 sample->measure_delta = measure_delta;
1652 return 0;
d0b96690
DG
1653}
1654
8c645bb0
MD
1655/*
1656 * Approximation of NTP time of day to clock monotonic correlation,
1657 * taken at start of trace. Keep the measurement that took the less time
1658 * to complete, thus removing imprecision caused by preemption.
c2636b57 1659 * May return a negative offset.
8c645bb0
MD
1660 */
1661static
c2636b57 1662int64_t measure_clock_offset(void)
8c645bb0
MD
1663{
1664 int i;
1665 struct offset_sample offset_best_sample = {
1666 .offset = 0,
1667 .measure_delta = UINT64_MAX,
1668 };
1669
1670 for (i = 0; i < NR_CLOCK_OFFSET_SAMPLES; i++) {
1671 if (measure_single_clock_offset(&offset_best_sample)) {
1672 return 0;
1673 }
1674 }
1675 return offset_best_sample.offset;
1676}
d0b96690
DG
1677
1678/*
1679 * Should be called with session registry mutex held.
1680 */
1681int ust_metadata_session_statedump(struct ust_registry_session *session,
af6142cf
MD
1682 struct ust_app *app,
1683 uint32_t major,
1684 uint32_t minor)
d0b96690 1685{
a0377dfe 1686 LTTNG_ASSERT(session);
7972aab2 1687
7532fa3b
MD
1688 try {
1689 json preamble = make_fragment("preamble");
1690 preamble.update({
1691 { "version", 2 },
1692 });
1693 lttng_metadata_print_fragment(*session, preamble);
1694
1695 json trace_class = make_fragment("trace-class");
1696 trace_class.update({
1697 { "packet-header-field-class",
1698 make_packet_header_field_class(*session) },
1699 { "uuid", make_uuid (session->uuid) }
1700 });
1701 lttng_metadata_print_fragment(*session, trace_class);
1702
1703 uint64_t clock_freq = trace_clock_freq();
1704 json clock_class = make_fragment("clock-class");
1705 clock_class.update({
1706 { "name", trace_clock_name() },
1707 { "description", trace_clock_description() },
1708 { "frequency", clock_freq },
1709 { "offset", make_clock_offset(measure_clock_offset(), clock_freq) },
1710 });
1711
1712 char clock_uuid_str[LTTNG_UUID_STR_LEN];
1713 int ret = trace_clock_uuid(clock_uuid_str);
1714 if (ret == 0) {
1715 uint8_t clock_uuid[LTTNG_UUID_LEN];
1716 ret = lttng_uuid_from_str(clock_uuid_str, clock_uuid);
1717 if (ret == 0) {
1718 clock_class["uuid"] = make_uuid(clock_uuid);
1719 } else {
1720 // FIXME: warn?
1721 }
1722 } else {
1723 // FIXME: warn?
0d32d1a9 1724 }
d0b96690 1725
7532fa3b 1726 lttng_metadata_print_fragment(*session, clock_class);
d0b96690 1727
7532fa3b
MD
1728 return 0;
1729 } catch (const std::exception &error) {
1730 ERR("%s", error.what());
1731 return -LTTNG_ERR_UNK;
1732 } catch (...) {
1733 return -LTTNG_ERR_UNK;
0d32d1a9 1734 }
d0b96690 1735}
This page took 0.179903 seconds and 5 git commands to generate.