From 088bc35301dc87ebb7b4d30e789deda7264b973e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 14 Oct 2020 12:42:30 +0200 Subject: [PATCH] update handler continued --- datapoollocal/LocalDataPoolManager.cpp | 154 +++++++++++++++++++++++++ datapoollocal/LocalDataPoolManager.h | 34 ++++-- datapoollocal/LocalPoolDataSetBase.cpp | 8 ++ datapoollocal/LocalPoolDataSetBase.h | 16 ++- datapoollocal/LocalPoolObjectBase.h | 10 +- datapoollocal/MarkChangedIF.h | 17 +++ 6 files changed, 224 insertions(+), 15 deletions(-) create mode 100644 datapoollocal/MarkChangedIF.h diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp index a33f19e5..a2a087e8 100644 --- a/datapoollocal/LocalDataPoolManager.cpp +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -115,9 +115,12 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { status = result; } } + handleChangeResetLogic(receiver.dataType, receiver.dataId, + dataSet); break; } case(ReportingType::UPDATE_NOTIFICATION): { + MarkChangedIF* toReset = nullptr; if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( receiver.dataId.localPoolId); @@ -125,8 +128,10 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { continue; } if(poolObj->hasChanged()) { + // prepare and send update notification. } + toReset = poolObj; } else { LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( @@ -135,12 +140,16 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { continue; } if(dataSet->hasChanged()) { + // prepare and send update notification } + toReset = dataSet; } + handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset); break; } case(ReportingType::UPDATE_SNAPSHOT): { + MarkChangedIF* toReset = nullptr; // check whether data has changed and send messages in case it has. if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( @@ -151,6 +160,7 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { if(poolObj->hasChanged()) { // prepare and send update snapshot. } + toReset = poolObj; } else { LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( @@ -161,7 +171,9 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { if(dataSet->hasChanged()) { // prepare and send update snapshot. } + toReset = dataSet; } + handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset); break; } default: @@ -169,9 +181,53 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() { return HasReturnvaluesIF::RETURN_FAILED; } } + resetHkUpdateResetHelper(); return status; } +void LocalDataPoolManager::handleChangeResetLogic( + DataType type, DataId dataId, MarkChangedIF* toReset) { + if(hkUpdateResetList == nullptr) { + // config error! + return; + } + + for(auto& changeInfo: *hkUpdateResetList) { + if(changeInfo.dataType != type) { + continue; + } + if((changeInfo.dataType == DataType::DATA_SET) and + (changeInfo.dataId.sid != dataId.sid)) { + continue; + } + if((changeInfo.dataType == DataType::LOCAL_POOL_VARIABLE) and + (changeInfo.dataId.localPoolId != dataId.localPoolId)) { + continue; + } + + if(changeInfo.updateCounter <= 1) { + toReset->setChanged(false); + } + if(changeInfo.currentUpdateCounter == 0) { + toReset->setChanged(false); + } + else { + changeInfo.currentUpdateCounter--; + } + return; + } +} + +void LocalDataPoolManager::resetHkUpdateResetHelper() { + if(hkUpdateResetList == nullptr) { + return; + } + + for(auto& changeInfo: *hkUpdateResetList) { + changeInfo.currentUpdateCounter = changeInfo.updateCounter; + } +} + ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool enableReporting, float collectionInterval, bool isDiagnostics, object_id_t packetDestination) { @@ -186,6 +242,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, struct HkReceiver hkReceiver; hkReceiver.dataId.sid = sid; hkReceiver.reportingType = ReportingType::PERIODIC; + hkReceiver.dataType = DataType::DATA_SET; hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); @@ -200,6 +257,103 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t LocalDataPoolManager::subscribeForUpdatePackets(sid_t sid, + bool isDiagnostics, bool reportingEnabled, + object_id_t packetDestination) { + AcceptsHkPacketsIF* hkReceiverObject = + objectManager->get(packetDestination); + if(hkReceiverObject == nullptr) { + sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:" + << " Invalid receiver!"<< std::endl; + return HasReturnvaluesIF::RETURN_OK; + } + + struct HkReceiver hkReceiver; + hkReceiver.dataId.sid = sid; + hkReceiver.reportingType = ReportingType::UPDATE_HK; + hkReceiver.dataType = DataType::DATA_SET; + hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); + + LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); + if(dataSet != nullptr) { + dataSet->setReportingEnabled(true); + dataSet->setDiagnostic(isDiagnostics); + } + + hkReceiversMap.push_back(hkReceiver); + + handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::subscribeForUpdateMessages(sid_t sid, + object_id_t destinationObject, MessageQueueId_t targetQueueId) { + struct HkReceiver hkReceiver; + hkReceiver.dataType = DataType::DATA_SET; + hkReceiver.dataId.sid = sid; + hkReceiver.destinationQueue = targetQueueId; + hkReceiver.objectId = destinationObject; + hkReceiver.reportingType = ReportingType::UPDATE_NOTIFICATION; + + hkReceiversMap.push_back(hkReceiver); + + handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::subscribeForUpdateMessages( + lp_id_t localPoolId, object_id_t destinationObject, + MessageQueueId_t targetQueueId) { + struct HkReceiver hkReceiver; + hkReceiver.dataType = DataType::LOCAL_POOL_VARIABLE; + hkReceiver.dataId.localPoolId = localPoolId; + hkReceiver.destinationQueue = targetQueueId; + hkReceiver.objectId = destinationObject; + hkReceiver.reportingType = ReportingType::UPDATE_NOTIFICATION; + + hkReceiversMap.push_back(hkReceiver); + + handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId); + return HasReturnvaluesIF::RETURN_OK; +} + +void LocalDataPoolManager::handleHkUpdateResetListInsertion(DataType dataType, + DataId dataId) { + if(hkUpdateResetList == nullptr) { + hkUpdateResetList = new std::vector(); + } + + for(auto& updateResetStruct: *hkUpdateResetList) { + if(dataType == DataType::DATA_SET) { + if(updateResetStruct.dataId.sid == dataId.sid) { + updateResetStruct.updateCounter++; + updateResetStruct.currentUpdateCounter++; + return; + } + } + else { + if(updateResetStruct.dataId.localPoolId == dataId.localPoolId) { + updateResetStruct.updateCounter++; + updateResetStruct.currentUpdateCounter++; + return; + } + } + + } + HkUpdateResetHelper hkUpdateResetHelper; + hkUpdateResetHelper.currentUpdateCounter = 1; + hkUpdateResetHelper.updateCounter = 1; + hkUpdateResetHelper.dataType = dataType; + if(dataType == DataType::DATA_SET) { + hkUpdateResetHelper.dataId.sid = dataId.sid; + } + else { + hkUpdateResetHelper.dataId.localPoolId = dataId.localPoolId; + } + hkUpdateResetList->push_back(hkUpdateResetHelper); +} + ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage( CommandMessage* message) { Command_t command = message->getCommand(); diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index 84a0d31e..cc9364e7 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -118,7 +118,8 @@ public: * @param packetDestination * @return */ - ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool isDiagnostics, + ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled, + bool isDiagnostics, object_id_t packetDestination = defaultHkDestination); /** @@ -129,7 +130,7 @@ public: * @return */ ReturnValue_t subscribeForUpdateMessages(sid_t sid, - MessageQueueId_t targetQueueId); + object_id_t destinationObject, MessageQueueId_t targetQueueId); /** * @brief Subscribe for an notification message which will be sent if a @@ -139,7 +140,7 @@ public: * @return */ ReturnValue_t subscribeForUpdateMessages(lp_id_t localPoolId, - MessageQueueId_t targetQueueId); + object_id_t destinationObject, MessageQueueId_t targetQueueId); /** * Non-Diagnostics packets usually have a lower minimum sampling frequency @@ -233,17 +234,18 @@ private: static object_id_t defaultHkDestination; MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE; + union DataId { + DataId(): sid() {}; + sid_t sid; + lp_id_t localPoolId; + }; + /** The data pool manager will keep an internal map of HK receivers. */ struct HkReceiver { /** Object ID of receiver */ object_id_t objectId = objects::NO_OBJECT; DataType dataType = DataType::DATA_SET; - union DataId { - DataId(): sid() {}; - sid_t sid; - lp_id_t localPoolId; - }; DataId dataId; ReportingType reportingType = ReportingType::PERIODIC; @@ -255,6 +257,17 @@ private: HkReceivers hkReceiversMap; + struct HkUpdateResetHelper { + DataType dataType = DataType::DATA_SET; + DataId dataId; + uint8_t updateCounter; + uint8_t currentUpdateCounter; + }; + + using HkUpdateResetList = std::vector; + // Will only be created when needed. + HkUpdateResetList* hkUpdateResetList = nullptr; + /** This is the map holding the actual data. Should only be initialized * once ! */ bool mapInitialized = false; @@ -312,6 +325,11 @@ private: ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval, bool isDiagnostics); ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics); + + void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId); + void handleChangeResetLogic(DataType type, + DataId dataId, MarkChangedIF* toReset); + void resetHkUpdateResetHelper(); }; diff --git a/datapoollocal/LocalPoolDataSetBase.cpp b/datapoollocal/LocalPoolDataSetBase.cpp index e9adaa5a..5bb71cb6 100644 --- a/datapoollocal/LocalPoolDataSetBase.cpp +++ b/datapoollocal/LocalPoolDataSetBase.cpp @@ -20,6 +20,8 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, this->sid.objectId = hkOwner->getObjectId(); this->sid.ownerSetId = setId; + mutex = MutexFactory::instance()->createMutex(); + // Data creators get a periodic helper for periodic HK data generation. if(not noPeriodicHandling) { periodicHelper = new PeriodicHousekeepingHelper(this); @@ -40,6 +42,8 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, } hkManager = hkOwner->getHkManagerHandle(); this->sid = sid; + + mutex = MutexFactory::instance()->createMutex(); } LocalPoolDataSetBase::~LocalPoolDataSetBase() { @@ -223,10 +227,12 @@ void LocalPoolDataSetBase::initializePeriodicHelper( } void LocalPoolDataSetBase::setChanged(bool changed) { + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); this->changed = changed; } bool LocalPoolDataSetBase::hasChanged() const { + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); return changed; } @@ -246,10 +252,12 @@ bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, } bool LocalPoolDataSetBase::isValid() const { + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); return this->valid; } void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) { + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); if(setEntriesRecursively) { for(size_t idx = 0; idx < this->getFillCount(); idx++) { registeredVariables[idx] -> setValid(valid); diff --git a/datapoollocal/LocalPoolDataSetBase.h b/datapoollocal/LocalPoolDataSetBase.h index 2774f507..aa155bf1 100644 --- a/datapoollocal/LocalPoolDataSetBase.h +++ b/datapoollocal/LocalPoolDataSetBase.h @@ -2,6 +2,8 @@ #define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ #include "HasLocalDataPoolIF.h" +#include "MarkChangedIF.h" + #include "../datapool/DataSetIF.h" #include "../datapool/PoolDataSetBase.h" #include "../serialize/SerializeIF.h" @@ -39,7 +41,8 @@ class PeriodicHousekeepingHelper; * * @ingroup data_pool */ -class LocalPoolDataSetBase: public PoolDataSetBase { +class LocalPoolDataSetBase: public PoolDataSetBase, + public MarkChangedIF { friend class LocalDataPoolManager; friend class PeriodicHousekeepingHelper; public: @@ -109,18 +112,23 @@ public: uint8_t getLocalPoolIdsSerializedSize(bool serializeFillCount = true) const; /** - * Set the dataset valid or invalid + * Set the dataset valid or invalid. These calls are mutex protected. * @param setEntriesRecursively * If this is true, all contained datasets will also be set recursively. */ void setValidity(bool valid, bool setEntriesRecursively); bool isValid() const override; - void setChanged(bool changed); - bool hasChanged() const; + /** + * These calls are mutex protected. + * @param changed + */ + void setChanged(bool changed) override; + bool hasChanged() const override; protected: sid_t sid; + MutexIF* mutex = nullptr; bool diagnostic = false; void setDiagnostic(bool diagnostics); diff --git a/datapoollocal/LocalPoolObjectBase.h b/datapoollocal/LocalPoolObjectBase.h index 8445b764..4d25b88a 100644 --- a/datapoollocal/LocalPoolObjectBase.h +++ b/datapoollocal/LocalPoolObjectBase.h @@ -1,10 +1,14 @@ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_ +#include "MarkChangedIF.h" #include "../datapoollocal/LocalDataPoolManager.h" #include "../datapool/PoolVariableIF.h" -class LocalPoolObjectBase: public PoolVariableIF, HasReturnvaluesIF { + +class LocalPoolObjectBase: public PoolVariableIF, + public HasReturnvaluesIF, + public MarkChangedIF { public: LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet, @@ -19,8 +23,8 @@ public: bool isValid() const override; void setValid(bool valid) override; - void setChanged(bool changed); - bool hasChanged() const; + void setChanged(bool changed) override; + bool hasChanged() const override; lp_id_t getDataPoolId() const override; void setDataPoolId(lp_id_t poolId); diff --git a/datapoollocal/MarkChangedIF.h b/datapoollocal/MarkChangedIF.h new file mode 100644 index 00000000..e575d1d3 --- /dev/null +++ b/datapoollocal/MarkChangedIF.h @@ -0,0 +1,17 @@ +#ifndef FSFW_DATAPOOLLOCAL_MARKCHANGEDIF_H_ +#define FSFW_DATAPOOLLOCAL_MARKCHANGEDIF_H_ + +/** + * Common interface for local pool entities which can be marked as changed. + */ +class MarkChangedIF { +public: + virtual~ MarkChangedIF() {}; + + virtual bool hasChanged() const = 0; + virtual void setChanged(bool changed) = 0; +}; + + + +#endif /* FSFW_DATAPOOLLOCAL_MARKCHANGEDIF_H_ */