sessiond: add a CTF 2-generating trace class visitor
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 4 Jul 2022 19:19:00 +0000 (15:19 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 8 Dec 2022 14:05:33 +0000 (09:05 -0500)
The enumeration_type class is modified to guarantee that a mapping is
present. Implicit (or auto) mappings provided by the tracer are
converted to an explicit mapping.

This results in a slightly more verbose TSDL output which can be fixed
later.

Change-Id: I4372ad528384c1b7d9321dd5183525e3bd60ded4
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
18 files changed:
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/ctf2-trace-class-visitor.cpp [new file with mode: 0644]
src/bin/lttng-sessiond/ctf2-trace-class-visitor.hpp [new file with mode: 0644]
src/bin/lttng-sessiond/field.cpp
src/bin/lttng-sessiond/field.hpp
src/bin/lttng-sessiond/trace-class.cpp
src/bin/lttng-sessiond/trace-class.hpp
src/bin/lttng-sessiond/tsdl-trace-class-visitor.cpp
src/bin/lttng-sessiond/tsdl-trace-class-visitor.hpp
src/bin/lttng-sessiond/ust-field-convert.cpp
src/bin/lttng-sessiond/ust-registry-channel.cpp
src/bin/lttng-sessiond/ust-registry-session-pid.cpp
src/bin/lttng-sessiond/ust-registry-session-pid.hpp
src/bin/lttng-sessiond/ust-registry-session-uid.cpp
src/bin/lttng-sessiond/ust-registry-session-uid.hpp
src/bin/lttng-sessiond/ust-registry-session.cpp
src/bin/lttng-sessiond/ust-registry-session.hpp
src/bin/lttng-sessiond/ust-registry.hpp

index 7f8ac379c216709a028856788fd34d7393c0c03b..7d618afe21b9ebb12a233cbddac52e46204d51de 100644 (file)
@@ -76,7 +76,8 @@ liblttng_sessiond_common_la_SOURCES += trace-ust.cpp ust-registry.cpp ust-app.cp
                        ust-registry-channel.cpp ust-registry-channel.hpp \
                        ust-registry-session-uid.cpp ust-registry-session-uid.hpp \
                        ust-registry-session-pid.cpp ust-registry-session-pid.hpp \
-                       tsdl-trace-class-visitor.cpp tsdl-trace-class-visitor.hpp
+                       tsdl-trace-class-visitor.cpp tsdl-trace-class-visitor.hpp \
+                       ctf2-trace-class-visitor.cpp ctf2-trace-class-visitor.hpp
 endif
 
 # link on liblttngctl for check if sessiond is already alive.
diff --git a/src/bin/lttng-sessiond/ctf2-trace-class-visitor.cpp b/src/bin/lttng-sessiond/ctf2-trace-class-visitor.cpp
new file mode 100644 (file)
index 0000000..169d370
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2022 Simon Marchi <simon.marchi@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "ctf2-trace-class-visitor.hpp"
+#include "clock-class.hpp"
+
+#include <common/exception.hpp>
+#include <common/format.hpp>
+
+#include <vendor/nlohmann/json.hpp>
+
+#include <algorithm>
+
+namespace lsc = lttng::sessiond::ctf2;
+namespace lst = lttng::sessiond::trace;
+
+namespace json = nlohmann;
+
+namespace {
+const unsigned int spaces_per_indent = 2;
+const std::string record_separator = "\x1e";
+
+json::json make_json_fragment(const char *type)
+{
+       return {{"type", type}};
+}
+
+json::json to_json(const lst::field_location &location)
+{
+       json::json location_array;
+
+       switch (location.root_) {
+       case lst::field_location::root::PACKET_HEADER:
+               location_array.push_back("packet-header");
+               break;
+       case lst::field_location::root::PACKET_CONTEXT:
+               location_array.push_back("packet-context");
+               break;
+       case lst::field_location::root::EVENT_RECORD_HEADER:
+               location_array.push_back("event-record-header");
+               break;
+       case lst::field_location::root::EVENT_RECORD_COMMON_CONTEXT:
+               location_array.push_back("event-record-common-context");
+               break;
+       case lst::field_location::root::EVENT_RECORD_SPECIFIC_CONTEXT:
+               location_array.push_back("event-record-specific-context");
+               break;
+       case lst::field_location::root::EVENT_RECORD_PAYLOAD:
+               location_array.push_back("event-record-payload");
+               break;
+       }
+
+       std::copy(location.elements_.begin(), location.elements_.end(),
+                       std::back_inserter(location_array));
+       return location_array;
+}
+
+const char *get_role_name(lst::integer_type::role role)
+{
+       switch (role) {
+       case lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP:
+               return "default-clock-timestamp";
+       case lst::integer_type::role::DATA_STREAM_CLASS_ID:
+               return "data-stream-class-id";
+       case lst::integer_type::role::DATA_STREAM_ID:
+               return "data-stream-id";
+       case lst::integer_type::role::PACKET_MAGIC_NUMBER:
+               return "packet-magic-number";
+       case lst::integer_type::role::DISCARDED_EVENT_RECORD_COUNTER_SNAPSHOT:
+               return "discarded-event-record-counter-snapshot";
+       case lst::integer_type::role::PACKET_CONTENT_LENGTH:
+               return "packet-content-length";
+       case lst::integer_type::role::PACKET_END_DEFAULT_CLOCK_TIMESTAMP:
+               return "packet-end-default-clock-timestamp";
+       case lst::integer_type::role::PACKET_SEQUENCE_NUMBER:
+               return "packet-sequence-number";
+       case lst::integer_type::role::PACKET_TOTAL_LENGTH:
+               return "packet-total-length";
+       case lst::integer_type::role::EVENT_RECORD_CLASS_ID:
+               return "event-record-class-id";
+       default:
+               abort();
+       }
+}
+
+const char *get_role_name(lst::static_length_blob_type::role role)
+{
+       switch (role) {
+       case lst::static_length_blob_type::role::METADATA_STREAM_UUID:
+               return "metadata-stream-uuid";
+       default:
+               abort();
+       }
+}
+
+namespace ctf2 {
+class trace_environment_visitor : public lst::trace_class_environment_visitor {
+public:
+       trace_environment_visitor()
+       {
+       }
+
+       virtual void visit(const lst::environment_field<int64_t>& field) override
+       {
+               _visit(field);
+       }
+
+       virtual void visit(const lst::environment_field<const char *>& field) override
+       {
+               _visit(field);
+       }
+
+       /* Only call once. */
+       json::json transfer_fragment()
+       {
+               return std::move(_environment);
+       }
+
+private:
+       template <class FieldType>
+       void _visit(const FieldType& field)
+       {
+               _environment[field.name] = field.value;
+       }
+
+       json::json _environment;
+};
+
+class field_visitor : public lttng::sessiond::trace::field_visitor,
+                     public lttng::sessiond::trace::type_visitor {
+public:
+       field_visitor()
+       {
+       }
+
+       /* Only call once. */
+       json::json transfer_fragment()
+       {
+               return std::move(_fragment);
+       }
+
+private:
+       virtual void visit(const lst::field& field) override final
+       {
+               field_visitor field_type_visitor;
+               field.get_type().accept(field_type_visitor);
+
+               _fragment["name"] = field.name;
+               _fragment["field-class"] = field_type_visitor.transfer_fragment();
+       }
+
+       virtual void visit(const lst::integer_type& type) override final
+       {
+               _fragment["type"] = type.signedness_ == lst::integer_type::signedness::SIGNED ?
+                               "fixed-length-signed-integer" :
+                               "fixed-length-unsigned-integer";
+               _fragment["length"] = type.size;
+               _fragment["byte-order"] = type.byte_order == lst::byte_order::BIG_ENDIAN_ ?
+                               "big-endian" :
+                               "little-endian";
+               _fragment["alignment"] = type.alignment;
+               _fragment["preferred-display-base"] = (unsigned int) type.base_;
+
+               if (type.roles_.size() > 0) {
+                       json::json role_array = json::json::array();
+
+                       for (const auto role : type.roles_) {
+                               role_array.push_back(get_role_name(role));
+                       }
+
+                       _fragment["roles"] = std::move(role_array);
+               }
+       }
+
+       virtual void visit(const lst::floating_point_type& type) override final
+       {
+               _fragment["type"] = "fixed-length-floating-point-number";
+               _fragment["length"] = type.exponent_digits + type.mantissa_digits;
+               _fragment["byte-order"] = type.byte_order == lst::byte_order::BIG_ENDIAN_ ?
+                               "big-endian" :
+                               "little-endian";
+               _fragment["alignment"] = type.alignment;
+       }
+
+       template <class EnumerationType>
+       void visit_enumeration(const EnumerationType& type)
+       {
+               _fragment["type"] = std::is_signed<typename EnumerationType::mapping::range_t::range_integer_t>::value ?
+                               "fixed-length-signed-enumeration" :
+                               "fixed-length-unsigned-enumeration";
+               _fragment["length"] = type.size;
+               _fragment["byte-order"] = type.byte_order == lst::byte_order::BIG_ENDIAN_ ?
+                               "big-endian" :
+                               "little-endian";
+               _fragment["alignment"] = type.alignment;
+               _fragment["preferred-display-base"] = (unsigned int) type.base_;
+
+               if (type.roles_.size() > 0) {
+                       if (std::is_signed<typename EnumerationType::mapping::range_t::
+                                                           range_integer_t>::value) {
+                               LTTNG_THROW_ERROR(fmt::format(
+                                               "Failed to serialize {}: unexpected role",
+                                               _fragment["type"]));
+                       }
+
+                       auto role_array = json::json::array();
+
+                       for (const auto role : type.roles_) {
+                               role_array.push_back(get_role_name(role));
+                       }
+
+                       _fragment["roles"] = std::move(role_array);
+               }
+
+               if (type.mappings_->size() < 1) {
+                       LTTNG_THROW_ERROR(fmt::format(
+                                       "Failed to serialize {}: enumeration must have at least one mapping",
+                                       _fragment["type"]));
+               }
+
+               json::json mappings_value;
+               for (const auto &mapping : *type.mappings_) {
+                       mappings_value[mapping.name] = {{mapping.range.begin, mapping.range.end}};
+               }
+
+               _fragment["mappings"] = std::move(mappings_value);
+       }
+
+       virtual void visit(const lst::signed_enumeration_type& type) override final
+       {
+               visit_enumeration(type);
+       }
+
+       virtual void visit(const lst::unsigned_enumeration_type& type) override final
+       {
+               visit_enumeration(type);
+       }
+
+       virtual void visit(const lst::static_length_array_type& type) override final
+       {
+               _fragment["type"] = "static-length-array";
+
+               ::ctf2::field_visitor element_visitor;
+               type.element_type->accept(element_visitor);
+               _fragment["element-field-class"] = element_visitor.transfer_fragment();
+
+               if (type.alignment != 0) {
+                       _fragment["minimum-alignment"] = type.alignment;
+               }
+
+               _fragment["length"] = type.length;
+       }
+
+       virtual void visit(const lst::dynamic_length_array_type& type) override final
+       {
+               _fragment["type"] = "dynamic-length-array";
+
+               ::ctf2::field_visitor element_visitor;
+               type.element_type->accept(element_visitor);
+               _fragment["element-field-class"] = element_visitor.transfer_fragment();
+
+               if (type.alignment != 0) {
+                       _fragment["minimum-alignment"] = type.alignment;
+               }
+
+               _fragment["length-field-location"] = to_json(type.length_field_location);
+       }
+
+       virtual void visit(const lst::static_length_blob_type& type) override final
+       {
+               _fragment["type"] = "static-length-blob";
+               _fragment["length"] = type.length_bytes;
+
+               if (type.roles_.size() > 0) {
+                       auto role_array = json::json::array();
+
+                       for (const auto role : type.roles_) {
+                               role_array.push_back(get_role_name(role));
+                       }
+
+                       _fragment["roles"] = std::move(role_array);
+               }
+       }
+
+       virtual void visit(const lst::dynamic_length_blob_type& type) override final
+       {
+               _fragment["type"] = "dynamic-length-blob";
+               _fragment["length-field-location"] = to_json(type.length_field_location);
+       }
+
+       virtual void visit(const lst::null_terminated_string_type& type
+                       __attribute__((unused))) override final
+       {
+               _fragment["type"] = "null-terminated-string";
+       }
+
+       virtual void visit(const lst::structure_type& type) override final
+       {
+               _fragment["type"] = "structure";
+
+               if (type.alignment != 0) {
+                       _fragment["minimum-alignment"] = type.alignment;
+               }
+
+               auto member_classes_value = json::json::array();
+               for (const auto &field : type.fields_) {
+                       ::ctf2::field_visitor member_visitor;
+                       json::json member_class;
+
+                       field->accept(member_visitor);
+                       member_classes_value.emplace_back(member_visitor.transfer_fragment());
+               }
+
+               _fragment["member-classes"] = std::move(member_classes_value);
+       }
+
+       template <class MappingIntegerType>
+       void visit_variant(const lst::variant_type<MappingIntegerType>& type)
+       {
+               _fragment["type"] = "variant";
+               _fragment["selector-field-location"] = to_json(type.selector_field_location);
+
+               auto options_value = json::json::array();
+               for (const auto& option : type.choices_) {
+                       ::ctf2::field_visitor option_visitor;
+                       json::json member_class;
+
+                       /* TODO missing selector-field-range. */
+                       member_class["selector-field-ranges"] = {{option.first.range.begin, option.first.range.end}};
+                       option.second->accept(option_visitor);
+                       member_class["field-class"] = option_visitor.transfer_fragment();
+                       options_value.emplace_back(std::move(member_class));
+               }
+
+               _fragment["options"] = std::move(options_value);
+       }
+
+       virtual void visit(const lst::variant_type<int64_t>& type) override final
+       {
+               visit_variant(type);
+       }
+
+       virtual void visit(const lst::variant_type<uint64_t>& type) override final
+       {
+               visit_variant(type);
+       }
+
+       virtual void visit(const lst::static_length_string_type& type) override final
+       {
+               _fragment["type"] = "static-length-string";
+               _fragment["length"] = type.length;
+       }
+
+       virtual void visit(const lst::dynamic_length_string_type& type) override final
+       {
+               _fragment["type"] = "dynamic-length-string";
+               _fragment["length-field-location"] = to_json(type.length_field_location);
+       }
+
+       json::json _fragment;
+};
+} /* namespace ctf2 */
+
+}; /* namespace */
+
+lsc::trace_class_visitor::trace_class_visitor(const lst::abi& trace_abi,
+               lsc::append_metadata_fragment_function append_metadata_fragment) :
+       _trace_abi{trace_abi}, _append_metadata_fragment(append_metadata_fragment)
+{
+}
+
+void lsc::trace_class_visitor::visit(const lst::trace_class& trace_class)
+{
+       {
+               auto preamble_fragment = make_json_fragment("preamble");
+
+               preamble_fragment["version"] = 2;
+               preamble_fragment["uuid"] = trace_class.uuid;
+               append_metadata_fragment(preamble_fragment);
+       }
+
+       auto trace_class_fragment = make_json_fragment("trace-class");
+
+       ::ctf2::trace_environment_visitor environment_visitor;
+       trace_class.accept(environment_visitor);
+       trace_class_fragment["environment"] = environment_visitor.transfer_fragment();
+
+       const auto packet_header = trace_class.get_packet_header();
+       if (packet_header) {
+               ::ctf2::field_visitor field_visitor;
+
+               packet_header->accept(field_visitor);
+               trace_class_fragment["packet-header-field-class"] = field_visitor.transfer_fragment();
+       }
+
+       append_metadata_fragment(trace_class_fragment);
+}
+
+void lsc::trace_class_visitor::visit(const lst::clock_class& clock_class)
+{
+        auto clock_class_fragment = make_json_fragment("clock-class");
+
+       json::json offset;
+       offset.update({{"seconds", clock_class.offset / clock_class.frequency},
+                       {"cycles", clock_class.offset % clock_class.frequency}});
+
+       clock_class_fragment.update({
+               {"name", clock_class.name},
+               {"description", clock_class.description},
+               {"frequency", clock_class.frequency},
+               {"offset", std::move(offset)}});
+
+       if (clock_class.uuid) {
+               clock_class_fragment["uuid"] = *clock_class.uuid;
+       }
+
+       append_metadata_fragment(clock_class_fragment);
+}
+
+void lsc::trace_class_visitor::visit(const lst::stream_class& stream_class)
+{
+       auto stream_class_fragment = make_json_fragment("data-stream-class");
+
+       stream_class_fragment["id"] = stream_class.id;
+       if (stream_class.default_clock_class_name) {
+               stream_class_fragment["default-clock-class-name"] =
+                               *stream_class.default_clock_class_name;
+       }
+
+       const auto packet_context = stream_class.get_packet_context();
+       if (packet_context) {
+               ::ctf2::field_visitor visitor;
+
+               packet_context->accept(visitor);
+               stream_class_fragment["packet-context-field-class"] = visitor.transfer_fragment();
+       }
+
+       const auto event_header = stream_class.get_event_header();
+       if (event_header) {
+               ::ctf2::field_visitor visitor;
+
+               event_header->accept(visitor);
+               stream_class_fragment["event-record-header-field-class"] =
+                               visitor.transfer_fragment();
+       }
+
+       const auto event_context = stream_class.get_event_context();
+       if (event_context) {
+               ::ctf2::field_visitor visitor;
+
+               event_context->accept(visitor);
+               stream_class_fragment["event-record-common-context-field-class"] =
+                               visitor.transfer_fragment();
+       }
+
+       append_metadata_fragment(stream_class_fragment);
+}
+
+void lsc::trace_class_visitor::visit(const lst::event_class& event_class)
+{
+       auto event_class_fragment = make_json_fragment("event-record-class");
+
+       event_class_fragment["id"] = event_class.id;
+       event_class_fragment["data-stream-class-id"] = event_class.stream_class_id;
+       event_class_fragment["name"] = event_class.name;
+
+       if (event_class.payload) {
+               ::ctf2::field_visitor visitor;
+
+               event_class.payload->accept(visitor);
+               event_class_fragment["payload-field-class"] = visitor.transfer_fragment();
+       }
+
+       append_metadata_fragment(event_class_fragment);
+}
+
+void lsc::trace_class_visitor::append_metadata_fragment(const nlohmann::json& fragment) const
+{
+       _append_metadata_fragment(record_separator + fragment.dump(spaces_per_indent).c_str());
+}
diff --git a/src/bin/lttng-sessiond/ctf2-trace-class-visitor.hpp b/src/bin/lttng-sessiond/ctf2-trace-class-visitor.hpp
new file mode 100644 (file)
index 0000000..0d28961
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_CTF2_TRACE_CLASS_VISITOR_H
+#define LTTNG_CTF2_TRACE_CLASS_VISITOR_H
+
+#include "trace-class.hpp"
+#include "stream-class.hpp"
+#include "event-class.hpp"
+
+#include <vendor/optional.hpp>
+#include <vendor/nlohmann/json.hpp>
+
+#include <functional>
+
+namespace lttng {
+namespace sessiond {
+namespace ctf2 {
+
+using append_metadata_fragment_function = std::function<void(const std::string& fragment)>;
+
+class trace_class_visitor : public lttng::sessiond::trace::trace_class_visitor {
+public:
+       trace_class_visitor(const lttng::sessiond::trace::abi& trace_abi,
+                       append_metadata_fragment_function append_metadata);
+
+       virtual void visit(const lttng::sessiond::trace::trace_class& trace_class) override final;
+       virtual void visit(const lttng::sessiond::trace::clock_class& clock_class) override final;
+       virtual void visit(const lttng::sessiond::trace::stream_class& stream_class) override final;
+       virtual void visit(const lttng::sessiond::trace::event_class& event_class) override final;
+
+private:
+       void append_metadata_fragment(const nlohmann::json& fragment) const;
+
+       const lttng::sessiond::trace::abi& _trace_abi;
+       const append_metadata_fragment_function _append_metadata_fragment;
+};
+
+} /* namespace ctf2 */
+} /* namespace sessiond */
+} /* namespace lttng */
+
+#endif /* LTTNG_CTF2_TRACE_CLASS_VISITOR_H */
index 35f4aa0eb4a9b3db1eb636312b433358c213c3e0..4a7915e203b0fcf74a743b40b3503066dd61eaf8 100644 (file)
@@ -375,7 +375,7 @@ void lst::null_terminated_string_type::accept(type_visitor& visitor) const
 }
 
 lst::structure_type::structure_type(unsigned int in_alignment, fields in_fields) :
-       type(in_alignment), _fields{std::move(in_fields)}
+       type(in_alignment), fields_{std::move(in_fields)}
 {
 }
 
@@ -383,10 +383,10 @@ bool lst::structure_type::_is_equal(const type& base_other) const noexcept
 {
        const auto &other = static_cast<decltype(*this)&>(base_other);
 
-       return fields_are_equal(this->_fields, other._fields);
+       return fields_are_equal(this->fields_, other.fields_);
 }
 
 void lst::structure_type::accept(type_visitor& visitor) const
 {
        visitor.visit(*this);
-}
+}
\ No newline at end of file
index 93091572885413e4722bff08358fc7dd13ba1dc8..a774d133a0978d0c59e0ce08f3a2865f675e23b4 100644 (file)
@@ -211,8 +211,7 @@ public:
        {
        }
 
-       /* Mapping with an implicit value. */
-       enumeration_mapping(std::string in_name) : name{std::move(in_name)}
+       enumeration_mapping(std::string in_name, MappingIntegerType value) : name{std::move(in_name)}, range{value, value}
        {
        }
 
@@ -221,7 +220,12 @@ public:
        }
 
        const std::string name;
-       const nonstd::optional<range_t> range;
+       /*
+        * Only one range per mapping is supported for the moment as
+        * the tracers (and CTF 1.8) can't express multiple ranges per
+        * mapping, which is allowed by CTF 2.
+        */
+       const range_t range;
 };
 
 template <class MappingIntegerType>
@@ -256,13 +260,13 @@ public:
                                                      integer_type::signedness::UNSIGNED,
                                in_base,
                                std::move(in_roles)),
-               _mappings{std::move(in_mappings)}
+               mappings_{std::move(in_mappings)}
        {
        }
 
        virtual void accept(type_visitor& visitor) const override final;
 
-       const std::shared_ptr<const mappings> _mappings;
+       const std::shared_ptr<const mappings> mappings_;
 
 private:
        virtual bool _is_equal(const type& base_other) const noexcept override final
@@ -270,7 +274,7 @@ private:
                const auto& other = static_cast<const typed_enumeration_type<MappingIntegerType>&>(
                                base_other);
 
-               return integer_type::_is_equal(base_other) && *this->_mappings == *other._mappings;
+               return integer_type::_is_equal(base_other) && *this->mappings_ == *other.mappings_;
        }
 };
 
@@ -320,7 +324,7 @@ class static_length_blob_type : public type {
 public:
        enum class role {
                /* Packet header field class specific role. */
-               TRACE_CLASS_UUID,
+               METADATA_STREAM_UUID,
        };
 
        using roles = std::vector<role>;
@@ -407,7 +411,7 @@ public:
 
        virtual void accept(type_visitor& visitor) const override final;
 
-       const fields _fields;
+       const fields fields_;
 
 private:
        virtual bool _is_equal(const type& base_other) const noexcept override final;
@@ -432,14 +436,15 @@ public:
                        choices in_choices) :
                type(in_alignment),
                selector_field_location{std::move(in_selector_field_location)},
-               _choices{std::move(in_choices)}
+               choices_{std::move(in_choices)}
        {
        }
 
        virtual void accept(type_visitor& visitor) const override final;
 
        const field_location selector_field_location;
-       const choices _choices;
+       const choices choices_;
+;
 
 private:
        static bool _choices_are_equal(const choices& a, const choices& b)
@@ -462,7 +467,7 @@ private:
                const auto& other = static_cast<decltype(*this)&>(base_other);
 
                return selector_field_location == other.selector_field_location &&
-                               _choices_are_equal(_choices, other._choices);
+                               _choices_are_equal(choices_, other.choices_);
        }
 };
 
index 21a0c52dca0f2a8ea4480886cefe4d1432e6985b..b9c9b326f6a403acee66284c55c6c2fa546040d4 100644 (file)
@@ -21,15 +21,10 @@ void lttng::sessiond::trace::trace_class::accept(trace_class_visitor& trace_clas
 {
        trace_class_visitor.visit(*this);
        _accept_on_clock_classes(trace_class_visitor);
-
-       trace_class_visitor.environment_begin();
-       _visit_environment(trace_class_visitor);
-       trace_class_visitor.environment_end();
-
        _accept_on_stream_classes(trace_class_visitor);
 }
 
-void lst::trace_class_visitor::visit(const environment_field<std::string>& field)
+void lst::trace_class_environment_visitor::visit(const environment_field<std::string>& field)
 {
        visit(environment_field<const char *>(field.name, field.value.c_str()));
 }
index 52dcb76a94355315004638334d8672fa2f75ea57..ed72f3f579e9cdaabc34a91ddcade7ec5ac60c2d 100644 (file)
@@ -20,6 +20,7 @@ class clock_class;
 class stream_class;
 class event_class;
 class trace_class_visitor;
+class trace_class_environment_visitor;
 
 struct abi {
        unsigned int bits_per_long;
@@ -39,54 +40,50 @@ public:
        {
        }
 
-       const char * const name;
+       const char* const name;
        const ValueType& value;
 };
 
 class trace_class {
 public:
+
+       virtual ~trace_class() = default;
+
        /*
         * Derived classes must implement the _accept_on_*()
         * to continue the traversal to the trace class' children.
         */
        virtual void accept(trace_class_visitor& trace_class_visitor) const;
+       virtual void accept(trace_class_environment_visitor& environment_visitor) const = 0;
        virtual const lttng::sessiond::trace::type *get_packet_header() const noexcept = 0;
 
-       virtual ~trace_class() = default;
-
        const struct abi abi;
        const lttng_uuid uuid;
 
 protected:
        trace_class(const struct abi& abi, const lttng_uuid& trace_uuid);
        virtual void _accept_on_clock_classes(trace_class_visitor& trace_class_visitor) const = 0;
-       virtual void _visit_environment(trace_class_visitor& trace_class_visitor) const = 0;
        virtual void _accept_on_stream_classes(trace_class_visitor& trace_class_visitor) const = 0;
 };
 
+class trace_class_environment_visitor {
+public:
+       virtual ~trace_class_environment_visitor() = default;
+
+       virtual void visit(const environment_field<int64_t>& field) = 0;
+       virtual void visit(const environment_field<const char *>& field) = 0;
+       virtual void visit(const environment_field<std::string>& field);
+};
+
 class trace_class_visitor {
 public:
        using cuptr = std::unique_ptr<trace_class_visitor>;
 
        virtual ~trace_class_visitor() = default;
 
-       /* trace class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::trace_class& trace_class) = 0;
-
-       /* clock class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::clock_class& clock_class) = 0;
-
-       /* environment visitor interface. */
-       virtual void environment_begin() = 0;
-       virtual void visit(const environment_field<int64_t>& field) = 0;
-       virtual void visit(const environment_field<const char *>& field) = 0;
-       void visit(const environment_field<std::string>& field);
-       virtual void environment_end() = 0;
-
-       /* stream class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::stream_class& stream_class) = 0;
-
-       /* event class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::event_class& event_class) = 0;
 };
 
index c02addcebdb0d1a902b1c18d7aa75dc8a65c310e..c28af242400b1586000ed8534b3e121391a2721a 100644 (file)
@@ -128,9 +128,10 @@ public:
        {
        }
 
-       std::string& get_description()
+       /* Only call once. */
+       std::string transfer_description()
        {
-               return _description;
+               return std::move(_description);
        }
 
 private:
@@ -269,31 +270,29 @@ private:
                tsdl_field_visitor integer_visitor{_trace_abi, _indentation_level};
 
                integer_visitor.visit(static_cast<const lst::integer_type&>(type));
-               _description += integer_visitor.get_description() + " {\n";
+               _description += integer_visitor.transfer_description() + " {\n";
 
                const auto mappings_indentation_level = _indentation_level + 1;
 
                bool first_mapping = true;
-               for (const auto& mapping : *type._mappings) {
+               for (const auto& mapping : *type.mappings_) {
                        if (!first_mapping) {
                                _description += ",\n";
                        }
 
                        _description.resize(_description.size() + mappings_indentation_level, '\t');
-                       if (!mapping.range) {
-                               _description += fmt::format("\"{}\"", mapping.name);
-                       } else if (mapping.range->begin == mapping.range->end) {
+                       if (mapping.range.begin == mapping.range.end) {
                                _description += fmt::format(
                                                "\"{mapping_name}\" = {mapping_value}",
                                                fmt::arg("mapping_name", mapping.name),
-                                               fmt::arg("mapping_value", mapping.range->begin));
+                                               fmt::arg("mapping_value", mapping.range.begin));
                        } else {
                                _description += fmt::format(
                                                "\"{mapping_name}\" = {mapping_range_begin} ... {mapping_range_end}",
                                                fmt::arg("mapping_name", mapping.name),
                                                fmt::arg("mapping_range_begin",
-                                                               mapping.range->begin),
-                                               fmt::arg("mapping_range_end", mapping.range->end));
+                                                               mapping.range.begin),
+                                               fmt::arg("mapping_range_end", mapping.range.end));
                        }
 
                        first_mapping = false;
@@ -394,7 +393,7 @@ private:
 
                const auto previous_bypass_identifier_escape = _bypass_identifier_escape;
                _bypass_identifier_escape = false;
-               for (const auto& field : type._fields) {
+               for (const auto& field : type.fields_) {
                        _description += "\n";
                        _description.resize(_description.size() + _indentation_level, '\t');
                        field->accept(*this);
@@ -403,7 +402,7 @@ private:
                _bypass_identifier_escape = previous_bypass_identifier_escape;
 
                _indentation_level--;
-               if (type._fields.size() != 0) {
+               if (type.fields_.size() != 0) {
                        _description += "\n";
                        _description.resize(_description.size() + _indentation_level, '\t');
                }
@@ -437,7 +436,8 @@ private:
                 */
                const auto previous_bypass_identifier_escape = _bypass_identifier_escape;
                _bypass_identifier_escape = true;
-               for (const auto& field : type._choices) {
+               for (const auto& field : type.choices_
+) {
                        _description.resize(_description.size() + _indentation_level, '\t');
                        field.second->accept(*this);
                        _description += fmt::format(" {};\n", field.first.name);
@@ -513,6 +513,34 @@ private:
        bool _bypass_identifier_escape;
        const char *_default_clock_class_name;
 };
+
+class tsdl_trace_environment_visitor : public lst::trace_class_environment_visitor {
+public:
+       tsdl_trace_environment_visitor() : _environment{"env {\n"}
+       {
+       }
+
+       virtual void visit(const lst::environment_field<int64_t>& field) override
+       {
+               _environment += fmt::format("   {} = {};\n", field.name, field.value);
+       }
+
+       virtual void visit(const lst::environment_field<const char *>& field) override
+       {
+               _environment += fmt::format("   {} = \"{}\";\n", field.name,
+                               escape_tsdl_env_string_value(field.value));
+       }
+
+       /* Only call once. */
+       std::string transfer_description()
+       {
+               _environment += "};\n\n";
+               return std::move(_environment);
+       }
+
+private:
+       std::string _environment;
+};
 } /* namespace */
 
 tsdl::trace_class_visitor::trace_class_visitor(const lst::abi& trace_abi,
@@ -555,10 +583,14 @@ void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::trace_class&
                        fmt::arg("uuid", lttng::utils::uuid_to_str(trace_class.uuid)),
                        fmt::arg("byte_order",
                                        trace_class.abi.byte_order == lst::byte_order::BIG_ENDIAN_ ? "be" : "le"),
-                       fmt::arg("packet_header_layout", packet_header_visitor.get_description()));
+                       fmt::arg("packet_header_layout", packet_header_visitor.transfer_description()));
 
        /* Declare trace scope and type aliases. */
        append_metadata_fragment(trace_class_tsdl);
+
+       tsdl_trace_environment_visitor environment_visitor;
+       trace_class.accept(environment_visitor);
+       append_metadata_fragment(environment_visitor.transfer_description());
 }
 
 void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::clock_class& clock_class)
@@ -600,7 +632,7 @@ void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::stream_class
 
                event_header->accept(event_header_visitor);
                stream_class_str += fmt::format("       event.header := {};\n",
-                               event_header_visitor.get_description());
+                               event_header_visitor.transfer_description());
        }
 
        const auto *packet_context = stream_class.get_packet_context();
@@ -610,7 +642,7 @@ void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::stream_class
 
                packet_context->accept(packet_context_visitor);
                stream_class_str += fmt::format("       packet.context := {};\n",
-                               packet_context_visitor.get_description());
+                               packet_context_visitor.transfer_description());
        }
 
        const auto *event_context = stream_class.get_event_context();
@@ -619,7 +651,7 @@ void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::stream_class
 
                event_context->accept(event_context_visitor);
                stream_class_str += fmt::format("       event.context := {};\n",
-                               event_context_visitor.get_description());
+                               event_context_visitor.transfer_description());
        }
 
        stream_class_str += "};\n\n";
@@ -649,32 +681,7 @@ void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::event_class&
        event_class.payload->accept(static_cast<lst::type_visitor&>(payload_visitor));
 
        event_class_str += fmt::format(
-                       "       fields := {};\n}};\n\n", payload_visitor.get_description());
+                       "       fields := {};\n}};\n\n", payload_visitor.transfer_description());
 
        append_metadata_fragment(event_class_str);
 }
-
-void tsdl::trace_class_visitor::environment_begin()
-{
-       _environment += "env {\n";
-}
-
-void tsdl::trace_class_visitor::visit(
-               const lttng::sessiond::trace::environment_field<int64_t>& field)
-{
-       _environment += fmt::format("   {} = {};\n", field.name, field.value);
-}
-
-void tsdl::trace_class_visitor::visit(
-               const lttng::sessiond::trace::environment_field<const char *>& field)
-{
-       _environment += fmt::format(
-                       "       {} = \"{}\";\n", field.name, escape_tsdl_env_string_value(field.value));
-}
-
-void tsdl::trace_class_visitor::environment_end()
-{
-       _environment += "};\n\n";
-       append_metadata_fragment(_environment);
-       _environment.clear();
-}
index 6d629e2beff51dbe35268ca8b8f4721bf7e4031b..d06ea9983afd4871d306fde9f56ed92e7670f48f 100644 (file)
@@ -27,22 +27,9 @@ public:
        trace_class_visitor(const lttng::sessiond::trace::abi& trace_abi,
                        append_metadata_fragment_function append_metadata);
 
-       /* trace class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::trace_class& trace_class) override final;
-
-       /* clock class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::clock_class& clock_class) override final;
-
-       /* environment visitor interface. */
-       virtual void environment_begin() override final;
-       virtual void visit(const lttng::sessiond::trace::environment_field<int64_t>& field) override final;
-       virtual void visit(const lttng::sessiond::trace::environment_field<const char *>& field) override final;
-       virtual void environment_end() override final;
-
-       /* stream class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::stream_class& stream_class) override final;
-
-       /* event class visitor interface. */
        virtual void visit(const lttng::sessiond::trace::event_class& event_class) override final;
 
 private:
@@ -51,7 +38,6 @@ private:
 
        const lttng::sessiond::trace::abi& _trace_abi;
        const append_metadata_fragment_function _append_metadata_fragment;
-       std::string _environment;
 };
 
 } /* namespace tsdl */
index 74c41939e3c218a3ce291040d9f49ca253f51cf6..91ab45c1a1396cb5c77b831371a4ed77499cc537 100644 (file)
@@ -594,15 +594,15 @@ typename lst::variant_type<VariantSelectorMappingIntegerType>::choices create_ty
                                         * field's name.
                                         */
                                        const auto mapping_it = std::find_if(
-                                                       typed_enumeration._mappings->begin(),
-                                                       typed_enumeration._mappings->end(),
+                                                       typed_enumeration.mappings_->begin(),
+                                                       typed_enumeration.mappings_->end(),
                                                        [&field](const typename std::remove_reference<
                                                                        decltype(typed_enumeration)>::type::
                                                                                        mapping& mapping) {
                                                                return mapping.name == field->name;
                                                        });
 
-                                       if (mapping_it == typed_enumeration._mappings->end()) {
+                                       if (mapping_it == typed_enumeration.mappings_->end()) {
                                                LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
                                                                "Invalid variant choice: `{}` does not match any mapping in `{}` enumeration",
                                                                field->name, selector_field.name));
@@ -768,6 +768,35 @@ void create_field_from_ust_ctl_fields(const lttng_ust_ctl_field *current,
                                        lookup_root, current_field_location_elements)));
 }
 
+std::vector<lst::field::cuptr>::iterator lookup_field_in_vector(
+               std::vector<lst::field::cuptr>& fields, const lst::field_location& location)
+{
+       if (location.elements_.size() != 1) {
+               LTTNG_THROW_ERROR(fmt::format(
+                               "Unexpected field location received during field look-up: location = {}",
+                               location));
+       }
+
+       /*
+        * In the context of fields received from LTTng-UST, field
+        * look-up is extremely naive as the protocol can only
+        * express empty structures. It is safe to assume that
+        * location has a depth of 1 and directly refers to a field
+        * in the 'fields' vector.
+        */
+       const auto field_it = std::find_if(fields.begin(), fields.end(),
+                       [location](lst::field::cuptr &field) {
+                               return field->name == location.elements_[0];
+                       });
+
+       if (field_it == fields.end()) {
+               LTTNG_THROW_PROTOCOL_ERROR(
+                               fmt::format("Failed to look-up field: location = {}", location));
+       }
+
+       return field_it;
+}
+
 /*
  * `lttng_ust_ctl_field`s can be nested, in which case creating a field will consume
  * more than one lttng_ust_ctl_field. create_field_from_ust_ctl_fields returns the
@@ -812,34 +841,8 @@ std::vector<lst::field::cuptr> create_fields_from_ust_ctl_fields(
                                },
                                [&fields](const lst::field_location& location)
                                                -> lookup_field_fn::result_type {
-                                       if (location.elements_.size() != 1) {
-                                               LTTNG_THROW_ERROR(fmt::format(
-                                                               "Unexpected field location received during field look-up: location = {}",
-                                                               location));
-                                       }
-
-                                       /*
-                                        * In the context of fields received from LTTng-UST, field
-                                        * look-up is extremely naive as the protocol can only
-                                        * express empty structures. It is safe to assume that
-                                        * location has a depth of 1 and directly refers to a field
-                                        * in the 'fields' vector.
-                                        */
-                                       const auto field_it = std::find_if(fields.begin(),
-                                                       fields.end(),
-                                                       [&location](decltype(fields)::value_type&
-                                                                                       field) {
-                                                               return field->name ==
-                                                                               location.elements_[0];
-                                                       });
-
-                                       if (field_it == fields.end()) {
-                                               LTTNG_THROW_PROTOCOL_ERROR(fmt::format(
-                                                               "Failed to look-up field: location = {}",
-                                                               location));
-                                       }
-
-                                       return **field_it;
+                                       /* Resolve location to a previously-constructed field. */
+                                       return **lookup_field_in_vector(fields, location);
                                },
                                lookup_root, current_field_location_elements);
 
index b6092d197217c433f6bd04fbeb5ed3458495568c..de14432fa65cd4fc442247853384bb03dd6d3fc1 100644 (file)
@@ -87,7 +87,7 @@ lst::type::cuptr create_event_header(const lst::abi& trace_abi, lst::stream_clas
                auto enum_mappings = std::make_shared<lst::unsigned_enumeration_type::mappings>();
                lst::unsigned_enumeration_type::mapping compact_mapping{
                                "compact", lst::unsigned_enumeration_type::mapping::range_t(0, 30)};
-               lst::unsigned_enumeration_type::mapping extended_mapping{"extended"};
+               lst::unsigned_enumeration_type::mapping extended_mapping{"extended", 31};
 
                enum_mappings->emplace_back(compact_mapping);
                enum_mappings->emplace_back(extended_mapping);
@@ -149,7 +149,7 @@ lst::type::cuptr create_event_header(const lst::abi& trace_abi, lst::stream_clas
                auto enum_mappings = std::make_shared<lst::unsigned_enumeration_type::mappings>();
                lst::unsigned_enumeration_type::mapping compact_mapping{"compact",
                                lst::unsigned_enumeration_type::mapping::range_t(0, 65534)};
-               lst::unsigned_enumeration_type::mapping extended_mapping{"extended"};
+               lst::unsigned_enumeration_type::mapping extended_mapping{"extended", 65535};
                enum_mappings->emplace_back(compact_mapping);
                enum_mappings->emplace_back(extended_mapping);
 
index 7e091fdac7abff133e4138f9814bf582befce597..db7bf58ce4e8d07676e3371fcca9b53d7fac10a2 100644 (file)
@@ -37,9 +37,9 @@ lttng_buffer_type lsu::registry_session_per_pid::get_buffering_scheme() const no
        return LTTNG_BUFFER_PER_PID;
 }
 
-void lsu::registry_session_per_pid::_visit_environment(lst::trace_class_visitor& visitor) const
+void lsu::registry_session_per_pid::accept(lst::trace_class_environment_visitor& visitor) const
 {
-       registry_session::_visit_environment(visitor);
+       registry_session::accept(visitor);
        visitor.visit(lst::environment_field<int64_t>("tracer_buffering_id", _vpid));
        visitor.visit(lst::environment_field<int64_t>(
                        "tracer_patchlevel", _tracer_patch_level_version));
index aa6cfb91b99e0f74b80de327a41bb079a614434a..4fd541d584848dd02992f2d7a87884f4dd7a1009 100644 (file)
@@ -34,12 +34,10 @@ public:
                        uint64_t tracing_id);
 
        virtual lttng_buffer_type get_buffering_scheme() const noexcept override final;
+       virtual void accept(lttng::sessiond::trace::trace_class_environment_visitor&
+                                       environment_visitor) const override final;
 
 private:
-       virtual void _visit_environment(
-                       lttng::sessiond::trace::trace_class_visitor& trace_class_visitor)
-                       const override final;
-
        const unsigned int _tracer_patch_level_version;
        const pid_t _vpid;
        const std::string _procname;
index 8aa79dd7b5bb54bbfb0f5f353bd75c3a7a72fa4d..77c46fd7c45dab499722a3044c4cc5fe51275692 100644 (file)
@@ -32,8 +32,8 @@ lttng_buffer_type lsu::registry_session_per_uid::get_buffering_scheme() const no
        return LTTNG_BUFFER_PER_UID;
 }
 
-void lsu::registry_session_per_uid::_visit_environment(lst::trace_class_visitor& visitor) const
+void lsu::registry_session_per_uid::accept(lst::trace_class_environment_visitor& visitor) const
 {
-       registry_session::_visit_environment(visitor);
+       registry_session::accept(visitor);
        visitor.visit(lst::environment_field<int64_t>("tracer_buffering_id", _tracing_uid));
 }
index 665bfa5d014bcd81217a4bf0655ebd28d4f906f6..10da75818fd718e750d86e9dfdfb1e308b1c46b1 100644 (file)
@@ -32,11 +32,10 @@ public:
                        uid_t tracing_uid);
 
        virtual lttng_buffer_type get_buffering_scheme() const noexcept override final;
+       virtual void accept(lttng::sessiond::trace::trace_class_environment_visitor&
+                                       environment_visitor) const override final;
 
 private:
-       virtual void _visit_environment(
-                       lttng::sessiond::trace::trace_class_visitor& trace_class_visitor)
-                       const override final;
 
        const uid_t _tracing_uid;
 };
index 03a87e2868f98d4f36848e0f2f45d9f3a88e41c4..e1089bd58678eaf07e07a416b0ffbe4373cd5513 100644 (file)
@@ -11,6 +11,7 @@
 #include "session.hpp"
 #include "trace-class.hpp"
 #include "tsdl-trace-class-visitor.hpp"
+#include "ctf2-trace-class-visitor.hpp"
 #include "ust-app.hpp"
 #include "ust-field-convert.hpp"
 #include "ust-registry.hpp"
@@ -222,7 +223,6 @@ unsigned long ht_hash_enum(void *_key, unsigned long seed)
        LTTNG_ASSERT(key);
        return hash_key_str(key->name.c_str(), seed);
 }
-
 } /* namespace */
 
 void lsu::details::locked_registry_session_release(lsu::registry_session *session)
@@ -302,7 +302,7 @@ lst::type::cuptr lsu::registry_session::_create_packet_header() const
        /* uuid */
        packet_header_fields.emplace_back(lttng::make_unique<lst::field>("uuid",
                        lttng::make_unique<lst::static_length_blob_type>(0, 16,
-                                       std::initializer_list<lst::static_length_blob_type::role>({lst::static_length_blob_type::role::TRACE_CLASS_UUID}))));
+                                       std::initializer_list<lst::static_length_blob_type::role>({lst::static_length_blob_type::role::METADATA_STREAM_UUID}))));
 
        /* uint32_t stream_id */
        packet_header_fields.emplace_back(lttng::make_unique<lst::field>("stream_id",
@@ -495,8 +495,8 @@ void lsu::registry_session::remove_channel(uint64_t channel_key, bool notify)
        destroy_channel(&channel, notify);
 }
 
-void lsu::registry_session::_visit_environment(
-               lttng::sessiond::trace::trace_class_visitor& visitor) const
+void lsu::registry_session::accept(
+               lttng::sessiond::trace::trace_class_environment_visitor& visitor) const
 {
        ASSERT_LOCKED(_lock);
 
@@ -647,7 +647,7 @@ void lsu::registry_session::_reset_metadata()
 
 void lsu::registry_session::_generate_metadata()
 {
-       accept(*_metadata_generating_visitor);
+       trace_class::accept(*_metadata_generating_visitor);
 }
 
 void lsu::registry_session::regenerate_metadata()
index fc425dca092d7b32c94ba0080f8ebf415b351b9b..5f59e6160612521a6f7dae4bf0c8d9b7d0527b87 100644 (file)
@@ -104,9 +104,8 @@ protected:
                        uid_t euid,
                        gid_t egid,
                        uint64_t tracing_id);
-       virtual void _visit_environment(
-                       lttng::sessiond::trace::trace_class_visitor& trace_class_visitor)
-                       const override;
+       virtual void accept(
+                       trace::trace_class_environment_visitor& environment_visitor) const override;
        void _generate_metadata();
 
 private:
index c438211005bbe9dd78c48ba0410cf0fb2f975075..2095cdda3ab3f15c8b04f7794971b784d241b0f7 100644 (file)
@@ -47,30 +47,29 @@ class registry_session;
 
 namespace details {
 
-template <class MappingIntegerType>
-typename trace::typed_enumeration_type<MappingIntegerType>::mapping mapping_from_ust_ctl_entry(
-               const lttng_ust_ctl_enum_entry& entry)
-{
-       if (entry.u.extra.options & LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
-               return {entry.string};
-
-       } else {
-               return {entry.string,
-                               {(MappingIntegerType) entry.start.value,
-                                               (MappingIntegerType) entry.end.value}};
-       }
-}
-
 template <class MappingIntegerType>
 typename trace::typed_enumeration_type<MappingIntegerType>::mappings mappings_from_ust_ctl_entries(
                const lttng_ust_ctl_enum_entry *in_entries, size_t in_entry_count)
 {
        typename trace::typed_enumeration_type<MappingIntegerType>::mappings mappings;
 
+       MappingIntegerType next_range_begin = 0;
        for (size_t entry_idx = 0; entry_idx < in_entry_count; entry_idx++) {
                const auto& entry = in_entries[entry_idx];
-
-               mappings.emplace_back(mapping_from_ust_ctl_entry<MappingIntegerType>(entry));
+               MappingIntegerType range_begin, range_end;
+
+               if (entry.u.extra.options & LTTNG_UST_CTL_UST_ENUM_ENTRY_OPTION_IS_AUTO) {
+                       range_begin = range_end = next_range_begin;
+               } else {
+                       range_begin = (MappingIntegerType) entry.start.value;
+                       range_end = (MappingIntegerType) entry.end.value;
+               }
+
+               next_range_begin = range_end + 1;
+               mappings.emplace_back(entry.string,
+                               typename trace::typed_enumeration_type<
+                                               MappingIntegerType>::mapping::range_t{
+                                               range_begin, range_end});
        }
 
        return mappings;
This page took 0.044001 seconds and 4 git commands to generate.