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

+186
View File
@@ -0,0 +1,186 @@
#
# $Id$
# $HeadURL$
# $Author$
#
INCLUDE(MacroRTIDDSGen)
INCLUDE(MacroCodeGenIdl)
SET(xml_FILE obd_service.xml)
#
# --- Library svcObdCommon --------------------------------------------------------------------------------
#
SET(SRCS_common
obd_export.h
logger.cpp
logger.h
)
# Generate obd_enums.idl / obd.idl
CODEGEN_IDL_SVC(SRCS_common ${xml_FILE})
# Generate obd_db_impl.cpp/.h, obd_db.h
CODEGEN_DATABASE(SRCS_common ${xml_FILE})
# Generate *.cpp/*.hpp from idl
RTIDDSGEN(SRCS_common obd_enums.idl)
RTIDDSGEN(SRCS_common obd.idl)
# Generate obd_dt[s,c]_types.h, obd_ft[s,c]_types.h
CODEGEN_TOPIC_TYPEDEFS(SRCS_common ${xml_FILE})
# Generate obd_[d|f]tc.h
CODEGEN_CLIENT_TOPICS_IFC(SRCS_common ${xml_FILE} PARTS FTC)
NGL_ADD_LIBRARY(SV WS svcObdCommon SHARED ${SRCS_common})
NGL_TARGET_INCLUDE_DIRECTORIES(svcObdCommon
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcObdCommon
PRIVATE
RTI::nddscpp2
PUBLIC
Qt5::Core
ngldb
ddscore
NGLLogger
)
NGL_INSTALL_TARGET(svcObdCommon)
#
# --- Library svcObdClient --------------------------------------------------------------------------------
#
SET(SRCS_client
obd_export.h
)
# generate obd_[d|f]tc.h, obd_[d|f]tc_impl.[cpp|h]
CODEGEN_CLIENT_TOPICS_IMPL(SRCS_client ${xml_FILE} PARTS FTC)
NGL_ADD_LIBRARY(SV WS svcObdClient SHARED ${SRCS_client})
NGL_TARGET_INCLUDE_DIRECTORIES(svcObdClient
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcObdClient
PRIVATE
RTI::nddscpp2
ddsconnector
PUBLIC
svcObdCommon
ddsftc
)
NGL_INSTALL_TARGET(svcObdClient)
#
# --- Library svcObdServer --------------------------------------------------------------------------------
#
SET(SRCS_server
obd_export.h
)
# generate obd_[d|f]ts.h, obd_[d|f]ts_impl.[cpp|h]
CODEGEN_SERVER_TOPICS(SRCS_server ${xml_FILE} PARTS FTS)
NGL_ADD_LIBRARY(SV svcObdServer SHARED ${SRCS_server})
NGL_TARGET_INCLUDE_DIRECTORIES(svcObdServer
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(svcObdServer
PRIVATE
RTI::nddscpp2
ddsconnector
ddsfts
PUBLIC
svcObdCommon
ngldb
)
NGL_INSTALL_TARGET(svcObdServer)
#
# --- Topic Type Plugin --------------------------------------------------------------
#
CREATE_TOPIC_TYPE_PLUGIN(${xml_FILE})
#
# --- Executable svcOcBaseDownload (sOBD) -------------------------------------------------
#
SET(SRCS_exe
copy_database.cpp
copy_database.h
main.cpp
main_handler.cpp
main_handler.h
dds_handler.cpp
dds_handler.h
handler_base_download.cpp
handler_base_download.h
handler_pdf_download.cpp
handler_pdf_download.h
pdf_download_socket.cpp
pdf_download_socket.h
pdf_downloader.cpp
pdf_downloader.h
settings.cpp
settings.h
WebSocketInterface/data_manager.cpp
WebSocketInterface/data_manager.h
WebSocketInterface/enums.h
WebSocketInterface/json_keys.h
WebSocketInterface/websocket_interface_handler.cpp
WebSocketInterface/websocket_interface_handler.h
WebSocketInterface/Messages/client_message.cpp
WebSocketInterface/Messages/client_message.h
WebSocketInterface/Messages/reply_message.cpp
WebSocketInterface/Messages/reply_message.h
${xml_FILE}
)
# Generate obd.sql, obd.xml
CODEGEN_SQL(SRCS_exe ${xml_FILE})
NGL_ADD_SVC_ICON(SRCS_exe)
NGL_ADD_EXECUTABLE(SV svcOcBaseDownload ${SRCS_exe})
NGL_TARGET_LINK_LIBRARIES(svcOcBaseDownload
Qt5::Core
dbAdminCopyExercise
svcObdCommon
svcObdServer
svcCoreClient
svcAsmServer
svcEscServer
svcEvlServer
svcExmServer
svcFlmServer
svcIsmServer
svcMsgServer
svcMrkServer
svcOpmServer
svcPpmServer
svcFltServer
svcAesServer
svcScmClient
ddsconnector
nglsettings
ProjectConfig
LtsCommandLineParser
LtsUtilsCoreHeaderOnly
LtsWebSocketClient
NGLLogger
nglcoreapplication
ngltools
)
NGL_INSTALL_TARGET(svcOcBaseDownload)
NGL_INSTALL(SV FILES log4cxx_obd.props DESTINATION bin)
NGL_ADD_TARGET_LINK(svcOcBaseDownload sOBD)
# Uncomment if necessary
#ADD_SUBDIRECTORY(UnitTests)
#ADD_SUBDIRECTORY(ModuleTests)
@@ -0,0 +1,286 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "client_message.h"
#include <AssetManagement/asm_db.h>
#include <ExerciseManagement/exm_db.h>
#include <FileManagement/flm_db.h>
#include <InfrastructureManagement/ism_db.h>
#include <ParticipantManagement/ppm_db.h>
#include <OperatorManagement/opm_db.h>
#include "WebSocketInterface/Messages/reply_message.h"
#include "WebSocketInterface/json_keys.h"
#include "WebSocketInterface/data_manager.h"
#include <QtCore/QJsonDocument>
#include <QtCore/QUuid>
namespace OcBaseDownload
{
namespace WebSocketInterface
{
namespace Messages
{
using namespace JsonKeys;
// ####### ClientMessageFactory begin #######
ClientMessageFactory::ClientMessageFactory(DataManager *dataManager)
: LtsWebSocket::AbstractClientMessageFactory(getLogger("ClientMessageFactory"))
, m_dataManager(dataManager)
{}
LtsWebSocket::AbstractClientMessage *ClientMessageFactory::createMessage(LtsWebSocket::ReplyHandler *client,
const QString &message)
{
LtsWebSocket::AbstractClientMessage *result = checkAttributes(client, message);
if (result)
return result;
if (m_type == LtsWebSocket::JsonKeys::ERROR_())
result = new ErrorMessage(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// SCM telegram
else if (m_type == ServiceManagement::WebSocketInterface::JsonKeys::SERVICE_PORTS_INFORMATION())
result = new ServicePortsInformation(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// ASM telegrams
else if (m_type == AssetManagement::WebSocketInterface::JsonKeys::TRAINING_AREA_BASE_DATA())
result = new BaseData<AssetManagement::DatabaseInterface, AssetManagement::Database::AsmTrainingArea>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == AssetManagement::WebSocketInterface::JsonKeys::TECHNICAL_AREA_BASE_DATA())
result = new BaseData<AssetManagement::DatabaseInterface, AssetManagement::Database::AsmTechnicalArea>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == AssetManagement::WebSocketInterface::JsonKeys::LOCATION_BASE_DATA())
result = new BaseData<AssetManagement::DatabaseInterface, AssetManagement::Database::AsmLocation>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == AssetManagement::WebSocketInterface::JsonKeys::ASM_ASSET_BASE_DATA())
result = new BaseData<AssetManagement::DatabaseInterface, AssetManagement::Database::AsmAsset>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// EXM telegrams
else if (m_type == ExerciseManagement::WebSocketInterface::JsonKeys::EXERCISE_BASE_DATA())
result = new BaseData<ExerciseManagement::DatabaseInterface, ExerciseManagement::Database::ExmExercise>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == ExerciseManagement::WebSocketInterface::JsonKeys::EXERCISE_PHASE_BASE_DATA())
result = new BaseData<ExerciseManagement::DatabaseInterface, ExerciseManagement::Database::ExmExercisePhase>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == ExerciseManagement::WebSocketInterface::JsonKeys::EXERCISE_STATE_CHANGE_BASE_DATA())
result = new BaseData<ExerciseManagement::DatabaseInterface, ExerciseManagement::Database::ExmExerciseStateChange>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// ISM telegrams
else if (m_type == InfrastructureManagement::WebSocketInterface::JsonKeys::ISM_ASSET_BASE_DATA())
result = new BaseData<InfrastructureManagement::DatabaseInterface, InfrastructureManagement::Database::IsmAsset>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == InfrastructureManagement::WebSocketInterface::JsonKeys::MAIN_STRUCTURE_ELEMENT_BASE_DATA())
result = new BaseData<InfrastructureManagement::DatabaseInterface, InfrastructureManagement::Database::IsmMainStructureElement>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == InfrastructureManagement::WebSocketInterface::JsonKeys::STRUCTURE_ELEMENT_BASE_DATA())
result = new BaseData<InfrastructureManagement::DatabaseInterface, InfrastructureManagement::Database::IsmStructureElement>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == InfrastructureManagement::WebSocketInterface::JsonKeys::STRUCTURE_ELEMENT_FOOTPRINT_BASE_DATA())
result = new BaseData<InfrastructureManagement::DatabaseInterface, InfrastructureManagement::Database::IsmStructureElementFootprint>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == InfrastructureManagement::WebSocketInterface::JsonKeys::MOUNTING_POINT_ASSET_BASE_DATA())
result = new BaseData<InfrastructureManagement::DatabaseInterface, InfrastructureManagement::Database::IsmMountingPointAsset>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == InfrastructureManagement::WebSocketInterface::JsonKeys::MOUNTING_POINT_SCHEDULE_BASE_DATA())
result = new BaseData<InfrastructureManagement::DatabaseInterface, InfrastructureManagement::Database::IsmMountingPointSchedule>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == InfrastructureManagement::WebSocketInterface::JsonKeys::MOUNTING_POINT_PLAN_BASE_DATA())
result = new BaseData<InfrastructureManagement::DatabaseInterface, InfrastructureManagement::Database::IsmMountingPointPlan>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// PPM Ex0 telegrams
else if (m_type == ParticipantManagement::WebSocketInterface::JsonKeys::EQUIPMENT_TYPE_BASE_DATA())
result = new BaseData<ParticipantManagement::DatabaseInterface, ParticipantManagement::Database::PpmEquipmentType>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == ParticipantManagement::WebSocketInterface::JsonKeys::TYPE_BASE_DATA())
result = new BaseData<ParticipantManagement::DatabaseInterface, ParticipantManagement::Database::PpmType>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// PPM ExN telegrams
else if (m_type == ParticipantManagement::WebSocketInterface::JsonKeys::PARTY_BASE_DATA())
result = new BaseData<ParticipantManagement::DatabaseInterface, ParticipantManagement::Database::PpmParty>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == ParticipantManagement::WebSocketInterface::JsonKeys::PARTICIPANT_BASE_DATA())
result = new BaseData<ParticipantManagement::DatabaseInterface, ParticipantManagement::Database::PpmParticipant>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// OPM telegrams
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::GROUP_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmGroup>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::GROUP_GROUP_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmGroupGroup>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::OPERATOR_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmOperator>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::OPERATOR_EXERCISE_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmOperatorExercise>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::SETTINGS_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmSettings>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::ACCESS_CONTROL_LEVEL_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmAccessControlLevel>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::ACL_ALLOW_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmAclAllow>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == OperatorManagement::WebSocketInterface::JsonKeys::ACL_DENY_BASE_DATA())
result = new BaseData<OperatorManagement::DatabaseInterface, OperatorManagement::Database::OpmAclDeny>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
// FLM telegrams
else if (m_type == FileManagement::WebSocketInterface::JsonKeys::FOLDER_BASE_DATA())
result = new BaseData<FileManagement::DatabaseInterface, FileManagement::Database::FlmFolder>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == FileManagement::WebSocketInterface::JsonKeys::FILE_CONTENT_BASE_DATA())
result = new BaseData<FileManagement::DatabaseInterface, FileManagement::Database::FlmFileContent>(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
else if (m_type == FileManagement::WebSocketInterface::JsonKeys::PDF_LIST_DATA())
result = new PdfListMessage(m_dataManager, client, m_type, m_typeId, m_uuid, m_data);
return checkResult(client, message, result);
}
// ####### ClientMessageFactory end #######
// ####### ClientMessage begin #######
ClientMessage::ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: LtsWebSocket::AbstractClientMessage(client, type, typeId, uuid, data)
, m_dataManager(dataManager)
, m_logger(getLogger("ClientMessage"))
{}
// ####### ClientMessage end #######
// ####### ServicesInformation begin #######
ErrorMessage::ErrorMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage(dataManager, client, type, typeId, uuid, data)
{}
void ErrorMessage::process()
{
ErrorData err;
err.errorClass = m_data.toObject().value(LtsWebSocket::JsonKeys::ERROR_CLASS()).toInt();
err.uuid = m_data.toObject().value(LtsWebSocket::JsonKeys::UUID_()).toString();
err.errorMessage = m_data.toObject().value(LtsWebSocket::JsonKeys::ERROR_MESSAGE()).toString();
m_dataManager->handleErrorMessage(err);
}
bool ErrorMessage::hasValidData() const
{
return true;
}
// ####### ErrorMessage end #######
// ####### ServicesInformation begin #######
ServicePortsInformation::ServicePortsInformation(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
: ClientMessage(dataManager, client, type, typeId, uuid, data)
{}
void ServicePortsInformation::process()
{
const QJsonArray exerciseInformationArray = m_data.toArray();
QVector<ExerciseInformation> exercises;
QVector<ServiceInformation> services;
QVector<PortInformation> ports;
exercises.reserve(exerciseInformationArray.size());
for (const auto &exerciseJsonValue : exerciseInformationArray)
{
QJsonObject exerciseJsonObject = exerciseJsonValue.toObject();
ExerciseInformation exercise;
exercise.exerciseId = exerciseJsonObject.value(ServiceManagement::WebSocketInterface::JsonKeys::EXERCISE_ID()).toInt();
if (exerciseJsonObject.contains(ServiceManagement::WebSocketInterface::JsonKeys::REPLAY_PARTITION_ID()))
exercise.replayPartitionId = dds::core::optional<int32_t>(exerciseJsonObject.value(ServiceManagement::WebSocketInterface::JsonKeys::REPLAY_PARTITION_ID()).toInt());
const QJsonArray servicesJsonArray = exerciseJsonObject.value(ServiceManagement::WebSocketInterface::JsonKeys::SERVICES()).toArray();
// prepare vector
services.clear();
services.reserve(servicesJsonArray.size());
for (const auto &serviceValue : servicesJsonArray)
{
ServiceInformation service;
QJsonObject serviceObject = serviceValue.toObject();
service.name = serviceObject.value(ServiceManagement::WebSocketInterface::JsonKeys::NAME()).toString();
service.abbreviation = serviceObject.value(ServiceManagement::WebSocketInterface::JsonKeys::NAME_ABBR()).toString();
const QJsonArray portsJsonArray = serviceObject.value(ServiceManagement::WebSocketInterface::JsonKeys::PORTS()).toArray();
// prepare vector
ports.clear();
ports.reserve(portsJsonArray.size());
for (const auto &portValue : portsJsonArray)
{
QJsonObject portObject = portValue.toObject();
PortInformation port;
port.number = portObject.value(ServiceManagement::WebSocketInterface::JsonKeys::NUMBER()).toInt();
port.type = portObject.value(ServiceManagement::WebSocketInterface::JsonKeys::TYPE_ID()).toInt();
ports.append(port);
}
service.ports = ports;
services.append(service);
}
exercise.services = services;
exercises.append(exercise);
}
m_dataManager->servicePortsInformation(exercises);
}
bool ServicePortsInformation::hasValidData() const
{
return true;
}
// ####### ServicesInformation end #######
// ####### BaseData begin #######
template <typename DB, typename T>
BaseData<DB, T>::BaseData(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, QJsonValue &data)
: ClientMessage(dataManager, client, type, typeId, uuid, data)
{}
template <typename DB, typename T>
void BaseData<DB, T>::process()
{
m_dataManager->baseData<T>(DB::template fromJson<T>(m_data.toArray()));
}
template <typename DB, typename T>
bool BaseData<DB, T>::hasValidData() const
{
return true;
}
// ####### BaseData end #######
// ####### PdfListData begin #######
PdfListMessage::PdfListMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, QJsonValue &data)
: ClientMessage(dataManager, client, type, typeId, uuid, data)
{}
void PdfListMessage::process()
{
PdfListData data;
using namespace FileManagement::WebSocketInterface::JsonKeys;
if (m_data.isArray())
{
data.pdfData.reserve(m_data.toArray().size());
QJsonArray arr = m_data.toArray();
for (const QJsonValue &current : qAsConst(arr))
{
if (!current.isObject())
continue;
QJsonObject obj = current.toObject();
data.pdfData.append({obj.value(FILE_ID()).toInt(),
obj.value(NAME()).toString(),
obj.value(FILE_SIZE()).toInt(),
FileManagement::FileCategory::inner_enum(obj.value(FILE_CATEGORY()).toInt()),
obj.value(IS_TEMPLATE()).toBool(),
obj.value(PROPERTIES()),
FileManagement::FileStatus::inner_enum(obj.value(FILE_STATUS()).toInt()),
obj.value(FOLDER_ID()).toInt(),
obj.value(PHASE_ID()).toInt(),
obj.value(OPERATOR_ID()).toInt(),
obj.value(EXERCISE_ID()).toInt()
});
}
}
m_dataManager->handlePdfListMessage(data);
}
bool PdfListMessage::hasValidData() const
{
return true;
}
// ####### PdfListData end #######
} // namespace Messages
} // namespace WebSocketInterface
} // namespace OcBaseDownload
@@ -0,0 +1,198 @@
/**
* @RDE_HEADER@
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QtCore/QJsonObject>
#include <QVector>
#include <DDS/Core/core.hpp>
#include <LtsWebSocket/client_message_factory.h>
#include <LtsWebSocket/client_message.h>
#include <FileManagement/flm_enums.hpp>
#include "logger.h"
namespace OcBaseDownload
{
namespace WebSocketInterface
{
class DataManager;
namespace Messages
{
/**
* @brief The ClientMessageFactory class creates ClientMessages which will then be processed
*/
class ClientMessageFactory final : public LtsWebSocket::AbstractClientMessageFactory
{
public:
explicit ClientMessageFactory(DataManager *dataManager);
/**
* @brief create Only way to create a ClientMessage object
* @param message Text message which will be converted to a ClientMessage object
* @return A ClientMessage object, which represents a concrete ClientMessage
*/
LtsWebSocket::AbstractClientMessage *createMessage(LtsWebSocket::ReplyHandler *client,
const QString &message);
private:
DataManager *m_dataManager;
}; // class ClientMessageFactory
/**
* @brief The ClientMessage class is an abstract base class for concrete ClientMessage objects
*/
class ClientMessage : public LtsWebSocket::AbstractClientMessage
{
protected: // method
explicit ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data = QJsonValue());
protected: // attributes
DataManager *m_dataManager;
LOGGER_T m_logger;
}; // class ClientMessage
// ################## Message Implementations ##################
class ErrorMessage : public ClientMessage
{
public:
explicit ErrorMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
/**
* @brief The ErrorData struct represents the data part of an ErrorMessage object
*/
struct ErrorData
{
int errorClass = 0;
QString uuid;
QString errorMessage;
};
void process();
bool hasValidData() const;
};
class ServicePortsInformation : public ClientMessage
{
public:
explicit ServicePortsInformation(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data);
public:
/**
* @brief The PortInformation struct holds the information what kind of port we have here
*/
struct PortInformation
{
int32_t number = 0;
int32_t type = 0;
};
/**
* @brief The ServiceInformation struct information about a service
*/
struct ServiceInformation
{
QString name;
QString abbreviation;
QVector<PortInformation> ports;
};
/**
* @brief The ExerciseInformation struct with information about an exercise (could also be a replay)
*/
struct ExerciseInformation
{
int32_t exerciseId = 0;
dds::core::optional<int32_t> replayPartitionId;
QVector<ServiceInformation> services;
};
void process();
bool hasValidData() const;
}; // class ServicesInformation
/**
* @brief Handle a BaseData telegram
*/
template <typename DB, typename T>
class BaseData final : public ClientMessage
{
public:
explicit BaseData(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, QJsonValue &data);
void process();
bool hasValidData() const;
}; // class BaseData
/**
* @brief Handle a PdfListData telegram
*/
class PdfListMessage : public ClientMessage
{
public:
explicit PdfListMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, QJsonValue &data);
struct PdfInformation
{
int32_t id = -1;
QString name;
int fileSize = -1;
FileManagement::FileCategory fileCategory = FileManagement::FileCategory::Global;
bool isTemplate = false;
QJsonValue properties;
FileManagement::FileStatus fileStatus = FileManagement::FileStatus::Deleted;
int folderId = -1;
int phaseId = -1;
int operatorId = -1;
int exerciseId = -1;
PdfInformation() = default;
PdfInformation(int32_t id,
const QString &name,
int fileSize,
FileManagement::FileCategory fileCategory,
bool isTemplate,
const QJsonValue &properties,
FileManagement::FileStatus fileStatus,
int folderId,
int phaseId,
int operatorId,
int exerciseId)
: id(id)
, name(name)
, fileSize(fileSize)
, fileCategory(fileCategory)
, isTemplate(isTemplate)
, properties(properties)
, fileStatus(fileStatus)
, folderId(folderId)
, phaseId(phaseId)
, operatorId(operatorId)
, exerciseId(exerciseId)
{}
};
struct PdfListData
{
QVector<PdfInformation> pdfData;
};
void process();
bool hasValidData() const;
}; // class PdfListData
} // namespace Messages
} // namespace WebSocketInterface
} // namespace OcBaseDownload
@@ -0,0 +1,63 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "reply_message.h"
#include <LtsWebSocket/json_keys.h>
#include "WebSocketInterface/json_keys.h"
#include <QtCore/QUuid>
#include <QtCore/QJsonDocument>
namespace OcBaseDownload
{
namespace WebSocketInterface
{
namespace Messages
{
using namespace JsonKeys;
using namespace LtsWebSocket::JsonKeys;
// ####### ServicePortsInformationRequest begin #######
ServicePortsInformationRequest::ServicePortsInformationRequest(const QString &uuid)
: ReplyMessage(ServiceManagement::WebSocketInterface::JsonKeys::SERVICE_PORTS_INFORMATION_REQUEST(), 6002, uuid)
{}
// ####### ServicePortsInformationRequest end #######
// ####### BaseDlRequest begin #######
/************************************************************
* Attention! TypeId 6006 is negotiated with ESG for ADLER! *
************************************************************/
BaseDlRequest::BaseDlRequest(const QString &uuid, int exerciseId)
: LtsWebSocket::ReplyMessage(BASE_DL_REQUEST(), 6006, uuid) // Todo: Check whether typeId is correct
{
if (0 < exerciseId)
{
QJsonObject data;
data.insert(EXERCISE_ID(), QJsonValue(exerciseId));
m_jsonRepresentation.insert(DATA(), data);
}
}
// ####### BaseDlRequest end #######
// ####### PdfListRequest begin #######
PdfListRequest::PdfListRequest(const QString &uuid, int exerciseId)
: LtsWebSocket::ReplyMessage(PDF_LIST_REQUEST(), 2, uuid) // Todo: Check whether typeId is correct
{
if (0 < exerciseId)
{
QJsonObject data;
data.insert(EXERCISE_ID(), QJsonValue(exerciseId));
m_jsonRepresentation.insert(DATA(), data);
}
}
// ####### PdfListRequest end #######
} // namespace Messages
} // namespace WebSocketInterface
} // namespace OcBaseDownload
@@ -0,0 +1,58 @@
/**
* @RDE_HEADER@
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <LtsWebSocket/client_message_factory.h>
#include <DDS/Core/core.hpp>
#include <QString>
#include <QMap>
#include <QtCore/QVector>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
namespace OcBaseDownload
{
namespace WebSocketInterface
{
namespace Messages
{
/**
* @brief The ServicePortsInformationRequest class
*/
class ServicePortsInformationRequest : public LtsWebSocket::ReplyMessage
{
public:
explicit ServicePortsInformationRequest(const QString &uuid);
}; // class ServicePortsInformationRequest
/**
* @brief The BaseDlRequest class
*/
class BaseDlRequest : public LtsWebSocket::ReplyMessage
{
public:
explicit BaseDlRequest(const QString &uuid, int exerciseId);
}; // class BaseDlRequest
/**
* @brief The BaseDlRequest class
*/
class PdfListRequest : public LtsWebSocket::ReplyMessage
{
public:
explicit PdfListRequest(const QString &uuid, int exerciseId);
}; // class PdfListRequest
} // namespace Messages
} // namespace WebSocketInterface
} // namespace OcBaseDownload
@@ -0,0 +1,94 @@
/**
* @RDE_HEADER@
* The DataManager class is a convenience class for managing structure data
* offers an interface to get and set structure data
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-03-27
*/
#include "WebSocketInterface/data_manager.h"
#include <QVector>
namespace OcBaseDownload
{
namespace WebSocketInterface
{
//---------------------------------------------------------------------------------------------------------
DataManager::DataManager(MainHandler *mainHandler)
: m_mainHandler(mainHandler)
, m_currentDownload(CurrentDownload::NOTHING)
, m_logger(getLogger(QStringLiteral("DataManager")))
{
}
//---------------------------------------------------------------------------------------------------------
void DataManager::handleErrorMessage(const OcBaseDownload::WebSocketInterface::Messages::ErrorMessage::ErrorData &errData)
{
ERROR_LOG(m_logger) << "uuid: " << errData.uuid << " error class: " << errData.errorClass << " text: " << errData.errorMessage;
}
//---------------------------------------------------------------------------------------------------------
void DataManager::servicePortsInformation(const QVector<Messages::ServicePortsInformation::ExerciseInformation> &exerciseInformation)
{
DEBUG_LOG(m_logger) << "Got ServicePortsInformation from websocket";
switch (m_currentDownload)
{
case CurrentDownload::PDF:
m_mainHandler->handlerPdfDownload()->handleServicePortsInformation(exerciseInformation);
break;
case CurrentDownload::BASE:
//m_mainHandler->handlerBaseDownload()->handleServicePortsInformation(exerciseInformation);
break;
case CurrentDownload::NOTHING:
default:
WARNING_LOG(m_logger) << "Got Ports Information in neither BASE nor PDF download mode";
break;
}
}
//---------------------------------------------------------------------------------------------------------
void DataManager::handlePdfListMessage(const Messages::PdfListMessage::PdfListData &pdfListData)
{
DEBUG_LOG(m_logger) << "Got PDF list from websocket";
m_mainHandler->handlerPdfDownload()->handlePdfListData(pdfListData);
}
//---------------------------------------------------------------------------------------------------------
void DataManager::setCurrentDownload(CurrentDownload currentDownload)
{
m_currentDownload = currentDownload;
switch (m_currentDownload)
{
case CurrentDownload::PDF:
DEBUG_LOG(m_logger) << "Setting current download mode to PDF";
m_mainHandler->dds()->fts()->enableStartBaseDownload(false);
m_mainHandler->dds()->fts()->enableGetPdfList();
m_mainHandler->dds()->fts()->enableStartPdfDownload();
break;
case CurrentDownload::BASE:
DEBUG_LOG(m_logger) << "Setting current download mode to BASE";
m_mainHandler->dds()->fts()->enableStartBaseDownload();
m_mainHandler->dds()->fts()->enableGetPdfList(false);
m_mainHandler->dds()->fts()->enableStartPdfDownload(false);
break;
case CurrentDownload::NOTHING:
DEBUG_LOG(m_logger) << "Setting current download mode to NOTHING";
m_mainHandler->dds()->fts()->enableAll();
break;
default:
break;
}
}
//---------------------------------------------------------------------------------------------------------
CurrentDownload DataManager::currentDownload() const
{
return m_currentDownload;
}
} // namespace WebSocketInterface
} // namespace OcBaseDownload
@@ -0,0 +1,80 @@
/**
* @RDE_HEADER@
* The DataManager class is a convenience class for managing structure data
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include "WebSocketInterface/Messages/client_message.h"
#include "main_handler.h"
#include "logger.h"
#include "enums.h"
namespace OcBaseDownload
{
namespace WebSocketInterface
{
/**
* @brief The DataManager class is a convenience class for managing structure data
*/
class DataManager final
{
public:
/**
* @brief DataManager Constructor
* @param mainHandler Source for needed handlers
*/
explicit DataManager(MainHandler *mainHandler);
/**
* @brief handleErrorMessage
* @param errData
*/
void handleErrorMessage(const Messages::ErrorMessage::ErrorData &errData);
/**
* @brief servicePortsInformation processing new port informations, only called during base DL
* @param exerciseInformation
*/
void servicePortsInformation(const QVector<Messages::ServicePortsInformation::ExerciseInformation> &exerciseInformation);
// handling asm base data
template <typename T>
void baseData(std::vector<T> &&data)
{
Q_UNUSED(data)
DEBUG_LOG(m_logger) << "Got new base data.";
//m_mainHandler->handlerBaseDownload()->handleBaseData(std::move(data));
}
/**
* @brief handlePdfListMessage
* @param pdfListData a list of PDF document names
*/
void handlePdfListMessage(const Messages::PdfListMessage::PdfListData &pdfListData);
/**
* @brief setCurrentDownload sets the current download
* @param currentDownload The new value
*/
void setCurrentDownload(CurrentDownload currentDownload);
/**
* @brief Getter for current download
* @return Value of the current download
*/
CurrentDownload currentDownload() const;
private: // attributes
MainHandler *m_mainHandler;
CurrentDownload m_currentDownload;
LOGGER_T m_logger;
}; // class DataManager
} // namespace WebSocketInterface
} // namespace OcBaseDownload
+25
View File
@@ -0,0 +1,25 @@
/**
* @RDE_HEADER@
* Header file which holds all occuring enums
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-26
*/
#pragma once
namespace OcBaseDownload
{
namespace WebSocketInterface
{
/**
* @brief Helper to serve the correct handler for incoming messages via WebSocket
*/
enum class CurrentDownload
{
NOTHING,
BASE,
PDF
};
}
}
+43
View File
@@ -0,0 +1,43 @@
/**
* @RDE_HEADER@
* Header file which holds all occuring JSON keys
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QtCore/QString>
#include <LtsWebSocket/json_keys.h>
#include <AssetManagement/WebSocketInterface/json_keys.h>
#include <ExerciseManagement/WebSocketInterface/json_keys.h>
#include <FileManagement/WebSocketInterface/json_keys.h>
#include <InfrastructureManagement/WebSocketInterface/json_keys.h>
#include <OperatorManagement/WebSocketInterface/json_keys.h>
#include <ParticipantManagement/WebSocketInterface/json_keys.h>
#include <ServiceManagement/WebSocketInterface/json_keys.h>
namespace OcBaseDownload
{
namespace WebSocketInterface
{
/**
* @brief Namespace which holds all occuring JSON keys as const QString objects
*/
namespace JsonKeys
{
// types for client --> server messages
inline QString BASE_DL_REQUEST() { return QStringLiteral("baseDlRequest"); }
inline QString PDF_LIST_REQUEST() { return QStringLiteral("pdfListRequest"); }
// types for server --> client messages
// data keys
inline QString EXERCISE_ID() { return QStringLiteral("exerciseId"); }
} // namespace JsonKeys
} // namespace WebSocketInterface
} // namespace OcBaseDownload
@@ -0,0 +1,133 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#include "websocket_interface_handler.h"
#include "settings.h"
#include "main_handler.h"
#include "data_manager.h"
#include "WebSocketInterface/Messages/client_message.h"
#include <QTimer>
namespace OcBaseDownload
{
namespace WebSocketInterface
{
WebSocketInterfaceHandler::WebSocketInterfaceHandler(MainHandler *mainHandler, QObject *parent)
: QObject(parent)
, m_webSocketClient(nullptr)
, m_messageFactory(nullptr)
, m_dataManager(nullptr)
, m_mainHandler(mainHandler)
, m_webSocketActivityTimer(new QTimer(this))
, m_logger(getLogger("WebSocketInterfaceHandler"))
{
connect(m_webSocketActivityTimer, &QTimer::timeout, this, &WebSocketInterfaceHandler::dataReceiveTimeout, Qt::UniqueConnection);
const int iTimeout = Settings::webSocketActivityTimeoutMSec();
if (iTimeout > 0)
m_webSocketActivityTimer->setInterval(iTimeout);
}
WebSocketInterfaceHandler::~WebSocketInterfaceHandler()
{
cleanup();
}
bool WebSocketInterfaceHandler::init()
{
cleanup();
DEBUG_LOG(m_logger) << "WebSocketInterfaceHandler::init";
m_dataManager = new DataManager(m_mainHandler);
DEBUG_LOG(m_logger) << "... ok";
m_messageFactory = new Messages::ClientMessageFactory(m_dataManager);
return true;
}
void WebSocketInterfaceHandler::open(const QString &hostname, int port)
{
DEBUG_LOG(m_logger) << "Opening " << hostname << ":" << port;
recreateWebSocket();
m_webSocketClient->open(hostname, port);
m_webSocketActivityTimer->start();
}
void WebSocketInterfaceHandler::close()
{
m_webSocketActivityTimer->stop();
if (m_webSocketClient)
{
disconnect(m_webSocketClient);
m_webSocketClient->disconnect();
m_webSocketClient->close();
m_webSocketClient->deleteLater();
m_webSocketClient = nullptr;
}
}
bool WebSocketInterfaceHandler::send(LtsWebSocket::ReplyMessage *message)
{
DEBUG_LOG(m_logger) << "Sending: " << message->toJsonString();
if (!m_webSocketClient)
return false;
m_webSocketClient->addReply(message);
return true;
}
void WebSocketInterfaceHandler::setCurrentDownload(CurrentDownload currentDownload)
{
m_dataManager->setCurrentDownload(currentDownload);
}
CurrentDownload WebSocketInterfaceHandler::currentDownload() const
{
return m_dataManager->currentDownload();
}
void WebSocketInterfaceHandler::recreateWebSocket()
{
close();
m_webSocketClient = new LtsWebSocket::LtsWebSocketClient(m_messageFactory, this);
connect(m_webSocketClient, &LtsWebSocket::LtsWebSocketClient::connected,
this, &WebSocketInterfaceHandler::connected);
connect(m_webSocketClient, &LtsWebSocket::LtsWebSocketClient::disconnected,
this, &WebSocketInterfaceHandler::disconnected);
//connect(m_webSocketClient, &LtsWebSocket::LtsWebSocketClient::dataReceived,
//m_webSocketActivityTimer, QOverload<>::of(&QTimer::start));
connect(m_webSocketClient, &LtsWebSocket::LtsWebSocketClient::dataReceived,
this, [this]()
{
DEBUG_LOG(m_logger) << "data received restart timer";
m_webSocketActivityTimer->start();
});
}
void WebSocketInterfaceHandler::cleanup()
{
delete m_webSocketClient;
delete m_messageFactory;
delete m_dataManager;
m_webSocketClient = nullptr;
m_messageFactory = nullptr;
m_dataManager = nullptr;
}
} // namespace WebSocketInterface
} // namespace OcBaseDownload
@@ -0,0 +1,105 @@
/**
* @RDE_HEADER@
* Handler for the WebSocket Interface
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2017-12-05
*/
#pragma once
#include <QObject>
#include <QString>
#include <LtsWebSocket/lts_web_socket_client.h>
#include "logger.h"
#include "enums.h"
class QTimer;
namespace OcBaseDownload
{
class MainHandler;
namespace WebSocketInterface
{
namespace Messages
{
class ClientMessageFactory;
class ReplyMessage;
}
class DataManager;
/**
* @brief The WebSocketInterfaceHandler class is the main class for the WebSocketInterface
*/
class WebSocketInterfaceHandler final : public QObject
{
Q_OBJECT
public:
/**
* @brief WebSocketInterfaceHandler Constructor
* @param mainHandler MainHandler to get the HandlerStructureElement from
*/
explicit WebSocketInterfaceHandler(MainHandler *mainHandler, QObject *parent = nullptr);
/**
* @brief ~WebSocketInterfaceHandler Destructor
*/
~WebSocketInterfaceHandler();
/**
* @brief init Initialises all needed classes for the WebSocketInterface
* @return True on success, otherwise false
*/
bool init();
/**
* @brief open Opens the websocket with the given parameter
* @param hostname
* @param port
*/
void open(const QString &hostname, int port);
/**
* @brief close
*/
void close();
/**
* @brief send Sends the given message
* @param msg
*/
bool send(LtsWebSocket::ReplyMessage *message);
/**
* @brief setCurrentDownload sets the current download
* @param currentDownload The new value
*/
void setCurrentDownload(CurrentDownload currentDownload);
/**
* @brief Getter for current download
* @return Value of the current download
*/
CurrentDownload currentDownload() const;
signals:
void connected();
void disconnected();
void dataReceiveTimeout();
void dataReceived();
private:
void cleanup();
void recreateWebSocket();
private:
LtsWebSocket::LtsWebSocketClient *m_webSocketClient;
Messages::ClientMessageFactory *m_messageFactory;
DataManager *m_dataManager;
MainHandler *m_mainHandler;
QTimer *m_webSocketActivityTimer;
LOGGER_T m_logger;
}; // class WebSocketInterfaceHandle
} // namespace WebSocketInterface
} // namespace OcBaseDownload
+270
View File
@@ -0,0 +1,270 @@
/*
* @RDE_HEADER@
* Copy exercise from server to evaluation server
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, NLSE, 2018-07-31
*/
#include "copy_database.h"
#include <ngldb/dbcommon.h>
#include <ngldb/dbconnection.h>
#include <ngldb/nsqlquery.h>
#include <ngltools/ngltools_filesystem.h>
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QSettings>
namespace OcBaseDownload
{
CopyDatabase::CopyDatabase(NGL::INGLLogger &logger, QObject *parent)
: QObject(parent)
, m_proc(nullptr)
, m_logger(logger)
{}
bool CopyDatabase::init(const QString &dbHost, const QString &srcDbName, const QString &dstDbName)
{
m_dbHost = dbHost;
m_srcDbName = srcDbName;
m_dstDbName = dstDbName;
return true;
}
bool CopyDatabase::doCopy()
{
if (!runPgDump())
{
ERROR_LOG(m_logger) << "Error running pg_dump";
emit copyDbFailed();
return false;
}
return true;
}
bool CopyDatabase::dropDatabase(const QString &dbName)
{
return runDropDb(dbName);
}
bool CopyDatabase::runDropDb(const QString &dbName)
{
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("--if-exists"),
QStringLiteral("-h"),
m_dbHost,
dbName});
handleProcInit(executablePath(QStringLiteral("dropdb")), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyDatabase::onDropDbFinished);
m_proc->start();
return true;
}
void CopyDatabase::onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
NOTICE_LOG(m_logger) << "onDropDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
if (exitCode > 0)
{
ERROR_LOG(m_logger) << "DropDb failed";
emit dropDatabaseFailed();
return;
}
emit dropDatabaseFinished();
}
bool CopyDatabase::runPgDump()
{
// start process
const QStringList args(
{
QStringLiteral("--column-inserts"),
QStringLiteral("-U"), QStringLiteral("postgres"),
QStringLiteral("-f"), getDumpFile(),
QStringLiteral("-h"), m_dbHost,
m_srcDbName
});
handleProcInit(executablePath(QStringLiteral("pg_dump")), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyDatabase::onPgDumpFinished);
m_proc->start();
return true;
}
void CopyDatabase::onPgDumpFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
NOTICE_LOG(m_logger) << "onProcessFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
runCreatedb();
}
void CopyDatabase::runCreatedb()
{
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-h"),
m_dbHost,
m_dstDbName});
handleProcInit(executablePath(QStringLiteral("createdb")), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyDatabase::onCreateDbFinished);
m_proc->start();
}
void CopyDatabase::onCreateDbFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
NOTICE_LOG(m_logger) << "onCreateDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
if (exitCode > 0)
{
ERROR_LOG(m_logger) << "CreateDB failed";
emit copyDbFailed();
return;
}
runGrant();
//runPgLoad();
}
void CopyDatabase::runGrant()
{
const QString command = QStringLiteral("-c 'GRANT ALL ON DATABASE %1 to ets_exm'").arg(m_dstDbName);
const QStringList args({ QStringLiteral("-U"),
QStringLiteral("postgres"),
command,
QStringLiteral("-h"),
m_dbHost,
m_dstDbName });
handleProcInit(executablePath(QStringLiteral("psql")), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyDatabase::runPgLoad);
m_proc->start();
}
void CopyDatabase::runPgLoad()
{
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-f"),
getDumpFile(),
QStringLiteral("-h"),
m_dbHost,
m_dstDbName});
handleProcInit(executablePath(QStringLiteral("psql")), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyDatabase::onPgLoadFinished);
m_proc->start();
}
void CopyDatabase::onPgLoadFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
NOTICE_LOG(m_logger) << "onPsqlFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
if (exitStatus == QProcess::ExitStatus::NormalExit)
QFile::remove(getDumpFile());
if (exitCode > 0)
{
ERROR_LOG(m_logger) << "Loading db failed";
emit copyDbFailed();
return;
}
runPgSetGrant();
}
void CopyDatabase::runPgSetGrant()
{
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-c"), QStringLiteral("GRANT ALL ON DATABASE %1 to ets_admin").arg(m_dstDbName),
QStringLiteral("-h"),
m_dbHost,
m_dstDbName});
handleProcInit(executablePath(QStringLiteral("psql")), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyDatabase::onPgSetGrantFinished);
m_proc->start();
}
void CopyDatabase::onPgSetGrantFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
NOTICE_LOG(m_logger) << "onPsqlFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
if (exitCode > 0)
{
ERROR_LOG(m_logger) << "Set grants to ets_admin failed";
emit copyDbFailed();
return;
}
emit copyDbFinished();
}
void CopyDatabase::handleProcInit(const QString &program, const QStringList &args)
{
if (m_proc)
{
m_proc->disconnect(this);
m_proc->deleteLater();
}
m_proc = new QProcess(this);
NOTICE_LOG(m_logger) << "Starting process '" << program << "' with args '" << args.join(QLatin1Char(' ')) << "'";
m_proc->setProgram(program);
m_proc->setArguments(args);
connect(m_proc, &QProcess::errorOccurred,
this, &CopyDatabase::onErrorOccured);
}
void CopyDatabase::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
if (!m_proc)
return;
if (exitCode != 0 || exitStatus != 0)
{
QByteArray out = m_proc->readAllStandardError();
if (!out.isEmpty())
out += '\n';
out += m_proc->readAllStandardOutput();
ERROR_LOG(m_logger) << "Process finished - exitCode: " << exitCode << ", exitStatus = " << exitStatus << ", " << out;
}
m_proc->disconnect(this);
m_proc->deleteLater();
m_proc = nullptr;
}
void CopyDatabase::onErrorOccured(QProcess::ProcessError error)
{
ERROR_LOG(m_logger) << "error: " << error << ", " << m_proc->readAllStandardOutput() << ", " << m_proc->readAllStandardError();
}
QString CopyDatabase::getDumpFile() const
{
return QDir::tempPath() + QLatin1Char('/') + m_srcDbName + QStringLiteral(".dump");
}
QString CopyDatabase::executablePath(const QString &program)
{
QString errStr;
const QString ret = NGL::postgresExecutablePath(program, errStr);
if (!errStr.isEmpty())
WARNING_LOG(m_logger) << errStr;
return ret;
}
} // namespace DBAdministration
+62
View File
@@ -0,0 +1,62 @@
/*
* @RDE_HEADER@
* Copy exercise from server to evaluation server
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, NLSE, 2018-07-31
*/
#pragma once
#include <QObject>
#include <QProcess>
#include "logger.h"
namespace OcBaseDownload
{
class CopyDatabase : public QObject
{
Q_OBJECT
public:
explicit CopyDatabase(NGL::INGLLogger &logger, QObject *parent = nullptr);
bool init(const QString &dbHost, const QString &srcDbName, const QString &dstDbName);
bool doCopy();
bool dropDatabase(const QString &dbName);
Q_SIGNALS:
void copyDbFailed();
void copyDbFinished();
void dropDatabaseFailed();
void dropDatabaseFinished();
private:
bool runDropDb(const QString &dbName);
void onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus);
void runGrant();
bool runPgDump();
void onPgDumpFinished(int exitCode, QProcess::ExitStatus exitStatus);
void runCreatedb();
void onCreateDbFinished(int exitCode, QProcess::ExitStatus exitStatus);
void runPgLoad();
void onPgLoadFinished(int exitCode, QProcess::ExitStatus exitStatus);
void runPgSetGrant();
void onPgSetGrantFinished(int exitCode, QProcess::ExitStatus exitStatus);
QString getDumpFile() const;
void handleProcInit(const QString &program, const QStringList &args);
void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onErrorOccured(QProcess::ProcessError error);
QString executablePath(const QString &program);
private:
QString m_dbHost;
QString m_srcDbName;
QString m_dstDbName;
QProcess *m_proc;
NGL::INGLLogger &m_logger;
};
} // namespace OcBaseDownload
+47
View File
@@ -0,0 +1,47 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-02
*/
#include "dds_handler.h"
#include <DDS/DTS/generic_dts_impl.h>
#include <DDS/Core/pacemaker.h>
namespace OcBaseDownload
{
DdsHandler::DdsHandler(int domainId)
: m_ddsConnector(std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Global, 0))
, m_logger(getLogger("DdsHandler"))
{
DEBUG_LOG(m_logger) << "DdsHandler(" << domainId << ") for partition: " << m_ddsConnector->getDefaultPartition();
}
bool DdsHandler::init(const QStringList &qosFileList)
{
if(!m_ddsConnector->init(qosFileList))
{
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
return false;
}
// default initialize Publisher and Subscriber
m_ddsConnector->initPublisherSubscriber();
// Pacemaker
m_pacemaker = std::make_shared<Core::Pacemaker>(m_ddsConnector);
m_topicLockMaster = std::make_shared<Core::TopicLockMaster>(m_ddsConnector);
m_ddsFts = OcBaseDownload::Interface::Fts::create(m_ddsConnector);
bool bRet = m_ddsFts->enableAll();
INFO_LOG(m_logger) << "Fts initialised";
return bRet;
}
} // namespace OcBaseDownload
+48
View File
@@ -0,0 +1,48 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-02
*/
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/Core/topic_lock_master.h>
#include <DDS/Core/core_dts_types.h>
#include <OcBaseDownload/obd_fts.h>
#include "logger.h"
namespace Core
{
class Pacemaker;
}
namespace OcBaseDownload
{
class DdsHandler final
{
public:
explicit DdsHandler(int domainId);
~DdsHandler() = default;
bool init(const QStringList &qosFileList = QStringList());
std::shared_ptr<Core::Pacemaker> pacemaker() const { return m_pacemaker; }
std::shared_ptr<Core::TopicLockMaster> topicLockMaster() const { return m_topicLockMaster; }
std::shared_ptr<DDSConnector::DdsConnector> dds() const { return m_ddsConnector; }
std::shared_ptr<OcBaseDownload::Interface::Fts> fts() const { return m_ddsFts; }
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<DTS::CurrentRunningState> m_dtsCurrentRunningState;
std::shared_ptr<Core::Pacemaker> m_pacemaker;
std::shared_ptr<Core::TopicLockMaster> m_topicLockMaster;
std::shared_ptr<OcBaseDownload::Interface::Fts> m_ddsFts;
NGL::INGLLogger &m_logger;
};
} // namespace OcBaseDownload
File diff suppressed because it is too large. Load diff
+303
View File
@@ -0,0 +1,303 @@
/**
* Handler for base download coordination
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, NLST, 15-03-2018
*/
#pragma once
#include <QElapsedTimer>
#include <QObject>
#include <QSqlDatabase>
#include <QTimer>
// db
#include <AssetManagement/asm_db.h>
#include <Evaluations/evl_db.h>
#include <ExerciseManagement/exm_db.h>
#include <FileManagement/flm_db.h>
#include <InfrastructureManagement/ism_db.h>
#include <Messaging/msg_db.h>
#include <MarkerManagement/mrk_db.h>
#include <EffectShowClient/esc_db.h>
#include <FilterManagement/flt_db.h>
#include <AreaEffectSimulation/aes_db.h>
#include <ParticipantManagement/ppm_db.h>
#include <OperatorManagement/opm_db.h>
#include <DBAdministration/exercise_table_generator.h>
// dds
#include <OcBaseDownload/obd_fts.h>
#include <ServiceManagement/scm_dtc.h>
#include <ServiceManagement/scm_ftc.h>
#include "logger.h"
namespace OcBaseDownload
{
class CopyDatabase;
class DbDataEntry
{
public:
virtual ~DbDataEntry() = default;
};
template <typename T>
class DbData : public DbDataEntry
{
public:
explicit DbData(std::vector<T> &&dataVec)
: m_dataVec(std::move(dataVec))
{}
~DbData() = default;
const std::vector<T> &data() const { return m_dataVec; }
private:
std::vector<T> m_dataVec;
};
class MainHandler;
class HandlerBaseDownload : public QObject
, protected Interface::Fts::StartBaseDownloadRequestHandler
, protected Interface::Fts::LifeUpdateRequestHandler
, protected ServiceManagement::Interface::Ftc::RestartGroupReplyHandler
, protected ServiceManagement::Interface::Ftc::StopGroupReplyHandler
{
Q_OBJECT
public:
explicit HandlerBaseDownload(MainHandler *mainHandler,
QObject *parent = nullptr);
~HandlerBaseDownload();
bool init();
// handling ErrorMessage
void handleErrorMessage(const QString &err);
void receiveAsmData();
void receiveExmData();
void receiveIsmData();
void receivePpmEx0Data();
void receivePpmExNData();
void receiveOpmData();
void receiveFlmData();
private slots:
void updateBaseDownloadReply();
private:
enum State
{
NotStarted = 0,
Finished = 0x8000,
StepCount = 20, // Update if adding new steps ...
SingleStepSize = 100 / StepCount,
ServicePortsInformationRequest = 1,
ServicePortsInformationFinished = ServicePortsInformationRequest | Finished,
// Donwloads
AsmDownloadRequest = 2,
AsmDownloadFinished = AsmDownloadRequest | Finished,
ExmDownloadRequest = 3,
ExmDownloadFinished = ExmDownloadRequest | Finished,
IsmDownloadRequest = 4,
IsmDownloadFinished = IsmDownloadRequest | Finished,
PpmDownloadEx0Request = 5,
PpmDownloadEx0Finished = PpmDownloadEx0Request | Finished,
PpmDownloadExNRequest = 6,
PpmDownloadExNFinished = PpmDownloadExNRequest | Finished,
OpmDownloadRequest = 7,
OpmDownloadFinished = OpmDownloadRequest | Finished,
FlmDownloadRequest = 8,
FlmDownloadFinished = FlmDownloadRequest | Finished,
// removing old exercise
DeletingOldExercise = 20,
DeletingOldExerciseFinished = DeletingOldExercise | Finished,
// storing new db data
InsertingAsmData = 21,
InsertingAsmDataFinished = InsertingAsmData | Finished,
InsertingPpmEx0Data = 22,
InsertingPpmEx0DataFinished = InsertingPpmEx0Data | Finished,
InsertingExmData = 23,
InsertingExmDataFinished = InsertingExmData | Finished,
InsertingIsmData = 24,
InsertingIsmDataFinished = InsertingIsmData | Finished,
InsertingPpmExNData = 25,
InsertingPpmExNDataFinished = InsertingPpmExNData | Finished,
InsertingOpmData = 26,
InsertingOpmDataFinished = InsertingOpmData | Finished,
InsertingFlmData = 27,
InsertingFlmDataFinished = InsertingFlmData | Finished,
UpdatingLtsConfig = 28,
UpdatingLtsConfigFinished = UpdatingLtsConfig | Finished,
CopyDatabaseRequest = 29,
CopyDatabaseFinished = CopyDatabaseRequest | Finished,
DropOldDatabaseRequest = 30,
DropOldDatabaseFinished = DropOldDatabaseRequest | Finished,
CopyDataRequest = 31,
CopyDataFinished = CopyDataRequest | Finished,
};
enum DbDataType
{
AsmTrainingArea = 1,
AsmLocation = 2,
AsmAsset = 3,
AsmTechnicalArea = 4,
ExmExercise = 10,
ExmExercisePhase = 11,
ExmExerciseStateChange = 12,
IsmAsset = 20,
IsmMainStructureElement = 21,
IsmStructureElement = 23,
IsmStructureElementFootprint = 24,
IsmMountingPointAsset = 25,
IsmMountingPointSchedule = 26,
IsmMountingPointPlan = 27,
IsmSpecialArea = 28,
PpmEquipmentType = 30,
PpmType = 31,
PpmParty = 32,
PpmParticipant = 33,
OpmGroup = 40,
OpmGroupGroup = 41,
OpmOperator = 42,
OpmOperatorExercise = 43,
OpmSettings = 44,
OpmAccessControlLevel = 45,
OpmAclAllow = 46,
OpmAclDeny = 47,
FlmFolder = 50,
FlmFileContent = 51
};
void onStartBaseDownloadRequest(const rti::core::SampleIdentity &cookie,
const StartBaseDownloadRequest &request) override;
void onLifeUpdateRequest(const rti::core::SampleIdentity &cookie,
const LiveUpdateRequest &request) override;
// state, connection, db and service handling
void switchLog(State state, const std::string &currentStep);
void stateFinished();
void switchState();
void dropOldDatabase();
void onDropOldDatabaseFailed();
void onDropOldDatabaseFinished();
void copyDatabase();
void onCopyDbFailed();
void onCopyDbFinished();
bool openDbConnection(const QString &databaseName);
bool openRemoteDbConnection(const QString &remoteDatabaseName);
QSqlDatabase openDb(const QString &databaseName, bool remote, bool *bOk);
void closeDb(QSqlDatabase &dbConn);
template <typename T>
const std::vector<T> &getDbDataVec(DbDataType type) const;
// download completion checks
void checkForAsmFinished();
void checkForExmFinished();
void checkForIsmFinished();
void checkForPpmEx0Finished();
void checkForPpmExNFinished();
void checkForOpmFinished();
void checkForFlmFinished();
// inserting new data
void removeOldExercises();
void replaceAsmDbData();
void createNewExercise();
void replaceExmDbData();
void replaceIsmDbData();
void replacePpmEx0DbData();
void insertPpmExNDbData(bool live = false);
void replaceOpmDbData();
void replaceFlmDbData();
void cleanup(const Core::FtReplyState &replyState, const std::string &errStr = std::string());
void retryCurrentSelect();
void copyFromOldDatabase();
void copyOldOpmData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
void copyOldEvlData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
void copyOldMsgData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
void copyOldFlmData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
void copyOldMrkData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
void copyOldEscData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
void copyOldFltData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
void copyOldAesData(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut) const;
bool copyTable(const QSqlDatabase &dbIn, const QSqlDatabase &dbOut, QString tableName);
bool fixUpSequence(const QSqlDatabase &dbOut, const QString &tableName);
void updateLtsConfig();
void onStopGroupReply(const Core::FunctionReplyObject &reply) override;
void onRestartGroupReply(const Core::FunctionReplyObject &reply) override;
void restartCoreGroup();
QString currentDatabaseName() const;
QString nextDatabaseName() const;
int getFolderId(const QVector<FileManagement::Database::FlmFolder> &dataVec, const QString &folderName, int exerciseId) const;
void checkAliveTimer();
std::shared_ptr<Interface::Fts> m_fts;
std::shared_ptr<ServiceManagement::Interface::Dtc> m_scmDtc;
std::shared_ptr<ServiceManagement::Interface::Ftc> m_scmFtc;
// DB data vector
QMap<DbDataType, DbDataEntry *> m_dataVecMap;
template <typename T>
void storeToDataVecMap(DbDataType type, std::vector<T> &&dataVec)
{
delete m_dataVecMap.take(type);
m_dataVecMap[type] = new DbData<T>(std::move(dataVec));
}
rti::core::SampleIdentity m_baseDownloadCookie;
BaseDownloadReply m_reply;
QTimer *m_baseDownloadReplyUpdateTimer;
MainHandler *m_mainHandler;
int m_exerciseId;
int m_operatorId;
QString m_hostname;
//int m_currentPort;
State m_currentState;
QSqlDatabase m_dbConnection;
QSqlDatabase m_remoteDbConnection;
QElapsedTimer m_aliveTimer;
//int m_webSocketRetryCounter;
int m_remoteDbRetryCounter;
QSet<int> m_stopGroupIds;
QVector<QString> m_databasesToDrop;
CopyDatabase *m_copyDatabase;
DBAdministration::ExerciseTableGenerator *m_exTblGen;
LOGGER_T &m_logger;
};
} // namespace OcBaseDownload
+488
View File
@@ -0,0 +1,488 @@
/**
* Handler for PDF download coordination
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 26-04-2019
*/
#include "handler_pdf_download.h"
#include "WebSocketInterface/Messages/reply_message.h"
#include <QUuid>
#include "pdf_downloader.h"
#include <ngldb/db_service_handler.h>
#include <nglsettings/nglsettings_connections.h>
#include <nglsettings/nglsettings_settings.h>
#include <ngldb/dbtransaction.h>
#include <ngldb/dbconnection.h>
#include <ngldb/ngldb_export.h>
#include <ngldb/nsqlquery.h>
#include <ngltools/ngltools_filesystem.h>
#include "main_handler.h"
#include "settings.h"
#include <QFileInfo>
#include <QDir>
namespace OcBaseDownload
{
HandlerPdfDownload::HandlerPdfDownload(MainHandler *mainHandler, QObject *parent)
: QObject(parent)
, Interface::Fts::GetPdfListRequestHandler(mainHandler->dds()->fts())
, Interface::Fts::StartPdfDownloadRequestHandler(mainHandler->dds()->fts())
, Interface::Fts::OcPdfDownloadRequestHandler(mainHandler->dds()->fts())
, m_fts(mainHandler->dds()->fts())
, m_webSocket(mainHandler->handlerWebSocket())
, m_mainHandler(mainHandler)
, m_exerciseId(0)
, m_hostname(NGL::Connections::hostName(NGL::Connections::eConnection::SCM_WEBSOCKET))
, m_remoteHostName(Settings::remoteDbHostName())
, m_currentPort(NGL::Connections::port(NGL::Connections::eConnection::SCM_WEBSOCKET))
, m_currentMode(Mode::PORT_REQUEST)
, m_downloader(nullptr)
, m_logger(getLogger("HandlerPdfDownload"))
{
}
HandlerPdfDownload::~HandlerPdfDownload()
{
m_fts = nullptr;
}
bool HandlerPdfDownload::init()
{
INFO_LOG(m_logger) << "HandlerPdfDownload initialised!";
return true;
}
void HandlerPdfDownload::handleServicePortsInformation(const QVector<WebSocketInterface::Messages::ServicePortsInformation::ExerciseInformation> &portsInformation)
{
m_webSocket->close();
int flmPort = 0;
for (const auto &exercise : portsInformation)
{
if (exercise.exerciseId == 0)
{
for (const auto &service : exercise.services)
{
if (service.abbreviation == QStringLiteral("flm"))
{
for (const auto &port : service.ports)
{
if (port.type == Core::PortType::WebSocketServer)
{
flmPort = port.number;
break;
}
}
}
}
}
}
m_currentMode = Mode::LIST_REQUEST;
if (flmPort)
m_webSocket->open(m_hostname, flmPort);
else
{
ERROR_LOG(m_logger) << "Could not connect to FileManagement WebSocket server.";
m_currentMode = Mode::PORT_REQUEST;
}
}
void HandlerPdfDownload::handlePdfListData(const WebSocketInterface::Messages::PdfListMessage::PdfListData &pdfListData)
{
m_webSocket->close();
PdfListReply rep;
auto &documentInformation = rep.documents();
documentInformation.reserve(pdfListData.pdfData.size());
for (const WebSocketInterface::Messages::PdfListMessage::PdfInformation &currentInfo : pdfListData.pdfData)
documentInformation.emplace_back(currentInfo.id,
currentInfo.name.toStdString(),
false,
false);
disconnect(m_webSocket.get(), &WebSocketInterface::WebSocketInterfaceHandler::connected, this, &HandlerPdfDownload::onConnected);
disconnect(m_webSocket.get(), &WebSocketInterface::WebSocketInterfaceHandler::disconnected, this, &HandlerPdfDownload::onDisconnected);
m_fts->getPdfListReply(m_pdfListCookie, rep);
m_pdfData = pdfListData.pdfData;
m_currentMode = Mode::PORT_REQUEST;
m_webSocket->setCurrentDownload(WebSocketInterface::CurrentDownload::NOTHING);
}
void HandlerPdfDownload::onGetPdfListRequest(const rti::core::SampleIdentity &cookie, const GetPdfListRequest &request)
{
m_webSocket->setCurrentDownload(WebSocketInterface::CurrentDownload::PDF);
m_hostname = NGL::Connections::hostName(NGL::Connections::eConnection::SCM_WEBSOCKET);
m_currentPort = NGL::Connections::port(NGL::Connections::eConnection::SCM_WEBSOCKET);
m_pdfListCookie = cookie;
m_hostname = QString::fromStdString(request.hostname());
m_currentPort = request.portNumber();
m_exerciseId = request.exerciseId();
connect(m_webSocket.get(), &WebSocketInterface::WebSocketInterfaceHandler::connected, this, &HandlerPdfDownload::onConnected);
connect(m_webSocket.get(), &WebSocketInterface::WebSocketInterfaceHandler::disconnected, this, &HandlerPdfDownload::onDisconnected);
openWebSocket();
}
void HandlerPdfDownload::onStartPdfDownloadRequest(const rti::core::SampleIdentity &cookie, const StartPdfDownloadRequest &request)
{
ERROR_LOG(m_logger) <<" onOcPdfDownloadRequest START" ;
m_downloadReply = PdfDownloadReply();
m_downloadCookie = cookie;
if (m_logger.isDebugEnabled())
{
QString str = QStringLiteral("Got PDF download request for ids: ");
for (int32_t id : request.documentIds())
str.append(QString::number(id) + QStringLiteral(" "));
DEBUG_LOG(m_logger) << str;
}
if (m_hostname.isEmpty())
{
QString errorStr = QStringLiteral("Not able to start PDF download. Hostname not set.");
ERROR_LOG(m_logger) << errorStr;
m_downloadReply.errorString(errorStr.toStdString());
m_fts->startPdfDownloadReply(m_downloadCookie, m_downloadReply);
return;
}
typedef WebSocketInterface::Messages::PdfListMessage::PdfInformation pdfInfo;
const auto containsId = [](const std::vector<int> &cont, int idToSearch) -> bool
{
for (const int curId : cont)
if (curId == idToSearch)
return true;
return false;
};
QVector<pdfInfo> pdfInfoVec;
for (const auto &current : qAsConst(m_pdfData))
{
if (!containsId(request.documentIds(), current.id))
continue;
pdfInfoVec.append(current);
}
if (m_downloader)
{
disconnect(m_downloader);
delete m_downloader;
m_downloader = nullptr;
}
m_downloader = new PdfDownloader(pdfInfoVec, m_mainHandler, m_hostname, m_exerciseId, this);
connect(m_downloader, &PdfDownloader::newState,
this, &HandlerPdfDownload::onNewDownloadState);
connect(m_downloader, &PdfDownloader::allDownloadsFinished,
this, &HandlerPdfDownload::onAllDownloadsFinished);
m_downloader->startDownload();
}
void HandlerPdfDownload::onOcPdfDownloadRequest(const rti::core::SampleIdentity &cookie, const OcPdfDownloadRequest &request)
{
DEBUG_LOG(m_logger) <<LOGFUNCTION<<" START OcPdfDownloadRequest" ;
m_ocPdfDownloadCookie = cookie;
m_ocPdfDownloadReply = Core::FunctionReply();
if(openRemoteDbConnection(QStringLiteral("lts_ets_pro")) == false)
{
QString errorStr = QStringLiteral("Not able to open remote connection to DB");
ERROR_LOG(m_logger) << errorStr;
m_ocPdfDownloadReply.errorString(errorStr.toStdString());
m_fts->ocPdfDownloadReply(m_ocPdfDownloadCookie, m_ocPdfDownloadReply);
return;
}
DEBUG_LOG(m_logger) << "Got PDF download request for ids: "<< request.folderId();
m_folderId = request.folderId();
if(m_folderId == -1)
{
QString errorStr = QStringLiteral("Not able to start PDF download. Folder id not valid.");
ERROR_LOG(m_logger) << errorStr;
m_ocPdfDownloadReply.errorString(errorStr.toStdString());
m_fts->ocPdfDownloadReply(m_ocPdfDownloadCookie, m_ocPdfDownloadReply);
return;
}
m_operatorName = QString::fromStdString(request.matrixOperator());
if (m_hostname.isEmpty())
{
QString errorStr = QStringLiteral("Not able to start PDF download. Hostname not set.");
ERROR_LOG(m_logger) << errorStr;
m_ocPdfDownloadReply.errorString(errorStr.toStdString());
m_fts->ocPdfDownloadReply(m_ocPdfDownloadCookie, m_ocPdfDownloadReply);
return;
}
exportOcPdfFileContent();
m_fts->ocPdfDownloadReply(m_ocPdfDownloadCookie, m_ocPdfDownloadReply);
closeDb(m_remoteDbConnection);
}
void HandlerPdfDownload::exportOcPdfFileContent()
{
// handling FLM data
using namespace FileManagement;
auto remoteDb = std::unique_ptr<NGLDB::DbServiceHandler<DatabaseInterface>>(new NGLDB::DbServiceHandler<DatabaseInterface>());
if (!remoteDb->init(0, m_remoteDbConnection))
{
const QString err = tr("Can't open remote Database");
m_ocPdfDownloadReply.errorString(err.toStdString());
return;
}
auto remoteDbIfc = remoteDb->db();
const QString dir = QStringLiteral("%1/OcPdf/%2/").arg(QDir::tempPath()).arg(m_operatorName);
DEBUG_LOG(m_logger)<<" export path: "<<dir;
QDir directory(dir);
if(!directory.exists())
directory.mkpath(dir);
const QString fExts = QStringLiteral(".pdf");
//first we look up our username folder
QString strm = QStringLiteral("Select id from flm.flm_folder WHERE name = '" ) + m_operatorName + QStringLiteral("' and '") +
QString::number(m_folderId) + QStringLiteral("' = ANY(path) LIMIT 1;");
DEBUG_LOG(m_logger) << "folder content ID querry" << strm;
std::unique_ptr<NSqlQuery> query = std::unique_ptr<NSqlQuery>(new NSqlQuery(remoteDbIfc->database(), m_logger));
query->prepare(strm);
qlonglong folderId = -1;
if (query->exec())
{
while (query->next())
{
folderId = query->value(0).toLongLong();
}
}
if(folderId < 0)
{
const QString err = tr("Can't find user folder in remote Database");
m_ocPdfDownloadReply.errorString(err.toStdString());
return;
}
/// check first if the pdf file is not alreay exist and oudated without loading file content
/// get ids of pdf file matching the named condition
QString where = QStringLiteral(" WHERE folder_id =%1 ").arg(QString::number(folderId)) +
QStringLiteral(" AND file_type_id=%1 ").arg(FileManagement::FileType_def::Pdf);
QString tableName(QStringLiteral("flm.flm_file_content"));
QString stmt(QStringLiteral("SELECT id, name, last_modified "
" FROM ") + tableName + where);
QStringList idsList;
query->prepare(stmt);
if (query->exec())
{
Database::FlmFileContent data;
while (query->next())
{
int i = 0;
data.id = query->value(i++).toLongLong();
data.name = query->value(i++).toString();
data.lastModified = query->value(i++).toLongLong();
QString fileName = dir + QString(data.name).trimmed() + fExts;
QFileInfo fileInfo(fileName);
bool fileExists = fileInfo.exists();
if(!fileExists ||
(data.lastModified > fileInfo.lastModified().toMSecsSinceEpoch()))
{
idsList << QString::number(data.id);
}
}
}
if(idsList.isEmpty())
{
WARNING_LOG(m_logger)<< " pdf files outdated! ";
return;
}
/// start a new query with id matching the define condition of beeing newer than current existing file
/// or file doesn't exist
/// folderId is used in the first statement so no need to reuse it for second one. just use id offlm_file_content
where = QStringLiteral(" WHERE id IN (%1)").arg(idsList.join(QStringLiteral(","))) +
QStringLiteral(" AND file_type_id=%1 ").arg(FileManagement::FileType_def::Pdf);
tableName = (QStringLiteral("flm.flm_file_content"));
stmt = (QStringLiteral("SELECT id, name, file_status_id, content, last_modified FROM ") + tableName + where);
DEBUG_LOG(m_logger) << "### statement: " << stmt;
query->prepare(stmt);
QVector<Database::FlmFileContent> dataVec;
if (query->exec())
{
Database::FlmFileContent data;
while (query->next())
{
int i = 0;
data.id = query->value(i++).toLongLong();
data.name = query->value(i++).toString();
data.fileStatusId = static_cast<FileManagement::FileStatus_def::type>(query->value(i++).toInt());
data.content = query->value(i++).toByteArray();
data.lastModified = query->value(i++).toLongLong();
if(data.fileStatusId == FileManagement::FileStatus::Deleted)
{
DEBUG_LOG(m_logger)<< " skip ";
continue;
}
dataVec.append(data);
}
}
else
{
const QString errorStr = tr("Not able to export PDF.");
ERROR_LOG(m_logger) << errorStr;
m_ocPdfDownloadReply.errorString(errorStr.toStdString());
return;
}
for(const auto &data : dataVec)
{
QByteArray content = data.content;
QString fileName = dir + QString(data.name).trimmed() + fExts;
QFile file(fileName);
QFileInfo fileInfo(file);
// remove if exist file by their name
if(fileInfo.exists() && file.remove() == false)
{
QString err = QStringLiteral("Couldn't replace existing file: ") + data.name;
WARNING_LOG(m_logger)<< err;
continue;
}
if(!file.open(QIODevice::WriteOnly))
{
QString err = tr("Failed to write file: ") + (data.name);
m_ocPdfDownloadReply.errorString(err.toStdString());
return;
}
file.write(content);
file.close();
}
}
bool HandlerPdfDownload::openRemoteDbConnection(const QString &remoteDatabaseName)
{
DEBUG_LOG(m_logger) <<" Open RemoteDb Connection..." ;
if (m_remoteDbConnection.isValid())
closeDb(m_remoteDbConnection);
bool bOk;
m_remoteDbConnection = openDb(remoteDatabaseName, true, &bOk);
if (!bOk)
return false;
return true;
}
QSqlDatabase HandlerPdfDownload::openDb(const QString &databaseName, bool remote, bool *bOk)
{
if (bOk)
*bOk = true;
// open postgres db, read table structure, read static data
auto s = Settings::settings();
const QString dbUser(QStringLiteral("ets_exm"));
const QString dbPasswd(QStringLiteral("ets11de"));
QSqlDatabase dbConnection = DBConnection::open(m_logger,
dbUser,
dbPasswd,
s->databaseDriver(),
remote ? m_remoteHostName : s->databaseHostname(),
remote ? Settings::remoteDbName() : databaseName);
DEBUG_LOG(m_logger) << "Trying to open database " << s->databaseHostname() << ":" << databaseName;
if (!dbConnection.isOpen())
{
ERROR_LOG(m_logger) << "Error opening database " << s->databaseHostname() << ":" << databaseName;
if (bOk)
*bOk = false;
}
else
NOTICE_LOG(m_logger) << "Opened database connection " << dbConnection.connectionName();
return dbConnection;
}
void HandlerPdfDownload::closeDb(QSqlDatabase &dbConn)
{
const QString connName = dbConn.connectionName();
NOTICE_LOG(m_logger) << "Closing database connection " << connName;
dbConn.close();
dbConn = QSqlDatabase();
QSqlDatabase::removeDatabase(connName);
}
void HandlerPdfDownload::onConnected()
{
INFO_LOG(m_logger) << "Connected to WebSocket server";
switch (m_currentMode)
{
case Mode::PORT_REQUEST:
m_webSocket->send(new WebSocketInterface::Messages::ServicePortsInformationRequest(QUuid::createUuid().toString()));
break;
case Mode::LIST_REQUEST:
m_webSocket->send(new WebSocketInterface::Messages::PdfListRequest(QUuid::createUuid().toString(), m_exerciseId));
break;
}
}
void HandlerPdfDownload::onDisconnected()
{
INFO_LOG(m_logger) << "Disconnected from server.";
}
void HandlerPdfDownload::onNewDownloadState(int progress, const QString &msg)
{
DEBUG_LOG(m_logger) << msg;
m_downloadReply.replyState(Core::FtReplyState::InProgress);
m_downloadReply.progress(progress);
m_downloadReply.currentStep(msg.toStdString());
m_fts->startPdfDownloadReply(m_downloadCookie, m_downloadReply);
}
void HandlerPdfDownload::onAllDownloadsFinished()
{
DEBUG_LOG(m_logger) << "Downloads finished";
m_downloadReply.replyState(Core::FtReplyState::Completed);
m_downloadReply.currentStep(tr("Downloads finished").toStdString());
m_downloadReply.progress(100);
m_fts->startPdfDownloadReply(m_downloadCookie, m_downloadReply);
}
void HandlerPdfDownload::openWebSocket()
{
DEBUG_LOG(m_logger) << "Opening websocket to: " << m_hostname << ":" << m_currentPort;
m_webSocket->open(m_hostname, m_currentPort);
}
} // namespace OcBaseDownload
+86
View File
@@ -0,0 +1,86 @@
/**
* Handler for PDF download coordination
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 26-04-2019
*/
#pragma once
// dds
#include <OcBaseDownload/obd_fts.h>
#include <QSqlDatabase>
#include <FileManagement/flm_db.h>
#include <FileManagement/flm_db_impl_custom.h>
#include "WebSocketInterface/Messages/client_message.h"
#include "WebSocketInterface/websocket_interface_handler.h"
#include "pdf_download_socket.h"
#include "logger.h"
namespace OcBaseDownload
{
class PdfDownloader;
class MainHandler;
class HandlerPdfDownload : public QObject
, protected Interface::Fts::GetPdfListRequestHandler
, protected Interface::Fts::StartPdfDownloadRequestHandler
, protected Interface::Fts::OcPdfDownloadRequestHandler
{
Q_OBJECT
public:
explicit HandlerPdfDownload(MainHandler *mainHandler,
QObject *parent = nullptr);
~HandlerPdfDownload();
bool init();
void handleServicePortsInformation(const QVector<WebSocketInterface::Messages::ServicePortsInformation::ExerciseInformation> &portsInformation);
void handlePdfListData(const WebSocketInterface::Messages::PdfListMessage::PdfListData &pdfListData);
void onGetPdfListRequest(const rti::core::SampleIdentity &cookie, const GetPdfListRequest &request) override final;
void onStartPdfDownloadRequest(const rti::core::SampleIdentity &cookie, const StartPdfDownloadRequest &request) override final;
void onOcPdfDownloadRequest(const rti::core::SampleIdentity &cookie, const OcPdfDownloadRequest &request )override final;
void exportOcPdfFileContent();
bool openRemoteDbConnection(const QString &remoteDatabaseName);
QSqlDatabase openDb(const QString &databaseName, bool remote, bool *bOk);
void closeDb(QSqlDatabase &dbConn);
private Q_SLOTS:
void onConnected();
void onDisconnected();
void onNewDownloadState(int progress, const QString &msg);
void onAllDownloadsFinished();
private: // other
enum class Mode
{
PORT_REQUEST,
LIST_REQUEST,
};
private: // methods
void openWebSocket();
private: // attributes
std::shared_ptr<Interface::Fts> m_fts;
std::shared_ptr<WebSocketInterface::WebSocketInterfaceHandler> m_webSocket;
MainHandler *m_mainHandler;
int m_exerciseId;
int m_folderId;
QString m_operatorName;
QString m_hostname;
QString m_remoteHostName;
int m_currentPort;
rti::core::SampleIdentity m_pdfListCookie;
rti::core::SampleIdentity m_downloadCookie;
rti::core::SampleIdentity m_ocPdfDownloadCookie;
PdfDownloadReply m_downloadReply;
Core::FunctionReply m_ocPdfDownloadReply;
Mode m_currentMode;
QVector<WebSocketInterface::Messages::PdfListMessage::PdfInformation> m_pdfData;
PdfDownloader *m_downloader;
QSqlDatabase m_remoteDbConnection;
LOGGER_T &m_logger;
};
} // namespace OcBaseDownload
+83
View File
@@ -0,0 +1,83 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# Service: OcBaseDownload
###########################################################
#log4j.logger.OBD=DEBUG
#log4j.logger.OBD.main=DEBUG
#log4j.logger.OBD.DdsHandler=DEBUG
#log4j.logger.OBD.MainHandler=DEBUG
#log4j.logger.OBD.Datamanager=DEBUG
#log4j.logger.OBD.HandlerBaseDownload=DEBUG
#log4j.logger.Lts.WebSocket=DEBUG
#
# Lts::RollingFileAppender
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:
+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace OcBaseDownload
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "OBD.";
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 OcBaseDownload
+23
View File
@@ -0,0 +1,23 @@
/**
* @RDE_HEADER@
* Logging for OcBaseDownload
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
#include "obd_export.h"
namespace OcBaseDownload
{
using LOGGER_T = NGL::INGLLogger &;
OBD_COMMON_EXPORT LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace OcBaseDownload
+42
View File
@@ -0,0 +1,42 @@
/**
* @RDE_HEADER@
* main for OcBaseDownload
* $Id$
* $HeadURL$
* $Author$
*/
#include <nglapplication/nglcoreapplication.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
#include "main_handler.h"
#include "logger.h"
#include "settings.h"
int main(int argc, char **argv)
{
NGLCoreApplication app(argc, argv);
LtsCommandLineParser::LtsCommandLineParser options;
if (!options.init())
return -1;
app.createLogger("OBD", options.exerciseId());
OcBaseDownload::Settings::setIniFile(options.iniFile());
int iRet = -3;
{
std::unique_ptr<OcBaseDownload::MainHandler> mainHandler(new OcBaseDownload::MainHandler);
if (!mainHandler->init(options.domainId()))
return iRet;
STARTUP_LOG(app.baseLogger());
iRet = app.exec();
SHUTDOWN_LOG(app.baseLogger());
}
return iRet;
}
+85
View File
@@ -0,0 +1,85 @@
/**
* MainHandler for AssetManagement
* $Id$
* $HeadURL$
* $Author$
*/
#include "main_handler.h"
#include <DDS/Core/pacemaker.h>
#include <ngldb/db_service_handler.h>
namespace OcBaseDownload
{
MainHandler::MainHandler(QObject *parent)
: QObject(parent)
, m_ddsHandler(nullptr)
, m_handlerBaseDownload(nullptr)
, m_handlerPdfDownload(nullptr)
, m_handlerWebSocket(nullptr)
, m_scmDtc(nullptr)
, m_scmFtc(nullptr)
, m_logger(getLogger("MainHandler"))
{}
MainHandler::~MainHandler()
{
m_ddsHandler = nullptr;
m_handlerBaseDownload = nullptr;
m_handlerPdfDownload = nullptr;
m_handlerWebSocket = nullptr;
m_scmDtc = nullptr;
m_scmFtc = nullptr;
}
bool MainHandler::init(int domainId)
{
// initialize DDS
m_ddsHandler = std::make_shared<DdsHandler>(domainId);
if (!m_ddsHandler->init())
{
ERROR_LOG(m_logger) << "Initialisation ddsHandler failed.";
return false;
}
DEBUG_LOG(m_logger) << "Initialisation ddsHandler succesful.";
// create SCM Dtc
m_scmDtc = ServiceManagement::Interface::Dtc::create(m_ddsHandler->dds());
DEBUG_LOG(m_logger) << "Created SCM Dtc";
// create SCM Ftc
m_scmFtc = ServiceManagement::Interface::Ftc::create(m_ddsHandler->dds());
DEBUG_LOG(m_logger) << "Created SCM Ftc";
// create handler base download
m_handlerWebSocket = std::make_shared<WebSocketInterface::WebSocketInterfaceHandler>(this);
if (!m_handlerWebSocket->init())
{
ERROR_LOG(m_logger) << "Initialisation HandlerWebSocket failed.";
return false;
}
// create handler base download
m_handlerBaseDownload = std::make_shared<HandlerBaseDownload>(this, this);
if (!m_handlerBaseDownload->init())
{
ERROR_LOG(m_logger) << "Initialisation HandlerBaseDownload failed.";
return false;
}
// create handler pdf download
m_handlerPdfDownload = std::make_shared<HandlerPdfDownload>(this, this);
if (!m_handlerBaseDownload->init())
{
ERROR_LOG(m_logger) << "Initialisation HandlerPdfDownload failed.";
return false;
}
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Running);
return true;
}
} // namespace OcBaseDownload
+56
View File
@@ -0,0 +1,56 @@
/**
* MainHandler for AereaEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QObject>
#include <memory>
#include <ServiceManagement/scm_dtc.h>
#include <ServiceManagement/scm_ftc.h>
#include "dds_handler.h"
#include "handler_base_download.h"
#include "handler_pdf_download.h"
#include "WebSocketInterface/websocket_interface_handler.h"
#include "logger.h"
namespace NGLDB
{
template <typename DB> class DbServiceHandler;
}
namespace OcBaseDownload
{
class MainHandler : public QObject
{
Q_OBJECT
public:
explicit MainHandler(QObject *parent = nullptr);
~MainHandler();
bool init(int domainId);
std::shared_ptr<DdsHandler> dds() const { return m_ddsHandler; }
std::shared_ptr<HandlerBaseDownload> handlerBaseDownload() const { return m_handlerBaseDownload; }
std::shared_ptr<HandlerPdfDownload> handlerPdfDownload() const { return m_handlerPdfDownload; }
std::shared_ptr<WebSocketInterface::WebSocketInterfaceHandler> handlerWebSocket() const { return m_handlerWebSocket; }
std::shared_ptr<ServiceManagement::Interface::Dtc> scmDtc() const { return m_scmDtc; }
std::shared_ptr<ServiceManagement::Interface::Ftc> scmFtc() const { return m_scmFtc; }
private:
std::shared_ptr<DdsHandler> m_ddsHandler;
std::shared_ptr<HandlerBaseDownload> m_handlerBaseDownload;
std::shared_ptr<HandlerPdfDownload> m_handlerPdfDownload;
std::shared_ptr<WebSocketInterface::WebSocketInterfaceHandler> m_handlerWebSocket;
std::shared_ptr<ServiceManagement::Interface::Dtc> m_scmDtc;
std::shared_ptr<ServiceManagement::Interface::Ftc> m_scmFtc;
NGL::INGLLogger &m_logger;
};
} // namespace OcBaseDownload
+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 OBD_COMMON_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define OBD_COMMON_EXPORT
# else
# if defined(MAKE_SVCOBDCOMMON_LIB)
# define OBD_COMMON_EXPORT Q_DECL_EXPORT
# ifndef WIN32
# ifdef NDDSUSERDllExport
# undef NDDSUSERDllExport
# endif
# define NDDSUSERDllExport Q_DECL_EXPORT
# endif
# else
# define OBD_COMMON_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef OBD_CLIENT_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define OBD_CLIENT_EXPORT
# else
# if defined(MAKE_SVCOBDCLIENT_LIB)
# define OBD_CLIENT_EXPORT Q_DECL_EXPORT
# else
# define OBD_CLIENT_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef OBD_SERVER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define OBD_SERVER_EXPORT
# else
# if defined(MAKE_SVCOBDSERVER_LIB)
# define OBD_SERVER_EXPORT Q_DECL_EXPORT
# else
# define OBD_SERVER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<service namespace="OcBaseDownload" abbreviation="OBD" procNames="OcBaseDownload" exerciseDependency="Global" groups="Core" prio="">
<rcs>
<Id Id="$Id: ea_export_script.txt 41311 2018-04-23 09:43:45Z ehrlicher $"/>
<HeadURL HeadURL="$HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Common/CodeGen/ea_export_script.txt $"/>
<Author Author="$Author: ehrlicher $"/>
</rcs>
<tables/>
<views/>
<dbServiceStructs/>
<topicTypes>
<topicType name="BaseDownloadReply" baseValueType="Core::FunctionReplyWithState">
<column name="currentStep" idlType="string"/>
<column name="progress" idlType="long"/>
</topicType>
<topicType name="GetPdfListRequest">
<column name="exerciseId" idlType="long"/>
<column name="hostname" idlType="string"/>
<column name="portNumber" idlType="long"/>
</topicType>
<topicType name="LiveUpdateRequest">
<column name="timeStamp" idlType="long long"/>
<column name="exerciseId" idlType="long"/>
</topicType>
<topicType name="OcPdfDownloadRequest">
<column name="folderId" idlType="long"/>
<column name="matrixOperator" idlType="string"/>
</topicType>
<topicType name="PdfDownloadReply" baseValueType="Core::FunctionReplyWithState">
<column name="currentStep" idlType="string"/>
<column name="progress" idlType="long"/>
</topicType>
<topicType name="PdfInfo">
<column name="id" idlType="long"/>
<column name="name" idlType="string"/>
<column name="folderId" idlType="boolean"/>
<column name="folderId2" idlType="boolean"/>
</topicType>
<topicType name="PdfListReply" baseValueType="Core::FunctionReply">
<column name="documents" idlType="sequence&lt;PdfInfo&gt;"/>
</topicType>
<topicType name="StartBaseDownloadRequest">
<column name="exerciseId" idlType="long"/>
<column name="loggedInOperatorId" idlType="long"/>
<column name="portNumber" idlType="long"/>
<column name="hostname" idlType="string"/>
<column name="timeStamp" idlType="long long"/>
</topicType>
<topicType name="StartPdfDownloadRequest">
<column name="documentIds" idlType="sequence&lt;long&gt;"/>
<column name="hostname" idlType="string"/>
<column name="exerciseId" idlType="long"/>
</topicType>
</topicTypes>
<functionTopics>
<functionTopic name="GetPdfList" requestTopicType="GetPdfListRequest" replyTopicType="PdfListReply" requestTopicName="GetPdfListRequest" replyTopicName="GetPdfListReply" routeInReplay="0"/>
<functionTopic name="StartPdfDownload" requestTopicType="StartPdfDownloadRequest" replyTopicType="PdfDownloadReply" requestTopicName="StartPdfDownloadRequest" replyTopicName="StartPdfDownloadReply" routeInReplay="0"/>
<functionTopic name="LifeUpdate" requestTopicType="LiveUpdateRequest" replyTopicType="Core::FunctionReply" requestTopicName="LifeUpdateRequest" replyTopicName="LifeUpdateReply" routeInReplay="0"/>
<functionTopic name="OcPdfDownload" requestTopicType="OcPdfDownloadRequest" replyTopicType="Core::FunctionReply" requestTopicName="OcPdfDownloadRequest" replyTopicName="OcPdfDownloadReply" routeInReplay="0"/>
<functionTopic name="StartBaseDownload" requestTopicType="StartBaseDownloadRequest" replyTopicType="BaseDownloadReply" requestTopicName="StartBaseDownloadRequest" replyTopicName="StartBaseDownloadReply" routeInReplay="0"/>
</functionTopics>
<enumerations>
<enumeration name="dummyEnum">
<attribute key="dummyVal" value="0"/>
</enumeration>
</enumerations>
</service>
+102
View File
@@ -0,0 +1,102 @@
/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-30
*/
#include "pdf_download_socket.h"
#include <nglsettings/nglsettings_connections.h>
#include <nglsettings/nglsettings_settings.h>
#include <QTimer>
namespace OcBaseDownload
{
PdfDownloadSocket::PdfDownloadSocket(const QString &hostName, QObject *parent)
: QObject(parent)
, m_socket(new QTcpSocket(this))
, m_readTimeout(new QTimer(this))
, m_sizeToDownload(0)
, m_logger(getLogger("PdfDownloadSocket"))
{
DEBUG_LOG(m_logger) << "PdfDownloadSocket::PdfDownloadSocket";
connect(m_socket, &QTcpSocket::connected, this, &PdfDownloadSocket::connected);
connect(m_socket, &QTcpSocket::readyRead, this, &PdfDownloadSocket::readyRead);
unsigned short port = NGL::Connections::port(NGL::Connections::eConnection::FLM_PDF_SERVER);
m_socket->connectToHost(hostName, port);
m_socket->waitForConnected();
DEBUG_LOG(m_logger) << "hostname " << hostName << " port " << port;
m_readTimeout->setInterval(10000);
m_readTimeout->setSingleShot(false);
connect(m_readTimeout, &QTimer::timeout, this, &PdfDownloadSocket::onReadTimeout);
}
PdfDownloadSocket::~PdfDownloadSocket()
{
DEBUG_LOG(m_logger) << "~PdfDownloadSocket";
m_socket->close();
}
void PdfDownloadSocket::readyRead()
{
DEBUG_LOG(m_logger) << "reading...";
m_readTimeout->stop();
m_downloadedData.append(m_socket->readAll());
DEBUG_LOG(m_logger) << m_downloadedData.size() << " of " << m_sizeToDownload << " bytes downloaded";
if (m_downloadedData.size() >= m_sizeToDownload)
{
m_sizeToDownload = 0;
DEBUG_LOG(m_logger) << "Download finished";
emit downloadFinished(m_downloadedData);
}
else
m_readTimeout->start();
}
void PdfDownloadSocket::connected()
{
DEBUG_LOG(m_logger) << "connected...";
}
void PdfDownloadSocket::onReadTimeout()
{
//check for filesize
m_readTimeout->stop();
DEBUG_LOG(m_logger) << "TimerEnd" << m_downloadedData.size() << " expected " << m_sizeToDownload;
if (m_downloadedData.size() < m_sizeToDownload)
WARNING_LOG(m_logger) << "not enough data: got " << m_downloadedData.size() << " expected " << m_sizeToDownload;
emit downloadFinished(m_downloadedData);
}
void PdfDownloadSocket::downloadFromHost(const int fileId, const qint64 fileSize)
{
m_sizeToDownload = fileSize;
m_downloadedData = QByteArray();
QByteArray cmd;
cmd += QByteArray("PDF_DOWNLOAD ");
cmd += QByteArray::number(fileId);
cmd += "\n";
m_socket->readAll();
int writeHeaderSize = m_socket->write(cmd);
DEBUG_LOG(m_logger) << "writeHeaderSize = " << writeHeaderSize;
m_readTimeout->start();
}
bool PdfDownloadSocket::isConnected() const
{
return m_socket->state() == QAbstractSocket::ConnectedState;
}
}
+44
View File
@@ -0,0 +1,44 @@
/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-30
*/
#pragma once
#include "logger.h"
#include <QObject>
#include <QTcpSocket>
#include <QString>
class QTimer;
namespace OcBaseDownload
{
class PdfDownloadSocket : public QObject
{
Q_OBJECT
public:
explicit PdfDownloadSocket(const QString &hostName, QObject *parent);
~PdfDownloadSocket();
void downloadFromHost(const int fileId, const qint64 fileSize);
bool isConnected() const;
void close() { m_socket->close(); }
signals:
void downloadFinished(const QByteArray &data);
private slots:
void readyRead();
void connected();
void onReadTimeout();
private:
QTcpSocket *m_socket;
QTimer *m_readTimeout;
int m_sizeToDownload;
QByteArray m_downloadedData;
NGL::INGLLogger &m_logger;
};
}
+191
View File
@@ -0,0 +1,191 @@
/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-30
*/
#include "pdf_downloader.h"
#include "pdf_download_socket.h"
#include "main_handler.h"
#include <nglsettings/nglsettings_settings.h>
#include <ngldb/dbconnection.h>
#include <ngldb/dbtransaction.h>
#include <ngldb/db_service_handler.h>
#include <ngltools/ngltools_filesystem.h>
#include <QJsonDocument>
namespace OcBaseDownload
{
PdfDownloader::PdfDownloader(const QVector<WebSocketInterface::Messages::PdfListMessage::PdfInformation> &pdfInfoVec, MainHandler *mainHandler, const QString &hostName, int exerciseId, QObject *parent)
: QObject(parent)
, m_pdfInfoVec(pdfInfoVec)
, m_socket(new PdfDownloadSocket(hostName, this))
, m_mainHandler(mainHandler)
, m_exerciseId(exerciseId)
, m_exTblGen(new DBAdministration::ExerciseTableGenerator(getLogger("ExerciseTableGenerator"), NGL::directory(NGL::FileType::ConfigFile, QLatin1String("xml")), this))
, m_downloadCount(0)
, m_totalDownloads(pdfInfoVec.size())
, m_logger(getLogger("PdfDownloader"))
{
connect(m_socket, &PdfDownloadSocket::downloadFinished,
this, &PdfDownloader::onSingleDownloadFinished);
}
PdfDownloader::~PdfDownloader()
{
}
bool PdfDownloader::startDownload()
{
DEBUG_LOG(m_logger) << "Downloading startet";
if (!m_socket->isConnected())
{
ERROR_LOG(m_logger) << "Download could not be startet. Socket not connected.";
return false;
}
if (!openDbConnection())
{
ERROR_LOG(m_logger) << "Could not open database connection";
return false;
}
return startNextDownload();
}
void PdfDownloader::onSingleDownloadFinished(const QByteArray &data)
{
DEBUG_LOG(m_logger) << "Downloading file " << m_currentDownload.name << " finished.";
++m_downloadCount;
if (!data.size())
WARNING_LOG(m_logger) << "Got finished download without data";
QString msg = QString::fromUtf8(data);
if (msg.startsWith(QStringLiteral("ERROR")))
{
ERROR_LOG(m_logger) << msg;
startNextDownload();
return;
}
if (!m_dbConnection.isValid())
{
ERROR_LOG(m_logger) << "Database not open";
return;
}
auto flmDbHandler = std::unique_ptr<NGLDB::DbServiceHandler<FileManagement::DatabaseInterface>>(new NGLDB::DbServiceHandler<FileManagement::DatabaseInterface>());
if (!flmDbHandler->init(0, m_dbConnection))
{
ERROR_LOG(m_logger) << "Couldn't initialise flmDbHandler";
return;
}
DBTransaction trans(m_dbConnection);
FileManagement::Database::FlmFileContent dbData;
dbData.name = m_currentDownload.name;
dbData.isTemplate = m_currentDownload.isTemplate;
dbData.folderId = m_currentDownload.folderId;
dbData.fileCategoryId = m_currentDownload.fileCategory;
dbData.fileTypeId = FileManagement::FileType::Pdf;
dbData.fileStatusId = m_currentDownload.fileStatus;
if (m_currentDownload.exerciseId)
dbData.exerciseId = m_currentDownload.exerciseId;
if (m_currentDownload.phaseId)
dbData.phaseId = m_currentDownload.phaseId;
dbData.operatorId = m_currentDownload.operatorId;
dbData.content = data;
dbData.properties = QString::fromLatin1(QJsonDocument(m_currentDownload.properties.toObject()).toJson(QJsonDocument::Compact));
flmDbHandler->db()->insert(dbData);
if (!trans.commit())
ERROR_LOG(m_logger) << "Error while inserting FLM data into database.";
startNextDownload();
}
bool PdfDownloader::startNextDownload()
{
if (m_pdfInfoVec.isEmpty())
{
DEBUG_LOG(m_logger) << "No more pending downloads.";
closeDb(m_dbConnection);
emit allDownloadsFinished();
return false;
}
m_currentDownload = m_pdfInfoVec.takeFirst();
emit newState(100 / m_totalDownloads * m_downloadCount, tr("Downloading file \"%1\"").arg(m_currentDownload.name));
DEBUG_LOG(m_logger) << "Downloading file " << m_currentDownload.name;
m_socket->downloadFromHost(m_currentDownload.id, m_currentDownload.fileSize);
return true;
}
bool PdfDownloader::openDbConnection()
{
if (m_dbConnection.isValid())
{
m_exTblGen->close();
closeDb(m_dbConnection);
}
bool bOk;
m_dbConnection = openDb(&bOk);
if (!bOk)
return false;
return m_exTblGen->init(m_dbConnection, QStringLiteral("exm"));
}
QSqlDatabase PdfDownloader::openDb(bool *bOk)
{
if (bOk)
*bOk = true;
// open postgres db, read table structure, read static data
auto s = Settings::settings();
const QString dbUser(QStringLiteral("ets_flm"));
const QString dbPasswd(QStringLiteral("ets11de"));
QSqlDatabase dbConnection = DBConnection::open(m_logger,
dbUser,
dbPasswd,
s->databaseDriver(),
s->databaseHostname(),
s->databaseName());
DEBUG_LOG(m_logger) << "Trying to open database " << s->databaseHostname() << ":" << s->databaseName();
if (!dbConnection.isOpen())
{
ERROR_LOG(m_logger) << "Error opening database " << s->databaseHostname() << ":" << s->databaseName();
if (bOk)
*bOk = false;
}
return dbConnection;
}
void PdfDownloader::closeDb(QSqlDatabase &dbConn)
{
const QString connName = dbConn.connectionName();
DEBUG_LOG(m_logger) << "Closing database: " << connName;
dbConn.close();
dbConn = QSqlDatabase();
}
}
+73
View File
@@ -0,0 +1,73 @@
/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, NLE, 2019-04-30
*/
#pragma once
#include <QObject>
#include <QString>
#include <QVector>
#include <QSqlDatabase>
#include <DBAdministration/exercise_table_generator.h>
#include <FileManagement/flm_db.h>
#include "WebSocketInterface/Messages/client_message.h"
#include "settings.h"
#include "logger.h"
namespace OcBaseDownload
{
class PdfDownloadSocket;
class MainHandler;
class PdfDownloader
: public QObject
{
Q_OBJECT
public:
explicit PdfDownloader(const QVector<WebSocketInterface::Messages::PdfListMessage::PdfInformation> &pdfInfoVec,
MainHandler *mainHandler,
const QString &hostName,
int exerciseId,
QObject *parent);
~PdfDownloader();
bool startDownload();
Q_SIGNALS:
void newState(int progress, const QString &msg);
void allDownloadsFinished();
private Q_SLOTS:
void onSingleDownloadFinished(const QByteArray &data);
private: // other
typedef WebSocketInterface::Messages::PdfListMessage::PdfInformation PdfInfo;
private: // methods
bool hasCompletedFolderStructure();
bool startNextDownload();
bool openDbConnection();
QSqlDatabase openDb(bool *bOk);
void closeDb(QSqlDatabase &dbConn);
private: // attributes
QVector<PdfInfo> m_pdfInfoVec;
PdfInfo m_currentDownload;
PdfDownloadSocket *m_socket;
MainHandler *m_mainHandler;
int m_exerciseId;
QSqlDatabase m_dbConnection;
DBAdministration::ExerciseTableGenerator *m_exTblGen;
int m_downloadCount;
int m_totalDownloads;
NGL::INGLLogger &m_logger;
};
}
+66
View File
@@ -0,0 +1,66 @@
/**
* Settings for OcBaseDownload
* $Id$
* $HeadURL$
* $Author$
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
#include <QDir>
namespace OcBaseDownload
{
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);
}
//-----------------------------------------------------------------------------
int Settings::unitOffset()
{
return s()->settings()->value(QLatin1String("OcSituationParameter/AliveTimeout"), 0x40000000).toInt();
}
//-----------------------------------------------------------------------------
QString Settings::remoteDbHostName()
{
return s()->settings()->value(QLatin1String("OcBaseDownload/remoteDbHostName"), QStringLiteral("EXCDBS01")).toString();
}
//-----------------------------------------------------------------------------
QString Settings::remoteDbName()
{
return s()->settings()->value(QLatin1String("OcBaseDownload/remoteDbName"), QStringLiteral("lts_ets_pro")).toString();
}
//-----------------------------------------------------------------------------
int32_t Settings::webSocketActivityTimeoutMSec()
{
return s()->settings()->value(QLatin1String("OcSituationParameter/WebSocketActivityTimeoutMSec"), 15000).toInt();
}
//-----------------------------------------------------------------------------
} // namespace OcBaseDownload
+29
View File
@@ -0,0 +1,29 @@
/**
* Settings for OcBaseDownload
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QString>
namespace NGL
{
class Settings;
}
namespace OcBaseDownload
{
namespace Settings
{
NGL::Settings *settings();
void setIniFile(const QString &ini);
int unitOffset();
QString remoteDbHostName();
QString remoteDbName();
int webSocketActivityTimeoutMSec();
}
} // namespace OcBaseDownload