/** * @RDE_HEADER@ * DDS specific parts for a session * $Id$ * $HeadURL$ * $Author$ * * Created by Christian Ehrlicher, SLSE, 2017-02-27 */ #pragma once #include #include #include #include #include // Export macro for shared library #include "ltssessiondatadds_export.h" #ifdef BUILD_RTI #include #include #include #include "Core/core.hpp" #include "Core/core_dtc_types.h" #include "Lts/Common/ProjectConfig/project_defines.h" namespace DDSConnector { class DdsConnector; } namespace DataPluginBase { class Interface; } namespace GuiPluginBase { class Interface; } #else // Forward declarations for stub types namespace DataPluginBase { class Interface; } namespace GuiPluginBase { class Interface; } #endif namespace LtsSession { // Stub enum for PartitionType enum class PartitionType { Any = 0, Exercise, Replay, AllExercises, Global, Invalid = -1 }; class Fetcher; struct DdsConnectionParams { int domainId = -1; int partitionId = 0; int exerciseId = 0; PartitionType partitionType = PartitionType::Any; QUrl tcpConnectionUrl; QStringList qos_file; DdsConnectionParams() = default; bool isValid() const { return domainId >= 0 && partitionType != PartitionType::Any; } bool operator==(const DdsConnectionParams& o) const { return domainId == o.domainId && partitionId == o.partitionId && exerciseId == o.exerciseId && qos_file == o.qos_file && partitionType == o.partitionType && tcpConnectionUrl == o.tcpConnectionUrl; } bool operator!=(const DdsConnectionParams& o) const { return !operator==(o); } bool operator<(const DdsConnectionParams& o) const { if (domainId != o.domainId) return domainId < o.domainId; if (partitionId != o.partitionId) return partitionId < o.partitionId; if (exerciseId != o.exerciseId) return exerciseId < o.exerciseId; if (qos_file != o.qos_file) return qos_file < o.qos_file; if (partitionType != o.partitionType) return partitionType < o.partitionType; return tcpConnectionUrl.toString() < o.tcpConnectionUrl.toString(); } #ifdef BUILD_RTI bool hasSameDomainParams(const DdsConnectionParams& o) const { return domainId == o.domainId && partitionType == o.partitionType; } #endif }; // Base class for session DDS data - always compiled, but RTI functionality guarded class LTSSESSIONDATADDS_EXPORT LtsSessionDataDds : public QObject { Q_OBJECT public: explicit LtsSessionDataDds(QObject* parent = nullptr); ~LtsSessionDataDds(); // Initialization #ifdef BUILD_RTI bool init(const DdsConnectionParams& connParams); bool init(const dds::domain::DomainParticipant& dp, const DdsConnectionParams& connParams); Fetcher* fetcher(const QString& yourPluginsName); #else virtual bool init(const DdsConnectionParams& connParams); virtual bool init(const void* dp, const DdsConnectionParams& connParams); virtual void* fetcher(const QString& yourPluginsName); #endif // Accessors int domainId() const; int exerciseId() const; int partitionId() const; PartitionType partitionType() const; static QString partitionTypeString(PartitionType partitionType); QStringList qosFile() const; QUrl tcpConnectionUrl() const; DdsConnectionParams connParams() const; bool isExercisePartition() const { return partitionType() == PartitionType::Exercise; } bool isReplayPartition() const { return partitionType() == PartitionType::Replay; } QString toString() const; qint64 partitionTime() const { return m_emittedTime; } // Data plugin interfaces #ifdef BUILD_RTI QMap> availableDataPluginInterfaces() const; void addAvailablaeDataPluginInterfaces(const QMap>& dataPlugins); #else QMap availableDataPluginInterfaces() const { return QMap(); } void addAvailablaeDataPluginInterfaces(const QMap& /*dataPlugins*/) {} #endif // retrieve DTC/FTC inside DataPlugin::createDataInterface() - always available template bool createTopicClient(std::shared_ptr &member, bool bEnableAll = false, bool bGlobal = false); template bool createTopicClient(std::shared_ptr &dtc, std::shared_ptr &ftc, bool bEnableAll = false, bool bGlobal = false); template bool getDtc(std::shared_ptr &val) const; // Foreign GUI interface retrieval - used by Fetcher helper class template bool getForeignGuiInterface(std::shared_ptr &val) const { #ifdef BUILD_RTI for (const auto &i : m_guiPluginInterfaces) { val = std::dynamic_pointer_cast(i); if (val) return true; } val.reset(); if (m_logger.isDebugEnabled()) DEBUG_LOG(m_logger) << "Cannot find foreign gui ifc " << typeid(S).name() << " in " << toString(); #else val.reset(); #endif return false; } signals: void partitionTimeChanged(qint64 newPartitionTime); void partitionTimeChangedInternal(); protected: #ifdef BUILD_RTI bool initInternal(); void onPartitionTimeChangedInternal(); static LtsSession::PartitionType toPartitionType(IDL::PartitionType idlType); static IDL::PartitionType toIdlPartitionType(LtsSession::PartitionType type); // Member variables - only with RTI int m_exerciseId; qint64 m_emittedTime; qint64 m_curMSecSinceEpoch; bool m_active; Fetcher* m_fetcher; std::shared_ptr m_ddsConnector; std::shared_ptr m_ddsConnectorGlobal; std::shared_ptr m_dtcPartitionTime; NGL::INGLLogger& m_logger; QMap> m_dataPluginInterfaces; QMap> m_guiPluginInterfaces; QStringList m_qosFileList; #else // Stub implementation - minimal members bool initInternal(); void onPartitionTimeChangedInternal(); int m_exerciseId; qint64 m_emittedTime; qint64 m_curMSecSinceEpoch; bool m_active; void* m_fetcher; #endif }; #ifdef BUILD_RTI class Fetcher { public: Fetcher(LtsSessionDataDds *sessionDataDds, const QString &caller) : m_sessionDataDds(sessionDataDds) , m_errors(false) , m_caller(caller) , m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsSession.Fetcher")) , m_optional(false) { } LtsSessionDataDds *m_sessionDataDds; bool m_errors; QString m_caller; QString m_whatWillNotWork; NGL::INGLLogger &m_logger; bool m_optional; QString m_resultType; QString m_getterFunctionType; template void getForeignGuiInterface(std::shared_ptr &foreignGuiInterface, const QString &whatWillNotWork /* only fill if optional */, bool optional) { if (!m_sessionDataDds->getForeignGuiInterface(foreignGuiInterface)) { m_whatWillNotWork = whatWillNotWork; m_optional = optional; m_resultType = QString::fromUtf8(typeid(ForeignGuiInterface).name()); m_getterFunctionType = QStringLiteral("gui interface"); print(); } } bool status() const { return !m_errors; } void print() { m_errors = true; QString msg(QStringLiteral("%1 cannot find '%2' in %3 %4")); if (m_optional) { INFO_LOG(m_logger) << msg.arg(m_caller, m_resultType, m_sessionDataDds->toString(), QStringLiteral("' - optional but %1 will not work").arg(m_whatWillNotWork)); } else // critical { ERROR_LOG(m_logger) << msg.arg(m_caller, m_resultType, m_sessionDataDds->toString(), QStringLiteral(" which is required")); } } }; #endif } // namespace LtsSession // Template method implementations - must be in header #ifdef BUILD_RTI template bool LtsSession::LtsSessionDataDds::createTopicClient(std::shared_ptr &member, bool bEnableAll, bool bGlobal) { member = T::create(bGlobal ? m_ddsConnectorGlobal : m_ddsConnector); if ( bEnableAll && !member->enableAll()) { member = nullptr; if (m_logger.isErrorEnabled()) NGL::LogStreamHelper(m_logger, NGL::LogLevel::Error, __FILE__, __LINE__, Q_FUNC_INFO) << "Error initializing dtc/ftc for service " << T::identifier(); return false; } return true; } template bool LtsSession::LtsSessionDataDds::createTopicClient(std::shared_ptr &dtc, std::shared_ptr &ftc, bool bEnableAll, bool bGlobal) { dtc = T::create(bGlobal ? m_ddsConnectorGlobal : m_ddsConnector); ftc = S::create(bGlobal ? m_ddsConnectorGlobal : m_ddsConnector); if ( (bEnableAll && !dtc->enableAll()) || !ftc->enableAll()) { dtc = nullptr; ftc = nullptr; if (m_logger.isErrorEnabled()) NGL::LogStreamHelper(m_logger, NGL::LogLevel::Error, __FILE__, __LINE__, Q_FUNC_INFO) << "Error initializing dtc/ftc for service " << T::identifier(); return false; } return true; } template bool LtsSession::LtsSessionDataDds::getDtc(std::shared_ptr &val) const { for (const auto &i : m_dataPluginInterfaces) { auto ifc = std::dynamic_pointer_cast(i); if (ifc) { val = ifc->getDtc(); return val != nullptr; } } val.reset(); if (m_logger.isDebugEnabled()) NGL::LogStreamHelper(m_logger, NGL::LogLevel::Debug, __FILE__, __LINE__, Q_FUNC_INFO) << "Trying to load dtc " << typeid(T).name() << " - " << typeid(S).name() << " failed!" << ", m_dataPluginInterfaces.size() = " << m_dataPluginInterfaces.size() << " - " << this; return false; } #else // Stub implementations for non-BUILD_RTI template bool LtsSession::LtsSessionDataDds::createTopicClient(std::shared_ptr &/*member*/, bool /*bEnableAll*/, bool /*bGlobal*/) { return false; } template bool LtsSession::LtsSessionDataDds::createTopicClient(std::shared_ptr &/*dtc*/, std::shared_ptr &/*ftc*/, bool /*bEnableAll*/, bool /*bGlobal*/) { return false; } template bool LtsSession::LtsSessionDataDds::getDtc(std::shared_ptr &/*val*/) const { return false; } #endif // BUILD_RTI