flt.utils.muxer: use a heap to sort iterators (also: rewrite in C++)
[babeltrace.git] / src / plugins / utils / muxer / msg-iter.hpp
diff --git a/src/plugins/utils/muxer/msg-iter.hpp b/src/plugins/utils/muxer/msg-iter.hpp
new file mode 100644 (file)
index 0000000..993ed4a
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2023 Philippe Proulx <pproulx@efficios.com>
+ */
+
+#ifndef BABELTRACE_PLUGINS_UTILS_MUXER_MSG_ITER_HPP
+#define BABELTRACE_PLUGINS_UTILS_MUXER_MSG_ITER_HPP
+
+#include <vector>
+
+#include "cpp-common/bt2/optional-borrowed-object.hpp"
+#include "cpp-common/bt2/plugin-dev.hpp"
+#include "cpp-common/bt2c/prio-heap.hpp"
+#include "cpp-common/bt2c/uuid.hpp"
+#include "cpp-common/bt2s/optional.hpp"
+
+#include "upstream-msg-iter.hpp"
+
+namespace bt2mux {
+
+class Comp;
+
+class MsgIter final : public bt2::UserMessageIterator<MsgIter, Comp>
+{
+    friend bt2::UserMessageIterator<MsgIter, Comp>;
+
+private:
+    /* Clock class nature expectation */
+    enum class _ClkClsExpectation
+    {
+        ANY,
+        NONE,
+        ORIG_IS_UNIX_EPOCH,
+        ORIG_ISNT_UNIX_EPOCH_AND_SPEC_UUID,
+        ORIG_ISNT_UNIX_EPOCH_AND_NO_UUID,
+    };
+
+    /* Comparator for `_mHeap` with its own logger */
+    class _HeapComparator final
+    {
+    public:
+        explicit _HeapComparator(const bt2c::Logger& logger);
+
+        bool operator()(const UpstreamMsgIter *upstreamMsgIterA,
+                        const UpstreamMsgIter *upstreamMsgIterB) const noexcept;
+
+    private:
+        bt2c::Logger _mLogger;
+    };
+
+public:
+    explicit MsgIter(bt2::SelfMessageIterator selfMsgIter,
+                     bt2::SelfMessageIteratorConfiguration config,
+                     bt2::SelfComponentOutputPort selfPort);
+
+private:
+    bool _canSeekBeginning();
+    void _seekBeginning();
+    void _next(bt2::ConstMessageArray& msgs);
+
+    /*
+     * Makes sure `_mUpstreamMsgItersToReload` is empty so that `_mHeap`
+     * is ready for the next message selection.
+     *
+     * This may throw whatever UpstreamMsgIter::reload() may throw.
+     */
+    void _ensureFullHeap();
+
+    /*
+     * Validates the clock class of the received message `msg`, setting
+     * the expectation if this is the first one.
+     *
+     * Throws `bt2::Error` on error.
+     */
+    void _validateMsgClkCls(bt2::ConstMessage msg);
+
+    /*
+     * Sets the clock class expectation (`_mClkClsExpectation` and
+     * `_mExpectedClkClsUuid`) according to `clkCls`.
+     */
+    void _setClkClsExpectation(bt2::OptionalBorrowedObject<bt2::ConstClockClass> clkCls) noexcept;
+
+    /*
+     * Checks that `clkCls` meets the current clock class expectation,
+     * throwing if it doesn't.
+     */
+    void _makeSureClkClsIsExpected(bt2::ConstMessage msg,
+                                   bt2::OptionalBorrowedObject<bt2::ConstClockClass> clkCls) const;
+
+    /*
+     * Container of all the upstream message iterators.
+     *
+     * The only purpose of this is to own them; where they are below
+     * indicates their state.
+     */
+    std::vector<UpstreamMsgIter::UP> _mUpstreamMsgIters;
+
+    /*
+     * Heap of ready-to-use upstream message iterators (pointers to
+     * owned objects in `_mUpstreamMsgIters` above).
+     */
+    bt2c::PrioHeap<UpstreamMsgIter *, _HeapComparator> _mHeap;
+
+    /*
+     * Current upstream message iterators to reload, on which we must
+     * call reload() before moving them to `_mHeap` or to
+     * `_mEndedUpstreamMsgIters`.
+     *
+     * Using `std::vector` instead of some linked list because the
+     * typical scenario is to add a single one and then remove it
+     * shortly after.
+     */
+    std::vector<UpstreamMsgIter *> _mUpstreamMsgItersToReload;
+
+    /*
+     * Which kind of clock class to expect from any incoming message.
+     *
+     * The very first received message determines this for all the
+     * following.
+     *
+     * For `ORIG_ISNT_UNIX_EPOCH_AND_SPEC_UUID`, `*_mExpectedClkClsUuid`
+     * is the expected specific UUID.
+     */
+    _ClkClsExpectation _mClkClsExpectation = _ClkClsExpectation::ANY;
+    bt2s::optional<bt2c::Uuid> _mExpectedClkClsUuid;
+};
+
+} /* namespace bt2mux */
+
+#endif /* BABELTRACE_PLUGINS_UTILS_MUXER_MSG_ITER_HPP */
This page took 0.033651 seconds and 4 git commands to generate.