2 * Copyright (C) 2010-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
8 #include "common/bytecode/bytecode.hpp"
9 #include "common/macros.hpp"
10 #include "common/uuid.hpp"
20 #include <common/common.hpp>
21 #include <common/time.hpp>
23 #include <vendor/nlohmann/json.hpp>
25 #include "ust-registry.hpp"
26 #include "ust-clock.hpp"
27 #include "ust-app.hpp"
29 #define NR_CLOCK_OFFSET_SAMPLES 10
31 using json
= nlohmann::json
;
33 struct offset_sample
{
34 int64_t offset
; /* correlation offset */
35 uint64_t measure_delta
; /* lower is better */
44 enum class display_base
52 struct metadata_generation_exception
: public std::runtime_error
54 metadata_generation_exception(const char *what
)
55 : std::runtime_error(what
)
59 struct lttng_ust_ctl_field_iterator
61 lttng_ust_ctl_field_iterator(const lttng_ust_ctl_field
*array
,
63 : _array(array
), _len(len
)
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;
70 const lttng_ust_ctl_field
&get_next()
73 throw metadata_generation_exception(
74 "Field iterator overflow");
77 return _array
[_cur
++];
86 const lttng_ust_ctl_field
*_array
;
92 byte_order
get_byte_order(const ust_registry_session
&session
, bool reverse
)
94 if (session
.byte_order
== BIG_ENDIAN
) {
95 return reverse
? byte_order::LITTLE
: byte_order::BIG
;
97 return reverse
? byte_order::BIG
: byte_order::LITTLE
;
103 using underlying_type
= uint64_t;
104 explicit bits(uint64_t val
)
108 underlying_type
to_underlying() const
110 return static_cast<underlying_type
>(_val
);
113 bool operator==(bits other
)
115 return to_underlying() == other
.to_underlying();
118 bool operator!=(bits other
)
120 return to_underlying() != other
.to_underlying();
128 bits
operator"" _bits(unsigned long long val
)
134 json
make_fragment(const char *type
)
142 json
make_field_class(const char *type
, const char *role
)
149 fc
["roles"] = {role
};
156 const char *make_byte_order(byte_order byte_order
)
158 switch (byte_order
) {
159 case byte_order::BIG
:
161 case byte_order::LITTLE
:
162 return "little-endian";
169 json
make_fixed_length_bit_array_field_class(const char *type
, bits length
,
170 byte_order byte_order
, bits alignment
, const char *role
)
172 json fc
= make_field_class(type
, role
);
175 { "length", length
.to_underlying() },
176 { "byte-order", make_byte_order(byte_order
) },
179 if (alignment
!= 0_bits
) {
180 fc
["alignment"] = alignment
.to_underlying();
187 json
make_display_base(display_base display_base
)
189 switch (display_base
) {
190 case display_base::BINARY
:
192 case display_base::OCTAL
:
194 case display_base::DECIMAL
:
196 case display_base::HEXADECIMAL
:
204 json
make_abstract_integer_field_class(display_base preferred_display_base
)
206 json base
= json::object();
207 if (preferred_display_base
!= display_base::DECIMAL
) {
209 { "preferred-display-base",
210 make_display_base(preferred_display_base
)},
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
)
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
));
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
)
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
));
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
)
244 return make_fixed_length_unsigned_integer_field_class(
245 "fixed-length-unsigned-integer", length
, byte_order
,
246 alignment
, preferred_display_base
, role
);
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
)
254 return make_fixed_length_signed_integer_field_class(
255 "fixed-length-signed-integer", length
, byte_order
,
256 alignment
, preferred_display_base
, role
);
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);
269 integer_range(int64_t lower_bound_
, int64_t upper_bound_
)
270 : is_signed(true), lower_bound(lower_bound_
), upper_bound(upper_bound_
)
273 integer_range(uint64_t lower_bound_
, uint64_t upper_bound_
)
274 : is_signed(false), lower_bound(lower_bound_
), upper_bound(upper_bound_
)
277 const bool is_signed
;
278 const int64_t lower_bound
, upper_bound
;
281 struct integer_range_set
283 using vec_type
= std::vector
<integer_range
>;
284 using const_iterator
= vec_type::const_iterator
;
286 integer_range_set() = default;
287 DISABLE_COPY_AND_ASSIGN(integer_range_set
);
288 integer_range_set(integer_range_set
&&) = default;
290 void add_range(int64_t lower_bound
, int64_t upper_bound
)
292 _ranges
.emplace_back(lower_bound
, upper_bound
);
295 void add_range(uint64_t lower_bound
, uint64_t upper_bound
)
297 _ranges
.emplace_back(lower_bound
, upper_bound
);
300 const_iterator
begin() const
301 { return _ranges
.begin(); }
303 const_iterator
end() const
304 { return _ranges
.end(); }
310 struct enumeration_mapping
312 enumeration_mapping(const char *name_
, json ranges_
)
313 : name(name_
), ranges(std::move(ranges_
))
316 const char *const name
;
320 struct enumeration_mappings
322 using vec_type
= std::vector
<enumeration_mapping
>;
323 using const_iterator
= vec_type::const_iterator
;
325 enumeration_mappings() = default;
326 DISABLE_COPY_AND_ASSIGN(enumeration_mappings
);
327 enumeration_mappings(enumeration_mappings
&&) = default;
329 void add_mapping(const char *name_
, json ranges_
)
331 _mappings
.emplace_back(name_
, std::move(ranges_
));
334 const_iterator
begin() const
335 { return _mappings
.begin(); }
337 const_iterator
end() const
338 { return _mappings
.end(); }
345 json
make_integer_range_set(const integer_range_set
&ranges
)
347 json rs
= json::array();
349 for (const integer_range
&range
: ranges
) {
350 rs
.push_back({ range
.lower_bound
, range
.upper_bound
});
357 make_enumeration_mappings(enumeration_mappings mappings
)
359 json mappings_obj
= json::object();
361 for (const enumeration_mapping
&mapping
: mappings
) {
362 mappings_obj
[mapping
.name
] = std::move(mapping
.ranges
);
369 json
make_abstract_enumeration_field_class(display_base preferred_display_base
,
370 enumeration_mappings mappings
)
372 json fc
= make_abstract_integer_field_class(preferred_display_base
);
373 fc
["mappings"] = make_enumeration_mappings(std::move(mappings
));
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
)
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
)));
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
)
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
)));
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
)
413 return make_fixed_length_signed_enumeration_field_class(
414 length
, byte_order
, alignment
, preferred_display_base
,
415 nullptr, std::move(mappings
));
417 return make_fixed_length_unsigned_enumeration_field_class(
418 length
, byte_order
, alignment
, preferred_display_base
,
419 nullptr, std::move(mappings
));
424 json
make_static_length_blob_field_class(uint64_t length
, const char *role
)
426 json fc
= make_field_class("static-length-blob", role
);
429 { "length", length
},
436 json
make_uuid_field_class(const char *role
)
438 return make_static_length_blob_field_class(16, role
);
441 struct structure_member
443 structure_member(const char *name_
, json field_class_
)
444 : name(name_
), field_class(std::move(field_class_
))
447 DISABLE_COPY_AND_ASSIGN(structure_member
);
448 structure_member(structure_member
&&) = default;
450 const char *const name
;
454 struct structure_members
456 using vec_type
= std::vector
<structure_member
>;
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;
463 void add_member(const char *name
, json field_class
)
465 _members
.emplace_back(structure_member(
466 name
, std::move(field_class
)
470 vec_type::iterator
begin()
471 { return _members
.begin (); }
473 vec_type::iterator
end()
474 { return _members
.end (); }
481 json
make_struct_member(structure_member member
)
484 { "name", member
.name
},
485 { "field-class", std::move(member
.field_class
) },
490 json
make_structure_members(structure_members members
)
492 json members_obj
= json::array();
494 for (structure_member
&member
: members
) {
495 members_obj
.push_back(make_struct_member(std::move(member
)));
502 json
make_structure_field_class(bits minimum_alignment
,
503 structure_members members
)
505 json fc
= make_field_class("structure", nullptr);
507 fc
["member-classes"] = make_structure_members(std::move(members
));
509 if (minimum_alignment
!= 0_bits
) {
510 fc
["minimum-alignment"] = minimum_alignment
.to_underlying();
517 struct variant_option
519 variant_option(const char *name_
,
520 json selector_field_ranges_
,
523 selector_field_ranges(std::move(selector_field_ranges_
)),
524 field_class(std::move(field_class_
))
527 variant_option(std::string name_
,
528 json selector_field_ranges_
,
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_
))
536 DISABLE_COPY_AND_ASSIGN(variant_option
);
538 variant_option(variant_option
&&other
)
539 : _name_buf(std::move(other
._name_buf
)),
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.
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
)
553 * Buffer for `name`, if it is dynamically allocated andmanaged by us.
555 const std::string _name_buf
;
559 json selector_field_ranges
;
563 struct variant_options
565 using vec_type
= std::vector
<variant_option
>;
566 using iterator
= vec_type::iterator
;
567 using const_iterator
= vec_type::const_iterator
;
569 variant_options() = default;
570 DISABLE_COPY_AND_ASSIGN(variant_options
);
571 variant_options(variant_options
&&) = default;
573 void add_option(const char *name
, json selector_field_ranges
,
576 _options
.emplace_back(variant_option(
577 name
, std::move(selector_field_ranges
),
578 std::move(field_class
)
582 void add_option(std::string name
, json selector_field_ranges
,
585 _options
.emplace_back(variant_option(
586 std::move(name
), std::move(selector_field_ranges
),
587 std::move(field_class
)
592 { return _options
.begin(); }
595 { return _options
.end(); }
597 const_iterator
begin() const
598 { return _options
.begin(); }
600 const_iterator
end() const
601 { return _options
.end(); }
609 using vec_type
= std::vector
<const char *>;
613 popper(struct field_path
&path
)
617 popper(const popper
&) = delete;
618 popper(popper
&&) = default;
619 void operator=(const popper
&) = delete;
623 _path
._path
.pop_back();
631 field_path(const char *root
)
635 field_path(std::initializer_list
<const char *> list
)
639 const vec_type
&path() const
644 popper
push(const char *element
)
646 _path
.push_back(element
);
647 return popper(*this);
655 json
make_variant_option(variant_option option
)
658 { "name", option
.name
},
659 { "selector-field-ranges", std::move(option
.selector_field_ranges
) },
660 { "field-class", std::move(option
.field_class
) },
665 json
make_variant_options(variant_options options
)
667 json options_obj
= json::array();
669 for (variant_option
&option
: options
) {
670 options_obj
.push_back(make_variant_option(std::move(option
)));
677 json
make_field_location(const field_path
&field_location
)
679 return field_location
.path();
683 json
make_variant_field_class(variant_options options
,
684 const field_path
&selector_field_location
)
686 json fc
= make_field_class("variant", nullptr);
688 fc
["options"] = make_variant_options(std::move(options
));
689 fc
["selector-field-location"] =
690 make_field_location(selector_field_location
);
696 json
make_array_field_class(const char *type
, json element_field_class
,
697 bits minimum_alignment
)
699 json fc
= make_field_class(type
, nullptr);
701 fc
["element-field-class"] = std::move(element_field_class
);
703 if (minimum_alignment
!= 0_bits
) {
704 fc
["minimum-alignment"] = minimum_alignment
.to_underlying();
711 json
make_static_length_array_field_class(json element_field_class
,
712 uint64_t length
, bits minimum_alignment
)
714 json fc
= make_array_field_class("static-length-array",
715 element_field_class
, minimum_alignment
);
717 fc
["length"] = length
;
723 json
make_dynamic_length_array_field_class(json element_field_class
,
724 const field_path
&length_field_location
, bits minimum_alignment
)
726 json fc
= make_array_field_class("dynamic-length-array",
727 element_field_class
, minimum_alignment
);
729 fc
["length-field-location"] =
730 make_field_location(length_field_location
);
736 json
make_string_field_class()
738 return make_field_class("null-terminated-string", nullptr);
742 json
make_packet_header_field_class(const ust_registry_session
&session
)
744 byte_order bo
= get_byte_order(session
, false);
746 structure_members members
;
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
,
763 return make_structure_field_class(0_bits
, std::move(members
));
767 json
make_uuid(uint8_t uuid_bytes
[LTTNG_UUID_LEN
])
769 json uuid
= json::array();
771 for (size_t i
= 0; i
< LTTNG_UUID_LEN
; ++i
) {
772 uuid
.push_back(uuid_bytes
[i
]);
779 json
make_clock_offset(int64_t offset_cycles
, uint64_t freq
)
781 // FIXME: not tested at all, especially not for negative values of offset
784 int64_t s
= offset_cycles
/ freq
;
786 /* Remaining cycles. */
787 int64_t cycles
= offset_cycles
% freq
;
791 { "cycles", cycles
},
796 int get_count_order(unsigned int count
)
800 order
= lttng_fls(count
) - 1;
801 if (count
& (count
- 1)) {
804 LTTNG_ASSERT(order
>= 0);
809 * Returns offset where to write in metadata array, or negative error value on error.
812 ssize_t
metadata_reserve(ust_registry_session
&session
, size_t len
)
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
;
819 if (new_alloc_len
> (UINT32_MAX
>> 1))
821 if ((old_alloc_len
<< 1) > (UINT32_MAX
>> 1))
824 if (new_alloc_len
> old_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
);
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
;
837 ret
= session
.metadata_len
;
838 session
.metadata_len
+= len
;
843 int metadata_file_append(ust_registry_session
&session
,
844 const char *str
, size_t len
)
848 if (session
.metadata_fd
< 0) {
851 /* Write to metadata file */
852 written
= lttng_write(session
.metadata_fd
, str
, len
);
853 if (written
!= len
) {
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.
865 static ATTR_FORMAT_PRINTF(2, 3)
866 int lttng_metadata_printf(ust_registry_session
&session
,
867 const char *fmt
, ...)
876 ret
= vasprintf(&str
, fmt
, ap
);
882 offset
= metadata_reserve(session
, len
);
887 memcpy(&session
.metadata
[offset
], str
, len
);
888 ret
= metadata_file_append(session
, str
, len
);
890 PERROR("Error appending to metadata file");
893 DBG3("Append to metadata: \"%s\"", str
);
903 void lttng_metadata_print_fragment(ust_registry_session
&session
,
904 const json
&fragment
)
906 lttng_metadata_printf(session
, "\x1e%s", fragment
.dump(2).c_str());
910 display_base
int_to_display_base(int base
)
912 /* If we ever get an invalid value, default to 10. */
915 return display_base::BINARY
;
917 return display_base::OCTAL
;
920 return display_base::DECIMAL
;
922 return display_base::HEXADECIMAL
;
927 json
make_ust_integer_field_class(const ust_registry_session
&session
,
928 const lttng_ust_ctl_integer_type
&type
)
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
),
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
),
943 /* Called with session registry mutex held. */
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
)
950 const ust_registry_enum
*reg_enum
= ust_registry_lookup_enum_by_id(
954 /* reg_enum can still be used because session registry mutex is held. */
959 bool is_signed
= container
.signedness
;
960 enumeration_mappings mappings
;
962 const lttng_ust_ctl_enum_entry
*entries
= reg_enum
->entries
;
967 } next_auto_low_bound
;
970 next_auto_low_bound
.sign
= 0;
972 next_auto_low_bound
.nosign
= 0;
975 for (size_t i
= 0; i
< reg_enum
->nr_entries
; ++i
) {
976 const lttng_ust_ctl_enum_entry
&entry
= entries
[i
];
978 //len = strlen(entry->string);
980 if (entry
.u
.extra
.options
&
981 LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO
) {
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
;
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
;
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
));
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
));
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
));
1015 void make_ust_field_class(const ust_registry_session
&session
,
1016 lttng_ust_ctl_field_iterator
&field_iterator
,
1017 field_path
¤t_field_path
,
1018 std::function
<void(const char *, json
)> add_field
,
1019 std::function
<const json
&(const char *)> get_last_field
);
1022 void make_ust_variant_field_class(
1023 const ust_registry_session
&session
,
1024 lttng_ust_ctl_field_iterator
&field_iterator
,
1025 field_path
¤t_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
)
1032 variant_options options
;
1033 const json
&selector_field
= lookup_field (selector_name
);
1034 const json
&mappings
= selector_field
["mappings"];
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
];
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
1048 options
.add_option(std::move(option_name_prefixed
), ranges
, option_fc
);
1052 auto field_location_popper
= current_field_path
.push(field_name
);
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
);
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
));
1066 void make_ust_field_class(const ust_registry_session
&session
,
1067 lttng_ust_ctl_field_iterator
&field_iterator
,
1068 field_path
¤t_field_path
,
1069 std::function
<void(const char *, json
)> add_field
,
1070 std::function
<const json
&(const char *)> lookup_field
)
1072 const lttng_ust_ctl_field
&field
= field_iterator
.get_next();
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
));
1081 case lttng_ust_ctl_atype_enum
:
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
));
1091 case lttng_ust_ctl_atype_float
:
1093 const lttng_ust_ctl_float_type
&t
= field
.type
.u
._float
;
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
)));
1103 case lttng_ust_ctl_atype_array
:
1105 const auto &array_type
= field
.type
.u
.legacy
.array
;
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");
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
));
1121 case lttng_ust_ctl_atype_array_nestable
:
1123 const struct lttng_ust_ctl_type
&element_type
=
1124 field_iterator
.get_next().type
;
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");
1132 const auto &array_type
= field
.type
.u
.array_nestable
;
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)));
1143 case lttng_ust_ctl_atype_sequence
:
1145 const auto &t
= field
.type
.u
.legacy
.sequence
;
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");
1153 const lttng_ust_ctl_integer_type
&length_type
1154 = t
.length_type
.u
.basic
.integer
;
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
));
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
));
1169 case lttng_ust_ctl_atype_sequence_nestable
:
1171 const struct lttng_ust_ctl_type
&element_type
=
1172 field_iterator
.get_next().type
;
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");
1180 const auto &array_type
= field
.type
.u
.sequence_nestable
;
1181 auto popper
= current_field_path
.push(
1182 array_type
.length_name
);
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
),
1190 bits(array_type
.alignment
* 8)));
1194 case lttng_ust_ctl_atype_string
:
1195 add_field(field
.name
, make_string_field_class());
1198 case lttng_ust_ctl_atype_variant
:
1200 const decltype(field
.type
.u
.legacy
.variant
) &variant_type
=
1201 field
.type
.u
.legacy
.variant
;
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
);
1209 case lttng_ust_ctl_atype_variant_nestable
:
1211 const decltype(field
.type
.u
.variant_nestable
) &variant_type
=
1212 field
.type
.u
.variant_nestable
;
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
);
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");
1226 /* Don't emit anything */
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");
1235 /* Don't emit anything */
1238 case lttng_ust_ctl_atype_enum_nestable
:
1240 const lttng_ust_ctl_field
&container
=
1241 field_iterator
.get_next();
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");
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
));
1257 throw metadata_generation_exception(
1258 "Unhandled lttng-ust field type");
1263 json
make_record_common_context_field_class(
1264 const ust_registry_session
&session
,
1265 const ust_registry_channel
&chan
)
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
;
1271 auto add_field
= [&members
] (const char *name
, json field_class
) {
1272 members
.add_member(name
, field_class
);
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
;
1282 throw metadata_generation_exception("failed to look up field");
1285 while (!iter
.done()) {
1286 make_ust_field_class(session
, iter
, fp
, add_field
,
1290 return make_structure_field_class(0_bits
, std::move(members
));
1294 json
make_event_record_class_payload_field_class(
1295 const ust_registry_session
&session
,
1296 const ust_registry_event
&event
)
1298 lttng_ust_ctl_field_iterator
iter(event
.fields
, event
.nr_fields
);
1299 field_path
fp("event-record-payload");
1300 structure_members members
;
1302 auto add_field
= [&members
] (const char *name
, json field_class
) {
1303 members
.add_member(name
, field_class
);
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
;
1313 throw metadata_generation_exception("failed to look up field");
1316 while (!iter
.done()) {
1317 make_ust_field_class(session
, iter
, fp
, add_field
,
1321 return make_structure_field_class(0_bits
, std::move(members
));
1325 json
make_user_attributes(json attributes
)
1328 { "lttng.org,2009", attributes
}
1333 json
make_event_record_class_user_attributes(const ust_registry_event
&event
)
1335 json user_attributes
= make_user_attributes({
1336 { "log-level", event
.loglevel_value
},
1339 if (event
.model_emf_uri
) {
1340 user_attributes
["emf-uri"] = event
.model_emf_uri
;
1343 return user_attributes
;
1347 * Should be called with session registry mutex held.
1349 int ust_metadata_event_statedump(struct ust_registry_session
*session
,
1350 struct ust_registry_channel
*chan
,
1351 struct ust_registry_event
*event
)
1353 /* Don't dump metadata events */
1354 if (chan
->chan_id
== -1U)
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.
1363 if (!chan
->metadata_dumped
) {
1367 LTTNG_ASSERT(!event
->metadata_dumped
);
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
) },
1378 if (event
->nr_fields
) {
1379 event_record_class
["payload-field-class"] =
1380 make_event_record_class_payload_field_class(*session
, *event
);
1383 lttng_metadata_print_fragment(*session
, event_record_class
);
1385 event
->metadata_dumped
= 1;
1388 } catch (const std::exception
&error
) {
1389 ERR("%s", error
.what());
1390 return -LTTNG_ERR_UNK
;
1392 return -LTTNG_ERR_UNK
;
1397 json
make_packet_context_field_class(const ust_registry_session
&session
)
1399 byte_order bo
= get_byte_order(session
, false);
1400 structure_members members
;
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));
1432 return make_structure_field_class(0_bits
, std::move(members
));
1436 json
make_record_header_compact_field_class(const ust_registry_session
&session
)
1438 byte_order bo
= get_byte_order(session
, false);
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"));
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"));
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);
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
)));
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
));
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"}));
1483 return make_structure_field_class(8_bits
, std::move(members
));
1487 json
make_record_header_large_field_class(const ust_registry_session
&session
)
1489 byte_order bo
= get_byte_order(session
, false);
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"));
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"));
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);
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
)));
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
));
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" }));
1534 return make_structure_field_class(8_bits
, std::move(members
));
1538 json
make_record_header_field_class(const ust_registry_session
&session
,
1539 const ust_registry_channel
&chan
)
1541 if (chan
.header_type
== LTTNG_UST_CTL_CHANNEL_HEADER_COMPACT
) {
1542 return make_record_header_compact_field_class(session
);
1544 return make_record_header_large_field_class(session
);
1549 * Should be called with session registry mutex held.
1551 int ust_metadata_channel_statedump(struct ust_registry_session
*session
,
1552 struct ust_registry_channel
*chan
)
1554 /* Don't dump metadata events */
1555 if (chan
->chan_id
== -1U)
1558 if (!chan
->header_type
)
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
) },
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
) }
1578 lttng_metadata_print_fragment(*session
, data_stream_class
);
1580 /* Flag success of metadata dump. */
1581 chan
->metadata_dumped
= 1;
1584 * Output the metadata of any existing event.
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.
1589 std::vector
<ust_registry_event
*> events
;
1591 cds_lfht_iter event_iter
;
1592 ust_registry_event
*event
;
1593 cds_lfht_for_each_entry(chan
->events
->ht
, &event_iter
, event
,
1595 events
.push_back(event
);
1599 std::sort(events
.begin(), events
.end(),
1600 [] (ust_registry_event
*a
, ust_registry_event
*b
) {
1601 return a
->id
< b
->id
;
1604 for (ust_registry_event
*event
: events
) {
1605 ust_metadata_event_statedump(session
, chan
, event
);
1609 } catch (const std::exception
&error
) {
1610 ERR("%s", error
.what());
1611 return -LTTNG_ERR_UNK
;
1613 return -LTTNG_ERR_UNK
;
1618 * The offset between monotonic and realtime clock can be negative if
1619 * the system sets the REALTIME clock to 0 after boot.
1622 int measure_single_clock_offset(struct offset_sample
*sample
)
1624 uint64_t monotonic_avg
, monotonic
[2], measure_delta
, realtime
;
1625 uint64_t tcf
= trace_clock_freq();
1626 struct timespec rts
= { 0, 0 };
1629 monotonic
[0] = trace_clock_read64();
1630 ret
= lttng_clock_gettime(CLOCK_REALTIME
, &rts
);
1634 monotonic
[1] = trace_clock_read64();
1635 measure_delta
= monotonic
[1] - monotonic
[0];
1636 if (measure_delta
> sample
->measure_delta
) {
1638 * Discard value if it took longer to read than the best
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
;
1648 realtime
+= (uint64_t) rts
.tv_nsec
* tcf
/ NSEC_PER_SEC
;
1650 sample
->offset
= (int64_t) realtime
- monotonic_avg
;
1651 sample
->measure_delta
= measure_delta
;
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.
1662 int64_t measure_clock_offset(void)
1665 struct offset_sample offset_best_sample
= {
1667 .measure_delta
= UINT64_MAX
,
1670 for (i
= 0; i
< NR_CLOCK_OFFSET_SAMPLES
; i
++) {
1671 if (measure_single_clock_offset(&offset_best_sample
)) {
1675 return offset_best_sample
.offset
;
1679 * Should be called with session registry mutex held.
1681 int ust_metadata_session_statedump(struct ust_registry_session
*session
,
1682 struct ust_app
*app
,
1686 LTTNG_ASSERT(session
);
1689 json preamble
= make_fragment("preamble");
1693 lttng_metadata_print_fragment(*session
, preamble
);
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
) }
1701 lttng_metadata_print_fragment(*session
, trace_class
);
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
) },
1712 char clock_uuid_str
[LTTNG_UUID_STR_LEN
];
1713 int ret
= trace_clock_uuid(clock_uuid_str
);
1715 uint8_t clock_uuid
[LTTNG_UUID_LEN
];
1716 ret
= lttng_uuid_from_str(clock_uuid_str
, clock_uuid
);
1718 clock_class
["uuid"] = make_uuid(clock_uuid
);
1726 lttng_metadata_print_fragment(*session
, clock_class
);
1729 } catch (const std::exception
&error
) {
1730 ERR("%s", error
.what());
1731 return -LTTNG_ERR_UNK
;
1733 return -LTTNG_ERR_UNK
;