sessiond: generate packet header, packet context and event header dynamically
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 7 Jul 2022 16:20:33 +0000 (12:20 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 8 Dec 2022 14:05:33 +0000 (09:05 -0500)
Instead of hardcoding event header and packet header/context layouts,
their layout is expressed using the lttng::sessiond::trace::field/type
API and serialized to TSDL using the visitor.

This reduces the duplication of code in the CTF2 visitor.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I9a4255889e36e6861a59536ce70b1e708da06ac5

12 files changed:
src/bin/lttng-sessiond/event-class.cpp
src/bin/lttng-sessiond/field.hpp
src/bin/lttng-sessiond/stream-class.cpp
src/bin/lttng-sessiond/stream-class.hpp
src/bin/lttng-sessiond/trace-class.hpp
src/bin/lttng-sessiond/tsdl-trace-class-visitor.cpp
src/bin/lttng-sessiond/ust-app.cpp
src/bin/lttng-sessiond/ust-field-convert.cpp
src/bin/lttng-sessiond/ust-registry-channel.cpp
src/bin/lttng-sessiond/ust-registry-channel.hpp
src/bin/lttng-sessiond/ust-registry-session.cpp
src/bin/lttng-sessiond/ust-registry-session.hpp

index 9d36703a014a45c15424ed7b290ab245d0e4b337..f5c7341b6799f3eef94ae721820d3397e647f744 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "event-class.hpp"
+#include "trace-class.hpp"
 
 namespace lst = lttng::sessiond::trace;
 
index 79017416617efb22a168633cd1dec65a34559132..f353adafbcc7d04e04e056144d53bb3c269b1b73 100644 (file)
@@ -8,8 +8,6 @@
 #ifndef LTTNG_FIELD_H
 #define LTTNG_FIELD_H
 
-#include "trace-class.hpp"
-
 #include <memory>
 #include <string>
 #include <type_traits>
@@ -24,6 +22,11 @@ namespace trace {
 class field_visitor;
 class type_visitor;
 
+enum class byte_order {
+       BIG_ENDIAN_,
+       LITTLE_ENDIAN_,
+};
+
 /*
  * Field, and the various field types, represents fields as exposed by the
  * LTTng tracers. These classes do not attempt to describe the complete spectrum of the CTF
index c087facbaa8cc1c4f820be892d38929caf010f2f..883a65e4122e2c460218eae294e8a4ce645f449c 100644 (file)
 
 namespace lst = lttng::sessiond::trace;
 
-lttng::sessiond::trace::stream_class::stream_class(
-               unsigned int in_id, enum header_type in_header_type) :
-       id{in_id}, header_type_{in_header_type}
+lttng::sessiond::trace::stream_class::stream_class(unsigned int in_id,
+               enum header_type in_header_type,
+               nonstd::optional<std::string> in_default_clock_class_name) :
+       id{in_id},
+       header_type_{in_header_type},
+       default_clock_class_name{std::move(in_default_clock_class_name)}
 {
 }
 
@@ -22,8 +25,17 @@ void lst::stream_class::accept(trace_class_visitor& visitor) const
        _accept_on_event_classes(visitor);
 }
 
-const lttng::sessiond::trace::type& lst::stream_class::get_context() const
+const lttng::sessiond::trace::type *lst::stream_class::get_packet_context() const
 {
-       LTTNG_ASSERT(_context);
-       return *_context;
+       return _packet_context.get();
+}
+
+const lttng::sessiond::trace::type *lst::stream_class::get_event_header() const
+{
+       return _event_header.get();
+}
+
+const lttng::sessiond::trace::type *lst::stream_class::get_event_context() const
+{
+       return _event_context.get();
 }
index 08555f3071e55362f1ce4f20fae3d4ca7ab59a12..78f0c83cb8ee46c7a2f37cf7d8457954fe928006 100644 (file)
@@ -10,6 +10,8 @@
 
 #include "field.hpp"
 
+#include <vendor/optional.hpp>
+
 #include <vector>
 
 namespace lttng {
@@ -29,7 +31,9 @@ public:
        void accept(trace_class_visitor& visitor) const;
        virtual ~stream_class() = default;
 
-       virtual const lttng::sessiond::trace::type& get_context() const;
+       virtual const type* get_packet_context() const;
+       virtual const type* get_event_header() const;
+       virtual const type* get_event_context() const;
 
        const unsigned int id;
        /*
@@ -38,12 +42,17 @@ public:
         * nested-name-specifiers.
         */
        const header_type header_type_;
+       const nonstd::optional<std::string> default_clock_class_name;
 
 protected:
-       stream_class(unsigned int id, enum header_type header_type);
+       stream_class(unsigned int id,
+                       enum header_type header_type,
+                       nonstd::optional<std::string> default_clock_class_name = nonstd::nullopt);
        virtual void _accept_on_event_classes(trace_class_visitor& trace_class_visitor) const = 0;
 
-       lttng::sessiond::trace::type::cuptr _context;
+       lttng::sessiond::trace::type::cuptr _packet_context;
+       lttng::sessiond::trace::type::cuptr _event_header;
+       lttng::sessiond::trace::type::cuptr _event_context;
 };
 
 } /* namespace trace */
index 087499866e097775dfc0bf4f2b2a564e1a4e3df8..05ea5c23efbf4c8c6fc8df36e0df3c3728a3029f 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef LTTNG_TRACE_CLASS_H
 #define LTTNG_TRACE_CLASS_H
 
+#include "field.hpp"
+
 #include <common/uuid.hpp>
 
 namespace lttng {
@@ -19,11 +21,6 @@ class stream_class;
 class event_class;
 class trace_class_visitor;
 
-enum class byte_order {
-       BIG_ENDIAN_,
-       LITTLE_ENDIAN_,
-};
-
 struct abi {
        unsigned int bits_per_long;
        unsigned int long_alignment;
@@ -53,6 +50,7 @@ public:
         * to continue the traversal to the trace class' children.
         */
        virtual void accept(trace_class_visitor& trace_class_visitor) const;
+       virtual lttng::sessiond::trace::type::cuptr get_packet_header() const = 0;
 
        virtual ~trace_class() = default;
 
index b7777d203d2a5f2c0f3d654c4eaa871c4df7af7f..d90f5eacd4cb2c8723ab576e7dc18423a4414ec8 100644 (file)
@@ -5,18 +5,22 @@
  *
  */
 
-#include "clock-class.hpp"
 #include "tsdl-trace-class-visitor.hpp"
+#include "clock-class.hpp"
 
 #include <common/exception.hpp>
 #include <common/format.hpp>
 #include <common/make-unique.hpp>
 #include <common/uuid.hpp>
 
+#include <vendor/optional.hpp>
+
+#include <algorithm>
 #include <array>
 #include <locale>
 #include <queue>
 #include <set>
+#include <stack>
 
 namespace lst = lttng::sessiond::trace;
 namespace tsdl = lttng::sessiond::tsdl;
@@ -29,7 +33,22 @@ const auto ctf_spec_minor = 8;
  * Although the CTF v1.8 specification recommends ignoring any leading underscore, Some readers,
  * such as Babeltrace 1.x, expect special identifiers without a prepended underscore.
  */
-const std::set<std::string> safe_tsdl_identifiers = {"stream_id"};
+const std::set<std::string> safe_tsdl_identifiers = {
+       "stream_id",
+       "packet_size",
+       "content_size",
+       "id",
+       "v",
+       "timestamp",
+       "events_discarded",
+       "packet_seq_num",
+       "timestamp_begin",
+       "timestamp_end",
+       "cpu_id",
+       "magic",
+       "uuid",
+       "stream_instance_id"
+};
 
 /*
  * A previous implementation always prepended '_' to the identifiers in order to
@@ -96,8 +115,16 @@ std::string escape_tsdl_env_string_value(const std::string& original_string)
 class tsdl_field_visitor : public lttng::sessiond::trace::field_visitor,
                           public lttng::sessiond::trace::type_visitor {
 public:
-       tsdl_field_visitor(const lst::abi& abi, unsigned int indentation_level) :
-               _indentation_level{indentation_level}, _trace_abi{abi}
+       tsdl_field_visitor(const lst::abi& abi,
+                       unsigned int indentation_level,
+                       const nonstd::optional<std::string>& in_default_clock_class_name =
+                                       nonstd::nullopt) :
+               _indentation_level{indentation_level},
+               _trace_abi{abi},
+               _bypass_identifier_escape{false},
+               _default_clock_class_name{in_default_clock_class_name ?
+                                               in_default_clock_class_name->c_str() :
+                                               nullptr}
        {
        }
 
@@ -116,11 +143,13 @@ private:
                 * empty structure declaration is inserted when needed to express the aligment
                 * constraint. The name of this structure is generated using the field's name.
                 */
-               _escaped_current_field_name = escape_tsdl_identifier(field.name);
+               _current_field_name.push(_bypass_identifier_escape ?
+                               field.name : escape_tsdl_identifier(field.name));
 
                field._type->accept(*this);
                _description += " ";
-               _description += _escaped_current_field_name;
+               _description += _current_field_name.top();
+               _current_field_name.pop();
 
                /*
                 * Some types requires suffixes to be appended (e.g. the length of arrays
@@ -132,7 +161,6 @@ private:
                }
 
                _description += ";";
-               _escaped_current_field_name.clear();
        }
 
        virtual void visit(const lst::integer_type& type) override final
@@ -199,6 +227,18 @@ private:
                        _current_integer_encoding_override.reset();
                }
 
+               if (std::find(type.roles_.begin(), type.roles_.end(),
+                                   lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP) !=
+                                               type.roles_.end() ||
+                               std::find(type.roles_.begin(), type.roles_.end(),
+                                               lst::integer_type::role::
+                                                               PACKET_END_DEFAULT_CLOCK_TIMESTAMP) !=
+                                               type.roles_.end()) {
+                       LTTNG_ASSERT(_default_clock_class_name);
+                       _description += fmt::format(
+                                       " map = clock.{}.value;", _default_clock_class_name);
+               }
+
                _description += " }";
        }
 
@@ -277,11 +317,11 @@ private:
        virtual void visit(const lst::static_length_array_type& type) override final
        {
                if (type.alignment != 0) {
-                       LTTNG_ASSERT(_escaped_current_field_name.size() > 0);
+                       LTTNG_ASSERT(_current_field_name.size() > 0);
                        _description += fmt::format(
                                        "struct {{ }} align({alignment}) {field_name}_padding;\n",
                                        fmt::arg("alignment", type.alignment),
-                                       fmt::arg("field_name", _escaped_current_field_name));
+                                       fmt::arg("field_name", _current_field_name.top()));
                        _description.resize(_description.size() + _indentation_level, '\t');
                }
 
@@ -298,17 +338,19 @@ private:
                         * could wrap nested sequences in structures, which
                         * would allow us to express alignment constraints.
                         */
-                       LTTNG_ASSERT(_escaped_current_field_name.size() > 0);
+                       LTTNG_ASSERT(_current_field_name.size() > 0);
                        _description += fmt::format(
                                        "struct {{ }} align({alignment}) {field_name}_padding;\n",
                                        fmt::arg("alignment", type.alignment),
-                                       fmt::arg("field_name", _escaped_current_field_name));
+                                       fmt::arg("field_name", _current_field_name.top()));
                        _description.resize(_description.size() + _indentation_level, '\t');
                }
 
                type.element_type->accept(*this);
-               _type_suffixes.emplace(fmt::format(
-                               "[{}]", escape_tsdl_identifier(type.length_field_name)));
+               _type_suffixes.emplace(fmt::format("[{}]",
+                               _bypass_identifier_escape ?
+                                               type.length_field_name :
+                                                     escape_tsdl_identifier(type.length_field_name)));
        }
 
        virtual void visit(const lst::static_length_blob_type& type) override final
@@ -337,7 +379,7 @@ private:
 
        virtual void visit(const lst::null_terminated_string_type& type) override final
        {
-               /* Defaults to UTF-8.  */
+               /* Defaults to UTF-8. */
                if (type.encoding_ == lst::null_terminated_string_type::encoding::ASCII) {
                        _description += "string { encoding = ASCII }";
                } else {
@@ -350,50 +392,61 @@ private:
                _indentation_level++;
                _description += "struct {";
 
+               const auto previous_bypass_identifier_escape = _bypass_identifier_escape;
+               _bypass_identifier_escape = false;
                for (const auto& field : type._fields) {
                        _description += "\n";
                        _description.resize(_description.size() + _indentation_level, '\t');
                        field->accept(*this);
                }
 
+               _bypass_identifier_escape = previous_bypass_identifier_escape;
+
                _indentation_level--;
                if (type._fields.size() != 0) {
                        _description += "\n";
                        _description.resize(_description.size() + _indentation_level, '\t');
                }
 
-               _description += "};";
+               _description += "}";
        }
 
        virtual void visit(const lst::variant_type& type) override final
        {
                if (type.alignment != 0) {
-                       LTTNG_ASSERT(_escaped_current_field_name.size() > 0);
+                       LTTNG_ASSERT(_current_field_name.size() > 0);
                        _description += fmt::format(
                                        "struct {{ }} align({alignment}) {field_name}_padding;\n",
                                        fmt::arg("alignment", type.alignment),
-                                       fmt::arg("field_name", _escaped_current_field_name));
+                                       fmt::arg("field_name", _current_field_name.top()));
                        _description.resize(_description.size() + _indentation_level, '\t');
                }
 
                _indentation_level++;
-               _description += fmt::format("variant <{}> {\n", escape_tsdl_identifier(type.tag_name));
+               _description += fmt::format("variant <{}> {{\n",
+                               _bypass_identifier_escape ?
+                                               type.tag_name :
+                                                     escape_tsdl_identifier(type.tag_name));
 
-               bool first_field = true;
+               /*
+                * The CTF 1.8 specification only recommends that implementations ignore
+                * leading underscores in field names. Both babeltrace 1 and 2 expect the
+                * variant choice and enumeration mapping name to match perfectly. Given that we
+                * don't have access to the tag in this context, we have to assume they match.
+                */
+               const auto previous_bypass_identifier_escape = _bypass_identifier_escape;
+               _bypass_identifier_escape = true;
                for (const auto& field : type._choices) {
-                       if (!first_field) {
-                               _description += ",\n";
-                       }
-
                        _description.resize(_description.size() + _indentation_level, '\t');
                        field->accept(*this);
-                       first_field = false;
+                       _description += fmt::format("\n", field->name);
                }
 
-               _description += "\n";
-               _description.resize(_description.size() + _indentation_level, '\t');
-               _description += "};";
+               _bypass_identifier_escape = previous_bypass_identifier_escape;
+
                _indentation_level--;
+               _description.resize(_description.size() + _indentation_level, '\t');
+               _description += "}";
        }
 
        lst::type::cuptr create_character_type(enum lst::string_type::encoding encoding)
@@ -429,7 +482,7 @@ private:
                visit(*char_sequence);
        }
 
-       std::string _escaped_current_field_name;
+       std::stack<std::string> _current_field_name;
        /*
         * Encoding to specify for the next serialized integer type.
         * Since the integer_type does not allow an encoding to be specified (it is a TSDL-specific
@@ -445,12 +498,16 @@ private:
 
        /* Description in TSDL format. */
        std::string _description;
+
+       bool _bypass_identifier_escape;
+       const char *_default_clock_class_name;
 };
 } /* namespace */
 
 tsdl::trace_class_visitor::trace_class_visitor(const lst::abi& trace_abi,
                tsdl::append_metadata_fragment_function append_metadata_fragment) :
-       _trace_abi{trace_abi}, _append_metadata_fragment(append_metadata_fragment)
+       _trace_abi{trace_abi},
+       _append_metadata_fragment(append_metadata_fragment)
 {
 }
 
@@ -461,28 +518,19 @@ void tsdl::trace_class_visitor::append_metadata_fragment(const std::string& frag
 
 void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::trace_class& trace_class)
 {
+       tsdl_field_visitor packet_header_visitor(trace_class.abi, 1);
+
+       trace_class.get_packet_header()->accept(packet_header_visitor);
+
        /* Declare type aliases, trace class, and packet header. */
        auto trace_class_tsdl = fmt::format(
                        "/* CTF {ctf_major}.{ctf_minor} */\n\n"
-                       "typealias integer {{ size = 8; align = {uint8_t_alignment}; signed = false; }} := uint8_t;\n"
-                       "typealias integer {{ size = 16; align = {uint16_t_alignment}; signed = false; }} := uint16_t;\n"
-                       "typealias integer {{ size = 32; align = {uint32_t_alignment}; signed = false; }} := uint32_t;\n"
-                       "typealias integer {{ size = 64; align = {uint64_t_alignment}; signed = false; }} := uint64_t;\n"
-                       "typealias integer {{ size = {bits_per_long}; align = {long_alignment}; signed = false; }} := unsigned long;\n"
-                       "typealias integer {{ size = 5; align = 1; signed = false; }} := uint5_t;\n"
-                       "typealias integer {{ size = 27; align = 1; signed = false; }} := uint27_t;\n"
-                       "\n"
                        "trace {{\n"
                        "       major = {ctf_major};\n"
                        "       minor = {ctf_minor};\n"
                        "       uuid = \"{uuid}\";\n"
                        "       byte_order = {byte_order};\n"
-                       "       packet.header := struct {{\n"
-                       "               uint32_t magic;\n"
-                       "               uint8_t  uuid[16];\n"
-                       "               uint32_t stream_id;\n"
-                       "               uint64_t stream_instance_id;\n"
-                       "       }};\n"
+                       "       packet.header := {packet_header_layout};\n"
                        "}};\n\n",
                        fmt::arg("ctf_major", ctf_spec_major),
                        fmt::arg("ctf_minor", ctf_spec_minor),
@@ -495,9 +543,8 @@ void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::trace_class&
                        fmt::arg("bits_per_long", trace_class.abi.bits_per_long),
                        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"));
+                                       trace_class.abi.byte_order == lst::byte_order::BIG_ENDIAN_ ? "be" : "le"),
+                       fmt::arg("packet_header_layout", packet_header_visitor.get_description()));
 
        /* Declare trace scope and type aliases. */
        append_metadata_fragment(std::move(trace_class_tsdl));
@@ -520,87 +567,51 @@ void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::clock_class&
                        "       freq = {frequency};\n"
                        "       offset = {offset};\n"
                        "}};\n"
-                       "\n"
-                       "typealias integer {{\n"
-                       "       size = 27; align = 1; signed = false;\n"
-                       "       map = clock.{name}.value;\n"
-                       "}} := uint27_clock_{name}_t;\n"
-                       "\n"
-                       "typealias integer {{\n"
-                       "       size = 32; align = {uint32_t_alignment}; signed = false;\n"
-                       "       map = clock.{name}.value;\n"
-                       "}} := uint32_clock_{name}_t;\n"
-                       "\n"
-                       "typealias integer {{\n"
-                       "       size = 64; align = {uint64_t_alignment}; signed = false;\n"
-                       "       map = clock.{name}.value;\n"
-                       "}} := uint64_clock_{name}_t;\n"
-                       "\n"
-                       "struct packet_context {{\n"
-                       "       uint64_clock_{name}_t timestamp_begin;\n"
-                       "       uint64_clock_{name}_t timestamp_end;\n"
-                       "       uint64_t content_size;\n"
-                       "       uint64_t packet_size;\n"
-                       "       uint64_t packet_seq_num;\n"
-                       "       unsigned long events_discarded;\n"
-                       "       uint32_t cpu_id;\n"
-                       "}};\n"
-                       "\n"
-                       "struct event_header_compact {{\n"
-                       "       enum : uint5_t {{ compact = 0 ... 30, extended = 31 }} id;\n"
-                       "       variant <id> {{\n"
-                       "               struct {{\n"
-                       "                       uint27_clock_{name}_t timestamp;\n"
-                       "               }} compact;\n"
-                       "               struct {{\n"
-                       "                       uint32_t id;\n"
-                       "                       uint64_clock_{name}_t timestamp;\n"
-                       "               }} extended;\n"
-                       "       }} v;\n"
-                       "}} align({uint32_t_alignment});\n"
-                       "\n"
-                       "struct event_header_large {{\n"
-                       "       enum : uint16_t {{ compact = 0 ... 65534, extended = 65535 }} id;\n"
-                       "       variant <id> {{\n"
-                       "               struct {{\n"
-                       "                       uint32_clock_{name}_t timestamp;\n"
-                       "               }} compact;\n"
-                       "               struct {{\n"
-                       "                       uint32_t id;\n"
-                       "                       uint64_clock_{name}_t timestamp;\n"
-                       "               }} extended;\n"
-                       "       }} v;\n"
-                       "}} align({uint16_t_alignment});\n\n",
+                       "\n",
                        fmt::arg("name", clock_class.name),
                        fmt::arg("uuid", uuid_str),
                        fmt::arg("description", clock_class.description),
                        fmt::arg("frequency", clock_class.frequency),
-                       fmt::arg("offset", clock_class.offset),
-                       fmt::arg("uint16_t_alignment", _trace_abi.uint16_t_alignment),
-                       fmt::arg("uint32_t_alignment", _trace_abi.uint32_t_alignment),
-                       fmt::arg("uint64_t_alignment", _trace_abi.uint64_t_alignment));
+                       fmt::arg("offset", clock_class.offset));
 
        append_metadata_fragment(std::move(clock_class_str));
 }
 
 void tsdl::trace_class_visitor::visit(const lttng::sessiond::trace::stream_class& stream_class)
 {
-       /* Declare stream. */
        auto stream_class_str = fmt::format("stream {{\n"
-                                           "   id = {id};\n"
-                                           "   event.header := {header_type};\n"
-                                           "   packet.context := struct packet_context;\n",
-                       fmt::arg("id", stream_class.id),
-                       fmt::arg("header_type", stream_class.header_type_ == lst::stream_class::header_type::COMPACT ?
-                                                       "struct event_header_compact" :
-                                                             "struct event_header_large"));
+               "       id = {};\n", stream_class.id);
 
-       auto context_field_visitor = tsdl_field_visitor(_trace_abi, 1);
+       const auto *event_header = stream_class.get_event_header();
+       if (event_header) {
+               auto event_header_visitor = tsdl_field_visitor(
+                               _trace_abi, 1, stream_class.default_clock_class_name);
 
-       stream_class.get_context().accept(static_cast<lst::type_visitor&>(context_field_visitor));
+               event_header->accept(event_header_visitor);
+               stream_class_str += fmt::format("       event.header := {};\n",
+                               event_header_visitor.get_description());
+       }
+
+       const auto *packet_context = stream_class.get_packet_context();
+       if (packet_context) {
+               auto packet_context_visitor = tsdl_field_visitor(
+                               _trace_abi, 1, stream_class.default_clock_class_name);
+
+               packet_context->accept(packet_context_visitor);
+               stream_class_str += fmt::format("       packet.context := {};\n",
+                               packet_context_visitor.get_description());
+       }
+
+       const auto *event_context = stream_class.get_event_context();
+       if (event_context) {
+               auto event_context_visitor = tsdl_field_visitor(_trace_abi, 1);
+
+               event_context->accept(event_context_visitor);
+               stream_class_str += fmt::format("       event.context := {};\n",
+                               event_context_visitor.get_description());
+       }
 
-       stream_class_str += fmt::format("       event.context := {}\n}};\n\n",
-                       context_field_visitor.get_description());
+       stream_class_str += "};\n\n";
 
        append_metadata_fragment(stream_class_str);
 }
@@ -627,7 +638,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.get_description());
 
        append_metadata_fragment(event_class_str);
 }
index 88db75f8f4d7da8f1f2ae5cc3d7978cae26fafdd..3f39b02e4d9ee3d0e6faf65fa1d243ddf242f2e0 100644 (file)
@@ -6426,23 +6426,47 @@ static int handle_app_register_channel_notification(int sock,
         * that all apps provide the same typing for the context fields as a
         * sanity check.
         */
-       lst::type::cuptr context_fields = lttng::make_unique<lst::structure_type>(0,
-                       lsu::create_trace_fields_from_ust_ctl_fields(*locked_registry_session,
-                                       ust_ctl_context_fields.get(), context_field_count));
+       try {
+               auto app_context_fields = lsu::create_trace_fields_from_ust_ctl_fields(
+                               *locked_registry_session, ust_ctl_context_fields.get(),
+                               context_field_count);
 
-       if (!ust_reg_chan.is_registered()) {
-               ust_reg_chan.set_context(std::move(context_fields));
-       } else {
-               /*
-                * Validate that the context fields match between
-                * registry and newcoming application.
-                */
-               if (ust_reg_chan.get_context() != *context_fields) {
-                       ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d",
-                               app->pid, app->sock);
-                       ret_code = -EINVAL;
-                       goto reply;
+               if (!ust_reg_chan.is_registered()) {
+                       lst::type::cuptr event_context = app_context_fields.size() ?
+                                       lttng::make_unique<lst::structure_type>(
+                                                       0, std::move(app_context_fields)) :
+                                       nullptr;
+
+                       ust_reg_chan.set_event_context(std::move(event_context));
+               } else {
+                       /*
+                        * Validate that the context fields match between
+                        * registry and newcoming application.
+                        */
+                       bool context_fields_match;
+                       const auto *previous_event_context = ust_reg_chan.get_event_context();
+
+                       if (!previous_event_context) {
+                               context_fields_match = app_context_fields.size() == 0;
+                       } else {
+                               const lst::structure_type app_event_context_struct(
+                                               0, std::move(app_context_fields));
+
+                               context_fields_match = *previous_event_context ==
+                                               app_event_context_struct;
+                       }
+
+                       if (!context_fields_match) {
+                               ERR("Registering application channel due to context field mismatch: pid = %d, sock = %d",
+                                               app->pid, app->sock);
+                               ret_code = -EINVAL;
+                               goto reply;
+                       }
                }
+       } catch (std::exception& ex) {
+               ERR("Failed to handle application context: %s", ex.what());
+               ret_code = -EINVAL;
+               goto reply;
        }
 
 reply:
index 81fa7bc7dec6952008fc6f7609c187f6e5797f59..9a07b38c46d3b054482e40f9044ec148ed2f7a9d 100644 (file)
@@ -190,8 +190,11 @@ lst::type::cuptr create_enumeration_type_from_ust_ctl_fields(const lttng_ust_ctl
                        lst::integer_type::reverse_byte_order(
                                        session_attributes._native_trace_byte_order) :
                              session_attributes._native_trace_byte_order;
+       const auto signedness = enum_container_uctl_type->signedness ?
+                       lst::integer_type::signedness::SIGNED :
+                             lst::integer_type::signedness::UNSIGNED;
 
-       if (enum_container_uctl_type->signedness) {
+       if (signedness == lst::integer_type::signedness::SIGNED) {
                const auto& enum_registry = static_cast<const lsu::registry_signed_enum&>(
                                *session_attributes.get_registry_enum(
                                                enumeration_name, enumeration_id));
index 85448b7032626024c116837aa392643bb8ed4d92..ed8a60daf2509fd191ec273fc3b0be866df6a4f4 100644 (file)
@@ -13,6 +13,7 @@
 #include <common/exception.hpp>
 #include <common/hashtable/utils.hpp>
 #include <common/make-unique-wrapper.hpp>
+#include <common/make-unique.hpp>
 #include <common/urcu.hpp>
 
 namespace lst = lttng::sessiond::trace;
@@ -77,12 +78,197 @@ int ht_match_event(struct cds_lfht_node *node, const void *_key)
 no_match:
        return 0;
 }
+
+lst::type::cuptr create_event_header(const lst::abi& trace_abi, lst::stream_class::header_type header_type)
+{
+       lst::structure_type::fields event_header_fields;
+
+       if (header_type == lst::stream_class::header_type::COMPACT) {
+               auto enum_mappings = std::make_shared<lst::unsigned_enumeration_type::mappings>();
+
+               enum_mappings->emplace_back("compact", lst::unsigned_enumeration_type::mapping::range_t(0, 30));
+               enum_mappings->emplace_back("extended");
+
+               lst::type::cuptr choice_enum = lttng::make_unique<lst::unsigned_enumeration_type>(1,
+                               trace_abi.byte_order, 5, lst::integer_type::base::DECIMAL,
+                               std::move(enum_mappings),
+                               std::initializer_list<lst::integer_type::role>(
+                                               {lst::integer_type::role::EVENT_RECORD_CLASS_ID}));
+
+               lst::variant_type::choices variant_choices;
+
+               lst::structure_type::fields compact_fields;
+               compact_fields.emplace_back(lttng::make_unique<lst::field>("timestamp",
+                               lttng::make_unique<lst::integer_type>(1, trace_abi.byte_order, 27,
+                                               lst::integer_type::signedness::UNSIGNED,
+                                               lst::integer_type::base::DECIMAL,
+                                               std::initializer_list<lst::integer_type::
+                                                                               role>({lst::integer_type::role::
+                                                                               DEFAULT_CLOCK_TIMESTAMP}))));
+
+               lst::type::cuptr compact = lttng::make_unique<lst::structure_type>(
+                               0, std::move(compact_fields));
+               variant_choices.emplace_back(lttng::make_unique<lst::field>("compact", std::move(compact)));
+
+               lst::structure_type::fields extended_fields;
+               extended_fields.emplace_back(lttng::make_unique<lst::field>("id",
+                               lttng::make_unique<lst::integer_type>(trace_abi.uint32_t_alignment,
+                                               trace_abi.byte_order, 32,
+                                               lst::integer_type::signedness::UNSIGNED,
+                                               lst::integer_type::base::DECIMAL,
+                                               std::initializer_list<lst::integer_type::
+                                                                               role>({lst::integer_type::role::
+                                                                               EVENT_RECORD_CLASS_ID}))));
+               extended_fields.emplace_back(lttng::make_unique<lst::field>("timestamp",
+                               lttng::make_unique<lst::integer_type>(trace_abi.uint64_t_alignment,
+                                               trace_abi.byte_order, 64,
+                                               lst::integer_type::signedness::UNSIGNED,
+                                               lst::integer_type::base::DECIMAL,
+                                               std::initializer_list<lst::integer_type::
+                                                                               role>({lst::integer_type::role::
+                                                                               DEFAULT_CLOCK_TIMESTAMP}))));
+
+               lst::type::cuptr extended = lttng::make_unique<lst::structure_type>(0, std::move(extended_fields));
+               variant_choices.emplace_back(lttng::make_unique<lst::field>("extended", std::move(extended)));
+
+               lst::type::cuptr variant = lttng::make_unique<lst::variant_type>(
+                               0, "id", std::move(variant_choices));
+
+               event_header_fields.emplace_back(lttng::make_unique<lst::field>("id", std::move(choice_enum)));
+               event_header_fields.emplace_back(
+                               lttng::make_unique<lst::field>("v", std::move(variant)));
+       } else {
+               auto enum_mappings = std::make_shared<lst::unsigned_enumeration_type::mappings>();
+
+               enum_mappings->emplace_back("compact", lst::unsigned_enumeration_type::mapping::range_t(0, 65534));
+               enum_mappings->emplace_back("extended");
+
+               lst::type::cuptr choice_enum = lttng::make_unique<lst::unsigned_enumeration_type>(
+                               trace_abi.uint16_t_alignment, trace_abi.byte_order, 16,
+                               lst::integer_type::base::DECIMAL, std::move(enum_mappings),
+                               std::initializer_list<lst::integer_type::role>(
+                                               {lst::integer_type::role::EVENT_RECORD_CLASS_ID}));
+
+               lst::variant_type::choices variant_choices;
+
+               lst::structure_type::fields compact_fields;
+               compact_fields.emplace_back(lttng::make_unique<lst::field>("timestamp",
+                               lttng::make_unique<lst::integer_type>(trace_abi.uint32_t_alignment,
+                                               trace_abi.byte_order, 32,
+                                               lst::integer_type::signedness::UNSIGNED,
+                                               lst::integer_type::base::DECIMAL,
+                                               std::initializer_list<lst::integer_type::
+                                                                               role>({lst::integer_type::role::
+                                                                               DEFAULT_CLOCK_TIMESTAMP}))));
+
+               lst::type::cuptr compact = lttng::make_unique<lst::structure_type>(
+                               0, std::move(compact_fields));
+               variant_choices.emplace_back(
+                               lttng::make_unique<lst::field>("compact", std::move(compact)));
+
+               lst::structure_type::fields extended_fields;
+               extended_fields.emplace_back(lttng::make_unique<lst::field>("id",
+                               lttng::make_unique<lst::integer_type>(trace_abi.uint32_t_alignment,
+                                               trace_abi.byte_order, 32,
+                                               lst::integer_type::signedness::UNSIGNED,
+                                               lst::integer_type::base::DECIMAL,
+                                               std::initializer_list<lst::integer_type::
+                                                                               role>({lst::integer_type::role::
+                                                                               EVENT_RECORD_CLASS_ID}))));
+               extended_fields.emplace_back(lttng::make_unique<lst::field>("timestamp",
+                               lttng::make_unique<lst::integer_type>(trace_abi.uint64_t_alignment,
+                                               trace_abi.byte_order, 64,
+                                               lst::integer_type::signedness::UNSIGNED,
+                                               lst::integer_type::base::DECIMAL,
+                                               std::initializer_list<lst::integer_type::
+                                                                               role>({lst::integer_type::role::
+                                                                               DEFAULT_CLOCK_TIMESTAMP}))));
+
+               lst::type::cuptr extended = lttng::make_unique<lst::structure_type>(0, std::move(extended_fields));
+               variant_choices.emplace_back(lttng::make_unique<lst::field>("extended", std::move(extended)));
+
+               lst::type::cuptr variant = lttng::make_unique<lst::variant_type>(
+                               0, "id", std::move(variant_choices));
+
+               event_header_fields.emplace_back(lttng::make_unique<lst::field>("id", std::move(choice_enum)));
+               event_header_fields.emplace_back(
+                               lttng::make_unique<lst::field>("v", std::move(variant)));
+       }
+
+       return lttng::make_unique<lst::structure_type>(0, std::move(event_header_fields));
+}
+
+lst::type::cuptr create_packet_context(const lst::abi& trace_abi)
+{
+       lst::structure_type::fields packet_context_fields;
+
+       /* uint64_t timestamp_begin */
+       packet_context_fields.emplace_back(lttng::make_unique<lst::field>("timestamp_begin",
+                       lttng::make_unique<lst::integer_type>(trace_abi.uint64_t_alignment,
+                                       trace_abi.byte_order, 64,
+                                       lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::DEFAULT_CLOCK_TIMESTAMP}))));
+
+       /* uint64_t timestamp_end */
+       packet_context_fields.emplace_back(lttng::make_unique<lst::field>("timestamp_end",
+                       lttng::make_unique<lst::integer_type>(trace_abi.uint64_t_alignment,
+                                       trace_abi.byte_order, 64,
+                                       lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::PACKET_END_DEFAULT_CLOCK_TIMESTAMP}))));
+
+       /* uint64_t content_size */
+       packet_context_fields.emplace_back(lttng::make_unique<lst::field>("content_size",
+                       lttng::make_unique<lst::integer_type>(trace_abi.uint64_t_alignment,
+                                       trace_abi.byte_order, 64,
+                                       lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::PACKET_CONTENT_LENGTH}))));
+
+       /* uint64_t packet_size */
+       packet_context_fields.emplace_back(lttng::make_unique<lst::field>("packet_size",
+                       lttng::make_unique<lst::integer_type>(trace_abi.uint64_t_alignment,
+                                       trace_abi.byte_order, 64,
+                                       lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::PACKET_TOTAL_LENGTH}))));
+
+       /* uint64_t packet_seq_num */
+       packet_context_fields.emplace_back(lttng::make_unique<lst::field>("packet_seq_num",
+                       lttng::make_unique<lst::integer_type>(trace_abi.uint64_t_alignment,
+                                       trace_abi.byte_order, 64,
+                                       lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::PACKET_SEQUENCE_NUMBER}))));
+
+       /* unsigned long events_discarded */
+       packet_context_fields.emplace_back(lttng::make_unique<lst::field>("events_discarded",
+                       lttng::make_unique<lst::integer_type>(trace_abi.long_alignment,
+                                       trace_abi.byte_order, trace_abi.bits_per_long,
+                                       lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::DISCARDED_EVENT_RECORD_COUNTER_SNAPSHOT}))));
+
+       /* uint32_t cpu_id */
+       packet_context_fields.emplace_back(lttng::make_unique<lst::field>("cpu_id",
+                       lttng::make_unique<lst::integer_type>(trace_abi.uint32_t_alignment,
+                                       trace_abi.byte_order, 32,
+                                       lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL)));
+
+       return lttng::make_unique<lst::structure_type>(0, std::move(packet_context_fields));
+}
 }; /* namespace */
 
 lsu::registry_channel::registry_channel(unsigned int channel_id,
+               const lst::abi& trace_abi,
+               std::string in_default_clock_class_name,
                lsu::registry_channel::registered_listener_fn channel_registered_listener,
                lsu::registry_channel::event_added_listener_fn event_added_listener) :
-       lst::stream_class(channel_id, lst::stream_class::header_type::LARGE),
+       lst::stream_class(channel_id,
+                       lst::stream_class::header_type::LARGE,
+                       std::move(in_default_clock_class_name)),
        _key{-1ULL},
        _consumer_key{-1ULL},
        _next_event_id{0},
@@ -105,6 +291,9 @@ lsu::registry_channel::registry_channel(unsigned int channel_id,
         * channel object itself.
         */
        _node = {};
+
+       _packet_context = create_packet_context(trace_abi);
+       _event_header = create_event_header(trace_abi, header_type_);
 }
 
 void lsu::registry_channel::add_event(
@@ -199,17 +388,17 @@ lsu::registry_channel::~registry_channel()
        lttng_ht_destroy(_events);
 }
 
-const lttng::sessiond::trace::type& lsu::registry_channel::get_context() const
+const lttng::sessiond::trace::type* lsu::registry_channel::get_event_context() const
 {
        LTTNG_ASSERT(_is_registered);
-       return lst::stream_class::get_context();
+       return lst::stream_class::get_event_context();
 }
 
-void lsu::registry_channel::set_context(lttng::sessiond::trace::type::cuptr context)
+void lsu::registry_channel::set_event_context(lttng::sessiond::trace::type::cuptr context)
 {
        /* Must only be set once, on the first channel registration provided by an application. */
-       LTTNG_ASSERT(!_context);
-       _context = std::move(context);
+       LTTNG_ASSERT(!_event_context);
+       _event_context = std::move(context);
 }
 
 bool lsu::registry_channel::is_registered() const
index 1e5745aedcfe2fdc4b980315c84414dbfbf4b2cb..5a99c1bdbbee3bd4e1bd6a242e73bfe00ab09a1b 100644 (file)
@@ -9,6 +9,7 @@
 #define LTTNG_UST_REGISTRY_CHANNEL_H
 
 #include "stream-class.hpp"
+#include "trace-class.hpp"
 
 #include <common/hashtable/hashtable.hpp>
 
@@ -31,6 +32,8 @@ public:
        using event_added_listener_fn = std::function<void(const registry_channel&, const registry_event &)>;
 
        registry_channel(uint32_t channel_id,
+                       const lttng::sessiond::trace::abi& trace_abi,
+                       std::string default_clock_class_name,
                        registered_listener_fn channel_registered_listener,
                        event_added_listener_fn new_event_listener);
        void add_event(int session_objd,
@@ -45,8 +48,8 @@ public:
                        uint32_t& out_event_id);
        virtual ~registry_channel();
 
-       virtual const lttng::sessiond::trace::type& get_context() const override final;
-       void set_context(lttng::sessiond::trace::type::cuptr context);
+       virtual const lttng::sessiond::trace::type *get_event_context() const override final;
+       void set_event_context(lttng::sessiond::trace::type::cuptr context);
 
        /* Channel was registered to at least one application. */
        bool is_registered() const;
index eced786e0446836f54ffbadf47a0607f5eb04775..48983f2b21d8d4f3347ae63d784c766c9597160f 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <fcntl.h>
 #include <functional>
+#include <initializer_list>
 #include <mutex>
 #include <sstream>
 #include <string>
@@ -240,15 +241,15 @@ lsu::registry_session::registry_session(const struct lst::abi& in_abi,
        lst::trace_class(in_abi, generate_uuid_or_throw()),
        _root_shm_path{root_shm_path ? root_shm_path : ""},
        _shm_path{shm_path ? shm_path : ""},
-       _metadata_path{_shm_path.size() > 0 ?
-                       fmt::format("{}/metadata", _shm_path) : std::string("")},
+       _metadata_path{_shm_path.size() > 0 ? fmt::format("{}/metadata", _shm_path) :
+                                                   std::string("")},
        _uid{euid},
        _gid{egid},
        _app_tracer_version{.major = major, .minor = minor},
        _tracing_id{tracing_id},
        _clock{lttng::make_unique<lsu::clock_class>()},
-       _metadata_generating_visitor{lttng::make_unique<ls::tsdl::trace_class_visitor>(abi,
-                       [this](const std::string& fragment) {
+       _metadata_generating_visitor{lttng::make_unique<ls::tsdl::trace_class_visitor>(
+                       abi, [this](const std::string& fragment) {
                                _append_metadata_fragment(fragment);
                        })}
 {
@@ -390,7 +391,7 @@ void lsu::registry_session::add_channel(uint64_t key)
        }
 
        auto chan = new lsu::registry_channel(
-                       _get_next_channel_id(),
+                       _get_next_channel_id(), abi, _clock->name,
                        /* Registered channel listener. */
                        [this](const lsu::registry_channel& registered_channel) {
                                /*
@@ -664,6 +665,39 @@ lsu::registry_session::get_enumeration(const char *enum_name, uint64_t enum_id)
        return lsu::registry_enum::const_rcu_protected_reference{*reg_enum, std::move(rcu_lock)};
 }
 
+lst::type::cuptr lsu::registry_session::get_packet_header() const
+{
+       lst::structure_type::fields packet_header_fields;
+
+       /* uint32_t magic */
+       packet_header_fields.emplace_back(lttng::make_unique<lst::field>("magic",
+                       lttng::make_unique<lst::integer_type>(abi.uint32_t_alignment,
+                                       abi.byte_order, 32, lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::HEXADECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::PACKET_MAGIC_NUMBER}))));
+
+       /* 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}))));
+
+       /* uint32_t stream_id */
+       packet_header_fields.emplace_back(lttng::make_unique<lst::field>("stream_id",
+                       lttng::make_unique<lst::integer_type>(abi.uint32_t_alignment,
+                                       abi.byte_order, 32, lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::DATA_STREAM_CLASS_ID}))));
+
+       /* uint64_t stream_instance_id */
+       packet_header_fields.emplace_back(lttng::make_unique<lst::field>("stream_instance_id",
+                       lttng::make_unique<lst::integer_type>(abi.uint64_t_alignment,
+                                       abi.byte_order, 64, lst::integer_type::signedness::UNSIGNED,
+                                       lst::integer_type::base::DECIMAL,
+                                       std::initializer_list<lst::integer_type::role>({lst::integer_type::role::DATA_STREAM_ID}))));
+
+       return lttng::make_unique<lst::structure_type>(0, std::move(packet_header_fields));
+}
+
 /*
  * Lookup enumeration by name and comparing enumeration entries.
  * Needs to be called from RCU read-side critical section.
index 316703769fe57e92d2391fa36cb3159a28972bae..4bda57a0774a2deab35b963fc1d49196f752594b 100644 (file)
@@ -62,6 +62,8 @@ public:
        void regenerate_metadata();
        virtual ~registry_session();
 
+       virtual lttng::sessiond::trace::type::cuptr get_packet_header() const override;
+
        /*
         * With multiple writers and readers, use this lock to access
         * the registry. Can nest within the ust app session lock.
This page took 0.041871 seconds and 4 git commands to generate.