From 9fa2b56bfa9d830a87ee6e67cbba0e772e449b16 Mon Sep 17 00:00:00 2001 From: Lamar Moore <lamar.moore@stfc.ac.uk> Date: Wed, 14 Nov 2018 12:25:32 +0000 Subject: [PATCH] IKafkaStreamDecoder and unit tests --- Framework/LiveData/CMakeLists.txt | 3 + .../Kafka/IKafkaStreamDecoder.h | 294 ++++ .../Kafka/KafkaEventStreamDecoder.h | 146 +- .../MantidLiveData/Kafka/KafkaHistoListener.h | 3 + .../Kafka/KafkaHistoStreamDecoder.h | 70 +- .../src/Kafka/IKafkaStreamDecoder.cpp | 503 ++++++ .../src/Kafka/KafkaEventStreamDecoder.cpp | 578 +------ .../LiveData/src/Kafka/KafkaHistoListener.cpp | 31 +- .../src/Kafka/KafkaHistoStreamDecoder.cpp | 242 +-- .../private/Schema/f142_logdata_generated.h | 1401 +++++++++-------- .../Schema/hs00_event_histogram_generated.h | 943 +++++------ .../test/KafkaHistoStreamDecoderTest.h | 189 +++ Framework/LiveData/test/KafkaTesting.h | 98 +- 13 files changed, 2499 insertions(+), 2002 deletions(-) create mode 100644 Framework/LiveData/inc/MantidLiveData/Kafka/IKafkaStreamDecoder.h create mode 100644 Framework/LiveData/src/Kafka/IKafkaStreamDecoder.cpp create mode 100644 Framework/LiveData/test/KafkaHistoStreamDecoderTest.h diff --git a/Framework/LiveData/CMakeLists.txt b/Framework/LiveData/CMakeLists.txt index 2629c652ab1..27d59394c54 100644 --- a/Framework/LiveData/CMakeLists.txt +++ b/Framework/LiveData/CMakeLists.txt @@ -56,6 +56,7 @@ find_package ( LibRDKafka 0.11 ) if ( LIBRDKAFKA_FOUND ) set ( SRC_FILES ${SRC_FILES} + src/Kafka/IKafkaStreamDecoder.cpp src/Kafka/KafkaEventListener.cpp src/Kafka/KafkaEventStreamDecoder.cpp src/Kafka/KafkaHistoListener.cpp @@ -69,6 +70,7 @@ if ( LIBRDKAFKA_FOUND ) inc/MantidLiveData/Kafka/KafkaEventStreamDecoder.h inc/MantidLiveData/Kafka/IKafkaStreamSubscriber.h inc/MantidLiveData/Kafka/IKafkaBroker.h + inc/MantidLiveData/Kafka/IKafkaStreamDecoder.h inc/MantidLiveData/Kafka/KafkaBroker.h inc/MantidLiveData/Kafka/KafkaHistoListener.h inc/MantidLiveData/Kafka/KafkaHistoStreamDecoder.h @@ -87,6 +89,7 @@ if ( LIBRDKAFKA_FOUND ) set ( TEST_FILES ${TEST_FILES} KafkaEventStreamDecoderTest.h + KafkaHistoStreamDecoderTest.h KafkaTopicSubscriberTest.h ) endif() diff --git a/Framework/LiveData/inc/MantidLiveData/Kafka/IKafkaStreamDecoder.h b/Framework/LiveData/inc/MantidLiveData/Kafka/IKafkaStreamDecoder.h new file mode 100644 index 00000000000..a255a0c524d --- /dev/null +++ b/Framework/LiveData/inc/MantidLiveData/Kafka/IKafkaStreamDecoder.h @@ -0,0 +1,294 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2016 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#ifndef MANTID_LIVEDATA_IKAFKASTREAMDECODER_H_ +#define MANTID_LIVEDATA_IKAFKASTREAMDECODER_H_ + +#include "MantidAPI/SpectraDetectorTypes.h" +#include "MantidDataObjects/EventWorkspace.h" +#include "MantidLiveData/Kafka/IKafkaBroker.h" +#include "MantidLiveData/Kafka/IKafkaStreamSubscriber.h" + +#include <atomic> +#include <condition_variable> +#include <mutex> +#include <thread> +#include <unordered_map> + +namespace Mantid { +namespace LiveData { + +/** +Kafka stream decoder interface. Handles (implements) all thread synchronization +functionality for accessing the data stream and processing data. +*/ +class DLLExport IKafkaStreamDecoder { +public: + using CallbackFn = std::function<void()>; + +public: + IKafkaStreamDecoder(std::shared_ptr<IKafkaBroker> broker, + const std::string &streamTopic, + const std::string &runInfoTopic, + const std::string &spDetTopic, + const std::string &sampleEnvTopic); + virtual ~IKafkaStreamDecoder(); + IKafkaStreamDecoder(const IKafkaStreamDecoder &) = delete; + IKafkaStreamDecoder &operator=(const IKafkaStreamDecoder &) = delete; + +public: + ///@name Start/stop + ///@{ + void startCapture(bool startNow = true); + void stopCapture() noexcept; + ///@} + + ///@name Querying + ///@{ + bool isCapturing() const noexcept { return m_capturing; } + virtual bool hasData() const noexcept = 0; + int runNumber() const noexcept { return m_runNumber; } + virtual bool hasReachedEndOfRun() noexcept = 0; + bool dataReset(); + ///@} + + ///@name Callbacks + ///@{ + virtual void registerIterationEndCb(CallbackFn cb) { + m_cbIterationEnd = std::move(cb); + } + virtual void registerErrorCb(CallbackFn cb) { m_cbError = std::move(cb); } + ///@} + + ///@name Modifying + ///@{ + API::Workspace_sptr extractData(); + ///@} + +protected: + struct RunStartStruct { + std::string instrumentName; + int runNumber; + uint64_t startTime; + size_t nPeriods; + int64_t runStartMsgOffset; + }; + + /// Main loop of listening for data messages and populating the cache + /// workspaces + void captureImpl() noexcept; + virtual void captureImplExcept() = 0; + + /// Create the cache workspaces, LoadLiveData extracts data from these + virtual void initLocalCaches(const std::string &rawMsgBuffer, + const RunStartStruct &runStartData) = 0; + + /// Get an expected message from the run information topic + int64_t getRunInfoMessage(std::string &rawMsgBuffer); + + /// Get an expected RunStart message + RunStartStruct getRunStartMessage(std::string &rawMsgBuffer); + + /// Populate cache workspaces with data from messages + virtual void sampleDataFromMessage(const std::string &buffer) = 0; + + /// For LoadLiveData to extract the cached data + virtual API::Workspace_sptr extractDataImpl() = 0; + + /// Broker to use to subscribe to topics + std::shared_ptr<IKafkaBroker> m_broker; + /// Topic names + const std::string m_streamTopic; + const std::string m_runInfoTopic; + const std::string m_spDetTopic; + const std::string m_sampleEnvTopic; + /// Flag indicating if user interruption has been requested + std::atomic<bool> m_interrupt; + /// Subscriber for the data stream + std::unique_ptr<IKafkaStreamSubscriber> m_dataStream; + /// Mapping of spectrum number to workspace index. + spec2index_map m_specToIdx; + /// Start time of the run + Types::Core::DateAndTime m_runStart; + /// Subscriber for the run info stream + std::unique_ptr<IKafkaStreamSubscriber> m_runStream; + /// Subscriber for the run info stream + std::unique_ptr<IKafkaStreamSubscriber> m_spDetStream; + /// Run number + int m_runNumber; + + /// Associated thread running the capture process + std::thread m_thread; + /// Mutex protecting event buffers + mutable std::mutex m_mutex; + /// Mutex protecting the wait flag + mutable std::mutex m_waitMutex; + /// Mutex protecting the runStatusSeen flag + mutable std::mutex m_runStatusMutex; + /// Flag indicating that the decoder is capturing + std::atomic<bool> m_capturing; + /// Exception object indicating there was an error + boost::shared_ptr<std::runtime_error> m_exception; + + /// For notifying other threads of changes to conditions (the following bools) + std::condition_variable m_cv; + std::condition_variable m_cvRunStatus; + /// Indicate that decoder has reached the last message in a run + std::atomic<bool> m_endRun; + /// Indicate that LoadLiveData is waiting for access to the buffer workspace + std::atomic<bool> m_extractWaiting; + /// Indicate that MonitorLiveData has seen the runStatus since it was set to + /// EndRun + bool m_runStatusSeen; + std::atomic<bool> m_extractedEndRunData; + /// Indicate if the next data to be extracted should replace LoadLiveData's + /// output workspace + std::atomic<bool> m_dataReset; + + void waitForDataExtraction(); + void waitForRunEndObservation(); + + std::map<int32_t, std::set<int32_t>> + buildSpectrumToDetectorMap(const size_t nspectra, const int32_t *spec, + const int32_t *udet, uint32_t length); + + template <typename T> + boost::shared_ptr<T> + createBufferWorkspace(const std::string &workspaceClassName, size_t nspectra, + const int32_t *spec, const int32_t *udet, + uint32_t length); + template <typename T> + boost::shared_ptr<T> + createBufferWorkspace(const std::string &workspaceClassName, + const boost::shared_ptr<T> &parent); + + template <typename T> + void loadInstrument(const std::string &name, boost::shared_ptr<T> workspace); + + void checkRunMessage( + const std::string &buffer, bool &checkOffsets, + std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, + std::unordered_map<std::string, std::vector<bool>> &reachedEnd); + + void checkRunEnd( + const std::string &topicName, bool &checkOffsets, const int64_t offset, + const int32_t partition, + std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, + std::unordered_map<std::string, std::vector<bool>> &reachedEnd); + + /// Methods for checking if the end of a run was reached + std::unordered_map<std::string, std::vector<int64_t>> getStopOffsets( + std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, + std::unordered_map<std::string, std::vector<bool>> &reachedEnd, + uint64_t stopTime) const; + void checkIfAllStopOffsetsReached( + const std::unordered_map<std::string, std::vector<bool>> &reachedEnd, + bool &checkOffsets); + + /// Callbacks for unit tests + CallbackFn m_cbIterationEnd; + CallbackFn m_cbError; + + /// Waits until a run start message with higher run number is received + bool waitForNewRunStartMessage(RunStartStruct &runStartStructOutput); + /// Subscribe to data stream at the time specified in a run start message + void joinStreamAtTime(const RunStartStruct &runStartData); + /// Convert a duration in nanoseconds to milliseconds + int64_t nanosecondsToMilliseconds(uint64_t timeNanoseconds) const; + /// Get a det-spec map message using the time specified in a run start message + std::string getDetSpecMapForRun(const RunStartStruct &runStartStruct); +}; + +/** + * Create a buffer workspace of the correct size based on the values given. + * @param workspaceClassName the name of the workspace class to be created e.g + * Workspace2D or EventWorkspace + * @param nspectra The number of unique spectrum numbers + * @param spec An array of length ndet specifying the spectrum number of each + * detector + * @param udet An array of length ndet specifying the detector ID of each + * detector + * @param length The length of the spec/udet arrays + * @return A new workspace of the appropriate size + */ +template <typename T> +boost::shared_ptr<T> IKafkaStreamDecoder::createBufferWorkspace( + const std::string &workspaceClassName, size_t nspectra, const int32_t *spec, + const int32_t *udet, uint32_t length) { + // Get spectra to detector mapping + auto spdetMap = buildSpectrumToDetectorMap(nspectra, spec, udet, length); + + // Create histo workspace + auto buffer = + boost::static_pointer_cast<T>(API::WorkspaceFactory::Instance().create( + workspaceClassName, nspectra, 2, 1)); + + // Set the units + buffer->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF"); + buffer->setYUnit("Counts"); + // Setup spectra-detector mapping. + size_t wsIdx(0); + for (const auto &spIter : spdetMap) { + auto &spectrum = buffer->getSpectrum(wsIdx); + spectrum.setSpectrumNo(spIter.first); + spectrum.addDetectorIDs(spIter.second); + ++wsIdx; + } + return buffer; +} + +/** + * Create new buffer workspace from an existing copy + * @param workspaceClassName the name of the workspace class to be created e.g + * Workspace2D or EventWorkspace + * @param parent A reference to an existing workspace + */ +template <typename T> +boost::shared_ptr<T> IKafkaStreamDecoder::createBufferWorkspace( + const std::string &workspaceClassName, const boost::shared_ptr<T> &parent) { + auto buffer = + boost::static_pointer_cast<T>(API::WorkspaceFactory::Instance().create( + workspaceClassName, parent->getNumberHistograms(), 2, 1)); + // Copy meta data + API::WorkspaceFactory::Instance().initializeFromParent(*parent, *buffer, + false); + // Clear out the old logs, except for the most recent entry + buffer->mutableRun().clearOutdatedTimeSeriesLogValues(); + return buffer; +} + +/** + * Run LoadInstrument for the given instrument name. If it cannot succeed it + * does nothing to the internal workspace + * @param name Name of an instrument to load + * @param workspace A pointer to the workspace receiving the instrument + */ +template <typename T> +void IKafkaStreamDecoder::loadInstrument(const std::string &name, + boost::shared_ptr<T> workspace) { + if (name.empty()) { + g_log.warning("Empty instrument name found"); + return; + } + try { + auto alg = + API::AlgorithmManager::Instance().createUnmanaged("LoadInstrument"); + // Do not put the workspace in the ADS + alg->setChild(true); + alg->initialize(); + alg->setPropertyValue("InstrumentName", name); + alg->setProperty("Workspace", workspace); + alg->setProperty("RewriteSpectraMap", Kernel::OptionalBool(false)); + alg->execute(); + } catch (std::exception &exc) { + g_log.warning() << "Error loading instrument '" << name + << "': " << exc.what() << "\n"; + } +} + +} // namespace LiveData +} // namespace Mantid +#endif // MANTID_LIVEDATA_IKAFKASTREAMDECODER_H_ diff --git a/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaEventStreamDecoder.h b/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaEventStreamDecoder.h index 472d18bc409..8236e6fe8b8 100644 --- a/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaEventStreamDecoder.h +++ b/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaEventStreamDecoder.h @@ -10,13 +10,9 @@ #include "MantidAPI/SpectraDetectorTypes.h" #include "MantidDataObjects/EventWorkspace.h" #include "MantidLiveData/Kafka/IKafkaBroker.h" +#include "MantidLiveData/Kafka/IKafkaStreamDecoder.h" #include "MantidLiveData/Kafka/IKafkaStreamSubscriber.h" -#include <atomic> -#include <condition_variable> -#include <mutex> -#include <thread> - namespace Mantid { namespace LiveData { @@ -27,10 +23,7 @@ namespace LiveData { A call to capture() starts the process of capturing the stream on a separate thread. */ -class DLLExport KafkaEventStreamDecoder { -public: - using CallbackFn = std::function<void()>; - +class DLLExport KafkaEventStreamDecoder : public IKafkaStreamDecoder { public: KafkaEventStreamDecoder(std::shared_ptr<IKafkaBroker> broker, const std::string &eventTopic, @@ -42,150 +35,29 @@ public: KafkaEventStreamDecoder &operator=(const KafkaEventStreamDecoder &) = delete; public: - ///@name Start/stop - ///@{ - void startCapture(bool startNow = true); - void stopCapture() noexcept; - ///@} - ///@name Querying ///@{ - bool isCapturing() const noexcept { return m_capturing; } - bool hasData() const noexcept; - int runNumber() const noexcept { return m_runNumber; } - bool hasReachedEndOfRun() noexcept; - bool dataReset(); - ///@} - - ///@name Callbacks - ///@{ - void registerIterationEndCb(CallbackFn cb) { - m_cbIterationEnd = std::move(cb); - } - void registerErrorCb(CallbackFn cb) { m_cbError = std::move(cb); } - ///@} - - ///@name Modifying - ///@{ - API::Workspace_sptr extractData(); + bool hasData() const noexcept override; + bool hasReachedEndOfRun() noexcept override; ///@} private: - struct RunStartStruct { - std::string instrumentName; - int runNumber; - uint64_t startTime; - size_t nPeriods; - int64_t runStartMsgOffset; - }; - /// Main loop of listening for data messages and populating the cache - /// workspaces - void captureImpl() noexcept; - void captureImplExcept(); + void captureImplExcept() override; /// Create the cache workspaces, LoadLiveData extracts data from these void initLocalCaches(const std::string &rawMsgBuffer, - const RunStartStruct &runStartData); - DataObjects::EventWorkspace_sptr createBufferWorkspace(size_t nspectra, - const int32_t *spec, - const int32_t *udet, - uint32_t length); - DataObjects::EventWorkspace_sptr - createBufferWorkspace(const DataObjects::EventWorkspace_sptr &parent); - - /// Load a named instrument into a workspace - void loadInstrument(const std::string &name, - DataObjects::EventWorkspace_sptr workspace); - - /// Get an expected message from the run information topic - int64_t getRunInfoMessage(std::string &rawMsgBuffer); - - /// Get an expected RunStart message - RunStartStruct getRunStartMessage(std::string &rawMsgBuffer); + const RunStartStruct &runStartData) override; /// Populate cache workspaces with data from messages void eventDataFromMessage(const std::string &buffer); - void sampleDataFromMessage(const std::string &buffer); + + void sampleDataFromMessage(const std::string &buffer) override; /// For LoadLiveData to extract the cached data - API::Workspace_sptr extractDataImpl(); + API::Workspace_sptr extractDataImpl() override; - /// Broker to use to subscribe to topics - std::shared_ptr<IKafkaBroker> m_broker; - /// Topic names - const std::string m_eventTopic; - const std::string m_runInfoTopic; - const std::string m_spDetTopic; - const std::string m_sampleEnvTopic; - /// Flag indicating if user interruption has been requested - std::atomic<bool> m_interrupt; - /// Subscriber for the event stream - std::unique_ptr<IKafkaStreamSubscriber> m_eventStream; /// Local event workspace buffers std::vector<DataObjects::EventWorkspace_sptr> m_localEvents; - /// Mapping of spectrum number to workspace index. - spec2index_map m_specToIdx; - /// Start time of the run - Types::Core::DateAndTime m_runStart; - /// Subscriber for the run info stream - std::unique_ptr<IKafkaStreamSubscriber> m_runStream; - /// Subscriber for the run info stream - std::unique_ptr<IKafkaStreamSubscriber> m_spDetStream; - /// Run number - int m_runNumber; - - /// Associated thread running the capture process - std::thread m_thread; - /// Mutex protecting event buffers - mutable std::mutex m_mutex; - /// Mutex protecting the wait flag - mutable std::mutex m_waitMutex; - /// Mutex protecting the runStatusSeen flag - mutable std::mutex m_runStatusMutex; - /// Flag indicating that the decoder is capturing - std::atomic<bool> m_capturing; - /// Exception object indicating there was an error - boost::shared_ptr<std::runtime_error> m_exception; - - /// For notifying other threads of changes to conditions (the following bools) - std::condition_variable m_cv; - std::condition_variable m_cvRunStatus; - /// Indicate that decoder has reached the last message in a run - std::atomic<bool> m_endRun; - /// Indicate that LoadLiveData is waiting for access to the buffer workspace - std::atomic<bool> m_extractWaiting; - /// Indicate that MonitorLiveData has seen the runStatus since it was set to - /// EndRun - bool m_runStatusSeen; - std::atomic<bool> m_extractedEndRunData; - /// Indicate if the next data to be extracted should replace LoadLiveData's - /// output workspace - std::atomic<bool> m_dataReset; - - void waitForDataExtraction(); - void waitForRunEndObservation(); - - /// Methods for checking if the end of a run was reached - std::unordered_map<std::string, std::vector<int64_t>> getStopOffsets( - std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, - std::unordered_map<std::string, std::vector<bool>> &reachedEnd, - uint64_t stopTime) const; - void checkIfAllStopOffsetsReached( - const std::unordered_map<std::string, std::vector<bool>> &reachedEnd, - bool &checkOffsets); - - /// Callbacks for unit tests - CallbackFn m_cbIterationEnd; - CallbackFn m_cbError; - - /// Waits until a run start message with higher run number is received - bool waitForNewRunStartMessage(RunStartStruct &runStartStructOutput); - /// Subscribe to event stream at the time specified in a run start message - void joinEventStreamAtTime(const RunStartStruct &runStartData); - /// Convert a duration in nanoseconds to milliseconds - int64_t nanosecondsToMilliseconds(uint64_t timeNanoseconds) const; - /// Get a det-spec map message using the time specified in a run start message - std::string getDetSpecMapForRun(const RunStartStruct &runStartStruct); }; } // namespace LiveData diff --git a/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoListener.h b/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoListener.h index 796962d211f..b87aa173543 100644 --- a/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoListener.h +++ b/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoListener.h @@ -39,6 +39,8 @@ public: /// Does this listener buffer events (true) or histogram data (false) bool buffersEvents() const override { return false; } + void setAlgorithm(const Mantid::API::IAlgorithm &callingAlgorithm) override; + //---------------------------------------------------------------------- // Actions //---------------------------------------------------------------------- @@ -56,6 +58,7 @@ public: private: std::unique_ptr<KafkaHistoStreamDecoder> m_decoder = nullptr; + std::string m_instrumentName; }; } // namespace LiveData diff --git a/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoStreamDecoder.h b/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoStreamDecoder.h index c40b313764e..25e5a6133fc 100644 --- a/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoStreamDecoder.h +++ b/Framework/LiveData/inc/MantidLiveData/Kafka/KafkaHistoStreamDecoder.h @@ -8,12 +8,9 @@ #define MANTID_LIVEDATA_ISISKAFKAHISTOSTREAMDECODER_H_ #include "MantidDataObjects/Workspace2D.h" +#include "MantidLiveData/Kafka/IKafkaBroker.h" +#include "MantidLiveData/Kafka/IKafkaStreamDecoder.h" #include "MantidLiveData/Kafka/IKafkaStreamSubscriber.h" -#include "MantidLiveData/Kafka/KafkaBroker.h" - -#include <atomic> -#include <mutex> -#include <thread> namespace Mantid { namespace LiveData { @@ -24,65 +21,34 @@ namespace LiveData { A call to startCapture() starts the process of capturing the stream on a separate thread. */ -class DLLExport KafkaHistoStreamDecoder { +class DLLExport KafkaHistoStreamDecoder : public IKafkaStreamDecoder { public: - KafkaHistoStreamDecoder(const std::string &brokerAddress, + KafkaHistoStreamDecoder(std::shared_ptr<IKafkaBroker> broker, const std::string &histoTopic, - const std::string &instrumentName); + const std::string &runInfoTopic, + const std::string &spDetTopic, + const std::string &sampleEnvTopic); ~KafkaHistoStreamDecoder(); KafkaHistoStreamDecoder(const KafkaHistoStreamDecoder &) = delete; KafkaHistoStreamDecoder &operator=(const KafkaHistoStreamDecoder &) = delete; -public: - ///@name Start/stop - ///@{ - void startCapture(bool startNow = true); - void stopCapture() noexcept; - ///@} + bool hasData() const noexcept override; + bool hasReachedEndOfRun() noexcept override { return !m_capturing; } - ///@name Querying - ///@{ - bool isCapturing() const { return m_capturing; } - bool hasData() const; - int runNumber() const { return 1; } - bool hasReachedEndOfRun() { return !m_capturing; } - ///@} +private: + void captureImplExcept() override; - ///@name Modifying - ///@{ - API::Workspace_sptr extractData(); - ///@} + /// Create the cache workspaces, LoadLiveData extracts data from these + void initLocalCaches(const std::string &rawMsgBuffer, + const RunStartStruct &runStartData) override; -private: - void captureImpl(); - void captureImplExcept(); - API::Workspace_sptr extractDataImpl(); + void sampleDataFromMessage(const std::string &buffer) override; - DataObjects::Workspace2D_sptr createBufferWorkspace(); + API::Workspace_sptr extractDataImpl() override; - /// Broker to use to subscribe to topics - KafkaBroker m_broker; - /// Topic name - const std::string m_histoTopic; - /// Instrument name - const std::string m_instrumentName; - /// Subscriber for the histo stream - std::unique_ptr<IKafkaStreamSubscriber> m_histoStream; - /// Workspace used as template for workspaces created when extracting - DataObjects::Workspace2D_sptr m_workspace; - /// Buffer for latest FlatBuffers message +private: std::string m_buffer; - - /// Associated thread running the capture process - std::thread m_thread; - /// Mutex protecting histo buffers - mutable std::mutex m_buffer_mutex; - /// Flag indicating if user interruption has been requested - std::atomic<bool> m_interrupt; - /// Flag indicating that the decoder is capturing - std::atomic<bool> m_capturing; - /// Exception object indicating there was an error - std::unique_ptr<std::runtime_error> m_exception; + DataObjects::Workspace2D_sptr m_workspace; }; } // namespace LiveData diff --git a/Framework/LiveData/src/Kafka/IKafkaStreamDecoder.cpp b/Framework/LiveData/src/Kafka/IKafkaStreamDecoder.cpp new file mode 100644 index 00000000000..448c20eca1f --- /dev/null +++ b/Framework/LiveData/src/Kafka/IKafkaStreamDecoder.cpp @@ -0,0 +1,503 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#include "MantidLiveData/Kafka/IKafkaStreamDecoder.h" +#include "MantidKernel/Logger.h" +#include "MantidKernel/WarningSuppressions.h" +#include "MantidLiveData/Exception.h" +#include "MantidLiveData/Kafka/KafkaTopicSubscriber.h" + +GNU_DIAG_OFF("conversion") +#include "private/Schema/ba57_run_info_generated.h" +#include "private/Schema/df12_det_spec_map_generated.h" +#include "private/Schema/f142_logdata_generated.h" +GNU_DIAG_ON("conversion") + +using namespace Mantid::Types; +using namespace LogSchema; + +namespace { +/// Logger +Mantid::Kernel::Logger g_log("IKafkaStreamDecoder"); + +// File identifiers from flatbuffers schema +const std::string RUN_MESSAGE_ID = "ba57"; + +const std::chrono::seconds MAX_LATENCY(1); +} // namespace + +namespace Mantid { +namespace LiveData { +// ----------------------------------------------------------------------------- +// Public members +// ----------------------------------------------------------------------------- +/** + * Constructor + * @param broker A reference to a Broker object for creating topic streams + * @param streamTopic The name of the topic streaming the stream data + * @param runInfoTopic The name of the topic streaming the run information + * @param spDetTopic The name of the topic streaming the spectrum-detector + * @param sampleEnvTopic The name of the topic stream sample environment + * information. run mapping + */ +IKafkaStreamDecoder::IKafkaStreamDecoder(std::shared_ptr<IKafkaBroker> broker, + const std::string &streamTopic, + const std::string &runInfoTopic, + const std::string &spDetTopic, + const std::string &sampleEnvTopic) + : m_broker(broker), m_streamTopic(streamTopic), + m_runInfoTopic(runInfoTopic), m_spDetTopic(spDetTopic), + m_sampleEnvTopic(sampleEnvTopic), m_interrupt(false), m_specToIdx(), + m_runStart(), m_runNumber(-1), m_thread(), m_capturing(false), + m_exception(), m_extractWaiting(false), m_cbIterationEnd([] {}), + m_cbError([] {}) {} + +/** + * Destructor. + * Stops capturing from the stream + */ +IKafkaStreamDecoder::~IKafkaStreamDecoder() { stopCapture(); } + +/** + * Start capturing from the stream on a separate thread. This is a non-blocking + * call and will return after the thread has started + */ +void IKafkaStreamDecoder::startCapture(bool startNow) { + + // If we are not starting now, then we want to start at the start of the run + if (!startNow) { + // Get last two messages in run topic to ensure we get a runStart message + m_runStream = + m_broker->subscribe({m_runInfoTopic}, SubscribeAtOption::LASTTWO); + std::string rawMsgBuffer; + auto runStartData = getRunStartMessage(rawMsgBuffer); + joinStreamAtTime(runStartData); + } else { + m_dataStream = + m_broker->subscribe({m_streamTopic, m_runInfoTopic, m_sampleEnvTopic}, + SubscribeAtOption::LATEST); + } + + // Get last two messages in run topic to ensure we get a runStart message + m_runStream = + m_broker->subscribe({m_runInfoTopic}, SubscribeAtOption::LASTTWO); + m_spDetStream = + m_broker->subscribe({m_spDetTopic}, SubscribeAtOption::LASTONE); + + m_thread = std::thread([this]() { this->captureImpl(); }); + m_thread.detach(); +} + +/** Indicate if the next data to be extracted should replace LoadLiveData's + * output workspace, + * for example the first data of a new run + */ +bool IKafkaStreamDecoder::dataReset() { + bool result = (m_dataReset == true); // copy from atomic bool + m_dataReset = false; // reset to false + return result; +} + +void IKafkaStreamDecoder::joinStreamAtTime( + const IKafkaStreamDecoder::RunStartStruct &runStartData) { + auto runStartTime = runStartData.startTime; + int64_t startTimeMilliseconds = nanosecondsToMilliseconds(runStartTime); + m_dataStream = + m_broker->subscribe({m_streamTopic, m_runInfoTopic, m_sampleEnvTopic}, + startTimeMilliseconds, SubscribeAtOption::TIME); + // make sure we listen to the run start topic starting from the run start + // message we already got the start time from + m_dataStream->seek(m_runInfoTopic, 0, runStartData.runStartMsgOffset); +} + +int64_t +IKafkaStreamDecoder::nanosecondsToMilliseconds(uint64_t timeNanoseconds) const { + return static_cast<int64_t>(timeNanoseconds / 1000000); +} + +/** + * Stop capturing from the stream. This is a blocking call until the capturing + * function has completed + */ +void IKafkaStreamDecoder::stopCapture() noexcept { + // This will interrupt the "event" loop + m_interrupt = true; + // Wait until the function has completed. The background thread + // will exit automatically + while (m_capturing) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + }; +} + +/** + * Check if a message has indicated that end of run has been reached + * @return True if end of run has been reached + */ +bool IKafkaStreamDecoder::hasReachedEndOfRun() noexcept { + // Notify the decoder that MonitorLiveData knows it has reached end of run + // and after giving it opportunity to interrupt, decoder can continue with + // messages of the next run + if (!m_extractedEndRunData || m_extractWaiting) + return false; + if (m_endRun) { + std::lock_guard<std::mutex> runStatusLock(m_runStatusMutex); + m_runStatusSeen = true; + m_cvRunStatus.notify_one(); + return true; + } + return false; +} + +/** + * Check for an exception thrown by the background thread and rethrow + * it if necessary. If no error occurred swap the current internal buffer + * for a fresh one and return the old buffer. + * @return A pointer to the data collected since the last call to this + * method + */ +API::Workspace_sptr IKafkaStreamDecoder::extractData() { + if (m_exception) { + throw std::runtime_error(*m_exception); + } + + m_extractWaiting = true; + m_cv.notify_one(); + + auto workspace_ptr = extractDataImpl(); + + m_extractWaiting = false; + m_cv.notify_one(); + + return workspace_ptr; +} + +/** + * Start decoding data from the streams into the internal buffers. + * Implementation designed to be entry point for new thread of execution. + * It catches all thrown exceptions. + */ +void IKafkaStreamDecoder::captureImpl() noexcept { + m_capturing = true; + try { + captureImplExcept(); + } catch (std::exception &exc) { + m_cbError(); + m_exception = boost::make_shared<std::runtime_error>(exc.what()); + } catch (...) { + m_cbError(); + m_exception = boost::make_shared<std::runtime_error>( + "IKafkaStreamDecoder: Unknown exception type caught."); + } + m_capturing = false; +} + +/** + * Check if we've reached the stop offset on every partition of every topic + * + * @param reachedEnd : Bool for each topic and partition to mark when stop + * offset reached + */ +void IKafkaStreamDecoder::checkIfAllStopOffsetsReached( + const std::unordered_map<std::string, std::vector<bool>> &reachedEnd, + bool &checkOffsets) { + + if (std::all_of(reachedEnd.cbegin(), reachedEnd.cend(), + [](std::pair<std::string, std::vector<bool>> kv) { + return std::all_of( + kv.second.cbegin(), kv.second.cend(), + [](bool partitionEnd) { return partitionEnd; }); + }) || + reachedEnd.empty()) { + m_endRun = true; + // If we've reached the end of a run then set m_extractWaiting to true + // so that we wait until the buffer is emptied before continuing. + // Otherwise we can end up with data from two different runs in the + // same buffer workspace which is problematic if the user wanted the + // "Stop" or "Rename" run transition option. + m_extractedEndRunData = false; + checkOffsets = false; + g_log.notice("Reached end of run in data streams."); + } +} + +std::unordered_map<std::string, std::vector<int64_t>> +IKafkaStreamDecoder::getStopOffsets( + std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, + std::unordered_map<std::string, std::vector<bool>> &reachedEnd, + uint64_t stopTime) const { + reachedEnd.clear(); + stopOffsets.clear(); + // Wait for max latency so that we don't miss any late messages + std::this_thread::sleep_for(MAX_LATENCY); + stopOffsets = m_dataStream->getOffsetsForTimestamp( + static_cast<int64_t>(stopTime / 1000000)); + // /1000000 to convert nanosecond precision from message to millisecond + // precision which Kafka offset query supports + + auto currentOffsets = m_dataStream->getCurrentOffsets(); + + // Set reachedEnd to false for each topic and partition + for (auto &topicOffsets : stopOffsets) { + auto topicName = topicOffsets.first; + // Ignore the runInfo topic + if (topicName.substr(topicName.length() - + KafkaTopicSubscriber::RUN_TOPIC_SUFFIX.length()) != + KafkaTopicSubscriber::RUN_TOPIC_SUFFIX) { + g_log.debug() << "TOPIC: " << topicName + << " PARTITIONS: " << topicOffsets.second.size() + << std::endl; + reachedEnd.insert( + {topicName, std::vector<bool>(topicOffsets.second.size(), false)}); + + auto &partitionOffsets = topicOffsets.second; + for (uint32_t partitionNumber = 0; + partitionNumber < partitionOffsets.size(); partitionNumber++) { + auto offset = partitionOffsets[partitionNumber]; + // If the stop offset is negative then there are no messages for us + // to collect on this topic, so mark reachedEnd as true already + reachedEnd[topicName][partitionNumber] = offset < 0; + // If the stop offset has already been reached then mark reachedEnd as + // true + if (currentOffsets[topicName][partitionNumber] >= offset) + reachedEnd[topicName][partitionNumber] = true; + } + } + } + return stopOffsets; +} + +/** + * If extractData method is waiting for access to the buffer workspace + * then we wait for it to finish + */ +void IKafkaStreamDecoder::waitForDataExtraction() { + { + std::unique_lock<std::mutex> readyLock(m_waitMutex); + m_cv.wait(readyLock, [&] { return !m_extractWaiting; }); + } +} + +void IKafkaStreamDecoder::waitForRunEndObservation() { + m_extractWaiting = true; + // Mark extractedEndRunData true before waiting on the extraction to ensure + // an immediate request for run status after extracting the data will return + // the correct value - avoids race condition in MonitorLiveData and tests + m_extractedEndRunData = true; + waitForDataExtraction(); + + // Wait until MonitorLiveData has seen that end of run was + // reached before setting m_endRun back to false and continuing + std::unique_lock<std::mutex> runStatusLock(m_runStatusMutex); + m_cvRunStatus.wait(runStatusLock, [&] { return m_runStatusSeen; }); + m_endRun = false; + m_runStatusSeen = false; + runStatusLock.unlock(); + + // Set to zero until we have the new run number, MonitorLiveData will + // queries before each time it extracts data until it gets non-zero + m_runNumber = 0; + + // Get new run message now so that new run number is available for + // MonitorLiveData as early as possible + RunStartStruct runStartStruct; + if (waitForNewRunStartMessage(runStartStruct)) + return; + + // Give time for MonitorLiveData to act on runStatus information + // and trigger m_interrupt for next loop iteration if user requested + // LiveData algorithm to stop at the end of the run + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (m_interrupt) + return; + + // Rejoin event stream at start of new run + joinStreamAtTime(runStartStruct); + std::string detSpecMapMsgBuffer = getDetSpecMapForRun(runStartStruct); + initLocalCaches(detSpecMapMsgBuffer, runStartStruct); +} + +/** + * Try to find a detector-spectrum map message published after the + * current run start time + * + * @param runStartStruct details of the current run + * @return received detector-spectrum map message buffer + */ +std::string IKafkaStreamDecoder::getDetSpecMapForRun( + const IKafkaStreamDecoder::RunStartStruct &runStartStruct) { + std::string rawMsgBuffer; + int64_t offset; + int32_t partition; + std::string topicName; + m_spDetStream = m_broker->subscribe( + {m_spDetTopic}, nanosecondsToMilliseconds(runStartStruct.startTime), + SubscribeAtOption::TIME); + m_spDetStream->consumeMessage(&rawMsgBuffer, offset, partition, topicName); + if (rawMsgBuffer.empty()) { + std::runtime_error( + "No detector-spectrum map message found for run number " + + std::to_string(runStartStruct.runNumber)); + } + return rawMsgBuffer; +} + +/** + * Wait for a run start message until we get one with a higher run number + * than the current run or the algorithm is interrupted + * + * @param runStartStructOutput details of the new run + * @return true if interrupted, false if got a new run start message + */ +bool IKafkaStreamDecoder::waitForNewRunStartMessage( + RunStartStruct &runStartStructOutput) { + while (!m_interrupt) { + std::string runMsgBuffer; + + int64_t offset; + int32_t partition; + std::string topicName; + m_runStream->consumeMessage(&runMsgBuffer, offset, partition, topicName); + if (runMsgBuffer.empty()) { + continue; // no message available, try again + } else { + auto runMsg = + GetRunInfo(reinterpret_cast<const uint8_t *>(runMsgBuffer.c_str())); + if (runMsg->info_type_type() == InfoTypes_RunStart) { + // We got a run start message, deserialise it + auto runStartData = static_cast<const RunStart *>(runMsg->info_type()); + IKafkaStreamDecoder::RunStartStruct runStartStruct = { + runStartData->instrument_name()->str(), runStartData->run_number(), + runStartData->start_time(), + static_cast<size_t>(runStartData->n_periods()), offset}; + if (runStartStruct.runNumber > m_runNumber) { + runStartStructOutput = runStartStruct; + m_runNumber = runStartStruct.runNumber; + return false; // not interrupted + } + } else { + continue; // received message wasn't a RunStart message, try again + } + } + } + return true; // interrupted +} + +IKafkaStreamDecoder::RunStartStruct +IKafkaStreamDecoder::getRunStartMessage(std::string &rawMsgBuffer) { + auto offset = getRunInfoMessage(rawMsgBuffer); + auto runMsg = + GetRunInfo(reinterpret_cast<const uint8_t *>(rawMsgBuffer.c_str())); + if (runMsg->info_type_type() != InfoTypes_RunStart) { + // We want a runStart message, try the next one + offset = getRunInfoMessage(rawMsgBuffer); + runMsg = + GetRunInfo(reinterpret_cast<const uint8_t *>(rawMsgBuffer.c_str())); + if (runMsg->info_type_type() != InfoTypes_RunStart) { + throw std::runtime_error("IKafkaStreamDecoder::initLocalCaches() - " + "Could not find a run start message" + "in the run info topic. Unable to continue"); + } + } + auto runStartData = static_cast<const RunStart *>(runMsg->info_type()); + IKafkaStreamDecoder::RunStartStruct runStart = { + runStartData->instrument_name()->str(), runStartData->run_number(), + runStartData->start_time(), + static_cast<size_t>(runStartData->n_periods()), offset}; + return runStart; +} + +/** + * Try to get a runInfo message from Kafka, throw error if it fails + * @param rawMsgBuffer : string to use as message buffer + */ +int64_t IKafkaStreamDecoder::getRunInfoMessage(std::string &rawMsgBuffer) { + int64_t offset; + int32_t partition; + std::string topicName; + m_runStream->consumeMessage(&rawMsgBuffer, offset, partition, topicName); + if (rawMsgBuffer.empty()) { + throw std::runtime_error("IKafkaStreamDecoder::getRunInfoMessage() - " + "Empty message received from run info " + "topic. Unable to continue"); + } + if (!flatbuffers::BufferHasIdentifier( + reinterpret_cast<const uint8_t *>(rawMsgBuffer.c_str()), + RUN_MESSAGE_ID.c_str())) { + throw std::runtime_error("IKafkaStreamDecoder::getRunInfoMessage() - " + "Received unexpected message type from run info " + "topic. Unable to continue"); + } + return offset; +} + +std::map<int32_t, std::set<int32_t>> +IKafkaStreamDecoder::buildSpectrumToDetectorMap(const size_t nspectra, + const int32_t *spec, + const int32_t *udet, + uint32_t length) { + // Order is important here + std::map<int32_t, std::set<int32_t>> spdetMap; + for (uint32_t i = 0; i < length; ++i) { + auto specNo = spec[i]; + auto detId = udet[i]; + auto search = spdetMap.find(specNo); + if (search != spdetMap.end()) { + search->second.insert(detId); + } else { + spdetMap.insert({specNo, {detId}}); + } + } + + assert(nspectra == spdetMap.size()); + + return spdetMap; +} + +void IKafkaStreamDecoder::checkRunMessage( + const std::string &buffer, bool &checkOffsets, + std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, + std::unordered_map<std::string, std::vector<bool>> &reachedEnd) { + if (flatbuffers::BufferHasIdentifier( + reinterpret_cast<const uint8_t *>(buffer.c_str()), + RUN_MESSAGE_ID.c_str())) { + auto runMsg = GetRunInfo(reinterpret_cast<const uint8_t *>(buffer.c_str())); + if (!checkOffsets && runMsg->info_type_type() == InfoTypes_RunStop) { + auto runStopMsg = static_cast<const RunStop *>(runMsg->info_type()); + auto stopTime = runStopMsg->stop_time(); + g_log.debug() << "Received an end-of-run message with stop time = " + << stopTime << std::endl; + stopOffsets = getStopOffsets(stopOffsets, reachedEnd, stopTime); + checkOffsets = true; + checkIfAllStopOffsetsReached(reachedEnd, checkOffsets); + } + } +} + +void IKafkaStreamDecoder::checkRunEnd( + const std::string &topicName, bool &checkOffsets, const int64_t offset, + const int32_t partition, + std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, + std::unordered_map<std::string, std::vector<bool>> &reachedEnd) { + if (reachedEnd.count(topicName) && + offset >= stopOffsets[topicName][static_cast<size_t>(partition)]) { + + reachedEnd[topicName][static_cast<size_t>(partition)] = true; + + if (offset == stopOffsets[topicName][static_cast<size_t>(partition)]) { + g_log.debug() << "Reached end-of-run in " << topicName << " topic." + << std::endl; + g_log.debug() << "topic: " << topicName << " offset: " << offset + << " stopOffset: " + << stopOffsets[topicName][static_cast<size_t>(partition)] + << std::endl; + } + checkIfAllStopOffsetsReached(reachedEnd, checkOffsets); + } +} + +} // namespace LiveData + +} // namespace Mantid diff --git a/Framework/LiveData/src/Kafka/KafkaEventStreamDecoder.cpp b/Framework/LiveData/src/Kafka/KafkaEventStreamDecoder.cpp index bdf5a0145ef..9bc1a458be7 100644 --- a/Framework/LiveData/src/Kafka/KafkaEventStreamDecoder.cpp +++ b/Framework/LiveData/src/Kafka/KafkaEventStreamDecoder.cpp @@ -29,6 +29,7 @@ GNU_DIAG_OFF("conversion") GNU_DIAG_ON("conversion") using namespace Mantid::Types; +using namespace LogSchema; namespace { /// Logger @@ -43,8 +44,6 @@ const std::string RUN_MESSAGE_ID = "ba57"; const std::string EVENT_MESSAGE_ID = "ev42"; const std::string SAMPLE_MESSAGE_ID = "f142"; -const std::chrono::seconds MAX_LATENCY(1); - /** * Append sample log data to existing log or create a new log if one with * specified name does not already exist @@ -88,88 +87,14 @@ KafkaEventStreamDecoder::KafkaEventStreamDecoder( std::shared_ptr<IKafkaBroker> broker, const std::string &eventTopic, const std::string &runInfoTopic, const std::string &spDetTopic, const std::string &sampleEnvTopic) - : m_broker(broker), m_eventTopic(eventTopic), m_runInfoTopic(runInfoTopic), - m_spDetTopic(spDetTopic), m_sampleEnvTopic(sampleEnvTopic), - m_interrupt(false), m_localEvents(), m_specToIdx(), m_runStart(), - m_runNumber(-1), m_thread(), m_capturing(false), m_exception(), - m_extractWaiting(false), m_cbIterationEnd([] {}), m_cbError([] {}) {} + : IKafkaStreamDecoder(broker, eventTopic, runInfoTopic, spDetTopic, + sampleEnvTopic) {} /** * Destructor. * Stops capturing from the stream */ -KafkaEventStreamDecoder::~KafkaEventStreamDecoder() { stopCapture(); } - -/** - * Start capturing from the stream on a separate thread. This is a non-blocking - * call and will return after the thread has started - */ -void KafkaEventStreamDecoder::startCapture(bool startNow) { - - // If we are not starting now, then we want to start at the start of the run - if (!startNow) { - // Get last two messages in run topic to ensure we get a runStart message - m_runStream = - m_broker->subscribe({m_runInfoTopic}, SubscribeAtOption::LASTTWO); - std::string rawMsgBuffer; - auto runStartData = getRunStartMessage(rawMsgBuffer); - joinEventStreamAtTime(runStartData); - } else { - m_eventStream = - m_broker->subscribe({m_eventTopic, m_runInfoTopic, m_sampleEnvTopic}, - SubscribeAtOption::LATEST); - } - - // Get last two messages in run topic to ensure we get a runStart message - m_runStream = - m_broker->subscribe({m_runInfoTopic}, SubscribeAtOption::LASTTWO); - m_spDetStream = - m_broker->subscribe({m_spDetTopic}, SubscribeAtOption::LASTONE); - - m_thread = std::thread([this]() { this->captureImpl(); }); - m_thread.detach(); -} - -/** Indicate if the next data to be extracted should replace LoadLiveData's - * output workspace, - * for example the first data of a new run - */ -bool KafkaEventStreamDecoder::dataReset() { - bool result = (m_dataReset == true); // copy from atomic bool - m_dataReset = false; // reset to false - return result; -} - -void KafkaEventStreamDecoder::joinEventStreamAtTime( - const KafkaEventStreamDecoder::RunStartStruct &runStartData) { - auto runStartTime = runStartData.startTime; - int64_t startTimeMilliseconds = nanosecondsToMilliseconds(runStartTime); - m_eventStream = - m_broker->subscribe({m_eventTopic, m_runInfoTopic, m_sampleEnvTopic}, - startTimeMilliseconds, SubscribeAtOption::TIME); - // make sure we listen to the run start topic starting from the run start - // message we already got the start time from - m_eventStream->seek(m_runInfoTopic, 0, runStartData.runStartMsgOffset); -} - -int64_t KafkaEventStreamDecoder::nanosecondsToMilliseconds( - uint64_t timeNanoseconds) const { - return static_cast<int64_t>(timeNanoseconds / 1000000); -} - -/** - * Stop capturing from the stream. This is a blocking call until the capturing - * function has completed - */ -void KafkaEventStreamDecoder::stopCapture() noexcept { - // This will interrupt the "event" loop - m_interrupt = true; - // Wait until the function has completed. The background thread - // will exit automatically - while (m_capturing) { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - }; -} +KafkaEventStreamDecoder::~KafkaEventStreamDecoder() {} /** * Check if there is data available to extract @@ -200,29 +125,6 @@ bool KafkaEventStreamDecoder::hasReachedEndOfRun() noexcept { return false; } -/** - * Check for an exception thrown by the background thread and rethrow - * it if necessary. If no error occurred swap the current internal buffer - * for a fresh one and return the old buffer. - * @return A pointer to the data collected since the last call to this - * method - */ -API::Workspace_sptr KafkaEventStreamDecoder::extractData() { - if (m_exception) { - throw std::runtime_error(*m_exception); - } - - m_extractWaiting = true; - m_cv.notify_one(); - - auto workspace_ptr = extractDataImpl(); - - m_extractWaiting = false; - m_cv.notify_one(); - - return workspace_ptr; -} - // ----------------------------------------------------------------------------- // Private members // ----------------------------------------------------------------------------- @@ -230,14 +132,16 @@ API::Workspace_sptr KafkaEventStreamDecoder::extractData() { API::Workspace_sptr KafkaEventStreamDecoder::extractDataImpl() { std::lock_guard<std::mutex> lock(m_mutex); if (m_localEvents.size() == 1) { - auto temp = createBufferWorkspace(m_localEvents.front()); + auto temp = createBufferWorkspace<DataObjects::EventWorkspace>( + "EventWorkspace", m_localEvents.front()); std::swap(m_localEvents.front(), temp); return temp; } else if (m_localEvents.size() > 1) { auto group = boost::make_shared<API::WorkspaceGroup>(); size_t index(0); for (auto &filledBuffer : m_localEvents) { - auto temp = createBufferWorkspace(filledBuffer); + auto temp = createBufferWorkspace<DataObjects::EventWorkspace>( + "EventWorkspace", filledBuffer); std::swap(m_localEvents[index++], temp); group->addWorkspace(temp); } @@ -247,26 +151,6 @@ API::Workspace_sptr KafkaEventStreamDecoder::extractDataImpl() { } } -/** - * Start decoding data from the streams into the internal buffers. - * Implementation designed to be entry point for new thread of execution. - * It catches all thrown exceptions. - */ -void KafkaEventStreamDecoder::captureImpl() noexcept { - m_capturing = true; - try { - captureImplExcept(); - } catch (std::exception &exc) { - m_cbError(); - m_exception = boost::make_shared<std::runtime_error>(exc.what()); - } catch (...) { - m_cbError(); - m_exception = boost::make_shared<std::runtime_error>( - "KafkaEventStreamDecoder: Unknown exception type caught."); - } - m_capturing = false; -} - /** * Exception-throwing variant of captureImpl(). Do not call this directly */ @@ -302,7 +186,7 @@ void KafkaEventStreamDecoder::captureImplExcept() { waitForDataExtraction(); } // Pull in events - m_eventStream->consumeMessage(&buffer, offset, partition, topicName); + m_dataStream->consumeMessage(&buffer, offset, partition, topicName); // No events, wait for some to come along... if (buffer.empty()) { m_cbIterationEnd(); @@ -310,28 +194,13 @@ void KafkaEventStreamDecoder::captureImplExcept() { } if (checkOffsets) { - if (reachedEnd.count(topicName) && - offset >= stopOffsets[topicName][static_cast<size_t>(partition)]) { - - reachedEnd[topicName][static_cast<size_t>(partition)] = true; - - if (offset == stopOffsets[topicName][static_cast<size_t>(partition)]) { - g_log.debug() << "Reached end-of-run in " << topicName << " topic." - << std::endl; - g_log.debug() - << "topic: " << topicName << " offset: " << offset - << " stopOffset: " - << stopOffsets[topicName][static_cast<size_t>(partition)] - << std::endl; - } - checkIfAllStopOffsetsReached(reachedEnd, checkOffsets); - - if (offset > stopOffsets[topicName][static_cast<size_t>(partition)]) { - // If the offset is beyond the end of the current run, then skip to - // the next iteration and don't process the message - m_cbIterationEnd(); - continue; - } + checkRunEnd(topicName, checkOffsets, offset, partition, stopOffsets, + reachedEnd); + if (offset > stopOffsets[topicName][static_cast<size_t>(partition)]) { + // If the offset is beyond the end of the current run, then skip to + // the next iteration and don't process the message + m_cbIterationEnd(); + continue; } } @@ -349,225 +218,51 @@ void KafkaEventStreamDecoder::captureImplExcept() { sampleDataFromMessage(buffer); } // Check if we have a runMessage - else if (flatbuffers::BufferHasIdentifier( - reinterpret_cast<const uint8_t *>(buffer.c_str()), - RUN_MESSAGE_ID.c_str())) { - auto runMsg = - GetRunInfo(reinterpret_cast<const uint8_t *>(buffer.c_str())); - if (!checkOffsets && runMsg->info_type_type() == InfoTypes_RunStop) { - auto runStopMsg = static_cast<const RunStop *>(runMsg->info_type()); - auto stopTime = runStopMsg->stop_time(); - g_log.debug() << "Received an end-of-run message with stop time = " - << stopTime << std::endl; - stopOffsets = getStopOffsets(stopOffsets, reachedEnd, stopTime); - checkOffsets = true; - checkIfAllStopOffsetsReached(reachedEnd, checkOffsets); - } - } + else + checkRunMessage(buffer, checkOffsets, stopOffsets, reachedEnd); m_cbIterationEnd(); } g_log.debug("Event capture finished"); } -/** - * Check if we've reached the stop offset on every partition of every topic - * - * @param reachedEnd : Bool for each topic and partition to mark when stop - * offset reached - */ -void KafkaEventStreamDecoder::checkIfAllStopOffsetsReached( - const std::unordered_map<std::string, std::vector<bool>> &reachedEnd, - bool &checkOffsets) { - - if (std::all_of(reachedEnd.cbegin(), reachedEnd.cend(), - [](std::pair<std::string, std::vector<bool>> kv) { - return std::all_of( - kv.second.cbegin(), kv.second.cend(), - [](bool partitionEnd) { return partitionEnd; }); - }) || - reachedEnd.empty()) { - m_endRun = true; - // If we've reached the end of a run then set m_extractWaiting to true - // so that we wait until the buffer is emptied before continuing. - // Otherwise we can end up with data from two different runs in the - // same buffer workspace which is problematic if the user wanted the - // "Stop" or "Rename" run transition option. - m_extractedEndRunData = false; - checkOffsets = false; - g_log.notice("Reached end of run in data streams."); - } -} - -std::unordered_map<std::string, std::vector<int64_t>> -KafkaEventStreamDecoder::getStopOffsets( - std::unordered_map<std::string, std::vector<int64_t>> &stopOffsets, - std::unordered_map<std::string, std::vector<bool>> &reachedEnd, - uint64_t stopTime) const { - reachedEnd.clear(); - stopOffsets.clear(); - // Wait for max latency so that we don't miss any late messages - std::this_thread::sleep_for(MAX_LATENCY); - stopOffsets = m_eventStream->getOffsetsForTimestamp( - static_cast<int64_t>(stopTime / 1000000)); - // /1000000 to convert nanosecond precision from message to millisecond - // precision which Kafka offset query supports - - auto currentOffsets = m_eventStream->getCurrentOffsets(); - - // Set reachedEnd to false for each topic and partition - for (auto &topicOffsets : stopOffsets) { - auto topicName = topicOffsets.first; - // Ignore the runInfo topic - if (topicName.substr(topicName.length() - - KafkaTopicSubscriber::RUN_TOPIC_SUFFIX.length()) != - KafkaTopicSubscriber::RUN_TOPIC_SUFFIX) { - g_log.debug() << "TOPIC: " << topicName - << " PARTITIONS: " << topicOffsets.second.size() - << std::endl; - reachedEnd.insert( - {topicName, std::vector<bool>(topicOffsets.second.size(), false)}); - - auto &partitionOffsets = topicOffsets.second; - for (uint32_t partitionNumber = 0; - partitionNumber < partitionOffsets.size(); partitionNumber++) { - auto offset = partitionOffsets[partitionNumber]; - // If the stop offset is negative then there are no messages for us - // to collect on this topic, so mark reachedEnd as true already - reachedEnd[topicName][partitionNumber] = offset < 0; - // If the stop offset has already been reached then mark reachedEnd as - // true - if (currentOffsets[topicName][partitionNumber] >= offset) - reachedEnd[topicName][partitionNumber] = true; - } - } - } - return stopOffsets; -} - -/** - * If extractData method is waiting for access to the buffer workspace - * then we wait for it to finish - */ -void KafkaEventStreamDecoder::waitForDataExtraction() { - { - std::unique_lock<std::mutex> readyLock(m_waitMutex); - m_cv.wait(readyLock, [&] { return !m_extractWaiting; }); - } -} +void KafkaEventStreamDecoder::eventDataFromMessage(const std::string &buffer) { + auto eventMsg = + GetEventMessage(reinterpret_cast<const uint8_t *>(buffer.c_str())); -void KafkaEventStreamDecoder::waitForRunEndObservation() { - m_extractWaiting = true; - // Mark extractedEndRunData true before waiting on the extraction to ensure - // an immediate request for run status after extracting the data will return - // the correct value - avoids race condition in MonitorLiveData and tests - m_extractedEndRunData = true; - waitForDataExtraction(); - - // Wait until MonitorLiveData has seen that end of run was - // reached before setting m_endRun back to false and continuing - std::unique_lock<std::mutex> runStatusLock(m_runStatusMutex); - m_cvRunStatus.wait(runStatusLock, [&] { return m_runStatusSeen; }); - m_endRun = false; - m_runStatusSeen = false; - runStatusLock.unlock(); - - // Set to zero until we have the new run number, MonitorLiveData will - // queries before each time it extracts data until it gets non-zero - m_runNumber = 0; - - // Get new run message now so that new run number is available for - // MonitorLiveData as early as possible - RunStartStruct runStartStruct; - if (waitForNewRunStartMessage(runStartStruct)) - return; - - // Give time for MonitorLiveData to act on runStatus information - // and trigger m_interrupt for next loop iteration if user requested - // LiveData algorithm to stop at the end of the run - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - if (m_interrupt) - return; - - // Rejoin event stream at start of new run - joinEventStreamAtTime(runStartStruct); - std::string detSpecMapMsgBuffer = getDetSpecMapForRun(runStartStruct); - initLocalCaches(detSpecMapMsgBuffer, runStartStruct); -} + DateAndTime pulseTime = static_cast<int64_t>(eventMsg->pulse_time()); + const auto &tofData = *(eventMsg->time_of_flight()); + const auto &detData = *(eventMsg->detector_id()); + auto nEvents = tofData.size(); -/** - * Try to find a detector-spectrum map message published after the - * current run start time - * - * @param runStartStruct details of the current run - * @return received detector-spectrum map message buffer - */ -std::string KafkaEventStreamDecoder::getDetSpecMapForRun( - const KafkaEventStreamDecoder::RunStartStruct &runStartStruct) { - std::string rawMsgBuffer; - int64_t offset; - int32_t partition; - std::string topicName; - m_spDetStream = m_broker->subscribe( - {m_spDetTopic}, nanosecondsToMilliseconds(runStartStruct.startTime), - SubscribeAtOption::TIME); - m_spDetStream->consumeMessage(&rawMsgBuffer, offset, partition, topicName); - if (rawMsgBuffer.empty()) { - std::runtime_error( - "No detector-spectrum map message found for run number " + - std::to_string(runStartStruct.runNumber)); + DataObjects::EventWorkspace_sptr periodBuffer; + std::lock_guard<std::mutex> lock(m_mutex); + if (eventMsg->facility_specific_data_type() == FacilityData_ISISData) { + auto ISISMsg = + static_cast<const ISISData *>(eventMsg->facility_specific_data()); + periodBuffer = m_localEvents[static_cast<size_t>(ISISMsg->period_number())]; + auto &mutableRunInfo = periodBuffer->mutableRun(); + mutableRunInfo.getTimeSeriesProperty<double>(PROTON_CHARGE_PROPERTY) + ->addValue(pulseTime, ISISMsg->proton_charge()); + } else { + periodBuffer = m_localEvents[0]; } - return rawMsgBuffer; -} - -/** - * Wait for a run start message until we get one with a higher run number - * than the current run or the algorithm is interrupted - * - * @param runStartStructOutput details of the new run - * @return true if interrupted, false if got a new run start message - */ -bool KafkaEventStreamDecoder::waitForNewRunStartMessage( - RunStartStruct &runStartStructOutput) { - while (!m_interrupt) { - std::string runMsgBuffer; - - int64_t offset; - int32_t partition; - std::string topicName; - m_runStream->consumeMessage(&runMsgBuffer, offset, partition, topicName); - if (runMsgBuffer.empty()) { - continue; // no message available, try again - } else { - auto runMsg = - GetRunInfo(reinterpret_cast<const uint8_t *>(runMsgBuffer.c_str())); - if (runMsg->info_type_type() == InfoTypes_RunStart) { - // We got a run start message, deserialise it - auto runStartData = static_cast<const RunStart *>(runMsg->info_type()); - KafkaEventStreamDecoder::RunStartStruct runStartStruct = { - runStartData->instrument_name()->str(), runStartData->run_number(), - runStartData->start_time(), - static_cast<size_t>(runStartData->n_periods()), offset}; - if (runStartStruct.runNumber > m_runNumber) { - runStartStructOutput = runStartStruct; - m_runNumber = runStartStruct.runNumber; - return false; // not interrupted - } - } else { - continue; // received message wasn't a RunStart message, try again - } - } + for (decltype(nEvents) i = 0; i < nEvents; ++i) { + auto &spectrum = periodBuffer->getSpectrum( + m_specToIdx[static_cast<int32_t>(detData[i])]); + spectrum.addEventQuickly(TofEvent(static_cast<double>(tofData[i]) * + 1e-3, // nanoseconds to microseconds + pulseTime)); } - return true; // interrupted } /** - * Get sample environment log data from the flatbuffer and append it to the - * workspace - * - * @param seData : flatbuffer offset of the sample environment log data - * @param nSEEvents : number of sample environment log values in the flatbuffer - * @param mutableRunInfo : Log manager containing the existing sample logs - */ +* Get sample environment log data from the flatbuffer and append it to the +* workspace +* +* @param seData : flatbuffer offset of the sample environment log data +* @param nSEEvents : number of sample environment log values in the flatbuffer +* @param mutableRunInfo : Log manager containing the existing sample logs +*/ void KafkaEventStreamDecoder::sampleDataFromMessage(const std::string &buffer) { std::lock_guard<std::mutex> lock(m_mutex); @@ -608,60 +303,6 @@ void KafkaEventStreamDecoder::sampleDataFromMessage(const std::string &buffer) { } } -void KafkaEventStreamDecoder::eventDataFromMessage(const std::string &buffer) { - auto eventMsg = - GetEventMessage(reinterpret_cast<const uint8_t *>(buffer.c_str())); - - DateAndTime pulseTime = static_cast<int64_t>(eventMsg->pulse_time()); - const auto &tofData = *(eventMsg->time_of_flight()); - const auto &detData = *(eventMsg->detector_id()); - auto nEvents = tofData.size(); - - DataObjects::EventWorkspace_sptr periodBuffer; - std::lock_guard<std::mutex> lock(m_mutex); - if (eventMsg->facility_specific_data_type() == FacilityData_ISISData) { - auto ISISMsg = - static_cast<const ISISData *>(eventMsg->facility_specific_data()); - periodBuffer = m_localEvents[static_cast<size_t>(ISISMsg->period_number())]; - auto &mutableRunInfo = periodBuffer->mutableRun(); - mutableRunInfo.getTimeSeriesProperty<double>(PROTON_CHARGE_PROPERTY) - ->addValue(pulseTime, ISISMsg->proton_charge()); - } else { - periodBuffer = m_localEvents[0]; - } - for (decltype(nEvents) i = 0; i < nEvents; ++i) { - auto &spectrum = periodBuffer->getSpectrum( - m_specToIdx[static_cast<int32_t>(detData[i])]); - spectrum.addEventQuickly(TofEvent(static_cast<double>(tofData[i]) * - 1e-3, // nanoseconds to microseconds - pulseTime)); - } -} - -KafkaEventStreamDecoder::RunStartStruct -KafkaEventStreamDecoder::getRunStartMessage(std::string &rawMsgBuffer) { - auto offset = getRunInfoMessage(rawMsgBuffer); - auto runMsg = - GetRunInfo(reinterpret_cast<const uint8_t *>(rawMsgBuffer.c_str())); - if (runMsg->info_type_type() != InfoTypes_RunStart) { - // We want a runStart message, try the next one - offset = getRunInfoMessage(rawMsgBuffer); - runMsg = - GetRunInfo(reinterpret_cast<const uint8_t *>(rawMsgBuffer.c_str())); - if (runMsg->info_type_type() != InfoTypes_RunStart) { - throw std::runtime_error("KafkaEventStreamDecoder::initLocalCaches() - " - "Could not find a run start message" - "in the run info topic. Unable to continue"); - } - } - auto runStartData = static_cast<const RunStart *>(runMsg->info_type()); - KafkaEventStreamDecoder::RunStartStruct runStart = { - runStartData->instrument_name()->str(), runStartData->run_number(), - runStartData->start_time(), - static_cast<size_t>(runStartData->n_periods()), offset}; - return runStart; -} - /** * Pull information from the run & detector-spectrum stream and initialize * the internal EventWorkspace buffer + other cached information such as run @@ -693,14 +334,14 @@ void KafkaEventStreamDecoder::initLocalCaches( m_runNumber = runStartData.runNumber; // Create buffer - auto eventBuffer = createBufferWorkspace( - static_cast<size_t>(spDetMsg->n_spectra()), spDetMsg->spectrum()->data(), - spDetMsg->detector_id()->data(), nudet); + auto eventBuffer = createBufferWorkspace<DataObjects::EventWorkspace>( + "EventWorkspace", static_cast<size_t>(spDetMsg->n_spectra()), + spDetMsg->spectrum()->data(), spDetMsg->detector_id()->data(), nudet); // Load the instrument if possible but continue if we can't auto instName = runStartData.instrumentName; if (!instName.empty()) - loadInstrument(instName, eventBuffer); + loadInstrument<DataObjects::EventWorkspace>(instName, eventBuffer); else g_log.warning( "Empty instrument name received. Continuing without instrument"); @@ -743,120 +384,7 @@ void KafkaEventStreamDecoder::initLocalCaches( m_dataReset = true; } -/** - * Try to get a runInfo message from Kafka, throw error if it fails - * @param rawMsgBuffer : string to use as message buffer - */ -int64_t KafkaEventStreamDecoder::getRunInfoMessage(std::string &rawMsgBuffer) { - int64_t offset; - int32_t partition; - std::string topicName; - m_runStream->consumeMessage(&rawMsgBuffer, offset, partition, topicName); - if (rawMsgBuffer.empty()) { - throw std::runtime_error("KafkaEventStreamDecoder::getRunInfoMessage() - " - "Empty message received from run info " - "topic. Unable to continue"); - } - if (!flatbuffers::BufferHasIdentifier( - reinterpret_cast<const uint8_t *>(rawMsgBuffer.c_str()), - RUN_MESSAGE_ID.c_str())) { - throw std::runtime_error("KafkaEventStreamDecoder::getRunInfoMessage() - " - "Received unexpected message type from run info " - "topic. Unable to continue"); - } - return offset; -} - -/** - * Create a buffer workspace of the correct size based on the values given. - * @param nspectra The number of unique spectrum numbers - * @param spec An array of length ndet specifying the spectrum number of each - * detector - * @param udet An array of length ndet specifying the detector ID of each - * detector - * @param length The length of the spec/udet arrays - * @return A new workspace of the appropriate size - */ -DataObjects::EventWorkspace_sptr KafkaEventStreamDecoder::createBufferWorkspace( - const size_t nspectra, const int32_t *spec, const int32_t *udet, - const uint32_t length) { - // Order is important here - std::map<int32_t, std::set<int32_t>> spdetMap; - for (uint32_t i = 0; i < length; ++i) { - auto specNo = spec[i]; - auto detId = udet[i]; - auto search = spdetMap.find(specNo); - if (search != spdetMap.end()) { - search->second.insert(detId); - } else { - spdetMap.insert({specNo, {detId}}); - } - } - assert(nspectra == spdetMap.size()); - - // Create event workspace - auto eventBuffer = boost::static_pointer_cast<DataObjects::EventWorkspace>( - API::WorkspaceFactory::Instance().create("EventWorkspace", nspectra, 2, - 1)); - // Set the units - eventBuffer->getAxis(0)->unit() = - Kernel::UnitFactory::Instance().create("TOF"); - eventBuffer->setYUnit("Counts"); - // Setup spectra-detector mapping. - size_t wsIdx(0); - for (const auto &spIter : spdetMap) { - auto &spectrum = eventBuffer->getSpectrum(wsIdx); - spectrum.setSpectrumNo(spIter.first); - spectrum.addDetectorIDs(spIter.second); - ++wsIdx; - } - return eventBuffer; -} - -/** - * Create new buffer workspace from an existing copy - * @param parent A pointer to an existing workspace - */ -DataObjects::EventWorkspace_sptr KafkaEventStreamDecoder::createBufferWorkspace( - const DataObjects::EventWorkspace_sptr &parent) { - auto buffer = boost::static_pointer_cast<DataObjects::EventWorkspace>( - API::WorkspaceFactory::Instance().create( - "EventWorkspace", parent->getNumberHistograms(), 2, 1)); - // Copy meta data - API::WorkspaceFactory::Instance().initializeFromParent(*parent, *buffer, - false); - // Clear out the old logs, except for the most recent entry - buffer->mutableRun().clearOutdatedTimeSeriesLogValues(); - return buffer; -} -/** - * Run LoadInstrument for the given instrument name. If it cannot succeed it - * does nothing to the internal workspace - * @param name Name of an instrument to load - * @param workspace A pointer to the workspace receiving the instrument - */ -void KafkaEventStreamDecoder::loadInstrument( - const std::string &name, DataObjects::EventWorkspace_sptr workspace) { - if (name.empty()) { - g_log.warning("Empty instrument name found"); - return; - } - try { - auto alg = - API::AlgorithmManager::Instance().createUnmanaged("LoadInstrument"); - // Do not put the workspace in the ADS - alg->setChild(true); - alg->initialize(); - alg->setPropertyValue("InstrumentName", name); - alg->setProperty("Workspace", workspace); - alg->setProperty("RewriteSpectraMap", Kernel::OptionalBool(false)); - alg->execute(); - } catch (std::exception &exc) { - g_log.warning() << "Error loading instrument '" << name - << "': " << exc.what() << "\n"; - } -} } // namespace LiveData } // namespace Mantid diff --git a/Framework/LiveData/src/Kafka/KafkaHistoListener.cpp b/Framework/LiveData/src/Kafka/KafkaHistoListener.cpp index b7f3d5ed22f..aaf35a39928 100644 --- a/Framework/LiveData/src/Kafka/KafkaHistoListener.cpp +++ b/Framework/LiveData/src/Kafka/KafkaHistoListener.cpp @@ -25,14 +25,37 @@ KafkaHistoListener::KafkaHistoListener() { declareProperty("InstrumentName", ""); } +void KafkaHistoListener::setAlgorithm( + const Mantid::API::IAlgorithm &callingAlgorithm) { + this->updatePropertyValues(callingAlgorithm); + // Get the instrument name from StartLiveData so we can sub to correct topics + if (callingAlgorithm.existsProperty("Instrument")) { + m_instrumentName = callingAlgorithm.getPropertyValue("Instrument"); + } else { + g_log.error("KafkaEventListener requires Instrument property to be set in " + "calling algorithm"); + } +} + /// @copydoc ILiveListener::connect bool KafkaHistoListener::connect(const Poco::Net::SocketAddress &address) { + if (m_instrumentName.empty()) { + g_log.error( + "KafkaHistoListener::connect requires a non-empty instrument name"); + } + try { - std::string instrumentName = getProperty("InstrumentName"); - const std::string histoTopic(instrumentName + - KafkaTopicSubscriber::HISTO_TOPIC_SUFFIX); + const std::string histoTopic(m_instrumentName + + KafkaTopicSubscriber::HISTO_TOPIC_SUFFIX), + runInfoTopic(m_instrumentName + KafkaTopicSubscriber::RUN_TOPIC_SUFFIX), + spDetInfoTopic(m_instrumentName + + KafkaTopicSubscriber::DET_SPEC_TOPIC_SUFFIX), + sampleEnvTopic(m_instrumentName + + KafkaTopicSubscriber::SAMPLE_ENV_TOPIC_SUFFIX); + m_decoder = Kernel::make_unique<KafkaHistoStreamDecoder>( - address.toString(), histoTopic, instrumentName); + std::make_shared<KafkaBroker>(address.toString()), histoTopic, + runInfoTopic, spDetInfoTopic, sampleEnvTopic); } catch (std::exception &exc) { g_log.error() << "KafkaHistoListener::connect - Connection Error: " << exc.what() << "\n"; diff --git a/Framework/LiveData/src/Kafka/KafkaHistoStreamDecoder.cpp b/Framework/LiveData/src/Kafka/KafkaHistoStreamDecoder.cpp index d127e3d2575..d3bb4d20448 100644 --- a/Framework/LiveData/src/Kafka/KafkaHistoStreamDecoder.cpp +++ b/Framework/LiveData/src/Kafka/KafkaHistoStreamDecoder.cpp @@ -12,16 +12,25 @@ #include "MantidDataObjects/WorkspaceCreation.h" #include "MantidGeometry/Instrument/DetectorInfo.h" #include "MantidHistogramData/BinEdges.h" +#include "MantidIndexing/IndexInfo.h" #include "MantidKernel/Logger.h" #include "MantidKernel/OptionalBool.h" +#include "MantidKernel/TimeSeriesProperty.h" +#include "MantidKernel/UnitFactory.h" #include "MantidKernel/WarningSuppressions.h" #include "MantidLiveData/Exception.h" GNU_DIAG_OFF("conversion") +#include "private/Schema/df12_det_spec_map_generated.h" #include "private/Schema/hs00_event_histogram_generated.h" GNU_DIAG_ON("conversion") +using namespace HistoSchema; + namespace { +const std::string PROTON_CHARGE_PROPERTY = "proton_charge"; +const std::string RUN_NUMBER_PROPERTY = "run_number"; +const std::string RUN_START_PROPERTY = "run_start"; /// Logger Mantid::Kernel::Logger g_log("KafkaHistoStreamDecoder"); } // namespace @@ -35,95 +44,41 @@ namespace LiveData { /** * Constructor - * @param brokerAddress The physical ipAddress of the broker + * @param broker Kafka broker * @param histoTopic The name of the topic streaming the histo data * @param spDetTopic The name of the topic streaming the spectrum-detector * run mapping */ KafkaHistoStreamDecoder::KafkaHistoStreamDecoder( - const std::string &brokerAddress, const std::string &histoTopic, - const std::string &instrumentName) - : m_broker(brokerAddress), m_histoTopic(histoTopic), - m_instrumentName(instrumentName), m_histoStream(), m_workspace(), - m_buffer(), m_thread(), m_interrupt(false), m_capturing(false), - m_exception(nullptr) { - if (histoTopic.empty()) - throw std::invalid_argument( - "KafkaHistoStreamDecoder::KafkaHistoStreamDecorder " - ": histogramTopic cannot be an empty string."); - if (instrumentName.empty()) - throw std::invalid_argument( - "KafkaHistoStreamDecoder::KafkaHistoStreamDecorder " - ": instrumentName cannot be an empty string."); - // Initialize buffer workspace - m_workspace = createBufferWorkspace(); -} + std::shared_ptr<IKafkaBroker> broker, const std::string &histoTopic, + const std::string &runInfoTopic, const std::string &spDetTopic, + const std::string &sampleEnvTopic) + : IKafkaStreamDecoder(broker, histoTopic, runInfoTopic, spDetTopic, + sampleEnvTopic), + m_workspace() {} /** * Destructor. * Stops capturing from the stream */ -KafkaHistoStreamDecoder::~KafkaHistoStreamDecoder() { stopCapture(); } - -/** - * Start capturing from the stream on a separate thread. This is a non-blocking - * call and will return after the thread has started - */ -void KafkaHistoStreamDecoder::startCapture(bool) { - g_log.debug() << "Starting capture on topic: " << m_histoTopic << "\n"; - m_histoStream = m_broker.subscribe({m_histoTopic}, SubscribeAtOption::LATEST); - - m_thread = std::thread([this]() { this->captureImpl(); }); - m_thread.detach(); -} - -/** - * Stop capturing from the stream. This is a blocking call until the capturing - * function has completed - */ -void KafkaHistoStreamDecoder::stopCapture() noexcept { - g_log.debug() << "Stopping capture\n"; - - // This will interrupt the "event" loop - m_interrupt = true; - // Wait until the function has completed. The background thread will exit - // automatically - while (m_capturing) { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - }; -} +KafkaHistoStreamDecoder::~KafkaHistoStreamDecoder() {} /** * Check if there is data available to extract * @return True if data has been accumulated so that extractData() * can be called, false otherwise */ -bool KafkaHistoStreamDecoder::hasData() const { - std::lock_guard<std::mutex> lock(m_buffer_mutex); +bool KafkaHistoStreamDecoder::hasData() const noexcept { + std::lock_guard<std::mutex> lock(m_mutex); return !m_buffer.empty(); } -/** - * Check for an exception thrown by the background thread and rethrow - * it if necessary. - * @return A pointer to the data collected since the last call to this - * method - */ -API::Workspace_sptr KafkaHistoStreamDecoder::extractData() { - if (m_exception) { - throw *m_exception; - } - - auto workspace_ptr = extractDataImpl(); - return workspace_ptr; -} - // ----------------------------------------------------------------------------- // Private members // ----------------------------------------------------------------------------- API::Workspace_sptr KafkaHistoStreamDecoder::extractDataImpl() { - std::lock_guard<std::mutex> lock(m_buffer_mutex); + std::lock_guard<std::mutex> lock(m_mutex); if (!m_capturing) { throw Exception::NotYet("Local buffers not initialized."); @@ -169,78 +124,143 @@ API::Workspace_sptr KafkaHistoStreamDecoder::extractDataImpl() { return ws; } -/** - * Start decoding data from the streams into the internal buffers. - * Implementation designed to be entry point for new thread of execution. - * It catches all thrown exceptions. - */ -void KafkaHistoStreamDecoder::captureImpl() { - m_capturing = true; - try { - captureImplExcept(); - } catch (std::exception &exc) { - m_exception.reset(new std::runtime_error(exc.what())); - } catch (...) { - m_exception.reset(new std::runtime_error( - "KafkaEventStreamDecoder: Unknown exception type caught.")); - } - m_capturing = false; -} - /** * Exception-throwing variant of captureImpl(). Do not call this directly */ void KafkaHistoStreamDecoder::captureImplExcept() { g_log.information("Event capture starting"); - m_interrupt = false; + m_interrupt = false; // Allow MonitorLiveData or user to interrupt + m_endRun = false; + m_runStatusSeen = false; // Flag to ensure MonitorLiveData observes end of run std::string buffer; + std::string runBuffer; int64_t offset; int32_t partition; std::string topicName; + auto runStartStruct = getRunStartMessage(runBuffer); + m_spDetStream->consumeMessage(&buffer, offset, partition, topicName); + initLocalCaches(buffer, runStartStruct); - while (!m_interrupt) { - // Pull in events - m_histoStream->consumeMessage(&buffer, offset, partition, topicName); + // Keep track of whether we've reached the end of a run + std::unordered_map<std::string, std::vector<int64_t>> stopOffsets; + std::unordered_map<std::string, std::vector<bool>> reachedEnd; + bool checkOffsets = false; - // No events, wait for some to come along... - if (buffer.empty()) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + while (!m_interrupt) { + if (m_endRun) { + waitForRunEndObservation(); continue; + } else { + waitForDataExtraction(); } - // Lock so we don't overwrite buffer while workspace is being extracted { - std::lock_guard<std::mutex> lock(m_buffer_mutex); + // Lock so we don't overwrite buffer while workspace is being extracted or + // try to access data before it is read. + std::lock_guard<std::mutex> lock(m_mutex); + // Pull in data + m_dataStream->consumeMessage(&buffer, offset, partition, topicName); + + // No events, wait for some to come along... + if (buffer.empty()) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + m_cbIterationEnd(); + continue; + } + + if (checkOffsets) { + checkRunEnd(topicName, checkOffsets, offset, partition, stopOffsets, + reachedEnd); + if (offset > stopOffsets[topicName][static_cast<size_t>(partition)]) { + // If the offset is beyond the end of the current run, then skip to + // the next iteration and don't process the message + m_cbIterationEnd(); + continue; + } + } + + // Data being accumulated before being streamed so no need to store + // messages. m_buffer = buffer; } + checkRunMessage(buffer, checkOffsets, stopOffsets, reachedEnd); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + m_cbIterationEnd(); } g_log.debug("Histo capture finished"); } -DataObjects::Workspace2D_sptr KafkaHistoStreamDecoder::createBufferWorkspace() { - DataObjects::Workspace2D_sptr workspace; - - try { - auto alg = API::AlgorithmManager::Instance().createUnmanaged( - "LoadEmptyInstrument"); - // Do not put the workspace in the ADS - alg->setChild(true); - alg->initialize(); - alg->setPropertyValue("InstrumentName", m_instrumentName); - // Dummy workspace value "ws" as not placed in ADS - alg->setPropertyValue("OutputWorkspace", "ws"); - alg->execute(); - workspace = alg->getProperty("OutputWorkspace"); - } catch (std::exception &exc) { - g_log.error() << "Error loading empty instrument '" << m_instrumentName - << "': " << exc.what() << "\n"; - throw; +void KafkaHistoStreamDecoder::initLocalCaches( + const std::string &rawMsgBuffer, const RunStartStruct &runStartData) { + if (rawMsgBuffer.empty()) { + throw std::runtime_error("KafkaEventStreamDecoder::initLocalCaches() - " + "Empty message received from spectrum-detector " + "topic. Unable to continue"); } + auto spDetMsg = GetSpectraDetectorMapping( + reinterpret_cast<const uint8_t *>(rawMsgBuffer.c_str())); + auto nspec = static_cast<uint32_t>(spDetMsg->n_spectra()); + auto nudet = spDetMsg->detector_id()->size(); + if (nudet != nspec) { + std::ostringstream os; + os << "KafkaEventStreamDecoder::initLocalEventBuffer() - Invalid " + "spectra/detector mapping. Expected matched length arrays but " + "found nspec=" + << nspec << ", ndet=" << nudet; + throw std::runtime_error(os.str()); + } + + m_runNumber = runStartData.runNumber; + + // Create buffer + auto histoBuffer = createBufferWorkspace<DataObjects::Workspace2D>( + "Workspace2D", static_cast<size_t>(spDetMsg->n_spectra()), + spDetMsg->spectrum()->data(), spDetMsg->detector_id()->data(), nudet); + + // Load the instrument if possible but continue if we can't + auto instName = runStartData.instrumentName; + if (!instName.empty()) + loadInstrument<DataObjects::Workspace2D>(instName, histoBuffer); + else + g_log.warning( + "Empty instrument name received. Continuing without instrument"); + + auto &mutableRun = histoBuffer->mutableRun(); + // Run start. Cache locally for computing frame times + // Convert nanoseconds to seconds (and discard the extra precision) + auto runStartTime = static_cast<time_t>(runStartData.startTime / 1000000000); + m_runStart.set_from_time_t(runStartTime); + auto timeString = m_runStart.toISO8601String(); + // Run number + mutableRun.addProperty(RUN_START_PROPERTY, std::string(timeString)); + mutableRun.addProperty(RUN_NUMBER_PROPERTY, + std::to_string(runStartData.runNumber)); + // Create the proton charge property + mutableRun.addProperty( + new Kernel::TimeSeriesProperty<double>(PROTON_CHARGE_PROPERTY)); + + // Cache spec->index mapping. We assume it is the same across all periods + m_specToIdx = histoBuffer->getSpectrumToWorkspaceIndexMap(); + + // Buffers for each period + const size_t nperiods = runStartData.nPeriods; + if (nperiods > 1) { + throw std::runtime_error( + "KafkaHistoStreamDecoder - Does not support multi-period data."); + } + // New caches so LoadLiveData's output workspace needs to be replaced + m_dataReset = true; + + m_workspace = histoBuffer; +} - return workspace; +void KafkaHistoStreamDecoder::sampleDataFromMessage(const std::string &) { + throw Kernel::Exception::NotImplementedError("This method will require " + "implementation when processing " + "sample environment messages."); } } // namespace LiveData diff --git a/Framework/LiveData/src/Kafka/private/Schema/f142_logdata_generated.h b/Framework/LiveData/src/Kafka/private/Schema/f142_logdata_generated.h index 0f84e9cf09c..af688ca8a43 100644 --- a/Framework/LiveData/src/Kafka/private/Schema/f142_logdata_generated.h +++ b/Framework/LiveData/src/Kafka/private/Schema/f142_logdata_generated.h @@ -14,762 +14,765 @@ #include "fwdi_forwarder_internal_generated.h" -struct fwdinfo_1_t; - - -struct Byte; -struct UByte; -struct Short; -struct UShort; -struct Int; -struct UInt; -struct Long; -struct ULong; -struct Float; -struct Double; -struct ArrayByte; -struct ArrayUByte; -struct ArrayShort; -struct ArrayUShort; -struct ArrayInt; -struct ArrayUInt; -struct ArrayLong; -struct ArrayULong; -struct ArrayFloat; -struct ArrayDouble; -struct LogData; - -enum Value { - Value_NONE = 0, - Value_Byte = 1, - Value_UByte = 2, - Value_Short = 3, - Value_UShort = 4, - Value_Int = 5, - Value_UInt = 6, - Value_Long = 7, - Value_ULong = 8, - Value_Float = 9, - Value_Double = 10, - Value_ArrayByte = 11, - Value_ArrayUByte = 12, - Value_ArrayShort = 13, - Value_ArrayUShort = 14, - Value_ArrayInt = 15, - Value_ArrayUInt = 16, - Value_ArrayLong = 17, - Value_ArrayULong = 18, - Value_ArrayFloat = 19, - Value_ArrayDouble = 20, - Value_MIN = Value_NONE, - Value_MAX = Value_ArrayDouble -}; - -inline const char **EnumNamesValue() { - static const char *names[] = { "NONE", "Byte", "UByte", "Short", "UShort", "Int", "UInt", "Long", "ULong", "Float", "Double", "ArrayByte", "ArrayUByte", "ArrayShort", "ArrayUShort", "ArrayInt", "ArrayUInt", "ArrayLong", "ArrayULong", "ArrayFloat", "ArrayDouble", nullptr }; - return names; -} +/// Due to type conflicts with other schemas it was necessary to +/// add this namespace LogSchema. +namespace LogSchema { + struct fwdinfo_1_t; + + + struct Byte; + struct UByte; + struct Short; + struct UShort; + struct Int; + struct UInt; + struct Long; + struct ULong; + struct Float; + struct Double; + struct ArrayByte; + struct ArrayUByte; + struct ArrayShort; + struct ArrayUShort; + struct ArrayInt; + struct ArrayUInt; + struct ArrayLong; + struct ArrayULong; + struct ArrayFloat; + struct ArrayDouble; + struct LogData; + + enum Value { + Value_NONE = 0, + Value_Byte = 1, + Value_UByte = 2, + Value_Short = 3, + Value_UShort = 4, + Value_Int = 5, + Value_UInt = 6, + Value_Long = 7, + Value_ULong = 8, + Value_Float = 9, + Value_Double = 10, + Value_ArrayByte = 11, + Value_ArrayUByte = 12, + Value_ArrayShort = 13, + Value_ArrayUShort = 14, + Value_ArrayInt = 15, + Value_ArrayUInt = 16, + Value_ArrayLong = 17, + Value_ArrayULong = 18, + Value_ArrayFloat = 19, + Value_ArrayDouble = 20, + Value_MIN = Value_NONE, + Value_MAX = Value_ArrayDouble + }; + + inline const char **EnumNamesValue() { + static const char *names[] = { "NONE", "Byte", "UByte", "Short", "UShort", "Int", "UInt", "Long", "ULong", "Float", "Double", "ArrayByte", "ArrayUByte", "ArrayShort", "ArrayUShort", "ArrayInt", "ArrayUInt", "ArrayLong", "ArrayULong", "ArrayFloat", "ArrayDouble", nullptr }; + return names; + } -inline const char *EnumNameValue(Value e) { return EnumNamesValue()[static_cast<int>(e)]; } + inline const char *EnumNameValue(Value e) { return EnumNamesValue()[static_cast<int>(e)]; } -inline bool VerifyValue(flatbuffers::Verifier &verifier, const void *union_obj, Value type); + inline bool VerifyValue(flatbuffers::Verifier &verifier, const void *union_obj, Value type); -struct Byte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + struct Byte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + int8_t value() const { return GetField<int8_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<int8_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - int8_t value() const { return GetField<int8_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<int8_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct ByteBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(int8_t value) { fbb_.AddElement<int8_t>(Byte::VT_VALUE, value, 0); } - ByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ByteBuilder &operator=(const ByteBuilder &); - flatbuffers::Offset<Byte> Finish() { - auto o = flatbuffers::Offset<Byte>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<Byte> CreateByte(flatbuffers::FlatBufferBuilder &_fbb, - int8_t value = 0) { - ByteBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ByteBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(int8_t value) { fbb_.AddElement<int8_t>(Byte::VT_VALUE, value, 0); } + ByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ByteBuilder &operator=(const ByteBuilder &); + flatbuffers::Offset<Byte> Finish() { + auto o = flatbuffers::Offset<Byte>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct UByte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<Byte> CreateByte(flatbuffers::FlatBufferBuilder &_fbb, + int8_t value = 0) { + ByteBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct UByte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + uint8_t value() const { return GetField<uint8_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<uint8_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - uint8_t value() const { return GetField<uint8_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<uint8_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct UByteBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(uint8_t value) { fbb_.AddElement<uint8_t>(UByte::VT_VALUE, value, 0); } - UByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - UByteBuilder &operator=(const UByteBuilder &); - flatbuffers::Offset<UByte> Finish() { - auto o = flatbuffers::Offset<UByte>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<UByte> CreateUByte(flatbuffers::FlatBufferBuilder &_fbb, - uint8_t value = 0) { - UByteBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct UByteBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(uint8_t value) { fbb_.AddElement<uint8_t>(UByte::VT_VALUE, value, 0); } + UByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UByteBuilder &operator=(const UByteBuilder &); + flatbuffers::Offset<UByte> Finish() { + auto o = flatbuffers::Offset<UByte>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct Short FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<UByte> CreateUByte(flatbuffers::FlatBufferBuilder &_fbb, + uint8_t value = 0) { + UByteBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct Short FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + int16_t value() const { return GetField<int16_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<int16_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - int16_t value() const { return GetField<int16_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<int16_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct ShortBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(int16_t value) { fbb_.AddElement<int16_t>(Short::VT_VALUE, value, 0); } - ShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ShortBuilder &operator=(const ShortBuilder &); - flatbuffers::Offset<Short> Finish() { - auto o = flatbuffers::Offset<Short>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<Short> CreateShort(flatbuffers::FlatBufferBuilder &_fbb, - int16_t value = 0) { - ShortBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ShortBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(int16_t value) { fbb_.AddElement<int16_t>(Short::VT_VALUE, value, 0); } + ShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ShortBuilder &operator=(const ShortBuilder &); + flatbuffers::Offset<Short> Finish() { + auto o = flatbuffers::Offset<Short>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct UShort FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<Short> CreateShort(flatbuffers::FlatBufferBuilder &_fbb, + int16_t value = 0) { + ShortBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct UShort FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + uint16_t value() const { return GetField<uint16_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<uint16_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - uint16_t value() const { return GetField<uint16_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<uint16_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct UShortBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(uint16_t value) { fbb_.AddElement<uint16_t>(UShort::VT_VALUE, value, 0); } - UShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - UShortBuilder &operator=(const UShortBuilder &); - flatbuffers::Offset<UShort> Finish() { - auto o = flatbuffers::Offset<UShort>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<UShort> CreateUShort(flatbuffers::FlatBufferBuilder &_fbb, - uint16_t value = 0) { - UShortBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct UShortBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(uint16_t value) { fbb_.AddElement<uint16_t>(UShort::VT_VALUE, value, 0); } + UShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UShortBuilder &operator=(const UShortBuilder &); + flatbuffers::Offset<UShort> Finish() { + auto o = flatbuffers::Offset<UShort>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct Int FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<UShort> CreateUShort(flatbuffers::FlatBufferBuilder &_fbb, + uint16_t value = 0) { + UShortBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct Int FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + int32_t value() const { return GetField<int32_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<int32_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - int32_t value() const { return GetField<int32_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<int32_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct IntBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(int32_t value) { fbb_.AddElement<int32_t>(Int::VT_VALUE, value, 0); } - IntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - IntBuilder &operator=(const IntBuilder &); - flatbuffers::Offset<Int> Finish() { - auto o = flatbuffers::Offset<Int>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<Int> CreateInt(flatbuffers::FlatBufferBuilder &_fbb, - int32_t value = 0) { - IntBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct IntBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(int32_t value) { fbb_.AddElement<int32_t>(Int::VT_VALUE, value, 0); } + IntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + IntBuilder &operator=(const IntBuilder &); + flatbuffers::Offset<Int> Finish() { + auto o = flatbuffers::Offset<Int>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct UInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<Int> CreateInt(flatbuffers::FlatBufferBuilder &_fbb, + int32_t value = 0) { + IntBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct UInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + uint32_t value() const { return GetField<uint32_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<uint32_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - uint32_t value() const { return GetField<uint32_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<uint32_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct UIntBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(uint32_t value) { fbb_.AddElement<uint32_t>(UInt::VT_VALUE, value, 0); } - UIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - UIntBuilder &operator=(const UIntBuilder &); - flatbuffers::Offset<UInt> Finish() { - auto o = flatbuffers::Offset<UInt>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<UInt> CreateUInt(flatbuffers::FlatBufferBuilder &_fbb, - uint32_t value = 0) { - UIntBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct UIntBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(uint32_t value) { fbb_.AddElement<uint32_t>(UInt::VT_VALUE, value, 0); } + UIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + UIntBuilder &operator=(const UIntBuilder &); + flatbuffers::Offset<UInt> Finish() { + auto o = flatbuffers::Offset<UInt>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct Long FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<UInt> CreateUInt(flatbuffers::FlatBufferBuilder &_fbb, + uint32_t value = 0) { + UIntBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct Long FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + int64_t value() const { return GetField<int64_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<int64_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - int64_t value() const { return GetField<int64_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<int64_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct LongBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(int64_t value) { fbb_.AddElement<int64_t>(Long::VT_VALUE, value, 0); } - LongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - LongBuilder &operator=(const LongBuilder &); - flatbuffers::Offset<Long> Finish() { - auto o = flatbuffers::Offset<Long>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<Long> CreateLong(flatbuffers::FlatBufferBuilder &_fbb, - int64_t value = 0) { - LongBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct LongBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(int64_t value) { fbb_.AddElement<int64_t>(Long::VT_VALUE, value, 0); } + LongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + LongBuilder &operator=(const LongBuilder &); + flatbuffers::Offset<Long> Finish() { + auto o = flatbuffers::Offset<Long>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ULong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<Long> CreateLong(flatbuffers::FlatBufferBuilder &_fbb, + int64_t value = 0) { + LongBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ULong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + uint64_t value() const { return GetField<uint64_t>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<uint64_t>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - uint64_t value() const { return GetField<uint64_t>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<uint64_t>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct ULongBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(uint64_t value) { fbb_.AddElement<uint64_t>(ULong::VT_VALUE, value, 0); } - ULongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ULongBuilder &operator=(const ULongBuilder &); - flatbuffers::Offset<ULong> Finish() { - auto o = flatbuffers::Offset<ULong>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ULong> CreateULong(flatbuffers::FlatBufferBuilder &_fbb, - uint64_t value = 0) { - ULongBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ULongBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(uint64_t value) { fbb_.AddElement<uint64_t>(ULong::VT_VALUE, value, 0); } + ULongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ULongBuilder &operator=(const ULongBuilder &); + flatbuffers::Offset<ULong> Finish() { + auto o = flatbuffers::Offset<ULong>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct Float FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ULong> CreateULong(flatbuffers::FlatBufferBuilder &_fbb, + uint64_t value = 0) { + ULongBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct Float FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + float value() const { return GetField<float>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<float>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - float value() const { return GetField<float>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<float>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct FloatBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(float value) { fbb_.AddElement<float>(Float::VT_VALUE, value, 0); } - FloatBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - FloatBuilder &operator=(const FloatBuilder &); - flatbuffers::Offset<Float> Finish() { - auto o = flatbuffers::Offset<Float>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<Float> CreateFloat(flatbuffers::FlatBufferBuilder &_fbb, - float value = 0) { - FloatBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct FloatBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(float value) { fbb_.AddElement<float>(Float::VT_VALUE, value, 0); } + FloatBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + FloatBuilder &operator=(const FloatBuilder &); + flatbuffers::Offset<Float> Finish() { + auto o = flatbuffers::Offset<Float>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct Double FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<Float> CreateFloat(flatbuffers::FlatBufferBuilder &_fbb, + float value = 0) { + FloatBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct Double FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + double value() const { return GetField<double>(VT_VALUE, 0); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<double>(verifier, VT_VALUE) && + verifier.EndTable(); + } }; - double value() const { return GetField<double>(VT_VALUE, 0); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<double>(verifier, VT_VALUE) && - verifier.EndTable(); - } -}; - -struct DoubleBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(double value) { fbb_.AddElement<double>(Double::VT_VALUE, value, 0); } - DoubleBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - DoubleBuilder &operator=(const DoubleBuilder &); - flatbuffers::Offset<Double> Finish() { - auto o = flatbuffers::Offset<Double>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<Double> CreateDouble(flatbuffers::FlatBufferBuilder &_fbb, - double value = 0) { - DoubleBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct DoubleBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(double value) { fbb_.AddElement<double>(Double::VT_VALUE, value, 0); } + DoubleBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + DoubleBuilder &operator=(const DoubleBuilder &); + flatbuffers::Offset<Double> Finish() { + auto o = flatbuffers::Offset<Double>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayByte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<Double> CreateDouble(flatbuffers::FlatBufferBuilder &_fbb, + double value = 0) { + DoubleBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayByte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<int8_t> *value() const { return GetPointer<const flatbuffers::Vector<int8_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<int8_t> *value() const { return GetPointer<const flatbuffers::Vector<int8_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayByteBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<int8_t>> value) { fbb_.AddOffset(ArrayByte::VT_VALUE, value); } - ArrayByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayByteBuilder &operator=(const ArrayByteBuilder &); - flatbuffers::Offset<ArrayByte> Finish() { - auto o = flatbuffers::Offset<ArrayByte>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayByte> CreateArrayByte(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<int8_t>> value = 0) { - ArrayByteBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayByteBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<int8_t>> value) { fbb_.AddOffset(ArrayByte::VT_VALUE, value); } + ArrayByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayByteBuilder &operator=(const ArrayByteBuilder &); + flatbuffers::Offset<ArrayByte> Finish() { + auto o = flatbuffers::Offset<ArrayByte>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayUByte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayByte> CreateArrayByte(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<int8_t>> value = 0) { + ArrayByteBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayUByte FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<uint8_t> *value() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<uint8_t> *value() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayUByteBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> value) { fbb_.AddOffset(ArrayUByte::VT_VALUE, value); } - ArrayUByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayUByteBuilder &operator=(const ArrayUByteBuilder &); - flatbuffers::Offset<ArrayUByte> Finish() { - auto o = flatbuffers::Offset<ArrayUByte>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayUByte> CreateArrayUByte(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<uint8_t>> value = 0) { - ArrayUByteBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayUByteBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> value) { fbb_.AddOffset(ArrayUByte::VT_VALUE, value); } + ArrayUByteBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayUByteBuilder &operator=(const ArrayUByteBuilder &); + flatbuffers::Offset<ArrayUByte> Finish() { + auto o = flatbuffers::Offset<ArrayUByte>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayShort FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayUByte> CreateArrayUByte(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<uint8_t>> value = 0) { + ArrayUByteBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayShort FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<int16_t> *value() const { return GetPointer<const flatbuffers::Vector<int16_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<int16_t> *value() const { return GetPointer<const flatbuffers::Vector<int16_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayShortBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<int16_t>> value) { fbb_.AddOffset(ArrayShort::VT_VALUE, value); } - ArrayShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayShortBuilder &operator=(const ArrayShortBuilder &); - flatbuffers::Offset<ArrayShort> Finish() { - auto o = flatbuffers::Offset<ArrayShort>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayShort> CreateArrayShort(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<int16_t>> value = 0) { - ArrayShortBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayShortBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<int16_t>> value) { fbb_.AddOffset(ArrayShort::VT_VALUE, value); } + ArrayShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayShortBuilder &operator=(const ArrayShortBuilder &); + flatbuffers::Offset<ArrayShort> Finish() { + auto o = flatbuffers::Offset<ArrayShort>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayUShort FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayShort> CreateArrayShort(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<int16_t>> value = 0) { + ArrayShortBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayUShort FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<uint16_t> *value() const { return GetPointer<const flatbuffers::Vector<uint16_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<uint16_t> *value() const { return GetPointer<const flatbuffers::Vector<uint16_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayUShortBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<uint16_t>> value) { fbb_.AddOffset(ArrayUShort::VT_VALUE, value); } - ArrayUShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayUShortBuilder &operator=(const ArrayUShortBuilder &); - flatbuffers::Offset<ArrayUShort> Finish() { - auto o = flatbuffers::Offset<ArrayUShort>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayUShort> CreateArrayUShort(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<uint16_t>> value = 0) { - ArrayUShortBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayUShortBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<uint16_t>> value) { fbb_.AddOffset(ArrayUShort::VT_VALUE, value); } + ArrayUShortBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayUShortBuilder &operator=(const ArrayUShortBuilder &); + flatbuffers::Offset<ArrayUShort> Finish() { + auto o = flatbuffers::Offset<ArrayUShort>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayUShort> CreateArrayUShort(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<uint16_t>> value = 0) { + ArrayUShortBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<int32_t> *value() const { return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<int32_t> *value() const { return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayIntBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<int32_t>> value) { fbb_.AddOffset(ArrayInt::VT_VALUE, value); } - ArrayIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayIntBuilder &operator=(const ArrayIntBuilder &); - flatbuffers::Offset<ArrayInt> Finish() { - auto o = flatbuffers::Offset<ArrayInt>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayInt> CreateArrayInt(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<int32_t>> value = 0) { - ArrayIntBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayIntBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<int32_t>> value) { fbb_.AddOffset(ArrayInt::VT_VALUE, value); } + ArrayIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayIntBuilder &operator=(const ArrayIntBuilder &); + flatbuffers::Offset<ArrayInt> Finish() { + auto o = flatbuffers::Offset<ArrayInt>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayUInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayInt> CreateArrayInt(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<int32_t>> value = 0) { + ArrayIntBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayUInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<uint32_t> *value() const { return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<uint32_t> *value() const { return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayUIntBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> value) { fbb_.AddOffset(ArrayUInt::VT_VALUE, value); } - ArrayUIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayUIntBuilder &operator=(const ArrayUIntBuilder &); - flatbuffers::Offset<ArrayUInt> Finish() { - auto o = flatbuffers::Offset<ArrayUInt>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayUInt> CreateArrayUInt(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<uint32_t>> value = 0) { - ArrayUIntBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayUIntBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> value) { fbb_.AddOffset(ArrayUInt::VT_VALUE, value); } + ArrayUIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayUIntBuilder &operator=(const ArrayUIntBuilder &); + flatbuffers::Offset<ArrayUInt> Finish() { + auto o = flatbuffers::Offset<ArrayUInt>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayLong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayUInt> CreateArrayUInt(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<uint32_t>> value = 0) { + ArrayUIntBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayLong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<int64_t> *value() const { return GetPointer<const flatbuffers::Vector<int64_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<int64_t> *value() const { return GetPointer<const flatbuffers::Vector<int64_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayLongBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<int64_t>> value) { fbb_.AddOffset(ArrayLong::VT_VALUE, value); } - ArrayLongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayLongBuilder &operator=(const ArrayLongBuilder &); - flatbuffers::Offset<ArrayLong> Finish() { - auto o = flatbuffers::Offset<ArrayLong>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayLong> CreateArrayLong(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<int64_t>> value = 0) { - ArrayLongBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayLongBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<int64_t>> value) { fbb_.AddOffset(ArrayLong::VT_VALUE, value); } + ArrayLongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayLongBuilder &operator=(const ArrayLongBuilder &); + flatbuffers::Offset<ArrayLong> Finish() { + auto o = flatbuffers::Offset<ArrayLong>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayULong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayLong> CreateArrayLong(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<int64_t>> value = 0) { + ArrayLongBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayULong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<uint64_t> *value() const { return GetPointer<const flatbuffers::Vector<uint64_t> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<uint64_t> *value() const { return GetPointer<const flatbuffers::Vector<uint64_t> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayULongBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<uint64_t>> value) { fbb_.AddOffset(ArrayULong::VT_VALUE, value); } - ArrayULongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayULongBuilder &operator=(const ArrayULongBuilder &); - flatbuffers::Offset<ArrayULong> Finish() { - auto o = flatbuffers::Offset<ArrayULong>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayULong> CreateArrayULong(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<uint64_t>> value = 0) { - ArrayULongBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayULongBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<uint64_t>> value) { fbb_.AddOffset(ArrayULong::VT_VALUE, value); } + ArrayULongBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayULongBuilder &operator=(const ArrayULongBuilder &); + flatbuffers::Offset<ArrayULong> Finish() { + auto o = flatbuffers::Offset<ArrayULong>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayFloat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayULong> CreateArrayULong(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<uint64_t>> value = 0) { + ArrayULongBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayFloat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<float> *value() const { return GetPointer<const flatbuffers::Vector<float> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<float> *value() const { return GetPointer<const flatbuffers::Vector<float> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayFloatBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<float>> value) { fbb_.AddOffset(ArrayFloat::VT_VALUE, value); } - ArrayFloatBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayFloatBuilder &operator=(const ArrayFloatBuilder &); - flatbuffers::Offset<ArrayFloat> Finish() { - auto o = flatbuffers::Offset<ArrayFloat>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayFloat> CreateArrayFloat(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<float>> value = 0) { - ArrayFloatBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayFloatBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<float>> value) { fbb_.AddOffset(ArrayFloat::VT_VALUE, value); } + ArrayFloatBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayFloatBuilder &operator=(const ArrayFloatBuilder &); + flatbuffers::Offset<ArrayFloat> Finish() { + auto o = flatbuffers::Offset<ArrayFloat>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct ArrayDouble FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + inline flatbuffers::Offset<ArrayFloat> CreateArrayFloat(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<float>> value = 0) { + ArrayFloatBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct ArrayDouble FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<double> *value() const { return GetPointer<const flatbuffers::Vector<double> *>(VT_VALUE); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<double> *value() const { return GetPointer<const flatbuffers::Vector<double> *>(VT_VALUE); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; - -struct ArrayDoubleBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<double>> value) { fbb_.AddOffset(ArrayDouble::VT_VALUE, value); } - ArrayDoubleBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - ArrayDoubleBuilder &operator=(const ArrayDoubleBuilder &); - flatbuffers::Offset<ArrayDouble> Finish() { - auto o = flatbuffers::Offset<ArrayDouble>(fbb_.EndTable(start_, 1)); - return o; - } -}; -inline flatbuffers::Offset<ArrayDouble> CreateArrayDouble(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::Vector<double>> value = 0) { - ArrayDoubleBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + struct ArrayDoubleBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<double>> value) { fbb_.AddOffset(ArrayDouble::VT_VALUE, value); } + ArrayDoubleBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + ArrayDoubleBuilder &operator=(const ArrayDoubleBuilder &); + flatbuffers::Offset<ArrayDouble> Finish() { + auto o = flatbuffers::Offset<ArrayDouble>(fbb_.EndTable(start_, 1)); + return o; + } + }; -struct LogData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_SOURCE_NAME = 4, - VT_VALUE_TYPE = 6, - VT_VALUE = 8, - VT_TIMESTAMP = 10, - VT_FWDINFO_TYPE = 12, - VT_FWDINFO = 14 - }; - const flatbuffers::String *source_name() const { return GetPointer<const flatbuffers::String *>(VT_SOURCE_NAME); } - Value value_type() const { return static_cast<Value>(GetField<uint8_t>(VT_VALUE_TYPE, 0)); } - const void *value() const { return GetPointer<const void *>(VT_VALUE); } - uint64_t timestamp() const { return GetField<uint64_t>(VT_TIMESTAMP, 0); } - forwarder_internal fwdinfo_type() const { return static_cast<forwarder_internal>(GetField<uint8_t>(VT_FWDINFO_TYPE, 0)); } - const void *fwdinfo() const { return GetPointer<const void *>(VT_FWDINFO); } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_SOURCE_NAME) && - verifier.Verify(source_name()) && - VerifyField<uint8_t>(verifier, VT_VALUE_TYPE) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && - VerifyValue(verifier, value(), value_type()) && - VerifyField<uint64_t>(verifier, VT_TIMESTAMP) && - VerifyField<uint8_t>(verifier, VT_FWDINFO_TYPE) && - VerifyField<flatbuffers::uoffset_t>(verifier, VT_FWDINFO) && - Verifyforwarder_internal(verifier, fwdinfo(), fwdinfo_type()) && - verifier.EndTable(); - } -}; - -struct LogDataBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_source_name(flatbuffers::Offset<flatbuffers::String> source_name) { fbb_.AddOffset(LogData::VT_SOURCE_NAME, source_name); } - void add_value_type(Value value_type) { fbb_.AddElement<uint8_t>(LogData::VT_VALUE_TYPE, static_cast<uint8_t>(value_type), 0); } - void add_value(flatbuffers::Offset<void> value) { fbb_.AddOffset(LogData::VT_VALUE, value); } - void add_timestamp(uint64_t timestamp) { fbb_.AddElement<uint64_t>(LogData::VT_TIMESTAMP, timestamp, 0); } - void add_fwdinfo_type(forwarder_internal fwdinfo_type) { fbb_.AddElement<uint8_t>(LogData::VT_FWDINFO_TYPE, static_cast<uint8_t>(fwdinfo_type), 0); } - void add_fwdinfo(flatbuffers::Offset<void> fwdinfo) { fbb_.AddOffset(LogData::VT_FWDINFO, fwdinfo); } - LogDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } - LogDataBuilder &operator=(const LogDataBuilder &); - flatbuffers::Offset<LogData> Finish() { - auto o = flatbuffers::Offset<LogData>(fbb_.EndTable(start_, 6)); - return o; - } -}; - -inline flatbuffers::Offset<LogData> CreateLogData(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset<flatbuffers::String> source_name = 0, - Value value_type = Value_NONE, - flatbuffers::Offset<void> value = 0, - uint64_t timestamp = 0, - forwarder_internal fwdinfo_type = forwarder_internal_NONE, - flatbuffers::Offset<void> fwdinfo = 0) { - LogDataBuilder builder_(_fbb); - builder_.add_timestamp(timestamp); - builder_.add_fwdinfo(fwdinfo); - builder_.add_value(value); - builder_.add_source_name(source_name); - builder_.add_fwdinfo_type(fwdinfo_type); - builder_.add_value_type(value_type); - return builder_.Finish(); -} + inline flatbuffers::Offset<ArrayDouble> CreateArrayDouble(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<double>> value = 0) { + ArrayDoubleBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } + + struct LogData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_SOURCE_NAME = 4, + VT_VALUE_TYPE = 6, + VT_VALUE = 8, + VT_TIMESTAMP = 10, + VT_FWDINFO_TYPE = 12, + VT_FWDINFO = 14 + }; + const flatbuffers::String *source_name() const { return GetPointer<const flatbuffers::String *>(VT_SOURCE_NAME); } + Value value_type() const { return static_cast<Value>(GetField<uint8_t>(VT_VALUE_TYPE, 0)); } + const void *value() const { return GetPointer<const void *>(VT_VALUE); } + uint64_t timestamp() const { return GetField<uint64_t>(VT_TIMESTAMP, 0); } + forwarder_internal fwdinfo_type() const { return static_cast<forwarder_internal>(GetField<uint8_t>(VT_FWDINFO_TYPE, 0)); } + const void *fwdinfo() const { return GetPointer<const void *>(VT_FWDINFO); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_SOURCE_NAME) && + verifier.Verify(source_name()) && + VerifyField<uint8_t>(verifier, VT_VALUE_TYPE) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) && + VerifyValue(verifier, value(), value_type()) && + VerifyField<uint64_t>(verifier, VT_TIMESTAMP) && + VerifyField<uint8_t>(verifier, VT_FWDINFO_TYPE) && + VerifyField<flatbuffers::uoffset_t>(verifier, VT_FWDINFO) && + Verifyforwarder_internal(verifier, fwdinfo(), fwdinfo_type()) && + verifier.EndTable(); + } + }; -inline bool VerifyValue(flatbuffers::Verifier &verifier, const void *union_obj, Value type) { - switch (type) { + struct LogDataBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_source_name(flatbuffers::Offset<flatbuffers::String> source_name) { fbb_.AddOffset(LogData::VT_SOURCE_NAME, source_name); } + void add_value_type(Value value_type) { fbb_.AddElement<uint8_t>(LogData::VT_VALUE_TYPE, static_cast<uint8_t>(value_type), 0); } + void add_value(flatbuffers::Offset<void> value) { fbb_.AddOffset(LogData::VT_VALUE, value); } + void add_timestamp(uint64_t timestamp) { fbb_.AddElement<uint64_t>(LogData::VT_TIMESTAMP, timestamp, 0); } + void add_fwdinfo_type(forwarder_internal fwdinfo_type) { fbb_.AddElement<uint8_t>(LogData::VT_FWDINFO_TYPE, static_cast<uint8_t>(fwdinfo_type), 0); } + void add_fwdinfo(flatbuffers::Offset<void> fwdinfo) { fbb_.AddOffset(LogData::VT_FWDINFO, fwdinfo); } + LogDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + LogDataBuilder &operator=(const LogDataBuilder &); + flatbuffers::Offset<LogData> Finish() { + auto o = flatbuffers::Offset<LogData>(fbb_.EndTable(start_, 6)); + return o; + } + }; + + inline flatbuffers::Offset<LogData> CreateLogData(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::String> source_name = 0, + Value value_type = Value_NONE, + flatbuffers::Offset<void> value = 0, + uint64_t timestamp = 0, + forwarder_internal fwdinfo_type = forwarder_internal_NONE, + flatbuffers::Offset<void> fwdinfo = 0) { + LogDataBuilder builder_(_fbb); + builder_.add_timestamp(timestamp); + builder_.add_fwdinfo(fwdinfo); + builder_.add_value(value); + builder_.add_source_name(source_name); + builder_.add_fwdinfo_type(fwdinfo_type); + builder_.add_value_type(value_type); + return builder_.Finish(); + } + + inline bool VerifyValue(flatbuffers::Verifier &verifier, const void *union_obj, Value type) { + switch (type) { case Value_NONE: return true; case Value_Byte: return verifier.VerifyTable(reinterpret_cast<const Byte *>(union_obj)); case Value_UByte: return verifier.VerifyTable(reinterpret_cast<const UByte *>(union_obj)); @@ -792,19 +795,19 @@ inline bool VerifyValue(flatbuffers::Verifier &verifier, const void *union_obj, case Value_ArrayFloat: return verifier.VerifyTable(reinterpret_cast<const ArrayFloat *>(union_obj)); case Value_ArrayDouble: return verifier.VerifyTable(reinterpret_cast<const ArrayDouble *>(union_obj)); default: return false; + } } -} -inline const LogData *GetLogData(const void *buf) { return flatbuffers::GetRoot<LogData>(buf); } + inline const LogData *GetLogData(const void *buf) { return flatbuffers::GetRoot<LogData>(buf); } -inline bool VerifyLogDataBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<LogData>(); } + inline bool VerifyLogDataBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<LogData>(); } -inline const char *LogDataIdentifier() { return "f142"; } + inline const char *LogDataIdentifier() { return "f142"; } -inline bool LogDataBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, LogDataIdentifier()); } - -inline void FinishLogDataBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<LogData> root) { fbb.Finish(root, LogDataIdentifier()); } + inline bool LogDataBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, LogDataIdentifier()); } + inline void FinishLogDataBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<LogData> root) { fbb.Finish(root, LogDataIdentifier()); } +} #endif // FLATBUFFERS_GENERATED_F142LOGDATA_H_ // clang-format on diff --git a/Framework/LiveData/src/Kafka/private/Schema/hs00_event_histogram_generated.h b/Framework/LiveData/src/Kafka/private/Schema/hs00_event_histogram_generated.h index 3a55e3dcd53..5494b08e0c0 100644 --- a/Framework/LiveData/src/Kafka/private/Schema/hs00_event_histogram_generated.h +++ b/Framework/LiveData/src/Kafka/private/Schema/hs00_event_histogram_generated.h @@ -8,504 +8,508 @@ #include "flatbuffers/flatbuffers.h" -struct ArrayUInt; +/// Due to type conflicts with other schemas it was necessary to +/// add this namespace HistoSchema. +namespace HistoSchema { -struct ArrayULong; + struct ArrayUInt; -struct ArrayDouble; + struct ArrayULong; -struct DimensionMetaData; + struct ArrayDouble; -struct EventHistogram; + struct DimensionMetaData; -enum Array { - Array_NONE = 0, - Array_ArrayUInt = 1, - Array_ArrayULong = 2, - Array_ArrayDouble = 3, - Array_MIN = Array_NONE, - Array_MAX = Array_ArrayDouble -}; + struct EventHistogram; -inline const Array (&EnumValuesArray())[4] { - static const Array values[] = { - Array_NONE, - Array_ArrayUInt, - Array_ArrayULong, - Array_ArrayDouble + enum Array { + Array_NONE = 0, + Array_ArrayUInt = 1, + Array_ArrayULong = 2, + Array_ArrayDouble = 3, + Array_MIN = Array_NONE, + Array_MAX = Array_ArrayDouble }; - return values; -} -inline const char * const *EnumNamesArray() { - static const char * const names[] = { - "NONE", - "ArrayUInt", - "ArrayULong", - "ArrayDouble", - nullptr - }; - return names; -} + inline const Array(&EnumValuesArray())[4]{ + static const Array values[] = { + Array_NONE, + Array_ArrayUInt, + Array_ArrayULong, + Array_ArrayDouble + }; + return values; + } -inline const char *EnumNameArray(Array e) { - const size_t index = static_cast<int>(e); - return EnumNamesArray()[index]; -} + inline const char * const *EnumNamesArray() { + static const char * const names[] = { + "NONE", + "ArrayUInt", + "ArrayULong", + "ArrayDouble", + nullptr + }; + return names; + } -template<typename T> struct ArrayTraits { - static const Array enum_value = Array_NONE; -}; + inline const char *EnumNameArray(Array e) { + const size_t index = static_cast<int>(e); + return EnumNamesArray()[index]; + } + + template<typename T> struct ArrayTraits { + static const Array enum_value = Array_NONE; + }; -template<> struct ArrayTraits<ArrayUInt> { - static const Array enum_value = Array_ArrayUInt; -}; + template<> struct ArrayTraits<ArrayUInt> { + static const Array enum_value = Array_ArrayUInt; + }; -template<> struct ArrayTraits<ArrayULong> { - static const Array enum_value = Array_ArrayULong; -}; + template<> struct ArrayTraits<ArrayULong> { + static const Array enum_value = Array_ArrayULong; + }; -template<> struct ArrayTraits<ArrayDouble> { - static const Array enum_value = Array_ArrayDouble; -}; + template<> struct ArrayTraits<ArrayDouble> { + static const Array enum_value = Array_ArrayDouble; + }; -bool VerifyArray(flatbuffers::Verifier &verifier, const void *obj, Array type); -bool VerifyArrayVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types); + bool VerifyArray(flatbuffers::Verifier &verifier, const void *obj, Array type); + bool VerifyArrayVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types); -struct ArrayUInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + struct ArrayUInt FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<uint32_t> *value() const { + return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_VALUE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<uint32_t> *value() const { - return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_VALUE); - } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; -struct ArrayUIntBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> value) { - fbb_.AddOffset(ArrayUInt::VT_VALUE, value); - } - explicit ArrayUIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ArrayUIntBuilder &operator=(const ArrayUIntBuilder &); - flatbuffers::Offset<ArrayUInt> Finish() { - const auto end = fbb_.EndTable(start_); - auto o = flatbuffers::Offset<ArrayUInt>(end); - return o; - } -}; + struct ArrayUIntBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> value) { + fbb_.AddOffset(ArrayUInt::VT_VALUE, value); + } + explicit ArrayUIntBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ArrayUIntBuilder &operator=(const ArrayUIntBuilder &); + flatbuffers::Offset<ArrayUInt> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<ArrayUInt>(end); + return o; + } + }; -inline flatbuffers::Offset<ArrayUInt> CreateArrayUInt( + inline flatbuffers::Offset<ArrayUInt> CreateArrayUInt( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::Vector<uint32_t>> value = 0) { - ArrayUIntBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + ArrayUIntBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } -inline flatbuffers::Offset<ArrayUInt> CreateArrayUIntDirect( + inline flatbuffers::Offset<ArrayUInt> CreateArrayUIntDirect( flatbuffers::FlatBufferBuilder &_fbb, const std::vector<uint32_t> *value = nullptr) { - return CreateArrayUInt( + return CreateArrayUInt( _fbb, value ? _fbb.CreateVector<uint32_t>(*value) : 0); -} + } -struct ArrayULong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + struct ArrayULong FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<uint64_t> *value() const { + return GetPointer<const flatbuffers::Vector<uint64_t> *>(VT_VALUE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<uint64_t> *value() const { - return GetPointer<const flatbuffers::Vector<uint64_t> *>(VT_VALUE); - } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; -struct ArrayULongBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<uint64_t>> value) { - fbb_.AddOffset(ArrayULong::VT_VALUE, value); - } - explicit ArrayULongBuilder(flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ArrayULongBuilder &operator=(const ArrayULongBuilder &); - flatbuffers::Offset<ArrayULong> Finish() { - const auto end = fbb_.EndTable(start_); - auto o = flatbuffers::Offset<ArrayULong>(end); - return o; - } -}; + struct ArrayULongBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<uint64_t>> value) { + fbb_.AddOffset(ArrayULong::VT_VALUE, value); + } + explicit ArrayULongBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ArrayULongBuilder &operator=(const ArrayULongBuilder &); + flatbuffers::Offset<ArrayULong> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<ArrayULong>(end); + return o; + } + }; -inline flatbuffers::Offset<ArrayULong> CreateArrayULong( + inline flatbuffers::Offset<ArrayULong> CreateArrayULong( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::Vector<uint64_t>> value = 0) { - ArrayULongBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + ArrayULongBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } -inline flatbuffers::Offset<ArrayULong> CreateArrayULongDirect( + inline flatbuffers::Offset<ArrayULong> CreateArrayULongDirect( flatbuffers::FlatBufferBuilder &_fbb, const std::vector<uint64_t> *value = nullptr) { - return CreateArrayULong( + return CreateArrayULong( _fbb, value ? _fbb.CreateVector<uint64_t>(*value) : 0); -} + } -struct ArrayDouble FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_VALUE = 4 + struct ArrayDouble FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_VALUE = 4 + }; + const flatbuffers::Vector<double> *value() const { + return GetPointer<const flatbuffers::Vector<double> *>(VT_VALUE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } }; - const flatbuffers::Vector<double> *value() const { - return GetPointer<const flatbuffers::Vector<double> *>(VT_VALUE); - } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_VALUE) && - verifier.Verify(value()) && - verifier.EndTable(); - } -}; -struct ArrayDoubleBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_value(flatbuffers::Offset<flatbuffers::Vector<double>> value) { - fbb_.AddOffset(ArrayDouble::VT_VALUE, value); - } - explicit ArrayDoubleBuilder(flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ArrayDoubleBuilder &operator=(const ArrayDoubleBuilder &); - flatbuffers::Offset<ArrayDouble> Finish() { - const auto end = fbb_.EndTable(start_); - auto o = flatbuffers::Offset<ArrayDouble>(end); - return o; - } -}; + struct ArrayDoubleBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_value(flatbuffers::Offset<flatbuffers::Vector<double>> value) { + fbb_.AddOffset(ArrayDouble::VT_VALUE, value); + } + explicit ArrayDoubleBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ArrayDoubleBuilder &operator=(const ArrayDoubleBuilder &); + flatbuffers::Offset<ArrayDouble> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<ArrayDouble>(end); + return o; + } + }; -inline flatbuffers::Offset<ArrayDouble> CreateArrayDouble( + inline flatbuffers::Offset<ArrayDouble> CreateArrayDouble( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::Vector<double>> value = 0) { - ArrayDoubleBuilder builder_(_fbb); - builder_.add_value(value); - return builder_.Finish(); -} + ArrayDoubleBuilder builder_(_fbb); + builder_.add_value(value); + return builder_.Finish(); + } -inline flatbuffers::Offset<ArrayDouble> CreateArrayDoubleDirect( + inline flatbuffers::Offset<ArrayDouble> CreateArrayDoubleDirect( flatbuffers::FlatBufferBuilder &_fbb, const std::vector<double> *value = nullptr) { - return CreateArrayDouble( + return CreateArrayDouble( _fbb, value ? _fbb.CreateVector<double>(*value) : 0); -} - -struct DimensionMetaData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_LENGTH = 4, - VT_UNIT = 6, - VT_LABEL = 8, - VT_BIN_BOUNDARIES_TYPE = 10, - VT_BIN_BOUNDARIES = 12 - }; - uint32_t length() const { - return GetField<uint32_t>(VT_LENGTH, 0); - } - const flatbuffers::String *unit() const { - return GetPointer<const flatbuffers::String *>(VT_UNIT); - } - const flatbuffers::String *label() const { - return GetPointer<const flatbuffers::String *>(VT_LABEL); - } - Array bin_boundaries_type() const { - return static_cast<Array>(GetField<uint8_t>(VT_BIN_BOUNDARIES_TYPE, 0)); - } - const void *bin_boundaries() const { - return GetPointer<const void *>(VT_BIN_BOUNDARIES); - } - template<typename T> const T *bin_boundaries_as() const; - const ArrayUInt *bin_boundaries_as_ArrayUInt() const { - return bin_boundaries_type() == Array_ArrayUInt ? static_cast<const ArrayUInt *>(bin_boundaries()) : nullptr; } - const ArrayULong *bin_boundaries_as_ArrayULong() const { - return bin_boundaries_type() == Array_ArrayULong ? static_cast<const ArrayULong *>(bin_boundaries()) : nullptr; - } - const ArrayDouble *bin_boundaries_as_ArrayDouble() const { - return bin_boundaries_type() == Array_ArrayDouble ? static_cast<const ArrayDouble *>(bin_boundaries()) : nullptr; - } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField<uint32_t>(verifier, VT_LENGTH) && - VerifyOffset(verifier, VT_UNIT) && - verifier.Verify(unit()) && - VerifyOffset(verifier, VT_LABEL) && - verifier.Verify(label()) && - VerifyField<uint8_t>(verifier, VT_BIN_BOUNDARIES_TYPE) && - VerifyOffset(verifier, VT_BIN_BOUNDARIES) && - VerifyArray(verifier, bin_boundaries(), bin_boundaries_type()) && - verifier.EndTable(); - } -}; - -template<> inline const ArrayUInt *DimensionMetaData::bin_boundaries_as<ArrayUInt>() const { - return bin_boundaries_as_ArrayUInt(); -} -template<> inline const ArrayULong *DimensionMetaData::bin_boundaries_as<ArrayULong>() const { - return bin_boundaries_as_ArrayULong(); -} - -template<> inline const ArrayDouble *DimensionMetaData::bin_boundaries_as<ArrayDouble>() const { - return bin_boundaries_as_ArrayDouble(); -} + struct DimensionMetaData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_LENGTH = 4, + VT_UNIT = 6, + VT_LABEL = 8, + VT_BIN_BOUNDARIES_TYPE = 10, + VT_BIN_BOUNDARIES = 12 + }; + uint32_t length() const { + return GetField<uint32_t>(VT_LENGTH, 0); + } + const flatbuffers::String *unit() const { + return GetPointer<const flatbuffers::String *>(VT_UNIT); + } + const flatbuffers::String *label() const { + return GetPointer<const flatbuffers::String *>(VT_LABEL); + } + Array bin_boundaries_type() const { + return static_cast<Array>(GetField<uint8_t>(VT_BIN_BOUNDARIES_TYPE, 0)); + } + const void *bin_boundaries() const { + return GetPointer<const void *>(VT_BIN_BOUNDARIES); + } + template<typename T> const T *bin_boundaries_as() const; + const ArrayUInt *bin_boundaries_as_ArrayUInt() const { + return bin_boundaries_type() == Array_ArrayUInt ? static_cast<const ArrayUInt *>(bin_boundaries()) : nullptr; + } + const ArrayULong *bin_boundaries_as_ArrayULong() const { + return bin_boundaries_type() == Array_ArrayULong ? static_cast<const ArrayULong *>(bin_boundaries()) : nullptr; + } + const ArrayDouble *bin_boundaries_as_ArrayDouble() const { + return bin_boundaries_type() == Array_ArrayDouble ? static_cast<const ArrayDouble *>(bin_boundaries()) : nullptr; + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<uint32_t>(verifier, VT_LENGTH) && + VerifyOffset(verifier, VT_UNIT) && + verifier.Verify(unit()) && + VerifyOffset(verifier, VT_LABEL) && + verifier.Verify(label()) && + VerifyField<uint8_t>(verifier, VT_BIN_BOUNDARIES_TYPE) && + VerifyOffset(verifier, VT_BIN_BOUNDARIES) && + VerifyArray(verifier, bin_boundaries(), bin_boundaries_type()) && + verifier.EndTable(); + } + }; -struct DimensionMetaDataBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_length(uint32_t length) { - fbb_.AddElement<uint32_t>(DimensionMetaData::VT_LENGTH, length, 0); - } - void add_unit(flatbuffers::Offset<flatbuffers::String> unit) { - fbb_.AddOffset(DimensionMetaData::VT_UNIT, unit); - } - void add_label(flatbuffers::Offset<flatbuffers::String> label) { - fbb_.AddOffset(DimensionMetaData::VT_LABEL, label); - } - void add_bin_boundaries_type(Array bin_boundaries_type) { - fbb_.AddElement<uint8_t>(DimensionMetaData::VT_BIN_BOUNDARIES_TYPE, static_cast<uint8_t>(bin_boundaries_type), 0); - } - void add_bin_boundaries(flatbuffers::Offset<void> bin_boundaries) { - fbb_.AddOffset(DimensionMetaData::VT_BIN_BOUNDARIES, bin_boundaries); + template<> inline const ArrayUInt *DimensionMetaData::bin_boundaries_as<ArrayUInt>() const { + return bin_boundaries_as_ArrayUInt(); } - explicit DimensionMetaDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); + + template<> inline const ArrayULong *DimensionMetaData::bin_boundaries_as<ArrayULong>() const { + return bin_boundaries_as_ArrayULong(); } - DimensionMetaDataBuilder &operator=(const DimensionMetaDataBuilder &); - flatbuffers::Offset<DimensionMetaData> Finish() { - const auto end = fbb_.EndTable(start_); - auto o = flatbuffers::Offset<DimensionMetaData>(end); - return o; + + template<> inline const ArrayDouble *DimensionMetaData::bin_boundaries_as<ArrayDouble>() const { + return bin_boundaries_as_ArrayDouble(); } -}; -inline flatbuffers::Offset<DimensionMetaData> CreateDimensionMetaData( + struct DimensionMetaDataBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_length(uint32_t length) { + fbb_.AddElement<uint32_t>(DimensionMetaData::VT_LENGTH, length, 0); + } + void add_unit(flatbuffers::Offset<flatbuffers::String> unit) { + fbb_.AddOffset(DimensionMetaData::VT_UNIT, unit); + } + void add_label(flatbuffers::Offset<flatbuffers::String> label) { + fbb_.AddOffset(DimensionMetaData::VT_LABEL, label); + } + void add_bin_boundaries_type(Array bin_boundaries_type) { + fbb_.AddElement<uint8_t>(DimensionMetaData::VT_BIN_BOUNDARIES_TYPE, static_cast<uint8_t>(bin_boundaries_type), 0); + } + void add_bin_boundaries(flatbuffers::Offset<void> bin_boundaries) { + fbb_.AddOffset(DimensionMetaData::VT_BIN_BOUNDARIES, bin_boundaries); + } + explicit DimensionMetaDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + DimensionMetaDataBuilder &operator=(const DimensionMetaDataBuilder &); + flatbuffers::Offset<DimensionMetaData> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<DimensionMetaData>(end); + return o; + } + }; + + inline flatbuffers::Offset<DimensionMetaData> CreateDimensionMetaData( flatbuffers::FlatBufferBuilder &_fbb, uint32_t length = 0, flatbuffers::Offset<flatbuffers::String> unit = 0, flatbuffers::Offset<flatbuffers::String> label = 0, Array bin_boundaries_type = Array_NONE, flatbuffers::Offset<void> bin_boundaries = 0) { - DimensionMetaDataBuilder builder_(_fbb); - builder_.add_bin_boundaries(bin_boundaries); - builder_.add_label(label); - builder_.add_unit(unit); - builder_.add_length(length); - builder_.add_bin_boundaries_type(bin_boundaries_type); - return builder_.Finish(); -} + DimensionMetaDataBuilder builder_(_fbb); + builder_.add_bin_boundaries(bin_boundaries); + builder_.add_label(label); + builder_.add_unit(unit); + builder_.add_length(length); + builder_.add_bin_boundaries_type(bin_boundaries_type); + return builder_.Finish(); + } -inline flatbuffers::Offset<DimensionMetaData> CreateDimensionMetaDataDirect( + inline flatbuffers::Offset<DimensionMetaData> CreateDimensionMetaDataDirect( flatbuffers::FlatBufferBuilder &_fbb, uint32_t length = 0, const char *unit = nullptr, const char *label = nullptr, Array bin_boundaries_type = Array_NONE, flatbuffers::Offset<void> bin_boundaries = 0) { - return CreateDimensionMetaData( + return CreateDimensionMetaData( _fbb, length, unit ? _fbb.CreateString(unit) : 0, label ? _fbb.CreateString(label) : 0, bin_boundaries_type, bin_boundaries); -} + } -struct EventHistogram FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { - VT_SOURCE = 4, - VT_TIMESTAMP = 6, - VT_DIM_METADATA = 8, - VT_LAST_METADATA_TIMESTAMP = 10, - VT_CURRENT_SHAPE = 12, - VT_OFFSET = 14, - VT_DATA_TYPE = 16, - VT_DATA = 18, - VT_ERRORS_TYPE = 20, - VT_ERRORS = 22, - VT_INFO = 24 + struct EventHistogram FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_SOURCE = 4, + VT_TIMESTAMP = 6, + VT_DIM_METADATA = 8, + VT_LAST_METADATA_TIMESTAMP = 10, + VT_CURRENT_SHAPE = 12, + VT_OFFSET = 14, + VT_DATA_TYPE = 16, + VT_DATA = 18, + VT_ERRORS_TYPE = 20, + VT_ERRORS = 22, + VT_INFO = 24 + }; + const flatbuffers::String *source() const { + return GetPointer<const flatbuffers::String *>(VT_SOURCE); + } + uint64_t timestamp() const { + return GetField<uint64_t>(VT_TIMESTAMP, 0); + } + const flatbuffers::Vector<flatbuffers::Offset<DimensionMetaData>> *dim_metadata() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<DimensionMetaData>> *>(VT_DIM_METADATA); + } + uint64_t last_metadata_timestamp() const { + return GetField<uint64_t>(VT_LAST_METADATA_TIMESTAMP, 0); + } + const flatbuffers::Vector<uint32_t> *current_shape() const { + return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_CURRENT_SHAPE); + } + const flatbuffers::Vector<uint32_t> *offset() const { + return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_OFFSET); + } + Array data_type() const { + return static_cast<Array>(GetField<uint8_t>(VT_DATA_TYPE, 0)); + } + const void *data() const { + return GetPointer<const void *>(VT_DATA); + } + template<typename T> const T *data_as() const; + const ArrayUInt *data_as_ArrayUInt() const { + return data_type() == Array_ArrayUInt ? static_cast<const ArrayUInt *>(data()) : nullptr; + } + const ArrayULong *data_as_ArrayULong() const { + return data_type() == Array_ArrayULong ? static_cast<const ArrayULong *>(data()) : nullptr; + } + const ArrayDouble *data_as_ArrayDouble() const { + return data_type() == Array_ArrayDouble ? static_cast<const ArrayDouble *>(data()) : nullptr; + } + Array errors_type() const { + return static_cast<Array>(GetField<uint8_t>(VT_ERRORS_TYPE, 0)); + } + const void *errors() const { + return GetPointer<const void *>(VT_ERRORS); + } + template<typename T> const T *errors_as() const; + const ArrayUInt *errors_as_ArrayUInt() const { + return errors_type() == Array_ArrayUInt ? static_cast<const ArrayUInt *>(errors()) : nullptr; + } + const ArrayULong *errors_as_ArrayULong() const { + return errors_type() == Array_ArrayULong ? static_cast<const ArrayULong *>(errors()) : nullptr; + } + const ArrayDouble *errors_as_ArrayDouble() const { + return errors_type() == Array_ArrayDouble ? static_cast<const ArrayDouble *>(errors()) : nullptr; + } + const flatbuffers::String *info() const { + return GetPointer<const flatbuffers::String *>(VT_INFO); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_SOURCE) && + verifier.Verify(source()) && + VerifyField<uint64_t>(verifier, VT_TIMESTAMP) && + VerifyOffset(verifier, VT_DIM_METADATA) && + verifier.Verify(dim_metadata()) && + verifier.VerifyVectorOfTables(dim_metadata()) && + VerifyField<uint64_t>(verifier, VT_LAST_METADATA_TIMESTAMP) && + VerifyOffsetRequired(verifier, VT_CURRENT_SHAPE) && + verifier.Verify(current_shape()) && + VerifyOffset(verifier, VT_OFFSET) && + verifier.Verify(offset()) && + VerifyField<uint8_t>(verifier, VT_DATA_TYPE) && + VerifyOffset(verifier, VT_DATA) && + VerifyArray(verifier, data(), data_type()) && + VerifyField<uint8_t>(verifier, VT_ERRORS_TYPE) && + VerifyOffset(verifier, VT_ERRORS) && + VerifyArray(verifier, errors(), errors_type()) && + VerifyOffset(verifier, VT_INFO) && + verifier.Verify(info()) && + verifier.EndTable(); + } }; - const flatbuffers::String *source() const { - return GetPointer<const flatbuffers::String *>(VT_SOURCE); - } - uint64_t timestamp() const { - return GetField<uint64_t>(VT_TIMESTAMP, 0); - } - const flatbuffers::Vector<flatbuffers::Offset<DimensionMetaData>> *dim_metadata() const { - return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<DimensionMetaData>> *>(VT_DIM_METADATA); - } - uint64_t last_metadata_timestamp() const { - return GetField<uint64_t>(VT_LAST_METADATA_TIMESTAMP, 0); - } - const flatbuffers::Vector<uint32_t> *current_shape() const { - return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_CURRENT_SHAPE); - } - const flatbuffers::Vector<uint32_t> *offset() const { - return GetPointer<const flatbuffers::Vector<uint32_t> *>(VT_OFFSET); - } - Array data_type() const { - return static_cast<Array>(GetField<uint8_t>(VT_DATA_TYPE, 0)); - } - const void *data() const { - return GetPointer<const void *>(VT_DATA); - } - template<typename T> const T *data_as() const; - const ArrayUInt *data_as_ArrayUInt() const { - return data_type() == Array_ArrayUInt ? static_cast<const ArrayUInt *>(data()) : nullptr; - } - const ArrayULong *data_as_ArrayULong() const { - return data_type() == Array_ArrayULong ? static_cast<const ArrayULong *>(data()) : nullptr; - } - const ArrayDouble *data_as_ArrayDouble() const { - return data_type() == Array_ArrayDouble ? static_cast<const ArrayDouble *>(data()) : nullptr; - } - Array errors_type() const { - return static_cast<Array>(GetField<uint8_t>(VT_ERRORS_TYPE, 0)); - } - const void *errors() const { - return GetPointer<const void *>(VT_ERRORS); - } - template<typename T> const T *errors_as() const; - const ArrayUInt *errors_as_ArrayUInt() const { - return errors_type() == Array_ArrayUInt ? static_cast<const ArrayUInt *>(errors()) : nullptr; - } - const ArrayULong *errors_as_ArrayULong() const { - return errors_type() == Array_ArrayULong ? static_cast<const ArrayULong *>(errors()) : nullptr; - } - const ArrayDouble *errors_as_ArrayDouble() const { - return errors_type() == Array_ArrayDouble ? static_cast<const ArrayDouble *>(errors()) : nullptr; - } - const flatbuffers::String *info() const { - return GetPointer<const flatbuffers::String *>(VT_INFO); - } - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_SOURCE) && - verifier.Verify(source()) && - VerifyField<uint64_t>(verifier, VT_TIMESTAMP) && - VerifyOffset(verifier, VT_DIM_METADATA) && - verifier.Verify(dim_metadata()) && - verifier.VerifyVectorOfTables(dim_metadata()) && - VerifyField<uint64_t>(verifier, VT_LAST_METADATA_TIMESTAMP) && - VerifyOffsetRequired(verifier, VT_CURRENT_SHAPE) && - verifier.Verify(current_shape()) && - VerifyOffset(verifier, VT_OFFSET) && - verifier.Verify(offset()) && - VerifyField<uint8_t>(verifier, VT_DATA_TYPE) && - VerifyOffset(verifier, VT_DATA) && - VerifyArray(verifier, data(), data_type()) && - VerifyField<uint8_t>(verifier, VT_ERRORS_TYPE) && - VerifyOffset(verifier, VT_ERRORS) && - VerifyArray(verifier, errors(), errors_type()) && - VerifyOffset(verifier, VT_INFO) && - verifier.Verify(info()) && - verifier.EndTable(); - } -}; - -template<> inline const ArrayUInt *EventHistogram::data_as<ArrayUInt>() const { - return data_as_ArrayUInt(); -} - -template<> inline const ArrayULong *EventHistogram::data_as<ArrayULong>() const { - return data_as_ArrayULong(); -} - -template<> inline const ArrayDouble *EventHistogram::data_as<ArrayDouble>() const { - return data_as_ArrayDouble(); -} - -template<> inline const ArrayUInt *EventHistogram::errors_as<ArrayUInt>() const { - return errors_as_ArrayUInt(); -} - -template<> inline const ArrayULong *EventHistogram::errors_as<ArrayULong>() const { - return errors_as_ArrayULong(); -} -template<> inline const ArrayDouble *EventHistogram::errors_as<ArrayDouble>() const { - return errors_as_ArrayDouble(); -} - -struct EventHistogramBuilder { - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - void add_source(flatbuffers::Offset<flatbuffers::String> source) { - fbb_.AddOffset(EventHistogram::VT_SOURCE, source); - } - void add_timestamp(uint64_t timestamp) { - fbb_.AddElement<uint64_t>(EventHistogram::VT_TIMESTAMP, timestamp, 0); - } - void add_dim_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<DimensionMetaData>>> dim_metadata) { - fbb_.AddOffset(EventHistogram::VT_DIM_METADATA, dim_metadata); - } - void add_last_metadata_timestamp(uint64_t last_metadata_timestamp) { - fbb_.AddElement<uint64_t>(EventHistogram::VT_LAST_METADATA_TIMESTAMP, last_metadata_timestamp, 0); - } - void add_current_shape(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> current_shape) { - fbb_.AddOffset(EventHistogram::VT_CURRENT_SHAPE, current_shape); - } - void add_offset(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> offset) { - fbb_.AddOffset(EventHistogram::VT_OFFSET, offset); - } - void add_data_type(Array data_type) { - fbb_.AddElement<uint8_t>(EventHistogram::VT_DATA_TYPE, static_cast<uint8_t>(data_type), 0); + template<> inline const ArrayUInt *EventHistogram::data_as<ArrayUInt>() const { + return data_as_ArrayUInt(); } - void add_data(flatbuffers::Offset<void> data) { - fbb_.AddOffset(EventHistogram::VT_DATA, data); - } - void add_errors_type(Array errors_type) { - fbb_.AddElement<uint8_t>(EventHistogram::VT_ERRORS_TYPE, static_cast<uint8_t>(errors_type), 0); + + template<> inline const ArrayULong *EventHistogram::data_as<ArrayULong>() const { + return data_as_ArrayULong(); } - void add_errors(flatbuffers::Offset<void> errors) { - fbb_.AddOffset(EventHistogram::VT_ERRORS, errors); + + template<> inline const ArrayDouble *EventHistogram::data_as<ArrayDouble>() const { + return data_as_ArrayDouble(); } - void add_info(flatbuffers::Offset<flatbuffers::String> info) { - fbb_.AddOffset(EventHistogram::VT_INFO, info); + + template<> inline const ArrayUInt *EventHistogram::errors_as<ArrayUInt>() const { + return errors_as_ArrayUInt(); } - explicit EventHistogramBuilder(flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); + + template<> inline const ArrayULong *EventHistogram::errors_as<ArrayULong>() const { + return errors_as_ArrayULong(); } - EventHistogramBuilder &operator=(const EventHistogramBuilder &); - flatbuffers::Offset<EventHistogram> Finish() { - const auto end = fbb_.EndTable(start_); - auto o = flatbuffers::Offset<EventHistogram>(end); - fbb_.Required(o, EventHistogram::VT_CURRENT_SHAPE); - return o; + + template<> inline const ArrayDouble *EventHistogram::errors_as<ArrayDouble>() const { + return errors_as_ArrayDouble(); } -}; -inline flatbuffers::Offset<EventHistogram> CreateEventHistogram( + struct EventHistogramBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_source(flatbuffers::Offset<flatbuffers::String> source) { + fbb_.AddOffset(EventHistogram::VT_SOURCE, source); + } + void add_timestamp(uint64_t timestamp) { + fbb_.AddElement<uint64_t>(EventHistogram::VT_TIMESTAMP, timestamp, 0); + } + void add_dim_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<DimensionMetaData>>> dim_metadata) { + fbb_.AddOffset(EventHistogram::VT_DIM_METADATA, dim_metadata); + } + void add_last_metadata_timestamp(uint64_t last_metadata_timestamp) { + fbb_.AddElement<uint64_t>(EventHistogram::VT_LAST_METADATA_TIMESTAMP, last_metadata_timestamp, 0); + } + void add_current_shape(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> current_shape) { + fbb_.AddOffset(EventHistogram::VT_CURRENT_SHAPE, current_shape); + } + void add_offset(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> offset) { + fbb_.AddOffset(EventHistogram::VT_OFFSET, offset); + } + void add_data_type(Array data_type) { + fbb_.AddElement<uint8_t>(EventHistogram::VT_DATA_TYPE, static_cast<uint8_t>(data_type), 0); + } + void add_data(flatbuffers::Offset<void> data) { + fbb_.AddOffset(EventHistogram::VT_DATA, data); + } + void add_errors_type(Array errors_type) { + fbb_.AddElement<uint8_t>(EventHistogram::VT_ERRORS_TYPE, static_cast<uint8_t>(errors_type), 0); + } + void add_errors(flatbuffers::Offset<void> errors) { + fbb_.AddOffset(EventHistogram::VT_ERRORS, errors); + } + void add_info(flatbuffers::Offset<flatbuffers::String> info) { + fbb_.AddOffset(EventHistogram::VT_INFO, info); + } + explicit EventHistogramBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + EventHistogramBuilder &operator=(const EventHistogramBuilder &); + flatbuffers::Offset<EventHistogram> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<EventHistogram>(end); + fbb_.Required(o, EventHistogram::VT_CURRENT_SHAPE); + return o; + } + }; + + inline flatbuffers::Offset<EventHistogram> CreateEventHistogram( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> source = 0, uint64_t timestamp = 0, @@ -518,22 +522,22 @@ inline flatbuffers::Offset<EventHistogram> CreateEventHistogram( Array errors_type = Array_NONE, flatbuffers::Offset<void> errors = 0, flatbuffers::Offset<flatbuffers::String> info = 0) { - EventHistogramBuilder builder_(_fbb); - builder_.add_last_metadata_timestamp(last_metadata_timestamp); - builder_.add_timestamp(timestamp); - builder_.add_info(info); - builder_.add_errors(errors); - builder_.add_data(data); - builder_.add_offset(offset); - builder_.add_current_shape(current_shape); - builder_.add_dim_metadata(dim_metadata); - builder_.add_source(source); - builder_.add_errors_type(errors_type); - builder_.add_data_type(data_type); - return builder_.Finish(); -} - -inline flatbuffers::Offset<EventHistogram> CreateEventHistogramDirect( + EventHistogramBuilder builder_(_fbb); + builder_.add_last_metadata_timestamp(last_metadata_timestamp); + builder_.add_timestamp(timestamp); + builder_.add_info(info); + builder_.add_errors(errors); + builder_.add_data(data); + builder_.add_offset(offset); + builder_.add_current_shape(current_shape); + builder_.add_dim_metadata(dim_metadata); + builder_.add_source(source); + builder_.add_errors_type(errors_type); + builder_.add_data_type(data_type); + return builder_.Finish(); + } + + inline flatbuffers::Offset<EventHistogram> CreateEventHistogramDirect( flatbuffers::FlatBufferBuilder &_fbb, const char *source = nullptr, uint64_t timestamp = 0, @@ -546,7 +550,7 @@ inline flatbuffers::Offset<EventHistogram> CreateEventHistogramDirect( Array errors_type = Array_NONE, flatbuffers::Offset<void> errors = 0, const char *info = nullptr) { - return CreateEventHistogram( + return CreateEventHistogram( _fbb, source ? _fbb.CreateString(source) : 0, timestamp, @@ -559,10 +563,10 @@ inline flatbuffers::Offset<EventHistogram> CreateEventHistogramDirect( errors_type, errors, info ? _fbb.CreateString(info) : 0); -} + } -inline bool VerifyArray(flatbuffers::Verifier &verifier, const void *obj, Array type) { - switch (type) { + inline bool VerifyArray(flatbuffers::Verifier &verifier, const void *obj, Array type) { + switch (type) { case Array_NONE: { return true; } @@ -579,59 +583,60 @@ inline bool VerifyArray(flatbuffers::Verifier &verifier, const void *obj, Array return verifier.VerifyTable(ptr); } default: return false; + } } -} -inline bool VerifyArrayVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) { - if (!values || !types) return !values && !types; - if (values->size() != types->size()) return false; - for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { - if (!VerifyArray( - verifier, values->Get(i), types->GetEnum<Array>(i))) { - return false; + inline bool VerifyArrayVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifyArray( + verifier, values->Get(i), types->GetEnum<Array>(i))) { + return false; + } } + return true; } - return true; -} -inline const EventHistogram *GetEventHistogram(const void *buf) { - return flatbuffers::GetRoot<EventHistogram>(buf); -} + inline const EventHistogram *GetEventHistogram(const void *buf) { + return flatbuffers::GetRoot<EventHistogram>(buf); + } -inline const EventHistogram *GetSizePrefixedEventHistogram(const void *buf) { - return flatbuffers::GetSizePrefixedRoot<EventHistogram>(buf); -} + inline const EventHistogram *GetSizePrefixedEventHistogram(const void *buf) { + return flatbuffers::GetSizePrefixedRoot<EventHistogram>(buf); + } -inline const char *EventHistogramIdentifier() { - return "hs00"; -} + inline const char *EventHistogramIdentifier() { + return "hs00"; + } -inline bool EventHistogramBufferHasIdentifier(const void *buf) { - return flatbuffers::BufferHasIdentifier( + inline bool EventHistogramBufferHasIdentifier(const void *buf) { + return flatbuffers::BufferHasIdentifier( buf, EventHistogramIdentifier()); -} + } -inline bool VerifyEventHistogramBuffer( + inline bool VerifyEventHistogramBuffer( flatbuffers::Verifier &verifier) { - return verifier.VerifyBuffer<EventHistogram>(EventHistogramIdentifier()); -} + return verifier.VerifyBuffer<EventHistogram>(EventHistogramIdentifier()); + } -inline bool VerifySizePrefixedEventHistogramBuffer( + inline bool VerifySizePrefixedEventHistogramBuffer( flatbuffers::Verifier &verifier) { - return verifier.VerifySizePrefixedBuffer<EventHistogram>(EventHistogramIdentifier()); -} + return verifier.VerifySizePrefixedBuffer<EventHistogram>(EventHistogramIdentifier()); + } -inline void FinishEventHistogramBuffer( + inline void FinishEventHistogramBuffer( flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<EventHistogram> root) { - fbb.Finish(root, EventHistogramIdentifier()); -} + fbb.Finish(root, EventHistogramIdentifier()); + } -inline void FinishSizePrefixedEventHistogramBuffer( + inline void FinishSizePrefixedEventHistogramBuffer( flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<EventHistogram> root) { - fbb.FinishSizePrefixed(root, EventHistogramIdentifier()); -} + fbb.FinishSizePrefixed(root, EventHistogramIdentifier()); + } +} #endif // FLATBUFFERS_GENERATED_HS00EVENTHISTOGRAM_H_ // clang-format on diff --git a/Framework/LiveData/test/KafkaHistoStreamDecoderTest.h b/Framework/LiveData/test/KafkaHistoStreamDecoderTest.h new file mode 100644 index 00000000000..d23e084e3ce --- /dev/null +++ b/Framework/LiveData/test/KafkaHistoStreamDecoderTest.h @@ -0,0 +1,189 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#ifndef MANTID_LIVEDATA_KAFKAHISTOSTREAMDECODERTEST_H_ +#define MANTID_LIVEDATA_KAFKAHISTOSTREAMDECODERTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "KafkaTesting.h" +#include "MantidAPI/Run.h" +#include "MantidGeometry/Instrument.h" +#include "MantidHistogramData/FixedLengthVector.h" +#include "MantidHistogramData/HistogramX.h" +#include "MantidHistogramData/HistogramY.h" +#include "MantidKernel/ConfigService.h" +#include "MantidKernel/TimeSeriesProperty.h" +#include "MantidKernel/make_unique.h" +#include "MantidLiveData/Kafka/KafkaHistoStreamDecoder.h" +#include <Poco/Path.h> + +using Mantid::LiveData::KafkaHistoStreamDecoder; +using namespace KafkaTesting; + +class KafkaHistoStreamDecoderTest : public CxxTest::TestSuite { +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static KafkaHistoStreamDecoderTest *createSuite() { + return new KafkaHistoStreamDecoderTest(); + } + static void destroySuite(KafkaHistoStreamDecoderTest *suite) { delete suite; } + + void setUp() override { + // Temporarily change the instrument directory to the testing one + using Mantid::Kernel::ConfigService; + auto &config = ConfigService::Instance(); + auto baseInstDir = config.getInstrumentDirectory(); + Poco::Path testFile = + Poco::Path(baseInstDir) + .resolve("IDFs_for_UNIT_TESTING/UnitTestFacilities.xml"); + // Load the test facilities file + config.updateFacilities(testFile.toString()); + config.setFacility("TEST"); + // Update instrument search directory + config.setString("instrumentDefinition.directory", + baseInstDir + "/IDFs_for_UNIT_TESTING"); + } + + void tearDown() override { + using Mantid::Kernel::ConfigService; + auto &config = ConfigService::Instance(); + config.reset(); + // Restore the main facilities file + config.updateFacilities(); + } + + void test_Histo_Stream() { + using namespace ::testing; + using namespace KafkaTesting; + using Mantid::API::Workspace_sptr; + using Mantid::DataObjects::Workspace2D; + using namespace Mantid::LiveData; + + auto mockBroker = std::make_shared<MockKafkaBroker>(); + EXPECT_CALL(*mockBroker, subscribe_(_, _)) + .Times(Exactly(3)) + .WillOnce(Return(new FakeHistoSubscriber())) + .WillOnce(Return(new FakeRunInfoStreamSubscriber(1))) + .WillOnce(Return(new FakeISISSpDetStreamSubscriber)); + auto decoder = createTestDecoder(mockBroker); + TSM_ASSERT("Decoder should not have create data buffers yet", + !decoder->hasData()); + startCapturing(*decoder, 1); + + // Checks + Workspace_sptr workspace; + TSM_ASSERT("Decoder's data buffers should be created now", + decoder->hasData()); + TS_ASSERT_THROWS_NOTHING(workspace = decoder->extractData()); + TS_ASSERT_THROWS_NOTHING(decoder->stopCapture()); + TS_ASSERT(!decoder->isCapturing()); + + // -- Workspace checks -- + TSM_ASSERT("Expected non-null workspace pointer from extractData()", + workspace); + auto histoWksp = boost::dynamic_pointer_cast<Workspace2D>(workspace); + TSM_ASSERT( + "Expected a Workspace2D from extractData(). Found something else", + histoWksp); + checkWorkspaceMetadata(*histoWksp); + checkWorkspaceHistoData(*histoWksp); + } + +private: + std::unique_ptr<Mantid::LiveData::KafkaHistoStreamDecoder> + createTestDecoder(std::shared_ptr<Mantid::LiveData::IKafkaBroker> broker) { + using namespace Mantid::LiveData; + return Mantid::Kernel::make_unique<KafkaHistoStreamDecoder>(broker, "", "", + "", ""); + } + + // Start decoding and wait until we have gathered enough data to test + void startCapturing(Mantid::LiveData::KafkaHistoStreamDecoder &decoder, + uint8_t maxIterations) { + // Register callback to know when a whole loop as been iterated through + m_niterations = 0; + auto callback = [this, maxIterations]() { + this->iterationCallback(maxIterations); + }; + decoder.registerIterationEndCb(callback); + decoder.registerErrorCb(callback); + TS_ASSERT_THROWS_NOTHING(decoder.startCapture()); + continueCapturing(decoder, maxIterations); + } + + void iterationCallback(uint8_t maxIterations) { + std::unique_lock<std::mutex> lock(this->m_callbackMutex); + this->m_niterations++; + if (this->m_niterations == maxIterations) { + lock.unlock(); + this->m_callbackCondition.notify_one(); + } + } + + void continueCapturing(Mantid::LiveData::KafkaHistoStreamDecoder &decoder, + uint8_t maxIterations) { + // Re-register callback with the (potentially) new value of maxIterations + auto callback = [this, maxIterations]() { + this->iterationCallback(maxIterations); + }; + decoder.registerIterationEndCb(callback); + decoder.registerErrorCb(callback); + { + std::unique_lock<std::mutex> lk(m_callbackMutex); + this->m_callbackCondition.wait(lk, [this, maxIterations]() { + return this->m_niterations == maxIterations; + }); + } + } + + void + checkWorkspaceMetadata(const Mantid::DataObjects::Workspace2D &histoWksp) { + TS_ASSERT(histoWksp.getInstrument()); + TS_ASSERT_EQUALS("HRPDTEST", histoWksp.getInstrument()->getName()); + TS_ASSERT_EQUALS( + "2016-08-31T12:07:42", + histoWksp.run().getPropertyValueAsType<std::string>("run_start")); + std::array<Mantid::specnum_t, 5> specs = {{1, 2, 3, 4, 5}}; + std::array<Mantid::detid_t, 5> ids = {{1001, 1002, 1100, 901000, 10100}}; + TS_ASSERT_EQUALS(specs.size(), histoWksp.getNumberHistograms()); + for (size_t i = 0; i < histoWksp.getNumberHistograms(); ++i) { + const auto &spec = histoWksp.getSpectrum(i); + TS_ASSERT_EQUALS(specs[i], spec.getSpectrumNo()); + const auto &sid = spec.getDetectorIDs(); + TS_ASSERT_EQUALS(ids[i], *(sid.begin())); + } + } + + void + checkWorkspaceHistoData(const Mantid::DataObjects::Workspace2D &histoWksp) { + // Inspect all 5 HRPDTEST Spectra + auto data = histoWksp.histogram(0); + // std::vector<double> xbins(data.x().cbegin(), data.x().cend()); + TS_ASSERT_EQUALS(data.x().rawData(), (std::vector<double>{0, 1, 2})); + TS_ASSERT_EQUALS(data.y().rawData(), (std::vector<double>{100, 140})); + + data = histoWksp.histogram(1); + TS_ASSERT_EQUALS(data.y().rawData(), (std::vector<double>{210, 100})); + + data = histoWksp.histogram(2); + TS_ASSERT_EQUALS(data.y().rawData(), (std::vector<double>{110, 70})); + + data = histoWksp.histogram(3); + TS_ASSERT_EQUALS(data.y().rawData(), (std::vector<double>{5, 3})); + + data = histoWksp.histogram(4); + TS_ASSERT_EQUALS(data.y().rawData(), (std::vector<double>{20, 4})); + } + +private: + std::mutex m_callbackMutex; + std::condition_variable m_callbackCondition; + uint8_t m_niterations = 0; +}; + +#endif /* MANTID_LIVEDATA_KAFKAHISTOSTREAMDECODERTEST_H_ */ \ No newline at end of file diff --git a/Framework/LiveData/test/KafkaTesting.h b/Framework/LiveData/test/KafkaTesting.h index 5b470219653..b8fec70e8a6 100644 --- a/Framework/LiveData/test/KafkaTesting.h +++ b/Framework/LiveData/test/KafkaTesting.h @@ -20,6 +20,7 @@ GNU_DIAG_OFF("conversion") #include "Kafka/private/Schema/ev42_events_generated.h" #include "Kafka/private/Schema/f142_logdata_generated.h" #include "Kafka/private/Schema/is84_isis_events_generated.h" +#include "kafka/private/Schema/hs00_event_histogram_generated.h" GNU_DIAG_ON("conversion") #include <ctime> @@ -134,6 +135,7 @@ public: } }; +namespace { void fakeReceiveAnISISEventMessage(std::string *buffer, int32_t nextPeriod) { flatbuffers::FlatBufferBuilder builder; std::vector<uint32_t> spec = {5, 4, 3, 2, 1, 2}; @@ -172,12 +174,43 @@ void fakeReceiveAnEventMessage(std::string *buffer) { builder.GetSize()); } +void fakeReceiveHistoMessage(std::string *buffer) { + flatbuffers::FlatBufferBuilder builder; + // shape is binedges=2 nspectra=5 + std::vector<uint32_t> current_shape{3, 5}; + auto bin_edges = builder.CreateVector(std::vector<double>{0, 1, 2}); + auto xbins = HistoSchema::CreateArrayDouble(builder, bin_edges); + auto bin_metadata = HistoSchema::CreateDimensionMetaData( + builder, 3, builder.CreateString("TOF"), builder.CreateString("TOF"), + HistoSchema::Array_ArrayDouble, xbins.Union()); + auto unit_metadata = HistoSchema::CreateDimensionMetaData( + builder, 1, builder.CreateString("Counts")); + + auto dim_metadata = builder.CreateVector( + std::vector<flatbuffers::Offset<HistoSchema::DimensionMetaData>>{ + bin_metadata, unit_metadata}); + + // Data values are nspectra*nbins + auto data_values = builder.CreateVector( + std::vector<double>{100, 140, 210, 100, 110, 70, 5, 3, 20, 4}); + auto data = HistoSchema::CreateArrayDouble(builder, data_values); + + auto messageFlatBuf = HistoSchema::CreateEventHistogram( + builder, builder.CreateString("KafkaTesting"), 0, dim_metadata, 0, + builder.CreateVector(current_shape), 0, HistoSchema::Array_ArrayDouble, + data.Union()); + + FinishEventHistogramBuffer(builder, messageFlatBuf); + buffer->assign(reinterpret_cast<const char *>(builder.GetBufferPointer()), + builder.GetSize()); +} + void fakeReceiveASampleEnvMessage(std::string *buffer) { flatbuffers::FlatBufferBuilder builder; // Sample environment log - auto logDataMessage = - CreateLogData(builder, builder.CreateString("fake source"), Value_Int, - CreateInt(builder, 42).Union(), 1495618188000000000L); + auto logDataMessage = LogSchema::CreateLogData( + builder, builder.CreateString("fake source"), LogSchema::Value_Int, + LogSchema::CreateInt(builder, 42).Union(), 1495618188000000000L); FinishLogDataBuffer(builder, logDataMessage); // Copy to provided buffer @@ -221,7 +254,7 @@ void fakeReceiveARunStopMessage(std::string *buffer, buffer->assign(reinterpret_cast<const char *>(builder.GetBufferPointer()), builder.GetSize()); } - +} // namespace // ----------------------------------------------------------------------------- // Fake ISIS event stream to provide event and sample environment data // ----------------------------------------------------------------------------- @@ -281,6 +314,61 @@ public: std::string &topic) override { assert(message); + switch (m_nextOffset) { + // case 0: + // fakeReceiveARunStartMessage(message, 1000, "2016-08-31T12:07:42", + // "HRPDTEST", 1); + // break; + case 1: + fakeReceiveARunStopMessage(message, m_stopTime); + break; + default: + fakeReceiveAnEventMessage(message); + } + m_nextOffset++; + + UNUSED_ARG(offset); + UNUSED_ARG(partition); + UNUSED_ARG(topic); + } + + std::unordered_map<std::string, std::vector<int64_t>> + getOffsetsForTimestamp(int64_t timestamp) override { + UNUSED_ARG(timestamp); + return {std::pair<std::string, std::vector<int64_t>>(m_topicName, {1})}; + } + + std::unordered_map<std::string, std::vector<int64_t>> + getCurrentOffsets() override { + std::unordered_map<std::string, std::vector<int64_t>> offsets; + return {std::pair<std::string, std::vector<int64_t>>(m_topicName, {1})}; + } + + void seek(const std::string &topic, uint32_t partition, + int64_t offset) override { + UNUSED_ARG(topic); + UNUSED_ARG(partition); + UNUSED_ARG(offset); + } + +private: + std::string m_topicName = "topic_name"; + int m_nextOffset = 0; + std::string m_stopTime = "2016-08-31T12:07:52"; +}; + +// --------------------------------------------------------------------------------------- +// Fake non-institution-specific histo stream to provide histogram and sample +// environment data +// --------------------------------------------------------------------------------------- +class FakeHistoSubscriber : public Mantid::LiveData::IKafkaStreamSubscriber { +public: + void subscribe() override {} + void subscribe(int64_t offset) override { UNUSED_ARG(offset) } + void consumeMessage(std::string *message, int64_t &offset, int32_t &partition, + std::string &topic) override { + assert(message); + switch (m_nextOffset) { case 0: fakeReceiveARunStartMessage(message, 1000, "2016-08-31T12:07:42", @@ -290,7 +378,7 @@ public: fakeReceiveARunStopMessage(message, m_stopTime); break; default: - fakeReceiveAnEventMessage(message); + fakeReceiveHistoMessage(message); } m_nextOffset++; -- GitLab