/** * Manages central aes data to be sent * $Id: handler_oc_situation_data.h 57655 2022-07-20 11:38:28Z karwat $ * $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Services/OcSituationServer/handler_oc_situation_data.h $ * $Author: karwat $ * Created by Hannes Fritsche, SLTE, 16-08-2022 */ #include "central_aes_data_queue.h" namespace OcSituationServer { CentralAesDataQueue::CentralAesDataQueue(QObject *parent) : QObject(parent) , m_logger(getLogger("CentralAesDataQueue")) { } void CentralAesDataQueue::addRemoveMessage(int32_t aesItemId, AreaEffectSimulation::AesType aesType, bool isPrioritized) { QMutexLocker locker(&m_accessMutex); QByteArray data; clearSpecificMessage(aesItemId, OcSituation::Remove); using namespace DataBuilder; addCentralAesChangeType(data, OcSituation::Remove); addAesItemId(data, aesItemId); addAesType(data, aesType); if (isPrioritized) m_internalPrioritizedQueue.prepend({aesItemId, OcSituation::Remove, data}); else m_internalQueue.prepend({aesItemId, OcSituation::Remove, data}); DEBUG_LOG(m_logger) << "New remove-message added: Id = " << aesItemId << ", aesType = " << aesType << ". " << m_internalQueue.size() << " normal, " << m_internalPrioritizedQueue.size() << " prioritized and " << m_internalQueue.size() + m_internalPrioritizedQueue.size() << " remaining messages in total."; } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::EffectCluster &effectCluster) { // we treat EffectClusters as ExplosionClusters for the ABT addRemoveMessage(effectCluster.id(), AreaEffectSimulation::AesType::inner_enum::AtExplosionCluster); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::NContamination &nContamination) { addRemoveMessage(nContamination.id(), AreaEffectSimulation::AesType::inner_enum::AtNContamination); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::BCContamination &bCContamination) { addRemoveMessage(bCContamination.id(), AreaEffectSimulation::AesType::inner_enum::AtBCContamination); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::ExplosionArea &explosionArea) { addRemoveMessage(explosionArea.id(), AreaEffectSimulation::AesType::inner_enum::AtExplosionArea); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::ExplosionSingle &explosionSingle) { addRemoveMessage(explosionSingle.id(), AreaEffectSimulation::AesType::inner_enum::AtExplosionSingle); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::MineArea &mineArea) { addRemoveMessage(mineArea.id(), AreaEffectSimulation::AesType::inner_enum::AtMineArea); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::FunctionalArea &functionalArea) { addRemoveMessage(functionalArea.id(), AreaEffectSimulation::AesType::inner_enum::AtFunctionalArea); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::BoobyTrap &boobyTrap) { addRemoveMessage(boobyTrap.id(), AreaEffectSimulation::AesType::inner_enum::AtBoobyTrap); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::OffRouteMine &offRouteMine) { addRemoveMessage(offRouteMine.id(), AreaEffectSimulation::AesType::inner_enum::AtOffRouteMine); } void CentralAesDataQueue::addRemoveMessage(const AreaEffectSimulation::ExplosionCluster &explosionCluster) { addRemoveMessage(explosionCluster.id(), AreaEffectSimulation::AesType::inner_enum::AtExplosionCluster, explosionCluster.impactCount() == 1); // we prioritize every single fire } QByteArray CentralAesDataQueue::getSendingData(qint32 size) { QMutexLocker locker(&m_accessMutex); QByteArray result; qint32 messageCounter = 0; while (!m_internalPrioritizedQueue.isEmpty() && ((result.size() + m_internalPrioritizedQueue.head().data.size()) <= size)) { result.append(m_internalPrioritizedQueue.dequeue().data); ++messageCounter; } // if the result is empty and we have messages left, there is no message small enough, to fit size // so we send the next best message if (result.isEmpty() && !m_internalPrioritizedQueue.isEmpty()) { result.append(m_internalPrioritizedQueue.dequeue().data); ++messageCounter; WARNING_LOG(m_logger) << "Could not build data with max size of " << size << " bytes. Delivering data with " << result.size() << " bytes."; } while (!m_internalQueue.isEmpty() && ((result.size() + m_internalQueue.head().data.size()) <= size)) { result.append(m_internalQueue.dequeue().data); ++messageCounter; } // if the result is empty and we have messages left, there is no message small enough, to fit size // so we send the next best message if (result.isEmpty() && !m_internalQueue.isEmpty()) { result.append(m_internalQueue.dequeue().data); ++messageCounter; WARNING_LOG(m_logger) << "Could not build data with max size of " << size << " bytes. Delivering data with " << result.size() << " bytes."; } DEBUG_LOG(m_logger) << "Data with max size = " << size << "requestet. " << result.size() << " bytes delivered."; DEBUG_LOG(m_logger) << messageCounter << " messages are sent. " << m_internalQueue.size() << " normal, " << m_internalPrioritizedQueue.size() << " prioritized and " << m_internalQueue.size() + m_internalPrioritizedQueue.size() << " remaining messages in total."; return result; } bool CentralAesDataQueue::hasMessages() const { return !m_internalQueue.isEmpty() || !m_internalPrioritizedQueue.isEmpty(); } void CentralAesDataQueue::clear() { m_internalQueue.clear(); m_internalPrioritizedQueue.clear(); } void CentralAesDataQueue::clearSpecificMessage(int32_t aesItemId, OcSituation::CentralAesChangeType changeType) { for (qint32 counter = 0; counter < m_internalQueue.size(); ++counter) { if (m_internalQueue.at(counter).aesItemId == aesItemId && m_internalQueue.at(counter).changeType == changeType) { m_internalQueue.removeAt(counter); DEBUG_LOG(m_logger) << "Removed already existing message. aesItemId = " << aesItemId << ", changeType = " << changeType; return; } } for (qint32 counter = 0; counter < m_internalPrioritizedQueue.size(); ++counter) { if (m_internalPrioritizedQueue.at(counter).aesItemId == aesItemId && m_internalPrioritizedQueue.at(counter).changeType == changeType) { m_internalPrioritizedQueue.removeAt(counter); DEBUG_LOG(m_logger) << "Removed already existing message. aesItemId = " << aesItemId << ", changeType = " << changeType; return; } } } } // namespace OcSituationServer