Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+201
View File
@@ -0,0 +1,201 @@
#
# $Id$
# $HeadURL$
# $Author$
#
INCLUDE(MacroRTIDDSGen)
INCLUDE(MacroCodeGenIdl)
SET(xml_FILE srp_service.xml)
#
# --- Library svcSrpCommon --------------------------------------------------------------------------------
#
SET(SRCS_common
srp_export.h
logger.cpp
logger.h
)
# Generate srp_enums.idl / srp.idl
CODEGEN_IDL_SVC(SRCS_common ${xml_FILE})
# Generate srp_db_impl.cpp/.h, srp_db.h
CODEGEN_DATABASE(SRCS_common ${xml_FILE})
# Generate *.cpp/*.hpp from idl
RTIDDSGEN(SRCS_common srp_enums.idl)
RTIDDSGEN(SRCS_common srp.idl)
# Generate srp_dt[s,c]_types.h, srp_ft[s,c]_types.h
CODEGEN_TOPIC_TYPEDEFS(SRCS_common ${xml_FILE})
# generate srp_[d|f]tc.h
CODEGEN_CLIENT_TOPICS_IFC(SRCS_common ${xml_FILE})
# SV needed for topic type plugin
NGL_ADD_LIBRARY(WS AAR SV svcSrpCommon SHARED ${SRCS_common})
NGL_TARGET_INCLUDE_DIRECTORIES(svcSrpCommon
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcSrpCommon
PRIVATE
RTI::nddscpp2
PUBLIC
Qt5::Core
ngldb
ddscore
NGLLogger
)
NGL_INSTALL_TARGET(svcSrpCommon)
#
# --- Library svcSrpClient --------------------------------------------------------------------------------
#
SET(SRCS_client
srp_export.h
)
# generate srp_ftc_impl.[cpp|h]
CODEGEN_CLIENT_TOPICS_IMPL(SRCS_client ${xml_FILE})
NGL_ADD_LIBRARY(WS svcSrpClient SHARED ${SRCS_client})
NGL_TARGET_INCLUDE_DIRECTORIES(svcSrpClient
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcSrpClient
PRIVATE
RTI::nddscpp2
ddsconnector
PUBLIC
svcSrpCommon
ddsftc
)
NGL_INSTALL_TARGET(svcSrpClient)
#
# --- Library svcSrpServer --------------------------------------------------------------------------------
#
SET(SRCS_server
srp_export.h
)
# generate srp_[d|f]ts.h, srp_[d|f]ts_impl.[cpp|h]
CODEGEN_SERVER_TOPICS(SRCS_server ${xml_FILE})
NGL_ADD_LIBRARY(AAR SV WS svcSrpServer SHARED ${SRCS_server})
NGL_TARGET_INCLUDE_DIRECTORIES(svcSrpServer
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcSrpServer
PRIVATE
RTI::nddscpp2
ddsconnector
ddsfts
PUBLIC
svcSrpCommon
ngldb
)
NGL_INSTALL_TARGET(svcSrpServer)
#
# --- Topic Type Plugin --------------------------------------------------------------
#
CREATE_TOPIC_TYPE_PLUGIN(${xml_FILE})
#
# --- Executable svcSituationReplay (sSrp) -------------------------------------------------
#
SET(SRCS_exe
db_reader.cpp
db_reader.h
dds_handler.cpp
dds_handler.h
handler_situation_replay.cpp
handler_situation_replay.h
main.cpp
main_handler.cpp
main_handler.h
object_situation_replay.cpp
object_situation_replay.h
settings.cpp
settings.h
${xml_FILE}
)
# Generate srp.sql, srp.xml
CODEGEN_SQL(SRCS_exe ${xml_FILE})
NGL_ADD_SVC_ICON(SRCS_exe)
NGL_ADD_EXECUTABLE(WS AAR SV svcSituationReplay ${SRCS_exe})
NGL_TARGET_LINK_LIBRARIES(svcSituationReplay
rscCommon
Qt5::Core
svcCoreClient
svcSrpCommon
svcSrpServer
ddsconnector
nglsettings
ProjectConfig
LtsCommandLineParser
NGLLogger
nglcoreapplication
LtsPluginLoader
ngltools
)
NGL_INSTALL_TARGET(svcSituationReplay)
NGL_INSTALL(WS FILES log4cxx_srp.props DESTINATION bin)
# svcSituationReplaySqlite
SET(SRCS_sqlite
db_reader.cpp
db_reader.h
dds_handler.cpp
dds_handler.h
handler_situation_replay_sqlite.cpp
handler_situation_replay_sqlite.h
main_handler_sqlite.cpp
main_handler_sqlite.h
object_situation_replay.cpp
object_situation_replay.h
static_publisher.cpp
static_publisher.h
${xml_FILE}
)
NGL_ADD_LIBRARY2(WS SituationReplaySqlite SHARED ${SRCS_sqlite})
NGL_TARGET_INCLUDE_DIRECTORIES(SituationReplaySqlite
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_BINARY_DIR}/..
)
NGL_TARGET_LINK_LIBRARIES(SituationReplaySqlite
ddsconnector
LtsPluginLoader
LtsScriptTimeline
NGLLogger
ngltools
Qt5::Core
Qt5::Sql
rscCommon
svcCoreClient
svcSrpCommon
svcSrpServer
svcAsmServer
svcExmServer
svcFlmServer
svcIsmServer
svcPdmServer
svcPpmServer
)
# Uncomment if necessary
#ADD_SUBDIRECTORY(UnitTests)
ADD_SUBDIRECTORY(ModuleTests)
+54
View File
@@ -0,0 +1,54 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(SRCS_DT_TEST
srp_dt_tests.cpp
)
SET(HDRS_DT_TEST
srp_dt_tests.h
)
SET(SRCS_FT_TEST
srp_ft_tests.cpp
)
SET(HDRS_FT_TEST
srp_ft_tests.h
)
IF(BUILD_TESTING)
IF(TARGET svcSrpClient)
# Testing DataTopic Functionality (DTC)
ADD_EXECUTABLE(srpDtTests ${SRCS_DT_TEST} ${HDRS_DT_TEST})
TARGET_LINK_LIBRARIES(srpDtTests
Qt5::Core
Qt5::Test
RTI::nddscpp2
svcSrpClient
LtsCommandLineParser
ddsconnector
nglcoreapplication
)
# Testing FunctionTopic Functionality (FTC)
ADD_EXECUTABLE(srpFtTests ${SRCS_FT_TEST} ${HDRS_FT_TEST})
TARGET_LINK_LIBRARIES(srpFtTests
Qt5::Core
Qt5::Test
RTI::nddscpp2
svcSrpClient
LtsCommandLineParser
ddsconnector
nglcoreapplication
)
IF(NOT BUILD_RPM)
NGL_INSTALL(AAR SV TARGETS srpDtTests DESTINATION bin/test)
NGL_INSTALL(AAR SV TARGETS srpFtTests DESTINATION bin/test)
NGL_INSTALL(AAR SV FILES ../log4cxx_srp.props DESTINATION bin/test)
ENDIF()
ENDIF()
ENDIF()
+186
View File
@@ -0,0 +1,186 @@
/**
* @RDE_HEADER@
* SRP Data Topic test executable
* $Id$
* $HeadURL$
* $Author$
*
* Created by Hanna E. Rathje, SLSE, 2015-09-11
*/
#include "srp_dt_tests.h"
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include <QTimer>
#include <SituationReplay/srp_dtc.h>
//---------------------------------------------------------------------------------
namespace SituationReplay
{
SrpDtTests::SrpDtTests(QObject *parent)
: QObject(parent)
, m_replayPartitionId(0)
, m_situationReplayId(0)
, m_bTestsSuccessful(true)
, m_logger(getLogger("DtTest"))
{
qRegisterMetaType<Core::FunctionReply>("Core::FunctionReply");
}
//---------------------------------------------------------------------------------
SrpDtTests::~SrpDtTests()
{}
//---------------------------------------------------------------------------------
bool SrpDtTests::init(int domainId, int replayPartitionId)
{
DEBUG_LOG(m_logger) << "init begin";
m_replayPartitionId = replayPartitionId;
// initialize DDS
m_ddsConnector.reset(new DDSConnector::DdsConnector(domainId, IDL::PartitionType::Replay, replayPartitionId));
if (!m_ddsConnector->init())
return false;
// Subscribe on replayPartition - default = true in this DdsSubscriber
// DdsInterface Subscriber
m_ddsConnector->initSubscriber();
// DdsInterface Publisher
//m_ddsConnector->setPublisher(new Publisher(domainId, m_ddsConnector->getPartition(), m_ddsConnector->getDomainParticipant()));
DEBUG_LOG(m_logger) << "Create dtc";
m_dtc = SituationReplay::Interface::Dtc::create(m_ddsConnector);
DEBUG_LOG(m_logger) << "Init dtc";
bool bRet = m_dtc->enableAll();
DEBUG_LOG(m_logger) << "init end - bRet = " << bRet;
connect(m_dtc.get(), &SituationReplay::Interface::Dtc::sitReplayChanged,
this, &SrpDtTests::onReceiveSituationReplayData);
return bRet;
}
//---------------------------------------------------------------------------------
void SrpDtTests::startTest()
{
INFO_LOG(m_logger) << "startTest";
QTimer::singleShot(1000, this, &SrpDtTests::tryGetAllSituationReplays);
}
//---------------------------------------------------------------------------------
void SrpDtTests::tryGetAllSituationReplays()
{
INFO_LOG(m_logger) << "trying to get all situationReplays";
const QMap<qint32, SituationReplay::SitReplay> map = m_dtc->sitReplays();
if (map.isEmpty())
{
ERROR_LOG(m_logger) << "Error requesting all situation replay data";
failExit();
}
else
{
INFO_LOG(m_logger) << "Amout of existing situation replays = " << map.size();
m_situationReplayId = map.firstKey();
for(auto it = map.begin(); it != map.end(); ++it)
INFO_LOG(m_logger) << "situationReplay(" << it.key() << ") : " << it.value().replayPartitionId() ;
}
QTimer::singleShot(10, this, &SrpDtTests::tryGetSituationReplay);
}
//---------------------------------------------------------------------------------
void SrpDtTests::tryGetSituationReplay()
{
INFO_LOG(m_logger) << "trying get itemData for situationReplay " << m_situationReplayId;
SituationReplay::SitReplay data = m_dtc->sitReplay(m_situationReplayId);
if (data.id() <= 0)
{
ERROR_LOG(m_logger) << "Error receiving data for situation replay " << m_situationReplayId;
failExit();
}
else
{
INFO_LOG(m_logger) << "## SitReplay(" << data.id() << "), replayPartition: " << data.replayPartitionId()
<< ", on exercise " << data.exerciseId();
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
}
//---------------------------------------------------------------------------------
void SrpDtTests::onReceiveSituationReplayData(const SituationReplay::SitReplay &data)
{
if (m_situationReplayId == data.id())
INFO_LOG(m_logger) << "##################### Data for id = " << data.id() << " received";
}
// ------------------------------------------------------------------------------
void SrpDtTests::failExit()
{
m_bTestsSuccessful = false;
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
} // end namespace
// ------------------------------------------------------------------
class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
{
public:
CmdLineParser()
: LtsCommandLineParser()
{
addOption( { QStringList() << QLatin1String("p") << QLatin1String("replay-partition-id")
, QLatin1String("ReplayPartitionId (required).")
, QLatin1String("> 0")
, QLatin1String("1")
} );
addHelpOption();
}
int replayPartitionId() const { return isSet(QLatin1String("p")) ? value(QLatin1String("p")).toInt() : -1; }
};
// ------------------------------------------------------------------
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
app.createLogger("SRP", "log4cxx_srp.props");
int iRet = -1;
CmdLineParser options;
if (!options.init())
return -1;
if (options.replayPartitionId() <= 0)
{
ERROR_LOG(app.baseLogger()) << "Required parameter p: (replay) partitionId ";
options.showHelp();
return -2;
}
std::unique_ptr<SituationReplay::SrpDtTests> srpDtTests(new SituationReplay::SrpDtTests);
if(!srpDtTests->init(options.domainId(), options.replayPartitionId()))
return iRet;
QTimer::singleShot(0, srpDtTests.get(), &SituationReplay::SrpDtTests::startTest);
STARTUP_LOG(app.baseLogger());
app.exec();
iRet = srpDtTests->testsSuccessful() ? 0 : 1;
fprintf(stderr, "%d\n", iRet);
DEBUG_LOG(app.baseLogger()) << "** TEST result = " << iRet;
SHUTDOWN_LOG(app.baseLogger());
return iRet;
}
+69
View File
@@ -0,0 +1,69 @@
/**
* @RDE_HEADER@
* SRP Data Topic test executable
*
* ModuleTests to get data from Service SituationReplay
* -> getAll()
* -> getItem()
* ---------------------------------------------------
* Client DTC is implemented
*
* => (!) Preconditon:
* - Service sExeMgmt running
*
* -------------------------------------------------
*
* $Id$
* $HeadURL$
* $Author$
*
* Created by Hanna E. Rathje, SLSE, 2015-09-11
*/
#pragma once
#include <SituationReplay/srp_dtc.h>
#include <SituationReplay/srp_dtc_types.h>
#include <SituationReplay/logger.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/DDSConnector/publisher.h>
#include <DDS/DDSConnector/subscriber.h>
//#include <Common/ProjectConfig/project_defines.h>
namespace SituationReplay
{
class SrpDtTests : public QObject
{
using Publisher = DDSConnector::Publisher;
using Subscriber = DDSConnector::Subscriber;
Q_OBJECT
public:
explicit SrpDtTests(QObject *parent = nullptr);
~SrpDtTests();
bool init(int domainId, int exerciseId);
bool testsSuccessful() const { return m_bTestsSuccessful; }
public Q_SLOTS:
void startTest();
protected Q_SLOTS:
void tryGetAllSituationReplays();
void tryGetSituationReplay();
void onReceiveSituationReplayData(const SitReplay &data);
protected:
void failExit();
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<SituationReplay::Interface::Dtc> m_dtc;
qint32 m_replayPartitionId;
qint32 m_situationReplayId;
bool m_bTestsSuccessful;
LOGGER_T m_logger;
};
} // namespace SituationReplay
+301
View File
@@ -0,0 +1,301 @@
/**
* @RDE_HEADER@
* SRP Function Topic test executable
* $Id$
* $HeadURL$
* $Author$
*
* Created by Hanna E. Rathje, SLSE, 2016-01-14
*/
#include "srp_ft_tests.h"
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include <QTimer>
#include <SituationReplay/srp_ftc.h>
//--------------------------------------------------------------------------------------------------------
namespace SituationReplay
{
SrpFtTests::SrpFtTests(QObject *parent)
: QObject(parent)
, m_replayPartitionId(0)
, m_testId(All)
, m_bTestsSuccessful(true)
, m_logger(getLogger("FtTest"))
{
qRegisterMetaType<Core::FunctionReply>("Core::FunctionReply");
}
//--------------------------------------------------------------------------------------------------------
SrpFtTests::~SrpFtTests()
{}
//--------------------------------------------------------------------------------------------------------
bool SrpFtTests::init(int domainId, TestId testId, int replayPartitionId, int srpId)
{
INFO_LOG(m_logger) << "init begin";
m_testId = testId;
m_replayPartitionId = replayPartitionId;
if (m_testId > 0)
m_situationReplayId = srpId;
// initialize DDS
m_ddsConnector.reset(new DDSConnector::DdsConnector(domainId, IDL::PartitionType::Replay, m_replayPartitionId));
if (!m_ddsConnector->init())
return false;
// Publish/Subscribe on replayPartition
m_ddsConnector->initPublisherSubscriber();
DEBUG_LOG(m_logger) << "create ftc";
m_ftc = SituationReplay::Interface::Ftc::create(m_ddsConnector);
DEBUG_LOG(m_logger) << "init ftc";
bool bRet = m_ftc->enableAll();
DEBUG_LOG(m_logger) << "init end - bRet = " << bRet;
return bRet;
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::startTest()
{
INFO_LOG(m_logger) << "startTest";
if (m_testId <= TryStart)
QTimer::singleShot(0, this, &SrpFtTests::tryStart);
else if (m_testId == TryNotAllowedChange)
QTimer::singleShot(0, this, &SrpFtTests::tryNotAllowedChange);
else if (m_testId == TryChangePaused)
QTimer::singleShot(0, this, &SrpFtTests::tryChangePaused);
else if (m_testId == TryChangeResumed)
QTimer::singleShot(0, this, &SrpFtTests::tryChangeResumed);
else if (m_testId == TryStop)
QTimer::singleShot(0, this, &SrpFtTests::tryStop);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::tryStart()
{
INFO_LOG(m_logger) << "trying to send startReplay";
m_currentTestId = TryStart;
qint64 beginTime = 1468401389668;
qint64 endTime = 1468401659954;
double pace = 2.0;
ChangeReplayStateRequest req;
req.id(0);
req.replayPartitionId(m_replayPartitionId);
req.state(SrpState::Started);
req.beginTime(beginTime);
req.endTime(endTime); // infinite
req.pace(pace);
if (!m_ftc->changeReplayStateRequest(req, this))
{
ERROR_LOG(m_logger) << "Error starting replay for srp " << m_replayPartitionId;
failExit();
}
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::tryNotAllowedChange()
{
INFO_LOG(m_logger) << "trying to send changeReplayState (start) => should fail (not possible with this method)";
m_currentTestId = TryNotAllowedChange;
switchToState(SituationReplay::SrpState::Started);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::tryChangePaused()
{
INFO_LOG(m_logger) << "trying to send changeReplayState (Paused)";
m_currentTestId = TryChangePaused;
switchToState(SituationReplay::SrpState::Paused);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::tryChangeResumed()
{
INFO_LOG(m_logger) << "trying to send changeReplayState (Resumed)";
m_currentTestId = TryChangeResumed;
switchToState(SituationReplay::SrpState::Resumed);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::tryStop()
{
INFO_LOG(m_logger) << "trying to send stopReplay";
m_currentTestId = TryStop;
switchToState(SituationReplay::SrpState::Stopped);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::startReplayReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got startReplayReply with id " << replyObject.id();
m_situationReplayId = replyObject.id();
if (m_testId == 0 && !replyObject.error())
QTimer::singleShot(0, this, &SrpFtTests::tryNotAllowedChange);
else
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::changeReplayStateReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got changeReplayStateReply with id " << replyObject.id();
if (replyObject.error())
INFO_LOG(m_logger) << ", string: " << replyObject.translated();
if (m_testId == 0 && !replyObject.error())
{
if (m_currentTestId == TryNotAllowedChange)
QTimer::singleShot(0, this, &SrpFtTests::tryChangePaused);
else if (m_currentTestId == TryChangePaused)
QTimer::singleShot(0, this, &SrpFtTests::tryChangeResumed);
else
QTimer::singleShot(0, this, &SrpFtTests::tryStop);
}
else
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::stopReplayReply(const Core::FunctionReplyObject &replyObject)
{
INFO_LOG(m_logger) << "Got stopReplayReply with id " << replyObject.id() ;
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::onChangeReplayStateReply(const Core::FunctionReplyObject &replyObject)
{
switch (m_currentTestId)
{
case TryStart:
startReplayReply(replyObject);
break;
case TryNotAllowedChange:
case TryChangePaused:
case TryChangeResumed:
changeReplayStateReply(replyObject);
break;
case TryStop:
stopReplayReply(replyObject);
break;
case All:
changeReplayStateReply(replyObject);
break;
}
}
// ------------------------------------------------------------------------------
void SrpFtTests::failExit()
{
m_bTestsSuccessful = false;
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
}
//--------------------------------------------------------------------------------------------------------
void SrpFtTests::switchToState(SrpState state)
{
ChangeReplayStateRequest req;
req.id(m_situationReplayId);
req.replayPartitionId(m_replayPartitionId);
req.state(state);
if (!m_ftc->changeReplayStateRequest(req, this))
{
ERROR_LOG(m_logger) << "Error changing replay state for srp " << m_situationReplayId << "(" << m_replayPartitionId << ")";
failExit();
}
}
} // end namespace
// ------------------------------------------------------------------
class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
{
public:
CmdLineParser()
: LtsCommandLineParser()
{
addOption( { QStringList() << QLatin1String("t") << QLatin1String("testId")
, QLatin1String("TestId.")
, QLatin1String("Default: 0 (all tests)")
, QLatin1String("0")
} );
addOption( { QStringList() << QLatin1String("p") << QLatin1String("replayPartitionId")
, QLatin1String("ReplayPartitionId.")
, QLatin1String("required")
, QLatin1String("0")
} );
addOption( { QStringList() << QLatin1String("r") << QLatin1String("situationReplayId")
, QLatin1String("SituationReplayId.")
, QLatin1String("optional")
, QLatin1String("0")
} );
addHelpOption();
}
int testId() const { return isSet(QLatin1String("t")) ? value(QLatin1String("t")).toInt() : -1; }
int replayPartitionId() const { return isSet(QLatin1String("p")) ? value(QLatin1String("p")).toInt() : -1; }
int situationReplayId() const { return isSet(QLatin1String("r")) ? value(QLatin1String("r")).toInt() : -1; }
};
// ------------------------------------------------------------------
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
app.createLogger("SRP", "log4cxx_srp.props");
CmdLineParser options;
if (!options.init())
return -1;
if (options.exerciseId() <= 0 || options.replayPartitionId() <= 0)
{
ERROR_LOG(app.baseLogger()) << "Required parameter: exerciseId & replayPartitionId ";
options.showHelp();
return -2;
}
if (options.testId() > 0 && options.situationReplayId() <= 0)
{
ERROR_LOG(app.baseLogger()) << "Required parameter for single test: situationReplayId ";
options.showHelp();
return -2;
}
std::unique_ptr<SituationReplay::SrpFtTests> SrpFtTests(new SituationReplay::SrpFtTests);
int iRet = -1;
if(!SrpFtTests->init(options.domainId(), SituationReplay::SrpFtTests::TestId(options.testId()),
options.replayPartitionId(), options.situationReplayId()))
return iRet;
QTimer::singleShot(0, SrpFtTests.get(), &SituationReplay::SrpFtTests::startTest);
STARTUP_LOG(app.baseLogger());
app.exec();
iRet = SrpFtTests->testsSuccessful() ? 0 : 1;
fprintf(stderr, "%d\n", iRet);
DEBUG_LOG(app.baseLogger()) << "** TEST result = " << iRet;
SHUTDOWN_LOG(app.baseLogger());
return iRet;
}
+84
View File
@@ -0,0 +1,84 @@
/**
* @RDE_HEADER@
* SRP Function Topic test executable
*
* ModuleTests for create/modify/remove exercise
* ---------------------------------------------------
* Client FTC is implemented
*
* => (!) Preconditon:
* - Service sSrp running
*
* -------------------------------------------------
*
* $Id$
* $HeadURL$
* $Author$
*
* Created by Hanna E. Rathje, SLSE, 2016-01-14
*/
#pragma once
#include <SituationReplay/srp_ftc.h>
#include <SituationReplay/srp_ftc_types.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/DDSConnector/publisher.h>
#include <DDS/DDSConnector/subscriber.h>
#include <Common/ProjectConfig/project_defines.h>
#include <SituationReplay/logger.h>
namespace SituationReplay
{
class SrpFtTests : public QObject
, protected SituationReplay::Interface::Ftc::ChangeReplayStateReplyHandler
{
using Publisher = DDSConnector::Publisher;
using Subscriber = DDSConnector::Subscriber;
Q_OBJECT
public:
enum TestId
{
All,
TryStart,
TryNotAllowedChange,
TryChangePaused,
TryChangeResumed,
TryStop,
};
explicit SrpFtTests(QObject *parent = nullptr);
~SrpFtTests();
bool init(int domainId, TestId testId, int replayPartitionId, int srpId);
bool testsSuccessful() const { return m_bTestsSuccessful; }
public Q_SLOTS:
void startTest();
protected Q_SLOTS:
void tryStart();
void tryNotAllowedChange();
void tryChangePaused();
void tryChangeResumed();
void tryStop();
protected:
void startReplayReply(const Core::FunctionReplyObject &replyObject);
void stopReplayReply(const Core::FunctionReplyObject &replyObject);
void changeReplayStateReply(const Core::FunctionReplyObject &replyObject);
void onChangeReplayStateReply(const Core::FunctionReplyObject &replyObject) override final;
void failExit();
void switchToState(SrpState state);
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<SituationReplay::Interface::Ftc> m_ftc;
qint32 m_replayPartitionId;
qint32 m_situationReplayId;
TestId m_testId;
TestId m_currentTestId;
bool m_bTestsSuccessful;
LOGGER_T m_logger;
};
} // namespace SituationReplay
+136
View File
@@ -0,0 +1,136 @@
/**
* DbReader for RecordingManagement
* $Id$
* $HeadURL$
* $Author$
*/
#include "db_reader.h"
#include "logger.h"
#include <DDS/DDSConnector/dds_connector.h>
#include <LtsPluginManager/lts_plugin_loader.h>
#include <ngldb/nsqlquery.h>
namespace SituationReplay
{
DbReader::DbReader(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector,
int exerciseId,
bool bCanHandleSchemas)
: m_exerciseId(exerciseId)
, m_query(nullptr)
, m_ddsConnector(ddsConnector)
, m_bCanHandleSchemas(bCanHandleSchemas)
, m_logger(getLogger("DbReader"))
{}
DbReader::~DbReader()
{
delete m_query;
LtsPluginManager::LtsPluginLoader::getInstance()->unloadAllPlugins();
m_plugins.clear();
}
bool DbReader::loadPlugin(const LtsPluginManager::PluginInstance &pi)
{
RecordReplay::RecordReplayPlugin *recPlugin = qobject_cast<RecordReplay::RecordReplayPlugin*>(pi.plugin);
if (!recPlugin)
{
ERROR_LOG(m_logger) << "Cannot load RecordReplayPlugin " << pi.fileName;
return false;
}
if (!recPlugin->initDts(m_ddsConnector, m_exerciseId, m_bCanHandleSchemas, *m_query))
{
ERROR_LOG(m_logger) << "Initialisation for RecordReplayPlugin " << pi.fileName << " failed ";
return false;
}
INFO_LOG(m_logger) << "Loaded record replay plugin " << recPlugin->pluginName();
m_plugins.push_back(recPlugin);
return true;
}
bool DbReader::init(const QSqlDatabase &db)
{
delete m_query;
m_query = new NSqlQuery(db);
auto cb = [this](const LtsPluginManager::PluginInstance &pi) { return loadPlugin(pi); };
LtsPluginManager::LtsPluginLoader::getInstance()->loadPlugins(LtsPluginManager::PluginType::SPECIAL,
cb,
QStringList(),
QStringLiteral("recordreplay"));
return true;
}
bool DbReader::setReplayStartTime(qint64 startTime)
{
INFO_LOG(m_logger) << "IN setReplayStartTime " << startTime;
if (!m_query)
{
WARNING_LOG(m_logger) << "Internal error - no query!";
return false;
}
for (RecordReplay::RecordReplayPlugin *recPlugin : m_plugins)
{
INFO_LOG(m_logger) << "IN setReplayStartTime, current Plugin: " << recPlugin->pluginName()
<< " typename=" << typeid(*recPlugin).name();
if (!recPlugin->setReplayStartTime(*m_query, startTime))
{
WARNING_LOG(m_logger) << "setReplayStartTime for plugin " << recPlugin->svcShortName() << " failed!";
return false;
}
}
INFO_LOG(m_logger) << "IN setReplayStartTime " << startTime << " DONE";
return true;
}
bool DbReader::readData(qint64 fromTime, qint64 toTime)
{
INFO_LOG(m_logger) << "IN readData " << fromTime << " to " << toTime;
if (!m_query)
{
WARNING_LOG(m_logger) << "Internal error - no query!";
return false;
}
for (RecordReplay::RecordReplayPlugin *recPlugin : m_plugins)
{
if (!recPlugin->ddsTopicsFromDatabase(*m_query, fromTime, toTime))
{
WARNING_LOG(m_logger) << "ddsTopicsFromDatabase for plugin " << recPlugin->svcShortName() << " failed!";
return false;
}
}
INFO_LOG(m_logger) << "IN readData " << fromTime << " to " << toTime << " DONE";
return true;
}
void DbReader::publish(qint64 desiredTime)
{
INFO_LOG(m_logger) << "IN publish " << desiredTime;
for (RecordReplay::RecordReplayPlugin *recPlugin : m_plugins)
if (!recPlugin->publishData(desiredTime))
WARNING_LOG(m_logger) << "publishData for plugin " << recPlugin->svcShortName() << " failed!";
INFO_LOG(m_logger) << "IN publish " << desiredTime << " DONE";
}
void DbReader::waitForAsyncOperations(qint64 desiredTime)
{
INFO_LOG(m_logger) << "IN waitForAsyncOperations " << desiredTime;
for (RecordReplay::RecordReplayPlugin *recPlugin : m_plugins)
if (!recPlugin->waitForAsyncOperations(desiredTime))
WARNING_LOG(m_logger) << "waitForAsyncOperations for plugin " << recPlugin->svcShortName() << " failed!";
}
void DbReader::clearData()
{
INFO_LOG(m_logger) << "IN clearData";
for (RecordReplay::RecordReplayPlugin *recPlugin : m_plugins)
recPlugin->clearData();
}
} // RecordingManagement
+49
View File
@@ -0,0 +1,49 @@
/**
* DbReader for SituationReplay
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <PluginInterfaces/record_replay_plugin.h>
#include "logger.h"
class QSqlDatabase;
class NSqlQuery;
namespace LtsPluginManager
{
struct PluginInstance;
}
namespace SituationReplay
{
class DbReader final
{
public:
explicit DbReader(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector,
int exerciseId,
bool bCanHandleSchemas);
~DbReader();
bool init(const QSqlDatabase &db);
bool setReplayStartTime(qint64 startTime);
bool readData(qint64 fromTime, qint64 toTime);
void publish(qint64 desiredTime);
void waitForAsyncOperations(qint64 desiredTime);
void clearData();
private:
bool loadPlugin(const LtsPluginManager::PluginInstance &pi);
private:
int m_exerciseId;
NSqlQuery *m_query;
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
bool m_bCanHandleSchemas;
std::vector<RecordReplay::RecordReplayPlugin*> m_plugins;
LOGGER_T m_logger;
};
} // namespace RecordingManagement
+141
View File
@@ -0,0 +1,141 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#include "dds_handler.h"
#include <DDS/DTS/generic_dts_impl.h>
#include <DDS/QosProfile/DDS_DefaultQos.h>
#include <QVector>
namespace SituationReplay
{
static std::shared_ptr<DDSConnector::DdsConnector> makeConnector(const ConnectionParams &params,
IDL::PartitionType partitionType,
DDS::QosProfile::ConnectionType defaultConnectionType)
{
if (params.discoveryPeer.isEmpty())
return std::make_shared<DDSConnector::DdsConnector>(params.domainId,
partitionType,
params.partitionId,
params.exerciseId,
defaultConnectionType);
return std::make_shared<DDSConnector::DdsConnector>(params.domainId,
partitionType,
params.partitionId,
params.exerciseId,
params.discoveryPeer);
}
DdsHandler::DdsHandler(const ConnectionParams &output)
: m_ddsConnectorReplay(makeConnector(output, IDL::PartitionType::Replay, DDS::QosProfile::ConnectionType::ShmUdpLocalhost))
, m_logger(getLogger("DdsHandler"))
{
DEBUG_LOG(m_logger) << "DdsHandler Replay(" << output.partitionId << ") for partition: " << m_ddsConnectorReplay->getDefaultPartition();
}
DdsHandler::DdsHandler(const ConnectionParams &input, const ConnectionParams &output)
: m_ddsConnectorExercise(makeConnector(input, IDL::PartitionType::Exercise, DDS::QosProfile::ConnectionType::Client))
, m_ddsConnectorReplay(makeConnector(output, IDL::PartitionType::Replay, DDS::QosProfile::ConnectionType::Shm))
, m_logger(getLogger("DdsHandler"))
{
DEBUG_LOG(m_logger) << "DdsHandler Exercise(" << input.partitionId << ") for partition: " << m_ddsConnectorExercise->getDefaultPartition();
DEBUG_LOG(m_logger) << "DdsHandler Replay(" << output.partitionId << ") for partition: " << m_ddsConnectorReplay->getDefaultPartition();
}
DdsHandler::~DdsHandler()
{
m_sessionRouting = nullptr;
m_dtsPartitionTime = nullptr;
m_ddsFts = nullptr;
m_ddsDts = nullptr;
m_ddsConnectorReplay = nullptr;
m_ddsConnectorExercise = nullptr;
}
bool DdsHandler::init(const QStringList &qosFileList)
{
if ((m_ddsConnectorExercise && !m_ddsConnectorExercise->init(qosFileList)) ||
!m_ddsConnectorReplay->init(qosFileList))
{
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
return false;
}
if (m_ddsConnectorExercise)
{
m_ddsConnectorExercise->initPublisherSubscriber();
m_ddsConnectorExercise->enableBatchedWriter(false);
}
m_ddsConnectorReplay->initPublisherSubscriber();
m_ddsConnectorReplay->enableBatchedWriter(false);
m_dtsPartitionTime.reset(m_ddsConnectorReplay->createDTS<DTS::PartitionTimeImpl>());
assert(m_dtsPartitionTime.get());
m_ddsDts = SituationReplay::Interface::Dts::create(m_ddsConnectorReplay);
m_ddsFts = SituationReplay::Interface::Fts::create(m_ddsConnectorReplay);
bool bRet = m_ddsDts->enableAll();
INFO_LOG(m_logger) << "Dts initialised";
bRet &= m_ddsFts->enableAll();
INFO_LOG(m_logger) << "Fts initialised";
initReplayRouting();
return bRet;
}
void DdsHandler::publishPartitionTime(const Core::PartitionTime &partitionTime)
{
INFO_LOG(m_logger) << "publish partitionTime: " << partitionTime.timeStamp();
m_dtsPartitionTime->write(partitionTime);
}
bool DdsHandler::parseOptions(const QString &opts, ConnectionParams &params)
{
QVector<QStringRef> parts = opts.splitRef(QLatin1Char(','));
if (parts.size() < 2 || parts.size() > 3)
return false;
bool bOk;
params.domainId = parts.at(0).toInt(&bOk);
if (!bOk)
return false;
params.partitionId = parts.at(1).toInt(&bOk);
if (!bOk)
return false;
if (parts.size() == 3)
{
QString str = parts.at(2).toString();
// '_' is not allowed in a scheme, but rti needs it ...
str.replace(QLatin1String("tcpv4_lan"), QLatin1String("tcpv4lan"));
QUrl url = QUrl::fromUserInput(str);
if (url.scheme() == QLatin1String("http") ||
url.scheme() == QLatin1String("file"))
url.setScheme(QStringLiteral("tcpv4lan"));
if (!url.isValid())
return false;
params.discoveryPeer = url;
}
return true;
}
void DdsHandler::initReplayRouting()
{
if (!m_ddsConnectorExercise)
return;
m_sessionRouting.reset(new RoutingService::SessionHandler(IDL::PartitionType::Replay,
m_ddsConnectorExercise,
m_ddsConnectorReplay));
m_sessionRouting->init();
m_sessionRouting->onCreateSession(QString::fromStdString(m_ddsConnectorExercise->getDefaultPartition()),
QString::fromStdString(m_ddsConnectorReplay->getDefaultPartition()));
}
} // Namespace SRP
+61
View File
@@ -0,0 +1,61 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include <RoutingServiceNG/session_handler.h>
#include <SituationReplay/srp_dts.h>
#include <SituationReplay/srp_fts.h>
#include <DDS/Core/core_dts_types.h>
#include "logger.h"
namespace SituationReplay
{
struct ConnectionParams
{
int domainId = 0;
int partitionId = 0;
int exerciseId = 0;
QUrl discoveryPeer;
};
class DdsHandler final
{
public:
explicit DdsHandler(const SituationReplay::ConnectionParams &output);
DdsHandler(const SituationReplay::ConnectionParams &input,
const SituationReplay::ConnectionParams &output);
~DdsHandler();
bool init(const QStringList &qosFileList = QStringList());
void publishPartitionTime(const Core::PartitionTime &partitionTime);
std::shared_ptr<SituationReplay::Interface::Dts> dts() const { return m_ddsDts; }
std::shared_ptr<SituationReplay::Interface::Fts> fts() const { return m_ddsFts; }
std::shared_ptr<DDSConnector::DdsConnector> ddsExercise() const { return m_ddsConnectorExercise; }
std::shared_ptr<DDSConnector::DdsConnector> ddsReplay() const { return m_ddsConnectorReplay; }
static bool parseOptions(const QString &opts, ConnectionParams &params);
private:
void initReplayRouting();
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnectorExercise;
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnectorReplay;
std::shared_ptr<SituationReplay::Interface::Dts> m_ddsDts;
std::shared_ptr<SituationReplay::Interface::Fts> m_ddsFts;
std::unique_ptr<DTS::PartitionTime> m_dtsPartitionTime;
std::unique_ptr<RoutingService::SessionHandler> m_sessionRouting;
NGL::INGLLogger &m_logger;
};
}
+174
View File
@@ -0,0 +1,174 @@
/**
* @RDE_HEADER@
* Handler for all request journal objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-01-13
*/
#include "handler_situation_replay.h"
#include "object_situation_replay.h"
#include "db_reader.h"
#include <SituationReplay/srp_db.h>
#include <ngldb/nsqlquery.h>
#include <QCoreApplication>
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace SituationReplay
{
HandlerSituationReplay::HandlerSituationReplay(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DatabaseInterface> &db,
const std::shared_ptr<DbReader> &dbReader)
: Interface::Fts::ChangeReplayStateRequestHandler(ddsHandler->fts())
, m_objSrp(nullptr)
, m_ddsHandler(ddsHandler)
, m_db(db)
, m_dbReader(dbReader)
, m_exerciseId(0)
, m_partitionId(0)
, m_logger(getLogger("HandlerSituationReplay"))
{}
HandlerSituationReplay::~HandlerSituationReplay()
{
delete m_objSrp;
}
bool HandlerSituationReplay::init(int exerciseId, int partitionId)
{
m_exerciseId = exerciseId;
m_partitionId = partitionId;
const QString tableName = m_db->schemaName().isEmpty() ? QStringLiteral("exercise") : QStringLiteral("exm.exercise");
const QString stmt(QStringLiteral("SELECT start_time FROM %1 WHERE id = %2").arg(tableName).arg(exerciseId));
NSqlQuery q(m_db->database());
const qint64 exerciseStartTime = (q.execAndFetch(stmt) ? q.value(0).toLongLong() : 0);
DEBUG_LOG(m_logger) << "stmt: " << stmt << ", res " << exerciseStartTime;
Database::SrpSituationReplay newData;
newData.srpStateId = SrpState::Stopped;
newData.replayPartitionId = m_partitionId;
newData.beginTime = exerciseStartTime;
newData.endTime = exerciseStartTime;
newData.pace = 0.0;
return createObject(newData);
}
bool HandlerSituationReplay::createObject(const Database::SrpSituationReplay &newData)
{
delete m_objSrp;
m_objSrp = new ObjectSituationReplay(m_ddsHandler, m_db, m_dbReader, m_exerciseId);
Core::FunctionReplyObject ret = m_objSrp->createObject(newData);
if (ret.error())
{
delete m_objSrp;
m_objSrp = nullptr;
ERROR_LOG(m_logger) << ret();
}
return m_objSrp != nullptr;
}
Core::FunctionReplyObject HandlerSituationReplay::startReplayRequest(const SituationReplay::ChangeReplayStateRequest &request)
{
DEBUG_LOG(m_logger) << "onStartReplayRequest: " << request;
// Start only own replay
if (request.replayPartitionId() != m_partitionId)
return Core::FunctionReplyObject(request.replayPartitionId(),tr_lts("dds", "Wrong replay partition"));
if (m_objSrp && m_objSrp->srpState() != SrpState::Stopped)
return Core::FunctionReplyObject(request.replayPartitionId(), tr_lts("dds", "Replay is not yet stopped"));
Database::SrpSituationReplay newData;
newData.srpStateId = SrpState::Started;
newData.replayPartitionId = m_partitionId;
newData.beginTime = request.beginTime();
newData.endTime = request.endTime();
newData.pace = request.pace().is_set() ? request.pace().get() : 1;
// round to sec
newData.beginTime = (newData.beginTime / 1000) * 1000;
if (newData.endTime)
newData.endTime = ((newData.endTime / 1000) + 1) * 1000;
if (!m_objSrp && !createObject(newData))
return Core::FunctionReplyObject(request.replayPartitionId(),tr_lts("dds", "Internal error"));
m_objSrp->setSrpData(newData);
return Core::FunctionReplyObject(m_objSrp->getId());
}
Core::FunctionReplyObject HandlerSituationReplay::stopReplayRequest(const SituationReplay::ChangeReplayStateRequest &request)
{
DEBUG_LOG(m_logger) << "onStopReplayRequest: " << request;
if (m_objSrp == nullptr)
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "SituationReplay for replayPartitionId %1 not found")).arg(request.replayPartitionId());
if (m_objSrp && (m_objSrp->getId() != request.id() || m_objSrp->getReplayPartitionId() != request.replayPartitionId()))
return Core::FunctionReplyObject(request.id(),tr_lts("dds", "Given request id %1 not equal object id %2")).arg(request.id()).arg(m_objSrp->getId());
Core::FunctionReplyObject ret = m_objSrp->switchToState(SrpState::Stopped);
if (!ret.error())
ret = m_objSrp->removeObject();
// remove all old data from DDS-Bus & clear maps
m_dbReader->clearData();
return ret;
}
Core::FunctionReplyObject HandlerSituationReplay::changeReplayStateRequest(const SituationReplay::ChangeReplayStateRequest &request)
{
if (request.state() != SrpState_def::Started)
{
if (m_objSrp == nullptr)
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "SituationReplay for replayPartitionId %1 not found")).arg(request.replayPartitionId());
if (m_objSrp && (m_objSrp->getId() != request.id() || m_objSrp->getReplayPartitionId() != request.replayPartitionId()))
return Core::FunctionReplyObject(request.id(),tr_lts("dds", "Given request id %1 not equal object id %2")).arg(request.id()).arg(m_objSrp->getId());
}
if (request.pace().is_set())
m_objSrp->setPace(request.pace().get());
switch (request.state().underlying())
{
case SrpState_def::Unknown:
if (request.pace().is_set())
return Core::FunctionReplyObject(request.id());
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Can not handle command 'Unknown' in changeReplayStateRequest"));
case SrpState_def::Started:
return startReplayRequest(request);
case SrpState_def::Resumed:
{
DEBUG_LOG(m_logger) << "Resume request: " << request.beginTime() << ", cur playback time: " << m_objSrp->currentReplayTime();
if (request.beginTime() != 0 && request.beginTime() != m_objSrp->currentReplayTime())
{
stopReplayRequest(request);
return startReplayRequest(request);
}
Q_FALLTHROUGH();
case SrpState_def::Paused:
return m_objSrp->switchToState(request.state());
}
case SrpState_def::Stopped:
return stopReplayRequest(request);
}
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Unhandled request state %1")).arg(request.state().underlying());
}
void HandlerSituationReplay::onChangeReplayStateRequest(const rti::core::SampleIdentity &cookie,
const ChangeReplayStateRequest &request)
{
DEBUG_LOG(m_logger) << "onChangeReplayStateRequest: " << request;
auto ret = changeReplayStateRequest(request);
if (ret.error())
WARNING_LOG(m_logger) << ret();
m_ddsHandler->fts()->changeReplayStateReply(cookie, ret);
}
} // Namespace SituationReplay
+60
View File
@@ -0,0 +1,60 @@
/**
* @RDE_HEADER@
* Handler for all situation replay objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <QObject>
#include <memory>
#include <SituationReplay/srp_fts.h>
#include "logger.h"
namespace SituationReplay
{
namespace Database
{
struct SrpSituationReplay;
}
class DatabaseInterface;
class DbReader;
class DdsHandler;
class ObjectSituationReplay;
class HandlerSituationReplay final : public QObject
, protected Interface::Fts::ChangeReplayStateRequestHandler
{
Q_OBJECT
public:
explicit HandlerSituationReplay(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DatabaseInterface> &db,
const std::shared_ptr<DbReader> &dbReader);
~HandlerSituationReplay();
bool init(int exerciseId, int partitionId);
private:
bool createObject(const Database::SrpSituationReplay &newData);
Core::FunctionReplyObject startReplayRequest(const ChangeReplayStateRequest &request);
Core::FunctionReplyObject stopReplayRequest(const ChangeReplayStateRequest &request);
Core::FunctionReplyObject changeReplayStateRequest(const ChangeReplayStateRequest &request);
void onChangeReplayStateRequest(const rti::core::SampleIdentity &cookie,
const ChangeReplayStateRequest &request) override;
private:
ObjectSituationReplay *m_objSrp; // only one (!) replay per partition possible
const std::shared_ptr<DdsHandler> m_ddsHandler;
const std::shared_ptr<DatabaseInterface> m_db;
const std::shared_ptr<DbReader> m_dbReader;
int m_exerciseId;
int m_partitionId;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,170 @@
/**
* @RDE_HEADER@
* Handler for all request journal objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-01-13
*/
#include "handler_situation_replay_sqlite.h"
#include "object_situation_replay.h"
#include "db_reader.h"
namespace SituationReplay
{
HandlerSituationReplaySqlite::HandlerSituationReplaySqlite(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DbReader> &dbReader)
: m_objSrp(nullptr)
, m_ddsHandler(ddsHandler)
, m_dbReader(dbReader)
, m_exerciseId(0)
, m_partitionId(0)
, m_beginTime(0)
, m_endTime(0)
, m_logger(getLogger("HandlerSituationReplaySqlite"))
{}
HandlerSituationReplaySqlite::~HandlerSituationReplaySqlite()
{
delete m_objSrp;
}
bool HandlerSituationReplaySqlite::init(int exerciseId, int partitionId, qint64 beginTime, qint64 endTime)
{
m_exerciseId = exerciseId;
m_partitionId = partitionId;
m_beginTime = beginTime;
m_endTime = endTime;
Database::SrpSituationReplay newData;
newData.srpStateId = SrpState::Stopped;
newData.replayPartitionId = m_partitionId;
newData.beginTime = m_beginTime;
newData.endTime = m_beginTime; // for init
newData.pace = 0.0;
createObject(newData);
return true;
}
bool HandlerSituationReplaySqlite::createObject(const Database::SrpSituationReplay &newData)
{
delete m_objSrp;
m_objSrp = new ObjectSituationReplay(m_ddsHandler, nullptr, m_dbReader, m_exerciseId);
Core::FunctionReplyObject ret = m_objSrp->createObject(newData);
if (ret.error())
{
delete m_objSrp;
m_objSrp = nullptr;
ERROR_LOG(m_logger) << ret();
return false;
}
connect(m_objSrp, &ObjectSituationReplay::replayTimeChanged, this, &HandlerSituationReplaySqlite::replayTimeChanged);
connect(m_objSrp, &ObjectSituationReplay::started, this, &HandlerSituationReplaySqlite::started);
connect(m_objSrp, &ObjectSituationReplay::paused, this, &HandlerSituationReplaySqlite::paused);
connect(m_objSrp, &ObjectSituationReplay::resumed, this, &HandlerSituationReplaySqlite::resumed);
connect(m_objSrp, &ObjectSituationReplay::stopped, this, &HandlerSituationReplaySqlite::stopped);
return true;
}
bool HandlerSituationReplaySqlite::onStartReplayRequest(qint64 begin, qint64 end, double pace)
{
DEBUG_LOG(m_logger) << "onStartReplayRequest: " << begin << ", " << end << ", " << pace;
Database::SrpSituationReplay newData;
newData.srpStateId = SrpState::Started;
newData.replayPartitionId = m_partitionId;
newData.beginTime = begin;
newData.endTime = end;
newData.pace = pace;
if (!m_objSrp && !createObject(newData))
return false;
return m_objSrp->setSrpData(newData);
}
bool HandlerSituationReplaySqlite::onStopReplayRequest()
{
DEBUG_LOG(m_logger) << "onStopReplayRequest";
if (m_objSrp == nullptr)
{
ERROR_LOG(m_logger) << "onStopReplayRequest - internal error";
return false;
}
Core::FunctionReplyObject ret = m_objSrp->switchToState(SrpState::Stopped);
if (!ret.error())
ret = m_objSrp->removeObject();
if (ret.error())
WARNING_LOG(m_logger) << ret();
// remove all old data from DDS-Bus & clear maps
m_dbReader->clearData();
return true;
}
bool HandlerSituationReplaySqlite::onPauseReplayRequest()
{
if (m_objSrp == nullptr)
{
ERROR_LOG(m_logger) << "onChangeReplayStateRequest - internal error";
return false;
}
return onChangeReplayStateRequest(SrpState::Paused, m_objSrp->pace());
}
bool HandlerSituationReplaySqlite::onResumeReplayRequest()
{
if (m_objSrp == nullptr)
{
ERROR_LOG(m_logger) << "onChangeReplayStateRequest - internal error";
return false;
}
return onChangeReplayStateRequest(SrpState::Resumed, m_objSrp->pace());
}
bool HandlerSituationReplaySqlite::onChangeReplayStateRequest(const SituationReplay::SrpState &newState, double newPace)
{
DEBUG_LOG(m_logger) << "onChangeReplayStateRequest: " << newState << ", " << newPace;
if (m_objSrp == nullptr)
{
ERROR_LOG(m_logger) << "onChangeReplayStateRequest - internal error";
return false;
}
if (newState != SrpState::Resumed && newState != SrpState::Paused)
{
ERROR_LOG(m_logger) << "onChangeReplayStateRequest: SrpStateChange not possible, only resumed & paused allowed";
return false;
}
m_objSrp->setPace(newPace);
const Core::FunctionReplyObject ret = m_objSrp->switchToState(newState);
if (ret.error())
WARNING_LOG(m_logger) << ret();
return !ret.error();
}
bool HandlerSituationReplaySqlite::onPaceChangeRequest(double newPace)
{
if (m_objSrp == nullptr)
{
ERROR_LOG(m_logger) << "onChangeReplayStateRequest - internal error";
return false;
}
m_objSrp->setPace(newPace);
return false;
}
} // Namespace SituationReplay
@@ -0,0 +1,69 @@
/**
* @RDE_HEADER@
* Handler for all situation replay objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <SituationReplay/situationreplaysqlite_export.h>
#include <SituationReplay/srp_enums.hpp>
#include <QObject>
#include <memory>
#include "logger.h"
namespace SituationReplay
{
namespace Database
{
struct SrpSituationReplay;
}
class DbReader;
class DdsHandler;
class ObjectSituationReplay;
class SITUATIONREPLAYSQLITE_EXPORT HandlerSituationReplaySqlite final : public QObject
{
Q_OBJECT
public:
explicit HandlerSituationReplaySqlite(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DbReader> &dbReader);
~HandlerSituationReplaySqlite();
bool init(int exerciseId, int partitionId, qint64 beginTime, qint64 endTime);
qint64 beginTime() const { return m_beginTime; }
qint64 endTime() const { return m_endTime; }
Q_SIGNALS:
void replayTimeChanged(qint64 curTime);
void started(qint64 currentReplayTime);
void paused();
void resumed(qint64 currentReplayTime);
void stopped();
public:
bool onStartReplayRequest(double pace) { return onStartReplayRequest(m_beginTime, m_endTime, pace); }
bool onStartReplayRequest(qint64 begin, qint64 end, double pace);
bool onStopReplayRequest();
bool onPauseReplayRequest();
bool onResumeReplayRequest();
bool onChangeReplayStateRequest(const SrpState &newState, double newPace);
bool onPaceChangeRequest(double newPace);
private:
bool createObject(const Database::SrpSituationReplay &newData);
private:
ObjectSituationReplay *m_objSrp; // only one (!) replay per partition possible
const std::shared_ptr<DdsHandler> m_ddsHandler;
const std::shared_ptr<DbReader> m_dbReader;
int m_exerciseId;
int m_partitionId;
qint64 m_beginTime;
qint64 m_endTime;
NGL::INGLLogger &m_logger;
};
}
+83
View File
@@ -0,0 +1,83 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# Service: SituationReplay
###########################################################
#log4j.logger.SRP=WARN
#log4j.logger.SRP.main=WARN
#log4j.logger.SRP.HandlerSituationReplay=INFO
#log4j.logger.SRP.ObjectSituationReplay=INFO
#log4j.logger.SRP.Settings=INFO
#log4j.logger.SRP.DbHandler=DEBUG
#log4j.logger.SRP.DdsHandler=INFO
# File
###########################################################
log4j.appender.file=Lts::RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
# Appnd_Console
###########################################################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
# Appnd_Syslog
###########################################################
log4j.appender.syslog=org.apache.log4j.SyslogAppender
log4j.appender.syslog.Threshold=ERROR
log4j.appender.syslog.SysLogHost=localhost
log4j.appender.syslog.Facility=LOCAL7
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
###########################################################
###########################################################
###########################################################
# 1) Available Levels in LOG4CXX Version 0.10.0:
# TRACE,
# DEBUG,
# INFO,
# WARN,
# ERROR
# FATAL
#
# d = date/time
# p = priority (Level)
# c = category/channel
# m = message
# F = file
# L = line
# n = platform dependent line separator character or characters.
# ....
#
# Examples for console:
# a)
# %d %p %c #%m# (%.50F:%L)%n
# date/time
# priority
# category/channel
# #message#
# (Maximal 50Character des Filename von rechts:Line)
# line separator
#
# b)
# %d (%.15F:%L) %-5p %c |#| %m%n
# date/time
# (Maximal 15Character des Filename von rechts:Line)
# priority, Right pad with spaces if the priority name is less than 5 characters long.
# category/channel
# message
# line separator
#
# Examples for files:
+36
View File
@@ -0,0 +1,36 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace SituationReplay
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "SRP.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try {
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger( loggerName );
} catch ( const std::exception &ex )
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
} // namespace SituationReplay
+24
View File
@@ -0,0 +1,24 @@
/**
* @RDE_HEADER@
* Logging for SituationReplay
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
#include "srp_export.h"
namespace SituationReplay
{
using LOGGER_T = NGL::INGLLogger &;
SRP_COMMON_EXPORT LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace SituationReplay
+93
View File
@@ -0,0 +1,93 @@
/**
* @RDE_HEADER@
* main for SituationReplay
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include "dds_handler.h"
#include "main_handler.h"
#include "logger.h"
#include "settings.h"
class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
{
public:
CmdLineParser()
: LtsCommandLineParser(ProvideCommandLineParameterOptions(CreateDomainIdFromIp|DomainId|ExerciseId))
{
addOption({ QStringList() << QLatin1String("input"),
QLatin1String("information for the input side (domainId,exerciseId,<tcpConnectionParams>"),
QLatin1String("1,42,tcpv4lan://srv:port"),
QString()
});
addOption({ QStringList() << QLatin1String("output"),
QLatin1String("information for the output side (domainId,replayId,<tcpConnectionParams>"),
QLatin1String("2,1,tcpv4lan://srv:port"),
QString()
});
}
QString inputParams() const { return isSet(QLatin1String("input")) ? value(QLatin1String("input")) : QString(); }
QString outputParams() const { return isSet(QLatin1String("output")) ? value(QLatin1String("output")) : QString(); }
};
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
CmdLineParser options;
if (!options.init())
return -1;
SituationReplay::ConnectionParams input, output;
if (!SituationReplay::DdsHandler::parseOptions(options.inputParams(), input))
{
app.createLogger("SRP", options.exerciseId());
ERROR_LOG(app.baseLogger()) << "Can not parse input params: '" << options.inputParams() << "'";
return -2;
}
if (!SituationReplay::DdsHandler::parseOptions(options.outputParams(), output))
{
app.createLogger("SRP", options.exerciseId());
ERROR_LOG(app.baseLogger()) << "Can not parse output params: '" << options.outputParams() << "'";
return -3;
}
//set output exercise id = input exercise id
input.exerciseId = input.partitionId;
output.exerciseId = input.partitionId;
app.createLogger("SRP", input.partitionId, output.partitionId);
SituationReplay::Settings::setIniFile(options.iniFile());
int iRet = -4;
{
std::unique_ptr<SituationReplay::MainHandler> mainHandler(new SituationReplay::MainHandler);
NOTICE_LOG(app.baseLogger()) << "Input domainId: " << input.domainId
<< ", partition id: " << input.partitionId
<< ", exercise id: " << input.exerciseId
<< (input.discoveryPeer.isEmpty() ? QString() : QStringLiteral(", discovery: ") + input.discoveryPeer.toString());
NOTICE_LOG(app.baseLogger()) << "Output domainId: " << output.domainId
<< ", replayId: " << output.partitionId
<< ", exerciseid: " << output.exerciseId
<< (output.discoveryPeer.isEmpty() ? QString() : QStringLiteral(", discovery: ") + output.discoveryPeer.toString());
if (!mainHandler->init(input, output))
return iRet;
STARTUP_LOG(app.baseLogger());
iRet = app.exec();
SHUTDOWN_LOG(app.baseLogger());
}
return iRet;
}
+74
View File
@@ -0,0 +1,74 @@
/**
* MainHandler for SituationReplay
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#include "main_handler.h"
#include "settings.h"
#include "db_reader.h"
#include "handler_situation_replay.h"
#include <DDS/DDSConnector/dds_connector.h>
#include <ngldb/db_service_handler.h>
namespace SituationReplay
{
MainHandler::MainHandler()
: m_handlerSrp(nullptr)
, m_ddsInterface(nullptr)
, m_dbHandler(nullptr)
, m_logger(getLogger("MainHandler"))
{}
MainHandler::~MainHandler()
{
m_dbReader = nullptr;
m_handlerSrp = nullptr;
m_ddsInterface = nullptr;
m_dbHandler = nullptr;
}
bool MainHandler::init(const SituationReplay::ConnectionParams &input,
const SituationReplay::ConnectionParams &output)
{
// initialize database
m_dbHandler = std::make_shared<DbHandler>();
if (!m_dbHandler->init(input.partitionId, Settings::settings()))
{
ERROR_LOG(m_logger) << "Initialisation dbHandler failed.";
return false;
}
// initialize DDS
m_ddsInterface = std::make_shared<DdsHandler>(input, output);
if (!m_ddsInterface->init())
return false;
m_dbReader = std::make_shared<DbReader>(m_ddsInterface->ddsReplay(), input.partitionId, true);
if (!m_dbReader->init(m_dbHandler->db()->database()))
return false;
// read project specific data from database
// publish project specific data
// initialize the specific handler
if (!initSrpHandler(input.partitionId, output.partitionId))
return false;
return true;
}
bool MainHandler::initSrpHandler(int partitionIdIn, int partitionIdOut)
{
m_handlerSrp.reset(new HandlerSituationReplay(m_ddsInterface, m_dbHandler->db(), m_dbReader));
if (!m_handlerSrp->init(partitionIdIn, partitionIdOut))
return false;
return true;
}
} // namespace SituationReplay
+47
View File
@@ -0,0 +1,47 @@
/**
* MainHandler for SituationReplay
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <memory>
#include "dds_handler.h"
#include "logger.h"
#include <SituationReplay/srp_db.h>
namespace NGLDB
{
template <typename DB> class DbServiceHandler;
}
namespace SituationReplay
{
class DbReader;
class HandlerSituationReplay;
using DbHandler = NGLDB::DbServiceHandler<DatabaseInterface>;
class MainHandler final
{
public:
MainHandler();
~MainHandler();
bool init(const ConnectionParams &input,
const ConnectionParams &output);
private:
bool initSrpHandler(int partitionIdIn, int partitionIdOut);
private:
std::unique_ptr<HandlerSituationReplay> m_handlerSrp;
std::shared_ptr<DdsHandler> m_ddsInterface;
std::shared_ptr<DbHandler> m_dbHandler;
std::shared_ptr<DbReader> m_dbReader;
NGL::INGLLogger &m_logger;
};
} // namespace SituationReplay
+318
View File
@@ -0,0 +1,318 @@
/**
* MainHandlerSqlite for SituationReplay
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#include "main_handler_sqlite.h"
#include "db_reader.h"
#include "static_publisher.h"
#include "handler_situation_replay_sqlite.h"
#include <DDS/DDSConnector/dds_connector.h>
#include <ngldb/db_service_handler.h>
#include <ngldb/nsqlquery.h>
#include <LtsScriptTimeline/track_entry.h>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QSet>
#include <QSqlError>
namespace SituationReplay
{
MainHandlerSqlite::MainHandlerSqlite()
: m_curFilterArrayIdx(-1)
, m_curOverlayArrayIdx(-1)
, m_handlerSrp(nullptr)
, m_staticPublisher(nullptr)
, m_ddsInterface(nullptr)
, m_dbHandler(nullptr)
, m_logger(getLogger("MainHandlerSqlite"))
{}
MainHandlerSqlite::~MainHandlerSqlite()
{
m_dbSqlite.close();
m_dbSqlite = QSqlDatabase();
m_staticPublisher = nullptr;
m_dbReader = nullptr;
m_handlerSrp = nullptr;
m_ddsInterface = nullptr;
m_dbHandler = nullptr;
}
bool MainHandlerSqlite::initDb(const ReplayInformation &replayInformation,
const QVector<FilterInformation> &filter,
const QVector<FilterInformation> &overlays)
{
if (!m_ddsInterface)
{
WARNING_LOG(m_logger) << "dds must be initialized first!";
return false;
}
m_replay = replayInformation;
// sort filter & overlays by begin time
const auto cbSort = [](const FilterInformation &a, const FilterInformation &b)
{
if (a.relativeTimeSpan.begin != b.relativeTimeSpan.begin)
return a.relativeTimeSpan.begin < b.relativeTimeSpan.begin;
return a.overlayId < b.overlayId;
};
m_filter = filter;
std::sort(m_filter.begin(), m_filter.end(), cbSort);
m_curFilterArrayIdx = -1;
m_overlays = overlays;
std::sort(m_overlays.begin(), m_overlays.end(), cbSort);
m_curOverlayArrayIdx = -1;
m_staticPublisher = nullptr;
m_handlerSrp = nullptr;
m_dbReader = nullptr;
m_dbHandler = nullptr;
if (m_dbSqlite.isOpen())
{
m_dbSqlite.close();
m_dbSqlite = QSqlDatabase();
QSqlDatabase::removeDatabase(QStringLiteral("sqliteDb"));
}
// initialize database
m_dbSqlite = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("sqliteDb"));
m_dbSqlite.setDatabaseName(replayInformation.databaseFilePath);
if (!m_dbSqlite.open())
{
const QString err = m_dbSqlite.lastError().nativeErrorCode();
FATAL_LOG(m_logger) << "Error opening database '" << replayInformation.databaseFilePath << "'";
FATAL_LOG(m_logger) << m_dbSqlite.lastError().driverText() << " "
<< m_dbSqlite.lastError().databaseText() << " " << err;
return false;
}
const QString stmt(QStringLiteral("SELECT id FROM exercise"));
NSqlQuery q(stmt, m_dbSqlite);
const int partitionIdIn = (q.execAndFetch() ? q.value(0).toInt() : 0);
m_dbHandler = std::make_shared<DbHandler>();
if (!m_dbHandler->init(partitionIdIn, m_dbSqlite))
{
ERROR_LOG(m_logger) << "Initialisation dbHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "opening sqlite db successful";
m_dbReader = std::make_shared<DbReader>(m_ddsInterface->ddsReplay(), partitionIdIn, false);
if (!m_dbReader->init(m_dbHandler->db()->database()))
{
ERROR_LOG(m_logger) << "Could not initialize database reader";
return false;
}
// read project specific data from database
// publish project specific data
// initialize the specific handler
if (!initSrpHandler(partitionIdIn, m_ddsInterface->ddsReplay()->getPartitionId(),
replayInformation.timeSpan.begin, replayInformation.timeSpan.end))
{
ERROR_LOG(m_logger) << "Could not initialize situation replay handler";
return false;
}
if (!initStaticPublisher())
return false;
if (!loadReplayConfig(replayInformation.replayConfigPath))
return false;
return true;
}
bool MainHandlerSqlite::initDds(const SituationReplay::ConnectionParams &output)
{
// initialize DDS
m_ddsInterface = std::make_shared<DdsHandler>(output);
if (!m_ddsInterface->init())
return false;
return true;
}
std::shared_ptr<DDSConnector::DdsConnector> MainHandlerSqlite::ddsReplay() const
{
return m_ddsInterface->ddsReplay();
}
bool MainHandlerSqlite::initSrpHandler(int partitionIdIn, int partitionIdOut, qint64 beginTime, qint64 endTime)
{
m_handlerSrp.reset(new HandlerSituationReplaySqlite(m_ddsInterface, m_dbReader));
if (!m_handlerSrp->init(partitionIdIn, partitionIdOut, beginTime, endTime))
return false;
connect(m_handlerSrp.get(), &HandlerSituationReplaySqlite::replayTimeChanged,
this, &MainHandlerSqlite::onReplayTimeChanged);
connect(m_handlerSrp.get(), &HandlerSituationReplaySqlite::started,
this, &MainHandlerSqlite::onReplayTimeMaybeJumped);
connect(m_handlerSrp.get(), &HandlerSituationReplaySqlite::resumed,
this, &MainHandlerSqlite::onReplayTimeMaybeJumped);
return true;
}
bool MainHandlerSqlite::initStaticPublisher()
{
m_staticPublisher.reset(new StaticPublisher(m_ddsInterface, m_dbSqlite));
connect(m_staticPublisher.get(), &StaticPublisher::fileContentAvailable,
this, &MainHandlerSqlite::fileContentAvailable);
return true;
}
bool MainHandlerSqlite::loadReplayConfig(const QString &replayConfigPath)
{
QFile f(replayConfigPath);
if (!f.open(QIODevice::ReadOnly))
{
WARNING_LOG(m_logger) << "Could not open '" << replayConfigPath << "' for reading - no replay config loaded";
return false;
}
QJsonParseError error;
const QJsonDocument doc(QJsonDocument::fromJson(f.readAll(), &error));
if (error.error != QJsonParseError::NoError)
{
WARNING_LOG(m_logger) << "Could not parse replay config loaded json file: " << error.errorString();
return false;
}
const QJsonObject obj = doc.object();
const double replaySpeed = obj[QStringLiteral("speed")].toDouble(1.0);
emit initialReplaySpeed(replaySpeed);
return true;
}
void MainHandlerSqlite::onReplayTimeChanged(qint64 curTime)
{
maybeApplyNextFilter(curTime);
maybeAddNewOverlay(curTime);
removeOutdatedOverlays(curTime);
}
void MainHandlerSqlite::onReplayTimeMaybeJumped(qint64 curTime)
{
replayTimeMaybeJumpedFilter(curTime);
replayTimeMaybeJumpedOverlays(curTime);
}
void MainHandlerSqlite::maybeApplyNextFilter(qint64 curTime)
{
const int nextIdx = findNextIndex(curTime,
m_curFilterArrayIdx,
m_filter);
if (nextIdx < 0)
return;
m_curFilterArrayIdx = nextIdx;
emit applyCurentFilter(m_filter.at(m_curFilterArrayIdx));
}
void MainHandlerSqlite::replayTimeMaybeJumpedFilter(qint64 curTime)
{
const qint64 curTimeRelative = curTime - m_replay.timeSpan.begin;
m_curFilterArrayIdx = -1;
for (int i = 0; i < m_filter.size(); ++i)
{
const auto &filter = m_filter.at(i);
if (filter.relativeTimeSpan.begin > curTimeRelative)
break;
m_curFilterArrayIdx = i;
}
if (m_curFilterArrayIdx >= 0 && m_curFilterArrayIdx < m_filter.size())
emit applyCurentFilter(m_filter.at(m_curFilterArrayIdx));
}
void MainHandlerSqlite::maybeAddNewOverlay(qint64 curTime)
{
// more than one overlay can start at curTime
while (true)
{
const int nextIdx = findNextIndex(curTime,
m_curOverlayArrayIdx,
m_overlays);
if (nextIdx < 0)
return;
m_curOverlayArrayIdx = nextIdx;
m_currentVisibleOverlays += m_overlays.at(nextIdx);
DEBUG_LOG(m_logger) << "Showing new overlay with id " << m_overlays.at(m_curOverlayArrayIdx).overlayId
<< " at time " << curTime;
emit applyNewOverlay(m_overlays.at(m_curOverlayArrayIdx).overlayId);
}
}
void MainHandlerSqlite::removeOutdatedOverlays(qint64 curTime)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " curTime = "<< curTime
<< " m_currentVisibleOverlays.size()= "<< m_currentVisibleOverlays.size();
const qint64 curTimeRelative = curTime - m_replay.timeSpan.begin + m_replay.relativeTimeSpan.begin; // + m_replay.relativeTimeSpan.begin
for (int i = m_currentVisibleOverlays.size() - 1; i >= 0; --i)
{
const qint64 endTime = m_currentVisibleOverlays.at(i).relativeTimeSpan.end;
DEBUG_LOG(m_logger) << LOGFUNCTION << " curTimeRelative = " << curTimeRelative << " endTime = " << endTime;
if (curTimeRelative > endTime)
{
emit removeOverlay(m_currentVisibleOverlays.at(i).overlayId);
m_currentVisibleOverlays.removeAt(i);
}
}
}
void MainHandlerSqlite::replayTimeMaybeJumpedOverlays(qint64 curTime)
{
// not really optimal
QSet<int> oldOverlayIds;
oldOverlayIds.reserve(m_currentVisibleOverlays.size());
for (const FilterInformation &overlay : qAsConst(m_currentVisibleOverlays))
oldOverlayIds += overlay.overlayId;
m_curOverlayArrayIdx = -1;
m_currentVisibleOverlays.clear();
maybeAddNewOverlay(curTime);
for (const FilterInformation &overlay : qAsConst(m_currentVisibleOverlays))
oldOverlayIds -= overlay.overlayId;
for (const int overlayId : qAsConst(oldOverlayIds))
emit removeOverlay(overlayId);
}
// struct ReplayInformation
// {
// int id = 0;
// TimeSpan timeSpan; // playbackTime msec since epoche
// TimeSpan relativeTimeSpan; // timeInPresentation msec since begin SCRIPT
int MainHandlerSqlite::findNextIndex(qint64 curTime, int curIdx, const QVector<FilterInformation> &data) const
{
const int nextIdx = curIdx + 1;
if (nextIdx < 0 || nextIdx >= data.size())
return -1;
const qint64 curTimeRelative = (curTime - m_replay.timeSpan.begin) + m_replay.relativeTimeSpan.begin;
// ^abs ^absBgn cur Topic/Replay + timeInPresentation since begin SCRIPT
// example: 1645787949000 - 1645787949000 + 375000
// startTime: msec, rel. to begin of SCRIPT
const qint64 startTime = data.at(nextIdx).relativeTimeSpan.begin;
DEBUG_LOG(m_logger) << LOGFUNCTION << " curTimeRelative = " << curTimeRelative << " startTime = " << startTime;
if (curTimeRelative < startTime)
return -1;
return nextIdx;
}
} // namespace SituationReplay
+135
View File
@@ -0,0 +1,135 @@
/**
* MainHandlerSqlite for AereaEffectSimulation
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <QJsonObject>
#include <QObject>
#include <QSqlDatabase>
#include <memory>
#include "dds_handler.h"
#include "logger.h"
#include <SituationReplay/srp_db.h>
#include <SituationReplay/situationreplaysqlite_export.h>
namespace DDSConnector
{
class DdsConnector;
}
namespace NGLDB
{
template <typename DB> class DbServiceHandler;
}
namespace FileManagement
{
namespace Database
{
struct FlmFileContent;
}
}
namespace SituationReplay
{
struct TimeSpan
{
qint64 begin = 0;
qint64 end = 0;
static SituationReplay::TimeSpan fromJson(const QJsonObject &obj)
{
SituationReplay::TimeSpan ts;
ts.begin = qRound64(obj[QStringLiteral("start")].toDouble());
ts.end = qRound64(obj[QStringLiteral("end")].toDouble());
return ts;
}
QJsonObject toJson() const
{
return {
{QStringLiteral("start"), begin},
{QStringLiteral("end"), end},
};
}
};
struct ReplayInformation
{
int id = 0;
TimeSpan timeSpan; // playbackTime msec since epoche
TimeSpan relativeTimeSpan; // timeInPresentation msec since begin SCRIPT
QString databaseFilePath; // path to sqlite db
QString replayConfigPath; // sitmap.json
};
struct FilterInformation
{
int id = 0;
int overlayId = 0;
TimeSpan relativeTimeSpan;
QJsonObject aesFilters;
QJsonObject symbolSettings;
QJsonObject buildingComponentSettings;
QJsonObject mapSettings;
};
class DbReader;
class StaticPublisher;
class HandlerSituationReplaySqlite;
using DbHandler = NGLDB::DbServiceHandler<DatabaseInterface>;
class SITUATIONREPLAYSQLITE_EXPORT MainHandlerSqlite final : public QObject
{
Q_OBJECT
public:
MainHandlerSqlite();
~MainHandlerSqlite();
bool initDb(const ReplayInformation &replayInformation,
const QVector<FilterInformation> &filter,
const QVector<FilterInformation> &overlays);// first init dds needed!
bool initDds(const ConnectionParams &output);
std::shared_ptr<HandlerSituationReplaySqlite> handlerSrp() const { return m_handlerSrp; }
std::shared_ptr<DDSConnector::DdsConnector> ddsReplay() const;
Q_SIGNALS:
void initialReplaySpeed(double speed);
void applyCurentFilter(const SituationReplay::FilterInformation &filter);
void applyNewOverlay(int overlayId);
void removeOverlay(int overlayId);
void fileContentAvailable(const FileManagement::Database::FlmFileContent &data);
private:
bool initSrpHandler(int partitionIdIn, int partitionIdOut, qint64 beginTime, qint64 endTime);
bool initStaticPublisher();
bool loadReplayConfig(const QString &replayConfigPath);
void maybeApplyNextFilter(qint64 curTime);
void replayTimeMaybeJumpedFilter(qint64 curTime);
void maybeAddNewOverlay(qint64 curTime);
void removeOutdatedOverlays(qint64 curTime);
void replayTimeMaybeJumpedOverlays(qint64 curTime);
int findNextIndex(qint64 curTime, int curIdx, const QVector<FilterInformation> &data) const;
private Q_SLOTS:
void onReplayTimeChanged(qint64 curTime);
void onReplayTimeMaybeJumped(qint64 curTime);
private:
QVector<FilterInformation> m_filter;
QVector<FilterInformation> m_overlays;
QVector<FilterInformation> m_currentVisibleOverlays;
ReplayInformation m_replay;
int m_curFilterArrayIdx;
int m_curOverlayArrayIdx;
std::shared_ptr<HandlerSituationReplaySqlite> m_handlerSrp;
std::unique_ptr<StaticPublisher> m_staticPublisher;
std::shared_ptr<DdsHandler> m_ddsInterface;
std::shared_ptr<DbHandler> m_dbHandler;
std::shared_ptr<DbReader> m_dbReader;
QSqlDatabase m_dbSqlite;
NGL::INGLLogger &m_logger;
};
} // namespace SituationReplay
+292
View File
@@ -0,0 +1,292 @@
/**
* situation replay objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#include "object_situation_replay.h"
#include "dds_handler.h"
#include "db_reader.h"
#include "logger.h"
#include <QDateTime>
#include <QTimer>
#include <QElapsedTimer>
namespace SituationReplay
{
ObjectSituationReplay::ObjectSituationReplay(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DatabaseInterface> &db,
const std::shared_ptr<DbReader> &dbReader,
int exerciseId)
: m_ddsInterface(ddsHandler)
, m_db(db)
, m_dbReader(dbReader)
, m_exerciseId(exerciseId)
, m_replayTimer(new QTimer(this))
, m_currentReplayTime(0)
, m_logger(getLogger("ObjectSituationReplay"))
{
connect(m_replayTimer, &QTimer::timeout, this, &ObjectSituationReplay::onReplayTimerTimeout);
}
ObjectSituationReplay::~ObjectSituationReplay()
{
m_ddsInterface->dts()->removeSitReplayByKey(m_data.id);
delete m_replayTimer;
}
bool ObjectSituationReplay::isStopped() const
{
return (m_data.srpStateId == SituationReplay::SrpState_def::Stopped);
}
bool ObjectSituationReplay::isRunning() const
{
return (m_data.srpStateId == SituationReplay::SrpState_def::Started ||
m_data.srpStateId == SituationReplay::SrpState_def::Resumed);
}
Core::FunctionReplyObject ObjectSituationReplay::createObject(const Database::SrpSituationReplay &data)
{
static int s_idCounter = 1;
m_data = data;
setPace(m_data.pace);
m_data.id = 0;
m_data.srpStateId = SituationReplay::SrpState_def::Unknown;
m_currentReplayTime = m_data.beginTime;
if (m_db)
{
if (!m_db->insert(m_data))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting SrpSitatuationReplay-data into database"));
}
else
{
m_data.id = s_idCounter++;
}
// Id is serial -> will be generated by db => inside m_data after db-insert
DEBUG_LOG(m_logger) << "New srpId: " << m_data.id;
switchToState(SituationReplay::SrpState_def::Stopped);
return Core::FunctionReplyObject(m_data.id);
}
Core::FunctionReplyObject ObjectSituationReplay::removeObject()
{
switchToState(SrpState::Stopped);
if (m_db && !m_db->removeSrpSituationReplay(m_data.id))
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "SituationReplay %1 can not be removed")).arg(m_data.id);
m_ddsInterface->dts()->removeSitReplayByKey(m_data.id);
return Core::FunctionReplyObject(m_data.id);
}
bool ObjectSituationReplay::setPace(double newPace)
{
if (newPace < 0)
{
WARNING_LOG(m_logger) << "Trying to set a pace < 0";
return false;
}
m_data.pace = newPace;
return true;
}
bool ObjectSituationReplay::setSrpData(const Database::SrpSituationReplay &newData)
{
const int id = m_data.id;
m_data = newData;
setPace(m_data.pace);
m_data.srpStateId = SituationReplay::SrpState::Unknown;
m_data.id = id;
m_currentReplayTime = m_data.beginTime;
switchToState(newData.srpStateId);
if (m_db)
{
if (!m_db->update(m_data))
{
ERROR_LOG(m_logger) << "Error updating SitReplay data in database (exerciseState)";
return false;
}
Database::SrpReplayJournal stateChange;
stateChange.situationReplayId = m_data.id;
stateChange.beginTime = m_data.beginTime;
stateChange.endTime = m_data.endTime;
stateChange.pace = m_data.pace;
stateChange.replayPartitionId = m_data.replayPartitionId;
stateChange.srpStateId = m_data.srpStateId;
stateChange.changedAt = QDateTime::currentDateTime();
// record SrpStateChange
if (!m_db->insert(stateChange))
WARNING_LOG(m_logger) << "Recording change of srpState failed";
}
// Publish Data via DTS
onPublishReplayInformation();
return true;
}
bool ObjectSituationReplay::start()
{
INFO_LOG(m_logger) << "start: " << m_currentReplayTime;
m_currentReplayTime = m_data.beginTime;
emit started(m_currentReplayTime);
// Read all data for a certain interval
if (!m_dbReader->setReplayStartTime(m_currentReplayTime))
return false;
if (!checkPublishData())
return false;
m_replayTimer->start(1000);
return true;
}
bool ObjectSituationReplay::pause()
{
INFO_LOG(m_logger) << "paused: " << m_currentReplayTime;
m_replayTimer->stop();
emit paused();
return true;
}
bool ObjectSituationReplay::resume()
{
INFO_LOG(m_logger) << "resumed" << m_currentReplayTime;
m_replayTimer->start(1000);
emit resumed(m_currentReplayTime);
return true;
}
bool ObjectSituationReplay::stop()
{
INFO_LOG(m_logger) << "stopped: " << m_currentReplayTime;
m_replayTimer->stop();
emit stopped();
return true;
}
void ObjectSituationReplay::onPublishReplayInformation()
{
const SituationReplay::SitReplay ddsData(m_data.id,
m_data.srpStateId,
m_exerciseId,
m_data.replayPartitionId,
m_data.beginTime,
m_data.endTime,
m_data.pace);
INFO_LOG(m_logger) << "Publish SitReplay data: " << ddsData;
if (!m_ddsInterface->dts()->publish(ddsData))
ERROR_LOG(m_logger) << "Error publishing SitReplay data to dds";
}
void ObjectSituationReplay::onPublishReplayTime()
{
// publish partitionTime
m_ddsInterface->publishPartitionTime(Core::PartitionTime(m_currentReplayTime));
emit replayTimeChanged(m_currentReplayTime);
}
void ObjectSituationReplay::onReplayTimerTimeout()
{
m_currentReplayTime += qRound64(m_data.pace * 1000);
DEBUG_LOG(m_logger) << "onReplayTimerTimeout, endTime: " << m_data.endTime << " - " << m_currentReplayTime;
checkPublishData();
}
bool ObjectSituationReplay::checkPublishData()
{
INFO_LOG(m_logger) << " checkPublishData...";
onPublishReplayTime();
if (m_data.endTime != 0 && m_data.endTime < m_currentReplayTime)
{
if (switchToState(SrpState_def::Stopped).error())
return false;
}
else
{
QElapsedTimer timer; if (m_logger.isInfoEnabled()) timer.start();
// publish data for current time
m_dbReader->publish(m_currentReplayTime);
if (m_logger.isInfoEnabled()) INFO_LOG(m_logger) << "m_dbReader->publish took " << timer.elapsed() << " [ms]";
if (qFuzzyIsNull(m_data.pace)) // pace == 0 -> snapshot
{
QElapsedTimer timerReadData; if (m_logger.isInfoEnabled()) timerReadData.start();
m_dbReader->waitForAsyncOperations(m_data.endTime);
if (switchToState(SrpState_def::Stopped).error())
return false;
if (m_logger.isInfoEnabled()) INFO_LOG(m_logger) << "m_dbReader->waitForAsyncOperations took " << timerReadData.elapsed() << " [ms]";
}
else
{
QElapsedTimer timerReadData; if (m_logger.isInfoEnabled()) timerReadData.start();
// read next chunk
if (!m_dbReader->readData(m_currentReplayTime, m_currentReplayTime + qRound64(m_data.pace * 1000)))
return false;
if (m_logger.isInfoEnabled()) INFO_LOG(m_logger) << "m_dbReader->readData took " << timerReadData.elapsed() << " [ms]";
}
}
INFO_LOG(m_logger) << " checkPublishData... DONE";
return true;
}
Core::FunctionReplyObject ObjectSituationReplay::switchToState(SrpState newSrpState)
{
Core::FunctionReplyObject ret(m_data.id);
INFO_LOG(m_logger) << "-------------- switchTo: " << newSrpState
<< ", current: " << m_data.srpStateId;
if (m_data.srpStateId != newSrpState)
{
switch (newSrpState.underlying())
{
case SrpState_def::Paused:
if (!pause())
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not pause replay"));
break;
case SrpState_def::Resumed:
if (!resume())
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not resume replay"));
break;
case SrpState_def::Started:
if (!start())
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not start replay"));
break;
case SrpState_def::Stopped:
if (!stop())
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not stop replay"));
break;
default:
break;
}
m_data.srpStateId = newSrpState;
onPublishReplayInformation();
}
return ret;
}
} // Namespace SituationReplay
+88
View File
@@ -0,0 +1,88 @@
/**
* situation replay objects
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <QObject>
#include <QTimer>
#include "dds_handler.h"
#include "db_reader.h"
#include <DDS/Core/function_reply_object.h>
// Generated
#include <SituationReplay/srp_db.h>
namespace SituationReplay
{
class DatabaseInterface;
class DbReader;
class ObjectSituationReplay : public QObject
{
Q_OBJECT
public:
explicit ObjectSituationReplay(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DatabaseInterface> &db,
const std::shared_ptr<DbReader> &dbReader,
int exerciseId);
~ObjectSituationReplay();
Core::FunctionReplyObject createObject(const Database::SrpSituationReplay &data);
Core::FunctionReplyObject removeObject();
qint32 getId() const { return m_data.id; }
qint32 getExerciseId() const { return m_exerciseId; }
qint32 getReplayPartitionId() const { return m_data.replayPartitionId; }
qint64 currentReplayTime() const { return m_currentReplayTime; }
SrpState srpState() const { return m_data.srpStateId; }
double pace() const { return m_data.pace; }
bool setPace(double newPace);
// Used by SrpStateManager (only internal)
bool setSrpData(const Database::SrpSituationReplay &newData);
// Used by Client
Core::FunctionReplyObject switchToState(SrpState newSrpState);
bool isRunning() const;
bool isStopped() const;
bool start();
bool pause();
bool resume();
bool stop();
protected Q_SLOTS:
void onPublishReplayInformation();
void onPublishReplayTime();
void onReplayTimerTimeout();
private:
bool checkPublishData();
Q_SIGNALS:
// for thp
void replayTimeChanged(qint64 currentReplayTime);
void started(qint64 currentReplayTime);
void paused();
void resumed(qint64 currentReplayTime);
void stopped();
private:
std::shared_ptr<DdsHandler> m_ddsInterface;
std::shared_ptr<DatabaseInterface> m_db;
std::shared_ptr<DbReader> m_dbReader;
Database::SrpSituationReplay m_data;
int m_exerciseId;
QTimer *m_replayTimer;
qint64 m_currentReplayTime;
NGL::INGLLogger &m_logger;
};
}
+42
View File
@@ -0,0 +1,42 @@
/**
* Settings for SituationReplay
* $Id$
* $HeadURL$
* $Author$
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
namespace SituationReplay
{
class NGLSettingsClass : public NGL::Settings
{
public:
NGLSettingsClass()
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
{}
static void setIniFile(const QString &fn)
{
s_iniFile = fn;
}
static QString s_iniFile;
};
QString NGLSettingsClass::s_iniFile;
Q_GLOBAL_STATIC(NGLSettingsClass, s)
//-----------------------------------------------------------------------------
NGL::Settings *Settings::settings()
{
return s();
}
//-----------------------------------------------------------------------------
void Settings::setIniFile(const QString &ini)
{
NGLSettingsClass::setIniFile(ini);
}
} // namespace SituationReplay
+26
View File
@@ -0,0 +1,26 @@
/**
* Settings for SituationReplay
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include <QString>
namespace NGL
{
class Settings;
}
namespace SituationReplay
{
namespace Settings
{
//!< The real NGL::Settings - object
NGL::Settings *settings();
void setIniFile(const QString &ini);
}
} // namespace SituationReplay
+52
View File
@@ -0,0 +1,52 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-08-04
*/
#pragma once
#include <QtCore/qglobal.h>
#ifndef SRP_COMMON_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define SRP_COMMON_EXPORT
# else
# if defined(MAKE_SVCSRPCOMMON_LIB)
# define SRP_COMMON_EXPORT Q_DECL_EXPORT
# ifndef WIN32
# ifdef NDDSUSERDllExport
# undef NDDSUSERDllExport
# endif
# define NDDSUSERDllExport Q_DECL_EXPORT
# endif
# else
# define SRP_COMMON_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef SRP_CLIENT_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define SRP_CLIENT_EXPORT
# else
# if defined(MAKE_SVCSRPCLIENT_LIB)
# define SRP_CLIENT_EXPORT Q_DECL_EXPORT
# else
# define SRP_CLIENT_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef SRP_SERVER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define SRP_SERVER_EXPORT
# else
# if defined(MAKE_SVCSRPSERVER_LIB)
# define SRP_SERVER_EXPORT Q_DECL_EXPORT
# else
# define SRP_SERVER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
+83
View File
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<service namespace="SituationReplay" abbreviation="SRP" procNames="SituationReplay" exerciseDependency="Exercise">
<rcs>
<Id Id="$Id$"/>
<HeadURL HeadURL="$HeadURL$"/>
<Author Author="$Author$"/>
</rcs>
<tables>
<table name="srp_replay_journal" comment="Information about past and currently used situation replay(as a journal)">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="situation_replay_id" datatype="integer"/>
<column name="replay_partition_id" datatype="integer"/>
<column name="srp_state_id" datatype="integer" isForeignKey="1"/>
<column name="begin_time" datatype="bigint"/>
<column name="end_time" datatype="bigint"/>
<column name="changed_at" datatype="timestamp"/>
<column name="pace" datatype="real"/>
<foreignKey name="FK_srp_journal_srp_state">
<source table="srp_replay_journal" column="srp_state_id"/>
<destination table="srp_state" column="id"/>
</foreignKey>
</table>
<table name="srp_situation_replay">
<column name="id" datatype="integer" isPrimaryKey="1">
<sequence start="1" increment="1"/>
</column>
<column name="srp_state_id" datatype="integer" isForeignKey="1"/>
<column name="replay_partition_id" datatype="integer"/>
<column name="begin_time" datatype="bigint"/>
<column name="end_time" datatype="bigint"/>
<column name="pace" datatype="real"/>
<foreignKey name="FK_srp_situation_replay_srp_state">
<source table="srp_situation_replay" column="srp_state_id"/>
<destination table="srp_state" column="id"/>
</foreignKey>
</table>
<table name="srp_state">
<column name="id" datatype="integer" isPrimaryKey="1"/>
<column name="name" datatype="text"/>
</table>
</tables>
<views/>
<dbServiceStructs>
<serviceStruct name="SrpReplayJournal" table="srp_replay_journal"/>
<serviceStruct name="SrpSituationReplay" table="srp_situation_replay"/>
<table name="srp_replay_journal"/>
<table name="srp_situation_replay"/>
</dbServiceStructs>
<topicTypes>
<topicType name="ChangeReplayStateRequest">
<column name="id" idlType="long"/>
<column name="state" idlType="SrpState"/>
<column name="replayPartitionId" idlType="long"/>
<column name="beginTime" idlType="long long"/>
<column name="endTime" idlType="long long"/>
<column name="pace" idlType="double" isOptional="1"/>
</topicType>
<topicType name="SitReplay" extensibility="EXTENSIBLE" isDataObject="1" routeToClient="1" routeToServer="0" routeInReplay="0">
<column name="id" idlType="long" isKey="1"/>
<column name="state" idlType="SrpState"/>
<column name="exerciseId" idlType="long" comment="Only in idl-struct, not needed in table"/>
<column name="replayPartitionId" idlType="long"/>
<column name="beginTime" idlType="long long"/>
<column name="endTime" idlType="long long"/>
<column name="pace" idlType="double"/>
</topicType>
</topicTypes>
<functionTopics>
<functionTopic name="ChangeReplayState" requestTopicType="ChangeReplayStateRequest" replyTopicType="Core::FunctionReply" requestTopicName="ChangeReplayStateRequest" replyTopicName="ChangeReplayStateReply" routeInReplay="0"/>
</functionTopics>
<enumerations>
<enumeration name="SrpState" table="srp_state">
<attribute key="Unknown" value="0"/>
<attribute key="Started" value="1"/>
<attribute key="Paused" value="2"/>
<attribute key="Resumed" value="3"/>
<attribute key="Stopped" value="4"/>
</enumeration>
</enumerations>
<operatorRights offset="36"/>
</service>
+244
View File
@@ -0,0 +1,244 @@
/**
* Publish static data (pdm, asm, ism) for THP
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#include "static_publisher.h"
#include <QCryptographicHash>
#include <QJsonDocument>
#include <QTimer>
#include <DDS/DTS/generic_dts_impl.h>
#include <AssetManagement/asm_db.h>
#include <AssetManagement/convert_db_to_dds.h>
#include <ExerciseManagement/exm_db.h>
#include <ExerciseManagement/convert_db_to_dds.h>
#include <FileManagement/flm_db.h>
#include <FileManagement/convert_db_to_dds.h>
#include <InfrastructureManagement/ism_db.h>
#include <InfrastructureManagement/convert_db_to_dds.h>
#include <ParticipantManagement/ppm_db.h>
#include <ParticipantManagement/convert_db_to_dds.h>
#include <ProjectDataManagement/pdm_db.h>
#include <ProjectDataManagement/convert_db_to_dds.h>
namespace SituationReplay
{
StaticPublisher::StaticPublisher(const std::shared_ptr<DdsHandler> &ddsInterface,
const QSqlDatabase &db)
: m_ddsInterface(ddsInterface)
, m_db(db)
{
auto ddsConnector = ddsInterface->ddsReplay();
m_asmTrainingArea.reset(ddsConnector->createDTS<DTS::TrainingAreaImpl>());
m_exmExercise.reset(ddsConnector->createDTS<DTS::ExerciseImpl>());
m_exmExercisePhase.reset(ddsConnector->createDTS<DTS::ExercisePhaseImpl>());
m_flmFileContent.reset(ddsConnector->createDTS<DTS::FileContentImpl>());
m_flmFileTypeInfo.reset(ddsConnector->createDTS<DTS::FileTypeInfoImpl>());
m_flmFolder.reset(ddsConnector->createDTS<DTS::FolderImpl>());
m_ismMainFootprint.reset(ddsConnector->createDTS<DTS::MainFootprintImpl>());
m_ismMainStructureElement.reset(ddsConnector->createDTS<DTS::MainStructureElementImpl>());
m_ppmType.reset(ddsConnector->createDTS<DTS::TypeImpl>());
m_pdmCanComponentString.reset(ddsConnector->createDTS<DTS::CanComponentStringImpl>());
m_pdmChargeType.reset(ddsConnector->createDTS<DTS::ChargeTypeImpl>());
m_pdmFirePurpose.reset(ddsConnector->createDTS<DTS::FirePurposeImpl>());
m_pdmGearType.reset(ddsConnector->createDTS<DTS::GearTypeImpl>());
m_ppmGearTypeChargeType.reset(ddsConnector->createDTS<DTS::GearTypeChargeTypeImpl>());
m_pdmIgniterType.reset(ddsConnector->createDTS<DTS::IgniterTypeImpl>());
m_pdmIgniterFunction.reset(ddsConnector->createDTS<DTS::IgniterFunctionImpl>());
m_pdmChargeTypeIgniterTypeIgniterFunction.reset(ddsConnector->createDTS<DTS::ChargeTypeIgniterTypeIgniterFunctionImpl>());
m_pdmLoadType.reset(ddsConnector->createDTS<DTS::LoadTypeImpl>());
m_pdmChargeTypeLoadType.reset(ddsConnector->createDTS<DTS::ChargeTypeLoadTypeImpl>());
m_pdmLanguageHmi.reset(ddsConnector->createDTS<DTS::LanguageHmiImpl>());
m_pdmTranslationBlob.reset(ddsConnector->createDTS<DTS::TranslationBlobImpl>());
m_pdmVulnerabilityKind.reset(ddsConnector->createDTS<DTS::VulnerabilityKindImpl>());
QTimer::singleShot(0, this, &StaticPublisher::publishData);
}
StaticPublisher::~StaticPublisher()
{
m_asmTrainingArea = nullptr;
m_exmExercise = nullptr;
m_exmExercisePhase = nullptr;
m_flmFileContent = nullptr;
m_flmFileTypeInfo = nullptr;
m_flmFolder = nullptr;
m_ismMainFootprint = nullptr;
m_ismMainStructureElement = nullptr;
m_ppmType = nullptr;
m_pdmCanComponentString = nullptr;
m_pdmChargeType = nullptr;
m_pdmFirePurpose = nullptr;
m_pdmGearType = nullptr;
m_ppmGearTypeChargeType = nullptr;
m_pdmIgniterType = nullptr;
m_pdmIgniterFunction = nullptr;
m_pdmLoadType = nullptr;
m_pdmChargeTypeIgniterTypeIgniterFunction = nullptr;
m_pdmChargeTypeLoadType = nullptr;
m_pdmLanguageHmi = nullptr;
m_pdmTranslationBlob = nullptr;
m_pdmVulnerabilityKind = nullptr;
m_ddsInterface = nullptr;
}
void StaticPublisher::publishData()
{
{
auto db = AssetManagement::DatabaseInterface::create(0);
db->init(m_db);
db->select([this](const AssetManagement::Database::AsmTrainingArea &data) { m_asmTrainingArea->write(AssetManagement::Database::convert(data)); });
}
{
auto db = ExerciseManagement::DatabaseInterface::create(0);
db->init(m_db);
db->select([this](const ExerciseManagement::Database::ExmExercise &data) { m_exmExercise->write(ExerciseManagement::Database::convert(data)); });
db->select([this](const ExerciseManagement::Database::ExmExercisePhase &data) { m_exmExercisePhase->write(ExerciseManagement::Database::convert(data)); });
}
{
auto db = FileManagement::DatabaseInterface::create(0);
db->init(m_db);
db->select([this](const FileManagement::Database::FlmFileContent &data) { m_flmFileContent->write(FileManagement::Database::convert(data)); emit fileContentAvailable(data); });
db->select([this](const FileManagement::Database::FlmFileTypeInfo &data) { m_flmFileTypeInfo->write(FileManagement::Database::convert(data)); });
db->select([this](const FileManagement::Database::FlmFolder &data) { m_flmFolder->write(FileManagement::Database::convert(data)); });
}
{
auto db = InfrastructureManagement::DatabaseInterface::create(0);
db->init(m_db);
publishMainStructureElement(db);
}
{
auto db = ParticipantManagement::DatabaseInterface::create(0);
db->init(m_db);
db->select([this](const ParticipantManagement::Database::PpmType &data) { m_ppmType->write(ParticipantManagement::Database::convert(data)); });
}
{
auto db = ProjectDataManagement::DatabaseInterface::create(0);
db->init(m_db);
db->select([this](const ProjectDataManagement::Database::PdmCanComponentString &data) { m_pdmCanComponentString->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmChargeType &data) { m_pdmChargeType->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmFirePurpose &data) { m_pdmFirePurpose->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmGearType &data) { m_pdmGearType->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmGearTypeChargeType &data) { m_ppmGearTypeChargeType->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmIgniterType &data) { m_pdmIgniterType->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmIgniterFunction &data) { m_pdmIgniterFunction->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmChargeTypeIgniterTypeIgniterFunction &data) { m_pdmChargeTypeIgniterTypeIgniterFunction->write(ProjectDataManagement::Database::convert(data)); });
db->select([this](const ProjectDataManagement::Database::PdmLanguage &data) { m_pdmLanguageHmi->write(ProjectDataManagement::Database::convert(data)); });
publishTranslationBlob(db);
db->select([this](const ProjectDataManagement::Database::PdmVulnerabilityKind &data) { m_pdmVulnerabilityKind->write(ProjectDataManagement::Database::convert(data)); });
}
m_db = QSqlDatabase();
}
void StaticPublisher::publishMainStructureElement(const std::shared_ptr<InfrastructureManagement::DatabaseInterface> &db)
{
// read all MSE from database
QHash<qint64, InfrastructureManagement::Database::IsmMainStructureElement> mainStructureElements;
if (!db->select([&mainStructureElements] (const InfrastructureManagement::Database::IsmMainStructureElement &data) { mainStructureElements[data.id] = data;}))
return;
// read all SE from database
QHash<qint64, QVector<InfrastructureManagement::Database::IsmStructureElement>> structureElements;
if (!db->select([&structureElements](const InfrastructureManagement::Database::IsmStructureElement &data) { structureElements[data.mainStructureElementId].push_back(data);}))
return;
QHash<qint64, qint64> seId2mseId;
for (const auto &mse : qAsConst(mainStructureElements))
{
auto mseDds = InfrastructureManagement::Database::convert(mse);
auto itContSe = structureElements.constFind(mse.id);
if (itContSe == structureElements.constEnd())
continue;
for (const auto &se : itContSe.value())
{
// currently only the building, not floors, rooms or mounting points needed
// DEDÖÖM we need rooms and floors and every thing else!
//if (se.structureElementTypeId != InfrastructureManagement::StructureElementType_def::Building)
// continue;
mseDds.elements().push_back(InfrastructureManagement::Database::convert(se));
seId2mseId[se.id] = mseDds.id();
// break;
}
if (mseDds.elements().size() > 0)
m_ismMainStructureElement->write(mseDds);
}
QHash<int, QMap<int, InfrastructureManagement::Database::IsmStructureElementFootprint>> footprintSorted;
auto cb = [&footprintSorted](const InfrastructureManagement::Database::IsmStructureElementFootprint &fp)
{
footprintSorted[fp.structureElementId][fp.indexNo] = fp;
};
if (!db->select(cb))
return;
InfrastructureManagement::MainFootprint mf;
InfrastructureManagement::FootprintElement elem;
for (const QMap<int, InfrastructureManagement::Database::IsmStructureElementFootprint> &cont : qAsConst(footprintSorted))
{
if (cont.empty())
continue;
const int structureElementId = cont.first().structureElementId;
const int mainStructureElementId = seId2mseId.value(structureElementId);
if (!mainStructureElementId)
continue;
mf.id(mainStructureElementId);
mf.structureElementId(structureElementId);
mf.name(mainStructureElements.value(mainStructureElementId).name.toStdString());
mf.elements().clear();
mf.elements().reserve(cont.size());
for (const auto &pos : cont)
{
elem.id(pos.id);
elem.relPosition(Core::RelativePosition(pos.relPosition.x(),
pos.relPosition.y(),
pos.relPosition.z()));
mf.elements().push_back(elem);
}
m_ismMainFootprint->write(mf);
}
}
void StaticPublisher::publishTranslationBlob(const std::shared_ptr<ProjectDataManagement::DatabaseInterface> &db)
{
QJsonArray arr;
const auto cb = [&arr](const ProjectDataManagement::Database::PdmTranslation &data)
{
arr += QJsonObject({{QStringLiteral("isoCode"), data.isoCode},
{QStringLiteral("context"), data.context},
{QStringLiteral("key"), data.key},
{QStringLiteral("disambiguation"), data.disambiguation},
{QStringLiteral("translation"), data.translation}
});
};
if (!db->select(cb))
return;
const QJsonObject jObj{ {QStringLiteral("translations"), arr} };
const QByteArray data = QJsonDocument(jObj).toBinaryData();
const QByteArray compressed = qCompress(data, 9);
const QByteArray md5Sum = QCryptographicHash::hash(compressed, QCryptographicHash::Md5).toHex();
m_pdmTranslationBlob->write(ProjectDataManagement::TranslationBlob(
1,
LtsUtils::convert<std::vector<uint8_t>>(compressed),
md5Sum.data()));
}
}
+79
View File
@@ -0,0 +1,79 @@
/**
* Publish static data (pdm, asm, ism) for THP
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2016-01-13
*/
#pragma once
#include "dds_handler.h"
#include <QSqlDatabase>
#include <QObject>
#include <AssetManagement/asm_dts_types.h>
#include <ExerciseManagement/exm_dts_types.h>
#include <FileManagement/flm_dts_types.h>
#include <InfrastructureManagement/ism_dts_types.h>
#include <ParticipantManagement/ppm_dts_types.h>
#include <ProjectDataManagement/pdm_dts_types.h>
namespace FileManagement
{
namespace Database
{
struct FlmFileContent;
}
}
namespace InfrastructureManagement
{
class DatabaseInterface;
}
namespace ProjectDataManagement
{
class DatabaseInterface;
}
namespace SituationReplay
{
class StaticPublisher final : public QObject
{
Q_OBJECT
public:
StaticPublisher(const std::shared_ptr<DdsHandler> &ddsInterface,
const QSqlDatabase &db);
~StaticPublisher();
Q_SIGNALS:
void fileContentAvailable(const FileManagement::Database::FlmFileContent &data);
private:
void publishData();
// including footprint
void publishMainStructureElement(const std::shared_ptr<InfrastructureManagement::DatabaseInterface> &db);
void publishTranslationBlob(const std::shared_ptr<ProjectDataManagement::DatabaseInterface> &db);
private:
std::shared_ptr<DdsHandler> m_ddsInterface;
std::unique_ptr<DTS::TrainingArea> m_asmTrainingArea;
std::unique_ptr<DTS::Exercise> m_exmExercise;
std::unique_ptr<DTS::ExercisePhase> m_exmExercisePhase;
std::unique_ptr<DTS::FileContent> m_flmFileContent;
std::unique_ptr<DTS::FileTypeInfo> m_flmFileTypeInfo;
std::unique_ptr<DTS::Folder> m_flmFolder;
std::unique_ptr<DTS::MainFootprint> m_ismMainFootprint;
std::unique_ptr<DTS::MainStructureElement> m_ismMainStructureElement;
std::unique_ptr<DTS::Type> m_ppmType;
std::unique_ptr<DTS::CanComponentString> m_pdmCanComponentString;
std::unique_ptr<DTS::ChargeType> m_pdmChargeType;
std::unique_ptr<DTS::FirePurpose> m_pdmFirePurpose;
std::unique_ptr<DTS::GearType> m_pdmGearType;
std::unique_ptr<DTS::GearTypeChargeType> m_ppmGearTypeChargeType;
std::unique_ptr<DTS::IgniterType> m_pdmIgniterType;
std::unique_ptr<DTS::IgniterFunction> m_pdmIgniterFunction;
std::unique_ptr<DTS::LoadType> m_pdmLoadType;
std::unique_ptr<DTS::ChargeTypeIgniterTypeIgniterFunction> m_pdmChargeTypeIgniterTypeIgniterFunction;
std::unique_ptr<DTS::ChargeTypeLoadType> m_pdmChargeTypeLoadType;
std::unique_ptr<DTS::LanguageHmi> m_pdmLanguageHmi;
std::unique_ptr<DTS::TranslationBlob> m_pdmTranslationBlob;
std::unique_ptr<DTS::VulnerabilityKind> m_pdmVulnerabilityKind;
QSqlDatabase m_db;
};
}