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.
--- /dev/null
+/*
+ * 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());
+}
--- /dev/null
+/*
+ * 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 */
}
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)}
{
}
{
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
{
}
- /* 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}
{
}
}
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>
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
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_;
}
};
public:
enum class role {
/* Packet header field class specific role. */
- TRACE_CLASS_UUID,
+ METADATA_STREAM_UUID,
};
using roles = std::vector<role>;
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;
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)
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_);
}
};
{
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()));
}
class stream_class;
class event_class;
class trace_class_visitor;
+class trace_class_environment_visitor;
struct abi {
unsigned int bits_per_long;
{
}
- 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;
};
{
}
- std::string& get_description()
+ /* Only call once. */
+ std::string transfer_description()
{
- return _description;
+ return std::move(_description);
}
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;
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);
_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');
}
*/
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);
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,
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)
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();
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();
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";
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();
-}
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:
const lttng::sessiond::trace::abi& _trace_abi;
const append_metadata_fragment_function _append_metadata_fragment;
- std::string _environment;
};
} /* namespace tsdl */
* 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));
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
},
[&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);
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);
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);
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));
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;
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));
}
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;
};
#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"
LTTNG_ASSERT(key);
return hash_key_str(key->name.c_str(), seed);
}
-
} /* namespace */
void lsu::details::locked_registry_session_release(lsu::registry_session *session)
/* 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",
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);
void lsu::registry_session::_generate_metadata()
{
- accept(*_metadata_generating_visitor);
+ trace_class::accept(*_metadata_generating_visitor);
}
void lsu::registry_session::regenerate_metadata()
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:
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;