From 842213ab5b375bcf8be8b8159f8ca3202d9d14a5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 13:04:28 +0200 Subject: [PATCH 1/8] split up global and generic datapool files --- datapool/ControllerSet.h | 4 +- datapool/DataPool.cpp | 131 -------- datapool/DataPool.h | 135 -------- datapool/DataSet.cpp | 150 --------- datapool/DataSet.h | 159 ---------- datapool/DataSetBase.cpp | 168 ++++++++++ datapool/DataSetBase.h | 149 +++++++++ datapool/DataSetIF.h | 65 ++-- datapool/HkSwitchHelper.cpp | 11 +- datapool/PoolRawAccess.cpp | 187 ----------- datapool/PoolRawAccess.h | 152 --------- datapool/PoolRawAccessHelper.cpp | 188 +++++++++++ datapool/PoolRawAccessHelper.h | 111 +++++++ datapool/PoolVarList.h | 6 +- datapool/PoolVariable.h | 295 ------------------ datapool/PoolVariableIF.h | 112 ++++--- datapool/PoolVector.h | 233 -------------- {datapool => datapoolglob}/DataPoolAdmin.cpp | 28 +- {datapool => datapoolglob}/DataPoolAdmin.h | 11 +- .../DataPoolParameterWrapper.cpp | 14 +- .../DataPoolParameterWrapper.h | 0 datapoolglob/GlobalDataPool.cpp | 132 ++++++++ datapoolglob/GlobalDataPool.h | 149 +++++++++ datapoolglob/GlobalDataSet.cpp | 44 +++ datapoolglob/GlobalDataSet.h | 96 ++++++ datapoolglob/GlobalPoolVariable.h | 213 +++++++++++++ datapoolglob/GlobalPoolVariable.tpp | 117 +++++++ datapoolglob/GlobalPoolVector.h | 185 +++++++++++ datapoolglob/GlobalPoolVector.tpp | 117 +++++++ {datapool => datapoolglob}/PIDReader.h | 33 +- {datapool => datapoolglob}/PIDReaderList.h | 8 +- datapoolglob/PoolRawAccess.cpp | 239 ++++++++++++++ datapoolglob/PoolRawAccess.h | 220 +++++++++++++ 33 files changed, 2307 insertions(+), 1555 deletions(-) delete mode 100644 datapool/DataPool.cpp delete mode 100644 datapool/DataPool.h delete mode 100644 datapool/DataSet.cpp delete mode 100644 datapool/DataSet.h create mode 100644 datapool/DataSetBase.cpp create mode 100644 datapool/DataSetBase.h delete mode 100644 datapool/PoolRawAccess.cpp delete mode 100644 datapool/PoolRawAccess.h create mode 100644 datapool/PoolRawAccessHelper.cpp create mode 100644 datapool/PoolRawAccessHelper.h delete mode 100644 datapool/PoolVariable.h delete mode 100644 datapool/PoolVector.h rename {datapool => datapoolglob}/DataPoolAdmin.cpp (92%) rename {datapool => datapoolglob}/DataPoolAdmin.h (96%) rename {datapool => datapoolglob}/DataPoolParameterWrapper.cpp (95%) rename {datapool => datapoolglob}/DataPoolParameterWrapper.h (100%) create mode 100644 datapoolglob/GlobalDataPool.cpp create mode 100644 datapoolglob/GlobalDataPool.h create mode 100644 datapoolglob/GlobalDataSet.cpp create mode 100644 datapoolglob/GlobalDataSet.h create mode 100644 datapoolglob/GlobalPoolVariable.h create mode 100644 datapoolglob/GlobalPoolVariable.tpp create mode 100644 datapoolglob/GlobalPoolVector.h create mode 100644 datapoolglob/GlobalPoolVector.tpp rename {datapool => datapoolglob}/PIDReader.h (79%) rename {datapool => datapoolglob}/PIDReaderList.h (73%) create mode 100644 datapoolglob/PoolRawAccess.cpp create mode 100644 datapoolglob/PoolRawAccess.h diff --git a/datapool/ControllerSet.h b/datapool/ControllerSet.h index de06bf918..7625c3d1b 100644 --- a/datapool/ControllerSet.h +++ b/datapool/ControllerSet.h @@ -1,9 +1,9 @@ #ifndef CONTROLLERSET_H_ #define CONTROLLERSET_H_ -#include +#include -class ControllerSet :public DataSet { +class ControllerSet :public GlobDataSet { public: ControllerSet(); virtual ~ControllerSet(); diff --git a/datapool/DataPool.cpp b/datapool/DataPool.cpp deleted file mode 100644 index f44da64ed..000000000 --- a/datapool/DataPool.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include - -DataPool::DataPool( void ( *initFunction )( std::map* pool_map ) ) { - mutex = MutexFactory::instance()->createMutex(); - if (initFunction != NULL ) { - initFunction( &this->data_pool ); - } -} - -DataPool::~DataPool() { - MutexFactory::instance()->deleteMutex(mutex); - for ( std::map::iterator it = this->data_pool.begin(); it != this->data_pool.end(); ++it ) { - delete it->second; - } -} - -//The function checks PID, type and array length before returning a copy of the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr. -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t sizeOrPosition ) { - std::map::iterator it = this->data_pool.find( data_pool_id ); - if ( it != this->data_pool.end() ) { - PoolEntry* entry = dynamic_cast< PoolEntry* >( it->second ); - if (entry != NULL ) { - if ( sizeOrPosition <= entry->length ) { - return entry; - } - } - } - return NULL; -} - -PoolEntryIF* DataPool::getRawData( uint32_t data_pool_id ) { - std::map::iterator it = this->data_pool.find( data_pool_id ); - if ( it != this->data_pool.end() ) { - return it->second; - } else { - return NULL; - } -} - -//uint8_t DataPool::getRawData( uint32_t data_pool_id, uint8_t* address, uint16_t* size, uint32_t maxSize ) { -// std::map::iterator it = this->data_pool.find( data_pool_id ); -// if ( it != this->data_pool.end() ) { -// if ( it->second->getByteSize() <= maxSize ) { -// *size = it->second->getByteSize(); -// memcpy( address, it->second->getRawData(), *size ); -// return DP_SUCCESSFUL; -// } -// } -// *size = 0; -// return DP_FAILURE; -//} - -ReturnValue_t DataPool::freeDataPoolLock() { - ReturnValue_t status = mutex->unlockMutex(); - if ( status != RETURN_OK ) { - sif::error << "DataPool::DataPool: unlock of mutex failed with error code: " << status << std::endl; - } - return status; -} - -ReturnValue_t DataPool::lockDataPool() { - ReturnValue_t status = mutex->lockMutex(MutexIF::NO_TIMEOUT); - if ( status != RETURN_OK ) { - sif::error << "DataPool::DataPool: lock of mutex failed with error code: " << status << std::endl; - } - return status; -} - -void DataPool::print() { - sif::debug << "DataPool contains: " << std::endl; - std::map::iterator dataPoolIt; - dataPoolIt = this->data_pool.begin(); - while( dataPoolIt != this->data_pool.end() ) { - sif::debug << std::hex << dataPoolIt->first << std::dec << " |"; - dataPoolIt->second->print(); - dataPoolIt++; - } -} - -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData(uint32_t data_pool_id, - uint8_t size); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData( uint32_t data_pool_id, uint8_t size ); -template PoolEntry* DataPool::getData(uint32_t data_pool_id, - uint8_t size); - - -uint32_t DataPool::PIDToDataPoolId(uint32_t parameter_id) { - return (parameter_id >> 8) & 0x00FFFFFF; -} - -uint8_t DataPool::PIDToArrayIndex(uint32_t parameter_id) { - return (parameter_id & 0x000000FF); -} - -uint32_t DataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) { - return (poolId << 8) + index; -} - - -//SHOULDDO: Do we need a mutex lock here... I don't think so, as we only check static const values of elements in a list that do not change. -//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM -ReturnValue_t DataPool::getType(uint32_t parameter_id, Type* type) { - std::map::iterator it = this->data_pool.find( PIDToDataPoolId(parameter_id)); - if ( it != this->data_pool.end() ) { - *type = it->second->getType(); - return RETURN_OK; - } else { - *type = Type::UNKNOWN_TYPE; - return RETURN_FAILED; - } -} - -bool DataPool::exists(uint32_t parameterId) { - uint32_t poolId = PIDToDataPoolId(parameterId); - uint32_t index = PIDToArrayIndex(parameterId); - std::map::iterator it = this->data_pool.find( poolId ); - if (it != data_pool.end()) { - if (it->second->getSize() >= index) { - return true; - } - } - return false; -} diff --git a/datapool/DataPool.h b/datapool/DataPool.h deleted file mode 100644 index 6e38dc1b9..000000000 --- a/datapool/DataPool.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * \file DataPool.h - * - * \date 10/17/2012 - * \author Bastian Baetz - * - * \brief This file contains the definition of the DataPool class and (temporarily) - * the "extern" definition of the global dataPool instance. - */ - -#ifndef DATAPOOL_H_ -#define DATAPOOL_H_ - -#include -#include -#include -#include - -/** - * \defgroup data_pool Data Pool - * This is the group, where all classes associated with Data Pool Handling belong to. - * This includes classes to access Data Pool variables. - */ - -#define DP_SUCCESSFUL 0 -#define DP_FAILURE 1 - -/** - * \brief This class represents the OBSW global data-pool. - * - * \details All variables are registered and space is allocated in an initialization - * function, which is passed do the constructor. - * Space for the variables is allocated on the heap (with a new call). - * The data is found by a data pool id, which uniquely represents a variable. - * Data pool variables should be used with a blackboard logic in mind, - * which means read data is valid (if flagged so), but not necessarily up-to-date. - * Variables are either single values or arrays. - * \ingroup data_pool - */ -class DataPool : public HasReturnvaluesIF { -private: - /** - * \brief This is the actual data pool itself. - * \details It is represented by a map - * with the data pool id as index and a pointer to a single PoolEntry as value. - */ - std::map data_pool; -public: - /** - * \brief The mutex is created in the constructor and makes access mutual exclusive. - * \details Locking and unlocking the pool is only done by the DataSet class. - */ - MutexIF* mutex; - /** - * \brief In the classes constructor, the passed initialization function is called. - * \details To enable filling the pool, - * a pointer to the map is passed, allowing direct access to the pool's content. - * On runtime, adding or removing variables is forbidden. - */ - DataPool( void ( *initFunction )( std::map* pool_map ) ); - /** - * \brief The destructor iterates through the data_pool map and calls all Entries destructors to clean up the heap. - */ - ~DataPool(); - /** - * \brief This is the default call to access the pool. - * \details A pointer to the PoolEntry object is returned. - * The call checks data pool id, type and array size. Returns NULL in case of failure. - * \param data_pool_id The data pool id to search. - * \param sizeOrPosition The array size (not byte size!) of the pool entry, or the position the user wants to read. - * If smaller than the entry size, everything's ok. - */ - template PoolEntry* getData( uint32_t data_pool_id, uint8_t sizeOrPosition ); - /** - * \brief An alternative call to get a data pool entry in case the type is not implicitly known - * (i.e. in Housekeeping Telemetry). - * \details It returns a basic interface and does NOT perform - * a size check. The caller has to assure he does not copy too much data. - * Returns NULL in case the entry is not found. - * \param data_pool_id The data pool id to search. - */ - PoolEntryIF* getRawData( uint32_t data_pool_id ); - /** - * \brief This is a small helper function to facilitate locking the global data pool. - * \details It fetches the pool's mutex id and tries to acquire the mutex. - */ - ReturnValue_t lockDataPool(); - /** - * \brief This is a small helper function to facilitate unlocking the global data pool. - * \details It fetches the pool's mutex id and tries to free the mutex. - */ - ReturnValue_t freeDataPoolLock(); - /** - * \brief The print call is a simple debug method. - * \details It prints the current content of the data pool. - * It iterates through the data_pool map and calls each entry's print() method. - */ - void print(); - /** - * Extracts the data pool id from a SCOS 2000 PID. - * @param parameter_id The passed Parameter ID. - * @return The data pool id as used within the OBSW. - */ - static uint32_t PIDToDataPoolId( uint32_t parameter_id ); - /** - * Extracts an array index out of a SCOS 2000 PID. - * @param parameter_id The passed Parameter ID. - * @return The index of the corresponding data pool entry. - */ - static uint8_t PIDToArrayIndex( uint32_t parameter_id ); - /** - * Retransforms a data pool id and an array index to a SCOS 2000 PID. - */ - static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index ); - - /** - * Method to return the type of a pool variable. - * @param parameter_id A parameterID (not pool id) of a DP member. - * @param type Returns the type or TYPE::UNKNOWN_TYPE - * @return RETURN_OK if parameter exists, RETURN_FAILED else. - */ - ReturnValue_t getType( uint32_t parameter_id, Type* type ); - - /** - * Method to check if a PID exists. - * Does not lock, as there's no possibility to alter the list that is checked during run-time. - * @param parameterId The PID (not pool id!) of a parameter. - * @return true if exists, false else. - */ - bool exists(uint32_t parameterId); -}; - -//We assume someone globally instantiates a DataPool. -extern DataPool dataPool; -#endif /* DATAPOOL_H_ */ diff --git a/datapool/DataSet.cpp b/datapool/DataSet.cpp deleted file mode 100644 index f49f2ee57..000000000 --- a/datapool/DataSet.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include - -DataSet::DataSet() : - fill_count(0), state(DATA_SET_UNINITIALISED) { - for (unsigned count = 0; count < DATA_SET_MAX_SIZE; count++) { - registeredVariables[count] = NULL; - } -} - -DataSet::~DataSet() { - //Don't do anything with your variables, they are dead already! (Destructor is already called) -} - -ReturnValue_t DataSet::read() { - ReturnValue_t result = RETURN_OK; - if (state == DATA_SET_UNINITIALISED) { - lockDataPool(); - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_WRITE - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - ReturnValue_t status = registeredVariables[count]->read(); - if (status != RETURN_OK) { - result = INVALID_PARAMETER_DEFINITION; - break; - } - } - } - state = DATA_SET_WAS_READ; - freeDataPoolLock(); - } else { - sif::error << "DataSet::read(): Call made in wrong position." << std::endl; - result = SET_WAS_ALREADY_READ; - } - return result; -} - -ReturnValue_t DataSet::commit(uint8_t valid) { - setValid(valid); - return commit(); -} - -ReturnValue_t DataSet::commit() { - if (state == DATA_SET_WAS_READ) { - lockDataPool(); - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_READ - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commit(); - } - } - state = DATA_SET_UNINITIALISED; - freeDataPoolLock(); - return RETURN_OK; - } else { - ReturnValue_t result = RETURN_OK; - lockDataPool(); - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - == PoolVariableIF::VAR_WRITE - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commit(); - } else if (registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - if (result != COMMITING_WITHOUT_READING) { - sif::error << - "DataSet::commit(): commit-without-read " - "call made with non write-only variable." << std::endl; - result = COMMITING_WITHOUT_READING; - } - } - } - state = DATA_SET_UNINITIALISED; - freeDataPoolLock(); - return result; - } - -} - -void DataSet::registerVariable(PoolVariableIF* variable) { - if (state == DATA_SET_UNINITIALISED) { - if (variable != NULL) { - if (fill_count < DATA_SET_MAX_SIZE) { - registeredVariables[fill_count] = variable; - fill_count++; - return; - } - } - } - sif::error - << "DataSet::registerVariable: failed. Either NULL, or set is full, or call made in wrong position." - << std::endl; - return; -} - -uint8_t DataSet::freeDataPoolLock() { - return ::dataPool.freeDataPoolLock(); -} - -uint8_t DataSet::lockDataPool() { - return ::dataPool.lockDataPool(); -} - -ReturnValue_t DataSet::serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const { - ReturnValue_t result = RETURN_FAILED; - for (uint16_t count = 0; count < fill_count; count++) { - result = registeredVariables[count]->serialize(buffer, size, maxSize, - streamEndianness); - if (result != RETURN_OK) { - return result; - } - } - return result; -} - -size_t DataSet::getSerializedSize() const { - size_t size = 0; - for (uint16_t count = 0; count < fill_count; count++) { - size += registeredVariables[count]->getSerializedSize(); - } - return size; -} - -void DataSet::setValid(uint8_t valid) { - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_READ) { - registeredVariables[count]->setValid(valid); - } - } -} - -ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { - ReturnValue_t result = RETURN_FAILED; - for (uint16_t count = 0; count < fill_count; count++) { - result = registeredVariables[count]->deSerialize(buffer, size, - streamEndianness); - if (result != RETURN_OK) { - return result; - } - } - return result; -} diff --git a/datapool/DataSet.h b/datapool/DataSet.h deleted file mode 100644 index 3d2115379..000000000 --- a/datapool/DataSet.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * \file DataSet.h - * - * \brief This file contains the DataSet class and a small structure called DataSetContent. - * - * \date 10/17/2012 - * - * \author Bastian Baetz - * - */ - -#ifndef DATASET_H_ -#define DATASET_H_ - -#include -#include -#include -#include -#include -#include -#include -/** - * \brief The DataSet class manages a set of locally checked out variables. - * - * \details This class manages a list, where a set of local variables (or pool variables) are - * registered. They are checked-out (i.e. their values are looked up and copied) - * with the read call. After the user finishes working with the pool variables, - * he can write back all variable values to the pool with the commit call. - * The data set manages locking and freeing the data pool, to ensure that all values - * are read and written back at once. - * An internal state manages usage of this class. Variables may only be registered before - * the read call is made, and the commit call only after the read call. - * If pool variables are writable and not committed until destruction of the set, the - * DataSet class automatically sets the valid flag in the data pool to invalid (without) - * changing the variable's value. - * - * \ingroup data_pool - */ -class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF { -private: - //SHOULDDO we could use a linked list of datapool variables - static const uint8_t DATA_SET_MAX_SIZE = 63; //!< This definition sets the maximum number of variables to register in one DataSet. - - /** - * \brief This array represents all pool variables registered in this set. - * \details It has a maximum size of DATA_SET_MAX_SIZE. - */ - PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE]; - /** - * \brief The fill_count attribute ensures that the variables register in the correct array - * position and that the maximum number of variables is not exceeded. - */ - uint16_t fill_count; - /** - * States of the seet. - */ - enum States { - DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED - DATA_SET_WAS_READ //!< DATA_SET_WAS_READ - }; - /** - * \brief state manages the internal state of the data set, which is important e.g. for the - * behavior on destruction. - */ - States state; - /** - * \brief This is a small helper function to facilitate locking the global data pool. - * \details It makes use of the lockDataPool method offered by the DataPool class. - */ - uint8_t lockDataPool(); - /** - * \brief This is a small helper function to facilitate unlocking the global data pool. - * \details It makes use of the freeDataPoolLock method offered by the DataPool class. - */ - uint8_t freeDataPoolLock(); - -public: - static const uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS; - static const ReturnValue_t INVALID_PARAMETER_DEFINITION = - MAKE_RETURN_CODE( 0x01 ); - static const ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE( 0x02 ); - static const ReturnValue_t COMMITING_WITHOUT_READING = - MAKE_RETURN_CODE(0x03); - - /** - * \brief The constructor simply sets the fill_count to zero and sets the state to "uninitialized". - */ - DataSet(); - /** - * \brief The destructor automatically manages writing the valid information of variables. - * \details In case the data set was read out, but not committed (indicated by state), - * the destructor parses all variables that are still registered to the set. - * For each, the valid flag in the data pool is set to "invalid". - */ - ~DataSet(); - /** - * \brief The read call initializes reading out all registered variables. - * \details It iterates through the list of registered variables and calls all read() - * functions of the registered pool variables (which read out their values from the - * data pool) which are not write-only. In case of an error (e.g. a wrong data type, - * or an invalid data pool id), the operation is aborted and - * \c INVALID_PARAMETER_DEFINITION returned. - * The data pool is locked during the whole read operation and freed afterwards. - * The state changes to "was written" after this operation. - * \return - \c RETURN_OK if all variables were read successfully. - * - \c INVALID_PARAMETER_DEFINITION if PID, size or type of the - * requested variable is invalid. - * - \c SET_WAS_ALREADY_READ if read() is called twice without calling - * commit() in between - */ - ReturnValue_t read(); - /** - * \brief The commit call initializes writing back the registered variables. - * \details It iterates through the list of registered variables and calls - * the commit() method of the remaining registered variables (which write back - * their values to the pool). - * The data pool is locked during the whole commit operation and freed afterwards. - * The state changes to "was committed" after this operation. - * If the set does contain at least one variable which is not write-only commit() - * can only be called after read(). If the set only contains variables which are - * write only, commit() can be called without a preceding read() call. - * \return - \c RETURN_OK if all variables were read successfully. - * - \c COMMITING_WITHOUT_READING if set was not read yet and contains non write-only - * variables - */ - ReturnValue_t commit(void); - /** - * Variant of method above which sets validity of all elements of the set. - * @param valid Validity information from PoolVariableIF. - * \return - \c RETURN_OK if all variables were read successfully. - * - \c COMMITING_WITHOUT_READING if set was not read yet and contains non write-only - * variables - */ - ReturnValue_t commit(uint8_t valid); - /** - * \brief This operation is used to register the local variables in the set. - * \details It copies all required information to the currently - * free space in the registeredVariables list. - */ - void registerVariable(PoolVariableIF* variable); - - /** - * Set the valid information of all variables contained in the set which are not readonly - * - * @param valid Validity information from PoolVariableIF. - */ - void setValid(uint8_t valid); - - ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const override; - - size_t getSerializedSize() const override; - - ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; - -}; - -#endif /* DATASET_H_ */ diff --git a/datapool/DataSetBase.cpp b/datapool/DataSetBase.cpp new file mode 100644 index 000000000..cb7a78993 --- /dev/null +++ b/datapool/DataSetBase.cpp @@ -0,0 +1,168 @@ +#include +#include + +DataSetBase::DataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxFillCount): + registeredVariables(registeredVariablesArray), + maxFillCount(maxFillCount) { + for (uint8_t count = 0; count < maxFillCount; count++) { + registeredVariables[count] = nullptr; + } +} + +DataSetBase::~DataSetBase() {} + +ReturnValue_t DataSetBase::registerVariable( + PoolVariableIF *variable) { + if (state != States::DATA_SET_UNINITIALISED) { + sif::error << "DataSet::registerVariable: " + "Call made in wrong position." << std::endl; + return DataSetIF::DATA_SET_UNINITIALISED; + } + if (variable == nullptr) { + sif::error << "DataSet::registerVariable: " + "Pool variable is nullptr." << std::endl; + return DataSetIF::POOL_VAR_NULL; + } + if (fillCount >= maxFillCount) { + sif::error << "DataSet::registerVariable: " + "DataSet is full." << std::endl; + return DataSetIF::DATA_SET_FULL; + } + registeredVariables[fillCount] = variable; + fillCount++; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DataSetBase::read(uint32_t lockTimeout) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + if (state == States::DATA_SET_UNINITIALISED) { + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + result = readVariable(count); + if(result != RETURN_OK) { + break; + } + } + state = States::DATA_SET_WAS_READ; + unlockDataPool(); + } + else { + sif::error << "DataSet::read(): " + "Call made in wrong position. Don't forget to commit" + " member datasets!" << std::endl; + result = SET_WAS_ALREADY_READ; + } + return result; +} + +uint16_t DataSetBase::getFillCount() const { + return fillCount; +} + +ReturnValue_t DataSetBase::readVariable(uint16_t count) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + // These checks are often performed by the respective + // variable implementation too, but I guess a double check does not hurt. + if (registeredVariables[count]->getReadWriteMode() != + PoolVariableIF::VAR_WRITE and + registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) + { + result = registeredVariables[count]->readWithoutLock(); + if(result != HasReturnvaluesIF::RETURN_OK) { + result = INVALID_PARAMETER_DEFINITION; + } + } + return result; +} + +ReturnValue_t DataSetBase::commit(uint32_t lockTimeout) { + if (state == States::DATA_SET_WAS_READ) { + handleAlreadyReadDatasetCommit(lockTimeout); + return HasReturnvaluesIF::RETURN_OK; + } + else { + return handleUnreadDatasetCommit(lockTimeout); + } +} + +void DataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + != PoolVariableIF::VAR_READ + && registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + registeredVariables[count]->commitWithoutLock(); + } + } + state = States::DATA_SET_UNINITIALISED; + unlockDataPool(); +} + +ReturnValue_t DataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + == PoolVariableIF::VAR_WRITE + && registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + registeredVariables[count]->commitWithoutLock(); + } else if (registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + if (result != COMMITING_WITHOUT_READING) { + sif::error << "DataSet::commit(): commit-without-read call made " + "with non write-only variable." << std::endl; + result = COMMITING_WITHOUT_READING; + } + } + } + state = States::DATA_SET_UNINITIALISED; + unlockDataPool(); + return result; +} + + +ReturnValue_t DataSetBase::lockDataPool(uint32_t timeoutMs) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DataSetBase::unlockDataPool() { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DataSetBase::serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->serialize(buffer, size, maxSize, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +ReturnValue_t DataSetBase::deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->deSerialize(buffer, size, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +size_t DataSetBase::getSerializedSize() const { + uint32_t size = 0; + for (uint16_t count = 0; count < fillCount; count++) { + size += registeredVariables[count]->getSerializedSize(); + } + return size; +} diff --git a/datapool/DataSetBase.h b/datapool/DataSetBase.h new file mode 100644 index 000000000..cc16aa9e5 --- /dev/null +++ b/datapool/DataSetBase.h @@ -0,0 +1,149 @@ +#ifndef FRAMEWORK_DATAPOOL_DATASETBASE_H_ +#define FRAMEWORK_DATAPOOL_DATASETBASE_H_ +#include +#include +#include + +/** + * @brief The DataSetBase class manages a set of locally checked out variables. + * @details + * This class manages a list, where a set of local variables (or pool variables) + * are registered. They are checked-out (i.e. their values are looked + * up and copied) with the read call. After the user finishes working with the + * pool variables, he can write back all variable values to the pool with + * the commit call. The data set manages locking and freeing the data pool, + * to ensure that all values are read and written back at once. + * + * An internal state manages usage of this class. Variables may only be + * registered before the read call is made, and the commit call only + * after the read call. + * + * If pool variables are writable and not committed until destruction + * of the set, the DataSet class automatically sets the valid flag in the + * data pool to invalid (without) changing the variable's value. + * + * The base class lockDataPool und unlockDataPool implementation are empty + * and should be implemented to protect the underlying pool type. + * @author Bastian Baetz + * @ingroup data_pool + */ +class DataSetBase: public DataSetIF, + public SerializeIF, + public HasReturnvaluesIF { +public: + + /** + * @brief Creates an empty dataset. Use registerVariable or + * supply a pointer to this dataset to PoolVariable + * initializations to register pool variables. + */ + DataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxFillCount); + virtual~ DataSetBase(); + + /** + * @brief The read call initializes reading out all registered variables. + * @details + * It iterates through the list of registered variables and calls all read() + * functions of the registered pool variables (which read out their values + * from the data pool) which are not write-only. + * In case of an error (e.g. a wrong data type, or an invalid data pool id), + * the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned. + * + * The data pool is locked during the whole read operation and + * freed afterwards.The state changes to "was written" after this operation. + * @return + * - @c RETURN_OK if all variables were read successfully. + * - @c INVALID_PARAMETER_DEFINITION if PID, size or type of the + * requested variable is invalid. + * - @c SET_WAS_ALREADY_READ if read() is called twice without calling + * commit() in between + */ + virtual ReturnValue_t read(uint32_t lockTimeout = + MutexIF::BLOCKING) override; + /** + * @brief The commit call initializes writing back the registered variables. + * @details + * It iterates through the list of registered variables and calls the + * commit() method of the remaining registered variables (which write back + * their values to the pool). + * + * The data pool is locked during the whole commit operation and + * freed afterwards. The state changes to "was committed" after this operation. + * + * If the set does contain at least one variable which is not write-only + * commit() can only be called after read(). If the set only contains + * variables which are write only, commit() can be called without a + * preceding read() call. + * @return - @c RETURN_OK if all variables were read successfully. + * - @c COMMITING_WITHOUT_READING if set was not read yet and + * contains non write-only variables + */ + virtual ReturnValue_t commit(uint32_t lockTimeout = + MutexIF::BLOCKING) override; + + /** + * Register the passed pool variable instance into the data set. + * @param variable + * @return + */ + virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override; + /** + * Provides the means to lock the underlying data structure to ensure + * thread-safety. Default implementation is empty + * @return Always returns -@c RETURN_OK + */ + virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = + MutexIF::BLOCKING) override; + /** + * Provides the means to unlock the underlying data structure to ensure + * thread-safety. Default implementation is empty + * @return Always returns -@c RETURN_OK + */ + virtual ReturnValue_t unlockDataPool() override; + + virtual uint16_t getFillCount() const; + + /* SerializeIF implementations */ + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; + +protected: + /** + * @brief The fill_count attribute ensures that the variables + * register in the correct array position and that the maximum + * number of variables is not exceeded. + */ + uint16_t fillCount = 0; + /** + * States of the seet. + */ + enum class States { + DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED + DATA_SET_WAS_READ //!< DATA_SET_WAS_READ + }; + /** + * @brief state manages the internal state of the data set, + * which is important e.g. for the behavior on destruction. + */ + States state = States::DATA_SET_UNINITIALISED; + + /** + * @brief This array represents all pool variables registered in this set. + * Child classes can use a static or dynamic container to create + * an array of registered variables and assign the first entry here. + */ + PoolVariableIF** registeredVariables = nullptr; + const size_t maxFillCount = 0; + +private: + ReturnValue_t readVariable(uint16_t count); + void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); + ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); +}; + +#endif /* FRAMEWORK_DATAPOOL_DATASETBASE_H_ */ diff --git a/datapool/DataSetIF.h b/datapool/DataSetIF.h index 7741477db..437f324f6 100644 --- a/datapool/DataSetIF.h +++ b/datapool/DataSetIF.h @@ -1,39 +1,62 @@ -/** - * \file DataSetIF.h - * - * \brief This file contains the small interface to access the DataSet class. - * - * \date 10/23/2012 - * - * \author Bastian Baetz - * - */ - #ifndef DATASETIF_H_ #define DATASETIF_H_ +#include +#include class PoolVariableIF; /** - * \brief This class defines a small interface to register on a DataSet. + * @brief This class defines a small interface to register on a DataSet. * - * \details Currently, the only purpose of this interface is to provide a method for locally - * checked-out variables to register on a data set. Still, it may become useful for - * other purposes as well. - * - * \ingroup data_pool + * @details + * Currently, the only purpose of this interface is to provide a + * method for locally checked-out variables to register on a data set. + * Still, it may become useful for other purposes as well. + * @author Bastian Baetz + * @ingroup data_pool */ class DataSetIF { public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS; + static constexpr ReturnValue_t INVALID_PARAMETER_DEFINITION = + MAKE_RETURN_CODE( 0x01 ); + static constexpr ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE( 0x02 ); + static constexpr ReturnValue_t COMMITING_WITHOUT_READING = + MAKE_RETURN_CODE(0x03); + + static constexpr ReturnValue_t DATA_SET_UNINITIALISED = MAKE_RETURN_CODE( 0x04 ); + static constexpr ReturnValue_t DATA_SET_FULL = MAKE_RETURN_CODE( 0x05 ); + static constexpr ReturnValue_t POOL_VAR_NULL = MAKE_RETURN_CODE( 0x06 ); + /** - * \brief This is an empty virtual destructor, as it is proposed for C++ interfaces. + * @brief This is an empty virtual destructor, + * as it is proposed for C++ interfaces. */ virtual ~DataSetIF() {} + + virtual ReturnValue_t read(uint32_t lockTimeout) = 0; + virtual ReturnValue_t commit(uint32_t lockTimeout) = 0; /** - * \brief This operation provides a method to register local data pool variables - * to register in a data set by passing itself to this DataSet operation. + * @brief This operation provides a method to register local data pool + * variables to register in a data set by passing itself + * to this DataSet operation. */ - virtual void registerVariable( PoolVariableIF* variable ) = 0; + virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0; + + virtual uint16_t getFillCount() const = 0; +private: + /** + * @brief Most underlying data structures will have a pool like structure + * and will require a lock and unlock mechanism to ensure + * thread-safety + * @return Lock operation result + */ + virtual ReturnValue_t lockDataPool(uint32_t timeoutMs) = 0; + /** + * @brief Unlock call corresponding to the lock call. + * @return Unlock operation result + */ + virtual ReturnValue_t unlockDataPool() = 0; }; #endif /* DATASETIF_H_ */ diff --git a/datapool/HkSwitchHelper.cpp b/datapool/HkSwitchHelper.cpp index caae21461..cf5114f75 100644 --- a/datapool/HkSwitchHelper.cpp +++ b/datapool/HkSwitchHelper.cpp @@ -1,5 +1,4 @@ #include -//#include #include HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) : @@ -22,14 +21,14 @@ ReturnValue_t HkSwitchHelper::initialize() { } ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) { - CommandMessage message; - while (actionQueue->receiveMessage(&message) == HasReturnvaluesIF::RETURN_OK) { - ReturnValue_t result = commandActionHelper.handleReply(&message); + CommandMessage command; + while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = commandActionHelper.handleReply(&command); if (result == HasReturnvaluesIF::RETURN_OK) { continue; } - message.setToUnknownCommand(); - actionQueue->reply(&message); + command.setToUnknownCommand(); + actionQueue->reply(&command); } return HasReturnvaluesIF::RETURN_OK; diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp deleted file mode 100644 index eca354a90..000000000 --- a/datapool/PoolRawAccess.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, - DataSetIF *data_set, ReadWriteMode_t setReadWriteMode) : - dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type( - Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0), readWriteMode( - setReadWriteMode) { - memset(value, 0, sizeof(value)); - if (data_set != NULL) { - data_set->registerVariable(this); - } -} - -PoolRawAccess::~PoolRawAccess() { - -} - -ReturnValue_t PoolRawAccess::read() { - PoolEntryIF *read_out = ::dataPool.getRawData(dataPoolId); - if (read_out != NULL) { - valid = read_out->getValid(); - if (read_out->getSize() > arrayEntry) { - arraySize = read_out->getSize(); - typeSize = read_out->getByteSize() / read_out->getSize(); - type = read_out->getType(); - if (typeSize <= sizeof(value)) { - uint16_t arrayPosition = arrayEntry * typeSize; - sizeTillEnd = read_out->getByteSize() - arrayPosition; - uint8_t *ptr = - &((uint8_t*) read_out->getRawData())[arrayPosition]; - memcpy(value, ptr, typeSize); - return HasReturnvaluesIF::RETURN_OK; - } else { - //Error value type too large. - } - } else { - //Error index requested too large - } - } else { - //Error entry does not exist. - } - sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex - << dataPoolId << std::dec << " failed." << std::endl; - valid = INVALID; - typeSize = 0; - sizeTillEnd = 0; - memset(value, 0, sizeof(value)); - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t PoolRawAccess::commit() { - PoolEntryIF *write_back = ::dataPool.getRawData(dataPoolId); - if ((write_back != NULL) && (readWriteMode != VAR_READ)) { - write_back->setValid(valid); - uint8_t array_position = arrayEntry * typeSize; - uint8_t *ptr = &((uint8_t*) write_back->getRawData())[array_position]; - memcpy(ptr, value, typeSize); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -uint8_t* PoolRawAccess::getEntry() { - return value; -} - -ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t *buffer, - size_t *writtenBytes, size_t maxSize) { - uint8_t *data_ptr = getEntry(); -// debug << "PoolRawAccess::getEntry: Array position: " << index * size_of_type << " Size of T: " << (int)size_of_type << " ByteSize: " << byte_size << " Position: " << *size << std::endl; - if (typeSize == 0) { - return DATA_POOL_ACCESS_FAILED; - } - if (typeSize > maxSize) { - return INCORRECT_SIZE; - } - EndianConverter::convertBigEndian(buffer, data_ptr, typeSize); - *writtenBytes = typeSize; - return HasReturnvaluesIF::RETURN_OK; -} - -Type PoolRawAccess::getType() { - return type; -} - -size_t PoolRawAccess::getSizeOfType() { - return typeSize; -} - -size_t PoolRawAccess::getArraySize() { - return arraySize; -} - -uint32_t PoolRawAccess::getDataPoolId() const { - return dataPoolId; -} - -PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const { - return readWriteMode; -} - -ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer, - size_t setSize) { - if (typeSize == setSize) { - EndianConverter::convertBigEndian(value, buffer, typeSize); - return HasReturnvaluesIF::RETURN_OK; - } else { - sif::error - << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: Internal" - << (uint32_t) typeSize << ", Requested: " << setSize - << std::endl; - return INCORRECT_SIZE; - } -} - -bool PoolRawAccess::isValid() const { - if (valid != INVALID) - return true; - else - return false; -} - -void PoolRawAccess::setValid(uint8_t valid) { - this->valid = valid; -} - -size_t PoolRawAccess::getSizeTillEnd() const { - return sizeTillEnd; -} - -ReturnValue_t PoolRawAccess::serialize(uint8_t **buffer, size_t *size, - size_t maxSize, Endianness streamEndianness) const { - if (typeSize + *size <= maxSize) { - switch (streamEndianness) { - case (Endianness::BIG): - EndianConverter::convertBigEndian(*buffer, value, typeSize); - break; - case (Endianness::LITTLE): - EndianConverter::convertLittleEndian(*buffer, value, typeSize); - break; - default: - case (Endianness::MACHINE): - memcpy(*buffer, value, typeSize); - break; - } - *size += typeSize; - (*buffer) += typeSize; - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::BUFFER_TOO_SHORT; - } -} - -size_t PoolRawAccess::getSerializedSize() const { - return typeSize; -} - -ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) { - - if (*size >= typeSize) { - switch (streamEndianness) { - case (Endianness::BIG): - EndianConverter::convertBigEndian(value, *buffer, typeSize); - break; - case (Endianness::LITTLE): - EndianConverter::convertLittleEndian(value, *buffer, typeSize); - break; - default: - case (Endianness::MACHINE): - memcpy(value, *buffer, typeSize); - break; - } - *size -= typeSize; - *buffer += typeSize; - return HasReturnvaluesIF::RETURN_OK; - } else { - return SerializeIF::STREAM_TOO_SHORT; - } -} diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h deleted file mode 100644 index 09d19afd6..000000000 --- a/datapool/PoolRawAccess.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef POOLRAWACCESS_H_ -#define POOLRAWACCESS_H_ - -#include -#include - -/** - * This class allows accessing Data Pool variables as raw bytes. - * This is necessary to have an access method for HK data, as the PID's alone do not - * provide a type information. - * \ingroup data_pool - */ -class PoolRawAccess: public PoolVariableIF { -private: - /** - * \brief To access the correct data pool entry on read and commit calls, the data pool id - * is stored. - */ - uint32_t dataPoolId; - /** - * \brief The array entry that is fetched from the data pool. - */ - uint8_t arrayEntry; - /** - * \brief The valid information as it was stored in the data pool is copied to this attribute. - */ - uint8_t valid; - /** - * \brief This value contains the type of the data pool entry. - */ - Type type; - /** - * \brief This value contains the size of the data pool entry in bytes. - */ - size_t typeSize; - /** - * The size of the DP array (single values return 1) - */ - size_t arraySize; - /** - * The size (in bytes) from the selected entry till the end of this DataPool variable. - */ - size_t sizeTillEnd; - /** - * \brief The information whether the class is read-write or read-only is stored here. - */ - ReadWriteMode_t readWriteMode; - static const uint8_t RAW_MAX_SIZE = sizeof(double); -protected: - /** - * \brief This is a call to read the value from the global data pool. - * \details When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies the value and the valid - * information to its local attributes. In case of a failure (wrong type or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself. - */ - ReturnValue_t read(); - /** - * \brief The commit call writes back the variable's value to the data pool. - * \details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. - * - */ - ReturnValue_t commit(); -public: - static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS; - static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02); - uint8_t value[RAW_MAX_SIZE]; - PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry, - DataSetIF *data_set, ReadWriteMode_t setReadWriteMode = - PoolVariableIF::VAR_READ); - /** - * \brief The classes destructor is empty. If commit() was not called, the local value is - * discarded and not written back to the data pool. - */ - ~PoolRawAccess(); - /** - * \brief This operation returns a pointer to the entry fetched. - * \details This means, it does not return a pointer to byte "index", but to the start byte of - * array entry "index". Example: If the original data pool array consists of an double - * array of size four, getEntry(1) returns &(this->value[8]). - */ - uint8_t* getEntry(); - /** - * \brief This operation returns the fetched entry from the data pool and - * flips the bytes, if necessary. - * \details It makes use of the getEntry call of this function, but additionally flips the - * bytes to big endian, which is the default for external communication (as House- - * keeping telemetry). To achieve this, the data is copied directly to the passed - * buffer, if it fits in the given maxSize. - * \param buffer A pointer to a buffer to write to - * \param writtenBytes The number of bytes written is returned with this value. - * \param maxSize The maximum size that the function may write to buffer. - * \return - \c RETURN_OK if entry could be acquired - * - \c RETURN_FAILED else. - */ - ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size, - size_t maxSize); - /** - * With this method, the content can be set from a big endian buffer safely. - * @param buffer Pointer to the data to set - * @param size Size of the data to write. Must fit this->size. - * @return - \c RETURN_OK on success - * - \c RETURN_FAILED on failure - */ - ReturnValue_t setEntryFromBigEndian(const uint8_t *buffer, - size_t setSize); - /** - * \brief This operation returns the type of the entry currently stored. - */ - Type getType(); - /** - * \brief This operation returns the size of the entry currently stored. - */ - size_t getSizeOfType(); - /** - * - * @return the size of the datapool array - */ - size_t getArraySize(); - /** - * \brief This operation returns the data pool id of the variable. - */ - uint32_t getDataPoolId() const; - /** - * This method returns if the variable is read-write or read-only. - */ - ReadWriteMode_t getReadWriteMode() const; - /** - * \brief With this call, the valid information of the variable is returned. - */ - bool isValid() const; - - void setValid(uint8_t valid); - /** - * Getter for the remaining size. - */ - size_t getSizeTillEnd() const; - - ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, - Endianness streamEndianness) const override; - - size_t getSerializedSize() const override; - - ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override; -}; - -#endif /* POOLRAWACCESS_H_ */ diff --git a/datapool/PoolRawAccessHelper.cpp b/datapool/PoolRawAccessHelper.cpp new file mode 100644 index 000000000..2324a56cd --- /dev/null +++ b/datapool/PoolRawAccessHelper.cpp @@ -0,0 +1,188 @@ +/** + * @file PoolRawAccessHelper.cpp + * + * @date 22.12.2019 + * @author R. Mueller + */ + +#include +#include +#include +#include + +#include +#include + +PoolRawAccessHelper::PoolRawAccessHelper(uint32_t * poolIdBuffer_, + uint8_t numberOfParameters_): + poolIdBuffer(reinterpret_cast(poolIdBuffer_)), + numberOfParameters(numberOfParameters_), validBufferIndex(0), + validBufferIndexBit(1) { +} + +PoolRawAccessHelper::~PoolRawAccessHelper() { +} + +ReturnValue_t PoolRawAccessHelper::serialize(uint8_t **buffer, size_t *size, + const size_t max_size, SerializeIF::Endianness streamEndianness) { + SerializationArgs serializationArgs = {buffer, size, max_size, + streamEndianness}; + ReturnValue_t result = RETURN_OK; + size_t remainingParametersSize = numberOfParameters * 4; + for(uint8_t count=0; count < numberOfParameters; count++) { + result = serializeCurrentPoolEntryIntoBuffer(serializationArgs, + &remainingParametersSize, false); + if(result != RETURN_OK) { + return result; + } + } + if(remainingParametersSize != 0) { + sif::debug << "PoolRawAccessHelper: " + "Remaining parameters size not 0 !" << std::endl; + result = RETURN_FAILED; + } + return result; +} + +ReturnValue_t PoolRawAccessHelper::serializeWithValidityMask(uint8_t ** buffer, + size_t * size, const size_t max_size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = RETURN_OK; + SerializationArgs argStruct = {buffer, size, max_size, streamEndianness}; + size_t remainingParametersSize = numberOfParameters * 4; + uint8_t validityMaskSize = ceil((float)numberOfParameters/8.0); + uint8_t validityMask[validityMaskSize]; + memset(validityMask,0, validityMaskSize); + for(uint8_t count = 0; count < numberOfParameters; count++) { + result = serializeCurrentPoolEntryIntoBuffer(argStruct, + &remainingParametersSize,true,validityMask); + if (result != RETURN_OK) { + return result; + } + } + if(remainingParametersSize != 0) { + sif::debug << "PoolRawAccessHelper: Remaining " + "parameters size not 0 !" << std::endl; + result = RETURN_FAILED; + } + + memcpy(*argStruct.buffer, validityMask, validityMaskSize); + *size += validityMaskSize; + validBufferIndex = 1; + validBufferIndexBit = 0; + return result; +} + +ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer( + SerializationArgs argStruct, size_t * remainingParameters, + bool withValidMask, uint8_t * validityMask) { + uint32_t currentPoolId; + // Deserialize current pool ID from pool ID buffer + ReturnValue_t result = SerializeAdapter::deSerialize(¤tPoolId, + &poolIdBuffer,remainingParameters, SerializeIF::Endianness::MACHINE); + if(result != RETURN_OK) { + sif::debug << std::hex << "PoolRawAccessHelper: Error deSeralizing " + "pool IDs" << std::dec << std::endl; + return result; + } + result = handlePoolEntrySerialization(currentPoolId, argStruct, + withValidMask, validityMask); + return result; +} + +ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization( + uint32_t currentPoolId,SerializationArgs argStruct, bool withValidMask, + uint8_t * validityMask) { + ReturnValue_t result = RETURN_FAILED; + uint8_t arrayPosition = 0; + uint8_t counter = 0; + bool poolEntrySerialized = false; + //debug << "Pool Raw Access Helper: Handling Pool ID: " + // << std::hex << currentPoolId << std::endl; + while(not poolEntrySerialized) { + + if(counter > GlobDataSet::DATA_SET_MAX_SIZE) { + sif::error << "PoolRawAccessHelper: Config error, " + "max. number of possible data set variables exceeded" + << std::endl; + return result; + } + counter ++; + + GlobDataSet currentDataSet; + //debug << "Current array position: " << (int)arrayPosition << std::endl; + PoolRawAccess currentPoolRawAccess(currentPoolId, arrayPosition, + ¤tDataSet, PoolVariableIF::VAR_READ); + + result = currentDataSet.read(); + if (result != RETURN_OK) { + sif::debug << std::hex << "PoolRawAccessHelper: Error reading raw " + "dataset with returncode 0x" << result << std::dec << std::endl; + return result; + } + + result = checkRemainingSize(¤tPoolRawAccess, &poolEntrySerialized, + &arrayPosition); + if(result != RETURN_OK) { + sif::error << "Pool Raw Access Helper: Configuration Error at pool ID " + << std::hex << currentPoolId + << ". Size till end smaller than 0" << std::dec << std::endl; + return result; + } + + // set valid mask bit if necessary + if(withValidMask) { + if(currentPoolRawAccess.isValid()) { + handleMaskModification(validityMask); + } + validBufferIndexBit ++; + } + + result = currentDataSet.serialize(argStruct.buffer, argStruct.size, + argStruct.max_size, argStruct.streamEndianness); + if (result != RETURN_OK) { + sif::debug << "Pool Raw Access Helper: Error serializing pool data with " + "ID 0x" << std::hex << currentPoolId << " into send buffer " + "with return code " << result << std::dec << std::endl; + return result; + } + + } + return result; +} + +ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess* + currentPoolRawAccess, bool * isSerialized, uint8_t * arrayPosition) { + int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() - + currentPoolRawAccess->getSizeOfType(); + if(remainingSize == 0) { + *isSerialized = true; + } + else if(remainingSize > 0) { + *arrayPosition += 1; + } + else { + return RETURN_FAILED; + } + return RETURN_OK; +} + +void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) { + validityMask[validBufferIndex] = + bitSetter(validityMask[validBufferIndex], validBufferIndexBit, true); + if(validBufferIndexBit == 8) { + validBufferIndex ++; + validBufferIndexBit = 1; + } +} + +uint8_t PoolRawAccessHelper::bitSetter(uint8_t byte, uint8_t position, + bool value) { + if(position < 1 or position > 8) { + sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl; + return byte; + } + uint8_t shiftNumber = position + (6 - 2 * (position - 1)); + byte |= 1UL << shiftNumber; + return byte; +} diff --git a/datapool/PoolRawAccessHelper.h b/datapool/PoolRawAccessHelper.h new file mode 100644 index 000000000..0d8f8d6d0 --- /dev/null +++ b/datapool/PoolRawAccessHelper.h @@ -0,0 +1,111 @@ +/** + * @file PoolRawAccessHelper.h + * + * @date 22.12.2019 + */ + +#ifndef FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ +#define FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ + +#include +#include +#include + +/** + * @brief This helper function simplifies accessing data pool entries + * via PoolRawAccess + * @details Can be used for a Housekeeping Service + * like ECSS PUS Service 3 if the type of the datapool entries is unknown. + * The provided dataset can be serialized into a provided buffer automatically by + * providing a buffer of pool IDs + * @ingroup data_pool + */ +class PoolRawAccessHelper: public HasReturnvaluesIF { +public: + /** + * Call this constructor if a dataset needs to be serialized via + * Pool Raw Access + * @param dataSet_ This dataset will be used to perform thread-safe reading + * @param poolIdBuffer_ A buffer of uint32_t pool IDs + * @param numberOfParameters_ The number of parameters / pool IDs + */ + PoolRawAccessHelper(uint32_t * poolIdBuffer_, uint8_t numberOfParameters_); + virtual ~PoolRawAccessHelper(); + + /** + * Serialize the datapool entries derived from the pool ID buffer + * directly into a provided buffer + * @param [out] buffer + * @param [out] size Size of the serialized buffer + * @param max_size + * @param bigEndian + * @return @c RETURN_OK On success + * @c RETURN_FAILED on failure + */ + ReturnValue_t serialize(uint8_t ** buffer, size_t * size, + const size_t max_size, SerializeIF::Endianness streamEndianness); + + /** + * Serializes data pool entries into provided buffer with the validity mask buffer + * at the end of the buffer. Every bit of the validity mask denotes + * the validity of a corresponding data pool entry from left to right. + * @param [out] buffer + * @param [out] size Size of the serialized buffer plus size + * of the validity mask + * @return @c RETURN_OK On success + * @c RETURN_FAILED on failure + */ + ReturnValue_t serializeWithValidityMask(uint8_t ** buffer, size_t * size, + const size_t max_size, SerializeIF::Endianness streamEndianness); + + +private: + // DataSet * dataSet; + const uint8_t * poolIdBuffer; + uint8_t numberOfParameters; + + uint8_t validBufferIndex; + uint8_t validBufferIndexBit; + + struct SerializationArgs { + uint8_t ** buffer; + size_t * size; + const size_t max_size; + SerializeIF::Endianness streamEndianness; + }; + /** + * Helper function to serialize single pool entries + * @param pPoolIdBuffer + * @param buffer + * @param remainingParameters + * @param hkDataSize + * @param max_size + * @param bigEndian + * @param withValidMask Can be set optionally to set a + * provided validity mask + * @param validityMask Can be supplied and will be set if + * @c withValidMask is set to true + * @return + */ + ReturnValue_t serializeCurrentPoolEntryIntoBuffer( + SerializationArgs argStruct, size_t * remainingParameters, + bool withValidMask = false, uint8_t * validityMask = nullptr); + + ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId, + SerializationArgs argStruct, bool withValidMask = false, + uint8_t * validityMask = nullptr); + + ReturnValue_t checkRemainingSize(PoolRawAccess * currentPoolRawAccess, + bool * isSerialized, uint8_t * arrayPosition); + void handleMaskModification(uint8_t * validityMask); + /** + * Sets specific bit of a byte + * @param byte + * @param position Position of byte to set from 1 to 8 + * @param value Binary value to set + * @return + */ + uint8_t bitSetter(uint8_t byte, uint8_t position, bool value); +}; + +#endif /* FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ */ diff --git a/datapool/PoolVarList.h b/datapool/PoolVarList.h index 90c9f1785..9d6bc461a 100644 --- a/datapool/PoolVarList.h +++ b/datapool/PoolVarList.h @@ -1,12 +1,12 @@ #ifndef POOLVARLIST_H_ #define POOLVARLIST_H_ -#include #include +#include template class PoolVarList { private: - PoolVariable variables[n_var]; + GlobPoolVar variables[n_var]; public: PoolVarList( const uint32_t set_id[n_var], DataSetIF* dataSet, PoolVariableIF::ReadWriteMode_t setReadWriteMode ) { //I really should have a look at the new init list c++ syntax. @@ -20,7 +20,7 @@ public: } } - PoolVariable &operator [](int i) { return variables[i]; } + GlobPoolVar &operator [](int i) { return variables[i]; } }; diff --git a/datapool/PoolVariable.h b/datapool/PoolVariable.h deleted file mode 100644 index a06935c37..000000000 --- a/datapool/PoolVariable.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * \file PoolVariable.h - * - * \brief This file contains the PoolVariable class, which locally represents a non-array data pool variable. - * - * \date 10/17/2012 - * - * \author Bastian Baetz - */ - -#ifndef POOLVARIABLE_H_ -#define POOLVARIABLE_H_ - -#include -#include -#include -#include -#include - -template class PoolVarList; - -/** - * \brief This is the access class for non-array data pool entries. - * - * \details To ensure safe usage of the data pool, operation is not done directly on the data pool - * entries, but on local copies. This class provides simple type-safe access to single - * data pool entries (i.e. entries with length = 1). - * The class can be instantiated as read-write and read only. - * It provides a commit-and-roll-back semantic, which means that the variable's value in - * the data pool is not changed until the commit call is executed. - * \tparam T The template parameter sets the type of the variable. Currently, all plain data types - * are supported, but in principle any type is possible. - * \ingroup data_pool - */ -template -class PoolVariable: public PoolVariableIF { - template friend class PoolVarList; -protected: - /** - * \brief To access the correct data pool entry on read and commit calls, the data pool id - * is stored. - */ - uint32_t dataPoolId; - /** - * \brief The valid information as it was stored in the data pool is copied to this attribute. - */ - uint8_t valid; - /** - * \brief The information whether the class is read-write or read-only is stored here. - */ - ReadWriteMode_t readWriteMode; - /** - * \brief This is a call to read the value from the global data pool. - * \details When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies the value and the valid - * information to its local attributes. In case of a failure (wrong type or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself. - */ - ReturnValue_t read() { - PoolEntry *read_out = ::dataPool.getData < T > (dataPoolId, 1); - if (read_out != NULL) { - valid = read_out->valid; - value = *(read_out->address); - return HasReturnvaluesIF::RETURN_OK; - } else { - value = 0; - valid = false; - sif::error << "PoolVariable: read of DP Variable 0x" << std::hex - << dataPoolId << std::dec << " failed." << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - } - /** - * \brief The commit call writes back the variable's value to the data pool. - * \details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. - * - */ - ReturnValue_t commit() { - PoolEntry *write_back = ::dataPool.getData < T > (dataPoolId, 1); - if ((write_back != NULL) && (readWriteMode != VAR_READ)) { - write_back->valid = valid; - *(write_back->address) = value; - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - /** - * Empty ctor for List initialization - */ - PoolVariable() : - dataPoolId(PoolVariableIF::NO_PARAMETER), valid( - PoolVariableIF::INVALID), readWriteMode(VAR_READ), value(0) { - - } -public: - /** - * \brief This is the local copy of the data pool entry. - * \details The user can work on this attribute - * just like he would on a simple local variable. - */ - T value; - /** - * \brief In the constructor, the variable can register itself in a DataSet (if not NULL is - * passed). - * \details It DOES NOT fetch the current value from the data pool, but sets the value - * attribute to default (0). The value is fetched within the read() operation. - * \param set_id This is the id in the global data pool this instance of the access class - * corresponds to. - * \param dataSet The data set in which the variable shall register itself. If NULL, - * the variable is not registered. - * \param setWritable If this flag is set to true, changes in the value attribute can be - * written back to the data pool, otherwise not. - */ - PoolVariable(uint32_t set_id, DataSetIF *dataSet, - ReadWriteMode_t setReadWriteMode) : - dataPoolId(set_id), valid(PoolVariableIF::INVALID), readWriteMode( - setReadWriteMode), value(0) { - if (dataSet != NULL) { - dataSet->registerVariable(this); - } - } - /** - * Copy ctor to copy classes containing Pool Variables. - */ - PoolVariable(const PoolVariable &rhs) : - dataPoolId(rhs.dataPoolId), valid(rhs.valid), readWriteMode( - rhs.readWriteMode), value(rhs.value) { - } - - /** - * \brief The classes destructor is empty. - * \details If commit() was not called, the local value is - * discarded and not written back to the data pool. - */ - ~PoolVariable() { - - } - /** - * \brief This operation returns the data pool id of the variable. - */ - uint32_t getDataPoolId() const { - return dataPoolId; - } - /** - * This operation sets the data pool id of the variable. - * The method is necessary to set id's of data pool member variables with bad initialization. - */ - void setDataPoolId(uint32_t poolId) { - dataPoolId = poolId; - } - /** - * This method returns if the variable is write-only, read-write or read-only. - */ - ReadWriteMode_t getReadWriteMode() const { - return readWriteMode; - } - /** - * \brief With this call, the valid information of the variable is returned. - */ - bool isValid() const { - if (valid) - return true; - else - return false; - } - - uint8_t getValid() { - return valid; - } - - void setValid(uint8_t valid) { - this->valid = valid; - } - - operator T() { - return value; - } - - operator T() const { - return value; - } - - PoolVariable& operator=(T newValue) { - value = newValue; - return *this; - } - - PoolVariable& operator=(PoolVariable newPoolVariable) { - value = newPoolVariable.value; - return *this; - } - - virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, - size_t maxSize, Endianness streamEndianness) const override { - return SerializeAdapter::serialize(&value, buffer, size, maxSize, - streamEndianness); - } - - virtual size_t getSerializedSize() const override { - return SerializeAdapter::getSerializedSize(&value); - } - - virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override { - return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); - } -}; - -typedef PoolVariable db_uint8_t; -typedef PoolVariable db_uint16_t; -typedef PoolVariable db_uint32_t; -typedef PoolVariable db_int8_t; -typedef PoolVariable db_int16_t; -typedef PoolVariable db_int32_t; -typedef PoolVariable db_bool_t; -typedef PoolVariable db_float_t; -typedef PoolVariable db_double_t; -//Alternative (but I thing this is not as useful: code duplication, differences too small): - -//template -//class PoolReader : public PoolVariableIF { -//private: -// uint32_t parameter_id; -// uint8_t valid; -//public: -// T value; -// PoolReader( uint32_t set_id, DataSetIF* set ) : parameter_id(set_id), valid(false), value(0) { -// set->registerVariable( this ); -// } -// -// ~PoolReader() {}; -// -// uint8_t commit() { -// return HasReturnvaluesIF::RETURN_OK; -// } -// -// uint8_t read() { -// PoolEntry* read_out = ::dataPool.getData( parameter_id, 1 ); -// if ( read_out != NULL ) { -// valid = read_out->valid; -// value = *(read_out->address); -// return HasReturnvaluesIF::RETURN_OK; -// } else { -// value = 0; -// valid = false; -// return CHECKOUT_FAILED; -// } -// } -// uint32_t getParameterId() { return parameter_id; } -// bool isWritable() { return false; }; -// bool isValid() { if (valid) return true; else return false; } -//}; -// -//template -//class PoolWriter : public PoolVariableIF { -//private: -// uint32_t parameter_id; -//public: -// T value; -// PoolWriter( uint32_t set_id, DataSetIF* set ) : parameter_id(set_id), value(0) { -// set->registerVariable( this ); -// } -// -// ~PoolWriter() {}; -// -// uint8_t commit() { -// PoolEntry* write_back = ::dataPool.getData( parameter_id, 1 ); -// if ( write_back != NULL ) { -// write_back->valid = true; -// *(write_back->address) = value; -// return HasReturnvaluesIF::RETURN_OK; -// } else { -// return CHECKOUT_FAILED; -// } -// } -// uint8_t read() { -// PoolEntry* read_out = ::dataPool.getData( parameter_id, 1 ); -// if ( read_out != NULL ) { -// value = *(read_out->address); -// return HasReturnvaluesIF::RETURN_OK; -// } else { -// value = 0; -// return CHECKOUT_FAILED; -// } -// } -// uint32_t getParameterId() { return parameter_id; } -// bool isWritable() { return true; }; -// bool isValid() { return false; } -//}; - -#endif /* POOLVARIABLE_H_ */ diff --git a/datapool/PoolVariableIF.h b/datapool/PoolVariableIF.h index 7626c9c17..30b87839b 100644 --- a/datapool/PoolVariableIF.h +++ b/datapool/PoolVariableIF.h @@ -1,71 +1,99 @@ -/* - * \file PoolVariableIF.h - * - * \brief This file contains the interface definition for pool variables. - * - * \date 10/17/2012 - * - * \author Bastian Baetz - */ - -#ifndef POOLVARIABLEIF_H_ -#define POOLVARIABLEIF_H_ +#ifndef FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_ +#define FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_ #include #include /** - * \brief This interface is used to control local data pool variable representations. - * - * \details To securely handle data pool variables, all pool entries are locally managed by - * data pool variable access classes, which are called pool variables. To ensure a - * common state of a set of variables needed in a function, these local pool variables - * again are managed by other classes, e.g. the DataSet. This interface provides unified - * access to local pool variables for such manager classes. - * \ingroup data_pool + * @brief This interface is used to control data pool + * variable representations. + * @details + * To securely handle data pool variables, all pool entries are locally + * managed by data pool variable access classes, which are called pool + * variables. To ensure a common state of a set of variables needed in a + * function, these local pool variables again are managed by other classes, + * like the DataSet classes. This interface provides unified access to + * local pool variables for such manager classes. + * @author Bastian Baetz + * @ingroup data_pool */ class PoolVariableIF : public SerializeIF { - friend class DataSet; -protected: - /** - * \brief The commit call shall write back a newly calculated local value to the data pool. - */ - virtual ReturnValue_t commit() = 0; - /** - * \brief The read call shall read the value of this parameter from the data pool and store - * the content locally. - */ - virtual ReturnValue_t read() = 0; + friend class DataSetBase; + friend class GlobDataSet; + friend class LocalDataSet; public: - static const uint8_t VALID = 1; - static const uint8_t INVALID = 0; - static const uint32_t NO_PARAMETER = 0; + static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF; + static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0); + + static constexpr bool VALID = 1; + static constexpr bool INVALID = 0; + static constexpr uint32_t NO_PARAMETER = 0xffffffff; + enum ReadWriteMode_t { VAR_READ, VAR_WRITE, VAR_READ_WRITE }; /** - * \brief This is an empty virtual destructor, as it is proposed for C++ interfaces. + * @brief This is an empty virtual destructor, + * as it is proposed for C++ interfaces. */ - virtual ~PoolVariableIF() { - } + virtual ~PoolVariableIF() {} /** - * \brief This method returns if the variable is write-only, read-write or read-only. + * @brief This method returns if the variable is write-only, + * read-write or read-only. */ virtual ReadWriteMode_t getReadWriteMode() const = 0; /** - * \brief This operation shall return the data pool id of the variable. + * @brief This operation shall return the data pool id of the variable. */ virtual uint32_t getDataPoolId() const = 0; /** - * \brief With this call, the valid information of the variable is returned. + * @brief With this call, the valid information of the + * variable is returned. */ virtual bool isValid() const = 0; /** - * \brief With this call, the valid information of the variable is set. + * @brief With this call, the valid information of the variable is set. */ - virtual void setValid(uint8_t validity) = 0; + virtual void setValid(bool validity) = 0; + /** + * @brief The commit call shall write back a newly calculated local + * value to the data pool. + * @details + * It is assumed that these calls are implemented in a thread-safe manner! + */ + virtual ReturnValue_t commit(uint32_t lockTimeout) = 0; + /** + * @brief The read call shall read the value of this parameter from + * the data pool and store the content locally. + * @details + * It is assumbed that these calls are implemented in a thread-safe manner! + */ + virtual ReturnValue_t read(uint32_t lockTimeout) = 0; + +protected: + + /** + * @brief Same as commit with the difference that comitting will be + * performed without a lock + * @return + * This can be used if the lock protection is handled externally + * to avoid the overhead of locking and unlocking consecutively. + * Declared protected to avoid free public usage. + */ + virtual ReturnValue_t readWithoutLock() = 0; + /** + * @brief Same as commit with the difference that comitting will be + * performed without a lock + * @return + * This can be used if the lock protection is handled externally + * to avoid the overhead of locking and unlocking consecutively. + * Declared protected to avoid free public usage. + */ + virtual ReturnValue_t commitWithoutLock() = 0; }; +using pool_rwm_t = PoolVariableIF::ReadWriteMode_t; + #endif /* POOLVARIABLEIF_H_ */ diff --git a/datapool/PoolVector.h b/datapool/PoolVector.h deleted file mode 100644 index 777ec7238..000000000 --- a/datapool/PoolVector.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * \file PoolVector.h - * - * \brief This file contains the PoolVector class, the header only class to handle data pool vectors. - * - * \date 10/23/2012 - * - * \author Bastian Baetz - */ - -#ifndef POOLVECTOR_H_ -#define POOLVECTOR_H_ - -#include -#include -#include -#include -#include - -/** - * \brief This is the access class for array-type data pool entries. - * - * \details To ensure safe usage of the data pool, operation is not done directly on the data pool - * entries, but on local copies. This class provides simple type- and length-safe access - * to vector-style data pool entries (i.e. entries with length > 1). - * The class can be instantiated as read-write and read only. - * It provides a commit-and-roll-back semantic, which means that no array entry in - * the data pool is changed until the commit call is executed. - * There are two template parameters: - * \tparam T This template parameter specifies the data type of an array entry. Currently, all - * plain data types are supported, but in principle any type is possible. - * \tparam vector_size This template parameter specifies the vector size of this entry. - * Using a template parameter for this is not perfect, but avoids dynamic memory allocation. - * \ingroup data_pool - */ -template -class PoolVector: public PoolVariableIF { -private: - /** - * \brief To access the correct data pool entry on read and commit calls, the data pool id - * is stored. - */ - uint32_t dataPoolId; - /** - * \brief The valid information as it was stored in the data pool is copied to this attribute. - */ - uint8_t valid; - /** - * \brief The information whether the class is read-write or read-only is stored here. - */ - ReadWriteMode_t readWriteMode; - -protected: - /** - * \brief This is a call to read the array's values from the global data pool. - * \details When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies all array values and the valid - * information to its local attributes. In case of a failure (wrong type, size or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself. - */ - ReturnValue_t read() { - PoolEntry* read_out = ::dataPool.getData(this->dataPoolId, - vector_size); - if (read_out != NULL) { - this->valid = read_out->valid; - memcpy(this->value, read_out->address, read_out->getByteSize()); - - return HasReturnvaluesIF::RETURN_OK; - - } else { - memset(this->value, 0, vector_size * sizeof(T)); - sif::error << "PoolVector: read of DP Variable 0x" << std::hex - << dataPoolId << std::dec << " failed." << std::endl; - this->valid = INVALID; - return HasReturnvaluesIF::RETURN_FAILED; - } - } - /** - * \brief The commit call copies the array values back to the data pool. - * \details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. - * - */ - ReturnValue_t commit() { - PoolEntry* write_back = ::dataPool.getData(this->dataPoolId, - vector_size); - if ((write_back != NULL) && (this->readWriteMode != VAR_READ)) { - write_back->valid = valid; - memcpy(write_back->address, this->value, write_back->getByteSize()); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } -public: - /** - * \brief This is the local copy of the data pool entry. - * \detials The user can work on this attribute - * just like he would on a local array of this type. - */ - T value[vector_size]; - /** - * \brief In the constructor, the variable can register itself in a DataSet (if not NULL is - * passed). - * \details It DOES NOT fetch the current value from the data pool, but sets the value - * attribute to default (0). The value is fetched within the read() operation. - * \param set_id This is the id in the global data pool this instance of the access class - * corresponds to. - * \param dataSet The data set in which the variable shall register itself. If NULL, - * the variable is not registered. - * \param setWritable If this flag is set to true, changes in the value attribute can be - * written back to the data pool, otherwise not. - */ - PoolVector(uint32_t set_id, DataSetIF* set, - ReadWriteMode_t setReadWriteMode) : - dataPoolId(set_id), valid(false), readWriteMode(setReadWriteMode) { - memset(this->value, 0, vector_size * sizeof(T)); - if (set != NULL) { - set->registerVariable(this); - } - } - /** - * Copy ctor to copy classes containing Pool Variables. - */ -// PoolVector(const PoolVector& rhs) { -// PoolVector temp(rhs.dataPoolId, rhs.) -// memcpy(value, rhs.value, sizeof(T)*vector_size); -// } - /** - * \brief The classes destructor is empty. - * \details If commit() was not called, the local value is - * discarded and not written back to the data pool. - */ - ~PoolVector() { - } - ; - /** - * \brief The operation returns the number of array entries in this variable. - */ - uint8_t getSize() { - return vector_size; - } - /** - * \brief This operation returns the data pool id of the variable. - */ - uint32_t getDataPoolId() const { - return dataPoolId; - } - /** - * This operation sets the data pool id of the variable. - * The method is necessary to set id's of data pool member variables with bad initialization. - */ - void setDataPoolId(uint32_t poolId) { - dataPoolId = poolId; - } - /** - * This method returns if the variable is write-only, read-write or read-only. - */ - ReadWriteMode_t getReadWriteMode() const { - return readWriteMode; - } - ; - /** - * \brief With this call, the valid information of the variable is returned. - */ - bool isValid() const { - if (valid != INVALID) - return true; - else - return false; - } - - void setValid(uint8_t valid) { - this->valid = valid; - } - - uint8_t getValid() { - return valid; - } - - T &operator [](int i) { - return value[i]; - } - - const T &operator [](int i) const { - return value[i]; - } - - PoolVector &operator=( - PoolVector newPoolVector) { - - for (uint16_t i = 0; i < vector_size; i++) { - this->value[i] = newPoolVector.value[i]; - } - return *this; - } - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const { - uint16_t i; - ReturnValue_t result; - for (i = 0; i < vector_size; i++) { - result = SerializeAdapter::serialize(&(value[i]), buffer, size, - maxSize, streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - return result; - } - - virtual size_t getSerializedSize() const { - return vector_size * SerializeAdapter::getSerializedSize(value); - } - - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { - uint16_t i; - ReturnValue_t result; - for (i = 0; i < vector_size; i++) { - result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, - streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - return result; - } -}; - -#endif /* POOLVECTOR_H_ */ diff --git a/datapool/DataPoolAdmin.cpp b/datapoolglob/DataPoolAdmin.cpp similarity index 92% rename from datapool/DataPoolAdmin.cpp rename to datapoolglob/DataPoolAdmin.cpp index 3ea266ea8..4d0e5530f 100644 --- a/datapool/DataPoolAdmin.cpp +++ b/datapoolglob/DataPoolAdmin.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -40,9 +40,9 @@ ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId, uint8_t valid = data[4]; - uint32_t poolId = ::dataPool.PIDToDataPoolId(address); + uint32_t poolId = glob::dataPool.PIDToDataPoolId(address); - DataSet mySet; + GlobDataSet mySet; PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE); ReturnValue_t status = mySet.read(); if (status != RETURN_OK) { @@ -92,9 +92,9 @@ void DataPoolAdmin::handleCommand() { ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, const uint8_t* data, size_t size, uint8_t** dataPointer) { - uint32_t poolId = ::dataPool.PIDToDataPoolId(address); - uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); - DataSet testSet; + uint32_t poolId = glob::dataPool.PIDToDataPoolId(address); + uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address); + GlobDataSet testSet; PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ); ReturnValue_t status = testSet.read(); @@ -113,7 +113,7 @@ ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, const uint8_t* readPosition = data; for (; size > 0; size -= typeSize) { - DataSet rawSet; + GlobDataSet rawSet; PoolRawAccess variable(poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ_WRITE); status = rawSet.read(); @@ -131,9 +131,9 @@ ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size, uint8_t** dataPointer, uint8_t* copyHere) { - uint32_t poolId = ::dataPool.PIDToDataPoolId(address); - uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); - DataSet testSet; + uint32_t poolId = glob::dataPool.PIDToDataPoolId(address); + uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address); + GlobDataSet testSet; PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ); ReturnValue_t status = testSet.read(); @@ -146,7 +146,7 @@ ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size, } uint8_t* ptrToCopy = copyHere; for (; size > 0; size -= typeSize) { - DataSet rawSet; + GlobDataSet rawSet; PoolRawAccess variable(poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ); status = rawSet.read(); diff --git a/datapool/DataPoolAdmin.h b/datapoolglob/DataPoolAdmin.h similarity index 96% rename from datapool/DataPoolAdmin.h rename to datapoolglob/DataPoolAdmin.h index 1be920b54..653fdd8e2 100644 --- a/datapool/DataPoolAdmin.h +++ b/datapoolglob/DataPoolAdmin.h @@ -1,15 +1,16 @@ #ifndef DATAPOOLADMIN_H_ #define DATAPOOLADMIN_H_ -#include -#include -#include #include #include #include -#include -#include +#include #include +#include + +#include +#include +#include class DataPoolAdmin: public HasActionsIF, public ExecutableObjectIF, diff --git a/datapool/DataPoolParameterWrapper.cpp b/datapoolglob/DataPoolParameterWrapper.cpp similarity index 95% rename from datapool/DataPoolParameterWrapper.cpp rename to datapoolglob/DataPoolParameterWrapper.cpp index e08eba5bb..a292016ea 100644 --- a/datapool/DataPoolParameterWrapper.cpp +++ b/datapoolglob/DataPoolParameterWrapper.cpp @@ -1,10 +1,8 @@ -#include "DataPoolParameterWrapper.h" - -//for returncodes +#include +#include +#include #include -#include -#include DataPoolParameterWrapper::DataPoolParameterWrapper() : type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId( @@ -20,7 +18,7 @@ ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId, uint16_t parameterId) { poolId = (domainId << 16) + parameterId; - DataSet mySet; + GlobDataSet mySet; PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ); ReturnValue_t status = mySet.read(); if (status != HasReturnvaluesIF::RETURN_OK) { @@ -57,7 +55,7 @@ ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, } for (uint8_t index = 0; index < rows; index++){ - DataSet mySet; + GlobDataSet mySet; PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ); mySet.read(); result = raw.serialize(buffer,size,maxSize,streamEndianness); @@ -94,7 +92,7 @@ ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow, for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) { - DataSet mySet; + GlobDataSet mySet; PoolRawAccess raw(poolId, startingRow + fromRow, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); diff --git a/datapool/DataPoolParameterWrapper.h b/datapoolglob/DataPoolParameterWrapper.h similarity index 100% rename from datapool/DataPoolParameterWrapper.h rename to datapoolglob/DataPoolParameterWrapper.h diff --git a/datapoolglob/GlobalDataPool.cpp b/datapoolglob/GlobalDataPool.cpp new file mode 100644 index 000000000..25acaab3f --- /dev/null +++ b/datapoolglob/GlobalDataPool.cpp @@ -0,0 +1,132 @@ +#include +#include +#include + +GlobalDataPool::GlobalDataPool( + void(*initFunction)(GlobPoolMap* pool_map)) { + mutex = MutexFactory::instance()->createMutex(); + if (initFunction != NULL ) { + initFunction( &this->globDataPool ); + } +} + +GlobalDataPool::~GlobalDataPool() { + MutexFactory::instance()->deleteMutex(mutex); + for(GlobPoolMapIter it = this->globDataPool.begin(); + it != this->globDataPool.end(); ++it ) + { + delete it->second; + } +} + +// The function checks PID, type and array length before returning a copy of +// the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr. +template PoolEntry* GlobalDataPool::getData( uint32_t data_pool_id, + uint8_t sizeOrPosition ) { + GlobPoolMapIter it = this->globDataPool.find( data_pool_id ); + if ( it != this->globDataPool.end() ) { + PoolEntry* entry = dynamic_cast< PoolEntry* >( it->second ); + if (entry != nullptr ) { + if ( sizeOrPosition <= entry->length ) { + return entry; + } + } + } + return nullptr; +} + +PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) { + GlobPoolMapIter it = this->globDataPool.find( data_pool_id ); + if ( it != this->globDataPool.end() ) { + return it->second; + } else { + return nullptr; + } +} + +ReturnValue_t GlobalDataPool::unlockDataPool() { + ReturnValue_t status = mutex->unlockMutex(); + if(status != RETURN_OK) { + sif::error << "DataPool::DataPool: unlock of mutex failed with" + " error code: " << status << std::endl; + } + return status; +} + +ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) { + ReturnValue_t status = mutex->lockMutex(timeoutMs); + if(status != RETURN_OK) { + sif::error << "DataPool::DataPool: lock of mutex failed " + "with error code: " << status << std::endl; + } + return status; +} + +void GlobalDataPool::print() { + sif::debug << "DataPool contains: " << std::endl; + std::map::iterator dataPoolIt; + dataPoolIt = this->globDataPool.begin(); + while( dataPoolIt != this->globDataPool.end() ) { + sif::debug << std::hex << dataPoolIt->first << std::dec << " |"; + dataPoolIt->second->print(); + dataPoolIt++; + } +} + +uint32_t GlobalDataPool::PIDToDataPoolId(uint32_t parameter_id) { + return (parameter_id >> 8) & 0x00FFFFFF; +} + +uint8_t GlobalDataPool::PIDToArrayIndex(uint32_t parameter_id) { + return (parameter_id & 0x000000FF); +} + +uint32_t GlobalDataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) { + return (poolId << 8) + index; +} + + +//SHOULDDO: Do we need a mutex lock here... I don't think so, +//as we only check static const values of elements in a list that do not change. +//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM +ReturnValue_t GlobalDataPool::getType(uint32_t parameter_id, Type* type) { + GlobPoolMapIter it = this->globDataPool.find( PIDToDataPoolId(parameter_id)); + if ( it != this->globDataPool.end() ) { + *type = it->second->getType(); + return RETURN_OK; + } else { + *type = Type::UNKNOWN_TYPE; + return RETURN_FAILED; + } +} + +bool GlobalDataPool::exists(uint32_t parameterId) { + uint32_t poolId = PIDToDataPoolId(parameterId); + uint32_t index = PIDToArrayIndex(parameterId); + GlobPoolMapIter it = this->globDataPool.find( poolId ); + if (it != globDataPool.end()) { + if (it->second->getSize() >= index) { + return true; + } + } + return false; +} + +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size ); +template PoolEntry* GlobalDataPool::getData( + uint32_t data_pool_id, uint8_t size); diff --git a/datapoolglob/GlobalDataPool.h b/datapoolglob/GlobalDataPool.h new file mode 100644 index 000000000..b9c1436fb --- /dev/null +++ b/datapoolglob/GlobalDataPool.h @@ -0,0 +1,149 @@ +#ifndef GLOBALDATAPOOL_H_ +#define GLOBALDATAPOOL_H_ + +#include +#include +#include +#include + +/** + * @defgroup data_pool Global data pool + * This is the group, where all classes associated with global + * data pool handling belong to. + * This includes classes to access Data Pool variables. + */ + +/** + * Typedefs for the global pool representations + */ +using GlobPoolMap = std::map; +using GlobPoolMapIter = GlobPoolMap::iterator; + +/** + * @brief This class represents the OBSW global data-pool. + * + * @details + * All variables are registered and space is allocated in an initialization + * function, which is passed do the constructor. Space for the variables is + * allocated on the heap (with a new call). + * + * The data is found by a data pool id, which uniquely represents a variable. + * Data pool variables should be used with a blackboard logic in mind, + * which means read data is valid (if flagged so), + * but not necessarily up-to-date. + * + * Variables are either single values or arrays. + * @author Bastian Baetz + * @ingroup data_pool + */ +class GlobalDataPool : public HasReturnvaluesIF { +private: + /** + * @brief This is the actual data pool itself. + * @details It is represented by a map with the data pool id as index + * and a pointer to a single PoolEntry as value. + */ + GlobPoolMap globDataPool; + + /** + * @brief The mutex is created in the constructor and makes + * access mutual exclusive. + * @details Locking and unlocking the pool is only done by the DataSet class. + */ + MutexIF* mutex; +public: + /** + * @brief In the classes constructor, + * the passed initialization function is called. + * @details + * To enable filling the pool, a pointer to the map is passed, + * allowing direct access to the pool's content. + * On runtime, adding or removing variables is forbidden. + */ + GlobalDataPool( void ( *initFunction )( GlobPoolMap* pool_map ) ); + + /** + * @brief The destructor iterates through the data_pool map and + * calls all entries destructors to clean up the heap. + */ + ~GlobalDataPool(); + + /** + * @brief This is the default call to access the pool. + * @details + * A pointer to the PoolEntry object is returned. + * The call checks data pool id, type and array size. + * Returns NULL in case of failure. + * @param data_pool_id The data pool id to search. + * @param sizeOrPosition The array size (not byte size!) of the pool entry, + * or the position the user wants to read. + * If smaller than the entry size, everything's ok. + */ + template PoolEntry* getData( uint32_t data_pool_id, + uint8_t sizeOrPosition ); + + /** + * @brief An alternative call to get a data pool entry in case the type is not implicitly known + * (i.e. in Housekeeping Telemetry). + * @details It returns a basic interface and does NOT perform + * a size check. The caller has to assure he does not copy too much data. + * Returns NULL in case the entry is not found. + * @param data_pool_id The data pool id to search. + */ + PoolEntryIF* getRawData( uint32_t data_pool_id ); + /** + * @brief This is a small helper function to facilitate locking the global data pool. + * @details It fetches the pool's mutex id and tries to acquire the mutex. + */ + ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING); + /** + * @brief This is a small helper function to facilitate unlocking the global data pool. + * @details It fetches the pool's mutex id and tries to free the mutex. + */ + ReturnValue_t unlockDataPool(); + /** + * @brief The print call is a simple debug method. + * @details It prints the current content of the data pool. + * It iterates through the data_pool map and calls each entry's print() method. + */ + void print(); + /** + * Extracts the data pool id from a SCOS 2000 PID. + * @param parameter_id The passed Parameter ID. + * @return The data pool id as used within the OBSW. + */ + static uint32_t PIDToDataPoolId( uint32_t parameter_id ); + /** + * Extracts an array index out of a SCOS 2000 PID. + * @param parameter_id The passed Parameter ID. + * @return The index of the corresponding data pool entry. + */ + static uint8_t PIDToArrayIndex( uint32_t parameter_id ); + /** + * Retransforms a data pool id and an array index to a SCOS 2000 PID. + */ + static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index ); + + /** + * Method to return the type of a pool variable. + * @param parameter_id A parameterID (not pool id) of a DP member. + * @param type Returns the type or TYPE::UNKNOWN_TYPE + * @return RETURN_OK if parameter exists, RETURN_FAILED else. + */ + ReturnValue_t getType( uint32_t parameter_id, Type* type ); + + /** + * Method to check if a PID exists. Does not lock, as there's no + * possibility to alter the list that is checked during run-time. + * @param parameterId The PID (not pool id!) of a parameter. + * @return true if exists, false else. + */ + bool exists(uint32_t parameterId); +}; + +//We assume someone globally instantiates a DataPool. +namespace glob { +extern GlobalDataPool dataPool; +} + +#endif /* DATAPOOL_H_ */ diff --git a/datapoolglob/GlobalDataSet.cpp b/datapoolglob/GlobalDataSet.cpp new file mode 100644 index 000000000..883f61577 --- /dev/null +++ b/datapoolglob/GlobalDataSet.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +GlobDataSet::GlobDataSet(): DataSetBase( + reinterpret_cast(®isteredVariables), + DATA_SET_MAX_SIZE) {} + +// Don't do anything with your variables, they are dead already! +// (Destructor is already called) +GlobDataSet::~GlobDataSet() {} + +ReturnValue_t GlobDataSet::commit(bool valid, uint32_t lockTimeout) { + setEntriesValid(valid); + setSetValid(valid); + return commit(lockTimeout); +} + +ReturnValue_t GlobDataSet::commit(uint32_t lockTimeout) { + return DataSetBase::commit(lockTimeout); +} + +ReturnValue_t GlobDataSet::unlockDataPool() { + return glob::dataPool.unlockDataPool(); +} + +ReturnValue_t GlobDataSet::lockDataPool(uint32_t timeoutMs) { + return glob::dataPool.lockDataPool(timeoutMs); +} + +void GlobDataSet::setEntriesValid(bool valid) { + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + != PoolVariableIF::VAR_READ) { + registeredVariables[count]->setValid(valid); + } + } +} + +void GlobDataSet::setSetValid(bool valid) { + this->valid = valid; +} + + diff --git a/datapoolglob/GlobalDataSet.h b/datapoolglob/GlobalDataSet.h new file mode 100644 index 000000000..d237cc1b4 --- /dev/null +++ b/datapoolglob/GlobalDataSet.h @@ -0,0 +1,96 @@ +#ifndef FRAMEWORK_DATAPOOLGLOB_DATASET_H_ +#define FRAMEWORK_DATAPOOLGLOB_DATASET_H_ + +#include + +/** + * @brief The DataSet class manages a set of locally checked out variables + * for the global data pool. + * @details + * This class uses the read-commit() semantic provided by the DataSetBase class. + * It extends the base class by using the global data pool, + * having a valid state and implementing lock und unlock calls for the global + * datapool. + * + * For more information on how this class works, see the DataSetBase + * documentation. + * @author Bastian Baetz + * @ingroup data_pool + */ +class GlobDataSet: public DataSetBase { +public: + + /** + * @brief Creates an empty GlobDataSet. Use registerVariable or + * supply a pointer to this dataset to PoolVariable + * initializations to register pool variables. + */ + GlobDataSet(); + + /** + * @brief The destructor automatically manages writing the valid + * information of variables. + * @details + * In case the data set was read out, but not committed(indicated by state), + * the destructor parses all variables that are still registered to the set. + * For each, the valid flag in the data pool is set to "invalid". + */ + ~GlobDataSet(); + + /** + * Variant of method above which sets validity of all elements of the set. + * @param valid Validity information from PoolVariableIF. + * @return - @c RETURN_OK if all variables were read successfully. + * - @c COMMITING_WITHOUT_READING if set was not read yet and + * contains non write-only variables + */ + ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::BLOCKING); + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + + /** + * Set all entries + * @param valid + */ + void setSetValid(bool valid); + + /** + * Set the valid information of all variables contained in the set which + * are not read-only + * + * @param valid Validity information from PoolVariableIF. + */ + void setEntriesValid(bool valid); + + //!< This definition sets the maximum number of variables to + //! register in one DataSet. + static const uint8_t DATA_SET_MAX_SIZE = 63; + +private: + /** + * If the valid state of a dataset is always relevant to the whole + * data set we can use this flag. + */ + bool valid = false; + + /** + * @brief This is a small helper function to facilitate locking + * the global data pool. + * @details + * It makes use of the lockDataPool method offered by the DataPool class. + */ + ReturnValue_t lockDataPool(uint32_t timeoutMs) override; + /** + * @brief This is a small helper function to facilitate + * unlocking the global data pool + * @details + * It makes use of the freeDataPoolLock method offered by the DataPool class. + */ + ReturnValue_t unlockDataPool() override; + + void handleAlreadyReadDatasetCommit(); + ReturnValue_t handleUnreadDatasetCommit(); + + PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE]; +}; + +#endif /* FRAMEWORK_DATAPOOLGLOB_DATASET_H_ */ diff --git a/datapoolglob/GlobalPoolVariable.h b/datapoolglob/GlobalPoolVariable.h new file mode 100644 index 000000000..b4aa6c4c1 --- /dev/null +++ b/datapoolglob/GlobalPoolVariable.h @@ -0,0 +1,213 @@ +#ifndef GLOBALPOOLVARIABLE_H_ +#define GLOBALPOOLVARIABLE_H_ + +#include +#include +#include +#include +#include +#include + +template class PoolVarList; + + +/** + * @brief This is the access class for non-array data pool entries. + * + * @details + * To ensure safe usage of the data pool, operation is not done directly + * on the data pool entries, but on local copies. This class provides simple + * type-safe access to single data pool entries (i.e. entries with length = 1). + * The class can be instantiated as read-write and read only. + * It provides a commit-and-roll-back semantic, which means that the + * variable's value in the data pool is not changed until the + * commit call is executed. + * @tparam T The template parameter sets the type of the variable. + * Currently, all plain data types are supported, but in principle + * any type is possible. + * @ingroup data_pool + */ +template +class GlobPoolVar: public PoolVariableIF { + template friend class PoolVarList; + static_assert(not std::is_same::value, + "Do not use boolean for the PoolEntry type, use uint8_t instead!" + "There is no boolean type in CCSDS."); +public: + /** + * @brief In the constructor, the variable can register itself in a + * DataSet (if nullptr is not passed). + * @details + * It DOES NOT fetch the current value from the data pool, but + * sets the value attribute to default (0). + * The value is fetched within the read() operation. + * @param set_id This is the id in the global data pool + * this instance of the access class corresponds to. + * @param dataSet The data set in which the variable shall register + * itself. If NULL, the variable is not registered. + * @param setWritable If this flag is set to true, changes in the value + * attribute can be written back to the data pool, otherwise not. + */ + GlobPoolVar(uint32_t set_id, DataSetIF* dataSet, + ReadWriteMode_t setReadWriteMode); + + /** + * @brief This is the local copy of the data pool entry. + * @details The user can work on this attribute + * just like he would on a simple local variable. + */ + T value = 0; + + /** + * @brief Copy ctor to copy classes containing Pool Variables. + * (Robin): This only copies member variables, which is done + * by the default copy ctor. maybe we can ommit this ctor? + */ + GlobPoolVar(const GlobPoolVar& rhs); + + /** + * @brief The classes destructor is empty. + * @details If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~GlobPoolVar() {} + + /** + * @brief This is a call to read the value from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies the value and the valid + * information to its local attributes. In case of a failure (wrong type or + * pool id not found), the variable is set to zero and invalid. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t read(uint32_t lockTimeout) override; + /** + * @brief The commit call writes back the variable's value to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The operation does NOT provide any mutual exclusive protection by itself. + * The commit call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(uint32_t lockTimeout) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + /** + * @brief To access the correct data pool entry on read and commit calls, + * the data pool is stored. + */ + uint32_t dataPoolId; + + /** + * @brief The valid information as it was stored in the data pool is + * copied to this attribute. + */ + uint8_t valid; + + /** + * @brief The information whether the class is read-write or read-only + * is stored here. + */ + pool_rwm_t readWriteMode; + + /** + * Empty ctor for List initialization + */ + GlobPoolVar(); +public: + /** + * \brief This operation returns the data pool id of the variable. + */ + uint32_t getDataPoolId() const override; + + /** + * This method returns if the variable is write-only, read-write or read-only. + */ + ReadWriteMode_t getReadWriteMode() const override; + /** + * This operation sets the data pool id of the variable. + * The method is necessary to set id's of data pool member variables with bad initialization. + */ + void setDataPoolId(uint32_t poolId); + + /** + * \brief With this call, the valid information of the variable is returned. + */ + bool isValid() const override; + + uint8_t getValid(); + + void setValid(bool valid) override; + + operator T() { + return value; + } + + operator T() const { + return value; + } + + GlobPoolVar &operator=(T newValue) { + value = newValue; + return *this; + } + + GlobPoolVar &operator=(GlobPoolVar newPoolVariable) { + value = newPoolVariable.value; + return *this; + } + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t max_size, + SerializeIF::Endianness streamEndianness) const override { + return SerializeAdapter::serialize(&value, buffer, size, max_size, + streamEndianness); + } + + virtual size_t getSerializedSize() const { + return SerializeAdapter::getSerializedSize(&value); + } + + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&value, buffer, size, + streamEndianness); + } +}; + +#include + +typedef GlobPoolVar gp_bool_t; +typedef GlobPoolVar gp_uint8_t; +typedef GlobPoolVar gp_uint16_t; +typedef GlobPoolVar gp_uint32_t; +typedef GlobPoolVar gp_int8_t; +typedef GlobPoolVar gp_int16_t; +typedef GlobPoolVar gp_int32_t; +typedef GlobPoolVar gp_float_t; +typedef GlobPoolVar gp_double_t; + +#endif /* POOLVARIABLE_H_ */ diff --git a/datapoolglob/GlobalPoolVariable.tpp b/datapoolglob/GlobalPoolVariable.tpp new file mode 100644 index 000000000..d61d605d7 --- /dev/null +++ b/datapoolglob/GlobalPoolVariable.tpp @@ -0,0 +1,117 @@ +#ifndef GLOBALPOOLVARIABLE_TPP_ +#define GLOBALPOOLVARIABLE_TPP_ + +template +inline GlobPoolVar::GlobPoolVar(uint32_t set_id, + DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode): + dataPoolId(set_id), valid(PoolVariableIF::INVALID), + readWriteMode(setReadWriteMode) +{ + if (dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline ReturnValue_t GlobPoolVar::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVar::commit(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVar::readWithoutLock() { + PoolEntry* read_out = glob::dataPool.getData(dataPoolId, 1); + if (read_out != NULL) { + valid = read_out->valid; + value = *(read_out->address); + return HasReturnvaluesIF::RETURN_OK; + } else { + value = 0; + valid = false; + sif::error << "PoolVariable: read of DP Variable 0x" << std::hex + << dataPoolId << std::dec << " failed." << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline ReturnValue_t GlobPoolVar::commitWithoutLock() { + PoolEntry* write_back = glob::dataPool.getData(dataPoolId, 1); + if ((write_back != NULL) && (readWriteMode != VAR_READ)) { + write_back->valid = valid; + *(write_back->address) = value; + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline GlobPoolVar::GlobPoolVar(): + dataPoolId(PoolVariableIF::NO_PARAMETER), + valid(PoolVariableIF::INVALID), + readWriteMode(VAR_READ), value(0) {} + +template +inline GlobPoolVar::GlobPoolVar(const GlobPoolVar& rhs) : + dataPoolId(rhs.dataPoolId), valid(rhs.valid), readWriteMode( + rhs.readWriteMode), value(rhs.value) {} + +template +inline pool_rwm_t GlobPoolVar::getReadWriteMode() const { + return readWriteMode; +} + +template +inline uint32_t GlobPoolVar::getDataPoolId() const { + return dataPoolId; +} + +template +inline void GlobPoolVar::setDataPoolId(uint32_t poolId) { + dataPoolId = poolId; +} + +template +inline bool GlobPoolVar::isValid() const { + if (valid) + return true; + else + return false; +} + +template +inline uint8_t GlobPoolVar::getValid() { + return valid; +} + +template +inline void GlobPoolVar::setValid(bool valid) { + this->valid = valid; +} + +#endif diff --git a/datapoolglob/GlobalPoolVector.h b/datapoolglob/GlobalPoolVector.h new file mode 100644 index 000000000..0e03f77db --- /dev/null +++ b/datapoolglob/GlobalPoolVector.h @@ -0,0 +1,185 @@ +#ifndef GLOBALPOOLVECTOR_H_ +#define GLOBALPOOLVECTOR_H_ + +#include +#include +#include +#include +#include + +/** + * @brief This is the access class for array-type data pool entries. + * + * @details + * To ensure safe usage of the data pool, operation is not done directly on the + * data pool entries, but on local copies. This class provides simple type- + * and length-safe access to vector-style data pool entries (i.e. entries with + * length > 1). The class can be instantiated as read-write and read only. + * + * It provides a commit-and-roll-back semantic, which means that no array + * entry in the data pool is changed until the commit call is executed. + * There are two template parameters: + * @tparam T + * This template parameter specifies the data type of an array entry. Currently, + * all plain data types are supported, but in principle any type is possible. + * @tparam vector_size + * This template parameter specifies the vector size of this entry. Using a + * template parameter for this is not perfect, but avoids + * dynamic memory allocation. + * @ingroup data_pool + */ +template +class GlobPoolVector: public PoolVariableIF { +public: + /** + * @brief In the constructor, the variable can register itself in a + * DataSet (if no nullptr is passed). + * @details + * It DOES NOT fetch the current value from the data pool, but sets the + * value attribute to default (0). The value is fetched within the + * read() operation. + * @param set_id + * This is the id in the global data pool this instance of the access + * class corresponds to. + * @param dataSet + * The data set in which the variable shall register itself. If nullptr, + * the variable is not registered. + * @param setWritable + * If this flag is set to true, changes in the value attribute can be + * written back to the data pool, otherwise not. + */ + GlobPoolVector(uint32_t set_id, DataSetIF* set, + ReadWriteMode_t setReadWriteMode); + + /** + * @brief This is the local copy of the data pool entry. + * @details The user can work on this attribute + * just like he would on a local array of this type. + */ + T value[vectorSize]; + /** + * @brief The classes destructor is empty. + * @details If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~GlobPoolVector() {}; + /** + * @brief The operation returns the number of array entries + * in this variable. + */ + uint8_t getSize() { + return vectorSize; + } + /** + * @brief This operation returns the data pool id of the variable. + */ + uint32_t getDataPoolId() const { + return dataPoolId; + } + /** + * @brief This operation sets the data pool id of the variable. + * @details + * The method is necessary to set id's of data pool member variables + * with bad initialization. + */ + void setDataPoolId(uint32_t poolId) { + dataPoolId = poolId; + } + /** + * This method returns if the variable is write-only, read-write or read-only. + */ + ReadWriteMode_t getReadWriteMode() const { + return readWriteMode; + } + + + /** + * @brief With this call, the valid information of the variable is returned. + */ + bool isValid() const { + if (valid != INVALID) + return true; + else + return false; + } + void setValid(bool valid) {this->valid = valid;} + uint8_t getValid() {return valid;} + + T &operator [](int i) {return value[i];} + const T &operator [](int i) const {return value[i];} + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t max_size, Endianness streamEndianness) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + /** + * @brief This is a call to read the array's values + * from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies all array values + * and the valid information to its local attributes. + * In case of a failure (wrong type, size or pool id not found), the + * variable is set to zero and invalid. + * The read call is protected by a lock of the global data pool. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call copies the array values back to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The commit call is protected by a lock of the global data pool. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + +private: + /** + * @brief To access the correct data pool entry on read and commit calls, + * the data pool id is stored. + */ + uint32_t dataPoolId; + /** + * @brief The valid information as it was stored in the data pool + * is copied to this attribute. + */ + uint8_t valid; + /** + * @brief The information whether the class is read-write or + * read-only is stored here. + */ + ReadWriteMode_t readWriteMode; +}; + +#include + +template +using gp_vec_t = GlobPoolVector; + +#endif /* POOLVECTOR_H_ */ diff --git a/datapoolglob/GlobalPoolVector.tpp b/datapoolglob/GlobalPoolVector.tpp new file mode 100644 index 000000000..ccf33138d --- /dev/null +++ b/datapoolglob/GlobalPoolVector.tpp @@ -0,0 +1,117 @@ +#ifndef GLOBALPOOLVECTOR_TPP_ +#define GLOBALPOOLVECTOR_TPP_ + + +template +inline GlobPoolVector::GlobPoolVector(uint32_t set_id, + DataSetIF* set, ReadWriteMode_t setReadWriteMode) : + dataPoolId(set_id), valid(false), readWriteMode(setReadWriteMode) { + memset(this->value, 0, vectorSize * sizeof(T)); + if (set != nullptr) { + set->registerVariable(this); + } +} + + +template +inline ReturnValue_t GlobPoolVector::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVector::commit( + uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVector::readWithoutLock() { + PoolEntry* read_out = glob::dataPool.getData(this->dataPoolId, + vectorSize); + if (read_out != nullptr) { + this->valid = read_out->valid; + memcpy(this->value, read_out->address, read_out->getByteSize()); + + return HasReturnvaluesIF::RETURN_OK; + + } else { + memset(this->value, 0, vectorSize * sizeof(T)); + sif::error << "PoolVector: Read of DP Variable 0x" << std::hex + << std::setw(8) << std::setfill('0') << dataPoolId << + std::dec << " failed." << std::endl; + this->valid = INVALID; + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline ReturnValue_t GlobPoolVector::commitWithoutLock() { + PoolEntry* writeBack = glob::dataPool.getData(this->dataPoolId, + vectorSize); + if ((writeBack != nullptr) && (this->readWriteMode != VAR_READ)) { + writeBack->valid = valid; + memcpy(writeBack->address, this->value, writeBack->getByteSize()); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +template +inline ReturnValue_t GlobPoolVector::serialize(uint8_t** buffer, + size_t* size, size_t max_size, + SerializeIF::Endianness streamEndianness) const { + uint16_t i; + ReturnValue_t result; + for (i = 0; i < vectorSize; i++) { + result = SerializeAdapter::serialize(&(value[i]), buffer, size, + max_size, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +template +inline size_t GlobPoolVector::getSerializedSize() const { + return vectorSize * SerializeAdapter::getSerializedSize(value); +} + +template +inline ReturnValue_t GlobPoolVector::deSerialize( + const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + uint16_t i; + ReturnValue_t result; + for (i = 0; i < vectorSize; i++) { + result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +#endif diff --git a/datapool/PIDReader.h b/datapoolglob/PIDReader.h similarity index 79% rename from datapool/PIDReader.h rename to datapoolglob/PIDReader.h index 464b15495..a11160402 100644 --- a/datapool/PIDReader.h +++ b/datapoolglob/PIDReader.h @@ -1,7 +1,7 @@ #ifndef PIDREADER_H_ #define PIDREADER_H_ -#include #include +#include #include #include #include @@ -15,10 +15,10 @@ class PIDReader: public PoolVariableIF { protected: uint32_t parameterId; uint8_t valid; - ReturnValue_t read() { - uint8_t arrayIndex = DataPool::PIDToArrayIndex(parameterId); - PoolEntry *read_out = ::dataPool.getData( - DataPool::PIDToDataPoolId(parameterId), arrayIndex); + ReturnValue_t readWithoutLock() { + uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId); + PoolEntry *read_out = glob::dataPool.getData( + GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex); if (read_out != NULL) { valid = read_out->valid; value = read_out->address[arrayIndex]; @@ -36,9 +36,13 @@ protected: * Reason is the possibility to access a single DP vector element, but if we commit, * we set validity of the whole vector. */ - ReturnValue_t commit() { + ReturnValue_t commit(uint32_t lockTimeout) override { return HasReturnvaluesIF::RETURN_FAILED; } + ReturnValue_t commitWithoutLock() override { + return HasReturnvaluesIF::RETURN_FAILED; + } + /** * Empty ctor for List initialization */ @@ -72,6 +76,19 @@ public: } } + ReturnValue_t read(uint32_t lockTimeout) override { + ReturnValue_t result = glob::dataPool.lockDataPool(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "PIDReader::read: Could not unlock data pool!" + << std::endl; + } + return result; + } /** * Copy ctor to copy classes containing Pool Variables. */ @@ -89,7 +106,7 @@ public: * \brief This operation returns the data pool id of the variable. */ uint32_t getDataPoolId() const { - return DataPool::PIDToDataPoolId(parameterId); + return GlobalDataPool::PIDToDataPoolId(parameterId); } uint32_t getParameterId() const { return parameterId; @@ -114,7 +131,7 @@ public: return valid; } - void setValid(uint8_t valid) { + void setValid(bool valid) { this->valid = valid; } diff --git a/datapool/PIDReaderList.h b/datapoolglob/PIDReaderList.h similarity index 73% rename from datapool/PIDReaderList.h rename to datapoolglob/PIDReaderList.h index 07d1b8e6d..0b8385081 100644 --- a/datapool/PIDReaderList.h +++ b/datapoolglob/PIDReaderList.h @@ -1,8 +1,8 @@ -#ifndef FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ -#define FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ +#ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ +#define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ -#include #include +#include template class PIDReaderList { private: @@ -24,4 +24,4 @@ public: -#endif /* FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ */ +#endif /* FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ */ diff --git a/datapoolglob/PoolRawAccess.cpp b/datapoolglob/PoolRawAccess.cpp new file mode 100644 index 000000000..783418cc9 --- /dev/null +++ b/datapoolglob/PoolRawAccess.cpp @@ -0,0 +1,239 @@ +#include +#include +#include +#include + +#include + +PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, + DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) : + dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), + type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0), + readWriteMode(setReadWriteMode) { + memset(value, 0, sizeof(value)); + if (dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +PoolRawAccess::~PoolRawAccess() {} + +ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +ReturnValue_t PoolRawAccess::readWithoutLock() { + ReturnValue_t result = RETURN_FAILED; + PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId); + if (readOut != nullptr) { + result = handleReadOut(readOut); + if(result == RETURN_OK) { + return result; + } + } else { + result = READ_ENTRY_NON_EXISTENT; + } + handleReadError(result); + return result; +} + +ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) { + ReturnValue_t result = RETURN_FAILED; + valid = readOut->getValid(); + if (readOut->getSize() > arrayEntry) { + arraySize = readOut->getSize(); + typeSize = readOut->getByteSize() / readOut->getSize(); + type = readOut->getType(); + if (typeSize <= sizeof(value)) { + uint16_t arrayPosition = arrayEntry * typeSize; + sizeTillEnd = readOut->getByteSize() - arrayPosition; + uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition]; + memcpy(value, ptr, typeSize); + return RETURN_OK; + } else { + result = READ_TYPE_TOO_LARGE; + } + } else { + //debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl; + result = READ_INDEX_TOO_LARGE; + } + return result; +} + +void PoolRawAccess::handleReadError(ReturnValue_t result) { + sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId + << std::dec << " failed, "; + if(result == READ_TYPE_TOO_LARGE) { + sif::error << "type too large." << std::endl; + } + else if(result == READ_INDEX_TOO_LARGE) { + sif::error << "index too large." << std::endl; + } + else if(result == READ_ENTRY_NON_EXISTENT) { + sif::error << "entry does not exist." << std::endl; + } + + valid = INVALID; + typeSize = 0; + sizeTillEnd = 0; + memset(value, 0, sizeof(value)); +} + +ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +ReturnValue_t PoolRawAccess::commitWithoutLock() { + PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId); + if ((write_back != NULL) && (readWriteMode != VAR_READ)) { + write_back->setValid(valid); + uint8_t array_position = arrayEntry * typeSize; + uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position]; + memcpy(ptr, value, typeSize); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t* PoolRawAccess::getEntry() { + return value; +} + +ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer, + size_t* writtenBytes, size_t max_size) { + uint8_t* data_ptr = getEntry(); + // debug << "PoolRawAccess::getEntry: Array position: " << + // index * size_of_type << " Size of T: " << (int)size_of_type << + // " ByteSize: " << byte_size << " Position: " << *size << std::endl; + if (typeSize == 0) + return DATA_POOL_ACCESS_FAILED; + if (typeSize > max_size) + return INCORRECT_SIZE; + EndianConverter::convertBigEndian(buffer, data_ptr, typeSize); + *writtenBytes = typeSize; + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const { + if (typeSize + *size <= maxSize) { + switch(streamEndianness) { + case(Endianness::BIG): + EndianConverter::convertBigEndian(*buffer, value, typeSize); + break; + case(Endianness::LITTLE): + EndianConverter::convertLittleEndian(*buffer, value, typeSize); + break; + case(Endianness::MACHINE): + default: + memcpy(*buffer, value, typeSize); + break; + } + *size += typeSize; + (*buffer) += typeSize; + return HasReturnvaluesIF::RETURN_OK; + } else { + return SerializeIF::BUFFER_TOO_SHORT; + } +} + + +Type PoolRawAccess::getType() { + return type; +} + +size_t PoolRawAccess::getSizeOfType() { + return typeSize; +} + +size_t PoolRawAccess::getArraySize(){ + return arraySize; +} + +uint32_t PoolRawAccess::getDataPoolId() const { + return dataPoolId; +} + +PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const { + return readWriteMode; +} + +ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer, + size_t setSize) { + if (typeSize == setSize) { + EndianConverter::convertBigEndian(value, buffer, typeSize); + return HasReturnvaluesIF::RETURN_OK; + } else { + sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: " + "Internal" << (uint32_t) typeSize << ", Requested: " << setSize + << std::endl; + return INCORRECT_SIZE; + } +} + +bool PoolRawAccess::isValid() const { + if (valid != INVALID) + return true; + else + return false; +} + +void PoolRawAccess::setValid(bool valid) { + this->valid = valid; +} + +size_t PoolRawAccess::getSizeTillEnd() const { + return sizeTillEnd; +} + + +size_t PoolRawAccess::getSerializedSize() const { + return typeSize; +} + +ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) { + + if (*size >= typeSize) { + switch(streamEndianness) { + case(Endianness::BIG): + EndianConverter::convertBigEndian(value, *buffer, typeSize); + break; + case(Endianness::LITTLE): + EndianConverter::convertLittleEndian(value, *buffer, typeSize); + break; + case(Endianness::MACHINE): + default: + memcpy(value, *buffer, typeSize); + break; + } + *size -= typeSize; + *buffer += typeSize; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SerializeIF::STREAM_TOO_SHORT; + } +} diff --git a/datapoolglob/PoolRawAccess.h b/datapoolglob/PoolRawAccess.h new file mode 100644 index 000000000..22dc312d7 --- /dev/null +++ b/datapoolglob/PoolRawAccess.h @@ -0,0 +1,220 @@ +#ifndef POOLRAWACCESS_H_ +#define POOLRAWACCESS_H_ + +#include +#include +#include +#include + +/** + * @brief This class allows accessing Data Pool variables as raw bytes. + * @details + * This is necessary to have an access method for HK data, as the PID's alone + * do not provide type information. Please note that the the raw pool access + * read() and commit() calls are not thread-safe. + * + * Please supply a data set and use the data set read(), commit() calls for + * thread-safe data pool access. + * @ingroup data_pool + */ +class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF { +public: + /** + * This constructor is used to access a data pool entry with a + * given ID if the target type is not known. A DataSet object is supplied + * and the data pool entry with the given ID is registered to that data set. + * Please note that a pool raw access buffer only has a buffer + * with a size of double. As such, for vector entries which have + * @param data_pool_id Target data pool entry ID + * @param arrayEntry + * @param data_set Dataset to register data pool entry to + * @param setReadWriteMode + * @param registerVectors If set to true, the constructor checks if + * there are multiple vector entries to registers + * and registers all of them recursively into the data_set + * + */ + PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry, + DataSetIF* data_set, ReadWriteMode_t setReadWriteMode = + PoolVariableIF::VAR_READ); + + /** + * @brief This operation returns a pointer to the entry fetched. + * @details Return pointer to the buffer containing the raw data + * Size and number of data can be retrieved by other means. + */ + uint8_t* getEntry(); + /** + * @brief This operation returns the fetched entry from the data pool and + * flips the bytes, if necessary. + * @details It makes use of the getEntry call of this function, but additionally flips the + * bytes to big endian, which is the default for external communication (as House- + * keeping telemetry). To achieve this, the data is copied directly to the passed + * buffer, if it fits in the given max_size. + * @param buffer A pointer to a buffer to write to + * @param writtenBytes The number of bytes written is returned with this value. + * @param max_size The maximum size that the function may write to buffer. + * @return - @c RETURN_OK if entry could be acquired + * - @c RETURN_FAILED else. + */ + ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size, + size_t maxSize); + + /** + * @brief Serialize raw pool entry into provided buffer directly + * @param buffer Provided buffer. Raw pool data will be copied here + * @param size [out] Increment provided size value by serialized size + * @param max_size Maximum allowed serialization size + * @param bigEndian Specify endianess + * @return - @c RETURN_OK if serialization was successfull + * - @c SerializeIF::BUFFER_TOO_SHORT if range check failed + */ + ReturnValue_t serialize(uint8_t **buffer, size_t *size, + size_t maxSize, Endianness streamEndianness) const override; + + size_t getSerializedSize() const override; + + ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, + Endianness streamEndianness) override; + + /** + * With this method, the content can be set from a big endian buffer safely. + * @param buffer Pointer to the data to set + * @param size Size of the data to write. Must fit this->size. + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer, + size_t setSize); + /** + * @brief This operation returns the type of the entry currently stored. + */ + Type getType(); + /** + * @brief This operation returns the size of the entry currently stored. + */ + size_t getSizeOfType(); + /** + * + * @return the size of the datapool array + */ + size_t getArraySize(); + /** + * @brief This operation returns the data pool id of the variable. + */ + uint32_t getDataPoolId() const; + + static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS; + static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02); + static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04); + static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05); + static const uint8_t RAW_MAX_SIZE = sizeof(double); + uint8_t value[RAW_MAX_SIZE]; + + + /** + * @brief The classes destructor is empty. If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~PoolRawAccess(); + + /** + * This method returns if the variable is read-write or read-only. + */ + ReadWriteMode_t getReadWriteMode() const; + /** + * @brief With this call, the valid information of the variable is returned. + */ + bool isValid() const; + + void setValid(bool valid); + /** + * Getter for the remaining size. + */ + size_t getSizeTillEnd() const; + + /** + * @brief This is a call to read the value from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies the value and the valid + * information to its local attributes. In case of a failure (wrong type or + * pool id not found), the variable is set to zero and invalid. + * The call is protected by a lock of the global data pool. + * @return -@c RETURN_OK Read successfull + * -@c READ_TYPE_TOO_LARGE + * -@c READ_INDEX_TOO_LARGE + * -@c READ_ENTRY_NON_EXISTENT + */ + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call writes back the variable's value to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The call is protected by a lock of the global data pool. + * + */ + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + + ReturnValue_t handleReadOut(PoolEntryIF* read_out); + void handleReadError(ReturnValue_t result); +private: + /** + * @brief To access the correct data pool entry on read and commit calls, the data pool id + * is stored. + */ + uint32_t dataPoolId; + /** + * @brief The array entry that is fetched from the data pool. + */ + uint8_t arrayEntry; + /** + * @brief The valid information as it was stored in the data pool is copied to this attribute. + */ + uint8_t valid; + /** + * @brief This value contains the type of the data pool entry. + */ + Type type; + /** + * @brief This value contains the size of the data pool entry type in bytes. + */ + size_t typeSize; + /** + * The size of the DP array (single values return 1) + */ + size_t arraySize; + /** + * The size (in bytes) from the selected entry till the end of this DataPool variable. + */ + size_t sizeTillEnd; + /** + * @brief The information whether the class is read-write or read-only is stored here. + */ + ReadWriteMode_t readWriteMode; +}; + +#endif /* POOLRAWACCESS_H_ */ -- 2.34.1 From 3a4e4ddff05b47659695ad534d533a92cb3446eb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 16 Jul 2020 13:18:37 +0200 Subject: [PATCH 2/8] implemented splitting of global and local datapool files --- datapool/DataSetBase.h | 6 +++--- datapoolglob/GlobalDataPool.h | 2 +- datapoolglob/GlobalDataSet.h | 4 ++-- datapoolglob/GlobalPoolVector.h | 5 +++-- datapoolglob/PoolRawAccess.h | 4 ++-- devicehandlers/DeviceHandlerBase.cpp | 24 ++++++++++++------------ framework.mk | 1 + internalError/InternalErrorReporter.cpp | 12 ++++++------ monitoring/MonitorBase.h | 6 +++--- power/Fuse.cpp | 2 +- power/Fuse.h | 9 +++++---- power/PowerSensor.h | 10 +++++----- thermal/CoreComponent.cpp | 12 ++++++------ thermal/CoreComponent.h | 14 +++++++------- thermal/ThermalComponent.cpp | 6 +++--- thermal/ThermalComponent.h | 2 +- thermal/ThermalModule.cpp | 8 ++++---- thermal/ThermalModule.h | 14 +++++++------- 18 files changed, 72 insertions(+), 69 deletions(-) diff --git a/datapool/DataSetBase.h b/datapool/DataSetBase.h index cc16aa9e5..41ab0e635 100644 --- a/datapool/DataSetBase.h +++ b/datapool/DataSetBase.h @@ -60,7 +60,7 @@ public: * commit() in between */ virtual ReturnValue_t read(uint32_t lockTimeout = - MutexIF::BLOCKING) override; + MutexIF::NO_TIMEOUT) override; /** * @brief The commit call initializes writing back the registered variables. * @details @@ -80,7 +80,7 @@ public: * contains non write-only variables */ virtual ReturnValue_t commit(uint32_t lockTimeout = - MutexIF::BLOCKING) override; + MutexIF::NO_TIMEOUT) override; /** * Register the passed pool variable instance into the data set. @@ -94,7 +94,7 @@ public: * @return Always returns -@c RETURN_OK */ virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = - MutexIF::BLOCKING) override; + MutexIF::NO_TIMEOUT) override; /** * Provides the means to unlock the underlying data structure to ensure * thread-safety. Default implementation is empty diff --git a/datapoolglob/GlobalDataPool.h b/datapoolglob/GlobalDataPool.h index b9c1436fb..b349fb603 100644 --- a/datapoolglob/GlobalDataPool.h +++ b/datapoolglob/GlobalDataPool.h @@ -95,7 +95,7 @@ public: * @brief This is a small helper function to facilitate locking the global data pool. * @details It fetches the pool's mutex id and tries to acquire the mutex. */ - ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING); + ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::NO_TIMEOUT); /** * @brief This is a small helper function to facilitate unlocking the global data pool. * @details It fetches the pool's mutex id and tries to free the mutex. diff --git a/datapoolglob/GlobalDataSet.h b/datapoolglob/GlobalDataSet.h index d237cc1b4..7efe8244a 100644 --- a/datapoolglob/GlobalDataSet.h +++ b/datapoolglob/GlobalDataSet.h @@ -44,8 +44,8 @@ public: * - @c COMMITING_WITHOUT_READING if set was not read yet and * contains non write-only variables */ - ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::BLOCKING); - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::NO_TIMEOUT); + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; /** * Set all entries diff --git a/datapoolglob/GlobalPoolVector.h b/datapoolglob/GlobalPoolVector.h index 0e03f77db..bb883634f 100644 --- a/datapoolglob/GlobalPoolVector.h +++ b/datapoolglob/GlobalPoolVector.h @@ -6,6 +6,7 @@ #include #include #include +#include /** * @brief This is the access class for array-type data pool entries. @@ -127,7 +128,7 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t read(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; /** * @brief The commit call copies the array values back to the data pool. * @details @@ -137,7 +138,7 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; protected: /** diff --git a/datapoolglob/PoolRawAccess.h b/datapoolglob/PoolRawAccess.h index 22dc312d7..0571d8b4c 100644 --- a/datapoolglob/PoolRawAccess.h +++ b/datapoolglob/PoolRawAccess.h @@ -148,7 +148,7 @@ public: * -@c READ_INDEX_TOO_LARGE * -@c READ_ENTRY_NON_EXISTENT */ - ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t read(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; /** * @brief The commit call writes back the variable's value to the data pool. * @details @@ -157,7 +157,7 @@ public: * The call is protected by a lock of the global data pool. * */ - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; protected: /** diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 872310a1a..e272090ac 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -4,8 +4,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -167,8 +167,8 @@ ReturnValue_t DeviceHandlerBase::initialize() { fillCommandAndReplyMap(); //Set temperature target state to NON_OP. - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_WRITE); mySet.read(); thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; @@ -436,8 +436,8 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { Clock::getUptime(&timeoutStart); if (mode == MODE_OFF) { - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -894,10 +894,10 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, if ((commandedMode == MODE_ON) && (mode == MODE_OFF) && (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) { - DataSet mySet; - PoolVariable thermalState(deviceThermalStatePoolId, &mySet, + GlobDataSet mySet; + gp_int8_t thermalState(deviceThermalStatePoolId, &mySet, PoolVariableIF::VAR_READ); - PoolVariable thermalRequest(deviceThermalRequestPoolId, &mySet, + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -924,8 +924,8 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON); triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); - DataSet mySet; - PoolVariable thermalRequest(deviceThermalRequestPoolId, + GlobDataSet mySet; + gp_int8_t thermalRequest(deviceThermalRequestPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { @@ -1141,7 +1141,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, } //Try to cast to DataSet and commit data. if (!neverInDataPool) { - DataSet* dataSet = dynamic_cast(data); + GlobDataSet* dataSet = dynamic_cast(data); if (dataSet != NULL) { dataSet->commit(PoolVariableIF::VALID); } diff --git a/framework.mk b/framework.mk index a5a653641..05265c7bc 100644 --- a/framework.mk +++ b/framework.mk @@ -8,6 +8,7 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 9a8ede002..ec69108a4 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -1,7 +1,7 @@ #include "InternalErrorReporter.h" -#include -#include +#include +#include #include #include @@ -21,13 +21,13 @@ InternalErrorReporter::~InternalErrorReporter() { ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { - DataSet mySet; - PoolVariable queueHitsInPool(queuePoolId, &mySet, + GlobDataSet mySet; + gp_uint32_t queueHitsInPool(queuePoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); - PoolVariable tmHitsInPool(tmPoolId, &mySet, + gp_uint32_t tmHitsInPool(tmPoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); - PoolVariable storeHitsInPool(storePoolId, &mySet, + gp_uint32_t storeHitsInPool(storePoolId, &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); diff --git a/monitoring/MonitorBase.h b/monitoring/MonitorBase.h index 796226452..f18ca4b5c 100644 --- a/monitoring/MonitorBase.h +++ b/monitoring/MonitorBase.h @@ -1,8 +1,8 @@ #ifndef MONITORBASE_H_ #define MONITORBASE_H_ -#include -#include +#include +#include #include #include #include @@ -48,7 +48,7 @@ public: protected: virtual ReturnValue_t fetchSample(T* sample) { - DataSet mySet; + GlobDataSet mySet; PIDReader parameter(this->parameterId, &mySet); mySet.read(); if (!parameter.isValid()) { diff --git a/power/Fuse.cpp b/power/Fuse.cpp index db24100bd..eabd6e70b 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -12,7 +12,7 @@ Fuse::Fuse(object_id_t fuseObjectId, uint8_t fuseId, VariableIds ids, SystemObject(fuseObjectId), oldFuseState(0), fuseId(fuseId), powerIF( NULL), currentLimit(fuseObjectId, 1, ids.pidCurrent, confirmationCount, maxCurrent, FUSE_CURRENT_HIGH), powerMonitor(fuseObjectId, 2, - DataPool::poolIdAndPositionToPid(ids.poolIdPower, 0), + GlobalDataPool::poolIdAndPositionToPid(ids.poolIdPower, 0), confirmationCount), set(), voltage(ids.pidVoltage, &set), current( ids.pidCurrent, &set), state(ids.pidState, &set), power( ids.poolIdPower, &set, PoolVariableIF::VAR_READ_WRITE), commandQueue( diff --git a/power/Fuse.h b/power/Fuse.h index 4e22e3ed0..e105e84b3 100644 --- a/power/Fuse.h +++ b/power/Fuse.h @@ -1,8 +1,9 @@ #ifndef FUSE_H_ #define FUSE_H_ -#include -#include +#include +#include +#include #include #include #include @@ -84,11 +85,11 @@ private: }; PowerMonitor powerMonitor; - DataSet set; + GlobDataSet set; PIDReader voltage; PIDReader current; PIDReader state; - db_float_t power; + gp_float_t power; MessageQueueIF *commandQueue; ParameterHelper parameterHelper; HealthHelper healthHelper; diff --git a/power/PowerSensor.h b/power/PowerSensor.h index 922560d07..159bc7ff9 100644 --- a/power/PowerSensor.h +++ b/power/PowerSensor.h @@ -1,9 +1,9 @@ #ifndef POWERSENSOR_H_ #define POWERSENSOR_H_ -#include -#include -#include +#include +#include +#include #include #include #include @@ -53,12 +53,12 @@ private: MessageQueueIF* commandQueue; ParameterHelper parameterHelper; HealthHelper healthHelper; - DataSet set; + GlobDataSet set; //Variables in PIDReader current; PIDReader voltage; //Variables out - db_float_t power; + gp_float_t power; static const uint8_t MODULE_ID_CURRENT = 1; static const uint8_t MODULE_ID_VOLTAGE = 2; diff --git a/thermal/CoreComponent.cpp b/thermal/CoreComponent.cpp index 304712ef8..0c74a7f0b 100644 --- a/thermal/CoreComponent.cpp +++ b/thermal/CoreComponent.cpp @@ -2,7 +2,7 @@ CoreComponent::CoreComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, - uint32_t currentStatePoolId, uint32_t requestPoolId, DataSet* dataSet, + uint32_t currentStatePoolId, uint32_t requestPoolId, GlobDataSet* dataSet, AbstractTemperatureSensor* sensor, AbstractTemperatureSensor* firstRedundantSensor, AbstractTemperatureSensor* secondRedundantSensor, @@ -18,14 +18,14 @@ CoreComponent::CoreComponent(object_id_t reportingObjectId, uint8_t domainId, AbstractTemperatureSensor::ZERO_KELVIN_C), parameters( parameters), temperatureMonitor(reportingObjectId, domainId + 1, - DataPool::poolIdAndPositionToPid(temperaturePoolId, 0), + GlobalDataPool::poolIdAndPositionToPid(temperaturePoolId, 0), COMPONENT_TEMP_CONFIRMATION), domainId(domainId) { if (thermalModule != NULL) { thermalModule->registerComponent(this, priority); } //Set thermal state once, then leave to operator. - DataSet mySet; - PoolVariable writableTargetState(targetStatePoolId, &mySet, + GlobDataSet mySet; + gp_int8_t writableTargetState(targetStatePoolId, &mySet, PoolVariableIF::VAR_WRITE); writableTargetState = initialTargetState; mySet.commit(PoolVariableIF::VALID); @@ -70,8 +70,8 @@ float CoreComponent::getLowerOpLimit() { } ReturnValue_t CoreComponent::setTargetState(int8_t newState) { - DataSet mySet; - PoolVariable writableTargetState(targetState.getDataPoolId(), + GlobDataSet mySet; + gp_int8_t writableTargetState(targetState.getDataPoolId(), &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if ((writableTargetState == STATE_REQUEST_OPERATIONAL) diff --git a/thermal/CoreComponent.h b/thermal/CoreComponent.h index f7e7aff8d..ed89ff48d 100644 --- a/thermal/CoreComponent.h +++ b/thermal/CoreComponent.h @@ -1,8 +1,8 @@ #ifndef MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ #define MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ -#include -#include +#include +#include #include #include #include @@ -22,7 +22,7 @@ public: CoreComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint32_t currentStatePoolId, - uint32_t requestPoolId, DataSet *dataSet, + uint32_t requestPoolId, GlobDataSet *dataSet, AbstractTemperatureSensor *sensor, AbstractTemperatureSensor *firstRedundantSensor, AbstractTemperatureSensor *secondRedundantSensor, @@ -57,10 +57,10 @@ protected: AbstractTemperatureSensor *secondRedundantSensor; ThermalModuleIF *thermalModule; - db_float_t temperature; - db_int8_t targetState; - db_int8_t currentState; - db_uint8_t heaterRequest; + gp_float_t temperature; + gp_int8_t targetState; + gp_int8_t currentState; + gp_uint8_t heaterRequest; bool isHeating; diff --git a/thermal/ThermalComponent.cpp b/thermal/ThermalComponent.cpp index 5dcd0bc64..75107a2eb 100644 --- a/thermal/ThermalComponent.cpp +++ b/thermal/ThermalComponent.cpp @@ -3,7 +3,7 @@ ThermalComponent::ThermalComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint32_t currentStatePoolId, - uint32_t requestPoolId, DataSet* dataSet, + uint32_t requestPoolId, GlobDataSet* dataSet, AbstractTemperatureSensor* sensor, AbstractTemperatureSensor* firstRedundantSensor, AbstractTemperatureSensor* secondRedundantSensor, @@ -24,8 +24,8 @@ ThermalComponent::~ThermalComponent() { } ReturnValue_t ThermalComponent::setTargetState(int8_t newState) { - DataSet mySet; - PoolVariable writableTargetState(targetState.getDataPoolId(), + GlobDataSet mySet; + gp_int8_t writableTargetState(targetState.getDataPoolId(), &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if ((writableTargetState == STATE_REQUEST_OPERATIONAL) diff --git a/thermal/ThermalComponent.h b/thermal/ThermalComponent.h index 932438684..c70fcdab3 100644 --- a/thermal/ThermalComponent.h +++ b/thermal/ThermalComponent.h @@ -20,7 +20,7 @@ public: }; ThermalComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint32_t currentStatePoolId, uint32_t requestPoolId, - DataSet *dataSet, AbstractTemperatureSensor *sensor, + GlobDataSet *dataSet, AbstractTemperatureSensor *sensor, AbstractTemperatureSensor *firstRedundantSensor, AbstractTemperatureSensor *secondRedundantSensor, ThermalModuleIF *thermalModule, Parameters parameters, diff --git a/thermal/ThermalModule.cpp b/thermal/ThermalModule.cpp index 24a4c90d9..9dc1f2372 100644 --- a/thermal/ThermalModule.cpp +++ b/thermal/ThermalModule.cpp @@ -6,7 +6,7 @@ ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, uint32_t currentStatePoolId, uint32_t targetStatePoolId, - DataSet *dataSet, Parameters parameters, + GlobDataSet *dataSet, Parameters parameters, RedundantHeater::Parameters heaterParameters) : oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( false), parameters(parameters), moduleTemperature( @@ -16,7 +16,7 @@ ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, heater = new RedundantHeater(heaterParameters); } -ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, DataSet* dataSet) : +ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, GlobDataSet* dataSet) : oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( false), parameters( { 0, 0 }), moduleTemperature( moduleTemperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), heater( @@ -250,8 +250,8 @@ bool ThermalModule::calculateModuleHeaterRequestAndSetModuleStatus( } void ThermalModule::setHeating(bool on) { - DataSet mySet; - PoolVariable writableTargetState(targetState.getDataPoolId(), + GlobDataSet mySet; + gp_int8_t writableTargetState(targetState.getDataPoolId(), &mySet, PoolVariableIF::VAR_WRITE); if (on) { writableTargetState = STATE_REQUEST_HEATING; diff --git a/thermal/ThermalModule.h b/thermal/ThermalModule.h index d8ac7d732..8a4d0cdb7 100644 --- a/thermal/ThermalModule.h +++ b/thermal/ThermalModule.h @@ -1,8 +1,8 @@ #ifndef THERMALMODULE_H_ #define THERMALMODULE_H_ -#include -#include +#include +#include #include #include #include "ThermalModuleIF.h" @@ -20,10 +20,10 @@ public: }; ThermalModule(uint32_t moduleTemperaturePoolId, uint32_t currentStatePoolId, - uint32_t targetStatePoolId, DataSet *dataSet, Parameters parameters, + uint32_t targetStatePoolId, GlobDataSet *dataSet, Parameters parameters, RedundantHeater::Parameters heaterParameters); - ThermalModule(uint32_t moduleTemperaturePoolId, DataSet *dataSet); + ThermalModule(uint32_t moduleTemperaturePoolId, GlobDataSet *dataSet); virtual ~ThermalModule(); @@ -67,12 +67,12 @@ protected: Parameters parameters; - db_float_t moduleTemperature; + gp_float_t moduleTemperature; RedundantHeater *heater; - db_int8_t currentState; - db_int8_t targetState; + gp_int8_t currentState; + gp_int8_t targetState; std::list sensors; std::list components; -- 2.34.1 From d61c6d1e6033ba037d2706ffd4d8ddf47dd7a91e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:29:18 +0200 Subject: [PATCH 3/8] controller set update --- datapool/ControllerSet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datapool/ControllerSet.h b/datapool/ControllerSet.h index 7625c3d1b..43e1cbf21 100644 --- a/datapool/ControllerSet.h +++ b/datapool/ControllerSet.h @@ -1,7 +1,7 @@ #ifndef CONTROLLERSET_H_ #define CONTROLLERSET_H_ -#include +#include "../datapoolglob/GlobalDataSet.h" class ControllerSet :public GlobDataSet { public: -- 2.34.1 From ff8881348cfd1b2b26ad06b787634eaa553751f9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:31:40 +0200 Subject: [PATCH 4/8] updates 3 core folders --- datapool/ControllerSet.cpp | 2 +- datapool/DataSetIF.h | 22 +- datapool/HkSwitchHelper.cpp | 4 +- datapool/HkSwitchHelper.h | 6 +- datapool/PoolDataSetBase.cpp | 169 ++++++++++ datapool/PoolDataSetBase.h | 151 +++++++++ datapool/PoolDataSetIF.h | 28 ++ datapool/PoolEntry.cpp | 6 +- datapool/PoolEntry.h | 2 +- datapool/PoolEntryIF.h | 2 +- datapool/PoolRawAccessHelper.cpp | 376 +++++++++++----------- datapool/PoolRawAccessHelper.h | 222 ++++++------- datapool/PoolVarList.h | 4 +- datapool/PoolVariableIF.h | 8 +- datapool/SharedDataSetIF.h | 14 + datapoolglob/DataPoolAdmin.cpp | 14 +- datapoolglob/DataPoolAdmin.h | 18 +- datapoolglob/DataPoolParameterWrapper.cpp | 8 +- datapoolglob/DataPoolParameterWrapper.h | 4 +- datapoolglob/GlobalDataPool.cpp | 9 +- datapoolglob/GlobalDataPool.h | 8 +- datapoolglob/GlobalDataSet.cpp | 14 +- datapoolglob/GlobalDataSet.h | 10 +- datapoolglob/GlobalPoolVariable.h | 14 +- datapoolglob/GlobalPoolVector.h | 17 +- datapoolglob/PIDReader.h | 12 +- datapoolglob/PIDReaderList.h | 4 +- datapoolglob/PoolRawAccess.cpp | 8 +- datapoolglob/PoolRawAccess.h | 12 +- datapoollocal/HasLocalDataPoolIF.h | 92 ++++++ datapoollocal/LocalDataPoolManager.cpp | 305 ++++++++++++++++++ datapoollocal/LocalDataPoolManager.h | 282 ++++++++++++++++ datapoollocal/LocalDataSet.cpp | 22 ++ datapoollocal/LocalDataSet.h | 20 ++ datapoollocal/LocalPoolDataSetBase.cpp | 193 +++++++++++ datapoollocal/LocalPoolDataSetBase.h | 133 ++++++++ datapoollocal/LocalPoolVariable.h | 176 ++++++++++ datapoollocal/LocalPoolVariable.tpp | 168 ++++++++++ datapoollocal/LocalPoolVector.h | 200 ++++++++++++ datapoollocal/LocalPoolVector.tpp | 208 ++++++++++++ datapoollocal/SharedLocalDataSet.cpp | 16 + datapoollocal/SharedLocalDataSet.h | 31 ++ datapoollocal/StaticLocalDataSet.h | 27 ++ 43 files changed, 2634 insertions(+), 407 deletions(-) create mode 100644 datapool/PoolDataSetBase.cpp create mode 100644 datapool/PoolDataSetBase.h create mode 100644 datapool/PoolDataSetIF.h create mode 100644 datapool/SharedDataSetIF.h create mode 100644 datapoollocal/HasLocalDataPoolIF.h create mode 100644 datapoollocal/LocalDataPoolManager.cpp create mode 100644 datapoollocal/LocalDataPoolManager.h create mode 100644 datapoollocal/LocalDataSet.cpp create mode 100644 datapoollocal/LocalDataSet.h create mode 100644 datapoollocal/LocalPoolDataSetBase.cpp create mode 100644 datapoollocal/LocalPoolDataSetBase.h create mode 100644 datapoollocal/LocalPoolVariable.h create mode 100644 datapoollocal/LocalPoolVariable.tpp create mode 100644 datapoollocal/LocalPoolVector.h create mode 100644 datapoollocal/LocalPoolVector.tpp create mode 100644 datapoollocal/SharedLocalDataSet.cpp create mode 100644 datapoollocal/SharedLocalDataSet.h create mode 100644 datapoollocal/StaticLocalDataSet.h diff --git a/datapool/ControllerSet.cpp b/datapool/ControllerSet.cpp index eb4f6d0fd..4055158bc 100644 --- a/datapool/ControllerSet.cpp +++ b/datapool/ControllerSet.cpp @@ -1,4 +1,4 @@ -#include +#include "../datapool/ControllerSet.h" ControllerSet::ControllerSet() { diff --git a/datapool/DataSetIF.h b/datapool/DataSetIF.h index 437f324f6..b51da3a47 100644 --- a/datapool/DataSetIF.h +++ b/datapool/DataSetIF.h @@ -1,8 +1,8 @@ #ifndef DATASETIF_H_ #define DATASETIF_H_ -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../timemanager/Clock.h" class PoolVariableIF; /** @@ -34,8 +34,7 @@ public: */ virtual ~DataSetIF() {} - virtual ReturnValue_t read(uint32_t lockTimeout) = 0; - virtual ReturnValue_t commit(uint32_t lockTimeout) = 0; + /** * @brief This operation provides a method to register local data pool * variables to register in a data set by passing itself @@ -44,19 +43,6 @@ public: virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0; virtual uint16_t getFillCount() const = 0; -private: - /** - * @brief Most underlying data structures will have a pool like structure - * and will require a lock and unlock mechanism to ensure - * thread-safety - * @return Lock operation result - */ - virtual ReturnValue_t lockDataPool(uint32_t timeoutMs) = 0; - /** - * @brief Unlock call corresponding to the lock call. - * @return Unlock operation result - */ - virtual ReturnValue_t unlockDataPool() = 0; }; -#endif /* DATASETIF_H_ */ +#endif /* FRAMEWORK_DATAPOOL_DATASETIF_H_ */ diff --git a/datapool/HkSwitchHelper.cpp b/datapool/HkSwitchHelper.cpp index cf5114f75..1a2a25eb9 100644 --- a/datapool/HkSwitchHelper.cpp +++ b/datapool/HkSwitchHelper.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../datapool/HkSwitchHelper.h" +#include "../ipc/QueueFactory.h" HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) : commandActionHelper(this), eventProxy(eventProxy) { diff --git a/datapool/HkSwitchHelper.h b/datapool/HkSwitchHelper.h index 1a3b62758..385b2047f 100644 --- a/datapool/HkSwitchHelper.h +++ b/datapool/HkSwitchHelper.h @@ -1,9 +1,9 @@ #ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ #define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ -#include -#include -#include +#include "../tasks/ExecutableObjectIF.h" +#include "../action/CommandsActionsIF.h" +#include "../events/EventReportingProxyIF.h" //TODO this class violations separation between mission and framework //but it is only a transitional solution until the Datapool is diff --git a/datapool/PoolDataSetBase.cpp b/datapool/PoolDataSetBase.cpp new file mode 100644 index 000000000..1acd3fd3b --- /dev/null +++ b/datapool/PoolDataSetBase.cpp @@ -0,0 +1,169 @@ +#include "PoolDataSetBase.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxFillCount): + registeredVariables(registeredVariablesArray), + maxFillCount(maxFillCount) { +} + +PoolDataSetBase::~PoolDataSetBase() {} + +ReturnValue_t PoolDataSetBase::registerVariable( + PoolVariableIF *variable) { + if (state != States::DATA_SET_UNINITIALISED) { + sif::error << "DataSet::registerVariable: " + "Call made in wrong position." << std::endl; + return DataSetIF::DATA_SET_UNINITIALISED; + } + if (variable == nullptr) { + sif::error << "DataSet::registerVariable: " + "Pool variable is nullptr." << std::endl; + return DataSetIF::POOL_VAR_NULL; + } + if (fillCount >= maxFillCount) { + sif::error << "DataSet::registerVariable: " + "DataSet is full." << std::endl; + return DataSetIF::DATA_SET_FULL; + } + registeredVariables[fillCount] = variable; + fillCount++; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PoolDataSetBase::read(uint32_t lockTimeout) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + if (state == States::DATA_SET_UNINITIALISED) { + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + result = readVariable(count); + if(result != RETURN_OK) { + break; + } + } + state = States::DATA_SET_WAS_READ; + unlockDataPool(); + } + else { + sif::error << "DataSet::read(): " + "Call made in wrong position. Don't forget to commit" + " member datasets!" << std::endl; + result = SET_WAS_ALREADY_READ; + } + return result; +} + +uint16_t PoolDataSetBase::getFillCount() const { + return fillCount; +} + +ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + // These checks are often performed by the respective + // variable implementation too, but I guess a double check does not hurt. + if (registeredVariables[count]->getReadWriteMode() != + PoolVariableIF::VAR_WRITE and + registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) + { + result = registeredVariables[count]->readWithoutLock(); + if(result != HasReturnvaluesIF::RETURN_OK) { + result = INVALID_PARAMETER_DEFINITION; + } + } + return result; +} + +ReturnValue_t PoolDataSetBase::commit(uint32_t lockTimeout) { + if (state == States::DATA_SET_WAS_READ) { + handleAlreadyReadDatasetCommit(lockTimeout); + return HasReturnvaluesIF::RETURN_OK; + } + else { + return handleUnreadDatasetCommit(lockTimeout); + } +} + +void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + != PoolVariableIF::VAR_READ + && registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + registeredVariables[count]->commitWithoutLock(); + } + } + state = States::DATA_SET_UNINITIALISED; + unlockDataPool(); +} + +ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + lockDataPool(lockTimeout); + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->getReadWriteMode() + == PoolVariableIF::VAR_WRITE + && registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + registeredVariables[count]->commitWithoutLock(); + } else if (registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) { + if (result != COMMITING_WITHOUT_READING) { + sif::error << "DataSet::commit(): commit-without-read call made " + "with non write-only variable." << std::endl; + result = COMMITING_WITHOUT_READING; + } + } + } + state = States::DATA_SET_UNINITIALISED; + unlockDataPool(); + return result; +} + + +ReturnValue_t PoolDataSetBase::lockDataPool(uint32_t timeoutMs) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PoolDataSetBase::unlockDataPool() { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->serialize(buffer, size, maxSize, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->deSerialize(buffer, size, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + return result; +} + +size_t PoolDataSetBase::getSerializedSize() const { + uint32_t size = 0; + for (uint16_t count = 0; count < fillCount; count++) { + size += registeredVariables[count]->getSerializedSize(); + } + return size; +} + +void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) { + this->registeredVariables = variablesContainer; +} diff --git a/datapool/PoolDataSetBase.h b/datapool/PoolDataSetBase.h new file mode 100644 index 000000000..666624138 --- /dev/null +++ b/datapool/PoolDataSetBase.h @@ -0,0 +1,151 @@ +#ifndef FRAMEWORK_DATAPOOL_DATASETBASE_H_ +#define FRAMEWORK_DATAPOOL_DATASETBASE_H_ +#include "../datapool/PoolDataSetIF.h" +#include "../datapool/PoolVariableIF.h" +#include "../ipc/MutexIF.h" + +/** + * @brief The DataSetBase class manages a set of locally checked out variables. + * @details + * This class manages a list, where a set of local variables (or pool variables) + * are registered. They are checked-out (i.e. their values are looked + * up and copied) with the read call. After the user finishes working with the + * pool variables, he can write back all variable values to the pool with + * the commit call. The data set manages locking and freeing the data pool, + * to ensure that all values are read and written back at once. + * + * An internal state manages usage of this class. Variables may only be + * registered before the read call is made, and the commit call only + * after the read call. + * + * If pool variables are writable and not committed until destruction + * of the set, the DataSet class automatically sets the valid flag in the + * data pool to invalid (without) changing the variable's value. + * + * The base class lockDataPool und unlockDataPool implementation are empty + * and should be implemented to protect the underlying pool type. + * @author Bastian Baetz + * @ingroup data_pool + */ +class PoolDataSetBase: public PoolDataSetIF, + public SerializeIF, + public HasReturnvaluesIF { +public: + + /** + * @brief Creates an empty dataset. Use registerVariable or + * supply a pointer to this dataset to PoolVariable + * initializations to register pool variables. + */ + PoolDataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxFillCount); + virtual~ PoolDataSetBase(); + + /** + * @brief The read call initializes reading out all registered variables. + * @details + * It iterates through the list of registered variables and calls all read() + * functions of the registered pool variables (which read out their values + * from the data pool) which are not write-only. + * In case of an error (e.g. a wrong data type, or an invalid data pool id), + * the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned. + * + * The data pool is locked during the whole read operation and + * freed afterwards.The state changes to "was written" after this operation. + * @return + * - @c RETURN_OK if all variables were read successfully. + * - @c INVALID_PARAMETER_DEFINITION if PID, size or type of the + * requested variable is invalid. + * - @c SET_WAS_ALREADY_READ if read() is called twice without calling + * commit() in between + */ + virtual ReturnValue_t read(uint32_t lockTimeout = + MutexIF::BLOCKING) override; + /** + * @brief The commit call initializes writing back the registered variables. + * @details + * It iterates through the list of registered variables and calls the + * commit() method of the remaining registered variables (which write back + * their values to the pool). + * + * The data pool is locked during the whole commit operation and + * freed afterwards. The state changes to "was committed" after this operation. + * + * If the set does contain at least one variable which is not write-only + * commit() can only be called after read(). If the set only contains + * variables which are write only, commit() can be called without a + * preceding read() call. + * @return - @c RETURN_OK if all variables were read successfully. + * - @c COMMITING_WITHOUT_READING if set was not read yet and + * contains non write-only variables + */ + virtual ReturnValue_t commit(uint32_t lockTimeout = + MutexIF::BLOCKING) override; + + /** + * Register the passed pool variable instance into the data set. + * @param variable + * @return + */ + virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override; + /** + * Provides the means to lock the underlying data structure to ensure + * thread-safety. Default implementation is empty + * @return Always returns -@c RETURN_OK + */ + virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = + MutexIF::BLOCKING) override; + /** + * Provides the means to unlock the underlying data structure to ensure + * thread-safety. Default implementation is empty + * @return Always returns -@c RETURN_OK + */ + virtual ReturnValue_t unlockDataPool() override; + + virtual uint16_t getFillCount() const; + + /* SerializeIF implementations */ + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; + +protected: + /** + * @brief The fill_count attribute ensures that the variables + * register in the correct array position and that the maximum + * number of variables is not exceeded. + */ + uint16_t fillCount = 0; + /** + * States of the seet. + */ + enum class States { + DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED + DATA_SET_WAS_READ //!< DATA_SET_WAS_READ + }; + /** + * @brief state manages the internal state of the data set, + * which is important e.g. for the behavior on destruction. + */ + States state = States::DATA_SET_UNINITIALISED; + + /** + * @brief This array represents all pool variables registered in this set. + * Child classes can use a static or dynamic container to create + * an array of registered variables and assign the first entry here. + */ + PoolVariableIF** registeredVariables = nullptr; + const size_t maxFillCount = 0; + + void setContainer(PoolVariableIF** variablesContainer); + +private: + ReturnValue_t readVariable(uint16_t count); + void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); + ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); +}; + +#endif /* FRAMEWORK_DATAPOOL_POOLPOOLDATASETBASE_H_ */ diff --git a/datapool/PoolDataSetIF.h b/datapool/PoolDataSetIF.h new file mode 100644 index 000000000..44ca468bd --- /dev/null +++ b/datapool/PoolDataSetIF.h @@ -0,0 +1,28 @@ +#ifndef FRAMEWORK_DATAPOOL_POOLDATASETIF_H_ +#define FRAMEWORK_DATAPOOL_POOLDATASETIF_H_ +#include "DataSetIF.h" + +class PoolDataSetIF: public DataSetIF { +public: + virtual~ PoolDataSetIF() {}; + + virtual ReturnValue_t read(dur_millis_t lockTimeout) = 0; + virtual ReturnValue_t commit(dur_millis_t lockTimeout) = 0; + + /** + * @brief Most underlying data structures will have a pool like structure + * and will require a lock and unlock mechanism to ensure + * thread-safety + * @return Lock operation result + */ + virtual ReturnValue_t lockDataPool(dur_millis_t timeoutMs) = 0; + /** + * @brief Unlock call corresponding to the lock call. + * @return Unlock operation result + */ + virtual ReturnValue_t unlockDataPool() = 0; + + virtual bool isValid() const = 0; +}; + +#endif /* FRAMEWORK_DATAPOOL_POOLDATASETIF_H_ */ diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index d535a72b6..b0506b824 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../datapool/PoolEntry.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../globalfunctions/arrayprinter.h" #include template diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 1a22bb638..6a3daacf9 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_ #define FRAMEWORK_DATAPOOL_POOLENTRY_H_ -#include +#include "../datapool/PoolEntryIF.h" #include #include diff --git a/datapool/PoolEntryIF.h b/datapool/PoolEntryIF.h index a075436e2..462de18b8 100644 --- a/datapool/PoolEntryIF.h +++ b/datapool/PoolEntryIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ #define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ -#include +#include "../globalfunctions/Type.h" #include /** diff --git a/datapool/PoolRawAccessHelper.cpp b/datapool/PoolRawAccessHelper.cpp index 2324a56cd..3696a21d1 100644 --- a/datapool/PoolRawAccessHelper.cpp +++ b/datapool/PoolRawAccessHelper.cpp @@ -1,188 +1,188 @@ -/** - * @file PoolRawAccessHelper.cpp - * - * @date 22.12.2019 - * @author R. Mueller - */ - -#include -#include -#include -#include - -#include -#include - -PoolRawAccessHelper::PoolRawAccessHelper(uint32_t * poolIdBuffer_, - uint8_t numberOfParameters_): - poolIdBuffer(reinterpret_cast(poolIdBuffer_)), - numberOfParameters(numberOfParameters_), validBufferIndex(0), - validBufferIndexBit(1) { -} - -PoolRawAccessHelper::~PoolRawAccessHelper() { -} - -ReturnValue_t PoolRawAccessHelper::serialize(uint8_t **buffer, size_t *size, - const size_t max_size, SerializeIF::Endianness streamEndianness) { - SerializationArgs serializationArgs = {buffer, size, max_size, - streamEndianness}; - ReturnValue_t result = RETURN_OK; - size_t remainingParametersSize = numberOfParameters * 4; - for(uint8_t count=0; count < numberOfParameters; count++) { - result = serializeCurrentPoolEntryIntoBuffer(serializationArgs, - &remainingParametersSize, false); - if(result != RETURN_OK) { - return result; - } - } - if(remainingParametersSize != 0) { - sif::debug << "PoolRawAccessHelper: " - "Remaining parameters size not 0 !" << std::endl; - result = RETURN_FAILED; - } - return result; -} - -ReturnValue_t PoolRawAccessHelper::serializeWithValidityMask(uint8_t ** buffer, - size_t * size, const size_t max_size, - SerializeIF::Endianness streamEndianness) { - ReturnValue_t result = RETURN_OK; - SerializationArgs argStruct = {buffer, size, max_size, streamEndianness}; - size_t remainingParametersSize = numberOfParameters * 4; - uint8_t validityMaskSize = ceil((float)numberOfParameters/8.0); - uint8_t validityMask[validityMaskSize]; - memset(validityMask,0, validityMaskSize); - for(uint8_t count = 0; count < numberOfParameters; count++) { - result = serializeCurrentPoolEntryIntoBuffer(argStruct, - &remainingParametersSize,true,validityMask); - if (result != RETURN_OK) { - return result; - } - } - if(remainingParametersSize != 0) { - sif::debug << "PoolRawAccessHelper: Remaining " - "parameters size not 0 !" << std::endl; - result = RETURN_FAILED; - } - - memcpy(*argStruct.buffer, validityMask, validityMaskSize); - *size += validityMaskSize; - validBufferIndex = 1; - validBufferIndexBit = 0; - return result; -} - -ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer( - SerializationArgs argStruct, size_t * remainingParameters, - bool withValidMask, uint8_t * validityMask) { - uint32_t currentPoolId; - // Deserialize current pool ID from pool ID buffer - ReturnValue_t result = SerializeAdapter::deSerialize(¤tPoolId, - &poolIdBuffer,remainingParameters, SerializeIF::Endianness::MACHINE); - if(result != RETURN_OK) { - sif::debug << std::hex << "PoolRawAccessHelper: Error deSeralizing " - "pool IDs" << std::dec << std::endl; - return result; - } - result = handlePoolEntrySerialization(currentPoolId, argStruct, - withValidMask, validityMask); - return result; -} - -ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization( - uint32_t currentPoolId,SerializationArgs argStruct, bool withValidMask, - uint8_t * validityMask) { - ReturnValue_t result = RETURN_FAILED; - uint8_t arrayPosition = 0; - uint8_t counter = 0; - bool poolEntrySerialized = false; - //debug << "Pool Raw Access Helper: Handling Pool ID: " - // << std::hex << currentPoolId << std::endl; - while(not poolEntrySerialized) { - - if(counter > GlobDataSet::DATA_SET_MAX_SIZE) { - sif::error << "PoolRawAccessHelper: Config error, " - "max. number of possible data set variables exceeded" - << std::endl; - return result; - } - counter ++; - - GlobDataSet currentDataSet; - //debug << "Current array position: " << (int)arrayPosition << std::endl; - PoolRawAccess currentPoolRawAccess(currentPoolId, arrayPosition, - ¤tDataSet, PoolVariableIF::VAR_READ); - - result = currentDataSet.read(); - if (result != RETURN_OK) { - sif::debug << std::hex << "PoolRawAccessHelper: Error reading raw " - "dataset with returncode 0x" << result << std::dec << std::endl; - return result; - } - - result = checkRemainingSize(¤tPoolRawAccess, &poolEntrySerialized, - &arrayPosition); - if(result != RETURN_OK) { - sif::error << "Pool Raw Access Helper: Configuration Error at pool ID " - << std::hex << currentPoolId - << ". Size till end smaller than 0" << std::dec << std::endl; - return result; - } - - // set valid mask bit if necessary - if(withValidMask) { - if(currentPoolRawAccess.isValid()) { - handleMaskModification(validityMask); - } - validBufferIndexBit ++; - } - - result = currentDataSet.serialize(argStruct.buffer, argStruct.size, - argStruct.max_size, argStruct.streamEndianness); - if (result != RETURN_OK) { - sif::debug << "Pool Raw Access Helper: Error serializing pool data with " - "ID 0x" << std::hex << currentPoolId << " into send buffer " - "with return code " << result << std::dec << std::endl; - return result; - } - - } - return result; -} - -ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess* - currentPoolRawAccess, bool * isSerialized, uint8_t * arrayPosition) { - int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() - - currentPoolRawAccess->getSizeOfType(); - if(remainingSize == 0) { - *isSerialized = true; - } - else if(remainingSize > 0) { - *arrayPosition += 1; - } - else { - return RETURN_FAILED; - } - return RETURN_OK; -} - -void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) { - validityMask[validBufferIndex] = - bitSetter(validityMask[validBufferIndex], validBufferIndexBit, true); - if(validBufferIndexBit == 8) { - validBufferIndex ++; - validBufferIndexBit = 1; - } -} - -uint8_t PoolRawAccessHelper::bitSetter(uint8_t byte, uint8_t position, - bool value) { - if(position < 1 or position > 8) { - sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl; - return byte; - } - uint8_t shiftNumber = position + (6 - 2 * (position - 1)); - byte |= 1UL << shiftNumber; - return byte; -} +/** + * @file PoolRawAccessHelper.cpp + * + * @date 22.12.2019 + * @author R. Mueller + */ + +#include "../datapool/PoolRawAccessHelper.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +#include +#include + +PoolRawAccessHelper::PoolRawAccessHelper(uint32_t * poolIdBuffer_, + uint8_t numberOfParameters_): + poolIdBuffer(reinterpret_cast(poolIdBuffer_)), + numberOfParameters(numberOfParameters_), validBufferIndex(0), + validBufferIndexBit(1) { +} + +PoolRawAccessHelper::~PoolRawAccessHelper() { +} + +ReturnValue_t PoolRawAccessHelper::serialize(uint8_t **buffer, size_t *size, + const size_t max_size, SerializeIF::Endianness streamEndianness) { + SerializationArgs serializationArgs = {buffer, size, max_size, + streamEndianness}; + ReturnValue_t result = RETURN_OK; + size_t remainingParametersSize = numberOfParameters * 4; + for(uint8_t count=0; count < numberOfParameters; count++) { + result = serializeCurrentPoolEntryIntoBuffer(serializationArgs, + &remainingParametersSize, false); + if(result != RETURN_OK) { + return result; + } + } + if(remainingParametersSize != 0) { + sif::debug << "PoolRawAccessHelper: " + "Remaining parameters size not 0 !" << std::endl; + result = RETURN_FAILED; + } + return result; +} + +ReturnValue_t PoolRawAccessHelper::serializeWithValidityMask(uint8_t ** buffer, + size_t * size, const size_t max_size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = RETURN_OK; + SerializationArgs argStruct = {buffer, size, max_size, streamEndianness}; + size_t remainingParametersSize = numberOfParameters * 4; + uint8_t validityMaskSize = ceil((float)numberOfParameters/8.0); + uint8_t validityMask[validityMaskSize]; + memset(validityMask,0, validityMaskSize); + for(uint8_t count = 0; count < numberOfParameters; count++) { + result = serializeCurrentPoolEntryIntoBuffer(argStruct, + &remainingParametersSize,true,validityMask); + if (result != RETURN_OK) { + return result; + } + } + if(remainingParametersSize != 0) { + sif::debug << "PoolRawAccessHelper: Remaining " + "parameters size not 0 !" << std::endl; + result = RETURN_FAILED; + } + + memcpy(*argStruct.buffer, validityMask, validityMaskSize); + *size += validityMaskSize; + validBufferIndex = 1; + validBufferIndexBit = 0; + return result; +} + +ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer( + SerializationArgs argStruct, size_t * remainingParameters, + bool withValidMask, uint8_t * validityMask) { + uint32_t currentPoolId; + // Deserialize current pool ID from pool ID buffer + ReturnValue_t result = SerializeAdapter::deSerialize(¤tPoolId, + &poolIdBuffer,remainingParameters, SerializeIF::Endianness::MACHINE); + if(result != RETURN_OK) { + sif::debug << std::hex << "PoolRawAccessHelper: Error deSeralizing " + "pool IDs" << std::dec << std::endl; + return result; + } + result = handlePoolEntrySerialization(currentPoolId, argStruct, + withValidMask, validityMask); + return result; +} + +ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization( + uint32_t currentPoolId,SerializationArgs argStruct, bool withValidMask, + uint8_t * validityMask) { + ReturnValue_t result = RETURN_FAILED; + uint8_t arrayPosition = 0; + uint8_t counter = 0; + bool poolEntrySerialized = false; + //debug << "Pool Raw Access Helper: Handling Pool ID: " + // << std::hex << currentPoolId << std::endl; + while(not poolEntrySerialized) { + + if(counter > GlobDataSet::DATA_SET_MAX_SIZE) { + sif::error << "PoolRawAccessHelper: Config error, " + "max. number of possible data set variables exceeded" + << std::endl; + return result; + } + counter ++; + + GlobDataSet currentDataSet; + //debug << "Current array position: " << (int)arrayPosition << std::endl; + PoolRawAccess currentPoolRawAccess(currentPoolId, arrayPosition, + ¤tDataSet, PoolVariableIF::VAR_READ); + + result = currentDataSet.read(); + if (result != RETURN_OK) { + sif::debug << std::hex << "PoolRawAccessHelper: Error reading raw " + "dataset with returncode 0x" << result << std::dec << std::endl; + return result; + } + + result = checkRemainingSize(¤tPoolRawAccess, &poolEntrySerialized, + &arrayPosition); + if(result != RETURN_OK) { + sif::error << "Pool Raw Access Helper: Configuration Error at pool ID " + << std::hex << currentPoolId + << ". Size till end smaller than 0" << std::dec << std::endl; + return result; + } + + // set valid mask bit if necessary + if(withValidMask) { + if(currentPoolRawAccess.isValid()) { + handleMaskModification(validityMask); + } + validBufferIndexBit ++; + } + + result = currentDataSet.serialize(argStruct.buffer, argStruct.size, + argStruct.max_size, argStruct.streamEndianness); + if (result != RETURN_OK) { + sif::debug << "Pool Raw Access Helper: Error serializing pool data with " + "ID 0x" << std::hex << currentPoolId << " into send buffer " + "with return code " << result << std::dec << std::endl; + return result; + } + + } + return result; +} + +ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess* + currentPoolRawAccess, bool * isSerialized, uint8_t * arrayPosition) { + int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() - + currentPoolRawAccess->getSizeOfType(); + if(remainingSize == 0) { + *isSerialized = true; + } + else if(remainingSize > 0) { + *arrayPosition += 1; + } + else { + return RETURN_FAILED; + } + return RETURN_OK; +} + +void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) { + validityMask[validBufferIndex] = + bitSetter(validityMask[validBufferIndex], validBufferIndexBit, true); + if(validBufferIndexBit == 8) { + validBufferIndex ++; + validBufferIndexBit = 1; + } +} + +uint8_t PoolRawAccessHelper::bitSetter(uint8_t byte, uint8_t position, + bool value) { + if(position < 1 or position > 8) { + sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl; + return byte; + } + uint8_t shiftNumber = position + (6 - 2 * (position - 1)); + byte |= 1UL << shiftNumber; + return byte; +} diff --git a/datapool/PoolRawAccessHelper.h b/datapool/PoolRawAccessHelper.h index 0d8f8d6d0..db25acdf8 100644 --- a/datapool/PoolRawAccessHelper.h +++ b/datapool/PoolRawAccessHelper.h @@ -1,111 +1,111 @@ -/** - * @file PoolRawAccessHelper.h - * - * @date 22.12.2019 - */ - -#ifndef FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ -#define FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ - -#include -#include -#include - -/** - * @brief This helper function simplifies accessing data pool entries - * via PoolRawAccess - * @details Can be used for a Housekeeping Service - * like ECSS PUS Service 3 if the type of the datapool entries is unknown. - * The provided dataset can be serialized into a provided buffer automatically by - * providing a buffer of pool IDs - * @ingroup data_pool - */ -class PoolRawAccessHelper: public HasReturnvaluesIF { -public: - /** - * Call this constructor if a dataset needs to be serialized via - * Pool Raw Access - * @param dataSet_ This dataset will be used to perform thread-safe reading - * @param poolIdBuffer_ A buffer of uint32_t pool IDs - * @param numberOfParameters_ The number of parameters / pool IDs - */ - PoolRawAccessHelper(uint32_t * poolIdBuffer_, uint8_t numberOfParameters_); - virtual ~PoolRawAccessHelper(); - - /** - * Serialize the datapool entries derived from the pool ID buffer - * directly into a provided buffer - * @param [out] buffer - * @param [out] size Size of the serialized buffer - * @param max_size - * @param bigEndian - * @return @c RETURN_OK On success - * @c RETURN_FAILED on failure - */ - ReturnValue_t serialize(uint8_t ** buffer, size_t * size, - const size_t max_size, SerializeIF::Endianness streamEndianness); - - /** - * Serializes data pool entries into provided buffer with the validity mask buffer - * at the end of the buffer. Every bit of the validity mask denotes - * the validity of a corresponding data pool entry from left to right. - * @param [out] buffer - * @param [out] size Size of the serialized buffer plus size - * of the validity mask - * @return @c RETURN_OK On success - * @c RETURN_FAILED on failure - */ - ReturnValue_t serializeWithValidityMask(uint8_t ** buffer, size_t * size, - const size_t max_size, SerializeIF::Endianness streamEndianness); - - -private: - // DataSet * dataSet; - const uint8_t * poolIdBuffer; - uint8_t numberOfParameters; - - uint8_t validBufferIndex; - uint8_t validBufferIndexBit; - - struct SerializationArgs { - uint8_t ** buffer; - size_t * size; - const size_t max_size; - SerializeIF::Endianness streamEndianness; - }; - /** - * Helper function to serialize single pool entries - * @param pPoolIdBuffer - * @param buffer - * @param remainingParameters - * @param hkDataSize - * @param max_size - * @param bigEndian - * @param withValidMask Can be set optionally to set a - * provided validity mask - * @param validityMask Can be supplied and will be set if - * @c withValidMask is set to true - * @return - */ - ReturnValue_t serializeCurrentPoolEntryIntoBuffer( - SerializationArgs argStruct, size_t * remainingParameters, - bool withValidMask = false, uint8_t * validityMask = nullptr); - - ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId, - SerializationArgs argStruct, bool withValidMask = false, - uint8_t * validityMask = nullptr); - - ReturnValue_t checkRemainingSize(PoolRawAccess * currentPoolRawAccess, - bool * isSerialized, uint8_t * arrayPosition); - void handleMaskModification(uint8_t * validityMask); - /** - * Sets specific bit of a byte - * @param byte - * @param position Position of byte to set from 1 to 8 - * @param value Binary value to set - * @return - */ - uint8_t bitSetter(uint8_t byte, uint8_t position, bool value); -}; - -#endif /* FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ */ +/** + * @file PoolRawAccessHelper.h + * + * @date 22.12.2019 + */ + +#ifndef FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ +#define FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ + +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/PoolRawAccess.h" + +/** + * @brief This helper function simplifies accessing data pool entries + * via PoolRawAccess + * @details Can be used for a Housekeeping Service + * like ECSS PUS Service 3 if the type of the datapool entries is unknown. + * The provided dataset can be serialized into a provided buffer automatically by + * providing a buffer of pool IDs + * @ingroup data_pool + */ +class PoolRawAccessHelper: public HasReturnvaluesIF { +public: + /** + * Call this constructor if a dataset needs to be serialized via + * Pool Raw Access + * @param dataSet_ This dataset will be used to perform thread-safe reading + * @param poolIdBuffer_ A buffer of uint32_t pool IDs + * @param numberOfParameters_ The number of parameters / pool IDs + */ + PoolRawAccessHelper(uint32_t * poolIdBuffer_, uint8_t numberOfParameters_); + virtual ~PoolRawAccessHelper(); + + /** + * Serialize the datapool entries derived from the pool ID buffer + * directly into a provided buffer + * @param [out] buffer + * @param [out] size Size of the serialized buffer + * @param max_size + * @param bigEndian + * @return @c RETURN_OK On success + * @c RETURN_FAILED on failure + */ + ReturnValue_t serialize(uint8_t ** buffer, size_t * size, + const size_t max_size, SerializeIF::Endianness streamEndianness); + + /** + * Serializes data pool entries into provided buffer with the validity mask buffer + * at the end of the buffer. Every bit of the validity mask denotes + * the validity of a corresponding data pool entry from left to right. + * @param [out] buffer + * @param [out] size Size of the serialized buffer plus size + * of the validity mask + * @return @c RETURN_OK On success + * @c RETURN_FAILED on failure + */ + ReturnValue_t serializeWithValidityMask(uint8_t ** buffer, size_t * size, + const size_t max_size, SerializeIF::Endianness streamEndianness); + + +private: + // DataSet * dataSet; + const uint8_t * poolIdBuffer; + uint8_t numberOfParameters; + + uint8_t validBufferIndex; + uint8_t validBufferIndexBit; + + struct SerializationArgs { + uint8_t ** buffer; + size_t * size; + const size_t max_size; + SerializeIF::Endianness streamEndianness; + }; + /** + * Helper function to serialize single pool entries + * @param pPoolIdBuffer + * @param buffer + * @param remainingParameters + * @param hkDataSize + * @param max_size + * @param bigEndian + * @param withValidMask Can be set optionally to set a + * provided validity mask + * @param validityMask Can be supplied and will be set if + * @c withValidMask is set to true + * @return + */ + ReturnValue_t serializeCurrentPoolEntryIntoBuffer( + SerializationArgs argStruct, size_t * remainingParameters, + bool withValidMask = false, uint8_t * validityMask = nullptr); + + ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId, + SerializationArgs argStruct, bool withValidMask = false, + uint8_t * validityMask = nullptr); + + ReturnValue_t checkRemainingSize(PoolRawAccess * currentPoolRawAccess, + bool * isSerialized, uint8_t * arrayPosition); + void handleMaskModification(uint8_t * validityMask); + /** + * Sets specific bit of a byte + * @param byte + * @param position Position of byte to set from 1 to 8 + * @param value Binary value to set + * @return + */ + uint8_t bitSetter(uint8_t byte, uint8_t position, bool value); +}; + +#endif /* FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ */ diff --git a/datapool/PoolVarList.h b/datapool/PoolVarList.h index 9d6bc461a..1c8a7be48 100644 --- a/datapool/PoolVarList.h +++ b/datapool/PoolVarList.h @@ -1,8 +1,8 @@ #ifndef POOLVARLIST_H_ #define POOLVARLIST_H_ -#include -#include +#include "../datapool/PoolVariableIF.h" +#include "../datapoolglob/GlobalPoolVariable.h" template class PoolVarList { private: diff --git a/datapool/PoolVariableIF.h b/datapool/PoolVariableIF.h index 30b87839b..2aa269dd4 100644 --- a/datapool/PoolVariableIF.h +++ b/datapool/PoolVariableIF.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_ #define FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_ -#include -#include +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../serialize/SerializeIF.h" /** * @brief This interface is used to control data pool @@ -18,9 +18,9 @@ * @ingroup data_pool */ class PoolVariableIF : public SerializeIF { - friend class DataSetBase; + friend class PoolDataSetBase; friend class GlobDataSet; - friend class LocalDataSet; + friend class LocalPoolDataSetBase; public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF; static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0); diff --git a/datapool/SharedDataSetIF.h b/datapool/SharedDataSetIF.h new file mode 100644 index 000000000..b8d98794d --- /dev/null +++ b/datapool/SharedDataSetIF.h @@ -0,0 +1,14 @@ +#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ +#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ +#include "PoolDataSetIF.h" + +class SharedDataSetIF: public PoolDataSetIF { +public: + virtual ~SharedDataSetIF() {}; + +private: + virtual ReturnValue_t lockDataset(dur_millis_t mutexTimeout) = 0; + virtual ReturnValue_t unlockDataset() = 0; +}; + +#endif /* FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ */ diff --git a/datapoolglob/DataPoolAdmin.cpp b/datapoolglob/DataPoolAdmin.cpp index 4d0e5530f..029a336d1 100644 --- a/datapoolglob/DataPoolAdmin.cpp +++ b/datapoolglob/DataPoolAdmin.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include -#include +#include "../datapoolglob/DataPoolAdmin.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapoolglob/PoolRawAccess.h" +#include "../ipc/CommandMessage.h" +#include "../ipc/QueueFactory.h" +#include "../parameters/ParameterMessage.h" DataPoolAdmin::DataPoolAdmin(object_id_t objectId) : SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper( diff --git a/datapoolglob/DataPoolAdmin.h b/datapoolglob/DataPoolAdmin.h index 653fdd8e2..a08f322d9 100644 --- a/datapoolglob/DataPoolAdmin.h +++ b/datapoolglob/DataPoolAdmin.h @@ -1,16 +1,16 @@ #ifndef DATAPOOLADMIN_H_ #define DATAPOOLADMIN_H_ -#include -#include -#include -#include -#include -#include +#include "../objectmanager/SystemObject.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../tasks/ExecutableObjectIF.h" +#include "../action/HasActionsIF.h" +#include "../ipc/MessageQueueIF.h" +#include "../parameters/ReceivesParameterMessagesIF.h" -#include -#include -#include +#include "../memory/MemoryHelper.h" +#include "../action/SimpleActionHelper.h" +#include "../datapoolglob/DataPoolParameterWrapper.h" class DataPoolAdmin: public HasActionsIF, public ExecutableObjectIF, diff --git a/datapoolglob/DataPoolParameterWrapper.cpp b/datapoolglob/DataPoolParameterWrapper.cpp index a292016ea..3a57d90df 100644 --- a/datapoolglob/DataPoolParameterWrapper.cpp +++ b/datapoolglob/DataPoolParameterWrapper.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/DataPoolParameterWrapper.h" +#include "../datapoolglob/PoolRawAccess.h" +#include "../parameters/HasParametersIF.h" DataPoolParameterWrapper::DataPoolParameterWrapper() : diff --git a/datapoolglob/DataPoolParameterWrapper.h b/datapoolglob/DataPoolParameterWrapper.h index a3dbdc04d..b1e505a75 100644 --- a/datapoolglob/DataPoolParameterWrapper.h +++ b/datapoolglob/DataPoolParameterWrapper.h @@ -1,8 +1,8 @@ #ifndef DATAPOOLPARAMETERWRAPPER_H_ #define DATAPOOLPARAMETERWRAPPER_H_ -#include -#include +#include "../globalfunctions/Type.h" +#include "../parameters/ParameterWrapper.h" class DataPoolParameterWrapper: public SerializeIF { public: diff --git a/datapoolglob/GlobalDataPool.cpp b/datapoolglob/GlobalDataPool.cpp index 25acaab3f..afb27b772 100644 --- a/datapoolglob/GlobalDataPool.cpp +++ b/datapoolglob/GlobalDataPool.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../datapoolglob/GlobalDataPool.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../ipc/MutexFactory.h" GlobalDataPool::GlobalDataPool( void(*initFunction)(GlobPoolMap* pool_map)) { @@ -54,7 +54,8 @@ ReturnValue_t GlobalDataPool::unlockDataPool() { } ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) { - ReturnValue_t status = mutex->lockMutex(timeoutMs); + ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING, + timeoutMs); if(status != RETURN_OK) { sif::error << "DataPool::DataPool: lock of mutex failed " "with error code: " << status << std::endl; diff --git a/datapoolglob/GlobalDataPool.h b/datapoolglob/GlobalDataPool.h index b349fb603..ce5b132c0 100644 --- a/datapoolglob/GlobalDataPool.h +++ b/datapoolglob/GlobalDataPool.h @@ -1,9 +1,9 @@ #ifndef GLOBALDATAPOOL_H_ #define GLOBALDATAPOOL_H_ -#include -#include -#include +#include "../datapool/PoolEntry.h" +#include "../globalfunctions/Type.h" +#include "../ipc/MutexIF.h" #include /** @@ -95,7 +95,7 @@ public: * @brief This is a small helper function to facilitate locking the global data pool. * @details It fetches the pool's mutex id and tries to acquire the mutex. */ - ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::NO_TIMEOUT); + ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING); /** * @brief This is a small helper function to facilitate unlocking the global data pool. * @details It fetches the pool's mutex id and tries to free the mutex. diff --git a/datapoolglob/GlobalDataSet.cpp b/datapoolglob/GlobalDataSet.cpp index 883f61577..1e99f8051 100644 --- a/datapoolglob/GlobalDataSet.cpp +++ b/datapoolglob/GlobalDataSet.cpp @@ -1,8 +1,8 @@ -#include -#include -#include +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapoolglob/GlobalDataSet.h" +#include "../serviceinterface/ServiceInterfaceStream.h" -GlobDataSet::GlobDataSet(): DataSetBase( +GlobDataSet::GlobDataSet(): PoolDataSetBase( reinterpret_cast(®isteredVariables), DATA_SET_MAX_SIZE) {} @@ -17,7 +17,11 @@ ReturnValue_t GlobDataSet::commit(bool valid, uint32_t lockTimeout) { } ReturnValue_t GlobDataSet::commit(uint32_t lockTimeout) { - return DataSetBase::commit(lockTimeout); + return PoolDataSetBase::commit(lockTimeout); +} + +bool GlobDataSet::isValid() const { + return this->valid; } ReturnValue_t GlobDataSet::unlockDataPool() { diff --git a/datapoolglob/GlobalDataSet.h b/datapoolglob/GlobalDataSet.h index 7efe8244a..2f0edbd5c 100644 --- a/datapoolglob/GlobalDataSet.h +++ b/datapoolglob/GlobalDataSet.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_DATAPOOLGLOB_DATASET_H_ #define FRAMEWORK_DATAPOOLGLOB_DATASET_H_ -#include +#include "../datapool/PoolDataSetBase.h" /** * @brief The DataSet class manages a set of locally checked out variables @@ -17,7 +17,7 @@ * @author Bastian Baetz * @ingroup data_pool */ -class GlobDataSet: public DataSetBase { +class GlobDataSet: public PoolDataSetBase { public: /** @@ -44,8 +44,8 @@ public: * - @c COMMITING_WITHOUT_READING if set was not read yet and * contains non write-only variables */ - ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::NO_TIMEOUT); - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; + ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::BLOCKING); + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; /** * Set all entries @@ -53,6 +53,8 @@ public: */ void setSetValid(bool valid); + bool isValid() const override; + /** * Set the valid information of all variables contained in the set which * are not read-only diff --git a/datapoolglob/GlobalPoolVariable.h b/datapoolglob/GlobalPoolVariable.h index b4aa6c4c1..a995bfaf2 100644 --- a/datapoolglob/GlobalPoolVariable.h +++ b/datapoolglob/GlobalPoolVariable.h @@ -1,12 +1,12 @@ #ifndef GLOBALPOOLVARIABLE_H_ #define GLOBALPOOLVARIABLE_H_ -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSetIF.h" +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapool/PoolVariableIF.h" +#include "../datapool/PoolEntry.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" template class PoolVarList; @@ -198,7 +198,7 @@ public: } }; -#include +#include "../datapoolglob/GlobalPoolVariable.tpp" typedef GlobPoolVar gp_bool_t; typedef GlobPoolVar gp_uint8_t; diff --git a/datapoolglob/GlobalPoolVector.h b/datapoolglob/GlobalPoolVector.h index bb883634f..6b592fc67 100644 --- a/datapoolglob/GlobalPoolVector.h +++ b/datapoolglob/GlobalPoolVector.h @@ -1,12 +1,11 @@ #ifndef GLOBALPOOLVECTOR_H_ #define GLOBALPOOLVECTOR_H_ -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolEntry.h" +#include "../datapool/PoolVariableIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" /** * @brief This is the access class for array-type data pool entries. @@ -128,7 +127,7 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t read(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; /** * @brief The commit call copies the array values back to the data pool. * @details @@ -138,7 +137,7 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; protected: /** @@ -178,7 +177,7 @@ private: ReadWriteMode_t readWriteMode; }; -#include +#include "../datapoolglob/GlobalPoolVector.tpp" template using gp_vec_t = GlobPoolVector; diff --git a/datapoolglob/PIDReader.h b/datapoolglob/PIDReader.h index a11160402..9431e1d40 100644 --- a/datapoolglob/PIDReader.h +++ b/datapoolglob/PIDReader.h @@ -1,11 +1,11 @@ #ifndef PIDREADER_H_ #define PIDREADER_H_ -#include -#include -#include -#include -#include -#include +#include "../datapool/DataSetIF.h" +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapool/PoolEntry.h" +#include "../datapool/PoolVariableIF.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" template class PIDReaderList; diff --git a/datapoolglob/PIDReaderList.h b/datapoolglob/PIDReaderList.h index 0b8385081..ae99f3aa2 100644 --- a/datapoolglob/PIDReaderList.h +++ b/datapoolglob/PIDReaderList.h @@ -1,8 +1,8 @@ #ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ #define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ -#include -#include +#include "../datapool/PoolVariableIF.h" +#include "../datapoolglob/PIDReader.h" template class PIDReaderList { private: diff --git a/datapoolglob/PoolRawAccess.cpp b/datapoolglob/PoolRawAccess.cpp index 783418cc9..53706c6d3 100644 --- a/datapoolglob/PoolRawAccess.cpp +++ b/datapoolglob/PoolRawAccess.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "../datapoolglob/GlobalDataPool.h" +#include "../datapoolglob/PoolRawAccess.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serialize/EndianConverter.h" #include diff --git a/datapoolglob/PoolRawAccess.h b/datapoolglob/PoolRawAccess.h index 0571d8b4c..15643a41c 100644 --- a/datapoolglob/PoolRawAccess.h +++ b/datapoolglob/PoolRawAccess.h @@ -1,10 +1,10 @@ #ifndef POOLRAWACCESS_H_ #define POOLRAWACCESS_H_ -#include -#include -#include -#include +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolEntryIF.h" +#include "../datapool/PoolVariableIF.h" +#include "../globalfunctions/Type.h" /** * @brief This class allows accessing Data Pool variables as raw bytes. @@ -148,7 +148,7 @@ public: * -@c READ_INDEX_TOO_LARGE * -@c READ_ENTRY_NON_EXISTENT */ - ReturnValue_t read(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; /** * @brief The commit call writes back the variable's value to the data pool. * @details @@ -157,7 +157,7 @@ public: * The call is protected by a lock of the global data pool. * */ - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::NO_TIMEOUT) override; + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; protected: /** diff --git a/datapoollocal/HasLocalDataPoolIF.h b/datapoollocal/HasLocalDataPoolIF.h new file mode 100644 index 000000000..9eb1c9f11 --- /dev/null +++ b/datapoollocal/HasLocalDataPoolIF.h @@ -0,0 +1,92 @@ +#ifndef FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ +#define FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ +#include "../datapool/PoolEntryIF.h" +#include "../ipc/MessageQueueSenderIF.h" +#include "../housekeeping/HousekeepingMessage.h" +#include + +class LocalDataPoolManager; +class DataSetIF; +/** + * @brief Type definition for local pool entries. + */ +using lp_id_t = uint32_t; +using LocalDataPool = std::map; +using LocalDataPoolMapIter = LocalDataPool::iterator; + +/** + * @brief This interface is implemented by classes which posses a local + * data pool (not the managing class). It defines the relationship + * between the local data pool owner and the LocalDataPoolManager. + * @details + * Any class implementing this interface shall also have a LocalDataPoolManager + * member class which contains the actual pool data structure + * and exposes the public interface for it. + * This is required because the pool entries are templates, which makes + * specifying an interface rather difficult. The local data pool can be + * accessed by using the LocalPoolVariable, LocalPoolVector or LocalDataSet + * classes. + * + * Architectural Note: + * This could be circumvented by using a wrapper/accessor function or + * implementing the templated function in this interface.. + * The first solution sounds better than the second but + * the LocalPoolVariable classes are templates as well, so this just shifts + * the problem somewhere else. Interfaces are nice, but the most + * pragmatic solution I found was to offer the client the full interface + * of the LocalDataPoolManager. + */ +class HasLocalDataPoolIF { +public: + virtual~ HasLocalDataPoolIF() {}; + + static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF; + static constexpr lp_id_t NO_POOL_ID = 0xffffffff; + + virtual object_id_t getObjectId() const = 0; + + /** Command queue for housekeeping messages. */ + virtual MessageQueueId_t getCommandQueue() const = 0; + + /** + * Is used by pool owner to initialize the pool map once + * The manager instance shall also be passed to this function. + * It can be used to subscribe for periodic packets for for updates. + */ + virtual ReturnValue_t initializeLocalDataPool( + LocalDataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) = 0; + + /** Can be used to get a handle to the local data pool manager. */ + virtual LocalDataPoolManager* getHkManagerHandle() = 0; + + /** + * Returns the minimum sampling frequency, which will usually be the + * period the pool owner performs its periodic operation- + * @return + */ + virtual dur_millis_t getPeriodicOperationFrequency() const = 0; + + /** + * This function is used by the pool manager to get a valid dataset + * from a SID + * @param sid Corresponding structure ID + * @return + */ + virtual DataSetIF* getDataSetHandle(sid_t sid) = 0; + + /* These function can be implemented by pool owner, as they are required + * by the housekeeping message interface */ + virtual ReturnValue_t addDataSet(sid_t sid) { + return HasReturnvaluesIF::RETURN_FAILED; + }; + virtual ReturnValue_t removeDataSet(sid_t sid) { + return HasReturnvaluesIF::RETURN_FAILED; + }; + virtual ReturnValue_t changeCollectionInterval(sid_t sid, + dur_seconds_t newInterval) { + return HasReturnvaluesIF::RETURN_FAILED; + }; +}; + +#endif /* FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ */ diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp new file mode 100644 index 000000000..87a0a3cb8 --- /dev/null +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -0,0 +1,305 @@ +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../datapoollocal/LocalDataSet.h" +#include "../housekeeping/AcceptsHkPacketsIF.h" +#include "../ipc/MutexFactory.h" +#include "../ipc/MutexHelper.h" +#include "../ipc/QueueFactory.h" + +#include +#include + +object_id_t LocalDataPoolManager::defaultHkDestination = objects::NO_OBJECT; + +LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, + MessageQueueIF* queueToUse, bool appendValidityBuffer): + appendValidityBuffer(appendValidityBuffer) { + if(owner == nullptr) { + sif::error << "HkManager: Invalid supplied owner!" << std::endl; + return; + } + this->owner = owner; + mutex = MutexFactory::instance()->createMutex(); + if(mutex == nullptr) { + sif::error << "LocalDataPoolManager::LocalDataPoolManager: " + "Could not create mutex." << std::endl; + } + ipcStore = objectManager->get(objects::IPC_STORE); + if(ipcStore == nullptr) { + sif::error << "LocalDataPoolManager::LocalDataPoolManager: " + "Could not set IPC store." << std::endl; + } + + hkQueue = queueToUse; + + if(defaultHkDestination != objects::NO_OBJECT) { + AcceptsHkPacketsIF* hkPacketReceiver = + objectManager->get(defaultHkDestination); + if(hkPacketReceiver != nullptr) { + defaultHkDestinationId = hkPacketReceiver->getHkQueue(); + } + } +} + +LocalDataPoolManager::~LocalDataPoolManager() {} + +ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { + if(queueToUse == nullptr) { + sif::error << "LocalDataPoolManager::initialize: Supplied queue " + "invalid!" << std::endl; + } + hkQueue = queueToUse; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation( + uint8_t nonDiagInvlFactor) { + setNonDiagnosticIntervalFactor(nonDiagInvlFactor); + diagnosticMinimumInterval = owner->getPeriodicOperationFrequency(); + regularMinimumInterval = diagnosticMinimumInterval * + nonDiagnosticIntervalFactor; + return initializeHousekeepingPoolEntriesOnce(); +} + +ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { + if(not mapInitialized) { + ReturnValue_t result = owner->initializeLocalDataPool(localPoolMap, + *this); + if(result == HasReturnvaluesIF::RETURN_OK) { + mapInitialized = true; + } + return result; + } + sif::warning << "HousekeepingManager: The map should only be initialized " + "once!" << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::performHkOperation() { + for(auto& hkReceiversIter: hkReceiversMap) { + HkReceiver* receiver = &hkReceiversIter.second; + if(not receiver->reportingEnabled) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(receiver->reportingType) { + case(ReportingType::PERIODIC): { + if(receiver->dataId.dataSetSid.notSet()) { + // Periodic packets shall only be generated from datasets. + continue; + } + performPeriodicHkGeneration(receiver); + break; + } + case(ReportingType::UPDATE_SNAPSHOT): { + // check whether data has changed and send messages in case it has. + break; + } + default: + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, + bool enableReporting, float collectionInterval, bool isDiagnostics, + 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.dataSetSid = sid; + hkReceiver.reportingType = ReportingType::PERIODIC; + hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); + hkReceiver.reportingEnabled = enableReporting; + if(not isDiagnostics) { + hkReceiver.hkParameter.collectionIntervalTicks = + intervalSecondsToInterval(isDiagnostics, collectionInterval * + nonDiagnosticIntervalFactor); + } + else { + hkReceiver.hkParameter.collectionIntervalTicks = + intervalSecondsToInterval(isDiagnostics, collectionInterval); + } + + hkReceiver.isDiagnostics = isDiagnostics; + hkReceiver.intervalCounter = 1; + + hkReceiversMap.emplace(packetDestination, hkReceiver); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage( + CommandMessage* message) { + Command_t command = message->getCommand(); + switch(command) { + // I think those are the only commands which can be handled here.. + case(HousekeepingMessage::ADD_HK_REPORT_STRUCT): + case(HousekeepingMessage::ADD_DIAGNOSTICS_REPORT_STRUCT): + // We should use OwnsLocalPoolDataIF to specify those functions.. + return HasReturnvaluesIF::RETURN_OK; + case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): + case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): + //return generateSetStructurePacket(message->getSid()); + case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): + case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): + //return generateHousekeepingPacket(message->getSid()); + default: + return CommandMessageIF::UNKNOWN_COMMAND; + } +} + +ReturnValue_t LocalDataPoolManager::printPoolEntry( + lp_id_t localPoolId) { + auto poolIter = localPoolMap.find(localPoolId); + if (poolIter == localPoolMap.end()) { + sif::debug << "HousekeepingManager::fechPoolEntry:" + " Pool entry not found." << std::endl; + return POOL_ENTRY_NOT_FOUND; + } + poolIter->second->print(); + return HasReturnvaluesIF::RETURN_OK; +} + +MutexIF* LocalDataPoolManager::getMutexHandle() { + return mutex; +} + +const HasLocalDataPoolIF* LocalDataPoolManager::getOwner() const { + return owner; +} + +ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, + float collectionInterval, MessageQueueId_t destination) { + LocalPoolDataSetBase* dataSetToSerialize = + dynamic_cast(owner->getDataSetHandle(sid)); + if(dataSetToSerialize == nullptr) { + sif::warning << "HousekeepingManager::generateHousekeepingPacket:" + " Set ID not found or dataset not assigned!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + sif::info << "hk gen called" << std::endl; + store_address_t storeId; + HousekeepingPacketDownlink hkPacket(sid, collectionInterval, + dataSetToSerialize->getFillCount(), dataSetToSerialize); + ReturnValue_t result = serializeHkPacketIntoStore(hkPacket, &storeId); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + // and now we set a HK message and send it the HK packet destination. + CommandMessage hkMessage; + HousekeepingMessage::setHkReportMessage(&hkMessage, sid, storeId); + if(hkQueue == nullptr) { + return QUEUE_OR_DESTINATION_NOT_SET; + } + if(destination == MessageQueueIF::NO_QUEUE) { + if(defaultHkDestinationId == MessageQueueIF::NO_QUEUE) { + // error, all destinations invalid + return HasReturnvaluesIF::RETURN_FAILED; + } + destination = defaultHkDestinationId; + } + + return hkQueue->sendMessage(destination, &hkMessage); +} + +ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore( + HousekeepingPacketDownlink& hkPacket, + store_address_t *storeId) { + uint8_t* dataPtr = nullptr; + size_t serializedSize = 0; + const size_t maxSize = hkPacket.getSerializedSize(); + ReturnValue_t result = ipcStore->getFreeElement(storeId, + serializedSize, &dataPtr); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + return hkPacket.serialize(&dataPtr, &serializedSize, maxSize, + SerializeIF::Endianness::MACHINE); +} + +ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) { + LocalPoolDataSetBase* dataSet = dynamic_cast( + owner->getDataSetHandle(sid)); + if(dataSet == nullptr) { + sif::warning << "HousekeepingManager::generateHousekeepingPacket:" + " Set ID not found" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + size_t expectedSize = dataSet->getFillCount() * sizeof(lp_id_t); + uint8_t* storePtr = nullptr; + store_address_t storeId; + ReturnValue_t result = ipcStore->getFreeElement(&storeId, + expectedSize,&storePtr); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "HousekeepingManager::generateHousekeepingPacket: " + "Could not get free element from IPC store." << std::endl; + return result; + } + size_t size = 0; + result = dataSet->serializeLocalPoolIds(&storePtr, &size, + expectedSize, SerializeIF::Endianness::BIG); + if(expectedSize != size) { + sif::error << "HousekeepingManager::generateSetStructurePacket: " + "Expected size is not equal to serialized size" << std::endl; + } + return result; +} + +void LocalDataPoolManager::setNonDiagnosticIntervalFactor( + uint8_t nonDiagInvlFactor) { + this->nonDiagnosticIntervalFactor = nonDiagInvlFactor; +} + + +void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver* receiver) { + if(receiver->intervalCounter >= + receiver->hkParameter.collectionIntervalTicks) { + ReturnValue_t result = generateHousekeepingPacket( + receiver->dataId.dataSetSid); + if(result != HasReturnvaluesIF::RETURN_OK) { + // configuration error + sif::debug << "LocalDataPoolManager::performHkOperation:" + << "0x" << std::setfill('0') << std::setw(8) + << owner->getObjectId() << " Error generating " + << "HK packet" << std::setfill(' ') << std::endl; + } + receiver->intervalCounter = 1; + } + else { + receiver->intervalCounter++; + } +} + +uint32_t LocalDataPoolManager::intervalSecondsToInterval(bool isDiagnostics, + float collectionIntervalSeconds) { + if(isDiagnostics) { + return std::ceil(collectionIntervalSeconds * 1000 + /diagnosticMinimumInterval); + } + else { + return std::ceil(collectionIntervalSeconds * 1000 + /regularMinimumInterval); + } +} + +float LocalDataPoolManager::intervalToIntervalSeconds(bool isDiagnostics, + uint32_t collectionInterval) { + if(isDiagnostics) { + return static_cast(collectionInterval * + diagnosticMinimumInterval); + } + else { + return static_cast(collectionInterval * + regularMinimumInterval); + } +} diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h new file mode 100644 index 000000000..c851978c4 --- /dev/null +++ b/datapoollocal/LocalDataPoolManager.h @@ -0,0 +1,282 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ + +#include "../housekeeping/HousekeepingPacketDownlink.h" +#include "../datapool/DataSetIF.h" +#include "../objectmanager/SystemObjectIF.h" +#include "../ipc/MutexIF.h" + +#include "../housekeeping/HousekeepingMessage.h" +#include "../datapool/PoolEntry.h" +#include "../datapoollocal/HasLocalDataPoolIF.h" +#include "../ipc/CommandMessage.h" +#include "../ipc/MessageQueueIF.h" +#include "../ipc/MutexHelper.h" + +#include + +namespace Factory { +void setStaticFrameworkObjectIds(); +} + +class LocalDataSetBase; + + +/** + * @brief This class is the managing instance for local data pool. + * @details + * The actual data pool structure is a member of this class. Any class which + * has a local data pool shall have this class as a member and implement + * the HasLocalDataPoolIF. + * + * Users of the data pool use the helper classes LocalDataSet, + * LocalPoolVariable and LocalPoolVector to access pool entries in + * a thread-safe and efficient way. + * + * The local data pools employ a blackboard logic: Only the most recent + * value is stored. The helper classes offer a read() and commit() interface + * through the PoolVariableIF which is used to read and update values. + * Each pool entry has a valid state too. + * @author R. Mueller + */ +class LocalDataPoolManager { + template + friend class LocalPoolVar; + template + friend class LocalPoolVector; + friend class LocalPoolDataSetBase; + friend void (Factory::setStaticFrameworkObjectIds)(); +public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; + + static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x0); + static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x1); + + static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x2); + + /** + * This constructor is used by a class which wants to implement + * a personal local data pool. The queueToUse can be supplied if it + * is already known. + * + * initialize() has to be called in any case before using the object! + * @param owner + * @param queueToUse + * @param appendValidityBuffer + */ + LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, + bool appendValidityBuffer = true); + virtual~ LocalDataPoolManager(); + + /** + * Initializes the map by calling the map initialization function of the + * owner and assigns the queue to use. + * @param queueToUse + * @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc + * @return + */ + ReturnValue_t initialize(MessageQueueIF* queueToUse); + + ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5); + + /** + * @return + */ + ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting, + float collectionInterval, bool isDiagnostics, + object_id_t packetDestination = defaultHkDestination); + + /** + * Non-Diagnostics packets usually have a lower minimum sampling frequency + * than diagnostic packets. + * A factor can be specified to determine the minimum sampling frequency + * for non-diagnostic packets. The minimum sampling frequency of the + * diagnostics packets,which is usually jusst the period of the + * performOperation calls, is multiplied with that factor. + * @param factor + */ + void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor); + + /** + * This should be called in the periodic handler of the owner. + * It performs all the periodic functionalities of the data pool manager. + * @return + */ + ReturnValue_t performHkOperation(); + + /** + * Generate a housekeeping packet with a given SID. + * @param sid + * @return + */ + ReturnValue_t generateHousekeepingPacket(sid_t sid, + float collectionInterval = 0, + MessageQueueId_t destination = MessageQueueIF::NO_QUEUE); + ReturnValue_t generateSetStructurePacket(sid_t sid); + + ReturnValue_t handleHousekeepingMessage(CommandMessage* message); + + /** + * This function is used to fill the local data pool map with pool + * entries. It should only be called once by the pool owner. + * @param localDataPoolMap + * @return + */ + ReturnValue_t initializeHousekeepingPoolEntriesOnce(); + + const HasLocalDataPoolIF* getOwner() const; + + ReturnValue_t printPoolEntry(lp_id_t localPoolId); + + /** + * Different types of housekeeping reporting are possible. + * 1. PERIODIC: HK packets are generated in fixed intervals and sent to + * destination. Fromat will be raw. + * 2. UPDATED: Notification will be sent out if HK data has changed. + * Question: Send Raw data directly or just the message? + * 3. REQUESTED: HK packets are only generated if explicitely requested. + * Propably not necessary, just use multiple local data sets or + * shared datasets. + * + * Notifications should also be possible for single variables instead of + * full dataset updates. + */ + enum class ReportingType: uint8_t { + //! Periodic generation of HK packets. + PERIODIC, + //! Update notification will be sent out as message. + UPDATE_NOTIFICATION, + //! Notification will be sent out as message and a snapshot of the + //! current data will be generated. + UPDATE_SNAPSHOT, + }; + + /* Copying forbidden */ + LocalDataPoolManager(const LocalDataPoolManager &) = delete; + LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete; + +private: + LocalDataPool localPoolMap; + //! Every housekeeping data manager has a mutex to protect access + //! to it's data pool. + MutexIF* mutex = nullptr; + /** The class which actually owns the manager (and its datapool). */ + HasLocalDataPoolIF* owner = nullptr; + + uint8_t nonDiagnosticIntervalFactor = 0; + dur_millis_t regularMinimumInterval = 0; + dur_millis_t diagnosticMinimumInterval = 0; + + /** Default receiver for periodic HK packets */ + static object_id_t defaultHkDestination; + MessageQueueId_t defaultHkDestinationId = MessageQueueIF::NO_QUEUE; + + /** The data pool manager will keep an internal map of HK receivers. */ + struct HkReceiver { + /** Different member of this union will be used depending on the + type of data the receiver is interested in (full datasets or + single data variables. */ + union DataId { + DataId(): dataSetSid() {} + /** Will be initialized to INVALID_ADDRESS */ + sid_t dataSetSid; + lp_id_t localPoolId = HasLocalDataPoolIF::NO_POOL_ID; + }; + DataId dataId; + + ReportingType reportingType = ReportingType::PERIODIC; + MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE; + bool reportingEnabled = true; + /** Different members of this union will be used depending on reporting + type */ + union HkParameter { + /** This parameter will be used for the PERIODIC type */ + uint32_t collectionIntervalTicks = 0; + /** This parameter will be used for the ON_UPDATE type */ + bool hkDataChanged; + }; + HkParameter hkParameter; + bool isDiagnostics; + /** General purpose counter which is used for periodic generation. */ + uint32_t intervalCounter; + }; + + /** Using a multimap as the same object might request multiple datasets */ + using HkReceiversMap = std::multimap; + + HkReceiversMap hkReceiversMap; + + /** This is the map holding the actual data. Should only be initialized + * once ! */ + bool mapInitialized = false; + /** This specifies whether a validity buffer is appended at the end + * of generated housekeeping packets. */ + bool appendValidityBuffer = true; + + /** + * @brief Queue used for communication, for example commands. + * Is also used to send messages. Can be set either in the constructor + * or in the initialize() function. + */ + MessageQueueIF* hkQueue = nullptr; + + /** Global IPC store is used to store all packets. */ + StorageManagerIF* ipcStore = nullptr; + /** + * Get the pointer to the mutex. Can be used to lock the data pool + * eternally. Use with care and don't forget to unlock locked mutexes! + * For now, only friend classes can accss this function. + * @return + */ + MutexIF* getMutexHandle(); + + /** + * Read a variable by supplying its local pool ID and assign the pool + * entry to the supplied PoolEntry pointer. The type of the pool entry + * is deduced automatically. This call is not thread-safe! + * For now, only friend classes like LocalPoolVar may access this + * function. + * @tparam T Type of the pool entry + * @param localPoolId Pool ID of the variable to read + * @param poolVar [out] Corresponding pool entry will be assigned to the + * supplied pointer. + * @return + */ + template ReturnValue_t fetchPoolEntry(lp_id_t localPoolId, + PoolEntry **poolEntry); + + void setMinimalSamplingFrequency(float frequencySeconds); + ReturnValue_t serializeHkPacketIntoStore( + HousekeepingPacketDownlink& hkPacket, + store_address_t *storeId); + + uint32_t intervalSecondsToInterval(bool isDiagnostics, + float collectionIntervalSeconds); + float intervalToIntervalSeconds(bool isDiagnostics, + uint32_t collectionInterval); + + void performPeriodicHkGeneration(HkReceiver* hkReceiver); +}; + + +template inline +ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, + PoolEntry **poolEntry) { + auto poolIter = localPoolMap.find(localPoolId); + if (poolIter == localPoolMap.end()) { + sif::warning << "HousekeepingManager::fechPoolEntry: Pool entry " + "not found." << std::endl; + return POOL_ENTRY_NOT_FOUND; + } + + *poolEntry = dynamic_cast< PoolEntry* >(poolIter->second); + if(*poolEntry == nullptr) { + sif::debug << "HousekeepingManager::fetchPoolEntry:" + " Pool entry not found." << std::endl; + return POOL_ENTRY_TYPE_CONFLICT; + } + return HasReturnvaluesIF::RETURN_OK; +} + + +#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ */ diff --git a/datapoollocal/LocalDataSet.cpp b/datapoollocal/LocalDataSet.cpp new file mode 100644 index 000000000..394a9abe9 --- /dev/null +++ b/datapoollocal/LocalDataSet.cpp @@ -0,0 +1,22 @@ +#include "LocalDataSet.h" +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../serialize/SerializeAdapter.h" + +#include +#include + +LocalDataSet::LocalDataSet(HasLocalDataPoolIF *hkOwner, uint32_t setId, + const size_t maxNumberOfVariables): + LocalPoolDataSetBase(hkOwner, setId, nullptr, maxNumberOfVariables), + poolVarList(maxNumberOfVariables) { + this->setContainer(poolVarList.data()); +} + +LocalDataSet::LocalDataSet(sid_t sid, const size_t maxNumberOfVariables): + LocalPoolDataSetBase(sid, nullptr, maxNumberOfVariables), + poolVarList(maxNumberOfVariables) { + this->setContainer(poolVarList.data()); +} + +LocalDataSet::~LocalDataSet() {} + diff --git a/datapoollocal/LocalDataSet.h b/datapoollocal/LocalDataSet.h new file mode 100644 index 000000000..5641ebfbc --- /dev/null +++ b/datapoollocal/LocalDataSet.h @@ -0,0 +1,20 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ +#include "../datapoollocal/LocalPoolDataSetBase.h" +#include + +class LocalDataSet: public LocalPoolDataSetBase { +public: + LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId, + const size_t maxSize); + LocalDataSet(sid_t sid, const size_t maxSize); + virtual~ LocalDataSet(); + + //! Copying forbidden for now. + LocalDataSet(const LocalDataSet&) = delete; + LocalDataSet& operator=(const LocalDataSet&) = delete; +private: + std::vector poolVarList; +}; + +#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ */ diff --git a/datapoollocal/LocalPoolDataSetBase.cpp b/datapoollocal/LocalPoolDataSetBase.cpp new file mode 100644 index 000000000..8abdc0e35 --- /dev/null +++ b/datapoollocal/LocalPoolDataSetBase.cpp @@ -0,0 +1,193 @@ +#include "LocalPoolDataSetBase.h" +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../serialize/SerializeAdapter.h" + +#include +#include + +LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, + uint32_t setId, PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables): + PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { + if(hkOwner == nullptr) { + sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" + << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + this->sid.objectId = hkOwner->getObjectId(); + this->sid.ownerSetId = setId; +} + +LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, + PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables): + PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { + HasLocalDataPoolIF* hkOwner = objectManager->get( + sid.objectId); + if(hkOwner == nullptr) { + sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" + << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + this->sid = sid; +} + +LocalPoolDataSetBase::~LocalPoolDataSetBase() { +} + +ReturnValue_t LocalPoolDataSetBase::lockDataPool(uint32_t timeoutMs) { + MutexIF* mutex = hkManager->getMutexHandle(); + return mutex->lockMutex(MutexIF::TimeoutType::WAITING, timeoutMs); +} + +ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer, + size_t *size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + uint8_t validityMaskSize = std::ceil(static_cast(fillCount)/8.0); + uint8_t validityMask[validityMaskSize]; + uint8_t validBufferIndex = 0; + uint8_t validBufferIndexBit = 0; + for (uint16_t count = 0; count < fillCount; count++) { + if(registeredVariables[count]->isValid()) { + // set validity buffer here. + this->bitSetter(validityMask + validBufferIndex, + validBufferIndexBit); + if(validBufferIndexBit == 7) { + validBufferIndex ++; + validBufferIndexBit = 0; + } + else { + validBufferIndexBit ++; + } + } + result = registeredVariables[count]->serialize(buffer, size, maxSize, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + // copy validity buffer to end + std::memcpy(*buffer, validityMask, validityMaskSize); + *size += validityMaskSize; + return result; +} + +ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer( + const uint8_t **buffer, size_t *size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t count = 0; count < fillCount; count++) { + result = registeredVariables[count]->deSerialize(buffer, size, + streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + uint8_t validBufferIndex = 0; + uint8_t validBufferIndexBit = 0; + // could be made more efficient but make it work first + for (uint16_t count = 0; count < fillCount; count++) { + // set validity buffer here. + bool nextVarValid = this->bitGetter(*buffer + + validBufferIndex, validBufferIndexBit); + registeredVariables[count]->setValid(nextVarValid); + + if(validBufferIndexBit == 7) { + validBufferIndex ++; + validBufferIndexBit = 0; + } + else { + validBufferIndexBit ++; + } + } + return result; +} +ReturnValue_t LocalPoolDataSetBase::unlockDataPool() { + MutexIF* mutex = hkManager->getMutexHandle(); + return mutex->unlockMutex(); +} + +ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer, + size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + for (uint16_t count = 0; count < fillCount; count++) { + lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId(); + auto result = SerializeAdapter::serialize(¤tPoolId, buffer, + size, maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "LocalDataSet::serializeLocalPoolIds: Serialization" + " error!" << std::endl; + return result; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + + +size_t LocalPoolDataSetBase::getSerializedSize() const { + if(withValidityBuffer) { + uint8_t validityMaskSize = std::ceil(static_cast(fillCount)/8.0); + return validityMaskSize + PoolDataSetBase::getSerializedSize(); + } + else { + return PoolDataSetBase::getSerializedSize(); + } +} + +void LocalPoolDataSetBase::setValidityBufferGeneration( + bool withValidityBuffer) { + this->withValidityBuffer = withValidityBuffer; +} + +ReturnValue_t LocalPoolDataSetBase::deSerialize(const uint8_t **buffer, + size_t *size, SerializeIF::Endianness streamEndianness) { + if(withValidityBuffer) { + return this->deSerializeWithValidityBuffer(buffer, size, + streamEndianness); + } + else { + return PoolDataSetBase::deSerialize(buffer, size, streamEndianness); + } +} + +ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, + size_t maxSize, SerializeIF::Endianness streamEndianness) const { + if(withValidityBuffer) { + return this->serializeWithValidityBuffer(buffer, size, + maxSize, streamEndianness); + } + else { + return PoolDataSetBase::serialize(buffer, size, maxSize, + streamEndianness); + } +} + +void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const { + if(position > 7) { + sif::debug << "Pool Raw Access: Bit setting invalid position" + << std::endl; + return; + } + uint8_t shiftNumber = position + (7 - 2 * position); + *byte |= 1 << shiftNumber; +} + +bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, + uint8_t position) const { + if(position > 7) { + sif::debug << "Pool Raw Access: Bit setting invalid position" + << std::endl; + return false; + } + uint8_t shiftNumber = position + (7 - 2 * position); + return *byte & (1 << shiftNumber); +} + +bool LocalPoolDataSetBase::isValid() const { + return this->valid; +} + + diff --git a/datapoollocal/LocalPoolDataSetBase.h b/datapoollocal/LocalPoolDataSetBase.h new file mode 100644 index 000000000..bd127db49 --- /dev/null +++ b/datapoollocal/LocalPoolDataSetBase.h @@ -0,0 +1,133 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolDataSetBase.h" +#include "../datapoollocal/HasLocalDataPoolIF.h" +#include "../serialize/SerializeIF.h" + +#include + +class LocalDataPoolManager; + +/** + * @brief The LocalDataSet class manages a set of locally checked out + * variables for local data pools + * @details + * This class manages a list, where a set of local variables (or pool variables) + * are registered. They are checked-out (i.e. their values are looked + * up and copied) with the read call. After the user finishes working with the + * pool variables, he can write back all variable values to the pool with + * the commit call. The data set manages locking and freeing the local data pools, + * to ensure thread-safety. + * + * An internal state manages usage of this class. Variables may only be + * registered before the read call is made, and the commit call only + * after the read call. + * + * If pool variables are writable and not committed until destruction + * of the set, the DataSet class automatically sets the valid flag in the + * data pool to invalid (without) changing the variable's value. + * + * @ingroup data_pool + */ +class LocalPoolDataSetBase: public PoolDataSetBase { +public: + /** + * @brief Constructor for the creator of local pool data. + */ + LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, + uint32_t setId, PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables); + + /** + * @brief Constructor for users of local pool data. The passed pool + * owner should implement the HasHkPoolParametersIF. + * @details + * @param sid Unique identifier of dataset consisting of object ID and + * set ID. + * @param registeredVariablesArray + * @param maxNumberOfVariables + */ + LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables); + + /** + * @brief The destructor automatically manages writing the valid + * information of variables. + * @details + * In case the data set was read out, but not committed(indicated by state), + * the destructor parses all variables that are still registered to the set. + * For each, the valid flag in the data pool is set to "invalid". + */ + ~LocalPoolDataSetBase(); + + void setValidityBufferGeneration(bool withValidityBuffer); + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size, + SerializeIF::Endianness streamEndianness) override; + size_t getSerializedSize() const override; + + /** + * Special version of the serilization function which appends a + * validity buffer at the end. Each bit of this validity buffer + * denotes whether the container data set entries are valid from left + * to right, MSB first. + * @param buffer + * @param size + * @param maxSize + * @param bigEndian + * @param withValidityBuffer + * @return + */ + ReturnValue_t serializeWithValidityBuffer(uint8_t** buffer, + size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const; + ReturnValue_t deSerializeWithValidityBuffer(const uint8_t** buffer, + size_t *size, SerializeIF::Endianness streamEndianness); + ReturnValue_t serializeLocalPoolIds(uint8_t** buffer, + size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const; + + bool isValid() const override; + +protected: + sid_t sid; + /** + * If the valid state of a dataset is always relevant to the whole + * data set we can use this flag. + */ + bool valid = false; + + bool withValidityBuffer = true; + + /** + * @brief This is a small helper function to facilitate locking + * the global data pool. + * @details + * It makes use of the lockDataPool method offered by the DataPool class. + */ + ReturnValue_t lockDataPool(uint32_t timeoutMs) override; + /** + * @brief This is a small helper function to facilitate + * unlocking the global data pool + * @details + * It makes use of the freeDataPoolLock method offered by the DataPool class. + */ + ReturnValue_t unlockDataPool() override; + + LocalDataPoolManager* hkManager; + + /** + * Set n-th bit of a byte, with n being the position from 0 + * (most significant bit) to 7 (least significant bit) + */ + void bitSetter(uint8_t* byte, uint8_t position) const; + bool bitGetter(const uint8_t* byte, uint8_t position) const; +private: + + +}; + +#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ */ diff --git a/datapoollocal/LocalPoolVariable.h b/datapoollocal/LocalPoolVariable.h new file mode 100644 index 000000000..7107bffe9 --- /dev/null +++ b/datapoollocal/LocalPoolVariable.h @@ -0,0 +1,176 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ + +#include "../datapool/PoolVariableIF.h" +#include "../datapool/DataSetIF.h" +#include "../datapoollocal/HasLocalDataPoolIF.h" +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../objectmanager/ObjectManagerIF.h" + +#include "../serialize/SerializeAdapter.h" + +/** + * @brief Local Pool Variable class which is used to access the local pools. + * @details + * This class is not stored in the map. Instead, it is used to access + * the pool entries by using a pointer to the map storing the pool + * entries. It can also be used to organize these pool entries into data sets. + * + * @tparam T The template parameter sets the type of the variable. Currently, + * all plain data types are supported, but in principle any type is possible. + * @ingroup data_pool + */ +template +class LocalPoolVar: public PoolVariableIF, HasReturnvaluesIF { +public: + //! Default ctor is forbidden. + LocalPoolVar() = delete; + + /** + * This constructor is used by the data creators to have pool variable + * instances which can also be stored in datasets. + * + * It does not fetch the current value from the data pool, which + * has to be done by calling the read() operation. + * Datasets can be used to access multiple local pool entries in an + * efficient way. A pointer to a dataset can be passed to register + * the pool variable in that dataset directly. + * @param poolId ID of the local pool entry. + * @param hkOwner Pointer of the owner. This will generally be the calling + * class itself which passes "this". + * @param setReadWriteMode Specify the read-write mode of the pool variable. + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + */ + LocalPoolVar(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, + DataSetIF* dataSet = nullptr); + + /** + * This constructor is used by data users like controllers to have + * access to the local pool variables of data creators by supplying + * the respective creator object ID. + * + * It does not fetch the current value from the data pool, which + * has to be done by calling the read() operation. + * Datasets can be used to access multiple local pool entries in an + * efficient way. A pointer to a dataset can be passed to register + * the pool variable in that dataset directly. + * @param poolId ID of the local pool entry. + * @param hkOwner object ID of the pool owner. + * @param setReadWriteMode Specify the read-write mode of the pool variable. + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + */ + LocalPoolVar(lp_id_t poolId, object_id_t poolOwner, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, + DataSetIF* dataSet = nullptr); + + virtual~ LocalPoolVar() {}; + + /** + * @brief This is the local copy of the data pool entry. + * @details The user can work on this attribute + * just like he would on a simple local variable. + */ + T value = 0; + + pool_rwm_t getReadWriteMode() const override; + + lp_id_t getDataPoolId() const override; + void setDataPoolId(lp_id_t poolId); + + bool isValid() const override; + void setValid(bool validity) override; + uint8_t getValid() const; + + ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; + + /** + * @brief This is a call to read the array's values + * from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the data pool and copies all array values and the valid + * information to its local attributes. + * In case of a failure (wrong type, size or pool id not found), the + * variable is set to zero and invalid. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + * + */ + ReturnValue_t read(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call copies the array values back to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the local valid flag is written back as well. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + + + LocalPoolVar &operator=(T newValue); +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + + // std::ostream is the type for object std::cout + template + friend std::ostream& operator<< (std::ostream &out, + const LocalPoolVar &var); + +private: + //! @brief Pool ID of pool entry inside the used local pool. + lp_id_t localPoolId = PoolVariableIF::NO_PARAMETER; + //! @brief Read-write mode of the pool variable + pool_rwm_t readWriteMode = pool_rwm_t::VAR_READ_WRITE; + //! @brief Specifies whether the entry is valid or invalid. + bool valid = false; + + //! Pointer to the class which manages the HK pool. + LocalDataPoolManager* hkManager; +}; + +#include "LocalPoolVariable.tpp" + +template +using lp_var_t = LocalPoolVar; + +using lp_bool_t = LocalPoolVar; +using lp_uint8_t = LocalPoolVar; +using lp_uint16_t = LocalPoolVar; +using lp_uint32_t = LocalPoolVar; +using lp_uint64_t = LocalPoolVar; +using lp_int8_t = LocalPoolVar; +using lp_int16_t = LocalPoolVar; +using lp_int32_t = LocalPoolVar; +using lp_int64_t = LocalPoolVar; +using lp_float_t = LocalPoolVar; +using lp_double_t = LocalPoolVar; + + +#endif diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp new file mode 100644 index 000000000..6e6f27aaa --- /dev/null +++ b/datapoollocal/LocalPoolVariable.tpp @@ -0,0 +1,168 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ + +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ +#error Include LocalPoolVariable.h before LocalPoolVariable.tpp! +#endif + +template +inline LocalPoolVar::LocalPoolVar(lp_id_t poolId, + HasLocalDataPoolIF* hkOwner, pool_rwm_t setReadWriteMode, + DataSetIF* dataSet): + localPoolId(poolId),readWriteMode(setReadWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " + "NO_PARAMETER value!" << std::endl; + } + if(hkOwner == nullptr) { + sif::error << "LocalPoolVariable: The supplied pool owner is a nullptr!" + << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + if(dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline LocalPoolVar::LocalPoolVar(lp_id_t poolId, object_id_t poolOwner, + pool_rwm_t setReadWriteMode, DataSetIF *dataSet): + readWriteMode(setReadWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " + "NO_PARAMETER value!" << std::endl; + } + HasLocalDataPoolIF* hkOwner = + objectManager->get(poolOwner); + if(hkOwner == nullptr) { + sif::error << "LocalPoolVariable: The supplied pool owner did not implement" + "the correct interface HasHkPoolParametersIF!" << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + if(dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline ReturnValue_t LocalPoolVar::read(dur_millis_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return readWithoutLock(); +} + +template +inline ReturnValue_t LocalPoolVar::readWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_WRITE) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for read() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + if(result != RETURN_OK and poolEntry != nullptr) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << " and lp ID 0x" << localPoolId << + std::dec << " failed.\n" << std::flush; + return result; + } + this->value = *(poolEntry->address); + this->valid = poolEntry->valid; + return RETURN_OK; +} + +template +inline ReturnValue_t LocalPoolVar::commit(dur_millis_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return commitWithoutLock(); +} + +template +inline ReturnValue_t LocalPoolVar::commitWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_READ) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for commit() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + if(result != RETURN_OK) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << " and lp ID 0x" << localPoolId << + std::dec << " failed.\n" << std::flush; + return result; + } + *(poolEntry->address) = this->value; + poolEntry->valid = this->valid; + return RETURN_OK; +} + +template +inline LocalPoolVar & LocalPoolVar::operator =(T newValue) { + value = newValue; + return *this; +} + + +template +inline pool_rwm_t LocalPoolVar::getReadWriteMode() const { + return readWriteMode; +} + +template +inline lp_id_t LocalPoolVar::getDataPoolId() const { + return localPoolId; +} + +template +inline void LocalPoolVar::setDataPoolId(lp_id_t poolId) { + this->localPoolId = poolId; +} + +template +inline bool LocalPoolVar::isValid() const { + return valid; +} + +template +inline void LocalPoolVar::setValid(bool validity) { + this->valid = validity; +} + +template +inline uint8_t LocalPoolVar::getValid() const { + return valid; +} + +template +inline ReturnValue_t LocalPoolVar::serialize(uint8_t** buffer, size_t* size, + const size_t max_size, SerializeIF::Endianness streamEndianness) const { + return SerializeAdapter::serialize(&value, + buffer, size ,max_size, streamEndianness); +} + +template +inline size_t LocalPoolVar::getSerializedSize() const { + return SerializeAdapter::getSerializedSize(&value); +} + +template +inline ReturnValue_t LocalPoolVar::deSerialize(const uint8_t** buffer, + size_t* size, SerializeIF::Endianness streamEndianness) { + return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); +} + +template +inline std::ostream& operator<< (std::ostream &out, + const LocalPoolVar &var) { + out << var.value; + return out; +} + +#endif diff --git a/datapoollocal/LocalPoolVector.h b/datapoollocal/LocalPoolVector.h new file mode 100644 index 000000000..86705bb0d --- /dev/null +++ b/datapoollocal/LocalPoolVector.h @@ -0,0 +1,200 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ + +#include "../datapool/DataSetIF.h" +#include "../datapool/PoolEntry.h" +#include "../datapool/PoolVariableIF.h" +#include "../datapoollocal/LocalDataPoolManager.h" +#include "../serialize/SerializeAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + + +/** + * @brief This is the access class for array-type data pool entries. + * @details + * To ensure safe usage of the data pool, operation is not done directly on the + * data pool entries, but on local copies. This class provides simple type- + * and length-safe access to vector-style data pool entries (i.e. entries with + * length > 1). The class can be instantiated as read-write and read only. + * + * It provides a commit-and-roll-back semantic, which means that no array + * entry in the data pool is changed until the commit call is executed. + * There are two template parameters: + * @tparam T + * This template parameter specifies the data type of an array entry. Currently, + * all plain data types are supported, but in principle any type is possible. + * @tparam vector_size + * This template parameter specifies the vector size of this entry. Using a + * template parameter for this is not perfect, but avoids + * dynamic memory allocation. + * @ingroup data_pool + */ +template +class LocalPoolVector: public PoolVariableIF, public HasReturnvaluesIF { +public: + LocalPoolVector() = delete; + /** + * This constructor is used by the data creators to have pool variable + * instances which can also be stored in datasets. + * It does not fetch the current value from the data pool. This is performed + * by the read() operation (which is not thread-safe). + * Datasets can be used to access local pool entires in a thread-safe way. + * @param poolId ID of the local pool entry. + * @param hkOwner Pointer of the owner. This will generally be the calling + * class itself which passes "this". + * @param setReadWriteMode Specify the read-write mode of the pool variable. + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + */ + LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, + DataSetIF* dataSet = nullptr); + + /** + * This constructor is used by data users like controllers to have + * access to the local pool variables of data creators by supplying + * the respective creator object ID. + * It does not fetch the current value from the data pool. This is performed + * by the read() operation (which is not thread-safe). + * Datasets can be used to access local pool entires in a thread-safe way. + * @param poolId ID of the local pool entry. + * @param hkOwner Pointer of the owner. This will generally be the calling + * class itself which passes "this". + * @param setReadWriteMode Specify the read-write mode of the pool variable. + * @param dataSet The data set in which the variable shall register itself. + * If nullptr, the variable is not registered. + */ + LocalPoolVector(lp_id_t poolId, object_id_t poolOwner, + pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, + DataSetIF* dataSet = nullptr); + + /** + * @brief This is the local copy of the data pool entry. + * @details + * The user can work on this attribute just like he would on a local + * array of this type. + */ + T value[vectorSize]; + /** + * @brief The classes destructor is empty. + * @details If commit() was not called, the local value is + * discarded and not written back to the data pool. + */ + ~LocalPoolVector() {}; + /** + * @brief The operation returns the number of array entries + * in this variable. + */ + uint8_t getSize() { + return vectorSize; + } + + uint32_t getDataPoolId() const override; + /** + * @brief This operation sets the data pool ID of the variable. + * @details + * The method is necessary to set id's of data pool member variables + * with bad initialization. + */ + void setDataPoolId(uint32_t poolId); + + /** + * This method returns if the variable is write-only, read-write or read-only. + */ + pool_rwm_t getReadWriteMode() const; + + /** + * @brief With this call, the valid information of the variable is returned. + */ + bool isValid() const override; + void setValid(bool valid) override; + uint8_t getValid() const; + + T& operator [](int i); + const T &operator [](int i) const; + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + const size_t maxSize, + SerializeIF::Endianness streamEndiannes) const override; + virtual size_t getSerializedSize() const override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) override; + + /** + * @brief This is a call to read the array's values + * from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the data pool and copies all array values and the valid + * information to its local attributes. + * In case of a failure (wrong type, size or pool id not found), the + * variable is set to zero and invalid. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + /** + * @brief The commit call copies the array values back to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the local valid flag is written back as well. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + +private: + /** + * @brief To access the correct data pool entry on read and commit calls, + * the data pool id is stored. + */ + uint32_t localPoolId; + /** + * @brief The valid information as it was stored in the data pool + * is copied to this attribute. + */ + bool valid; + /** + * @brief The information whether the class is read-write or + * read-only is stored here. + */ + ReadWriteMode_t readWriteMode; + //! @brief Pointer to the class which manages the HK pool. + LocalDataPoolManager* hkManager; + + // std::ostream is the type for object std::cout + template + friend std::ostream& operator<< (std::ostream &out, + const LocalPoolVector &var); + + +}; + +#include "../datapoollocal/LocalPoolVector.tpp" + +template +using lp_vec_t = LocalPoolVector; + +#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ */ diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp new file mode 100644 index 000000000..7c3d2c1ee --- /dev/null +++ b/datapoollocal/LocalPoolVector.tpp @@ -0,0 +1,208 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ +#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ + +#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ +#error Include LocalPoolVector.h before LocalPoolVector.tpp! +#endif + +template +inline LocalPoolVector::LocalPoolVector(lp_id_t poolId, + HasLocalDataPoolIF* hkOwner, pool_rwm_t setReadWriteMode, + DataSetIF* dataSet) : + localPoolId(poolId), valid(false), readWriteMode(setReadWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " + "NO_PARAMETER value!" << std::endl; + } + memset(this->value, 0, vectorSize * sizeof(T)); + hkManager = hkOwner->getHkManagerHandle(); + if (dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline LocalPoolVector::LocalPoolVector(lp_id_t poolId, + object_id_t poolOwner, pool_rwm_t setReadWriteMode, DataSetIF *dataSet): + readWriteMode(readWriteMode) { + if(poolId == PoolVariableIF::NO_PARAMETER) { + sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " + "NO_PARAMETER value!" << std::endl; + } + HasLocalDataPoolIF* hkOwner = + objectManager->get(poolOwner); + if(hkOwner == nullptr) { + sif::error << "LocalPoolVariable: The supplied pool owner did not implement" + "the correct interface HasHkPoolParametersIF!" << std::endl; + return; + } + hkManager = hkOwner->getHkManagerHandle(); + if(dataSet != nullptr) { + dataSet->registerVariable(this); + } +} + +template +inline ReturnValue_t LocalPoolVector::read(uint32_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return readWithoutLock(); +} +template +inline ReturnValue_t LocalPoolVector::readWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_WRITE) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for read() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + memset(this->value, 0, vectorSize * sizeof(T)); + + if(result != RETURN_OK) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << "and lp ID 0x" << localPoolId << + std::dec << " failed." << std::endl; + return result; + } + memcpy(this->value, poolEntry->address, poolEntry->getByteSize()); + this->valid = poolEntry->valid; + return RETURN_OK; +} + +template +inline ReturnValue_t LocalPoolVector::commit( + uint32_t lockTimeout) { + MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, + lockTimeout); + return commitWithoutLock(); +} + +template +inline ReturnValue_t LocalPoolVector::commitWithoutLock() { + if(readWriteMode == pool_rwm_t::VAR_READ) { + sif::debug << "LocalPoolVar: Invalid read write " + "mode for commit() call." << std::endl; + return PoolVariableIF::INVALID_READ_WRITE_MODE; + } + PoolEntry* poolEntry = nullptr; + ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); + if(result != RETURN_OK) { + sif::error << "PoolVector: Read of local pool variable of object " + "0x" << std::hex << std::setw(8) << std::setfill('0') << + hkManager->getOwner() << " and lp ID 0x" << localPoolId << + std::dec << " failed.\n" << std::flush; + return result; + } + memcpy(poolEntry->address, this->value, poolEntry->getByteSize()); + poolEntry->valid = this->valid; + return RETURN_OK; +} + +template +inline T& LocalPoolVector::operator [](int i) { + if(i <= vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. + sif::error << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" << std::endl; + return value[i]; +} + +template +inline const T& LocalPoolVector::operator [](int i) const { + if(i <= vectorSize) { + return value[i]; + } + // If this happens, I have to set some value. I consider this + // a configuration error, but I wont exit here. + sif::error << "LocalPoolVector: Invalid index. Setting or returning" + " last value!" << std::endl; + return value[i]; +} + +template +inline ReturnValue_t LocalPoolVector::serialize(uint8_t** buffer, + size_t* size, size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::serialize(&(value[i]), buffer, size, + maxSize, streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + } + return result; +} + +template +inline size_t LocalPoolVector::getSerializedSize() const { + return vectorSize * SerializeAdapter::getSerializedSize(value); +} + +template +inline ReturnValue_t LocalPoolVector::deSerialize( + const uint8_t** buffer, size_t* size, + SerializeIF::Endianness streamEndianness) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + for (uint16_t i = 0; i < vectorSize; i++) { + result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, + streamEndianness); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + } + return result; +} + +template +inline pool_rwm_t LocalPoolVector::getReadWriteMode() const { + return this->readWriteMode; +} + + +template +inline uint32_t LocalPoolVector::getDataPoolId() const { + return localPoolId; +} + +template +inline void LocalPoolVector::setDataPoolId(uint32_t poolId) { + this->localPoolId = poolId; +} + +template +inline void LocalPoolVector::setValid(bool valid) { + this->valid = valid; +} + +template +inline uint8_t LocalPoolVector::getValid() const { + return valid; +} + +template +inline bool LocalPoolVector::isValid() const { + return valid; +} + +template +inline std::ostream& operator<< (std::ostream &out, + const LocalPoolVector &var) { + out << "Vector: ["; + for(int i = 0;i < vectorSize; i++) { + out << var.value[i]; + if(i < vectorSize - 1) { + out << ", "; + } + } + out << "]"; + return out; +} + +#endif diff --git a/datapoollocal/SharedLocalDataSet.cpp b/datapoollocal/SharedLocalDataSet.cpp new file mode 100644 index 000000000..dd1bdcc40 --- /dev/null +++ b/datapoollocal/SharedLocalDataSet.cpp @@ -0,0 +1,16 @@ +#include "SharedLocalDataSet.h" + +SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid, + const size_t maxSize): SystemObject(objectId), + LocalPoolDataSetBase(sid, nullptr, maxSize) { + this->setContainer(poolVarVector.data()); + datasetLock = MutexFactory::instance()->createMutex(); +} + +ReturnValue_t SharedLocalDataSet::lockDataset(dur_millis_t mutexTimeout) { + return datasetLock->lockMutex(MutexIF::TimeoutType::WAITING, mutexTimeout); +} + +ReturnValue_t SharedLocalDataSet::unlockDataset() { + return datasetLock->unlockMutex(); +} diff --git a/datapoollocal/SharedLocalDataSet.h b/datapoollocal/SharedLocalDataSet.h new file mode 100644 index 000000000..f6748e4da --- /dev/null +++ b/datapoollocal/SharedLocalDataSet.h @@ -0,0 +1,31 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ +#define FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ +#include "../datapool/SharedDataSetIF.h" +#include "../datapoollocal/LocalPoolDataSetBase.h" +#include "../objectmanager/SystemObject.h" +#include + +/** + * Baseline question: If this dataset is shared, is there once instance + * shared among many objects or multiple instances? Maybe be flexible + * and provide both ways? Sharing one instance requires a mutex lock. + * If there are multiple instances, it is not shared anymore, to be fair.. + * Then a regular local data set is sufficient. + */ +class SharedLocalDataSet: public SystemObject, + public LocalPoolDataSetBase, + public SharedDataSetIF { +public: + SharedLocalDataSet(object_id_t objectId, sid_t sid, + const size_t maxSize); + ReturnValue_t lockDataset(dur_millis_t mutexTimeout) override; + ReturnValue_t unlockDataset() override; +private: + + MutexIF* datasetLock = nullptr; + std::vector poolVarVector; +}; + + + +#endif /* FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ */ diff --git a/datapoollocal/StaticLocalDataSet.h b/datapoollocal/StaticLocalDataSet.h new file mode 100644 index 000000000..b3e8422c9 --- /dev/null +++ b/datapoollocal/StaticLocalDataSet.h @@ -0,0 +1,27 @@ +#ifndef FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_ +#define FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_ +#include "LocalPoolDataSetBase.h" +#include "../objectmanager/SystemObjectIF.h" +#include + +/** + * @brief This local dataset type is created on the stack. + * @details + * Size of data set specified as a constructor argument. It is recommended + * to use the default LocalDataSet of the dataset is constructed on the heap + * and the SharedLocalDataSet if it created on the heap and used by multiple + * other software objects. + * @tparam capacity + */ +template +class StaticLocalDataSet: public LocalPoolDataSetBase { +public: + StaticLocalDataSet(sid_t sid): + LocalPoolDataSetBase(sid, poolVarList.data(), NUM_VARIABLES) { + } + +private: + std::array poolVarList; +}; + +#endif /* FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */ -- 2.34.1 From 3bee42811cb74bfb042082dbfcb2aaa9b765c0b7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:34:54 +0200 Subject: [PATCH 5/8] fsfw.mk taken over --- framework.mk => fsfw.mk | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) rename framework.mk => fsfw.mk (80%) diff --git a/framework.mk b/fsfw.mk similarity index 80% rename from framework.mk rename to fsfw.mk index 05265c7bc..a548b6a88 100644 --- a/framework.mk +++ b/fsfw.mk @@ -1,5 +1,6 @@ -# This file needs FRAMEWORK_PATH and API set correctly -# Valid API settings: rtems, linux, freeRTOS +# This submake file needs to be included by the primary Makefile. +# This file needs FRAMEWORK_PATH and OS_FSFW set correctly by another Makefile. +# Valid API settings: rtems, linux, freeRTOS, host CXXSRC += $(wildcard $(FRAMEWORK_PATH)/action/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/container/*.cpp) @@ -9,11 +10,12 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/fdir/*.cpp) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/framework.mk/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/matching/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/math/*.cpp) @@ -27,14 +29,16 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/objectmanager/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) # select the OS -ifeq ($(OS),rtems) +ifeq ($(OS_FSFW),rtems) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) -else ifeq ($(OS),linux) +else ifeq ($(OS_FSFW),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) -else ifeq ($(OS),freeRTOS) +else ifeq ($(OS_FSFW),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) +else ifeq ($(OS_FSFW),host) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) else -$(error invalid OS specified, valid OS are rtems, linux, freeRTOS) +$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) endif CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) @@ -55,3 +59,4 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/pus/*.cpp) -- 2.34.1 From b4173f4e0578e68e372507251d4a550ebecb3051 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:37:32 +0200 Subject: [PATCH 6/8] updated all other modules using pool --- internalError/InternalErrorReporter.cpp | 33 ++++++++++++------------- monitoring/MonitorBase.h | 12 ++++----- power/Fuse.cpp | 14 +++++------ power/Fuse.h | 20 +++++++-------- power/PowerSensor.h | 16 ++++++------ thermal/CoreComponent.cpp | 4 +-- thermal/CoreComponent.h | 13 +++++----- thermal/ThermalComponent.cpp | 12 ++++----- thermal/ThermalComponent.h | 26 ++++++++++++++++++- thermal/ThermalModule.cpp | 4 +-- thermal/ThermalModule.h | 11 ++++++--- 11 files changed, 95 insertions(+), 70 deletions(-) diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index ec69108a4..3424266bd 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -1,17 +1,16 @@ +#include "../datapoolglob/GlobalDataSet.h" #include "InternalErrorReporter.h" -#include -#include -#include +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../ipc/MutexFactory.h" -#include +#include "../serviceinterface/ServiceInterfaceStream.h" InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) : - SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId), tmPoolId( - tmPoolId), storePoolId( - storePoolId), queueHits(0), tmHits(0), storeHits( - 0) { + SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId), + tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0), + storeHits(0) { mutex = MutexFactory::instance()->createMutex(); } @@ -54,7 +53,7 @@ void InternalErrorReporter::lostTm() { uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = queueHits; queueHits = 0; mutex->unlockMutex(); @@ -63,21 +62,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t InternalErrorReporter::getQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = queueHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementQueueHits() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); queueHits++; mutex->unlockMutex(); } uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = tmHits; tmHits = 0; mutex->unlockMutex(); @@ -86,14 +85,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t InternalErrorReporter::getTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = tmHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementTmHits() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); tmHits++; mutex->unlockMutex(); } @@ -104,7 +103,7 @@ void InternalErrorReporter::storeFull() { uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = storeHits; storeHits = 0; mutex->unlockMutex(); @@ -113,14 +112,14 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t InternalErrorReporter::getStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); value = storeHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementStoreHits() { - mutex->lockMutex(MutexIF::NO_TIMEOUT); + mutex->lockMutex(MutexIF::BLOCKING); storeHits++; mutex->unlockMutex(); } diff --git a/monitoring/MonitorBase.h b/monitoring/MonitorBase.h index f18ca4b5c..5173c4798 100644 --- a/monitoring/MonitorBase.h +++ b/monitoring/MonitorBase.h @@ -1,12 +1,12 @@ #ifndef MONITORBASE_H_ #define MONITORBASE_H_ -#include -#include -#include -#include -#include -#include +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/PIDReader.h" +#include "../monitoring/LimitViolationReporter.h" +#include "../monitoring/MonitoringIF.h" +#include "../monitoring/MonitoringMessageContent.h" +#include "../monitoring/MonitorReporter.h" /** * Base class for monitoring of parameters. diff --git a/power/Fuse.cpp b/power/Fuse.cpp index eabd6e70b..3ea0b18cc 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include -#include -#include +#include "../monitoring/LimitViolationReporter.h" +#include "../monitoring/MonitoringMessageContent.h" +#include "../objectmanager/ObjectManagerIF.h" +#include "../power/Fuse.h" +#include "../serialize/SerialFixedArrayListAdapter.h" +#include "../ipc/QueueFactory.h" object_id_t Fuse::powerSwitchId = 0; @@ -109,7 +109,7 @@ size_t Fuse::getSerializedSize() const { } ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, size_t* size, -Endianness streamEndianness) { + Endianness streamEndianness) { ReturnValue_t result = RETURN_FAILED; for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); iter++) { diff --git a/power/Fuse.h b/power/Fuse.h index e105e84b3..dd8759f47 100644 --- a/power/Fuse.h +++ b/power/Fuse.h @@ -1,15 +1,15 @@ #ifndef FUSE_H_ #define FUSE_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../datapoolglob/PIDReader.h" +#include "../devicehandlers/HealthDevice.h" +#include "../monitoring/AbsLimitMonitor.h" +#include "../power/PowerComponentIF.h" +#include "../power/PowerSwitchIF.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../parameters/ParameterHelper.h" #include namespace Factory { @@ -90,7 +90,7 @@ private: PIDReader current; PIDReader state; gp_float_t power; - MessageQueueIF *commandQueue; + MessageQueueIF* commandQueue; ParameterHelper parameterHelper; HealthHelper healthHelper; static object_id_t powerSwitchId; diff --git a/power/PowerSensor.h b/power/PowerSensor.h index 159bc7ff9..da0bd8c73 100644 --- a/power/PowerSensor.h +++ b/power/PowerSensor.h @@ -1,14 +1,14 @@ #ifndef POWERSENSOR_H_ #define POWERSENSOR_H_ -#include -#include -#include -#include -#include -#include -#include -#include +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../datapoolglob/PIDReader.h" +#include "../devicehandlers/HealthDevice.h" +#include "../monitoring/LimitMonitor.h" +#include "../parameters/ParameterHelper.h" +#include "../objectmanager/SystemObject.h" +#include "../ipc/MessageQueueIF.h" class PowerController; diff --git a/thermal/CoreComponent.cpp b/thermal/CoreComponent.cpp index 0c74a7f0b..657e79cb0 100644 --- a/thermal/CoreComponent.cpp +++ b/thermal/CoreComponent.cpp @@ -25,7 +25,7 @@ CoreComponent::CoreComponent(object_id_t reportingObjectId, uint8_t domainId, } //Set thermal state once, then leave to operator. GlobDataSet mySet; - gp_int8_t writableTargetState(targetStatePoolId, &mySet, + gp_uint8_t writableTargetState(targetStatePoolId, &mySet, PoolVariableIF::VAR_WRITE); writableTargetState = initialTargetState; mySet.commit(PoolVariableIF::VALID); @@ -71,7 +71,7 @@ float CoreComponent::getLowerOpLimit() { ReturnValue_t CoreComponent::setTargetState(int8_t newState) { GlobDataSet mySet; - gp_int8_t writableTargetState(targetState.getDataPoolId(), + gp_uint8_t writableTargetState(targetState.getDataPoolId(), &mySet, PoolVariableIF::VAR_READ_WRITE); mySet.read(); if ((writableTargetState == STATE_REQUEST_OPERATIONAL) diff --git a/thermal/CoreComponent.h b/thermal/CoreComponent.h index ed89ff48d..8093711d6 100644 --- a/thermal/CoreComponent.h +++ b/thermal/CoreComponent.h @@ -1,13 +1,14 @@ #ifndef MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ #define MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ -#include -#include -#include -#include -#include -#include +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../thermal/ThermalComponentIF.h" +#include "../thermal/AbstractTemperatureSensor.h" +#include "../thermal/ThermalModule.h" +#include "../thermal/ThermalMonitor.h" +// TODO: Documentaiton, how to use this? only use Thermal Component, which inherits core component? class CoreComponent: public ThermalComponentIF { public: struct Parameters { diff --git a/thermal/ThermalComponent.cpp b/thermal/ThermalComponent.cpp index 75107a2eb..50786654b 100644 --- a/thermal/ThermalComponent.cpp +++ b/thermal/ThermalComponent.cpp @@ -12,12 +12,10 @@ ThermalComponent::ThermalComponent(object_id_t reportingObjectId, CoreComponent(reportingObjectId, domainId, temperaturePoolId, targetStatePoolId, currentStatePoolId, requestPoolId, dataSet, sensor, firstRedundantSensor, secondRedundantSensor, - thermalModule, - { parameters.lowerOpLimit, parameters.upperOpLimit, - parameters.heaterOn, parameters.hysteresis, - parameters.heaterSwitchoff }, priority, - ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL), nopParameters( - { parameters.lowerNopLimit, parameters.upperNopLimit }) { + thermalModule,{ parameters.lowerOpLimit, parameters.upperOpLimit, + parameters.heaterOn, parameters.hysteresis, parameters.heaterSwitchoff }, + priority, ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL), + nopParameters({ parameters.lowerNopLimit, parameters.upperNopLimit }) { } ThermalComponent::~ThermalComponent() { @@ -42,7 +40,7 @@ ReturnValue_t ThermalComponent::setTargetState(int8_t newState) { } } -ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, uint32_t size) { +ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, size_t size) { if (size != 4 * sizeof(parameters.lowerOpLimit)) { return MonitoringIF::INVALID_SIZE; } diff --git a/thermal/ThermalComponent.h b/thermal/ThermalComponent.h index c70fcdab3..195f03b10 100644 --- a/thermal/ThermalComponent.h +++ b/thermal/ThermalComponent.h @@ -3,6 +3,9 @@ #include "CoreComponent.h" +/** + * What is it. How to use + */ class ThermalComponent: public CoreComponent { public: struct Parameters { @@ -14,10 +17,31 @@ public: float hysteresis; float heaterSwitchoff; }; + + /** + * Non-Operational Temperatures + */ struct NopParameters { float lowerNopLimit; float upperNopLimit; }; + + /** + * How to use. + * @param reportingObjectId + * @param domainId + * @param temperaturePoolId + * @param targetStatePoolId + * @param currentStatePoolId + * @param requestPoolId + * @param dataSet + * @param sensor + * @param firstRedundantSensor + * @param secondRedundantSensor + * @param thermalModule + * @param parameters + * @param priority + */ ThermalComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, uint32_t targetStatePoolId, uint32_t currentStatePoolId, uint32_t requestPoolId, GlobDataSet *dataSet, AbstractTemperatureSensor *sensor, @@ -29,7 +53,7 @@ public: ReturnValue_t setTargetState(int8_t newState); - virtual ReturnValue_t setLimits( const uint8_t* data, uint32_t size); + virtual ReturnValue_t setLimits( const uint8_t* data, size_t size); virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper *parameterWrapper, diff --git a/thermal/ThermalModule.cpp b/thermal/ThermalModule.cpp index 9dc1f2372..fbd6939e7 100644 --- a/thermal/ThermalModule.cpp +++ b/thermal/ThermalModule.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "../monitoring/LimitViolationReporter.h" +#include "../monitoring/MonitoringMessageContent.h" #include "ThermalModule.h" #include "AbstractTemperatureSensor.h" diff --git a/thermal/ThermalModule.h b/thermal/ThermalModule.h index 8a4d0cdb7..41be6baae 100644 --- a/thermal/ThermalModule.h +++ b/thermal/ThermalModule.h @@ -1,16 +1,19 @@ #ifndef THERMALMODULE_H_ #define THERMALMODULE_H_ -#include -#include -#include -#include +#include "../datapoolglob/GlobalDataSet.h" +#include "../datapoolglob/GlobalPoolVariable.h" +#include "../devicehandlers/HealthDevice.h" +#include "../events/EventReportingProxyIF.h" #include "ThermalModuleIF.h" #include #include "tcsDefinitions.h" #include "RedundantHeater.h" class PowerSwitchIF; +/** + * @brief Allows creation of different thermal control domains within a system. + */ class ThermalModule: public ThermalModuleIF { friend class ThermalController; public: -- 2.34.1 From 08235b2e5fb2baa8f21530d7be3aa0f2f368c34d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:40:07 +0200 Subject: [PATCH 7/8] deleted old dataset base --- datapool/DataSetBase.cpp | 168 --------------------------------------- datapool/DataSetBase.h | 149 ---------------------------------- 2 files changed, 317 deletions(-) delete mode 100644 datapool/DataSetBase.cpp delete mode 100644 datapool/DataSetBase.h diff --git a/datapool/DataSetBase.cpp b/datapool/DataSetBase.cpp deleted file mode 100644 index cb7a78993..000000000 --- a/datapool/DataSetBase.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include - -DataSetBase::DataSetBase(PoolVariableIF** registeredVariablesArray, - const size_t maxFillCount): - registeredVariables(registeredVariablesArray), - maxFillCount(maxFillCount) { - for (uint8_t count = 0; count < maxFillCount; count++) { - registeredVariables[count] = nullptr; - } -} - -DataSetBase::~DataSetBase() {} - -ReturnValue_t DataSetBase::registerVariable( - PoolVariableIF *variable) { - if (state != States::DATA_SET_UNINITIALISED) { - sif::error << "DataSet::registerVariable: " - "Call made in wrong position." << std::endl; - return DataSetIF::DATA_SET_UNINITIALISED; - } - if (variable == nullptr) { - sif::error << "DataSet::registerVariable: " - "Pool variable is nullptr." << std::endl; - return DataSetIF::POOL_VAR_NULL; - } - if (fillCount >= maxFillCount) { - sif::error << "DataSet::registerVariable: " - "DataSet is full." << std::endl; - return DataSetIF::DATA_SET_FULL; - } - registeredVariables[fillCount] = variable; - fillCount++; - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t DataSetBase::read(uint32_t lockTimeout) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - if (state == States::DATA_SET_UNINITIALISED) { - lockDataPool(lockTimeout); - for (uint16_t count = 0; count < fillCount; count++) { - result = readVariable(count); - if(result != RETURN_OK) { - break; - } - } - state = States::DATA_SET_WAS_READ; - unlockDataPool(); - } - else { - sif::error << "DataSet::read(): " - "Call made in wrong position. Don't forget to commit" - " member datasets!" << std::endl; - result = SET_WAS_ALREADY_READ; - } - return result; -} - -uint16_t DataSetBase::getFillCount() const { - return fillCount; -} - -ReturnValue_t DataSetBase::readVariable(uint16_t count) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - // These checks are often performed by the respective - // variable implementation too, but I guess a double check does not hurt. - if (registeredVariables[count]->getReadWriteMode() != - PoolVariableIF::VAR_WRITE and - registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) - { - result = registeredVariables[count]->readWithoutLock(); - if(result != HasReturnvaluesIF::RETURN_OK) { - result = INVALID_PARAMETER_DEFINITION; - } - } - return result; -} - -ReturnValue_t DataSetBase::commit(uint32_t lockTimeout) { - if (state == States::DATA_SET_WAS_READ) { - handleAlreadyReadDatasetCommit(lockTimeout); - return HasReturnvaluesIF::RETURN_OK; - } - else { - return handleUnreadDatasetCommit(lockTimeout); - } -} - -void DataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { - lockDataPool(lockTimeout); - for (uint16_t count = 0; count < fillCount; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_READ - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commitWithoutLock(); - } - } - state = States::DATA_SET_UNINITIALISED; - unlockDataPool(); -} - -ReturnValue_t DataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - lockDataPool(lockTimeout); - for (uint16_t count = 0; count < fillCount; count++) { - if (registeredVariables[count]->getReadWriteMode() - == PoolVariableIF::VAR_WRITE - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commitWithoutLock(); - } else if (registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - if (result != COMMITING_WITHOUT_READING) { - sif::error << "DataSet::commit(): commit-without-read call made " - "with non write-only variable." << std::endl; - result = COMMITING_WITHOUT_READING; - } - } - } - state = States::DATA_SET_UNINITIALISED; - unlockDataPool(); - return result; -} - - -ReturnValue_t DataSetBase::lockDataPool(uint32_t timeoutMs) { - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t DataSetBase::unlockDataPool() { - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t DataSetBase::serialize(uint8_t** buffer, size_t* size, - const size_t maxSize, SerializeIF::Endianness streamEndianness) const { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - for (uint16_t count = 0; count < fillCount; count++) { - result = registeredVariables[count]->serialize(buffer, size, maxSize, - streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - return result; -} - -ReturnValue_t DataSetBase::deSerialize(const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - for (uint16_t count = 0; count < fillCount; count++) { - result = registeredVariables[count]->deSerialize(buffer, size, - streamEndianness); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - return result; -} - -size_t DataSetBase::getSerializedSize() const { - uint32_t size = 0; - for (uint16_t count = 0; count < fillCount; count++) { - size += registeredVariables[count]->getSerializedSize(); - } - return size; -} diff --git a/datapool/DataSetBase.h b/datapool/DataSetBase.h deleted file mode 100644 index 41ab0e635..000000000 --- a/datapool/DataSetBase.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef FRAMEWORK_DATAPOOL_DATASETBASE_H_ -#define FRAMEWORK_DATAPOOL_DATASETBASE_H_ -#include -#include -#include - -/** - * @brief The DataSetBase class manages a set of locally checked out variables. - * @details - * This class manages a list, where a set of local variables (or pool variables) - * are registered. They are checked-out (i.e. their values are looked - * up and copied) with the read call. After the user finishes working with the - * pool variables, he can write back all variable values to the pool with - * the commit call. The data set manages locking and freeing the data pool, - * to ensure that all values are read and written back at once. - * - * An internal state manages usage of this class. Variables may only be - * registered before the read call is made, and the commit call only - * after the read call. - * - * If pool variables are writable and not committed until destruction - * of the set, the DataSet class automatically sets the valid flag in the - * data pool to invalid (without) changing the variable's value. - * - * The base class lockDataPool und unlockDataPool implementation are empty - * and should be implemented to protect the underlying pool type. - * @author Bastian Baetz - * @ingroup data_pool - */ -class DataSetBase: public DataSetIF, - public SerializeIF, - public HasReturnvaluesIF { -public: - - /** - * @brief Creates an empty dataset. Use registerVariable or - * supply a pointer to this dataset to PoolVariable - * initializations to register pool variables. - */ - DataSetBase(PoolVariableIF** registeredVariablesArray, - const size_t maxFillCount); - virtual~ DataSetBase(); - - /** - * @brief The read call initializes reading out all registered variables. - * @details - * It iterates through the list of registered variables and calls all read() - * functions of the registered pool variables (which read out their values - * from the data pool) which are not write-only. - * In case of an error (e.g. a wrong data type, or an invalid data pool id), - * the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned. - * - * The data pool is locked during the whole read operation and - * freed afterwards.The state changes to "was written" after this operation. - * @return - * - @c RETURN_OK if all variables were read successfully. - * - @c INVALID_PARAMETER_DEFINITION if PID, size or type of the - * requested variable is invalid. - * - @c SET_WAS_ALREADY_READ if read() is called twice without calling - * commit() in between - */ - virtual ReturnValue_t read(uint32_t lockTimeout = - MutexIF::NO_TIMEOUT) override; - /** - * @brief The commit call initializes writing back the registered variables. - * @details - * It iterates through the list of registered variables and calls the - * commit() method of the remaining registered variables (which write back - * their values to the pool). - * - * The data pool is locked during the whole commit operation and - * freed afterwards. The state changes to "was committed" after this operation. - * - * If the set does contain at least one variable which is not write-only - * commit() can only be called after read(). If the set only contains - * variables which are write only, commit() can be called without a - * preceding read() call. - * @return - @c RETURN_OK if all variables were read successfully. - * - @c COMMITING_WITHOUT_READING if set was not read yet and - * contains non write-only variables - */ - virtual ReturnValue_t commit(uint32_t lockTimeout = - MutexIF::NO_TIMEOUT) override; - - /** - * Register the passed pool variable instance into the data set. - * @param variable - * @return - */ - virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override; - /** - * Provides the means to lock the underlying data structure to ensure - * thread-safety. Default implementation is empty - * @return Always returns -@c RETURN_OK - */ - virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = - MutexIF::NO_TIMEOUT) override; - /** - * Provides the means to unlock the underlying data structure to ensure - * thread-safety. Default implementation is empty - * @return Always returns -@c RETURN_OK - */ - virtual ReturnValue_t unlockDataPool() override; - - virtual uint16_t getFillCount() const; - - /* SerializeIF implementations */ - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - const size_t maxSize, - SerializeIF::Endianness streamEndianness) const override; - virtual size_t getSerializedSize() const override; - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - SerializeIF::Endianness streamEndianness) override; - -protected: - /** - * @brief The fill_count attribute ensures that the variables - * register in the correct array position and that the maximum - * number of variables is not exceeded. - */ - uint16_t fillCount = 0; - /** - * States of the seet. - */ - enum class States { - DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED - DATA_SET_WAS_READ //!< DATA_SET_WAS_READ - }; - /** - * @brief state manages the internal state of the data set, - * which is important e.g. for the behavior on destruction. - */ - States state = States::DATA_SET_UNINITIALISED; - - /** - * @brief This array represents all pool variables registered in this set. - * Child classes can use a static or dynamic container to create - * an array of registered variables and assign the first entry here. - */ - PoolVariableIF** registeredVariables = nullptr; - const size_t maxFillCount = 0; - -private: - ReturnValue_t readVariable(uint16_t count); - void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); - ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); -}; - -#endif /* FRAMEWORK_DATAPOOL_DATASETBASE_H_ */ -- 2.34.1 From 19fea9fb808a97377a52d8bdd81c47b4e47e5189 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 5 Sep 2020 21:43:11 +0200 Subject: [PATCH 8/8] hk switch helper changes discarded --- datapool/HkSwitchHelper.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/datapool/HkSwitchHelper.cpp b/datapool/HkSwitchHelper.cpp index 1a2a25eb9..04096acaf 100644 --- a/datapool/HkSwitchHelper.cpp +++ b/datapool/HkSwitchHelper.cpp @@ -1,4 +1,5 @@ -#include "../datapool/HkSwitchHelper.h" +#include "HkSwitchHelper.h" +//#include #include "../ipc/QueueFactory.h" HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) : @@ -21,14 +22,14 @@ ReturnValue_t HkSwitchHelper::initialize() { } ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) { - CommandMessage command; - while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) { - ReturnValue_t result = commandActionHelper.handleReply(&command); + CommandMessage message; + while (actionQueue->receiveMessage(&message) == HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = commandActionHelper.handleReply(&message); if (result == HasReturnvaluesIF::RETURN_OK) { continue; } - command.setToUnknownCommand(); - actionQueue->reply(&command); + message.setToUnknownCommand(); + actionQueue->reply(&message); } return HasReturnvaluesIF::RETURN_OK; -- 2.34.1