cpp-common/bt2: add C++ bindings around `bt_error *`
authorSimon Marchi <simon.marchi@efficios.com>
Tue, 12 Mar 2024 22:17:42 +0000 (18:17 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Tue, 26 Mar 2024 18:56:36 +0000 (14:56 -0400)
Add C++ bindings to access the error on the current thread.

 - Take the current thread error with takeCurrentThreadError(),
   returning a `UniqueConstError`.
 - Move the current thread error back with moveErrorToCurrentThread().
 - Access the error cause by iterating or subscripting
   `UniqueConstError`, which yields objects of type `ConstErrorCause` (a
   borrowed object type).
 - Access the common error cause information using methods of
   `ConstErrorCause`, including the error cause actor type.
 - Obtain a more specific error cause object with
   `ConstErrorCause::as*()`.

Change-Id: Ie18e22ef8901bc9c8d7c85432d515ca763b484c2
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/12006
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
src/Makefile.am
src/cpp-common/bt2/component-class.hpp
src/cpp-common/bt2/error.hpp [new file with mode: 0644]
src/cpp-common/bt2/wrap.hpp

index bdd43fc0dd66b667e9bab0bd92a57f281891c9f7..0cf759902ecda513ce300f8016482b7c7f86eea9 100644 (file)
@@ -127,6 +127,7 @@ cpp_common_libcpp_common_la_SOURCES = \
        cpp-common/bt2/component-class.hpp \
        cpp-common/bt2/component-port.hpp \
        cpp-common/bt2/graph.hpp \
+       cpp-common/bt2/error.hpp \
        cpp-common/bt2/exc.hpp \
        cpp-common/bt2/field-class.hpp \
        cpp-common/bt2/field-path.hpp \
index efee3f43cfec81c5544089a4c3a010d70ed79047..e32ba34ae6811be0558401ce3f3f05de0b91b057 100644 (file)
@@ -52,6 +52,13 @@ public:
     using typename _ThisBorrowedObject::LibObjPtr;
     using Shared = SharedObject<CommonComponentClass, LibObjT, internal::ComponentClassRefFuncs>;
 
+    enum class Type
+    {
+        SOURCE = BT_COMPONENT_CLASS_TYPE_SOURCE,
+        FILTER = BT_COMPONENT_CLASS_TYPE_FILTER,
+        SINK = BT_COMPONENT_CLASS_TYPE_SINK,
+    };
+
     explicit CommonComponentClass(const LibObjPtr libObjPtr) noexcept :
         _ThisBorrowedObject {libObjPtr}
     {
diff --git a/src/cpp-common/bt2/error.hpp b/src/cpp-common/bt2/error.hpp
new file mode 100644 (file)
index 0000000..7daaaf6
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2024 EfficiOS Inc.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef BABELTRACE_CPP_COMMON_BT2_ERROR_HPP
+#define BABELTRACE_CPP_COMMON_BT2_ERROR_HPP
+
+#include <cstdint>
+#include <memory>
+
+#include <babeltrace2/babeltrace.h>
+
+#include "common/assert.h"
+#include "cpp-common/bt2c/c-string-view.hpp"
+#include "cpp-common/vendor/fmt/format.h" /* IWYU pragma: keep */
+
+#include "borrowed-object.hpp"
+#include "component-class.hpp"
+
+namespace bt2 {
+
+class ConstComponentClassErrorCause;
+class ConstComponentErrorCause;
+class ConstMessageIteratorErrorCause;
+
+class ConstErrorCause : public BorrowedObject<const bt_error_cause>
+{
+public:
+    enum class ActorType
+    {
+        UNKNOWN = BT_ERROR_CAUSE_ACTOR_TYPE_UNKNOWN,
+        COMPONENT = BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT,
+        COMPONENT_CLASS = BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS,
+        MESSAGE_ITERATOR = BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR,
+    };
+
+    explicit ConstErrorCause(const LibObjPtr libObjPtr) noexcept : _ThisBorrowedObject {libObjPtr}
+    {
+    }
+
+    ActorType actorType() const noexcept
+    {
+        return static_cast<ActorType>(bt_error_cause_get_actor_type(this->libObjPtr()));
+    }
+
+    bool actorTypeIsComponentClass() const noexcept
+    {
+        return this->actorType() == ActorType::COMPONENT_CLASS;
+    }
+
+    bool actorTypeIsComponent() const noexcept
+    {
+        return this->actorType() == ActorType::COMPONENT;
+    }
+
+    bool actorTypeIsMessageIterator() const noexcept
+    {
+        return this->actorType() == ActorType::MESSAGE_ITERATOR;
+    }
+
+    ConstComponentClassErrorCause asComponentClass() const noexcept;
+    ConstComponentErrorCause asComponent() const noexcept;
+    ConstMessageIteratorErrorCause asMessageIterator() const noexcept;
+
+    bt2c::CStringView message() const noexcept
+    {
+        return bt_error_cause_get_message(this->libObjPtr());
+    }
+
+    bt2c::CStringView moduleName() const noexcept
+    {
+        return bt_error_cause_get_module_name(this->libObjPtr());
+    }
+
+    bt2c::CStringView fileName() const noexcept
+    {
+        return bt_error_cause_get_file_name(this->libObjPtr());
+    }
+
+    std::uint64_t lineNumber() const noexcept
+    {
+        return bt_error_cause_get_line_number(this->libObjPtr());
+    }
+};
+
+class ConstComponentClassErrorCause final : public ConstErrorCause
+{
+public:
+    explicit ConstComponentClassErrorCause(const LibObjPtr libObjPtr) : ConstErrorCause {libObjPtr}
+    {
+        BT_ASSERT(this->actorTypeIsComponentClass());
+    }
+
+    bt2::ComponentClass::Type componentClassType() const noexcept
+    {
+        return static_cast<bt2::ComponentClass::Type>(
+            bt_error_cause_component_class_actor_get_component_class_type(this->libObjPtr()));
+    }
+
+    bt2c::CStringView componentClassName() const noexcept
+    {
+        return bt_error_cause_component_class_actor_get_component_class_name(this->libObjPtr());
+    }
+
+    bt2c::CStringView pluginName() const noexcept
+    {
+        return bt_error_cause_component_class_actor_get_plugin_name(this->libObjPtr());
+    }
+};
+
+inline ConstComponentClassErrorCause ConstErrorCause::asComponentClass() const noexcept
+{
+    return ConstComponentClassErrorCause {this->libObjPtr()};
+}
+
+class ConstComponentErrorCause final : public ConstErrorCause
+{
+public:
+    explicit ConstComponentErrorCause(const LibObjPtr libObjPtr) : ConstErrorCause {libObjPtr}
+    {
+        BT_ASSERT(this->actorTypeIsComponent());
+    }
+
+    bt2c::CStringView componentName() const noexcept
+    {
+        return bt_error_cause_component_actor_get_component_name(this->libObjPtr());
+    }
+
+    bt2::ComponentClass::Type componentClassType() const noexcept
+    {
+        return static_cast<bt2::ComponentClass::Type>(
+            bt_error_cause_component_actor_get_component_class_type(this->libObjPtr()));
+    }
+
+    bt2c::CStringView componentClassName() const noexcept
+    {
+        return bt_error_cause_component_actor_get_component_class_name(this->libObjPtr());
+    }
+
+    bt2c::CStringView pluginName() const noexcept
+    {
+        return bt_error_cause_component_actor_get_plugin_name(this->libObjPtr());
+    }
+};
+
+inline ConstComponentErrorCause ConstErrorCause::asComponent() const noexcept
+{
+    return ConstComponentErrorCause {this->libObjPtr()};
+}
+
+class ConstMessageIteratorErrorCause final : public ConstErrorCause
+{
+public:
+    explicit ConstMessageIteratorErrorCause(const LibObjPtr libObjPtr) : ConstErrorCause {libObjPtr}
+    {
+        BT_ASSERT(this->actorTypeIsMessageIterator());
+    }
+
+    bt2c::CStringView componentOutputPortName() const noexcept
+    {
+        return bt_error_cause_message_iterator_actor_get_component_name(this->libObjPtr());
+    }
+
+    bt2c::CStringView componentName() const noexcept
+    {
+        return bt_error_cause_message_iterator_actor_get_component_name(this->libObjPtr());
+    }
+
+    bt2::ComponentClass::Type componentClassType() const noexcept
+    {
+        return static_cast<bt2::ComponentClass::Type>(
+            bt_error_cause_message_iterator_actor_get_component_class_type(this->libObjPtr()));
+    }
+
+    bt2c::CStringView componentClassName() const noexcept
+    {
+        return bt_error_cause_message_iterator_actor_get_component_class_name(this->libObjPtr());
+    }
+
+    bt2c::CStringView pluginName() const noexcept
+    {
+        return bt_error_cause_message_iterator_actor_get_plugin_name(this->libObjPtr());
+    }
+};
+
+inline ConstMessageIteratorErrorCause ConstErrorCause::asMessageIterator() const noexcept
+{
+    return ConstMessageIteratorErrorCause {this->libObjPtr()};
+}
+
+class ConstErrorIterator;
+
+class ConstErrorCauseProxy final
+{
+    friend ConstErrorIterator;
+
+private:
+    explicit ConstErrorCauseProxy(const ConstErrorCause cause) noexcept : _mCause {cause}
+    {
+    }
+
+public:
+    const ConstErrorCause *operator->() const noexcept
+    {
+        return &_mCause;
+    }
+
+private:
+    ConstErrorCause _mCause;
+};
+
+class UniqueConstError;
+
+class ConstErrorIterator final
+{
+    friend UniqueConstError;
+
+private:
+    explicit ConstErrorIterator(const UniqueConstError& error, const std::uint64_t index) noexcept :
+        _mError {error}, _mIndex {index}
+    {
+    }
+
+public:
+    bool operator==(const ConstErrorIterator& other) const noexcept
+    {
+        BT_ASSERT(&other._mError == &_mError);
+        return other._mIndex == _mIndex;
+    }
+
+    bool operator!=(const ConstErrorIterator& other) const noexcept
+    {
+        return !(*this == other);
+    }
+
+    ConstErrorIterator& operator++() noexcept
+    {
+        ++_mIndex;
+        return *this;
+    }
+
+    ConstErrorIterator operator++(int) noexcept
+    {
+        const auto ret = *this;
+
+        ++_mIndex;
+        return ret;
+    }
+
+    ConstErrorCause operator*() const noexcept;
+
+    ConstErrorCauseProxy operator->() const noexcept
+    {
+        return ConstErrorCauseProxy {**this};
+    }
+
+private:
+    const UniqueConstError& _mError;
+    std::uint64_t _mIndex;
+};
+
+class UniqueConstError final
+{
+public:
+    using LibObjPtr = const bt_error *;
+
+    explicit UniqueConstError(const LibObjPtr libError) noexcept : _mLibError {libError}
+    {
+    }
+
+    explicit operator bool() const noexcept
+    {
+        return this->libObjPtr();
+    }
+
+    LibObjPtr libObjPtr() const noexcept
+    {
+        return _mLibError.get();
+    }
+
+    LibObjPtr release() noexcept
+    {
+        return _mLibError.release();
+    }
+
+    std::uint64_t length() const noexcept
+    {
+        return bt_error_get_cause_count(this->libObjPtr());
+    }
+
+    ConstErrorCause operator[](const std::uint64_t index) const noexcept
+    {
+        return ConstErrorCause {bt_error_borrow_cause_by_index(this->libObjPtr(), index)};
+    }
+
+    ConstErrorIterator begin() const noexcept
+    {
+        BT_ASSERT(_mLibError);
+        return ConstErrorIterator {*this, 0};
+    }
+
+    ConstErrorIterator end() const noexcept
+    {
+        BT_ASSERT(_mLibError);
+        return ConstErrorIterator {*this, this->length()};
+    }
+
+private:
+    struct _LibErrorDeleter final
+    {
+        void operator()(const LibObjPtr libError) const noexcept
+        {
+            bt_error_release(libError);
+        }
+    };
+
+    std::unique_ptr<std::remove_pointer<LibObjPtr>::type, _LibErrorDeleter> _mLibError;
+};
+
+inline ConstErrorCause ConstErrorIterator::operator*() const noexcept
+{
+    return _mError[_mIndex];
+}
+
+inline UniqueConstError takeCurrentThreadError() noexcept
+{
+    return UniqueConstError {bt_current_thread_take_error()};
+}
+
+inline void moveErrorToCurrentThread(UniqueConstError error) noexcept
+{
+    bt_current_thread_move_error(error.release());
+}
+
+} /* namespace bt2 */
+
+#endif /* BABELTRACE_CPP_COMMON_BT2_ERROR_HPP */
index 3b8a86f8e15de0d377806e549795932c4675ffda..c3b177cc089ba4640173f50e66dd2a8a19fa7504 100644 (file)
@@ -12,6 +12,7 @@
 #include "clock-class.hpp"
 #include "clock-snapshot.hpp"
 #include "component-port.hpp"
+#include "error.hpp"
 #include "field-class.hpp"
 #include "field.hpp"
 #include "graph.hpp"
 
 namespace bt2 {
 
+inline ConstErrorCause wrap(const bt_error_cause * const libObjPtr) noexcept
+{
+    return ConstErrorCause {libObjPtr};
+}
+
 inline Graph wrap(bt_graph * const libObjPtr) noexcept
 {
     return Graph {libObjPtr};
This page took 0.028315 seconds and 4 git commands to generate.