X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Ffield.hpp;h=dc418b661bd1344049141b9dd39d825244ed0615;hb=9d89db29f3bf6c826293350f8f1a8559ec906b24;hp=dec5b103222008200b7adbcb8a019fa2ae3dbd3d;hpb=6e01cdc6c6e9cd18d99e8898fa3df41911388e8e;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/field.hpp b/src/bin/lttng-sessiond/field.hpp index dec5b1032..dc418b661 100644 --- a/src/bin/lttng-sessiond/field.hpp +++ b/src/bin/lttng-sessiond/field.hpp @@ -9,9 +9,11 @@ #define LTTNG_FIELD_H #include +#include #include +#include #include #include #include @@ -63,13 +65,22 @@ public: bool operator==(const type& other) const noexcept; bool operator!=(const type& other) const noexcept; + virtual ~type(); + type(const type&) = delete; + type(type&&) = delete; + type& operator=(type&&) = delete; + type& operator=(const type&) = delete; + + /* Obtain an independent copy of `type`. */ + virtual type::cuptr copy() const = 0; + virtual void accept(type_visitor& visitor) const = 0; const unsigned int alignment; protected: - type(unsigned int alignment); + explicit type(unsigned int alignment); private: virtual bool _is_equal(const type& rhs) const noexcept = 0; @@ -77,14 +88,20 @@ private: class field { public: + using uptr = std::unique_ptr; using cuptr = std::unique_ptr; field(std::string name, type::cuptr type); void accept(field_visitor& visitor) const; bool operator==(const field& other) const noexcept; + const type& get_type() const; + type::cuptr move_type() noexcept; + const std::string name; - const type::cuptr _type; + +private: + type::cuptr _type; }; class integer_type : public type { @@ -126,7 +143,9 @@ public: base base, roles roles = {}); - virtual void accept(type_visitor& visitor) const override; + type::cuptr copy() const override; + + void accept(type_visitor& visitor) const override; const enum byte_order byte_order; const unsigned int size; @@ -140,7 +159,7 @@ public: const roles roles_; protected: - virtual bool _is_equal(const type& other) const noexcept override; + bool _is_equal(const type& other) const noexcept override; }; class floating_point_type : public type { @@ -150,26 +169,35 @@ public: unsigned int exponent_digits, unsigned int mantissa_digits); - virtual void accept(type_visitor& visitor) const override final; + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; const enum byte_order byte_order; const unsigned int exponent_digits; const unsigned int mantissa_digits; private: - virtual bool _is_equal(const type& other) const noexcept override final; + bool _is_equal(const type& other) const noexcept final; }; class enumeration_type : public integer_type { +public: + ~enumeration_type() override = default; + enumeration_type(const enumeration_type&) = delete; + enumeration_type(enumeration_type&&) = delete; + enumeration_type& operator=(enumeration_type&&) = delete; + enumeration_type& operator=(const enumeration_type&) = delete; + protected: enumeration_type(unsigned int alignment, - enum byte_order byte_order, - unsigned int size, - enum signedness signedness, - enum base base, - integer_type::roles roles = {}); + enum byte_order byte_order, + unsigned int size, + enum signedness signedness, + enum base base, + integer_type::roles roles = {}); - virtual void accept(type_visitor& visitor) const = 0; + void accept(type_visitor& visitor) const override = 0; }; namespace details { @@ -198,23 +226,33 @@ class enumeration_mapping { public: using range_t = enumeration_mapping_range; - enumeration_mapping(const enumeration_mapping& other) = delete; - enumeration_mapping(const enumeration_mapping&& other) : - name{std::move(other.name)}, range{other.range} + enumeration_mapping(std::string in_name, MappingIntegerType value) : + name{ std::move(in_name) }, range{ value, value } { } - /* Mapping with an implicit value. */ - enumeration_mapping(std::string in_name) : name{std::move(in_name)} + enumeration_mapping(std::string in_name, range_t in_range) : + name{ std::move(in_name) }, range{ in_range } { } - enumeration_mapping(std::string in_name, range_t in_range) : name{std::move(in_name)}, range{in_range} + enumeration_mapping(const enumeration_mapping& other) = default; + enumeration_mapping(enumeration_mapping&& other) noexcept : + name{ std::move(other.name) }, range{ other.range } { } + enumeration_mapping& operator=(enumeration_mapping&&) = delete; + enumeration_mapping& operator=(const enumeration_mapping&) = delete; + ~enumeration_mapping() = default; + const std::string name; - const nonstd::optional 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 @@ -225,7 +263,7 @@ bool operator==(const enumeration_mapping& lhs, } } /* namespace details */ -template +template class typed_enumeration_type : public enumeration_type { public: using mapping = details::enumeration_mapping; @@ -249,21 +287,27 @@ 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; + type::cuptr copy() const override + { + return lttng::make_unique>( + alignment, byte_order, size, base_, mappings_, roles_); + } + + void accept(type_visitor& visitor) const final; - const std::shared_ptr _mappings; + const std::shared_ptr mappings_; private: - virtual bool _is_equal(const type& base_other) const noexcept override final + bool _is_equal(const type& base_other) const noexcept final { const auto& other = static_cast&>( base_other); - return integer_type::_is_equal(base_other) && *this->_mappings == *other._mappings; + return integer_type::_is_equal(base_other) && *this->mappings_ == *other.mappings_; } }; @@ -278,7 +322,7 @@ public: const type::cuptr element_type; protected: - virtual bool _is_equal(const type& base_other) const noexcept override; + bool _is_equal(const type& base_other) const noexcept override; }; class static_length_array_type : public array_type { @@ -287,12 +331,14 @@ public: type::cuptr element_type, uint64_t in_length); - virtual void accept(type_visitor& visitor) const override final; + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; const uint64_t length; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + bool _is_equal(const type& base_other) const noexcept final; }; class dynamic_length_array_type : public array_type { @@ -301,44 +347,50 @@ public: type::cuptr element_type, field_location length_field_location); - virtual void accept(type_visitor& visitor) const override final; + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; const field_location length_field_location; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + bool _is_equal(const type& base_other) const noexcept final; }; 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; static_length_blob_type(unsigned int alignment, uint64_t in_length_bytes, roles roles = {}); - virtual void accept(type_visitor& visitor) const override final; + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; const uint64_t length_bytes; const roles roles_; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + bool _is_equal(const type& base_other) const noexcept final; }; class dynamic_length_blob_type : public type { public: dynamic_length_blob_type(unsigned int alignment, field_location length_field_location); - virtual void accept(type_visitor& visitor) const override final; + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; const field_location length_field_location; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + bool _is_equal(const type& base_other) const noexcept final; }; class string_type : public type { @@ -358,19 +410,22 @@ public: const encoding encoding_; protected: - virtual bool _is_equal(const type& base_other) const noexcept override; + bool _is_equal(const type& base_other) const noexcept override; }; class static_length_string_type : public string_type { public: static_length_string_type( unsigned int alignment, enum encoding in_encoding, uint64_t length); - virtual void accept(type_visitor& visitor) const override final; + + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; const uint64_t length; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + bool _is_equal(const type& base_other) const noexcept final; }; class dynamic_length_string_type : public string_type { @@ -378,18 +433,24 @@ public: dynamic_length_string_type(unsigned int alignment, enum encoding in_encoding, field_location length_field_location); - virtual void accept(type_visitor& visitor) const override final; + + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; const field_location length_field_location; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + bool _is_equal(const type& base_other) const noexcept final; }; class null_terminated_string_type : public string_type { public: null_terminated_string_type(unsigned int alignment, enum encoding in_encoding); - virtual void accept(type_visitor& visitor) const override final; + + type::cuptr copy() const final; + + void accept(type_visitor& visitor) const final; }; class structure_type : public type { @@ -398,35 +459,89 @@ public: structure_type(unsigned int alignment, fields in_fields); - virtual void accept(type_visitor& visitor) const override final; + type::cuptr copy() const final; - const fields _fields; + void accept(type_visitor& visitor) const final; + + const fields fields_; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + bool _is_equal(const type& base_other) const noexcept final; }; +template class variant_type : public type { + static_assert(std::is_same::value || + std::is_same::value, + "Variant mapping integer type must be one of those allowed by typed_enumeration_type"); + public: - using choices = std::vector; + using choice = std::pair, type::cuptr>; + using choices = std::vector; + + variant_type(unsigned int in_alignment, + field_location in_selector_field_location, + choices in_choices) : + type(in_alignment), + selector_field_location{std::move(in_selector_field_location)}, + choices_{std::move(in_choices)} + { + } - variant_type(unsigned int alignment, - field_location selector_field_location, - choices in_choices); + type::cuptr copy() const final + { + choices copy_of_choices; + + copy_of_choices.reserve(choices_.size()); + for (const auto& current_choice : choices_) { + copy_of_choices.emplace_back( + current_choice.first, current_choice.second->copy()); + } + + return lttng::make_unique>( + alignment, selector_field_location, std::move(copy_of_choices)); + } - virtual void accept(type_visitor& visitor) const override final; + void accept(type_visitor& visitor) const final; const field_location selector_field_location; - const choices _choices; -; + const choices choices_; private: - virtual bool _is_equal(const type& base_other) const noexcept override final; + static bool _choices_are_equal(const choices& a, const choices& b) + { + if (a.size() != b.size()) { + return false; + } + + return std::equal(a.cbegin(), a.cend(), b.cbegin(), + [](const choice& choice_a, const choice& choice_b) { + return choice_a.first == choice_b.first && + *choice_a.second == *choice_b.second; + }); + } + + bool _is_equal(const type& base_other) const noexcept final + { + const auto& other = static_cast(base_other); + + return selector_field_location == other.selector_field_location && + _choices_are_equal(choices_, other.choices_); + } }; class field_visitor { public: virtual ~field_visitor() = default; + field_visitor(field_visitor&&) = delete; + field_visitor(const field_visitor&) = delete; + field_visitor& operator=(const field_visitor&) = delete; + field_visitor& operator=(field_visitor&&) = delete; + virtual void visit(const field& field) = 0; protected: @@ -436,6 +551,11 @@ protected: class type_visitor { public: virtual ~type_visitor() = default; + type_visitor(type_visitor&&) = delete; + type_visitor(const type_visitor&) = delete; + type_visitor& operator=(const type_visitor&) = delete; + type_visitor& operator=(type_visitor&&) = delete; + virtual void visit(const integer_type& type) = 0; virtual void visit(const floating_point_type& type) = 0; virtual void visit(const signed_enumeration_type& type) = 0; @@ -448,7 +568,8 @@ public: virtual void visit(const static_length_string_type& type) = 0; virtual void visit(const dynamic_length_string_type& type) = 0; virtual void visit(const structure_type& type) = 0; - virtual void visit(const variant_type& type) = 0; + virtual void visit(const variant_type& type) = 0; + virtual void visit(const variant_type& type) = 0; protected: type_visitor() = default; @@ -459,15 +580,17 @@ protected: } /* namespace lttng */ /* + * Field formatters for libfmt. + * * Due to a bug in g++ < 7.1, this specialization must be enclosed in the fmt namespace, * see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480. */ namespace fmt { template <> struct formatter : formatter { - template - typename FormatCtx::iterator format( - const lttng::sessiond::trace::field_location& location, FormatCtx& ctx) + template + typename FormatContextType::iterator format( + const lttng::sessiond::trace::field_location& location, FormatContextType& ctx) { std::string location_str{"["}; @@ -500,6 +623,52 @@ struct formatter : formatter +::std::string format_mapping_range(typename lttng::sessiond::trace::typed_enumeration_type< + MappingIntegerType>::mapping::range_t range) +{ + if (range.begin == range.end) { + return ::fmt::format("[{}]", range.begin); + } else { + return ::fmt::format("[{}, {}]", range.begin, range.end); + } +} +} /* namespace details */ + +template <> +struct formatter + : formatter { + template + typename FormatContextType::iterator + format(typename lttng::sessiond::trace::signed_enumeration_type::mapping::range_t range, + FormatContextType& ctx) + { + return format_to(ctx.out(), + details::format_mapping_range< + lttng::sessiond::trace::signed_enumeration_type:: + mapping::range_t::range_integer_t>( + range)); + } +}; + +template <> +struct formatter + : formatter { + template + typename FormatContextType::iterator + format(typename lttng::sessiond::trace::unsigned_enumeration_type::mapping::range_t range, + FormatContextType& ctx) + { + return format_to(ctx.out(), + details::format_mapping_range< + lttng::sessiond::trace::unsigned_enumeration_type:: + mapping::range_t::range_integer_t>( + range)); + } +}; + } /* namespace fmt */ #endif /* LTTNG_FIELD_H */