Common Trace Format 2 generation
[deliverable/lttng-tools.git] / src / bin / lttng-sessiond / ust-metadata.cpp
1 /*
2 * Copyright (C) 2010-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include "common/bytecode/bytecode.hpp"
9 #include "common/macros.hpp"
10 #include "common/uuid.hpp"
11 #include <endian.h>
12 #define _LGPL_SOURCE
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>
20 #include <common/common.hpp>
21 #include <common/time.hpp>
22 #include <vector>
23 #include <vendor/nlohmann/json.hpp>
24
25 #include "ust-registry.hpp"
26 #include "ust-clock.hpp"
27 #include "ust-app.hpp"
28
29 #define NR_CLOCK_OFFSET_SAMPLES 10
30
31 using json = nlohmann::json;
32
33 struct offset_sample {
34 int64_t offset; /* correlation offset */
35 uint64_t measure_delta; /* lower is better */
36 };
37
38 enum class byte_order
39 {
40 BIG,
41 LITTLE,
42 };
43
44 enum class display_base
45 {
46 BINARY,
47 OCTAL,
48 DECIMAL,
49 HEXADECIMAL,
50 };
51
52 struct metadata_generation_exception : public std::runtime_error
53 {
54 metadata_generation_exception(const char *what)
55 : std::runtime_error(what)
56 {}
57 };
58
59 struct 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
85 private:
86 const lttng_ust_ctl_field *_array;
87 size_t _cur = 0;
88 size_t _len;
89 };
90
91 static
92 byte_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
101 struct 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
123 private:
124 const uint64_t _val;
125 };
126
127 static
128 bits operator"" _bits(unsigned long long val)
129 {
130 return bits(val);
131 }
132
133 static
134 json make_fragment(const char *type)
135 {
136 return {
137 { "type", type }
138 };
139 }
140
141 static
142 json 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
155 static
156 const 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
168 static
169 json 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
186 static
187 json 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
203 static
204 json 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
217 static
218 json 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
228 static
229 json 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
239 static
240 json 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
249 static
250 json 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
259 static
260 json 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
267 struct 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
281 struct 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
306 private:
307 vec_type _ranges;
308 };
309
310 struct 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
320 struct 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
340 private:
341 vec_type _mappings;
342 };
343
344 static
345 json 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
356 static json
357 make_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
368 static
369 json 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
378 static
379 json 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
392 static
393 json 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
406 static
407 json 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
423 static
424 json 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
435 static
436 json make_uuid_field_class(const char *role)
437 {
438 return make_static_length_blob_field_class(16, role);
439 }
440
441 struct 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
454 struct 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
476 private:
477 vec_type _members;
478 };
479
480 static
481 json make_struct_member(structure_member member)
482 {
483 return {
484 { "name", member.name },
485 { "field-class", std::move(member.field_class) },
486 };
487 }
488
489 static
490 json 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
501 static
502 json 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
517 struct 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
551 private:
552 /*
553 * Buffer for `name`, if it is dynamically allocated andmanaged by us.
554 */
555 const std::string _name_buf;
556
557 public:
558 const char *name;
559 json selector_field_ranges;
560 json field_class;
561 };
562
563 struct 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
603 private:
604 vec_type _options;
605 };
606
607 struct 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
650 private:
651 vec_type _path;
652 };
653
654 static
655 json 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
664 static
665 json 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
676 static
677 json make_field_location(const field_path &field_location)
678 {
679 return field_location.path();
680 }
681
682 static
683 json 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
695 static
696 json 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
710 static
711 json 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
722 static
723 json 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
735 static
736 json make_string_field_class()
737 {
738 return make_field_class("null-terminated-string", nullptr);
739 }
740
741 static
742 json 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
766 static
767 json 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
778 static
779 json 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 }
794
795 static inline
796 int get_count_order(unsigned int count)
797 {
798 int order;
799
800 order = lttng_fls(count) - 1;
801 if (count & (count - 1)) {
802 order++;
803 }
804 LTTNG_ASSERT(order >= 0);
805 return order;
806 }
807
808 /*
809 * Returns offset where to write in metadata array, or negative error value on error.
810 */
811 static
812 ssize_t metadata_reserve(ust_registry_session &session, size_t len)
813 {
814 size_t new_len = session.metadata_len + len;
815 size_t new_alloc_len = new_len;
816 size_t old_alloc_len = session.metadata_alloc_len;
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 =
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);
830 if (!newptr)
831 return -ENOMEM;
832 session.metadata = newptr;
833 /* We zero directly the memory from start of allocation. */
834 memset(&session.metadata[old_alloc_len], 0, new_alloc_len - old_alloc_len);
835 session.metadata_alloc_len = new_alloc_len;
836 }
837 ret = session.metadata_len;
838 session.metadata_len += len;
839 return ret;
840 }
841
842 static
843 int metadata_file_append(ust_registry_session &session,
844 const char *str, size_t len)
845 {
846 ssize_t written;
847
848 if (session.metadata_fd < 0) {
849 return 0;
850 }
851 /* Write to metadata file */
852 written = lttng_write(session.metadata_fd, str, len);
853 if (written != len) {
854 return -1;
855 }
856 return 0;
857 }
858
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 */
865 static ATTR_FORMAT_PRINTF(2, 3)
866 int lttng_metadata_printf(ust_registry_session &session,
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 }
887 memcpy(&session.metadata[offset], str, len);
888 ret = metadata_file_append(session, str, len);
889 if (ret) {
890 PERROR("Error appending to metadata file");
891 goto end;
892 }
893 DBG3("Append to metadata: \"%s\"", str);
894 ret = 0;
895
896 end:
897 free(str);
898 return ret;
899 }
900
901
902 static
903 void lttng_metadata_print_fragment(ust_registry_session &session,
904 const json &fragment)
905 {
906 lttng_metadata_printf(session, "\x1e%s", fragment.dump(2).c_str());
907 }
908
909 static
910 display_base int_to_display_base(int base)
911 {
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;
923 }
924 }
925
926 static
927 json 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);
940 }
941 }
942
943 /* Called with session registry mutex held. */
944 static
945 json 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 {
949 rcu_read_lock();
950 const ust_registry_enum *reg_enum = ust_registry_lookup_enum_by_id(
951 session, name, id);
952 rcu_read_unlock();
953
954 /* reg_enum can still be used because session registry mutex is held. */
955 if (!reg_enum) {
956 return -ENOENT;
957 }
958
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;
973 }
974
975 for (size_t i = 0; i < reg_enum->nr_entries; ++i) {
976 const lttng_ust_ctl_enum_entry &entry = entries[i];
977
978 //len = strlen(entry->string);
979
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;
987 } else {
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;
992 }
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));
1003 }
1004 }
1005 }
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));
1012 }
1013
1014 static
1015 void 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);
1020
1021 static
1022 void 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 };
1050
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);
1057 }
1058 }
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));
1063 }
1064
1065 static
1066 void 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();
1073
1074 switch (field.type.atype) {
1075 case lttng_ust_ctl_atype_integer:
1076 add_field(field.name,
1077 make_ust_integer_field_class(session,
1078 field.type.u.integer));
1079 break;
1080
1081 case lttng_ust_ctl_atype_enum:
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));
1088 break;
1089 }
1090
1091 case lttng_ust_ctl_atype_float:
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
1100 break;
1101 }
1102
1103 case lttng_ust_ctl_atype_array:
1104 {
1105 const auto &array_type = field.type.u.legacy.array;
1106
1107 /* Only integers are currently supported in arrays. */
1108 if (array_type.elem_type.atype != lttng_ust_ctl_atype_integer) {
1109 throw metadata_generation_exception(
1110 "array element type not supported");
1111 }
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
1118 break;
1119 }
1120
1121 case lttng_ust_ctl_atype_array_nestable:
1122 {
1123 const struct lttng_ust_ctl_type &element_type =
1124 field_iterator.get_next().type;
1125
1126 /* Only integers are currently supported in arrays. */
1127 if (element_type.atype != lttng_ust_ctl_atype_integer) {
1128 throw metadata_generation_exception(
1129 "array element type not supported");
1130 }
1131
1132 const auto &array_type = field.type.u.array_nestable;
1133
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)));
1140 break;
1141 }
1142
1143 case lttng_ust_ctl_atype_sequence:
1144 {
1145 const auto &t = field.type.u.legacy.sequence;
1146
1147 /* Only integers are currently supported in sequences. */
1148 if (t.elem_type.atype != lttng_ust_ctl_atype_integer) {
1149 throw metadata_generation_exception(
1150 "sequence element type not supported");
1151 }
1152
1153 const lttng_ust_ctl_integer_type &length_type
1154 = t.length_type.u.basic.integer;
1155
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));
1167 break;
1168 }
1169 case lttng_ust_ctl_atype_sequence_nestable:
1170 {
1171 const struct lttng_ust_ctl_type &element_type =
1172 field_iterator.get_next().type;
1173
1174 /* Only integers are currently supported in sequences. */
1175 if (element_type.atype != lttng_ust_ctl_atype_integer) {
1176 throw metadata_generation_exception(
1177 "sequence element type not supported");
1178 }
1179
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)));
1191 break;
1192 }
1193
1194 case lttng_ust_ctl_atype_string:
1195 add_field(field.name, make_string_field_class());
1196 break;
1197
1198 case lttng_ust_ctl_atype_variant:
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);
1206 break;
1207 }
1208
1209 case lttng_ust_ctl_atype_variant_nestable:
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);
1217 break;
1218 }
1219
1220 case lttng_ust_ctl_atype_struct:
1221 if (field.type.u.legacy._struct.nr_fields != 0) {
1222 /* Currently only 0-length structures are supported. */
1223 throw metadata_generation_exception("Only 0-length structures are supported");
1224 }
1225
1226 /* Don't emit anything */
1227 break;
1228
1229 case lttng_ust_ctl_atype_struct_nestable:
1230 if (field.type.u.struct_nestable.nr_fields != 0) {
1231 /* Currently only 0-length structures are supported. */
1232 throw metadata_generation_exception("Only 0-length structures are supported");
1233 }
1234
1235 /* Don't emit anything */
1236 break;
1237
1238 case lttng_ust_ctl_atype_enum_nestable:
1239 {
1240 const lttng_ust_ctl_field &container =
1241 field_iterator.get_next();
1242
1243 /* Only integers are supported as container types. */
1244 if (container.type.atype != lttng_ust_ctl_atype_integer) {
1245 throw metadata_generation_exception(
1246 "Enumeration container type not an integer");
1247 }
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));
1254 break;
1255 }
1256 default:
1257 throw metadata_generation_exception(
1258 "Unhandled lttng-ust field type");
1259 }
1260 }
1261
1262 static
1263 json make_record_common_context_field_class(
1264 const ust_registry_session &session,
1265 const ust_registry_channel &chan)
1266 {
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;
1270
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 }
1280 }
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);
1288 }
1289
1290 return make_structure_field_class(0_bits, std::move(members));
1291 }
1292
1293 static
1294 json make_event_record_class_payload_field_class(
1295 const ust_registry_session &session,
1296 const ust_registry_event &event)
1297 {
1298 lttng_ust_ctl_field_iterator iter(event.fields, event.nr_fields);
1299 field_path fp("event-record-payload");
1300 structure_members members;
1301
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 }
1311 }
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);
1319 }
1320
1321 return make_structure_field_class(0_bits, std::move(members));
1322 }
1323
1324 static
1325 json make_user_attributes(json attributes)
1326 {
1327 return {
1328 { "lttng.org,2009", attributes }
1329 };
1330 }
1331
1332 static
1333 json 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;
1344 }
1345
1346 /*
1347 * Should be called with session registry mutex held.
1348 */
1349 int ust_metadata_event_statedump(struct ust_registry_session *session,
1350 struct ust_registry_channel *chan,
1351 struct ust_registry_event *event)
1352 {
1353 /* Don't dump metadata events */
1354 if (chan->chan_id == -1U)
1355 return 0;
1356
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;
1365 }
1366
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 });
1377
1378 if (event->nr_fields) {
1379 event_record_class["payload-field-class"] =
1380 make_event_record_class_payload_field_class(*session, *event);
1381 }
1382
1383 lttng_metadata_print_fragment(*session, event_record_class);
1384
1385 event->metadata_dumped = 1;
1386
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;
1393 }
1394 }
1395
1396 static
1397 json 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
1435 static
1436 json 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
1486 static
1487 json 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
1537 static
1538 json 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 }
1546 }
1547
1548 /*
1549 * Should be called with session registry mutex held.
1550 */
1551 int ust_metadata_channel_statedump(struct ust_registry_session *session,
1552 struct ust_registry_channel *chan)
1553 {
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
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 });
1576 }
1577
1578 lttng_metadata_print_fragment(*session, data_stream_class);
1579
1580 /* Flag success of metadata dump. */
1581 chan->metadata_dumped = 1;
1582
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 }
1598
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 }
1615 }
1616
1617 /*
1618 * The offset between monotonic and realtime clock can be negative if
1619 * the system sets the REALTIME clock to 0 after boot.
1620 */
1621 static
1622 int measure_single_clock_offset(struct offset_sample *sample)
1623 {
1624 uint64_t monotonic_avg, monotonic[2], measure_delta, realtime;
1625 uint64_t tcf = trace_clock_freq();
1626 struct timespec rts = { 0, 0 };
1627 int ret;
1628
1629 monotonic[0] = trace_clock_read64();
1630 ret = lttng_clock_gettime(CLOCK_REALTIME, &rts);
1631 if (ret < 0) {
1632 return ret;
1633 }
1634 monotonic[1] = trace_clock_read64();
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 }
1643 monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
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;
1649 }
1650 sample->offset = (int64_t) realtime - monotonic_avg;
1651 sample->measure_delta = measure_delta;
1652 return 0;
1653 }
1654
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.
1659 * May return a negative offset.
1660 */
1661 static
1662 int64_t measure_clock_offset(void)
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 }
1677
1678 /*
1679 * Should be called with session registry mutex held.
1680 */
1681 int ust_metadata_session_statedump(struct ust_registry_session *session,
1682 struct ust_app *app,
1683 uint32_t major,
1684 uint32_t minor)
1685 {
1686 LTTNG_ASSERT(session);
1687
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?
1724 }
1725
1726 lttng_metadata_print_fragment(*session, clock_class);
1727
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;
1734 }
1735 }
This page took 0.06608 seconds and 5 git commands to generate.