/** * Handle the mapping real aircraft <-> participant in exercise * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2018-08-02 */ #include "handler_nasat_aircraft_participant.h" #include "handler_nasat_aircraft.h" #include "initialization.h" #include "dds_handler.h" #include "handler_participant.h" #include #include namespace GuezNasat { Database::NasatAircraftParticipant toDb(const NasatAircraftParticipant &dds) { Database::NasatAircraftParticipant ret; ret.id = dds.id(); ret.nasatAircraftId = dds.nasatAircraftId(); ret.exerciseId = dds.exerciseId(); ret.participantId = dds.participantId(); return ret; } NasatAircraftParticipant fromDb(const Database::NasatAircraftParticipant &db) { NasatAircraftParticipant ret; ret.id(db.id); ret.nasatAircraftId(db.nasatAircraftId); ret.exerciseId(db.exerciseId); ret.participantId(db.participantId); return ret; } HandlerNasatAircraftParticipant::HandlerNasatAircraftParticipant(Initialization *mainHandler) : QObject() , Interface::Fts::ModifyNasatAircraftParticipantRequestHandler(mainHandler->dds()->fts()) , m_mainHandler(mainHandler) , m_dts(mainHandler->dds()->dts()) , m_fts(mainHandler->dds()->fts()) , m_db(mainHandler->db()) , m_logger(getLogger("HandlerNasatAircraftParticipant")) { DEBUG_LOG(m_logger) << LOGFUNCTION << " START"; DEBUG_LOG(m_logger) << LOGFUNCTION << " END"; } HandlerNasatAircraftParticipant::~HandlerNasatAircraftParticipant() { DEBUG_LOG(m_logger) << LOGFUNCTION << " START"; for (const auto &data : qAsConst(m_nasatAircraftParticipants)) m_dts->removeNasatAircraftByKey(data.id()); DEBUG_LOG(m_logger) << LOGFUNCTION << " END"; } bool HandlerNasatAircraftParticipant::init() { DEBUG_LOG(m_logger) << LOGFUNCTION << " START"; auto cb = [this](const Database::NasatAircraftParticipant & data) { const auto dds(fromDb(data)); DEBUG_LOG(m_logger) << "m_nasatAircraftParticipants.insert(" << dds.id() << ")"; m_nasatAircraftParticipants.insert(dds.id(), dds); m_dts->publish(dds); m_mainHandler->handlerParticipant()->onNasatAircraftParticipantCreated(dds); }; m_db->select(cb); // Most likely, the exercises are empty on normal startup of serviceManagement // since ExerciseManagement is started later... auto exmDtc = m_mainHandler->dds()->exmDtc(); connect(exmDtc.get(), &ExerciseManagement::Interface::Dtc::exerciseChanged, this, &HandlerNasatAircraftParticipant::onExerciseChanged, Qt::UniqueConnection); exmDtc->exercises([this](const ExerciseManagement::Exercise &exercise) { onExerciseChanged(exercise, DataModification::eAdded); }); dumpNasatAircraftParticipants(); dumpExercises(); // exercises are started one by one. So try 30 QTimer::singleShot(30000, this, [this]() { // 30000 -> 30sec dumpNasatAircraftParticipants(); dumpExercises(); }); DEBUG_LOG(m_logger) << "HandlerNasatAircraftParticipant init done"; DEBUG_LOG(m_logger) << LOGFUNCTION << " START"; return true; } void HandlerNasatAircraftParticipant::dumpNasatAircraftParticipants() { DEBUG_LOG(m_logger) << LOGFUNCTION << " START, size=" << m_nasatAircraftParticipants.size(); DEBUG_LOG(m_logger) << LOGFUNCTION << " --------------------------------------"; auto it = m_nasatAircraftParticipants.begin(); while (it != m_nasatAircraftParticipants.end()) { const auto &id = it.key(); const auto &nap = it.value(); DEBUG_LOG(m_logger) << LOGFUNCTION << " id=" << id << " - nap=" << nap; ++it; } DEBUG_LOG(m_logger) << LOGFUNCTION << " --------------------------------------"; DEBUG_LOG(m_logger) << LOGFUNCTION << " END, size=" << m_nasatAircraftParticipants.size(); } void HandlerNasatAircraftParticipant::dumpExercises() { DEBUG_LOG(m_logger) << LOGFUNCTION << " START, size=" << m_exercises.size(); DEBUG_LOG(m_logger) << LOGFUNCTION << " --------------------------------------"; auto it = m_exercises.begin(); while (it != m_exercises.end()) { const auto &id = it.key(); const auto &nasatAircraftParticipant = it.value(); DEBUG_LOG(m_logger) << LOGFUNCTION << " id=" << id << " - nasatAircraftParticipant=" << nasatAircraftParticipant; ++it; } DEBUG_LOG(m_logger) << LOGFUNCTION << " --------------------------------------"; DEBUG_LOG(m_logger) << LOGFUNCTION << " END, size=" << m_exercises.size(); } void HandlerNasatAircraftParticipant::aircraftRemoved(int nasatAircraftId) { auto it = m_nasatAircraftParticipants.begin(); while (it != m_nasatAircraftParticipants.end()) { const auto &val = it.value(); if (val.nasatAircraftId() == nasatAircraftId) { removeNasatAircraftParticipant(val); it = m_nasatAircraftParticipants.erase(it); } else ++it; } } void HandlerNasatAircraftParticipant::participantRemoved(int exerciseId, int participantId) { DEBUG_LOG(m_logger) << "participantRemoved: " << exerciseId << ", " << participantId; auto it = m_nasatAircraftParticipants.begin(); while (it != m_nasatAircraftParticipants.end()) { const auto &val = it.value(); if (val.participantId() == participantId && val.exerciseId() == exerciseId) { removeNasatAircraftParticipant(val); it = m_nasatAircraftParticipants.erase(it); } else ++it; } } bool isExerciseStateValid(ExerciseManagement::ExerciseState_def::type state) { switch (state) { case ExerciseManagement::ExerciseState_def::Created: case ExerciseManagement::ExerciseState_def::Paused: case ExerciseManagement::ExerciseState_def::Started: case ExerciseManagement::ExerciseState_def::Stopped: return true; case ExerciseManagement::ExerciseState_def::Unknown: case ExerciseManagement::ExerciseState_def::Terminated: return false; } return false; } void HandlerNasatAircraftParticipant::onExerciseChanged(const ExerciseManagement::Exercise &exercise, DataModification modType) { INFO_LOG(m_logger) << LOGFUNCTION << " START" << " , exercise" << exercise << " , modType" << modType; const int exId = exercise.id(); switch (modType) { case DataModification::eAdded: { m_exercises[exId] = exercise; const bool valid = isExerciseStateValid(exercise.state().underlying()); if (!valid) { INFO_LOG(m_logger) << LOGFUNCTION << " STATE of exId=" << exId << " , state=" << exercise.state(); int cnt = removeNapsOfExercise(exId); INFO_LOG(m_logger) << LOGFUNCTION << " STATE of exId=" << exId << " not valid : counter of removed naps=" << cnt; } } break; case DataModification::eModified: { const ExerciseManagement::Exercise &exerciseRef = m_exercises[exId]; if (exerciseRef.state() != exercise.state()) { const bool valid = isExerciseStateValid(exercise.state().underlying()); if (!valid) { INFO_LOG(m_logger) << LOGFUNCTION << " STATE change of exId=" << exId << " , old state=" << exerciseRef.state() << " , new state=" << exercise.state(); int cnt = removeNapsOfExercise(exId); INFO_LOG(m_logger) << LOGFUNCTION << " STATE change of exId=" << exId << " : counter of removed naps=" << cnt; } } m_exercises[exId] = exercise; } break; case DataModification::eRemoved: { int cnt = removeNapsOfExercise(exId); INFO_LOG(m_logger) << LOGFUNCTION << " STATE change of Exercise, counter of removed naps=" << cnt; m_exercises.remove(exId); } break; } INFO_LOG(m_logger) << LOGFUNCTION << " END" << " , exercise" << exercise << " , modType" << modType; } void HandlerNasatAircraftParticipant::removeNasatAircraftParticipant(const NasatAircraftParticipant &val) { m_mainHandler->handlerParticipant()->onNasatAircraftParticipantRemoved(val); // empty -> remove m_db->removeNasatAircraftParticipant(val.id()); m_dts->removeNasatAircraftParticipantByKey(val.id()); } void HandlerNasatAircraftParticipant::onModifyNasatAircraftParticipantRequest(const rti::core::SampleIdentity &cookie, const NasatAircraftParticipant &request) { DEBUG_LOG(m_logger) << "onModifyNasatAircraftParticipantRequest: " << request; auto ret = request.id() <= 0 ? createNasatAircraftParticipantRequest(request) : modifyNasatAircraftParticipantRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); m_fts->modifyNasatAircraftParticipantReply(cookie, ret); } Core::FunctionReplyObject HandlerNasatAircraftParticipant::createNasatAircraftParticipantRequest(const NasatAircraftParticipant &request) { // create Database::NasatAircraftParticipant napDb(toDb(request)); napDb.id = 0; if (!m_db->insert(napDb)) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Can not create Aircraft Participant connection - error inserting values in database")); // Success, Send Topic to DDS const auto dds(fromDb(napDb)); m_dts->publish(dds); m_nasatAircraftParticipants.insert(dds.id(), dds); m_mainHandler->handlerParticipant()->onNasatAircraftParticipantCreated(request); return Core::FunctionReplyObject(request.id()); } Core::FunctionReplyObject HandlerNasatAircraftParticipant::modifyNasatAircraftParticipantRequest(const NasatAircraftParticipant &request) { auto it = m_nasatAircraftParticipants.find(request.id()); if (it == m_nasatAircraftParticipants.end()) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Can not modify Aircraft Participant connection - id %1 not found")).arg(request.id()); if (request == *it) return Core::FunctionReplyObject(request.id()); if ((request.exerciseId() == 0 && request.participantId() == 0) || request.nasatAircraftId() == 0) { removeNasatAircraftParticipant(it.value()); m_nasatAircraftParticipants.erase(it); return Core::FunctionReplyObject(request.id()); } // modify Database::NasatAircraftParticipant napDb(toDb(request)); if (!m_db->update(napDb)) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Can not modify Aircraft Participant connection - error updating values in database")); // remove old subscriber m_mainHandler->handlerParticipant()->onNasatAircraftParticipantRemoved(*it); const auto dds(fromDb(napDb)); m_dts->publish(dds); m_nasatAircraftParticipants.insert(dds.id(), dds); // Success, Send Topic to DDS m_dts->publish(fromDb(napDb)); // add new subscriber m_mainHandler->handlerParticipant()->onNasatAircraftParticipantCreated(request); return Core::FunctionReplyObject(request.id()); } int HandlerNasatAircraftParticipant::removeNapsOfExercise(int exerciseId) { DEBUG_LOG(m_logger) << LOGFUNCTION << " START, exerciseId=" << exerciseId << ", m_nasatAircraftParticipants.size()" << m_nasatAircraftParticipants.size(); int count = 0; QHash napsCopy = m_nasatAircraftParticipants; for (const NasatAircraftParticipant &nap : qAsConst(napsCopy)) { if (nap.exerciseId() == exerciseId) { DEBUG_LOG(m_logger) << LOGFUNCTION << " nap has to be removed: nap=" << nap; NasatAircraftParticipant napToTriggerRemoving; napToTriggerRemoving.id(nap.id()); // to trigger removing napToTriggerRemoving.exerciseId(0); // to trigger removing napToTriggerRemoving.participantId(0); // to trigger removing napToTriggerRemoving.nasatAircraftId(0); // to trigger removing modifyNasatAircraftParticipantRequest(napToTriggerRemoving); ++count; } } DEBUG_LOG(m_logger) << LOGFUNCTION << " END, exerciseId=" << exerciseId << ", m_nasatAircraftParticipants.size()" << m_nasatAircraftParticipants.size() << ", counter=" << count; return count; } } // namespace GuezNasat