Base lttng_trace_format_descriptor
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Thu, 7 Apr 2022 17:45:34 +0000 (13:45 -0400)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 19 Aug 2022 15:49:42 +0000 (11:49 -0400)
Implements an internal lttng::trace_format_descriptor c++ based object
as the backing object for lttng_trace_format_descriptor (C API).

TODO: MI might be better off using a visitor? Config also?
      Same for serialize?

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Change-Id: I588f9da11d2cbc697f26b91e006bdc23074ac9fd

include/Makefile.am
include/lttng/lttng.h
include/lttng/trace-format-descriptor-internal.hpp [new file with mode: 0644]
include/lttng/trace-format-descriptor.h [new file with mode: 0644]
src/common/Makefile.am
src/common/config/config-session-abi.hpp
src/common/config/session-config.cpp
src/common/trace-format-descriptor.cpp [new file with mode: 0644]
src/lib/lttng-ctl/liblttng-ctl.sym
tests/unit/Makefile.am
tests/unit/test_trace_format_descriptor.cpp [new file with mode: 0644]

index d840d58dcd8458487348a993feddde279d531485..e445d90357a6cf4ec63ef72f919e02e180fdd7a8 100644 (file)
@@ -123,6 +123,7 @@ lttnginclude_HEADERS = \
        lttng/session.h \
        lttng/snapshot.h \
        lttng/tracker.h \
+       lttng/trace-format-descriptor.h \
        lttng/userspace-probe.h
 
 lttngactioninclude_HEADERS= \
@@ -208,6 +209,7 @@ noinst_HEADERS = \
        lttng/session-internal.hpp \
        lttng/snapshot-internal.hpp \
        lttng/trigger/trigger-internal.hpp \
+       lttng/trace-format-descriptor-internal.hpp \
        lttng/userspace-probe-internal.hpp \
        version.hpp \
        version.i
index dbfe9a7dbde5f94494d646c957765a7b63c33e76..5833d0ba40342db39f8c4707f84c92986c6682e1 100644 (file)
 #include <lttng/event-expr.h>
 #include <lttng/event-field-value.h>
 #include <lttng/event-rule/event-rule.h>
-#include <lttng/event-rule/log4j-logging.h>
 #include <lttng/event-rule/jul-logging.h>
 #include <lttng/event-rule/kernel-kprobe.h>
 #include <lttng/event-rule/kernel-syscall.h>
-#include <lttng/event-rule/python-logging.h>
 #include <lttng/event-rule/kernel-tracepoint.h>
 #include <lttng/event-rule/kernel-uprobe.h>
+#include <lttng/event-rule/log4j-logging.h>
+#include <lttng/event-rule/python-logging.h>
 #include <lttng/event-rule/user-tracepoint.h>
 #include <lttng/event.h>
 #include <lttng/handle.h>
@@ -66,6 +66,7 @@
 #include <lttng/session-descriptor.h>
 #include <lttng/session.h>
 #include <lttng/snapshot.h>
+#include <lttng/trace-format-descriptor.h>
 #include <lttng/tracker.h>
 #include <lttng/trigger/trigger.h>
 #include <lttng/userspace-probe.h>
diff --git a/include/lttng/trace-format-descriptor-internal.hpp b/include/lttng/trace-format-descriptor-internal.hpp
new file mode 100644 (file)
index 0000000..6a142e2
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2022 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_TRACE_FORMAT_DESCRIPTOR_INTERNAL_HPP
+#define LTTNG_TRACE_FORMAT_DESCRIPTOR_INTERNAL_HPP
+
+#include <bits/stdint-uintn.h>
+#include <common/config/session-config.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/macros.hpp>
+#include <common/optional.hpp>
+#include <cstdint>
+#include <functional>
+#include <lttng/lttng.h>
+#include <lttng/trace-format-descriptor.h>
+#include <memory>
+#include <pthread.h>
+#include <sys/types.h>
+#include <unordered_map>
+#include <urcu/ref.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+struct mi_writer;
+
+struct lttng_trace_format_descriptor_comm {
+       uint8_t type;
+};
+
+namespace lttng {
+class trace_format_descriptor {
+public:
+       using uptr = std::unique_ptr<trace_format_descriptor>;
+       using sptr = std::shared_ptr<trace_format_descriptor>;
+       explicit trace_format_descriptor(enum lttng_trace_format_descriptor_type type) : _type(type)
+       {
+       }
+
+       virtual ~trace_format_descriptor();
+       virtual uptr clone() const = 0; // Virtual constructor (copying)
+
+       enum lttng_trace_format_descriptor_type type() const
+       {
+               return _type;
+       }
+
+       virtual lttng_error_code mi_serialize(mi_writer *writer) const final;
+       virtual lttng_error_code config_serialize(config_writer *writer) const final;
+       virtual int serialize(lttng_payload *payload) const;
+       static ssize_t create_from_payload(lttng_payload_view *view, uptr& descriptor);
+
+       friend bool operator==(
+                       trace_format_descriptor const& lhs, trace_format_descriptor const& rhs)
+       {
+               if (lhs.type() != rhs.type()) {
+                       return false;
+               }
+               return lhs.equal_to(rhs);
+       }
+
+       friend bool operator!=(
+                       trace_format_descriptor const& lhs, trace_format_descriptor const& rhs)
+       {
+               return !(lhs == rhs);
+       }
+
+protected:
+       using DeserializerFunction =
+                       std::function<ssize_t(lttng_payload_view *view, uptr& descriptor)>;
+       using deserializer_map =
+                       std::unordered_map<lttng_trace_format_descriptor_type, DeserializerFunction>;
+
+       static deserializer_map _deserializer_map;
+       virtual bool equal_to(trace_format_descriptor const& rhs) const = 0;
+
+private:
+       enum lttng_trace_format_descriptor_type _type = LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_UNKNOWN;
+
+       virtual lttng_error_code subtype_mi_serialize(mi_writer *writer) const = 0;
+       virtual lttng_error_code subtype_config_serialize(config_writer *writer) const = 0;
+};
+
+class trace_format_descriptor_ctf1 : public trace_format_descriptor {
+public:
+       trace_format_descriptor_ctf1() :
+               trace_format_descriptor(LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1)
+       {
+       } // Default constructor.
+
+       trace_format_descriptor_ctf1(trace_format_descriptor_ctf1 const&) :
+               trace_format_descriptor_ctf1()
+       {
+       } // Copy constructor
+
+       uptr clone() const
+       {
+               return uptr(new trace_format_descriptor_ctf1(*this));
+       }
+
+       uint64_t getMajor() const
+       {
+               return _major;
+       }
+       uint64_t getMinor() const
+       {
+               return _minor;
+       }
+
+protected:
+       static ssize_t deserialize(lttng_payload_view *view, uptr& descriptor);
+       bool equal_to(trace_format_descriptor const& rhs) const override;
+
+private:
+       lttng_error_code subtype_mi_serialize(mi_writer *writer) const override;
+       lttng_error_code subtype_config_serialize(config_writer *writer) const override;
+
+       const uint64_t _major = 1;
+       const uint64_t _minor = 8;
+};
+
+class trace_format_descriptor_ctf2 : public trace_format_descriptor {
+public:
+       trace_format_descriptor_ctf2() :
+               trace_format_descriptor(LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2)
+       {
+       }
+
+       trace_format_descriptor_ctf2(trace_format_descriptor_ctf2 const&) :
+               trace_format_descriptor_ctf2()
+       {
+       } // Copy constructor
+
+       uptr clone() const
+       {
+               return uptr(new trace_format_descriptor_ctf2(*this));
+       }
+
+       uint64_t getMajor() const
+       {
+               return _major;
+       }
+       uint64_t getMinor() const
+       {
+               return _minor;
+       }
+
+protected:
+       static ssize_t deserialize(lttng_payload_view *view, uptr& descriptor);
+       bool equal_to(trace_format_descriptor const& rhs) const override;
+
+private:
+       lttng_error_code subtype_mi_serialize(mi_writer *writer) const override;
+       lttng_error_code subtype_config_serialize(config_writer *writer) const override;
+       const uint64_t _major = 2;
+       const uint64_t _minor = 0;
+};
+} // namespace lttng
+
+#endif /* LTTNG_TRACE_FORMAT_DESCRIPTOR_INTERNAL_HPP */
diff --git a/include/lttng/trace-format-descriptor.h b/include/lttng/trace-format-descriptor.h
new file mode 100644 (file)
index 0000000..ade8225
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_TRACE_FORMAT_DESCRIPTOR_H
+#define LTTNG_TRACE_FORMAT_DESCRIPTOR_H
+
+#include <inttypes.h>
+#include <lttng/lttng-export.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lttng_trace_format_descriptor;
+
+enum lttng_trace_format_descriptor_status {
+       LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID = -1,
+       LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK = 0,
+};
+
+enum lttng_trace_format_descriptor_type {
+       LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_UNKNOWN = -1,
+       LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1 = 0,
+       LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2 = 1,
+};
+
+LTTNG_EXPORT extern enum lttng_trace_format_descriptor_type lttng_trace_format_get_type(
+               const struct lttng_trace_format_descriptor *descriptor);
+
+LTTNG_EXPORT extern struct lttng_trace_format_descriptor *
+lttng_trace_format_ctf_1_descriptor_create(void);
+
+LTTNG_EXPORT extern enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_1_get_version(
+               const struct lttng_trace_format_descriptor *descriptor,
+               uint64_t *major,
+               uint64_t *minor);
+
+LTTNG_EXPORT extern struct lttng_trace_format_descriptor *
+lttng_trace_format_ctf_2_descriptor_create(void);
+
+LTTNG_EXPORT extern enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_2_get_version(
+               const struct lttng_trace_format_descriptor *descriptor,
+               uint64_t *major,
+               uint64_t *minor);
+
+LTTNG_EXPORT void lttng_trace_format_descriptor_destroy(
+               struct lttng_trace_format_descriptor *descriptor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LTTNG_TRACE_FORMAT_DESCRIPTOR_H */
index a7d43b39c2ad36e63260ff18105784a373ee6b64..607b65971659d00e91775d174248ac9d58f2b00f 100644 (file)
@@ -105,6 +105,7 @@ libcommon_lgpl_la_SOURCES = \
        spawn-viewer.cpp spawn-viewer.hpp \
        thread.cpp thread.hpp \
        time.cpp \
+       trace-format-descriptor.cpp \
        tracker.cpp tracker.hpp \
        trigger.cpp \
        unix.cpp unix.hpp \
index f921a7363953a172db1f0d688aba09b9c665f00d..c61ea4a4f762d562453772c574ecaf0d58e54af2 100644 (file)
@@ -179,4 +179,8 @@ extern const char * const config_event_context_vgid;
 extern const char * const config_event_context_vegid;
 extern const char * const config_event_context_vsgid;
 
+extern const char * const config_element_session_trace_format;
+extern const char * const config_element_session_trace_format_ctf1;
+extern const char * const config_element_session_trace_format_ctf2;
+
 #endif /* CONFIG_SESSION_INTERNAL_H */
index 8f96b7f21e638a122fef392a4a5ed0e7dd3a86bf..f9d9d0eca558973a1e649bd4281d2572f9795bd2 100644 (file)
@@ -227,6 +227,11 @@ const char * const config_event_context_vgid = "VGID";
 const char * const config_event_context_vegid = "VEGID";
 const char * const config_event_context_vsgid = "VSGID";
 
+const char * const config_element_session_trace_format = "trace_format";
+const char * const config_element_session_trace_format_ctf1 = "ctf1";
+const char * const config_element_session_trace_format_ctf2 = "ctf2";
+
+
 /* Deprecated symbols */
 LTTNG_EXPORT const char *config_element_perf;
 
diff --git a/src/common/trace-format-descriptor.cpp b/src/common/trace-format-descriptor.cpp
new file mode 100644 (file)
index 0000000..d9d3ef5
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2022 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <bits/stdint-intn.h>
+#include <common/mi-lttng.hpp>
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/lttng-error.h>
+#include <lttng/trace-format-descriptor-internal.hpp>
+#include <lttng/trace-format-descriptor.h>
+#include <memory>
+
+namespace lttng {
+/* Initialize deserializer map */
+trace_format_descriptor::deserializer_map trace_format_descriptor::_deserializer_map;
+
+template <class type, lttng_trace_format_descriptor_type enumType>
+class deserializer_register {
+private:
+       class initializer : public type {
+       public:
+               initializer()
+               {
+                       type::_deserializer_map[enumType] = type::deserialize;
+               }
+       };
+
+public:
+       deserializer_register()
+       {
+               deserializer_register::initializer i;
+       }
+};
+
+/* Default destructor for the base type */
+trace_format_descriptor::~trace_format_descriptor() = default;
+
+static deserializer_register<trace_format_descriptor_ctf1, LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1>
+               ctf1Deserializer;
+static deserializer_register<trace_format_descriptor_ctf2, LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2>
+               ctf2Deserializer;
+
+enum lttng_error_code trace_format_descriptor::mi_serialize(struct mi_writer *writer) const
+{
+       int ret;
+       enum lttng_error_code ret_code;
+
+       LTTNG_ASSERT(writer);
+
+       /* Open trace format element. */
+       ret = mi_lttng_writer_open_element(writer, config_element_session_trace_format);
+       if (ret) {
+               goto mi_error;
+       }
+
+       /* Serialize underlying descriptor. */
+       ret_code = this->subtype_mi_serialize(writer);
+       if (ret_code != LTTNG_OK) {
+               goto end;
+       }
+
+       /* Close trace format element. */
+       ret = mi_lttng_writer_close_element(writer);
+       if (ret) {
+               goto mi_error;
+       }
+       ret_code = LTTNG_OK;
+       goto end;
+mi_error:
+       ret_code = LTTNG_ERR_MI_IO_FAIL;
+end:
+       return ret_code;
+}
+
+lttng_error_code trace_format_descriptor_ctf1::subtype_mi_serialize(mi_writer *writer) const
+{
+       int ret;
+       enum lttng_error_code ret_code;
+
+       LTTNG_ASSERT(writer);
+
+       /* Open ctf1 element. */
+       ret = mi_lttng_writer_open_element(writer, config_element_session_trace_format_ctf1);
+       if (ret) {
+               goto mi_error;
+       }
+
+       ret = mi_lttng_writer_write_element_unsigned_int(
+                       writer, mi_lttng_element_version_major, _major);
+       if (ret) {
+               goto mi_error;
+       }
+
+       ret = mi_lttng_writer_write_element_unsigned_int(
+                       writer, mi_lttng_element_version_minor, _minor);
+       if (ret) {
+               goto mi_error;
+       }
+
+       /* Close ctf1 element. */
+       ret = mi_lttng_writer_close_element(writer);
+       if (ret) {
+               goto mi_error;
+       }
+       ret_code = LTTNG_OK;
+       goto end;
+mi_error:
+       ret_code = LTTNG_ERR_MI_IO_FAIL;
+end:
+       return ret_code;
+}
+
+lttng_error_code trace_format_descriptor_ctf2::subtype_mi_serialize(mi_writer *writer) const
+{
+       int ret;
+       enum lttng_error_code ret_code;
+
+       LTTNG_ASSERT(writer);
+
+       /* Open ctf2 element. */
+       ret = mi_lttng_writer_open_element(writer, config_element_session_trace_format_ctf2);
+       if (ret) {
+               goto mi_error;
+       }
+
+       ret = mi_lttng_writer_write_element_unsigned_int(
+                       writer, mi_lttng_element_version_major, _major);
+       if (ret) {
+               goto mi_error;
+       }
+
+       ret = mi_lttng_writer_write_element_unsigned_int(
+                       writer, mi_lttng_element_version_minor, _minor);
+       if (ret) {
+               goto mi_error;
+       }
+
+       /* Close ctf2 element. */
+       ret = mi_lttng_writer_close_element(writer);
+       if (ret) {
+               goto mi_error;
+       }
+       ret_code = LTTNG_OK;
+       goto end;
+mi_error:
+       ret_code = LTTNG_ERR_MI_IO_FAIL;
+end:
+       return ret_code;
+}
+
+enum lttng_error_code trace_format_descriptor::config_serialize(config_writer *writer) const
+{
+       int ret;
+       enum lttng_error_code ret_code;
+
+       LTTNG_ASSERT(writer);
+
+       /* Open trace format element. */
+       ret = config_writer_open_element(writer, config_element_session_trace_format);
+       if (ret) {
+               goto mi_error;
+       }
+
+       /* Serialize underlying descriptor. */
+       ret_code = this->subtype_config_serialize(writer);
+       if (ret_code != LTTNG_OK) {
+               goto end;
+       }
+
+       /* Close trace format element. */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               goto mi_error;
+       }
+       ret_code = LTTNG_OK;
+       goto end;
+mi_error:
+       ret_code = LTTNG_ERR_MI_IO_FAIL;
+end:
+       return ret_code;
+}
+
+lttng_error_code trace_format_descriptor_ctf1::subtype_config_serialize(config_writer *writer) const
+{
+       int ret;
+       enum lttng_error_code ret_code;
+
+       LTTNG_ASSERT(writer);
+
+       /* Open ctf1 element. */
+       ret = config_writer_open_element(writer, config_element_session_trace_format_ctf1);
+       if (ret) {
+               goto error;
+       }
+
+       /* Close ctf1 element. */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               goto error;
+       }
+       ret_code = LTTNG_OK;
+       goto end;
+error:
+       ret_code = LTTNG_ERR_SAVE_IO_FAIL;
+end:
+       return ret_code;
+}
+
+lttng_error_code trace_format_descriptor_ctf2::subtype_config_serialize(config_writer *writer) const
+{
+       int ret;
+       enum lttng_error_code ret_code;
+
+       LTTNG_ASSERT(writer);
+
+       /* Open ctf2 element. */
+       ret = config_writer_open_element(writer, config_element_session_trace_format_ctf2);
+       if (ret) {
+               goto error;
+       }
+
+       /* Close ctf2 element. */
+       ret = config_writer_close_element(writer);
+       if (ret) {
+               goto error;
+       }
+       ret_code = LTTNG_OK;
+       goto end;
+error:
+       ret_code = LTTNG_ERR_SAVE_IO_FAIL;
+end:
+       return ret_code;
+}
+
+int trace_format_descriptor::serialize(lttng_payload *payload) const
+{
+       struct lttng_trace_format_descriptor_comm comm = {};
+
+       LTTNG_ASSERT(payload);
+
+       comm.type = (int8_t) this->type();
+
+       return lttng_dynamic_buffer_append(&payload->buffer, &comm, sizeof(comm));
+}
+
+ssize_t trace_format_descriptor_ctf1::deserialize(lttng_payload_view *view, uptr& descriptor)
+{
+       int ret = 0;
+
+       /* Nothing to deserialize */
+       (void) view;
+
+       trace_format_descriptor::uptr local_descriptor(new trace_format_descriptor_ctf1);
+       descriptor = std::move(local_descriptor);
+
+       return ret;
+}
+bool trace_format_descriptor_ctf1::equal_to(const trace_format_descriptor& rhs) const
+{
+       trace_format_descriptor_ctf1 const *p =
+                       static_cast<trace_format_descriptor_ctf1 const *>(&rhs);
+
+       return _major == p->_major && _minor == p->_minor;
+}
+
+ssize_t trace_format_descriptor_ctf2::deserialize(lttng_payload_view *view, uptr& descriptor)
+{
+       int ret = 0;
+
+       /* Nothing to deserialize */
+       (void) view;
+
+       trace_format_descriptor::uptr local_descriptor(new trace_format_descriptor_ctf2);
+       descriptor = std::move(local_descriptor);
+
+       return ret;
+}
+bool trace_format_descriptor_ctf2::equal_to(const trace_format_descriptor& rhs) const
+{
+       trace_format_descriptor_ctf2 const *p =
+                       static_cast<trace_format_descriptor_ctf2 const *>(&rhs);
+
+       return _major == p->_major && _minor == p->_minor;
+}
+
+ssize_t trace_format_descriptor::create_from_payload(lttng_payload_view *view, uptr& descriptor)
+{
+       ssize_t ret = 0, consumed = 0;
+       const struct lttng_trace_format_descriptor_comm *comm;
+       const struct lttng_payload_view comm_view =
+                       lttng_payload_view_from_view(view, 0, sizeof(*comm));
+
+       if (!view) {
+               return -1;
+       }
+
+       if (!lttng_payload_view_is_valid(&comm_view)) {
+               /* Payload not large enough to contain the header. */
+               return -1;
+       }
+
+       comm = (typeof(comm)) comm_view.buffer.data;
+       consumed += sizeof(*comm);
+
+       lttng_trace_format_descriptor_type type = (lttng_trace_format_descriptor_type) comm->type;
+       ret = _deserializer_map[type](view, descriptor);
+       if (ret < 0) {
+               return ret;
+       }
+       consumed += ret;
+
+       ret = consumed;
+
+       return ret;
+}
+} // namespace lttng
+
+struct lttng_trace_format_descriptor *lttng_trace_format_ctf_1_descriptor_create()
+{
+       lttng::trace_format_descriptor *descriptor = new lttng::trace_format_descriptor_ctf1();
+       return reinterpret_cast<struct lttng_trace_format_descriptor *>(descriptor);
+}
+
+struct lttng_trace_format_descriptor *lttng_trace_format_ctf_2_descriptor_create()
+{
+       lttng::trace_format_descriptor *descriptor = new lttng::trace_format_descriptor_ctf2();
+       return reinterpret_cast<struct lttng_trace_format_descriptor *>(descriptor);
+}
+
+void lttng_trace_format_descriptor_destroy(lttng_trace_format_descriptor *descriptor)
+{
+       if (descriptor == nullptr) {
+               return;
+       }
+
+       lttng::trace_format_descriptor *_descriptor =
+                       reinterpret_cast<lttng::trace_format_descriptor *>(descriptor);
+
+       delete _descriptor;
+}
+
+enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_1_get_version(
+               const struct lttng_trace_format_descriptor *descriptor,
+               uint64_t *major,
+               uint64_t *minor)
+{
+       lttng_trace_format_descriptor_status status;
+       const lttng::trace_format_descriptor *tf;
+       const lttng::trace_format_descriptor_ctf1 *ctf1;
+
+       if (descriptor == nullptr || major == nullptr || minor == nullptr) {
+               status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID;
+               goto end;
+       }
+
+       tf = reinterpret_cast<const lttng::trace_format_descriptor *>(descriptor);
+
+       if (tf->type() != LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1) {
+               status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID;
+               goto end;
+       }
+
+       ctf1 = static_cast<const lttng::trace_format_descriptor_ctf1 *>(tf);
+
+       *major = ctf1->getMajor();
+       *minor = ctf1->getMinor();
+       status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK;
+
+end:
+       return status;
+}
+
+enum lttng_trace_format_descriptor_status lttng_trace_format_ctf_2_get_version(
+               const struct lttng_trace_format_descriptor *descriptor,
+               uint64_t *major,
+               uint64_t *minor)
+{
+       lttng_trace_format_descriptor_status status;
+       const lttng::trace_format_descriptor *tf;
+       const lttng::trace_format_descriptor_ctf2 *ctf2;
+
+       if (descriptor == nullptr || major == nullptr || minor == nullptr) {
+               status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID;
+               goto end;
+       }
+
+       tf = reinterpret_cast<const lttng::trace_format_descriptor *>(descriptor);
+
+       if (tf->type() != LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_2) {
+               status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID;
+               goto end;
+       }
+
+       ctf2 = static_cast<const lttng::trace_format_descriptor_ctf2 *>(tf);
+
+       *major = ctf2->getMajor();
+       *minor = ctf2->getMinor();
+       status = LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK;
+
+end:
+       return status;
+}
+enum lttng_trace_format_descriptor_type lttng_trace_format_get_type(
+               const struct lttng_trace_format_descriptor *descriptor)
+{
+       if (!descriptor) {
+               return LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_UNKNOWN;
+       }
+
+       auto tf = reinterpret_cast<const lttng::trace_format_descriptor *>(descriptor);
+
+       return tf->type();
+}
index b69e78df9cb8b45d66eb4c20a12837a99c742ceb..e72e121ba839a7be038c1356660bb0a2483ca953 100644 (file)
@@ -504,6 +504,10 @@ lttng_trace_archive_location_relay_get_data_port
 lttng_trace_archive_location_relay_get_host
 lttng_trace_archive_location_relay_get_protocol_type
 lttng_trace_archive_location_relay_get_relative_path
+lttng_trace_format_ctf_1_get_version
+lttng_trace_format_ctf_2_get_version
+lttng_trace_format_descriptor_destroy
+lttng_trace_format_get_type
 lttng_track_pid
 lttng_trigger_create
 lttng_trigger_destroy
index d1b526d307a9d245ace77c20111ae15ce88e6baf..8bc59b3fe7e3f8c2eb24706ce9cf4cc3562041ba 100644 (file)
@@ -32,6 +32,7 @@ TESTS = \
        test_utils_expand_path \
        test_utils_parse_size_suffix \
        test_utils_parse_time_suffix \
+       test_trace_format_descriptor \
        test_uuid
 
 LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la
@@ -62,6 +63,7 @@ noinst_PROGRAMS = \
        test_relayd_backward_compat_group_by_session \
        test_session \
        test_string_utils \
+       test_trace_format_descriptor \
        test_unix_socket \
        test_uri \
        test_utils_compat_poll \
@@ -189,3 +191,7 @@ test_log_level_rule_LDADD = $(LIBTAP) $(LIBCOMMON_GPL) $(LIBLTTNG_CTL) $(DL_LIBS
 # Action api
 test_action_SOURCES = test_action.cpp
 test_action_LDADD = $(LIBTAP) $(LIBCOMMON_GPL) $(LIBLTTNG_CTL) $(DL_LIBS)
+
+# Trace format descriptor
+test_trace_format_descriptor_SOURCES = test_trace_format_descriptor.cpp
+test_trace_format_descriptor_LDADD = $(LIBTAP) $(LIBCOMMON_GPL) $(LIBLTTNG_CTL) $(DL_LIBS)
diff --git a/tests/unit/test_trace_format_descriptor.cpp b/tests/unit/test_trace_format_descriptor.cpp
new file mode 100644 (file)
index 0000000..a9d3d3a
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Unit tests for the trace format descriptor API.
+ *
+ * Copyright (C) 2022 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.hpp>
+#include <common/payload.hpp>
+#include <lttng/trace-format-descriptor-internal.hpp>
+#include <lttng/trace-format-descriptor.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 28
+
+static void test_trace_format_descriptor_base(void)
+{
+       lttng_trace_format_descriptor_status status;
+       uint64_t major;
+       uint64_t minor;
+
+       lttng_trace_format_descriptor *ctf1 = lttng_trace_format_ctf_1_descriptor_create();
+       lttng_trace_format_descriptor *ctf2 = lttng_trace_format_ctf_2_descriptor_create();
+       ok1(ctf1);
+       ok1(ctf2);
+
+       /* Ctf 1 */
+       status = lttng_trace_format_ctf_1_get_version(nullptr, nullptr, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_1_get_version(nullptr, nullptr, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_1_get_version(nullptr, &major, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_1_get_version(nullptr, &major, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_1_get_version(ctf1, nullptr, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_1_get_version(ctf1, nullptr, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_1_get_version(ctf1, &major, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+
+       /* Wrong object type */
+       status = lttng_trace_format_ctf_1_get_version(ctf2, &major, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+
+       status = lttng_trace_format_ctf_1_get_version(ctf1, &major, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK);
+       ok1(major == 1);
+       ok1(minor == 8);
+
+       /* Ctf 2 */
+       status = lttng_trace_format_ctf_2_get_version(nullptr, nullptr, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_2_get_version(nullptr, nullptr, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_2_get_version(nullptr, &major, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_2_get_version(nullptr, &major, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_2_get_version(ctf2, nullptr, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_2_get_version(ctf2, nullptr, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+       status = lttng_trace_format_ctf_2_get_version(ctf2, &major, nullptr);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+
+       /* Wrong object type */
+       status = lttng_trace_format_ctf_1_get_version(ctf2, &major, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_INVALID);
+
+       status = lttng_trace_format_ctf_2_get_version(ctf2, &major, &minor);
+       ok1(status == LTTNG_TRACE_FORMAT_DESCRIPTOR_STATUS_OK);
+       ok1(major == 2);
+       ok1(minor == 0);
+
+       lttng_trace_format_descriptor_destroy(ctf1);
+       lttng_trace_format_descriptor_destroy(ctf2);
+}
+
+static void test_trace_format_descriptor_ctf1_ser_des(void)
+{
+       struct lttng_payload buffer;
+       lttng_payload_init(&buffer);
+
+       lttng::trace_format_descriptor::uptr descriptor_from_buffer;
+       lttng::trace_format_descriptor::uptr ctf1(new lttng::trace_format_descriptor_ctf1);
+       lttng::trace_format_descriptor::uptr ctf2(new lttng::trace_format_descriptor_ctf2);
+
+       /* Ctf1 ser/des */
+       ctf1->serialize(&buffer);
+       {
+               struct lttng_payload_view view = lttng_payload_view_from_payload(&buffer, 0, -1);
+
+               (void) lttng::trace_format_descriptor::create_from_payload(
+                               &view, descriptor_from_buffer);
+       }
+
+       ok1(*descriptor_from_buffer == *ctf1);
+       ok1(*descriptor_from_buffer != *ctf2);
+
+       lttng_payload_reset(&buffer);
+
+       /* Ctf2 ser/des */
+       ctf2->serialize(&buffer);
+       {
+               struct lttng_payload_view view = lttng_payload_view_from_payload(&buffer, 0, -1);
+
+               (void) lttng::trace_format_descriptor::create_from_payload(
+                               &view, descriptor_from_buffer);
+       }
+
+       ok1(*descriptor_from_buffer != *ctf1);
+       ok1(*descriptor_from_buffer == *ctf2);
+
+       lttng_payload_reset(&buffer);
+}
+
+int main(void)
+{
+       plan_tests(NUM_TESTS);
+       test_trace_format_descriptor_base();
+       test_trace_format_descriptor_ctf1_ser_des();
+       return exit_status();
+}
This page took 0.036778 seconds and 5 git commands to generate.