Merge pull request 'Local Pool Update' (#349) from KSat/fsfw:mueller/local-pool-update into development

Reviewed-on: fsfw/fsfw#349
This commit is contained in:
Steffen Gaisser 2021-01-19 15:38:07 +01:00
commit 543e0d4649
91 changed files with 3534 additions and 1985 deletions

View File

@ -107,7 +107,8 @@ else()
endif() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(WARNING_FLAGS if(NOT DEFINED FSFW_WARNING_FLAGS)
set(FSFW_WARNING_FLAGS
-Wall -Wall
-Wextra -Wextra
-Wshadow=local -Wshadow=local
@ -116,6 +117,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-Wno-psabi -Wno-psabi
) )
endif() endif()
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-") set(COMPILER_FLAGS "/permissive-")
@ -135,8 +137,7 @@ target_include_directories(${LIB_FSFW_NAME} PRIVATE
${FSFW_CONFIG_PATH_ABSOLUTE} ${FSFW_CONFIG_PATH_ABSOLUTE}
) )
# Machine specific options can be set with the ABI_FLAGS variable.
target_compile_options(${LIB_FSFW_NAME} PRIVATE target_compile_options(${LIB_FSFW_NAME} PRIVATE
${WARNING_FLAGS} ${FSFW_WARNING_FLAGS}
${COMPILER_FLAGS} ${COMPILER_FLAGS}
) )

View File

@ -3,6 +3,7 @@
#include "ArrayList.h" #include "ArrayList.h"
#include <cstring> #include <cstring>
#include <functional>
/** /**
* @brief An associative container which allows multiple entries of the same key. * @brief An associative container which allows multiple entries of the same key.

View File

@ -4,7 +4,7 @@
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
object_id_t parentId, size_t commandQueueDepth): object_id_t parentId, size_t commandQueueDepth):
ControllerBase(objectId, parentId, commandQueueDepth), ControllerBase(objectId, parentId, commandQueueDepth),
localPoolManager(this, commandQueue), poolManager(this, commandQueue),
actionHelper(this, commandQueue) { actionHelper(this, commandQueue) {
} }
@ -17,7 +17,7 @@ ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
ReturnValue_t ExtendedControllerBase::initializeLocalDataPool( ReturnValue_t ExtendedControllerBase::initializeLocalDataPool(
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
// needs to be overriden and implemented by child class. // needs to be overriden and implemented by child class.
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -26,10 +26,6 @@ object_id_t ExtendedControllerBase::getObjectId() const {
return SystemObject::getObjectId(); return SystemObject::getObjectId();
} }
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
return &localPoolManager;
}
uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const { uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs(); return this->executingTask->getPeriodMs();
} }
@ -40,7 +36,7 @@ ReturnValue_t ExtendedControllerBase::handleCommandMessage(
if(result == HasReturnvaluesIF::RETURN_OK) { if(result == HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return localPoolManager.handleHousekeepingMessage(message); return poolManager.handleHousekeepingMessage(message);
} }
void ExtendedControllerBase::handleQueue() { void ExtendedControllerBase::handleQueue() {
@ -64,7 +60,7 @@ void ExtendedControllerBase::handleQueue() {
continue; continue;
} }
result = localPoolManager.handleHousekeepingMessage(&command); result = poolManager.handleHousekeepingMessage(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
@ -88,16 +84,16 @@ ReturnValue_t ExtendedControllerBase::initialize() {
return result; return result;
} }
return localPoolManager.initialize(commandQueue); return poolManager.initialize(commandQueue);
} }
ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() { ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
return localPoolManager.initializeAfterTaskCreation(); return poolManager.initializeAfterTaskCreation();
} }
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) { ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
handleQueue(); handleQueue();
localPoolManager.performHkOperation(); poolManager.performHkOperation();
performControlOperation(); performControlOperation();
return RETURN_OK; return RETURN_OK;
} }
@ -113,3 +109,7 @@ LocalPoolDataSetBase* ExtendedControllerBase::getDataSetHandle(sid_t sid) {
#endif #endif
return nullptr; return nullptr;
} }
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
return &poolManager;
}

View File

@ -33,7 +33,7 @@ public:
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t initializeAfterTaskCreation() override;
protected: protected:
LocalDataPoolManager localPoolManager; LocalDataPoolManager poolManager;
ActionHelper actionHelper; ActionHelper actionHelper;
/** /**
@ -58,11 +58,11 @@ protected:
size_t size) override; size_t size) override;
/** HasLocalDatapoolIF overrides */ /** HasLocalDatapoolIF overrides */
virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual object_id_t getObjectId() const override; virtual object_id_t getObjectId() const override;
virtual ReturnValue_t initializeLocalDataPool( virtual ReturnValue_t initializeLocalDataPool(
LocalDataPool& localDataPoolMap, localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override; LocalDataPoolManager& poolManager) override;
virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual uint32_t getPeriodicOperationFrequency() const override; virtual uint32_t getPeriodicOperationFrequency() const override;
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
}; };

View File

@ -38,11 +38,12 @@ ReturnValue_t PoolDataSetBase::registerVariable(
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t PoolDataSetBase::read(uint32_t lockTimeout) { ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
ReturnValue_t error = result; ReturnValue_t error = result;
if (state == States::STATE_SET_UNINITIALISED) { if (state == States::STATE_SET_UNINITIALISED) {
lockDataPool(lockTimeout); lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) { for (uint16_t count = 0; count < fillCount; count++) {
result = readVariable(count); result = readVariable(count);
if(result != RETURN_OK) { if(result != RETURN_OK) {
@ -86,7 +87,9 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
!= PoolVariableIF::NO_PARAMETER) != PoolVariableIF::NO_PARAMETER)
{ {
if(protectEveryReadCommitCall) { if(protectEveryReadCommitCall) {
result = registeredVariables[count]->read(mutexTimeout); result = registeredVariables[count]->read(
timeoutTypeForSingleVars,
mutexTimeoutForSingleVars);
} }
else { else {
result = registeredVariables[count]->readWithoutLock(); result = registeredVariables[count]->readWithoutLock();
@ -99,25 +102,29 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
return result; return result;
} }
ReturnValue_t PoolDataSetBase::commit(uint32_t lockTimeout) { ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
if (state == States::STATE_SET_WAS_READ) { if (state == States::STATE_SET_WAS_READ) {
handleAlreadyReadDatasetCommit(lockTimeout); handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
return handleUnreadDatasetCommit(lockTimeout); return handleUnreadDatasetCommit(timeoutType, lockTimeout);
} }
} }
void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { void PoolDataSetBase::handleAlreadyReadDatasetCommit(
lockDataPool(lockTimeout); MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) { for (uint16_t count = 0; count < fillCount; count++) {
if (registeredVariables[count]->getReadWriteMode() if (registeredVariables[count]->getReadWriteMode()
!= PoolVariableIF::VAR_READ != PoolVariableIF::VAR_READ
&& registeredVariables[count]->getDataPoolId() && registeredVariables[count]->getDataPoolId()
!= PoolVariableIF::NO_PARAMETER) { != PoolVariableIF::NO_PARAMETER) {
if(protectEveryReadCommitCall) { if(protectEveryReadCommitCall) {
registeredVariables[count]->commit(mutexTimeout); registeredVariables[count]->commit(
timeoutTypeForSingleVars,
mutexTimeoutForSingleVars);
} }
else { else {
registeredVariables[count]->commitWithoutLock(); registeredVariables[count]->commitWithoutLock();
@ -128,16 +135,19 @@ void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) {
unlockDataPool(); unlockDataPool();
} }
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
lockDataPool(lockTimeout); lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) { for (uint16_t count = 0; count < fillCount; count++) {
if (registeredVariables[count]->getReadWriteMode() if (registeredVariables[count]->getReadWriteMode()
== PoolVariableIF::VAR_WRITE == PoolVariableIF::VAR_WRITE
&& registeredVariables[count]->getDataPoolId() && registeredVariables[count]->getDataPoolId()
!= PoolVariableIF::NO_PARAMETER) { != PoolVariableIF::NO_PARAMETER) {
if(protectEveryReadCommitCall) { if(protectEveryReadCommitCall) {
result = registeredVariables[count]->commit(mutexTimeout); result = registeredVariables[count]->commit(
timeoutTypeForSingleVars,
mutexTimeoutForSingleVars);
} }
else { else {
result = registeredVariables[count]->commitWithoutLock(); result = registeredVariables[count]->commitWithoutLock();
@ -160,7 +170,8 @@ ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) {
} }
ReturnValue_t PoolDataSetBase::lockDataPool(uint32_t timeoutMs) { ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -206,8 +217,14 @@ void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
this->registeredVariables = variablesContainer; this->registeredVariables = variablesContainer;
} }
void PoolDataSetBase::setReadCommitProtectionBehaviour( PoolVariableIF** PoolDataSetBase::getContainer() const {
bool protectEveryReadCommit, uint32_t mutexTimeout) { return registeredVariables;
this->protectEveryReadCommitCall = protectEveryReadCommit; }
this->mutexTimeout = mutexTimeout;
void PoolDataSetBase::setReadCommitProtectionBehaviour(
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType,
uint32_t mutexTimeout) {
this->protectEveryReadCommitCall = protectEveryReadCommit;
this->timeoutTypeForSingleVars = timeoutType;
this->mutexTimeoutForSingleVars = mutexTimeout;
} }

View File

@ -3,6 +3,7 @@
#include "PoolDataSetIF.h" #include "PoolDataSetIF.h"
#include "PoolVariableIF.h" #include "PoolVariableIF.h"
#include "../serialize/SerializeIF.h"
#include "../ipc/MutexIF.h" #include "../ipc/MutexIF.h"
/** /**
@ -62,8 +63,9 @@ public:
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling * - @c SET_WAS_ALREADY_READ if read() is called twice without calling
* commit() in between * commit() in between
*/ */
virtual ReturnValue_t read(uint32_t lockTimeout = virtual ReturnValue_t read(
MutexIF::BLOCKING) override; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override;
/** /**
* @brief The commit call initializes writing back the registered variables. * @brief The commit call initializes writing back the registered variables.
* @details * @details
@ -82,8 +84,9 @@ public:
* - @c COMMITING_WITHOUT_READING if set was not read yet and * - @c COMMITING_WITHOUT_READING if set was not read yet and
* contains non write-only variables * contains non write-only variables
*/ */
virtual ReturnValue_t commit(uint32_t lockTimeout = virtual ReturnValue_t commit(
MutexIF::BLOCKING) override; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override;
/** /**
* Register the passed pool variable instance into the data set. * Register the passed pool variable instance into the data set.
@ -97,8 +100,9 @@ public:
* thread-safety. Default implementation is empty * thread-safety. Default implementation is empty
* @return Always returns -@c RETURN_OK * @return Always returns -@c RETURN_OK
*/ */
virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = virtual ReturnValue_t lockDataPool(
MutexIF::BLOCKING) override; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/** /**
* Provides the means to unlock the underlying data structure to ensure * Provides the means to unlock the underlying data structure to ensure
* thread-safety. Default implementation is empty * thread-safety. Default implementation is empty
@ -116,15 +120,15 @@ public:
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override; SerializeIF::Endianness streamEndianness) override;
protected:
/** /**
* Can be used to individually protect every read and commit call. * Can be used to individually protect every read and commit call.
* @param protectEveryReadCommit * @param protectEveryReadCommit
* @param mutexTimeout * @param mutexTimeout
*/ */
void setReadCommitProtectionBehaviour(bool protectEveryReadCommit, void setReadCommitProtectionBehaviour(bool protectEveryReadCommit,
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t mutexTimeout = 20); uint32_t mutexTimeout = 20);
protected:
/** /**
* @brief The fill_count attribute ensures that the variables * @brief The fill_count attribute ensures that the variables
@ -154,14 +158,20 @@ protected:
const size_t maxFillCount = 0; const size_t maxFillCount = 0;
void setContainer(PoolVariableIF** variablesContainer); void setContainer(PoolVariableIF** variablesContainer);
PoolVariableIF** getContainer() const;
private: private:
bool protectEveryReadCommitCall = false; bool protectEveryReadCommitCall = false;
uint32_t mutexTimeout = 20; MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
uint32_t mutexTimeoutForSingleVars = 20;
ReturnValue_t readVariable(uint16_t count); ReturnValue_t readVariable(uint16_t count);
void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); void handleAlreadyReadDatasetCommit(
ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20);
ReturnValue_t handleUnreadDatasetCommit(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20);
}; };
#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */ #endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */

View File

@ -18,7 +18,10 @@ public:
* thread-safety * thread-safety
* @return Lock operation result * @return Lock operation result
*/ */
virtual ReturnValue_t lockDataPool(dur_millis_t timeoutMs) = 0; virtual ReturnValue_t lockDataPool(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) = 0;
/** /**
* @brief Unlock call corresponding to the lock call. * @brief Unlock call corresponding to the lock call.
* @return Unlock operation result * @return Unlock operation result

View File

@ -25,6 +25,7 @@ class PoolVariableIF : public SerializeIF,
public: public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF; 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 ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
static constexpr bool VALID = 1; static constexpr bool VALID = 1;
static constexpr bool INVALID = 0; static constexpr bool INVALID = 0;

View File

@ -1,7 +1,8 @@
#ifndef FSFW_DATAPOOL_READCOMMITIF_H_ #ifndef FSFW_DATAPOOL_READCOMMITIF_H_
#define FSFW_DATAPOOL_READCOMMITIF_H_ #define FSFW_DATAPOOL_READCOMMITIF_H_
#include <fsfw/returnvalues/HasReturnvaluesIF.h> #include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MutexIF.h"
/** /**
* @brief Common interface for all software objects which employ read-commit * @brief Common interface for all software objects which employ read-commit
@ -10,8 +11,10 @@
class ReadCommitIF { class ReadCommitIF {
public: public:
virtual ~ReadCommitIF() {} virtual ~ReadCommitIF() {}
virtual ReturnValue_t read(uint32_t mutexTimeout) = 0; virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType,
virtual ReturnValue_t commit(uint32_t mutexTimeout) = 0; uint32_t timeoutMs) = 0;
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) = 0;
protected: protected:
@ -19,11 +22,11 @@ protected:
//! members with commit and read semantics where the lock is only necessary //! members with commit and read semantics where the lock is only necessary
//! once. //! once.
virtual ReturnValue_t readWithoutLock() { virtual ReturnValue_t readWithoutLock() {
return read(20); return read(MutexIF::TimeoutType::WAITING, 20);
} }
virtual ReturnValue_t commitWithoutLock() { virtual ReturnValue_t commitWithoutLock() {
return commit(20); return commit(MutexIF::TimeoutType::WAITING, 20);
} }
}; };

View File

@ -0,0 +1,27 @@
#ifndef FSFW_DATAPOOLLOCAL_ACCESSLOCALPOOLF_H_
#define FSFW_DATAPOOLLOCAL_ACCESSLOCALPOOLF_H_
class LocalDataPoolManager;
class MutexIF;
/**
* @brief Accessor class which can be used by classes which like to use the pool manager.
*/
class AccessPoolManagerIF {
public:
virtual ~AccessPoolManagerIF() {};
virtual MutexIF* getLocalPoolMutex() = 0;
/**
* Can be used to get a handle to the local data pool manager.
* This function is protected because it should only be used by the
* class imlementing the interface.
*/
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
protected:
};
#endif /* FSFW_DATAPOOLLOCAL_ACCESSLOCALPOOLF_H_ */

View File

@ -6,3 +6,5 @@ target_sources(${LIB_FSFW_NAME}
LocalPoolObjectBase.cpp LocalPoolObjectBase.cpp
SharedLocalDataSet.cpp SharedLocalDataSet.cpp
) )
add_subdirectory(internal)

View File

@ -1,52 +1,40 @@
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ #ifndef FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#define FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ #define FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#include "locPoolDefinitions.h" #include "localPoolDefinitions.h"
#include "LocalDataPoolManager.h"
#include "../datapool/PoolEntryIF.h" #include "../datapool/PoolEntryIF.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
#include "../housekeeping/HousekeepingMessage.h" #include "../housekeeping/HousekeepingMessage.h"
#include <map> #include <map>
class LocalDataPoolManager; class AccessPoolManagerIF;
class ProvidesDataPoolSubscriptionIF;
class LocalPoolDataSetBase; class LocalPoolDataSetBase;
class LocalPoolObjectBase; class LocalPoolObjectBase;
using LocalDataPool = std::map<lp_id_t, PoolEntryIF*>;
using LocalDataPoolMapIter = LocalDataPool::iterator;
/** /**
* @brief This interface is implemented by classes which posses a local * @brief This interface is implemented by classes which posses a local data pool (not the
* data pool (not the managing class). It defines the relationship * managing class). It defines the relationship between the local data pool owner
* between the local data pool owner and the LocalDataPoolManager. * and the LocalDataPoolManager.
* @details * @details
* Any class implementing this interface shall also have a LocalDataPoolManager * Any class implementing this interface shall also have a LocalDataPoolManager member class which
* member class which contains the actual pool data structure * contains the actual pool data structure and exposes the public interface for it.
* and exposes the public interface for it. * The local data pool can be accessed using helper classes by using the
* This is required because the pool entries are templates, which makes * LocalPoolVariable, LocalPoolVector or LocalDataSet classes. Every local pool variable can
* specifying an interface rather difficult. The local data pool can be * be uniquely identified by a global pool ID (gp_id_t) and every dataset tied
* accessed by using the LocalPoolVariable, LocalPoolVector or LocalDataSet * to a pool manager can be uniqely identified by a global structure ID (sid_t).
* 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 { class HasLocalDataPoolIF {
friend class HasLocalDpIFManagerAttorney;
friend class HasLocalDpIFUserAttorney;
public: public:
virtual~ HasLocalDataPoolIF() {}; virtual~ HasLocalDataPoolIF() {};
static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF;
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID; static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
virtual object_id_t getObjectId() const = 0; virtual object_id_t getObjectId() const = 0;
@ -59,13 +47,9 @@ public:
* The manager instance shall also be passed to this function. * The manager instance shall also be passed to this function.
* It can be used to subscribe for periodic packets for for updates. * It can be used to subscribe for periodic packets for for updates.
*/ */
virtual ReturnValue_t initializeLocalDataPool( virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) = 0; 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 in milliseconds, which will * Returns the minimum sampling frequency in milliseconds, which will
* usually be the period the pool owner performs its periodic operation. * usually be the period the pool owner performs its periodic operation.
@ -73,33 +57,10 @@ public:
*/ */
virtual uint32_t getPeriodicOperationFrequency() const = 0; virtual uint32_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 LocalPoolDataSetBase* getDataSetHandle(sid_t sid) = 0;
/**
* Similar to the function above, but used to get a local pool variable
* handle. This is only needed for update notifications, so it is not
* defined as abstract.
* @param localPoolId
* @return
*/
virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "HasLocalDataPoolIF::getPoolObjectHandle: Not overriden"
<< ". Returning nullptr!" << std::endl;
#endif
return nullptr;
}
/** /**
* @brief This function will be called by the manager if an update * @brief This function will be called by the manager if an update
* notification is received. * notification is received.
* @details * @details HasLocalDataPoolIF
* Can be overriden by the child class to handle changed datasets. * Can be overriden by the child class to handle changed datasets.
* @param sid * @param sid
* @param storeId If a snapshot was requested, data will be located inside * @param storeId If a snapshot was requested, data will be located inside
@ -124,18 +85,81 @@ public:
return; return;
} }
/* These function can be implemented by pool owner, as they are required /**
* by the housekeeping message interface */ * These function can be implemented by pool owner, if they are required
* and used by the housekeeping message interface.
* */
virtual ReturnValue_t addDataSet(sid_t sid) { virtual ReturnValue_t addDataSet(sid_t sid) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
}; };
virtual ReturnValue_t removeDataSet(sid_t sid) { virtual ReturnValue_t removeDataSet(sid_t sid) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
}; };
virtual ReturnValue_t changeCollectionInterval(sid_t sid, virtual ReturnValue_t changeCollectionInterval(sid_t sid, float newIntervalSeconds) {
float newIntervalSeconds) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
}; };
/**
* This function can be used by data pool consumers to retrieve a handle
* which allows subscriptions to dataset and variable updates in form of messages.
* The consumers can then read the most recent variable value by calling read with
* an own pool variable or set instance or using the deserialized snapshot data.
* Returns the HK manager casted to the required interface by default.
* @return
*/
virtual ProvidesDataPoolSubscriptionIF* getSubscriptionInterface() {
return getHkManagerHandle();
}
protected:
/**
* Every class implementing this interface should have a local data pool manager. This
* function will return a reference to the manager.
* @return
*/
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
/**
* Accessor handle required for internal handling. Not intended for users and therefore
* declared protected. Users should instead use pool variables, sets or the subscription
* interface to access pool entries. Returns the HK manager casted to a different interface
* by default.
* @return
*/
virtual AccessPoolManagerIF* getAccessorHandle() {
return getHkManagerHandle();
}
/**
* This function is used by the pool manager to get a valid dataset
* from a SID. This function is protected to prevent users from
* using raw data set pointers which could not be thread-safe. Users
* should use the #ProvidesDataPoolSubscriptionIF.
* @param sid Corresponding structure ID
* @return
*/
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) = 0;
/**
* Similar to the function above, but used to get a local pool variable
* handle. This is only needed for update notifications, so it is not
* defined as abstract. This function is protected to prevent users from
* using raw pool variable pointers which could not be thread-safe.
* Users should use the #ProvidesDataPoolSubscriptionIF.
* @param localPoolId
* @return
*/
virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "HasLocalDataPoolIF::getPoolObjectHandle: Not overriden"
<< ". Returning nullptr!" << std::endl;
#else
sif::printWarning("HasLocalDataPoolIF::getPoolObjectHandle: "
"Not overriden. Returning nullptr!\n");
#endif
return nullptr;
}
}; };
#endif /* FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ */ #endif /* FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ */

View File

@ -1,11 +1,13 @@
#include "HasLocalDataPoolIF.h"
#include "LocalDataPoolManager.h" #include "LocalDataPoolManager.h"
#include "LocalPoolObjectBase.h" #include "LocalPoolObjectBase.h"
#include "LocalPoolDataSetBase.h" #include "LocalPoolDataSetBase.h"
#include "internal/LocalPoolDataSetAttorney.h"
#include "internal/HasLocalDpIFManagerAttorney.h"
#include "../housekeeping/HousekeepingPacketUpdate.h" #include "../housekeeping/HousekeepingPacketUpdate.h"
#include "../housekeeping/HousekeepingSetPacket.h" #include "../housekeeping/HousekeepingSetPacket.h"
#include "../housekeeping/AcceptsHkPacketsIF.h" #include "../housekeeping/AcceptsHkPacketsIF.h"
#include "../timemanager/CCSDSTime.h" #include "../timemanager/CCSDSTime.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
#include "../ipc/MutexHelper.h" #include "../ipc/MutexHelper.h"
@ -14,26 +16,23 @@
#include <array> #include <array>
#include <cmath> #include <cmath>
object_id_t LocalDataPoolManager::defaultHkDestination = object_id_t LocalDataPoolManager::defaultHkDestination = objects::PUS_SERVICE_3_HOUSEKEEPING;
objects::PUS_SERVICE_3_HOUSEKEEPING;
LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
MessageQueueIF* queueToUse, bool appendValidityBuffer): bool appendValidityBuffer):
appendValidityBuffer(appendValidityBuffer) { appendValidityBuffer(appendValidityBuffer) {
if(owner == nullptr) { if(owner == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::error << "LocalDataPoolManager::LocalDataPoolManager: " "LocalDataPoolManager", HasReturnvaluesIF::RETURN_FAILED,
<< "Invalid supplied owner!" << std::endl; "Invalid supplied owner");
#endif
return; return;
} }
this->owner = owner; this->owner = owner;
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
if(mutex == nullptr) { if(mutex == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR,
sif::error << "LocalDataPoolManager::LocalDataPoolManager: " "LocalDataPoolManager", HasReturnvaluesIF::RETURN_FAILED,
<< "Could not create mutex." << std::endl; "Could not create mutex");
#endif
} }
hkQueue = queueToUse; hkQueue = queueToUse;
@ -43,21 +42,18 @@ LocalDataPoolManager::~LocalDataPoolManager() {}
ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
if(queueToUse == nullptr) { if(queueToUse == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 // error, all destinations invalid
sif::error << "LocalDataPoolManager::initialize: " printWarningOrError(sif::OutputTypes::OUT_ERROR,
<< std::hex << "0x" << owner->getObjectId() << ". Supplied " "initialize", QUEUE_OR_DESTINATION_INVALID);
<< "queue invalid!" << std::dec << std::endl;
#endif
} }
hkQueue = queueToUse; hkQueue = queueToUse;
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE); ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if(ipcStore == nullptr) { if(ipcStore == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 // error, all destinations invalid
sif::error << "LocalDataPoolManager::initialize: " printWarningOrError(sif::OutputTypes::OUT_ERROR,
<< std::hex << "0x" << owner->getObjectId() << ": Could not " "initialize", HasReturnvaluesIF::RETURN_FAILED,
<< "set IPC store." <<std::dec << std::endl; "Could not set IPC store.");
#endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
@ -69,11 +65,9 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
hkDestinationId = hkPacketReceiver->getHkQueue(); hkDestinationId = hkPacketReceiver->getHkQueue();
} }
else { else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR,
sif::error << "LocalDataPoolManager::LocalDataPoolManager: " "initialize", QUEUE_OR_DESTINATION_INVALID);
<< "Default HK destination object is invalid!" << std::endl; return QUEUE_OR_DESTINATION_INVALID;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
@ -95,10 +89,10 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
} }
return result; return result;
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "HousekeepingManager: The map should only be initialized " printWarningOrError(sif::OutputTypes::OUT_WARNING,
<< "once!" << std::endl; "initialize", HasReturnvaluesIF::RETURN_FAILED,
#endif "The map should only be initialized once");
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -141,7 +135,7 @@ ReturnValue_t LocalDataPoolManager::handleHkUpdate(HkReceiver& receiver,
// Update packets shall only be generated from datasets. // Update packets shall only be generated from datasets.
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
receiver.dataId.sid); receiver.dataId.sid);
if(dataSet->hasChanged()) { if(dataSet->hasChanged()) {
// prepare and send update notification // prepare and send update notification
@ -156,20 +150,23 @@ ReturnValue_t LocalDataPoolManager::handleHkUpdate(HkReceiver& receiver,
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::handleNotificationUpdate( ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receiver,
HkReceiver& receiver, ReturnValue_t& status) { ReturnValue_t& status) {
MarkChangedIF* toReset = nullptr; MarkChangedIF* toReset = nullptr;
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
receiver.dataId.localPoolId); receiver.dataId.localPoolId);
//LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle(receiver.dataId.localPoolId);
if(poolObj == nullptr) { if(poolObj == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; printWarningOrError(sif::OutputTypes::OUT_WARNING,
"handleNotificationUpdate", POOLOBJECT_NOT_FOUND);
return POOLOBJECT_NOT_FOUND;
} }
if(poolObj->hasChanged()) { if(poolObj->hasChanged()) {
// prepare and send update notification. // prepare and send update notification.
CommandMessage notification; CommandMessage notification;
HousekeepingMessage::setUpdateNotificationVariableCommand( HousekeepingMessage::setUpdateNotificationVariableCommand(&notification,
&notification, receiver.dataId.localPoolId); receiver.dataId.localPoolId);
ReturnValue_t result = hkQueue->sendMessage( ReturnValue_t result = hkQueue->sendMessage(
receiver.destinationQueue, &notification); receiver.destinationQueue, &notification);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
@ -180,10 +177,12 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(
} }
else { else {
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
receiver.dataId.sid); receiver.dataId.sid);
if(dataSet == nullptr) { if(dataSet == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; printWarningOrError(sif::OutputTypes::OUT_WARNING,
"handleNotificationUpdate", DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
} }
if(dataSet->hasChanged()) { if(dataSet->hasChanged()) {
// prepare and send update notification // prepare and send update notification
@ -210,10 +209,12 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
MarkChangedIF* toReset = nullptr; MarkChangedIF* toReset = nullptr;
// check whether data has changed and send messages in case it has. // check whether data has changed and send messages in case it has.
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
receiver.dataId.localPoolId); receiver.dataId.localPoolId);
if(poolObj == nullptr) { if(poolObj == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; printWarningOrError(sif::OutputTypes::OUT_WARNING,
"handleNotificationSnapshot", POOLOBJECT_NOT_FOUND);
return POOLOBJECT_NOT_FOUND;
} }
if (not poolObj->hasChanged()) { if (not poolObj->hasChanged()) {
@ -226,7 +227,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
CCSDSTime::CDS_short cds; CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now); CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds), HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
sizeof(cds), owner->getPoolObjectHandle( sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
receiver.dataId.localPoolId)); receiver.dataId.localPoolId));
store_address_t storeId; store_address_t storeId;
@ -246,10 +247,12 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
toReset = poolObj; toReset = poolObj;
} }
else { else {
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
receiver.dataId.sid); receiver.dataId.sid);
if(dataSet == nullptr) { if(dataSet == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; printWarningOrError(sif::OutputTypes::OUT_WARNING,
"handleNotificationSnapshot", DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
} }
if(not dataSet->hasChanged()) { if(not dataSet->hasChanged()) {
@ -262,7 +265,8 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
CCSDSTime::CDS_short cds; CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now); CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds), HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
sizeof(cds), owner->getDataSetHandle(receiver.dataId.sid)); sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
receiver.dataId.sid));
store_address_t storeId; store_address_t storeId;
ReturnValue_t result = addUpdateToStore(updatePacket, storeId); ReturnValue_t result = addUpdateToStore(updatePacket, storeId);
@ -308,8 +312,8 @@ void LocalDataPoolManager::handleChangeResetLogic(
// config error! // config error!
return; return;
} }
HkUpdateResetList& listRef = *hkUpdateResetList;
for(auto& changeInfo: *hkUpdateResetList) { for(auto& changeInfo: listRef) {
if(changeInfo.dataType != type) { if(changeInfo.dataType != type) {
continue; continue;
} }
@ -322,12 +326,16 @@ void LocalDataPoolManager::handleChangeResetLogic(
continue; continue;
} }
// only one update recipient, we can reset changes status immediately.
if(changeInfo.updateCounter <= 1) { if(changeInfo.updateCounter <= 1) {
toReset->setChanged(false); toReset->setChanged(false);
} }
if(changeInfo.currentUpdateCounter == 0) { // All recipients have been notified, reset the changed flag.
if(changeInfo.currentUpdateCounter <= 1) {
toReset->setChanged(false); toReset->setChanged(false);
changeInfo.currentUpdateCounter = 0;
} }
// Not all recipiens have been notified yet, decrement.
else { else {
changeInfo.currentUpdateCounter--; changeInfo.currentUpdateCounter--;
} }
@ -351,11 +359,9 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
AcceptsHkPacketsIF* hkReceiverObject = AcceptsHkPacketsIF* hkReceiverObject =
objectManager->get<AcceptsHkPacketsIF>(packetDestination); objectManager->get<AcceptsHkPacketsIF>(packetDestination);
if(hkReceiverObject == nullptr) { if(hkReceiverObject == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:" "subscribeForPeriodicPacket", QUEUE_OR_DESTINATION_INVALID);
<< " Invalid receiver!"<< std::endl; return QUEUE_OR_DESTINATION_INVALID;
#endif
return HasReturnvaluesIF::RETURN_OK;
} }
struct HkReceiver hkReceiver; struct HkReceiver hkReceiver;
@ -364,11 +370,12 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
hkReceiver.dataType = DataType::DATA_SET; hkReceiver.dataType = DataType::DATA_SET;
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if(dataSet != nullptr) { if(dataSet != nullptr) {
dataSet->setReportingEnabled(enableReporting); LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting);
dataSet->setDiagnostic(isDiagnostics); LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
dataSet->initializePeriodicHelper(collectionInterval, LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, collectionInterval,
owner->getPeriodicOperationFrequency(), isDiagnostics); owner->getPeriodicOperationFrequency(), isDiagnostics);
} }
@ -383,11 +390,9 @@ ReturnValue_t LocalDataPoolManager::subscribeForUpdatePackets(sid_t sid,
AcceptsHkPacketsIF* hkReceiverObject = AcceptsHkPacketsIF* hkReceiverObject =
objectManager->get<AcceptsHkPacketsIF>(packetDestination); objectManager->get<AcceptsHkPacketsIF>(packetDestination);
if(hkReceiverObject == nullptr) { if(hkReceiverObject == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:" "subscribeForPeriodicPacket", QUEUE_OR_DESTINATION_INVALID);
<< " Invalid receiver!"<< std::endl; return QUEUE_OR_DESTINATION_INVALID;
#endif
return HasReturnvaluesIF::RETURN_OK;
} }
struct HkReceiver hkReceiver; struct HkReceiver hkReceiver;
@ -396,10 +401,11 @@ ReturnValue_t LocalDataPoolManager::subscribeForUpdatePackets(sid_t sid,
hkReceiver.dataType = DataType::DATA_SET; hkReceiver.dataType = DataType::DATA_SET;
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if(dataSet != nullptr) { if(dataSet != nullptr) {
dataSet->setReportingEnabled(true); LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true);
dataSet->setDiagnostic(isDiagnostics); LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
} }
hkReceiversMap.push_back(hkReceiver); hkReceiversMap.push_back(hkReceiver);
@ -413,7 +419,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForSetUpdateMessages(
MessageQueueId_t targetQueueId, bool generateSnapshot) { MessageQueueId_t targetQueueId, bool generateSnapshot) {
struct HkReceiver hkReceiver; struct HkReceiver hkReceiver;
hkReceiver.dataType = DataType::DATA_SET; hkReceiver.dataType = DataType::DATA_SET;
hkReceiver.dataId.sid = sid_t(this->getOwner()->getObjectId(), setId); hkReceiver.dataId.sid = sid_t(owner->getObjectId(), setId);
hkReceiver.destinationQueue = targetQueueId; hkReceiver.destinationQueue = targetQueueId;
hkReceiver.objectId = destinationObject; hkReceiver.objectId = destinationObject;
if(generateSnapshot) { if(generateSnapshot) {
@ -513,10 +519,13 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
break; break;
} }
case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): {
return generateSetStructurePacket(sid, true); return generateSetStructurePacket(sid, true);
case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): }
case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): {
return generateSetStructurePacket(sid, false); return generateSetStructurePacket(sid, false);
}
case(HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL): case(HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL):
case(HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): { case(HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
float newCollIntvl = 0; float newCollIntvl = 0;
@ -534,13 +543,14 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT):
case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): { case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): {
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); LocalPoolDataSetBase* dataSet =HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if(command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT if(command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT
and dataSet->isDiagnostics()) { and LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
else if(command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT else if(command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT
and not dataSet->isDiagnostics()) { and not LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
return generateHousekeepingPacket(HousekeepingMessage::getSid(message), return generateHousekeepingPacket(HousekeepingMessage::getSid(message),
@ -591,11 +601,9 @@ ReturnValue_t LocalDataPoolManager::printPoolEntry(
lp_id_t localPoolId) { lp_id_t localPoolId) {
auto poolIter = localPoolMap.find(localPoolId); auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) { if (poolIter == localPoolMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING, "printPoolEntry",
sif::debug << "HousekeepingManager::fechPoolEntry:" localpool::POOL_ENTRY_NOT_FOUND);
<< " Pool entry not found." << std::endl; return localpool::POOL_ENTRY_NOT_FOUND;
#endif
return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND;
} }
poolIter->second->print(); poolIter->second->print();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -614,11 +622,10 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
MessageQueueId_t destination) { MessageQueueId_t destination) {
if(dataSet == nullptr) { if(dataSet == nullptr) {
// Configuration error. // Configuration error.
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::warning << "HousekeepingManager::generateHousekeepingPacket:" "generateHousekeepingPacket",
<< " Set ID not found or dataset not assigned!" << std::endl; DATASET_NOT_FOUND);
#endif return DATASET_NOT_FOUND;
return HasReturnvaluesIF::RETURN_FAILED;
} }
store_address_t storeId; store_address_t storeId;
@ -632,7 +639,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
// and now we set a HK message and send it the HK packet destination. // and now we set a HK message and send it the HK packet destination.
CommandMessage hkMessage; CommandMessage hkMessage;
if(dataSet->isDiagnostics()) { if(LocalPoolDataSetAttorney::isDiagnostics(*dataSet)) {
HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId); HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId);
} }
else { else {
@ -640,12 +647,18 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
} }
if(hkQueue == nullptr) { if(hkQueue == nullptr) {
return QUEUE_OR_DESTINATION_NOT_SET; // error, no queue available to send packet with.
printWarningOrError(sif::OutputTypes::OUT_WARNING,
"generateHousekeepingPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
} }
if(destination == MessageQueueIF::NO_QUEUE) { if(destination == MessageQueueIF::NO_QUEUE) {
if(hkDestinationId == MessageQueueIF::NO_QUEUE) { if(hkDestinationId == MessageQueueIF::NO_QUEUE) {
// error, all destinations invalid // error, all destinations invalid
return HasReturnvaluesIF::RETURN_FAILED; printWarningOrError(sif::OutputTypes::OUT_WARNING,
"generateHousekeepingPacket",
QUEUE_OR_DESTINATION_INVALID);
} }
destination = hkDestinationId; destination = hkDestinationId;
} }
@ -680,17 +693,28 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid; sid_t sid = receiver.dataId.sid;
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); //LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if(not dataSet->getReportingEnabled()) { LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if(dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING,
"performPeriodicHkGeneration",
DATASET_NOT_FOUND);
return; return;
} }
if(dataSet->periodicHelper == nullptr) { if(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet)) {
return;
}
PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
if(periodicHelper == nullptr) {
// Configuration error. // Configuration error.
return; return;
} }
if(not dataSet->periodicHelper->checkOpNecessary()) { if(periodicHelper->checkOpNecessary()) {
return; return;
} }
@ -699,10 +723,11 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
// configuration error // configuration error
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "LocalDataPoolManager::performHkOperation:" sif::warning << "LocalDataPoolManager::performHkOperation: "
<< "0x" << std::hex << std::setfill('0') << std::setw(8) << "HK generation failed." << std::endl;
<< owner->getObjectId() << " Error generating " #else
<< "HK packet" << std::setfill(' ') << std::dec << std::endl; sif::printWarning("LocalDataPoolManager::performHkOperation: "
"HK generation failed.\n");
#endif #endif
} }
} }
@ -710,62 +735,67 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
bool enable, bool isDiagnostics) { bool enable, bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); //LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if((dataSet->isDiagnostics() and not isDiagnostics) or LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
(not dataSet->isDiagnostics() and isDiagnostics)) { if((LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and not isDiagnostics) or
(not LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
if((dataSet->getReportingEnabled() and enable) or if((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
(not dataSet->getReportingEnabled() and not enable)) { (not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
return REPORTING_STATUS_UNCHANGED; return REPORTING_STATUS_UNCHANGED;
} }
dataSet->setReportingEnabled(enable); LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval, bool isDiagnostics) { float newCollectionInterval, bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); //LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
bool targetIsDiagnostics = dataSet->isDiagnostics(); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if((targetIsDiagnostics and not isDiagnostics) or if((targetIsDiagnostics and not isDiagnostics) or
(not targetIsDiagnostics and isDiagnostics)) { (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
if(dataSet->periodicHelper == nullptr) { PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
if(periodicHelper == nullptr) {
// config error // config error
return PERIODIC_HELPER_INVALID; return PERIODIC_HELPER_INVALID;
} }
dataSet->periodicHelper->changeCollectionInterval(newCollectionInterval); periodicHelper->changeCollectionInterval(newCollectionInterval);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
bool isDiagnostics) { bool isDiagnostics) {
// Get and check dataset first. // Get and check dataset first.
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); //LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if(dataSet == nullptr) { if(dataSet == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::warning << "HousekeepingManager::generateHousekeepingPacket:" "performPeriodicHkGeneration",
<< " Set ID not found" << std::endl; DATASET_NOT_FOUND);
#endif return DATASET_NOT_FOUND;
return HasReturnvaluesIF::RETURN_FAILED;
} }
bool targetIsDiagnostics = dataSet->isDiagnostics(); bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if((targetIsDiagnostics and not isDiagnostics) or if((targetIsDiagnostics and not isDiagnostics) or
(not targetIsDiagnostics and isDiagnostics)) { (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
bool valid = dataSet->isValid(); bool valid = dataSet->isValid();
bool reportingEnabled = dataSet->getReportingEnabled(); bool reportingEnabled = LocalPoolDataSetAttorney::getReportingEnabled(*dataSet);
float collectionInterval = float collectionInterval = LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet)->
dataSet->periodicHelper->getCollectionIntervalInSeconds(); getCollectionIntervalInSeconds();
// Generate set packet which can be serialized. // Generate set packet which can be serialized.
HousekeepingSetPacket setPacket(sid, HousekeepingSetPacket setPacket(sid,
@ -776,10 +806,9 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
ReturnValue_t result = ipcStore->getFreeElement(&storeId, ReturnValue_t result = ipcStore->getFreeElement(&storeId,
expectedSize,&storePtr); expectedSize,&storePtr);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR,
sif::error << "HousekeepingManager::generateHousekeepingPacket: " "generateSetStructurePacket", HasReturnvaluesIF::RETURN_FAILED,
<< "Could not get free element from IPC store." << std::endl; "Could not get free element from IPC store.");
#endif
return result; return result;
} }
@ -788,10 +817,9 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
result = setPacket.serialize(&storePtr, &size, expectedSize, result = setPacket.serialize(&storePtr, &size, expectedSize,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
if(expectedSize != size) { if(expectedSize != size) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::error << "HousekeepingManager::generateSetStructurePacket: " "generateSetStructurePacket", HasReturnvaluesIF::RETURN_FAILED,
<< "Expected size is not equal to serialized size" << std::endl; "Expected size is not equal to serialized size");
#endif
} }
// Send structure reporting reply. // Send structure reporting reply.
@ -808,3 +836,76 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
hkQueue->reply(&reply); hkQueue->reply(&reply);
return result; return result;
} }
void LocalDataPoolManager::clearReceiversList() {
// clear the vector completely and releases allocated memory.
HkReceivers().swap(hkReceiversMap);
}
MutexIF* LocalDataPoolManager::getLocalPoolMutex() {
return this->mutex;
}
object_id_t LocalDataPoolManager::getCreatorObjectId() const {
return owner->getObjectId();
//return owner->getObjectId();
}
void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
const char* functionName, ReturnValue_t error, const char* errorPrint) {
if(errorPrint == nullptr) {
if(error == DATASET_NOT_FOUND) {
errorPrint = "Dataset not found";
}
else if(error == POOLOBJECT_NOT_FOUND) {
errorPrint = "Pool Object not found";
}
else if(error == HasReturnvaluesIF::RETURN_FAILED) {
if(outputType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";
}
else {
errorPrint = "Generic error";
}
}
else if(error == QUEUE_OR_DESTINATION_INVALID) {
errorPrint = "Queue or destination not set";
}
else if(error == localpool::POOL_ENTRY_TYPE_CONFLICT) {
errorPrint = "Pool entry type conflict";
}
else if(error == localpool::POOL_ENTRY_NOT_FOUND) {
errorPrint = "Pool entry not found";
}
else {
errorPrint = "Unknown error";
}
}
if(outputType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::" << functionName
<< ": Object ID " << std::setw(8) << std::setfill('0')
<< std::hex << owner->getObjectId() << " | " << errorPrint
<< std::dec << std::setfill(' ') << std::endl;
#else
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
owner->getObjectId(), errorPrint);
#endif
}
else if(outputType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalDataPoolManager::" << functionName
<< ": Object ID " << std::setw(8) << std::setfill('0')
<< std::hex << owner->getObjectId() << " | " << errorPrint
<< std::dec << std::setfill(' ') << std::endl;
#else
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
owner->getObjectId(), errorPrint);
#endif
}
}
LocalDataPoolManager* LocalDataPoolManager::getHkManagerHandle() {
return this;
}

View File

@ -1,8 +1,10 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#define FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ #define FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#include "HasLocalDataPoolIF.h" #include "ProvidesDataPoolSubscriptionIF.h"
#include "AccessLocalPoolF.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../housekeeping/HousekeepingPacketDownlink.h" #include "../housekeeping/HousekeepingPacketDownlink.h"
#include "../housekeeping/HousekeepingMessage.h" #include "../housekeeping/HousekeepingMessage.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h" #include "../housekeeping/PeriodicHousekeepingHelper.h"
@ -15,6 +17,7 @@
#include "../ipc/MutexHelper.h" #include "../ipc/MutexHelper.h"
#include <map> #include <map>
#include <vector>
namespace Factory { namespace Factory {
void setStaticFrameworkObjectIds(); void setStaticFrameworkObjectIds();
@ -22,6 +25,8 @@ void setStaticFrameworkObjectIds();
class LocalPoolDataSetBase; class LocalPoolDataSetBase;
class HousekeepingPacketUpdate; class HousekeepingPacketUpdate;
class HasLocalDataPoolIF;
class LocalDataPool;
/** /**
* @brief This class is the managing instance for the local data pool. * @brief This class is the managing instance for the local data pool.
@ -47,19 +52,23 @@ class HousekeepingPacketUpdate;
* Each pool entry has a valid state too. * Each pool entry has a valid state too.
* @author R. Mueller * @author R. Mueller
*/ */
class LocalDataPoolManager { class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF,
template<typename T> friend class LocalPoolVariable; public AccessPoolManagerIF {
template<typename T, uint16_t vecSize> friend class LocalPoolVector;
friend class LocalPoolDataSetBase;
friend void (Factory::setStaticFrameworkObjectIds)(); friend void (Factory::setStaticFrameworkObjectIds)();
//! Some classes using the pool manager directly need to access class internals of the
//! manager. The attorney provides granular control of access to these internals.
friend class LocalDpManagerAttorney;
public: public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x0); static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
static constexpr ReturnValue_t POOLOBJECT_NOT_FOUND = MAKE_RETURN_CODE(4);
static constexpr ReturnValue_t DATASET_NOT_FOUND = MAKE_RETURN_CODE(5);
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(0x01);
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(0x02);
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(0x03);
/** /**
* This constructor is used by a class which wants to implement * This constructor is used by a class which wants to implement
@ -116,7 +125,7 @@ public:
*/ */
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting, ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
float collectionInterval, bool isDiagnostics, float collectionInterval, bool isDiagnostics,
object_id_t packetDestination = defaultHkDestination); object_id_t packetDestination = defaultHkDestination) override;
/** /**
* @brief Subscribe for the generation of packets if the dataset * @brief Subscribe for the generation of packets if the dataset
@ -130,7 +139,7 @@ public:
*/ */
ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled, ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled,
bool isDiagnostics, bool isDiagnostics,
object_id_t packetDestination = defaultHkDestination); object_id_t packetDestination = defaultHkDestination) override;
/** /**
* @brief Subscribe for a notification message which will be sent * @brief Subscribe for a notification message which will be sent
@ -149,7 +158,7 @@ public:
ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId, ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
object_id_t destinationObject, object_id_t destinationObject,
MessageQueueId_t targetQueueId, MessageQueueId_t targetQueueId,
bool generateSnapshot); bool generateSnapshot) override;
/** /**
* @brief Subscribe for an notification message which will be sent if a * @brief Subscribe for an notification message which will be sent if a
@ -168,7 +177,9 @@ public:
ReturnValue_t subscribeForVariableUpdateMessages(const lp_id_t localPoolId, ReturnValue_t subscribeForVariableUpdateMessages(const lp_id_t localPoolId,
object_id_t destinationObject, object_id_t destinationObject,
MessageQueueId_t targetQueueId, MessageQueueId_t targetQueueId,
bool generateSnapshot); bool generateSnapshot) override;
MutexIF* getLocalPoolMutex() override;
/** /**
* Non-Diagnostics packets usually have a lower minimum sampling frequency * Non-Diagnostics packets usually have a lower minimum sampling frequency
@ -247,8 +258,18 @@ public:
LocalDataPoolManager(const LocalDataPoolManager &) = delete; LocalDataPoolManager(const LocalDataPoolManager &) = delete;
LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete; LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete;
/**
* This function can be used to clear the receivers list. This is
* intended for test functions and not for regular operations, because
* the insertion operations allocate dynamically.
*/
void clearReceiversList();
object_id_t getCreatorObjectId() const;
virtual LocalDataPoolManager* getHkManagerHandle() override;
private: private:
LocalDataPool localPoolMap; localpool::DataPool localPoolMap;
//! Every housekeeping data manager has a mutex to protect access //! Every housekeeping data manager has a mutex to protect access
//! to it's data pool. //! to it's data pool.
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
@ -367,6 +388,11 @@ private:
ReturnValue_t& status); ReturnValue_t& status);
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket, ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket,
store_address_t& storeId); store_address_t& storeId);
void printWarningOrError(sif::OutputTypes outputType,
const char* functionName,
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
const char* errorPrint = nullptr);
}; };
@ -375,20 +401,16 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
PoolEntry<T> **poolEntry) { PoolEntry<T> **poolEntry) {
auto poolIter = localPoolMap.find(localPoolId); auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) { if (poolIter == localPoolMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
sif::warning << "HousekeepingManager::fechPoolEntry: Pool entry " localpool::POOL_ENTRY_NOT_FOUND);
"not found." << std::endl; return localpool::POOL_ENTRY_NOT_FOUND;
#endif
return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND;
} }
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second); *poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
if(*poolEntry == nullptr) { if(*poolEntry == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
sif::debug << "HousekeepingManager::fetchPoolEntry:" localpool::POOL_ENTRY_TYPE_CONFLICT);
" Pool entry not found." << std::endl; return localpool::POOL_ENTRY_TYPE_CONFLICT;
#endif
return HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,4 +1,8 @@
#include "LocalPoolDataSetBase.h" #include "LocalPoolDataSetBase.h"
#include "HasLocalDataPoolIF.h"
#include "internal/HasLocalDpIFUserAttorney.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../datapoollocal/LocalDataPoolManager.h" #include "../datapoollocal/LocalDataPoolManager.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h" #include "../housekeeping/PeriodicHousekeepingHelper.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
@ -15,15 +19,22 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner " sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
<< "invalid!" << std::endl; << "invalid!" << std::endl;
#endif #else
sif::printError("LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
"invalid!\n\r");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if(accessor != nullptr) {
poolManager = accessor->getHkManagerHandle();
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
}
this->sid.objectId = hkOwner->getObjectId(); this->sid.objectId = hkOwner->getObjectId();
this->sid.ownerSetId = setId; this->sid.ownerSetId = setId;
mutex = MutexFactory::instance()->createMutex();
// Data creators get a periodic helper for periodic HK data generation. // Data creators get a periodic helper for periodic HK data generation.
if(periodicHandling) { if(periodicHandling) {
periodicHelper = new PeriodicHousekeepingHelper(this); periodicHelper = new PeriodicHousekeepingHelper(this);
@ -37,20 +48,34 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>( HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
sid.objectId); sid.objectId);
if(hkOwner != nullptr) { if(hkOwner != nullptr) {
hkManager = hkOwner->getHkManagerHandle(); AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if(accessor != nullptr) {
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
}
} }
this->sid = sid;
mutex = MutexFactory::instance()->createMutex(); this->sid = sid;
} }
LocalPoolDataSetBase::LocalPoolDataSetBase(
PoolVariableIF **registeredVariablesArray,
const size_t maxNumberOfVariables, bool protectEveryReadCommitCall):
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
this->setReadCommitProtectionBehaviour(protectEveryReadCommitCall);
}
LocalPoolDataSetBase::~LocalPoolDataSetBase() { LocalPoolDataSetBase::~LocalPoolDataSetBase() {
if(periodicHelper != nullptr) {
delete periodicHelper;
}
} }
ReturnValue_t LocalPoolDataSetBase::lockDataPool(uint32_t timeoutMs) { ReturnValue_t LocalPoolDataSetBase::lockDataPool(
if(hkManager != nullptr) { MutexIF::TimeoutType timeoutType,
MutexIF* mutex = hkManager->getMutexHandle(); uint32_t timeoutMs) {
return mutex->lockMutex(MutexIF::TimeoutType::WAITING, timeoutMs); if(mutexIfSingleDataCreator != nullptr) {
return mutexIfSingleDataCreator->lockMutex(timeoutType, timeoutMs);
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -128,9 +153,8 @@ ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer(
} }
ReturnValue_t LocalPoolDataSetBase::unlockDataPool() { ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
if(hkManager != nullptr) { if(mutexIfSingleDataCreator != nullptr) {
MutexIF* mutex = hkManager->getMutexHandle(); return mutexIfSingleDataCreator->unlockMutex();
return mutex->unlockMutex();
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -150,9 +174,12 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
size, maxSize, streamEndianness); size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataSet::serializeLocalPoolIds: Serialization" sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: "
" error!" << std::endl; << "Serialization error!" << std::endl;
#endif #else
sif::printWarning("LocalPoolDataSetBase::serializeLocalPoolIds: "
"Serialization error!\n\r");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return result; return result;
} }
} }
@ -211,8 +238,11 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size,
void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const { void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const {
if(position > 7) { if(position > 7) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Pool Raw Access: Bit setting invalid position" sif::warning << "LocalPoolDataSetBase::bitSetter: Invalid position!"
<< std::endl; << std::endl;
#else
sif::printWarning("LocalPoolDataSetBase::bitSetter: "
"Invalid position!\n\r");
#endif #endif
return; return;
} }
@ -244,14 +274,10 @@ void LocalPoolDataSetBase::initializePeriodicHelper(
} }
void LocalPoolDataSetBase::setChanged(bool changed) { void LocalPoolDataSetBase::setChanged(bool changed) {
// TODO: Make this configurable?
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
this->changed = changed; this->changed = changed;
} }
bool LocalPoolDataSetBase::hasChanged() const { bool LocalPoolDataSetBase::hasChanged() const {
// TODO: Make this configurable?
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
return changed; return changed;
} }
@ -273,12 +299,10 @@ bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte,
} }
bool LocalPoolDataSetBase::isValid() const { bool LocalPoolDataSetBase::isValid() const {
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5);
return this->valid; return this->valid;
} }
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) { void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5);
if(setEntriesRecursively) { if(setEntriesRecursively) {
for(size_t idx = 0; idx < this->getFillCount(); idx++) { for(size_t idx = 0; idx < this->getFillCount(); idx++) {
registeredVariables[idx] -> setValid(valid); registeredVariables[idx] -> setValid(valid);
@ -287,8 +311,9 @@ void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
this->valid = valid; this->valid = valid;
} }
void LocalPoolDataSetBase::setReadCommitProtectionBehaviour( object_id_t LocalPoolDataSetBase::getCreatorObjectId() {
bool protectEveryReadCommit, uint32_t mutexTimeout) { if(poolManager != nullptr) {
PoolDataSetBase::setReadCommitProtectionBehaviour(protectEveryReadCommit, return poolManager->getCreatorObjectId();
mutexTimeout); }
return objects::NO_OBJECT;
} }

View File

@ -1,16 +1,16 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#include "HasLocalDataPoolIF.h"
#include "MarkChangedIF.h" #include "MarkChangedIF.h"
#include "localPoolDefinitions.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapool/PoolDataSetBase.h" #include "../datapool/PoolDataSetBase.h"
#include "../serialize/SerializeIF.h"
#include <vector> #include <vector>
class LocalDataPoolManager; class LocalDataPoolManager;
class HasLocalDataPoolIF;
class PeriodicHousekeepingHelper; class PeriodicHousekeepingHelper;
/** /**
@ -41,9 +41,10 @@ class PeriodicHousekeepingHelper;
* *
* @ingroup data_pool * @ingroup data_pool
*/ */
class LocalPoolDataSetBase: public PoolDataSetBase, class LocalPoolDataSetBase:
public PoolDataSetBase,
public MarkChangedIF { public MarkChangedIF {
friend class LocalDataPoolManager; friend class LocalPoolDataSetAttorney;
friend class PeriodicHousekeepingHelper; friend class PeriodicHousekeepingHelper;
public: public:
/** /**
@ -57,8 +58,11 @@ public:
const size_t maxNumberOfVariables, bool periodicHandling = true); const size_t maxNumberOfVariables, bool periodicHandling = true);
/** /**
* @brief Constructor for users of local pool data. * @brief Constructor for users of the local pool data, which need
* to access data created by one (!) HK manager.
* @details * @details
* Unlike the first constructor, no component for periodic handling
* will be initiated.
* @param sid Unique identifier of dataset consisting of object ID and * @param sid Unique identifier of dataset consisting of object ID and
* set ID. * set ID.
* @param registeredVariablesArray * @param registeredVariablesArray
@ -67,6 +71,28 @@ public:
LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray, LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables); const size_t maxNumberOfVariables);
/**
* @brief Simple constructor, if the dataset is not the owner by
* a class with a HK manager.
* @details
* This constructor won't create components required for periodic handling
* and it also won't try to deduce the HK manager because no SID is
* supplied. This function should therefore be called by classes which need
* to access pool variables from different creators.
*
* If the class is intended to access pool variables from different
* creators, the third argument should be set to true. The mutex
* properties can be set with #setReadCommitProtectionBehaviour .
* @param registeredVariablesArray
* @param maxNumberOfVariables
* @param protectEveryReadCommitCall If the pool variables are created by
* multiple creators, this flag can be set to protect all read and
* commit calls separately.
*/
LocalPoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables,
bool protectEveryReadCommitCall = true);
/** /**
* @brief The destructor automatically manages writing the valid * @brief The destructor automatically manages writing the valid
* information of variables. * information of variables.
@ -77,16 +103,6 @@ public:
*/ */
~LocalPoolDataSetBase(); ~LocalPoolDataSetBase();
/**
* If the data is pulled from different local data pools, every read and
* commit call should be mutex protected for thread safety.
* This can be specified with the second parameter.
* @param dataCreator
* @param protectEveryReadCommit
*/
void setReadCommitProtectionBehaviour(bool protectEveryReadCommit,
uint32_t mutexTimeout = 20);
void setValidityBufferGeneration(bool withValidityBuffer); void setValidityBufferGeneration(bool withValidityBuffer);
sid_t getSid() const; sid_t getSid() const;
@ -136,10 +152,11 @@ public:
void setChanged(bool changed) override; void setChanged(bool changed) override;
bool hasChanged() const override; bool hasChanged() const override;
object_id_t getCreatorObjectId();
protected: protected:
sid_t sid; sid_t sid;
uint32_t mutexTimeout = 20; //! This mutex is used if the data is created by one object only.
MutexIF* mutex = nullptr; MutexIF* mutexIfSingleDataCreator = nullptr;
bool diagnostic = false; bool diagnostic = false;
void setDiagnostic(bool diagnostics); void setDiagnostic(bool diagnostics);
@ -183,7 +200,9 @@ protected:
* @details * @details
* It makes use of the lockDataPool method offered by the DataPool class. * It makes use of the lockDataPool method offered by the DataPool class.
*/ */
ReturnValue_t lockDataPool(uint32_t timeoutMs) override; ReturnValue_t lockDataPool(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) override;
/** /**
* @brief This is a small helper function to facilitate * @brief This is a small helper function to facilitate
* unlocking the global data pool * unlocking the global data pool
@ -192,8 +211,6 @@ protected:
*/ */
ReturnValue_t unlockDataPool() override; ReturnValue_t unlockDataPool() override;
LocalDataPoolManager* hkManager = nullptr;
/** /**
* Set n-th bit of a byte, with n being the position from 0 * Set n-th bit of a byte, with n being the position from 0
* (most significant bit) to 7 (least significant bit) * (most significant bit) to 7 (least significant bit)
@ -202,6 +219,7 @@ protected:
bool bitGetter(const uint8_t* byte, uint8_t position) const; bool bitGetter(const uint8_t* byte, uint8_t position) const;
PeriodicHousekeepingHelper* periodicHelper = nullptr; PeriodicHousekeepingHelper* periodicHelper = nullptr;
LocalDataPoolManager* poolManager = nullptr;
}; };

View File

@ -1,9 +1,13 @@
#include "LocalPoolObjectBase.h" #include "LocalPoolObjectBase.h"
#include "LocalDataPoolManager.h"
#include "internal/HasLocalDpIFUserAttorney.h"
#include "HasLocalDataPoolIF.h"
LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, #include "../objectmanager/ObjectManagerIF.h"
HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode): localPoolId(poolId), LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
readWriteMode(setReadWriteMode) { DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
localPoolId(poolId), readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) { if(poolId == PoolVariableIF::NO_PARAMETER) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, " sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
@ -17,23 +21,24 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId,
#endif #endif
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
hkManager = poolManAccessor->getHkManagerHandle();
if (dataSet != nullptr) { if (dataSet != nullptr) {
dataSet->registerVariable(this); dataSet->registerVariable(this);
} }
} }
LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF *dataSet,
DataSetIF *dataSet, pool_rwm_t setReadWriteMode): localPoolId(poolId), pool_rwm_t setReadWriteMode):
readWriteMode(setReadWriteMode) { localPoolId(poolId), readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) { if(poolId == PoolVariableIF::NO_PARAMETER) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, " sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
<< "which is the NO_PARAMETER value!" << std::endl; << "which is the NO_PARAMETER value!" << std::endl;
#endif #endif
} }
HasLocalDataPoolIF* hkOwner = HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(poolOwner);
objectManager->get<HasLocalDataPoolIF>(poolOwner);
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolVariable: The supplied pool owner did not " sif::error << "LocalPoolVariable: The supplied pool owner did not "
@ -42,7 +47,12 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
#endif #endif
return; return;
} }
hkManager = hkOwner->getHkManagerHandle();
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if(accessor != nullptr) {
hkManager = accessor->getHkManagerHandle();
}
if(dataSet != nullptr) { if(dataSet != nullptr) {
dataSet->registerVariable(this); dataSet->registerVariable(this);
} }
@ -79,3 +89,42 @@ bool LocalPoolObjectBase::hasChanged() const {
void LocalPoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) { void LocalPoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) {
this->readWriteMode = newReadWriteMode; this->readWriteMode = newReadWriteMode;
} }
void LocalPoolObjectBase::reportReadCommitError(const char* variableType,
ReturnValue_t error, bool read, object_id_t objectId, lp_id_t lpId) {
#if FSFW_DISABLE_PRINTOUT == 0
const char* type = nullptr;
if(read) {
type = "read";
}
else {
type = "commit";
}
const char* errMsg = nullptr;
if(error == localpool::POOL_ENTRY_NOT_FOUND) {
errMsg = "Pool entry not found";
}
else if(error == localpool::POOL_ENTRY_TYPE_CONFLICT) {
errMsg = "Pool entry type conflict";
}
else if(error == PoolVariableIF::INVALID_READ_WRITE_MODE) {
errMsg = "Pool variable wrong read-write mode";
}
else if(error == PoolVariableIF::INVALID_POOL_ENTRY) {
errMsg = "Pool entry invalid";
}
else {
errMsg = "Unknown error code";
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << variableType << ": " << type << " call | " << errMsg << " | Owner: 0x"
<< std::hex << std::setw(8) << std::setfill('0') << objectId << std::dec
<< " LPID: " << lpId << std::endl;
#else
sif::printWarning("%s: %s call | %s | Owner: 0x%08x LPID: %lu\n",
variableType, type, errMsg, objectId, lpId);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
}

View File

@ -2,10 +2,20 @@
#define FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_
#include "MarkChangedIF.h" #include "MarkChangedIF.h"
#include "../datapoollocal/LocalDataPoolManager.h" #include "localPoolDefinitions.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../datapool/PoolVariableIF.h" #include "../datapool/PoolVariableIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
class LocalDataPoolManager;
class DataSetIF;
class HasLocalDataPoolIF;
/**
* @brief This class serves as a non-template base for pool objects like pool variables
* or pool vectors.
*/
class LocalPoolObjectBase: public PoolVariableIF, class LocalPoolObjectBase: public PoolVariableIF,
public HasReturnvaluesIF, public HasReturnvaluesIF,
public MarkChangedIF { public MarkChangedIF {
@ -54,10 +64,10 @@ protected:
ReadWriteMode_t readWriteMode = pool_rwm_t::VAR_READ_WRITE; ReadWriteMode_t readWriteMode = pool_rwm_t::VAR_READ_WRITE;
//! @brief Pointer to the class which manages the HK pool. //! @brief Pointer to the class which manages the HK pool.
LocalDataPoolManager* hkManager; LocalDataPoolManager* hkManager = nullptr;
void reportReadCommitError(const char* variableType,
ReturnValue_t error, bool read, object_id_t objectId, lp_id_t lpId);
}; };
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_ */ #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_ */

View File

@ -4,9 +4,12 @@
#include "LocalPoolObjectBase.h" #include "LocalPoolObjectBase.h"
#include "HasLocalDataPoolIF.h" #include "HasLocalDataPoolIF.h"
#include "LocalDataPoolManager.h" #include "LocalDataPoolManager.h"
#include "AccessLocalPoolF.h"
#include "internal/LocalDpManagerAttorney.h"
#include "../datapool/PoolVariableIF.h" #include "../datapool/PoolVariableIF.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
@ -105,7 +108,9 @@ public:
* at once to avoid the overhead of unnecessary lock und unlock operations. * at once to avoid the overhead of unnecessary lock und unlock operations.
* *
*/ */
ReturnValue_t read(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; ReturnValue_t read(MutexIF::TimeoutType timeoutType =
MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/** /**
* @brief The commit call copies the array values back to the data pool. * @brief The commit call copies the array values back to the data pool.
* @details * @details
@ -115,8 +120,21 @@ public:
* It is recommended to use DataSets to read and commit multiple variables * It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations. * at once to avoid the overhead of unnecessary lock und unlock operations.
*/ */
ReturnValue_t commit(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; ReturnValue_t commit(MutexIF::TimeoutType timeoutType =
MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/**
* @brief This commit function can be used to set the pool variable valid
* as well.
* @param setValid
* @param timeoutType
* @param timeoutMs
* @return
*/
ReturnValue_t commit(bool setValid, MutexIF::TimeoutType timeoutType =
MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20);
LocalPoolVariable<T> &operator=(const T& newValue); LocalPoolVariable<T> &operator=(const T& newValue);
LocalPoolVariable<T> &operator=(const LocalPoolVariable<T>& newPoolVariable); LocalPoolVariable<T> &operator=(const LocalPoolVariable<T>& newPoolVariable);
@ -163,8 +181,6 @@ protected:
friend std::ostream& operator<< (std::ostream &out, friend std::ostream& operator<< (std::ostream &out,
const LocalPoolVariable<U> &var); const LocalPoolVariable<U> &var);
#endif #endif
private:
}; };
#include "LocalPoolVariable.tpp" #include "LocalPoolVariable.tpp"

View File

@ -24,73 +24,91 @@ inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId,
template<typename T> template<typename T>
inline ReturnValue_t LocalPoolVariable<T>::read(dur_millis_t lockTimeout) { inline ReturnValue_t LocalPoolVariable<T>::read(
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
lockTimeout); MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
return readWithoutLock(); return readWithoutLock();
} }
template<typename T> template<typename T>
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() { inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
if(readWriteMode == pool_rwm_t::VAR_WRITE) { if(readWriteMode == pool_rwm_t::VAR_WRITE) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t targetObjectId = hkManager->getCreatorObjectId();
sif::debug << "LocalPoolVar: Invalid read write " reportReadCommitError("LocalPoolVector",
"mode for read() call." << std::endl; PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
#endif localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE; return PoolVariableIF::INVALID_READ_WRITE_MODE;
} }
PoolEntry<T>* poolEntry = nullptr; PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
if(result != RETURN_OK or poolEntry == nullptr) { &poolEntry);
#if FSFW_CPP_OSTREAM_ENABLED == 1 //ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
sif::error << "PoolVector: Read of local pool variable of object " if(result != RETURN_OK) {
<< std::hex << std::setw(8) << std::setfill('0') object_id_t ownerObjectId = hkManager->getCreatorObjectId();
<< hkManager->getOwner() << " and lp ID " << localPoolId reportReadCommitError("LocalPoolVariable", result,
<< std::dec << " failed." << std::setfill(' ') << std::endl; false, ownerObjectId, localPoolId);
#endif
return result; return result;
} }
this->value = *(poolEntry->address);
this->valid = poolEntry->valid; // Actually this should never happen..
// if(poolEntry->address == nullptr) {
// result = PoolVariableIF::INVALID_POOL_ENTRY;
// object_id_t ownerObjectId = hkManager->getOwner()->getObjectId();
// reportReadCommitError("LocalPoolVariable", result,
// false, ownerObjectId, localPoolId);
// return result;
// }
this->value = *(poolEntry->getDataPtr());
this->valid = poolEntry->getValid();
return RETURN_OK; return RETURN_OK;
} }
template<typename T> template<typename T>
inline ReturnValue_t LocalPoolVariable<T>::commit(dur_millis_t lockTimeout) { inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid,
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
lockTimeout); this->setValid(setValid);
return commit(timeoutType, timeoutMs);
}
template<typename T>
inline ReturnValue_t LocalPoolVariable<T>::commit(
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
return commitWithoutLock(); return commitWithoutLock();
} }
template<typename T> template<typename T>
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() { inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
if(readWriteMode == pool_rwm_t::VAR_READ) { if(readWriteMode == pool_rwm_t::VAR_READ) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t targetObjectId = hkManager->getCreatorObjectId();
sif::debug << "LocalPoolVariable: Invalid read write " reportReadCommitError("LocalPoolVector",
"mode for commit() call." << std::endl; PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
#endif localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE; return PoolVariableIF::INVALID_READ_WRITE_MODE;
} }
PoolEntry<T>* poolEntry = nullptr; PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); //ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
&poolEntry);
if(result != RETURN_OK) { if(result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t ownerObjectId = hkManager->getCreatorObjectId();
sif::error << "PoolVector: Read of local pool variable of object " reportReadCommitError("LocalPoolVariable", result,
"0x" << std::hex << std::setw(8) << std::setfill('0') << false, ownerObjectId, localPoolId);
hkManager->getOwner() << " and lp ID 0x" << localPoolId <<
std::dec << " failed.\n" << std::flush;
#endif
return result; return result;
} }
*(poolEntry->address) = this->value;
poolEntry->valid = this->valid; *(poolEntry->getDataPtr()) = this->value;
poolEntry->setValid(this->valid);
return RETURN_OK; return RETURN_OK;
} }
template<typename T> template<typename T>
inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer, size_t* size, inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer,
const size_t max_size, SerializeIF::Endianness streamEndianness) const { size_t* size, const size_t max_size,
SerializeIF::Endianness streamEndianness) const {
return SerializeAdapter::serialize(&value, return SerializeAdapter::serialize(&value,
buffer, size ,max_size, streamEndianness); buffer, size ,max_size, streamEndianness);
} }
@ -121,7 +139,8 @@ inline LocalPoolVariable<T>::operator T() const {
} }
template<typename T> template<typename T>
inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(const T& newValue) { inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(
const T& newValue) {
value = newValue; value = newValue;
return *this; return *this;
} }
@ -134,7 +153,8 @@ inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator =(
} }
template<typename T> template<typename T>
inline bool LocalPoolVariable<T>::operator ==(const LocalPoolVariable<T> &other) const { inline bool LocalPoolVariable<T>::operator ==(
const LocalPoolVariable<T> &other) const {
return this->value == other.value; return this->value == other.value;
} }
@ -145,7 +165,8 @@ inline bool LocalPoolVariable<T>::operator ==(const T &other) const {
template<typename T> template<typename T>
inline bool LocalPoolVariable<T>::operator !=(const LocalPoolVariable<T> &other) const { inline bool LocalPoolVariable<T>::operator !=(
const LocalPoolVariable<T> &other) const {
return not (*this == other); return not (*this == other);
} }
@ -156,7 +177,8 @@ inline bool LocalPoolVariable<T>::operator !=(const T &other) const {
template<typename T> template<typename T>
inline bool LocalPoolVariable<T>::operator <(const LocalPoolVariable<T> &other) const { inline bool LocalPoolVariable<T>::operator <(
const LocalPoolVariable<T> &other) const {
return this->value < other.value; return this->value < other.value;
} }
@ -167,7 +189,8 @@ inline bool LocalPoolVariable<T>::operator <(const T &other) const {
template<typename T> template<typename T>
inline bool LocalPoolVariable<T>::operator >(const LocalPoolVariable<T> &other) const { inline bool LocalPoolVariable<T>::operator >(
const LocalPoolVariable<T> &other) const {
return not (*this < other); return not (*this < other);
} }

View File

@ -2,12 +2,14 @@
#define FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#include "LocalPoolObjectBase.h" #include "LocalPoolObjectBase.h"
#include "internal/LocalDpManagerAttorney.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h" #include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h" #include "../datapool/PoolVariableIF.h"
#include "../datapoollocal/LocalDataPoolManager.h" #include "../datapoollocal/LocalDataPoolManager.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
/** /**
@ -100,8 +102,8 @@ public:
return vectorSize; return vectorSize;
} }
T& operator [](int i); T& operator [](size_t i);
const T &operator [](int i) const; const T &operator [](size_t i) const;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t maxSize, const size_t maxSize,
@ -123,7 +125,10 @@ public:
* It is recommended to use DataSets to read and commit multiple variables * It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations. * at once to avoid the overhead of unnecessary lock und unlock operations.
*/ */
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; ReturnValue_t read(MutexIF::TimeoutType timeoutType =
MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/** /**
* @brief The commit call copies the array values back to the data pool. * @brief The commit call copies the array values back to the data pool.
* @details * @details
@ -133,7 +138,17 @@ public:
* It is recommended to use DataSets to read and commit multiple variables * It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations. * at once to avoid the overhead of unnecessary lock und unlock operations.
*/ */
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; ReturnValue_t commit(MutexIF::TimeoutType timeoutType =
MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/**
* @brief This commit call also sets the validity of the pool entry.
* @details
*/
ReturnValue_t commit(bool valid, MutexIF::TimeoutType timeoutType =
MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20);
protected: protected:
/** /**
@ -157,12 +172,12 @@ protected:
private: private:
#if FSFW_CPP_OSTREAM_ENABLED == 1
// std::ostream is the type for object std::cout // std::ostream is the type for object std::cout
template <typename U, uint16_t otherSize> template <typename U, uint16_t otherSize>
friend std::ostream& operator<< (std::ostream &out, friend std::ostream& operator<< (std::ostream &out,
const LocalPoolVector<U, otherSize> &var); const LocalPoolVector<U, otherSize> &var);
#endif
}; };

View File

@ -24,98 +24,106 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
dataSet, setReadWriteMode) {} dataSet, setReadWriteMode) {}
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(uint32_t lockTimeout) { inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
lockTimeout); MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
return readWithoutLock(); return readWithoutLock();
} }
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() { inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
if(readWriteMode == pool_rwm_t::VAR_WRITE) { if(readWriteMode == pool_rwm_t::VAR_WRITE) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t targetObjectId = hkManager->getCreatorObjectId();
sif::debug << "LocalPoolVar: Invalid read write " reportReadCommitError("LocalPoolVector",
"mode for read() call." << std::endl; PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
#endif localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE; return PoolVariableIF::INVALID_READ_WRITE_MODE;
} }
PoolEntry<T>* poolEntry = nullptr; PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
&poolEntry);
memset(this->value, 0, vectorSize * sizeof(T)); memset(this->value, 0, vectorSize * sizeof(T));
if(result != RETURN_OK) { if(result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t targetObjectId = hkManager->getCreatorObjectId();
sif::error << "PoolVector: Read of local pool variable of object " reportReadCommitError("LocalPoolVector", result, true, targetObjectId,
"0x" << std::hex << std::setw(8) << std::setfill('0') << localPoolId);
hkManager->getOwner() << "and lp ID 0x" << localPoolId <<
std::dec << " failed." << std::endl;
#endif
return result; return result;
} }
std::memcpy(this->value, poolEntry->address, poolEntry->getByteSize()); std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
this->valid = poolEntry->valid; this->valid = poolEntry->getValid();
return RETURN_OK; return RETURN_OK;
} }
template<typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
this->setValid(valid);
return commit(timeoutType, timeoutMs);
}
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit( inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
uint32_t lockTimeout) { MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
lockTimeout);
return commitWithoutLock(); return commitWithoutLock();
} }
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() { inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
if(readWriteMode == pool_rwm_t::VAR_READ) { if(readWriteMode == pool_rwm_t::VAR_READ) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t targetObjectId = hkManager->getCreatorObjectId();
sif::debug << "LocalPoolVar: Invalid read write " reportReadCommitError("LocalPoolVector",
"mode for commit() call." << std::endl; PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
#endif localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE; return PoolVariableIF::INVALID_READ_WRITE_MODE;
} }
PoolEntry<T>* poolEntry = nullptr; PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
&poolEntry);
if(result != RETURN_OK) { if(result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 object_id_t targetObjectId = hkManager->getCreatorObjectId();
sif::error << "PoolVector: Read of local pool variable of object " reportReadCommitError("LocalPoolVector", result, false, targetObjectId,
"0x" << std::hex << std::setw(8) << std::setfill('0') << localPoolId);
hkManager->getOwner() << " and lp ID 0x" << localPoolId <<
std::dec << " failed.\n" << std::flush;
#endif
return result; return result;
} }
std::memcpy(poolEntry->address, this->value, poolEntry->getByteSize()); std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
poolEntry->valid = this->valid; poolEntry->setValid(this->valid);
return RETURN_OK; return RETURN_OK;
} }
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline T& LocalPoolVector<T, vectorSize>::operator [](int i) { inline T& LocalPoolVector<T, vectorSize>::operator [](size_t i) {
if(i <= vectorSize) { if(i < vectorSize) {
return value[i]; return value[i];
} }
// If this happens, I have to set some value. I consider this // If this happens, I have to set some value. I consider this
// a configuration error, but I wont exit here. // a configuration error, but I wont exit here.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolVector: Invalid index. Setting or returning" sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
" last value!" << std::endl; " last value!" << std::endl;
#else
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
" last value!\n");
#endif #endif
return value[i]; return value[vectorSize - 1];
} }
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline const T& LocalPoolVector<T, vectorSize>::operator [](int i) const { inline const T& LocalPoolVector<T, vectorSize>::operator [](size_t i) const {
if(i <= vectorSize) { if(i < vectorSize) {
return value[i]; return value[i];
} }
// If this happens, I have to set some value. I consider this // If this happens, I have to set some value. I consider this
// a configuration error, but I wont exit here. // a configuration error, but I wont exit here.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolVector: Invalid index. Setting or returning" sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
" last value!" << std::endl; " last value!" << std::endl;
#else
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
" last value!\n");
#endif #endif
return value[i]; return value[vectorSize - 1];
} }
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
@ -153,6 +161,7 @@ inline ReturnValue_t LocalPoolVector<T, vectorSize>::deSerialize(
return result; return result;
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline std::ostream& operator<< (std::ostream &out, inline std::ostream& operator<< (std::ostream &out,
const LocalPoolVector<T, vectorSize> &var) { const LocalPoolVector<T, vectorSize> &var) {
@ -166,5 +175,6 @@ inline std::ostream& operator<< (std::ostream &out,
out << "]"; out << "]";
return out; return out;
} }
#endif
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ */ #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ */

View File

@ -1,7 +1,8 @@
#ifndef FSFW_DATAPOOLLOCAL_POOLREADHELPER_H_ #ifndef FSFW_DATAPOOLLOCAL_POOLREADHELPER_H_
#define FSFW_DATAPOOLLOCAL_POOLREADHELPER_H_ #define FSFW_DATAPOOLLOCAL_POOLREADHELPER_H_
#include <fsfw/datapoollocal/LocalPoolDataSetBase.h> #include "LocalPoolDataSetBase.h"
#include "../serviceinterface/ServiceInterface.h"
#include <FSFWConfig.h> #include <FSFWConfig.h>
/** /**
@ -9,17 +10,23 @@
*/ */
class PoolReadHelper { class PoolReadHelper {
public: public:
PoolReadHelper(ReadCommitIF* readObject, uint32_t mutexTimeout = 20): PoolReadHelper(ReadCommitIF* readObject,
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t mutexTimeout = 20):
readObject(readObject), mutexTimeout(mutexTimeout) { readObject(readObject), mutexTimeout(mutexTimeout) {
if(readObject != nullptr) { if(readObject != nullptr) {
readResult = readObject->read(mutexTimeout); readResult = readObject->read(timeoutType, mutexTimeout);
#if FSFW_PRINT_VERBOSITY_LEVEL == 1 if(readResult != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PoolReadHelper: Read failed!" << std::endl; sif::error << "PoolReadHelper: Read failed!" << std::endl;
#else
sif::printError("PoolReadHelper: Read failed!\n");
#endif /* FSFW_PRINT_VERBOSITY_LEVEL == 1 */ #endif /* FSFW_PRINT_VERBOSITY_LEVEL == 1 */
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} }
} }
}
ReturnValue_t getReadResult() const { ReturnValue_t getReadResult() const {
return readResult; return readResult;
@ -27,7 +34,7 @@ public:
~PoolReadHelper() { ~PoolReadHelper() {
if(readObject != nullptr) { if(readObject != nullptr) {
readObject->commit(mutexTimeout); readObject->commit(timeoutType, mutexTimeout);
} }
} }
@ -35,6 +42,7 @@ public:
private: private:
ReadCommitIF* readObject = nullptr; ReadCommitIF* readObject = nullptr;
ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK; ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t mutexTimeout = 20; uint32_t mutexTimeout = 20;
}; };

View File

@ -0,0 +1,83 @@
#ifndef FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#define FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#include "localPoolDefinitions.h"
#include "../ipc/messageQueueDefinitions.h"
#include "../returnvalues/HasReturnvaluesIF.h"
class ProvidesDataPoolSubscriptionIF {
public:
virtual ~ProvidesDataPoolSubscriptionIF(){};
/**
* @brief Subscribe for the generation of periodic packets.
* @details
* This subscription mechanism will generally be used by the data creator
* to generate housekeeping packets which are downlinked directly.
* @return
*/
virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid,
bool enableReporting,
float collectionInterval, bool isDiagnostics,
object_id_t packetDestination) = 0;
/**
* @brief Subscribe for the generation of packets if the dataset
* is marked as changed.
* @details
* This subscription mechanism will generally be used by the data creator.
* @param sid
* @param isDiagnostics
* @param packetDestination
* @return
*/
virtual ReturnValue_t subscribeForUpdatePackets(sid_t sid,
bool reportingEnabled,
bool isDiagnostics,
object_id_t packetDestination) = 0;
/**
* @brief Subscribe for a notification message which will be sent
* if a dataset has changed.
* @details
* This subscription mechanism will generally be used internally by
* other software components.
* @param setId Set ID of the set to receive update messages from.
* @param destinationObject
* @param targetQueueId
* @param generateSnapshot If this is set to true, a copy of the current
* data with a timestamp will be generated and sent via message.
* Otherwise, only an notification message is sent.
* @return
*/
virtual ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) = 0;
/**
* @brief Subscribe for an notification message which will be sent if a
* pool variable has changed.
* @details
* This subscription mechanism will generally be used internally by
* other software components.
* @param localPoolId Pool ID of the pool variable
* @param destinationObject
* @param targetQueueId
* @param generateSnapshot If this is set to true, a copy of the current
* data with a timestamp will be generated and sent via message.
* Otherwise, only an notification message is sent.
* @return
*/
virtual ReturnValue_t subscribeForVariableUpdateMessages(
const lp_id_t localPoolId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) = 0;
};
#endif /* FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ */

View File

@ -6,7 +6,15 @@
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include <vector> #include <vector>
class SharedLocalDataSet: public SystemObject, /**
* This local dataset variation can be used if the dataset is used concurrently across
* multiple threads. It provides a lock in addition to all other functionalities provided
* by the LocalPoolDataSetBase class.
*
* TODO: override and protect read, commit and some other calls used by pool manager.
*/
class SharedLocalDataSet:
public SystemObject,
public LocalPoolDataSetBase, public LocalPoolDataSetBase,
public SharedDataSetIF { public SharedDataSetIF {
public: public:

View File

@ -27,9 +27,8 @@ public:
* @param hkOwner * @param hkOwner
* @param setId * @param setId
*/ */
StaticLocalDataSet(HasLocalDataPoolIF* hkOwner, StaticLocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId):
uint32_t setId): LocalPoolDataSetBase(hkOwner, setId, nullptr, LocalPoolDataSetBase(hkOwner, setId, nullptr, NUM_VARIABLES) {
NUM_VARIABLES) {
this->setContainer(poolVarList.data()); this->setContainer(poolVarList.data());
} }
@ -38,8 +37,7 @@ public:
* @param hkOwner * @param hkOwner
* @param setId * @param setId
*/ */
StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr, StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr, NUM_VARIABLES) {
NUM_VARIABLES) {
this->setContainer(poolVarList.data()); this->setContainer(poolVarList.data());
} }

View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
HasLocalDpIFUserAttorney.cpp
HasLocalDpIFManagerAttorney.cpp
)

View File

@ -0,0 +1,18 @@
#include "HasLocalDpIFManagerAttorney.h"
#include "../LocalPoolObjectBase.h"
#include "../LocalPoolDataSetBase.h"
#include "../HasLocalDataPoolIF.h"
LocalPoolDataSetBase* HasLocalDpIFManagerAttorney::getDataSetHandle(HasLocalDataPoolIF* clientIF,
sid_t sid) {
return clientIF->getDataSetHandle(sid);
}
LocalPoolObjectBase* HasLocalDpIFManagerAttorney::getPoolObjectHandle(HasLocalDataPoolIF* clientIF,
lp_id_t localPoolId) {
return clientIF->getPoolObjectHandle(localPoolId);
}
object_id_t HasLocalDpIFManagerAttorney::getObjectId(HasLocalDataPoolIF* clientIF) {
return clientIF->getObjectId();
}

View File

@ -0,0 +1,22 @@
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDPIFMANAGERATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_HASLOCALDPIFMANAGERATTORNEY_H_
#include "../localPoolDefinitions.h"
class HasLocalDataPoolIF;
class LocalPoolDataSetBase;
class LocalPoolObjectBase;
class HasLocalDpIFManagerAttorney {
static LocalPoolDataSetBase* getDataSetHandle(HasLocalDataPoolIF* clientIF, sid_t sid);
static LocalPoolObjectBase* getPoolObjectHandle(HasLocalDataPoolIF* clientIF,
lp_id_t localPoolId);
static object_id_t getObjectId(HasLocalDataPoolIF* clientIF);
friend class LocalDataPoolManager;
};
#endif /* FSFW_DATAPOOLLOCAL_HASLOCALDPIFMANAGERATTORNEY_H_ */

View File

@ -0,0 +1,7 @@
#include "HasLocalDpIFUserAttorney.h"
#include "../AccessLocalPoolF.h"
#include "../HasLocalDataPoolIF.h"
AccessPoolManagerIF* HasLocalDpIFUserAttorney::getAccessorHandle(HasLocalDataPoolIF *clientIF) {
return clientIF->getAccessorHandle();
}

View File

@ -0,0 +1,18 @@
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDPIFUSERATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_HASLOCALDPIFUSERATTORNEY_H_
class HasLocalDataPoolIF;
class AccessPoolManagerIF;
class HasLocalDpIFUserAttorney {
private:
static AccessPoolManagerIF* getAccessorHandle(HasLocalDataPoolIF* clientIF);
friend class LocalPoolObjectBase;
friend class LocalPoolDataSetBase;
};
#endif /* FSFW_DATAPOOLLOCAL_HASLOCALDPIFUSERATTORNEY_H_ */

View File

@ -0,0 +1,32 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALDPMANAGERATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_LOCALDPMANAGERATTORNEY_H_
#include "../LocalDataPoolManager.h"
/**
* @brief This is a helper class implements the Attorney-Client idiom for access to
* LocalDataPoolManager internals
* @details
* This helper class provides better control over which classes are allowed to access
* LocalDataPoolManager internals in a granular and encapsulated way when compared to
* other methods like direct friend declarations. It allows these classes to use
* an explicit subset of the pool manager private/protected functions.
* See: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Friendship_and_the_Attorney-Client
*/
class LocalDpManagerAttorney {
private:
template<typename T> static ReturnValue_t fetchPoolEntry(LocalDataPoolManager& manager,
lp_id_t localPoolId, PoolEntry<T> **poolEntry) {
return manager.fetchPoolEntry(localPoolId, poolEntry);
}
static MutexIF* getMutexHandle(LocalDataPoolManager& manager) {
return manager.getMutexHandle();
}
template<typename T> friend class LocalPoolVariable;
template<typename T, uint16_t vecSize> friend class LocalPoolVector;
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALDPMANAGERATTORNEY_H_ */

View File

@ -0,0 +1,39 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETATTORNEY_H_
#include "../LocalPoolDataSetBase.h"
class LocalPoolDataSetAttorney {
private:
static void setDiagnostic(LocalPoolDataSetBase& set, bool diagnostics) {
set.setDiagnostic(diagnostics);
}
static bool isDiagnostics(LocalPoolDataSetBase& set) {
return set.isDiagnostics();
}
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
uint32_t minimumPeriodicIntervalMs,
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs, isDiagnostics,
nonDiagIntervalFactor);
}
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {
set.setReportingEnabled(enabled);
}
static bool getReportingEnabled(LocalPoolDataSetBase& set) {
return set.getReportingEnabled();
}
static PeriodicHousekeepingHelper* getPeriodicHelper(LocalPoolDataSetBase& set) {
return set.periodicHelper;
}
friend class LocalDataPoolManager;
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETATTORNEY_H_ */

View File

@ -1,10 +1,13 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCPOOLDEFINITIONS_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_
#define FSFW_DATAPOOLLOCAL_LOCPOOLDEFINITIONS_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_
#include <cstdint> #include "../datapool/PoolEntryIF.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
#include "../objectmanager/frameworkObjects.h" #include "../objectmanager/frameworkObjects.h"
#include <cstdint>
#include <map>
/** /**
* @brief Type definition for local pool entries. * @brief Type definition for local pool entries.
*/ */
@ -12,10 +15,21 @@ using lp_id_t = uint32_t;
namespace localpool { namespace localpool {
static constexpr uint32_t INVALID_LPID = -1; static constexpr uint32_t INVALID_LPID = -1;
static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF;
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
//! This is the core data structure of the local data pools. Users should insert all desired
//! pool variables, using the std::map interface.
using DataPool = std::map<lp_id_t, PoolEntryIF*>;
using DataPoolMapIter = DataPool::iterator;
} }
/** /**
* Used as a unique identifier for data sets. * Used as a unique identifier for data sets. Consists of 4 byte object ID and 4 byte set ID.
*/ */
union sid_t { union sid_t {
static constexpr uint64_t INVALID_SID = -1; static constexpr uint64_t INVALID_SID = -1;
@ -57,7 +71,8 @@ union sid_t {
}; };
/** /**
* Used as a global unique identifier for local pool variables. * Used as a global unique identifier for local pool variables. Consists of 4 byte object ID
* and 4 byte local pool ID.
*/ */
union gp_id_t { union gp_id_t {
static constexpr uint64_t INVALID_GPID = -1; static constexpr uint64_t INVALID_GPID = -1;
@ -90,4 +105,4 @@ union gp_id_t {
} }
}; };
#endif /* FSFW_DATAPOOLLOCAL_LOCPOOLDEFINITIONS_H_ */ #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_ */

View File

@ -2,7 +2,7 @@
#include "AcceptsDeviceResponsesIF.h" #include "AcceptsDeviceResponsesIF.h"
#include "DeviceTmReportingWrapper.h" #include "DeviceTmReportingWrapper.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#include "../objectmanager/ObjectManager.h" #include "../objectmanager/ObjectManager.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include "../thermal/ThermalComponentIF.h" #include "../thermal/ThermalComponentIF.h"
@ -13,9 +13,6 @@
#include "../subsystem/SubsystemBase.h" #include "../subsystem/SubsystemBase.h"
#include "../datapoollocal/LocalPoolVariable.h" #include "../datapoollocal/LocalPoolVariable.h"
#include <iomanip>
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
@ -27,7 +24,7 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS),
deviceCommunicationId(deviceCommunication), comCookie(comCookie), deviceCommunicationId(deviceCommunication), comCookie(comCookie),
healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this),
actionHelper(this, nullptr), hkManager(this, nullptr), actionHelper(this, nullptr), poolManager(this, nullptr),
childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance),
hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr),
switchOffWasReported(false), childTransitionDelay(5000), switchOffWasReported(false), childTransitionDelay(5000),
@ -39,13 +36,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
cookieInfo.state = COOKIE_UNUSED; cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end(); cookieInfo.pendingCommand = deviceCommandMap.end();
if (comCookie == nullptr) { if (comCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
<< std::setw(8) << std::setfill('0') << this->getObjectId()
<< std::dec << ": Do not pass nullptr as a cookie, consider "
<< std::setfill(' ') << "passing a dummy cookie instead!"
<< std::endl;
#endif
} }
if (this->fdirInstance == nullptr) { if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId,
@ -115,7 +107,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
doGetRead(); doGetRead();
// This will be performed after datasets have been updated by the // This will be performed after datasets have been updated by the
// custom device implementation. // custom device implementation.
hkManager.performHkOperation(); poolManager.performHkOperation();
break; break;
default: default:
break; break;
@ -132,30 +124,24 @@ ReturnValue_t DeviceHandlerBase::initialize() {
communicationInterface = objectManager->get<DeviceCommunicationIF>( communicationInterface = objectManager->get<DeviceCommunicationIF>(
deviceCommunicationId); deviceCommunicationId);
if (communicationInterface == nullptr) { if (communicationInterface == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
sif::error << "DeviceHandlerBase::initialize: Communication interface " ObjectManagerIF::CHILD_INIT_FAILED,
"invalid." << std::endl; "Passed communication IF invalid");
sif::error << "Make sure it is set up properly and implements"
" DeviceCommunicationIF" << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
result = communicationInterface->initializeInterface(comCookie); result = communicationInterface->initializeInterface(comCookie);
if (result != RETURN_OK) { if (result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
sif::error << "DeviceHandlerBase::initialize: Initializing " ObjectManagerIF::CHILD_INIT_FAILED,
"communication interface failed!" << std::endl; "ComIF initialization failed");
#endif
return result; return result;
} }
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE); IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == nullptr) { if (IPCStore == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
sif::error << "DeviceHandlerBase::initialize: IPC store not set up in " ObjectManagerIF::CHILD_INIT_FAILED, "IPC Store not set up");
"factory." << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
@ -164,11 +150,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
AcceptsDeviceResponsesIF>(rawDataReceiverId); AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == nullptr) { if (rawReceiver == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_ERROR,
"initialize", ObjectManagerIF::CHILD_INIT_FAILED,
"Raw receiver object ID set but no valid object found.");
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::initialize: Raw receiver object "
"ID set but no valid object found." << std::endl;
sif::error << "Make sure the raw receiver object is set up properly" sif::error << "Make sure the raw receiver object is set up properly"
" and implements AcceptsDeviceResponsesIF" << std::endl; " and implements AcceptsDeviceResponsesIF" << std::endl;
#else
sif::printError("Make sure the raw receiver object is set up "
"properly and implements AcceptsDeviceResponsesIF\n");
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
@ -178,11 +168,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if(powerSwitcherId != objects::NO_OBJECT) { if(powerSwitcherId != objects::NO_OBJECT) {
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId); powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
if (powerSwitcher == nullptr) { if (powerSwitcher == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_ERROR,
"initialize", ObjectManagerIF::CHILD_INIT_FAILED,
"Power switcher set but no valid object found.");
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::initialize: Power switcher " sif::error << "Make sure the power switcher object is set up "
<< "object ID set but no valid object found." << std::endl; << "properly and implements PowerSwitchIF" << std::endl;
sif::error << "Make sure the raw receiver object is set up properly" #else
<< " and implements PowerSwitchIF" << std::endl; sif::printError("Make sure the power switcher object is set up "
"properly and implements PowerSwitchIF\n");
#endif #endif
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
@ -216,7 +210,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
return result; return result;
} }
result = hkManager.initialize(commandQueue); result = poolManager.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
@ -229,7 +223,8 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if(result == HasReturnvaluesIF::RETURN_OK) { if(result == HasReturnvaluesIF::RETURN_OK) {
thermalSet->heaterRequest.value = thermalSet->heaterRequest.value =
ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
thermalSet->commit(PoolVariableIF::VALID); thermalSet->heaterRequest.setValid(true);
thermalSet->commit();
} }
} }
@ -285,7 +280,7 @@ void DeviceHandlerBase::readCommandQueue() {
return; return;
} }
result = hkManager.handleHousekeepingMessage(&command); result = poolManager.handleHousekeepingMessage(&command);
if (result == RETURN_OK) { if (result == RETURN_OK) {
return; return;
} }
@ -580,7 +575,8 @@ void DeviceHandlerBase::replyToCommand(ReturnValue_t status,
void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter, void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter,
ReturnValue_t status) { ReturnValue_t status) {
//No need to check if iter exists, as this is checked by callers. If someone else uses the method, add check. // No need to check if iter exists, as this is checked by callers.
// If someone else uses the method, add check.
if (iter->second.command == deviceCommandMap.end()) { if (iter->second.command == deviceCommandMap.end()) {
//Is most likely periodic reply. Silent return. //Is most likely periodic reply. Silent return.
return; return;
@ -588,7 +584,8 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter,
// Check if more replies are expected. If so, do nothing. // Check if more replies are expected. If so, do nothing.
DeviceCommandInfo* info = &(iter->second.command->second); DeviceCommandInfo* info = &(iter->second.command->second);
if (--info->expectedReplies == 0) { if (--info->expectedReplies == 0) {
//Check if it was transition or internal command. Don't send any replies in that case. // Check if it was transition or internal command.
// Don't send any replies in that case.
if (info->sendReplyTo != NO_COMMANDER) { if (info->sendReplyTo != NO_COMMANDER) {
actionHelper.finish(info->sendReplyTo, iter->first, status); actionHelper.finish(info->sendReplyTo, iter->first, status);
} }
@ -720,10 +717,9 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
case RETURN_OK: case RETURN_OK:
handleReply(receivedData, foundId, foundLen); handleReply(receivedData, foundId, foundLen);
if(foundLen == 0) { if(foundLen == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" "parseReply", ObjectManagerIF::CHILD_INIT_FAILED,
" Packet parsing will be stuck." << std::endl; "Found length is one, parsing might be stuck");
#endif
} }
break; break;
case APERIODIC_REPLY: { case APERIODIC_REPLY: {
@ -734,6 +730,9 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
foundId); foundId);
} }
if(foundLen == 0) { if(foundLen == 0) {
printWarningOrError(sif::OutputTypes::OUT_ERROR,
"parseReply", ObjectManagerIF::CHILD_INIT_FAILED,
"Power switcher set but no valid object found.");
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!"
" Packet parsing will be stuck." << std::endl; " Packet parsing will be stuck." << std::endl;
@ -746,7 +745,8 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
case IGNORE_FULL_PACKET: case IGNORE_FULL_PACKET:
return; return;
default: default:
//We need to wait for timeout.. don't know what command failed and who sent it. // We need to wait for timeout.. don't know what command failed
// and who sent it.
replyRawReplyIfnotWiretapped(receivedData, foundLen); replyRawReplyIfnotWiretapped(receivedData, foundLen);
triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen); triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen);
break; break;
@ -967,7 +967,8 @@ ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) {
} }
Mode_t DeviceHandlerBase::getBaseMode(Mode_t transitionMode) { Mode_t DeviceHandlerBase::getBaseMode(Mode_t transitionMode) {
//only child action special modes are handled, as a child should never see any base action modes // only child action special modes are handled, as a child should
// never see any base action modes
if (transitionMode == _MODE_START_UP) { if (transitionMode == _MODE_START_UP) {
return _MODE_TO_ON; return _MODE_TO_ON;
} }
@ -1291,11 +1292,10 @@ void DeviceHandlerBase::buildInternalCommand(void) {
result = buildNormalDeviceCommand(&deviceCommandId); result = buildNormalDeviceCommand(&deviceCommandId);
if (result == BUSY) { if (result == BUSY) {
// so we can track misconfigurations // so we can track misconfigurations
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::debug << std::hex << getObjectId() "buildInternalCommand",
<< ": DHB::buildInternalCommand: Busy" << std::dec HasReturnvaluesIF::RETURN_FAILED,
<< std::endl; "Busy.");
#endif
result = NOTHING_TO_SEND; //no need to report this result = NOTHING_TO_SEND; //no need to report this
} }
} }
@ -1319,12 +1319,15 @@ void DeviceHandlerBase::buildInternalCommand(void) {
if (iter == deviceCommandMap.end()) { if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED; result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) { } else if (iter->second.isExecuting) {
#if FSFW_DISABLE_PRINTOUT == 0
char output[36];
sprintf(output, "Command 0x%08x is executing",
static_cast<unsigned int>(deviceCommandId));
// so we can track misconfigurations // so we can track misconfigurations
#if FSFW_CPP_OSTREAM_ENABLED == 1 printWarningOrError(sif::OutputTypes::OUT_WARNING,
sif::debug << std::hex << getObjectId() "buildInternalCommand",
<< ": DHB::buildInternalCommand: Command " HasReturnvaluesIF::RETURN_FAILED,
<< deviceCommandId << " isExecuting" << std::dec output);
<< std::endl;
#endif #endif
// this is an internal command, no need to report a failure here, // this is an internal command, no need to report a failure here,
// missed reply will track if a reply is too late, otherwise, it's ok // missed reply will track if a reply is too late, otherwise, it's ok
@ -1418,7 +1421,7 @@ void DeviceHandlerBase::performOperationHook() {
} }
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool( ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(
LocalDataPool &localDataPoolMap, localpool::DataPool &localDataPoolMap,
LocalDataPoolManager& poolManager) { LocalDataPoolManager& poolManager) {
if(thermalSet != nullptr) { if(thermalSet != nullptr) {
localDataPoolMap.emplace(thermalSet->thermalStatePoolId, localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
@ -1429,18 +1432,13 @@ ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(
return RETURN_OK; return RETURN_OK;
} }
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
return &hkManager;
}
ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
// In this function, the task handle should be valid if the task // In this function, the task handle should be valid if the task
// was implemented correctly. We still check to be 1000 % sure :-) // was implemented correctly. We still check to be 1000 % sure :-)
if(executingTask != nullptr) { if(executingTask != nullptr) {
pstIntervalMs = executingTask->getPeriodMs(); pstIntervalMs = executingTask->getPeriodMs();
} }
this->hkManager.initializeAfterTaskCreation(); this->poolManager.initializeAfterTaskCreation();
if(setStartupImmediately) { if(setStartupImmediately) {
startTransition(MODE_ON, SUBMODE_NONE); startTransition(MODE_ON, SUBMODE_NONE);
@ -1484,3 +1482,52 @@ void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
} }
} }
} }
void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
const char *functionName, ReturnValue_t errorCode,
const char *errorPrint) {
if(errorPrint == nullptr) {
if(errorCode == ObjectManagerIF::CHILD_INIT_FAILED) {
errorPrint = "Initialization error";
}
if(errorCode == HasReturnvaluesIF::RETURN_FAILED) {
if(errorType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";
}
else {
errorPrint = "Generic Error";
}
}
else {
errorPrint = "Unknown error";
}
}
if(errorType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "DeviceHandlerBase::" << functionName << ": Object ID "
<< std::hex << std::setw(8) << std::setfill('0')
<< this->getObjectId() << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
sif::printWarning("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint);
#endif
}
else if(errorType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::" << functionName << ": Object ID "
<< std::hex << std::setw(8) << std::setfill('0')
<< this->getObjectId() << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
sif::printError("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint);
#endif
}
}
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
return &poolManager;
}

View File

@ -6,6 +6,8 @@
#include "DeviceHandlerFailureIsolation.h" #include "DeviceHandlerFailureIsolation.h"
#include "DeviceHandlerThermalSet.h" #include "DeviceHandlerThermalSet.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../serviceinterface/serviceInterfaceDefintions.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h" #include "../tasks/ExecutableObjectIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
@ -512,11 +514,14 @@ protected:
* @param localDataPoolMap * @param localDataPoolMap
* @return * @return
*/ */
virtual ReturnValue_t initializeLocalDataPool(LocalDataPool& localDataPoolMap, virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override; LocalDataPoolManager& poolManager) override;
/** Get the HK manager object handle */ /**
virtual LocalDataPoolManager* getHkManagerHandle() override; * Required for HasLocalDataPoolIF, return a handle to the local pool manager.
* @return
*/
LocalDataPoolManager* getHkManagerHandle() override;
/** /**
* @brief Hook function for child handlers which is called once per * @brief Hook function for child handlers which is called once per
@ -646,7 +651,7 @@ protected:
/** Action helper for HasActionsIF */ /** Action helper for HasActionsIF */
ActionHelper actionHelper; ActionHelper actionHelper;
/** Housekeeping Manager */ /** Housekeeping Manager */
LocalDataPoolManager hkManager; LocalDataPoolManager poolManager;
/** /**
* @brief Information about commands * @brief Information about commands
@ -1111,7 +1116,7 @@ private:
/** /**
* @brief The mode the current transition originated from * @brief The mode the current transition originated from
* *
* This is private so the child can not change it and fuck up the timeouts * This is private so the child can not change it and mess up the timeouts
* *
* IMPORTANT: This is not valid during _MODE_SHUT_DOWN and _MODE_START_UP!! * IMPORTANT: This is not valid during _MODE_SHUT_DOWN and _MODE_START_UP!!
* (it is _MODE_POWER_DOWN during this modes) * (it is _MODE_POWER_DOWN during this modes)
@ -1190,7 +1195,8 @@ private:
* Check if the RMAP sendWrite action was successful. * Check if the RMAP sendWrite action was successful.
* *
* Depending on the result, the following is done * Depending on the result, the following is done
* - if the device command was external commanded, a reply is sent indicating the result * - if the device command was external commanded, a reply is sent
* indicating the result
* - if the action was successful, the reply timout counter is initialized * - if the action was successful, the reply timout counter is initialized
*/ */
void doGetWrite(void); void doGetWrite(void);
@ -1206,9 +1212,9 @@ private:
/** /**
* Check the getRead reply and the contained data. * Check the getRead reply and the contained data.
* *
* If data was received scanForReply() and, if successful, handleReply() are called. * If data was received scanForReply() and, if successful, handleReply()
* If the current mode is @c MODE_RAW, the received packet is sent to the commanding object * are called. If the current mode is @c MODE_RAW, the received packet
* via commandQueue. * is sent to the commanding object via commandQueue.
*/ */
void doGetRead(void); void doGetRead(void);
@ -1227,7 +1233,7 @@ private:
uint32_t *len); uint32_t *len);
/** /**
* @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!! * @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW, nothing else!
*/ */
void setTransition(Mode_t modeTo, Submode_t submodeTo); void setTransition(Mode_t modeTo, Submode_t submodeTo);
@ -1247,6 +1253,11 @@ private:
void handleTransitionToOnMode(Mode_t commandedMode, void handleTransitionToOnMode(Mode_t commandedMode,
Submode_t commandedSubmode); Submode_t commandedSubmode);
void printWarningOrError(sif::OutputTypes errorType,
const char* functionName,
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
const char* errorPrint = nullptr);
}; };
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ #endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

View File

@ -3,8 +3,8 @@
#include "DeviceHandlerMessage.h" #include "DeviceHandlerMessage.h"
#include "../datapoollocal/localPoolDefinitions.h"
#include "../action/HasActionsIF.h" #include "../action/HasActionsIF.h"
#include "../datapoollocal/locPoolDefinitions.h"
#include "../events/Event.h" #include "../events/Event.h"
#include "../modes/HasModesIF.h" #include "../modes/HasModesIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"

View File

@ -162,9 +162,15 @@ void EventManager::printEvent(EventMessage* message) {
#endif #endif
void EventManager::lockMutex() { void EventManager::lockMutex() {
mutex->lockMutex(MutexIF::BLOCKING); mutex->lockMutex(timeoutType, timeoutMs);
} }
void EventManager::unlockMutex() { void EventManager::unlockMutex() {
mutex->unlockMutex(); mutex->unlockMutex();
} }
void EventManager::setMutexTimeout(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
this->timeoutType = timeoutType;
this->timeoutMs = timeoutMs;
}

View File

@ -29,6 +29,8 @@ public:
EventManager(object_id_t setObjectId); EventManager(object_id_t setObjectId);
virtual ~EventManager(); virtual ~EventManager();
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
MessageQueueId_t getEventReportQueue(); MessageQueueId_t getEventReportQueue();
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false); ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
@ -51,6 +53,8 @@ protected:
std::map<MessageQueueId_t, EventMatchTree> listenerList; std::map<MessageQueueId_t, EventMatchTree> listenerList;
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
static const uint8_t N_POOLS = 3; static const uint8_t N_POOLS = 3;
LocalPool factoryBackend; LocalPool factoryBackend;

View File

@ -10,6 +10,7 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/internal/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp)

View File

@ -1,5 +1,5 @@
#include "arrayprinter.h" #include "arrayprinter.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#include <bitset> #include <bitset>
void arrayprinter::print(const uint8_t *data, size_t size, OutputType type, void arrayprinter::print(const uint8_t *data, size_t size, OutputType type,
@ -9,6 +9,8 @@ void arrayprinter::print(const uint8_t *data, size_t size, OutputType type,
sif::info << "Printing data with size " << size << ": "; sif::info << "Printing data with size " << size << ": ";
} }
sif::info << "["; sif::info << "[";
#else
sif::printInfo("Printing data with size %zu: [", size);
#endif #endif
if(type == OutputType::HEX) { if(type == OutputType::HEX) {
arrayprinter::printHex(data, size, maxCharPerLine); arrayprinter::printHex(data, size, maxCharPerLine);
@ -37,6 +39,8 @@ void arrayprinter::printHex(const uint8_t *data, size_t size,
} }
sif::info << std::dec; sif::info << std::dec;
sif::info << "]" << std::endl; sif::info << "]" << std::endl;
#else
// how much memory to reserve for printout?
#endif #endif
} }
@ -54,6 +58,8 @@ void arrayprinter::printDec(const uint8_t *data, size_t size,
} }
} }
sif::info << "]" << std::endl; sif::info << "]" << std::endl;
#else
// how much memory to reserve for printout?
#endif #endif
} }
@ -65,5 +71,7 @@ void arrayprinter::printBin(const uint8_t *data, size_t size) {
std::bitset<8>(data[i]) << ",\n" << std::flush; std::bitset<8>(data[i]) << ",\n" << std::flush;
} }
sif::info << "]" << std::endl; sif::info << "]" << std::endl;
#else
// how much memory to reserve for printout?
#endif #endif
} }

View File

@ -1,7 +1,7 @@
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ #ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ #define FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#include "../datapoollocal/locPoolDefinitions.h" #include "../datapoollocal/localPoolDefinitions.h"
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../ipc/FwMessageTypes.h" #include "../ipc/FwMessageTypes.h"
#include "../objectmanager/frameworkObjects.h" #include "../objectmanager/frameworkObjects.h"

View File

@ -21,11 +21,11 @@ public:
InternalErrorDataset(object_id_t objectId): InternalErrorDataset(object_id_t objectId):
StaticLocalDataSet(sid_t(objectId , ERROR_SET_ID)) {} StaticLocalDataSet(sid_t(objectId , ERROR_SET_ID)) {}
lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(hkManager->getOwner(), lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(sid.objectId,
TM_HITS, this); TM_HITS, this);
lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(hkManager->getOwner(), lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(sid.objectId,
QUEUE_HITS, this); QUEUE_HITS, this);
lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(hkManager->getOwner(), lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(sid.objectId,
STORE_HITS, this); STORE_HITS, this);
}; };

View File

@ -2,7 +2,7 @@
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
uint32_t messageQueueDepth): SystemObject(setObjectId), uint32_t messageQueueDepth): SystemObject(setObjectId),
@ -23,13 +23,13 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
} }
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
internalErrorDataset.read(INTERNAL_ERROR_MUTEX_TIMEOUT); internalErrorDataset.read(timeoutType, timeoutMs);
uint32_t newQueueHits = getAndResetQueueHits(); uint32_t newQueueHits = getAndResetQueueHits();
uint32_t newTmHits = getAndResetTmHits(); uint32_t newTmHits = getAndResetTmHits();
uint32_t newStoreHits = getAndResetStoreHits(); uint32_t newStoreHits = getAndResetStoreHits();
#if FSFW_ENHANCED_PRINTOUT == 1 #if FSFW_VERBOSE_LEVEL == 1
if(diagnosticPrintout) { if(diagnosticPrintout) {
if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) { if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@ -38,6 +38,11 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
sif::debug << "Queue errors: " << newQueueHits << std::endl; sif::debug << "Queue errors: " << newQueueHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl; sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl; sif::debug << "Store errors: " << newStoreHits << std::endl;
#else
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
#endif #endif
} }
} }
@ -46,8 +51,8 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
internalErrorDataset.queueHits.value += newQueueHits; internalErrorDataset.queueHits.value += newQueueHits;
internalErrorDataset.storeHits.value += newStoreHits; internalErrorDataset.storeHits.value += newStoreHits;
internalErrorDataset.tmHits.value += newTmHits; internalErrorDataset.tmHits.value += newTmHits;
internalErrorDataset.setValidity(true, true);
internalErrorDataset.commit(INTERNAL_ERROR_MUTEX_TIMEOUT); internalErrorDataset.commit(timeoutType, timeoutMs);
poolManager.performHkOperation(); poolManager.performHkOperation();
@ -69,7 +74,7 @@ void InternalErrorReporter::lostTm() {
uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
value = queueHits; value = queueHits;
queueHits = 0; queueHits = 0;
mutex->unlockMutex(); mutex->unlockMutex();
@ -78,21 +83,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t InternalErrorReporter::getQueueHits() { uint32_t InternalErrorReporter::getQueueHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
value = queueHits; value = queueHits;
mutex->unlockMutex(); mutex->unlockMutex();
return value; return value;
} }
void InternalErrorReporter::incrementQueueHits() { void InternalErrorReporter::incrementQueueHits() {
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
queueHits++; queueHits++;
mutex->unlockMutex(); mutex->unlockMutex();
} }
uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
value = tmHits; value = tmHits;
tmHits = 0; tmHits = 0;
mutex->unlockMutex(); mutex->unlockMutex();
@ -101,14 +106,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t InternalErrorReporter::getTmHits() { uint32_t InternalErrorReporter::getTmHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
value = tmHits; value = tmHits;
mutex->unlockMutex(); mutex->unlockMutex();
return value; return value;
} }
void InternalErrorReporter::incrementTmHits() { void InternalErrorReporter::incrementTmHits() {
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
tmHits++; tmHits++;
mutex->unlockMutex(); mutex->unlockMutex();
} }
@ -119,7 +124,7 @@ void InternalErrorReporter::storeFull() {
uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
value = storeHits; value = storeHits;
storeHits = 0; storeHits = 0;
mutex->unlockMutex(); mutex->unlockMutex();
@ -128,14 +133,14 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t InternalErrorReporter::getStoreHits() { uint32_t InternalErrorReporter::getStoreHits() {
uint32_t value; uint32_t value;
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
value = storeHits; value = storeHits;
mutex->unlockMutex(); mutex->unlockMutex();
return value; return value;
} }
void InternalErrorReporter::incrementStoreHits() { void InternalErrorReporter::incrementStoreHits() {
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); mutex->lockMutex(timeoutType, timeoutMs);
storeHits++; storeHits++;
mutex->unlockMutex(); mutex->unlockMutex();
} }
@ -149,7 +154,7 @@ MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
} }
ReturnValue_t InternalErrorReporter::initializeLocalDataPool( ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(errorPoolIds::TM_HITS, localDataPoolMap.emplace(errorPoolIds::TM_HITS,
new PoolEntry<uint32_t>()); new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS,
@ -162,10 +167,6 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
return &poolManager;
}
dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const { dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs(); return this->executingTask->getPeriodMs();
} }
@ -190,3 +191,12 @@ ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation(); return poolManager.initializeAfterTaskCreation();
} }
void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
this->timeoutType = timeoutType;
this->timeoutMs = timeoutMs;
}
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
return &poolManager;
}

View File

@ -22,7 +22,6 @@ class InternalErrorReporter: public SystemObject,
public InternalErrorReporterIF, public InternalErrorReporterIF,
public HasLocalDataPoolIF { public HasLocalDataPoolIF {
public: public:
static constexpr uint8_t INTERNAL_ERROR_MUTEX_TIMEOUT = 20;
InternalErrorReporter(object_id_t setObjectId, InternalErrorReporter(object_id_t setObjectId,
uint32_t messageQueueDepth = 5); uint32_t messageQueueDepth = 5);
@ -34,16 +33,19 @@ public:
*/ */
void setDiagnosticPrintout(bool enable); void setDiagnosticPrintout(bool enable);
void setMutexTimeout(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs);
virtual ~InternalErrorReporter(); virtual ~InternalErrorReporter();
virtual object_id_t getObjectId() const override; virtual object_id_t getObjectId() const override;
virtual MessageQueueId_t getCommandQueue() const override; virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t initializeLocalDataPool( virtual ReturnValue_t initializeLocalDataPool(
LocalDataPool& localDataPoolMap, localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override; LocalDataPoolManager& poolManager) override;
virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual dur_millis_t getPeriodicOperationFrequency() const override; virtual dur_millis_t getPeriodicOperationFrequency() const override;
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
LocalDataPoolManager* getHkManagerHandle() override;
virtual ReturnValue_t initialize() override; virtual ReturnValue_t initialize() override;
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t initializeAfterTaskCreation() override;
@ -61,7 +63,11 @@ protected:
LocalDataPoolManager poolManager; LocalDataPoolManager poolManager;
PeriodicTaskIF* executingTask = nullptr; PeriodicTaskIF* executingTask = nullptr;
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
sid_t internalErrorSid; sid_t internalErrorSid;
InternalErrorDataset internalErrorDataset; InternalErrorDataset internalErrorDataset;

View File

@ -14,7 +14,7 @@ public:
/** /**
* Different types of timeout for the mutex lock. * Different types of timeout for the mutex lock.
*/ */
enum TimeoutType { enum class TimeoutType {
POLLING, //!< If mutex is not available, return immediately POLLING, //!< If mutex is not available, return immediately
WAITING, //!< Wait a specified time for the mutex to become available WAITING, //!< Wait a specified time for the mutex to become available
BLOCKING //!< Block indefinitely until the mutex becomes available. BLOCKING //!< Block indefinitely until the mutex becomes available.

View File

@ -5,7 +5,7 @@
#include "MonitoringIF.h" #include "MonitoringIF.h"
#include "MonitoringMessageContent.h" #include "MonitoringMessageContent.h"
#include "../datapoollocal/locPoolDefinitions.h" #include "../datapoollocal/localPoolDefinitions.h"
#include "../events/EventManagerIF.h" #include "../events/EventManagerIF.h"
#include "../parameters/HasParametersIF.h" #include "../parameters/HasParametersIF.h"

View File

@ -1,9 +1,10 @@
#ifndef MONITORINGMESSAGECONTENT_H_ #ifndef FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_
#define MONITORINGMESSAGECONTENT_H_ #define FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_
#include "HasMonitorsIF.h" #include "HasMonitorsIF.h"
#include "MonitoringIF.h" #include "MonitoringIF.h"
#include "../datapoollocal/locPoolDefinitions.h"
#include "../datapoollocal/localPoolDefinitions.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerialBufferAdapter.h" #include "../serialize/SerialBufferAdapter.h"
#include "../serialize/SerialFixedArrayListAdapter.h" #include "../serialize/SerialFixedArrayListAdapter.h"
@ -85,4 +86,4 @@ private:
template<typename T> template<typename T>
object_id_t MonitoringReportContent<T>::timeStamperId = 0; object_id_t MonitoringReportContent<T>::timeStamperId = 0;
#endif /* MONITORINGMESSAGECONTENT_H_ */ #endif /* FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_ */

View File

@ -163,7 +163,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) { if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
@ -178,7 +178,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if (timeMutex == NULL) { if (timeMutex == NULL) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }

View File

@ -202,7 +202,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); ReturnValue_t result = timeMutex->lockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
@ -217,7 +217,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if(timeMutex == nullptr){ if(timeMutex == nullptr){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); ReturnValue_t result = timeMutex->lockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }

View File

@ -4,16 +4,16 @@
Mutex::Mutex() {} Mutex::Mutex() {}
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) {
if(timeoutType == MutexIF::BLOCKING) { if(timeoutType == TimeoutType::BLOCKING) {
mutex.lock(); mutex.lock();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else if(timeoutType == MutexIF::POLLING) { else if(timeoutType == TimeoutType::POLLING) {
if(mutex.try_lock()) { if(mutex.try_lock()) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
} }
else if(timeoutMs > MutexIF::POLLING){ else if(timeoutType == TimeoutType::WAITING){
auto chronoMs = std::chrono::milliseconds(timeoutMs); auto chronoMs = std::chrono::milliseconds(timeoutMs);
if(mutex.try_lock_for(chronoMs)) { if(mutex.try_lock_for(chronoMs)) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;

View File

@ -22,7 +22,6 @@ public:
std::timed_mutex* getMutexHandle(); std::timed_mutex* getMutexHandle();
private: private:
//bool locked = false;
std::timed_mutex mutex; std::timed_mutex mutex;
}; };

View File

@ -1,10 +1,11 @@
#include "BinarySemaphore.h" #include "BinarySemaphore.h"
#include "../../serviceinterface/ServiceInterfacePrinter.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
extern "C" { #include <time.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
}
BinarySemaphore::BinarySemaphore() { BinarySemaphore::BinarySemaphore() {
// Using unnamed semaphores for now // Using unnamed semaphores for now
@ -113,7 +114,8 @@ uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) {
} }
else if(result != 0 and errno == EINVAL) { else if(result != 0 and errno == EINVAL) {
// Could be called from interrupt, use lightweight printf // Could be called from interrupt, use lightweight printf
printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n"); sif::printError("BinarySemaphore::getSemaphoreCounter: "
"Invalid semaphore\n");
return 0; return 0;
} }
else { else {
@ -128,15 +130,19 @@ void BinarySemaphore::initSemaphore(uint8_t initCount) {
switch(errno) { switch(errno) {
case(EINVAL): case(EINVAL):
// Value exceeds SEM_VALUE_MAX // Value exceeds SEM_VALUE_MAX
case(ENOSYS): case(ENOSYS): {
// System does not support process-shared semaphores // System does not support process-shared semaphores
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "BinarySemaphore: Init failed with" << strerror(errno) sif::error << "BinarySemaphore: Init failed with "
<< std::endl; << strerror(errno) << std::endl;
#else
sif::printError("BinarySemaphore: Init failed with %s\n",
strerror(errno));
#endif #endif
} }
} }
} }
}
ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) {
int value = getSemaphoreCounter(handle); int value = getSemaphoreCounter(handle);

View File

@ -182,7 +182,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
@ -197,7 +197,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if(timeMutex==NULL){ if(timeMutex==NULL){
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
@ -209,13 +209,13 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
} }
ReturnValue_t Clock::checkOrCreateClockMutex(){ ReturnValue_t Clock::checkOrCreateClockMutex(){
if(timeMutex==NULL){ if(timeMutex == nullptr){
MutexFactory* mutexFactory = MutexFactory::instance(); MutexFactory* mutexFactory = MutexFactory::instance();
if (mutexFactory == NULL) { if (mutexFactory == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
timeMutex = mutexFactory->createMutex(); timeMutex = mutexFactory->createMutex();
if (timeMutex == NULL) { if (timeMutex == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }

View File

@ -1,5 +1,7 @@
#include "../../osal/linux/CountingSemaphore.h" #include "../../osal/linux/CountingSemaphore.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterface.h"
#include <errno.h>
CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount):
maxCount(maxCount), initCount(initCount) { maxCount(maxCount), initCount(initCount) {

View File

@ -1,5 +1,5 @@
#include "MessageQueue.h" #include "MessageQueue.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterface.h"
#include "../../objectmanager/ObjectManagerIF.h" #include "../../objectmanager/ObjectManagerIF.h"
#include <fstream> #include <fstream>
@ -121,14 +121,16 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
break; break;
} }
default: default: {
// Failed either the first time or the second time // Failed either the first time or the second time
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex sif::error << "MessageQueue::MessageQueue: Creating Queue " << name
<< name << std::dec << " failed with status: " << " failed with status: " << strerror(errno) << std::endl;
<< strerror(errno) << std::endl; #else
sif::printError("MessageQueue::MessageQueue: Creating Queue %s"
" failed with status: %s\n", name, strerror(errno));
#endif #endif
}
} }
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;

View File

@ -1,6 +1,6 @@
#include "PosixThread.h" #include "PosixThread.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterface.h"
#include <cstring> #include <cstring>
#include <errno.h> #include <errno.h>
@ -146,16 +146,22 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
strerror(status) << std::endl; strerror(status) << std::endl;
#endif #endif
if(errno == ENOMEM) { if(errno == ENOMEM) {
uint64_t stackMb = stackSize/10e6; size_t stackMb = stackSize/10e6;
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: Insufficient memory for" sif::error << "PosixThread::createTask: Insufficient memory for"
" the requested " << stackMb << " MB" << std::endl; " the requested " << stackMb << " MB" << std::endl;
#else
sif::printError("PosixThread::createTask: Insufficient memory for "
"the requested %zu MB\n", stackMb);
#endif #endif
} }
else if(errno == EINVAL) { else if(errno == EINVAL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PosixThread::createTask: Wrong alignment argument!" sif::error << "PosixThread::createTask: Wrong alignment argument!"
<< std::endl; << std::endl;
#else
sif::printError("PosixThread::createTask: "
"Wrong alignment argument!\n");
#endif #endif
} }
return; return;

View File

@ -1,6 +1,8 @@
#include "TcUnixUdpPollingTask.h" #include "TcUnixUdpPollingTask.h"
#include "../../globalfunctions/arrayprinter.h" #include "../../globalfunctions/arrayprinter.h"
#include <errno.h>
TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId, TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId,
object_id_t tmtcUnixUdpBridge, size_t frameSize, object_id_t tmtcUnixUdpBridge, size_t frameSize,
double timeoutSeconds): SystemObject(objectId), double timeoutSeconds): SystemObject(objectId),

View File

@ -1,5 +1,5 @@
#include "TmTcUnixUdpBridge.h" #include "TmTcUnixUdpBridge.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterface.h"
#include "../../ipc/MutexHelper.h" #include "../../ipc/MutexHelper.h"
#include <errno.h> #include <errno.h>
@ -188,13 +188,17 @@ void TmTcUnixUdpBridge::handleBindError() {
void TmTcUnixUdpBridge::handleSendError() { void TmTcUnixUdpBridge::handleSendError() {
switch(errno) { switch(errno) {
default: default: {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcUnixBridge::handleSendError: " sif::error << "TmTcUnixBridge::handleSendError: "
<< strerror(errno) << std::endl; << strerror(errno) << std::endl;
#else
sif::printError("TmTcUnixBridge::handleSendError: %s\n",
strerror(errno));
#endif #endif
} }
} }
}
void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){ void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){
this->ipAddrAnySet = ipAddrAnySet; this->ipAddrAnySet = ipAddrAnySet;

View File

@ -30,11 +30,11 @@ Mutex::~Mutex() {
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType = ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType =
TimeoutType::BLOCKING, uint32_t timeoutMs) { TimeoutType::BLOCKING, uint32_t timeoutMs) {
rtems_status_code status = RTEMS_INVALID_ID; rtems_status_code status = RTEMS_INVALID_ID;
if(timeoutMs == MutexIF::TimeoutType::BLOCKING) { if(timeoutType == MutexIF::TimeoutType::BLOCKING) {
status = rtems_semaphore_obtain(mutexId, status = rtems_semaphore_obtain(mutexId,
RTEMS_WAIT, RTEMS_NO_TIMEOUT); RTEMS_WAIT, RTEMS_NO_TIMEOUT);
} }
else if(timeoutMs == MutexIF::TimeoutType::POLLING) { else if(timeoutType == MutexIF::TimeoutType::POLLING) {
timeoutMs = RTEMS_NO_TIMEOUT; timeoutMs = RTEMS_NO_TIMEOUT;
status = rtems_semaphore_obtain(mutexId, status = rtems_semaphore_obtain(mutexId,
RTEMS_NO_WAIT, 0); RTEMS_NO_WAIT, 0);

View File

@ -65,8 +65,8 @@ ReturnValue_t Fuse::check() {
set.read(); set.read();
if (!healthHelper.healthTable->isHealthy(getObjectId())) { if (!healthHelper.healthTable->isHealthy(getObjectId())) {
setAllMonitorsToUnchecked(); setAllMonitorsToUnchecked();
set.commit(PoolVariableIF::INVALID); set.setValidity(false, true);
return RETURN_OK; return set.commit();
} }
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
checkFuseState(); checkFuseState();
@ -206,7 +206,8 @@ float Fuse::getPower() {
void Fuse::setDataPoolEntriesInvalid() { void Fuse::setDataPoolEntriesInvalid() {
set.read(); set.read();
set.commit(PoolVariableIF::INVALID); set.setValidity(false, true);
set.commit();
} }
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId,

View File

@ -97,7 +97,8 @@ void PowerSensor::checkCommandQueue() {
void PowerSensor::setDataPoolEntriesInvalid() { void PowerSensor::setDataPoolEntriesInvalid() {
powerSensorSet.read(); powerSensorSet.read();
powerSensorSet.commit(PoolVariableIF::INVALID); powerSensorSet.setValidity(false, true);
powerSensorSet.commit();
} }
float PowerSensor::getPower() { float PowerSensor::getPower() {

View File

@ -3,7 +3,9 @@
ReturnValue_t unitt::put_error(std::string errorId) { ReturnValue_t unitt::put_error(std::string errorId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Unit Tester error: Failed at test ID " sif::error << "Unit Tester error: Failed at test ID "
<< errorId << "\n" << std::flush; << errorId << std::endl;
#endif #else
sif::printError("Unit Tester error: Failed at test ID 0x%08x", errorId);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -2,9 +2,10 @@
#define UNITTEST_INTERNAL_UNITTDEFINITIONS_H_ #define UNITTEST_INTERNAL_UNITTDEFINITIONS_H_
#include "../../returnvalues/HasReturnvaluesIF.h" #include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterface.h"
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include <string>
namespace tv { namespace tv {
// POD test values // POD test values

View File

@ -13,7 +13,7 @@
void testmutex::testMutex() { void testmutex::testMutex() {
std::string id = "[testMutex]"; std::string id = "[testMutex]";
MutexIF* mutex = MutexFactory::instance()->createMutex(); MutexIF* mutex = MutexFactory::instance()->createMutex();
auto result = mutex->lockMutex(MutexIF::POLLING); auto result = mutex->lockMutex(MutexIF::TimeoutType::POLLING);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
unitt::put_error(id); unitt::put_error(id);
} }

View File

@ -2,5 +2,6 @@ add_subdirectory(action)
add_subdirectory(container) add_subdirectory(container)
add_subdirectory(osal) add_subdirectory(osal)
add_subdirectory(serialize) add_subdirectory(serialize)
add_subdirectory(datapoollocal)
add_subdirectory(storagemanager) add_subdirectory(storagemanager)

View File

@ -4,9 +4,12 @@
#include <fsfw/action/ActionHelper.h> #include <fsfw/action/ActionHelper.h>
#include <fsfw/ipc/CommandMessage.h> #include <fsfw/ipc/CommandMessage.h>
#include <fsfw/unittest/tests/mocks/MessageQueueMockBase.h>
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <array>
TEST_CASE( "Action Helper" , "[ActionHelper]") { TEST_CASE( "Action Helper" , "[ActionHelper]") {
ActionHelperOwnerMockBase testDhMock; ActionHelperOwnerMockBase testDhMock;

View File

@ -48,85 +48,4 @@ public:
}; };
class MessageQueueMockBase: public MessageQueueIF {
public:
MessageQueueId_t myQueueId = 0;
bool defaultDestSet = false;
bool messageSent = false;
bool wasMessageSent() {
bool tempMessageSent = messageSent;
messageSent = false;
return tempMessageSent;
}
virtual ReturnValue_t reply( MessageQueueMessageIF* message ) {
messageSent = true;
lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
return HasReturnvaluesIF::RETURN_OK;
};
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom) {
(*message) = lastMessage;
lastMessage.clear();
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) {
memcpy(message->getBuffer(), lastMessage.getBuffer(),
message->getMessageSize());
lastMessage.clear();
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
virtual MessageQueueId_t getLastPartner() const {
return tconst::testQueueId;
}
virtual MessageQueueId_t getId() const {
return tconst::testQueueId;
}
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false ) {
messageSent = true;
lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault = false ) override {
messageSent = true;
lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false ) {
messageSent = true;
lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) {
messageSent = true;
lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
return HasReturnvaluesIF::RETURN_OK;
}
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) {
myQueueId = defaultDestination;
defaultDestSet = true;
}
virtual MessageQueueId_t getDefaultDestination() const {
return myQueueId;
}
virtual bool isDefaultDestinationSet() const {
return defaultDestSet;
}
private:
MessageQueueMessage lastMessage;
};
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTACTIONHELPER_H_ */ #endif /* UNITTEST_TESTFW_NEWTESTS_TESTACTIONHELPER_H_ */

View File

@ -1,45 +1,48 @@
//#include <fsfw/container/PlacementFactory.h> #include <fsfw/container/PlacementFactory.h>
//#include <fsfw/storagemanager/LocalPool.h> #include <fsfw/storagemanager/LocalPool.h>
//#include <fsfw/returnvalues/HasReturnvaluesIF.h> #include <fsfw/returnvalues/HasReturnvaluesIF.h>
//#include <fsfw/container/ArrayList.h> #include <fsfw/container/ArrayList.h>
//
//#include <catch2/catch.hpp> #include <catch2/catch_test_macros.hpp>
//#include "../../core/CatchDefinitions.h" #include <unittest/core/CatchDefinitions.h>
//
//TEST_CASE( "PlacementFactory Tests", "[TestPlacementFactory]") { TEST_CASE( "PlacementFactory Tests", "[TestPlacementFactory]") {
// INFO("PlacementFactory Tests"); INFO("PlacementFactory Tests");
//
LocalPool::LocalPoolConfig poolCfg= {{1, sizeof(uint16_t)},
{1, sizeof(uint32_t)}, {1, sizeof(uint64_t)}
};
//const uint16_t element_sizes[3] = {sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t)}; //const uint16_t element_sizes[3] = {sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t)};
//const uint16_t n_elements[3] = {1, 1, 1}; //const uint16_t n_elements[3] = {1, 1, 1};
// LocalPool<3> storagePool(0x1, element_sizes, n_elements, false, true); LocalPool storagePool(0x1, poolCfg, false, true);
// PlacementFactory factory(&storagePool); PlacementFactory factory(&storagePool);
//
// SECTION("Pool overload"){ SECTION("Pool overload"){
// store_address_t address; store_address_t address;
// uint8_t* ptr = nullptr; uint8_t* ptr = nullptr;
// REQUIRE(storagePool.getFreeElement(&address, sizeof(ArrayList<uint32_t, uint16_t>), &ptr) REQUIRE(storagePool.getFreeElement(&address, sizeof(ArrayList<uint32_t, uint16_t>), &ptr)
// == static_cast<int>(StorageManagerIF::DATA_TOO_LARGE)); == static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
// ArrayList<uint32_t, uint16_t>* list2 = factory.generate<ArrayList<uint32_t, uint16_t> >(80); ArrayList<uint32_t, uint16_t>* list2 = factory.generate<ArrayList<uint32_t, uint16_t> >(80);
// REQUIRE(list2 == nullptr); REQUIRE(list2 == nullptr);
// } }
//
// SECTION("Test generate and destroy"){ SECTION("Test generate and destroy"){
// uint64_t* number = factory.generate<uint64_t>(32000); uint64_t* number = factory.generate<uint64_t>(32000);
// REQUIRE(number != nullptr); REQUIRE(number != nullptr);
// REQUIRE(*number == 32000); REQUIRE(*number == 32000);
// store_address_t address; store_address_t address;
// uint8_t* ptr = nullptr; uint8_t* ptr = nullptr;
// REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr) REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
// == static_cast<int>(StorageManagerIF::DATA_TOO_LARGE)); == static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
// uint64_t* number2 = factory.generate<uint64_t>(12345); uint64_t* number2 = factory.generate<uint64_t>(12345);
// REQUIRE(number2 == nullptr); REQUIRE(number2 == nullptr);
// REQUIRE(factory.destroy(number) == static_cast<int>(HasReturnvaluesIF::RETURN_OK)); REQUIRE(factory.destroy(number) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
// REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr) REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
// == static_cast<int>(HasReturnvaluesIF::RETURN_OK)); == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
// REQUIRE(storagePool.deleteData(address) == static_cast<int>(HasReturnvaluesIF::RETURN_OK)); REQUIRE(storagePool.deleteData(address) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
//
// //Check that PlacementFactory checks for nullptr //Check that PlacementFactory checks for nullptr
// ptr = nullptr; ptr = nullptr;
// REQUIRE(factory.destroy(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED)); REQUIRE(factory.destroy(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
// } }
//} }

View File

@ -0,0 +1,6 @@
target_sources(${TARGET_NAME} PRIVATE
LocalPoolVariableTest.cpp
LocalPoolVectorTest.cpp
DataSetTest.cpp
LocalPoolManagerTest.cpp
)

View File

@ -0,0 +1,23 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE("LocalDataSet" , "[LocDataSetTest]") {
LocalPoolOwnerBase* poolOwner = objectManager->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK);
const uint32_t setId = 0;
SECTION("BasicTest") {
StaticLocalDataSet<3> localSet = StaticLocalDataSet<3>(
sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE, setId));
}
}

View File

@ -0,0 +1,122 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/ipc/CommandMessageCleaner.h>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
LocalPoolOwnerBase* poolOwner = objectManager->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK);
REQUIRE(poolOwner->dataset.assignPointers() == retval::CATCH_OK);
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
REQUIRE(mqMock != nullptr);
CommandMessage messageSent;
uint8_t messagesSent = 0;
SECTION("BasicTest") {
// Subscribe for message generation on update.
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
// Subscribe for an update message.
poolOwner->dataset.setChanged(true);
// Now the update message should be generated.
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent() == true);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
// Should have been reset.
CHECK(poolOwner->dataset.hasChanged() == false);
// Set changed again, result should be the same.
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
// now subscribe for set update HK as well.
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
// first message sent should be the update notification, considering
// the internal list is a vector checked in insertion order.
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::HK_REPORT));
// clear message to avoid memory leak, our mock won't do it for us (yet)
CommandMessageCleaner::clearCommandMessage(&messageSent);
}
SECTION("AdvancedTests") {
// we need to reset the subscription list because the pool owner
// is a global object.
poolOwner->resetSubscriptionList();
// Subscribe for variable update as well
REQUIRE(not poolOwner->dataset.hasChanged());
REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) ==
retval::CATCH_OK);
lp_var_t<uint8_t>* poolVar = dynamic_cast<lp_var_t<uint8_t>*>(
poolOwner->getPoolObjectHandle(lpool::uint8VarId));
REQUIRE(poolVar != nullptr);
poolVar->setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
// Check update notification was sent.
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
// Should have been reset.
CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
// now subscribe for the dataset update (HK and update) again
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
// now two messages should be sent.
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
mqMock->clearMessages(true);
poolOwner->dataset.setChanged(true);
poolVar->setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
// now three messages should be sent.
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 3);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::HK_REPORT));
CommandMessageCleaner::clearCommandMessage(&messageSent);
REQUIRE(mqMock->receiveMessage(&messageSent) ==
static_cast<int>(MessageQueueIF::EMPTY));
}
}

View File

@ -0,0 +1,197 @@
#ifndef FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_
#define FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/datapoollocal/LocalDataSet.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/LocalPoolVector.h>
#include <fsfw/ipc/QueueFactory.h>
#include <testcfg/objects/systemObjectList.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/unittest/tests/mocks/MessageQueueMockBase.h>
namespace lpool {
static constexpr lp_id_t uint8VarId = 0;
static constexpr lp_id_t floatVarId = 1;
static constexpr lp_id_t uint32VarId = 2;
static constexpr lp_id_t uint16Vec3Id = 3;
static constexpr lp_id_t int64Vec2Id = 4;
static constexpr uint32_t testSetId = 0;
static constexpr uint8_t dataSetMaxVariables = 10;
static const sid_t testSid = sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE,
testSetId);
}
class LocalPoolTestDataSet: public LocalDataSet {
public:
LocalPoolTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId):
LocalDataSet(owner, setId, lpool::dataSetMaxVariables) {
}
ReturnValue_t assignPointers() {
PoolVariableIF** rawVarArray = getContainer();
localPoolVarUint8 = dynamic_cast<lp_var_t<uint8_t>*>(rawVarArray[0]);
localPoolVarFloat = dynamic_cast<lp_var_t<float>*>(rawVarArray[1]);
localPoolUint16Vec = dynamic_cast<lp_vec_t<uint16_t, 3>*>(
rawVarArray[2]);
if(localPoolVarUint8 == nullptr or localPoolVarFloat == nullptr or
localPoolUint16Vec == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
lp_var_t<uint8_t>* localPoolVarUint8 = nullptr;
lp_var_t<float>* localPoolVarFloat = nullptr;
lp_vec_t<uint16_t, 3>* localPoolUint16Vec = nullptr;
private:
};
class LocalPoolOwnerBase: public SystemObject, public HasLocalDataPoolIF {
public:
LocalPoolOwnerBase(
object_id_t objectId = objects::TEST_LOCAL_POOL_OWNER_BASE):
SystemObject(objectId), poolManager(this, messageQueue),
dataset(this, lpool::testSetId) {
messageQueue = new MessageQueueMockBase();
}
~LocalPoolOwnerBase() {
QueueFactory::instance()->deleteMessageQueue(messageQueue);
}
object_id_t getObjectId() const override {
return SystemObject::getObjectId();
}
ReturnValue_t initializeHkManager() {
if(not initialized) {
initialized = true;
return poolManager.initialize(messageQueue);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t initializeHkManagerAfterTaskCreation() {
if(not initializedAfterTaskCreation) {
initializedAfterTaskCreation = true;
return poolManager.initializeAfterTaskCreation();
}
return HasReturnvaluesIF::RETURN_OK;
}
/** Command queue for housekeeping messages. */
MessageQueueId_t getCommandQueue() const override {
return messageQueue->getId();
}
// This is called by initializeAfterTaskCreation of the HK manager.
virtual ReturnValue_t initializeLocalDataPool(
localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
// Default initialization empty for now.
localDataPoolMap.emplace(lpool::uint8VarId,
new PoolEntry<uint8_t>({0}));
localDataPoolMap.emplace(lpool::floatVarId,
new PoolEntry<float>({0}));
localDataPoolMap.emplace(lpool::uint32VarId,
new PoolEntry<uint32_t>({0}));
localDataPoolMap.emplace(lpool::uint16Vec3Id,
new PoolEntry<uint16_t>({0, 0, 0}));
localDataPoolMap.emplace(lpool::int64Vec2Id,
new PoolEntry<int64_t>({0, 0}));
return HasReturnvaluesIF::RETURN_OK;
}
LocalDataPoolManager* getHkManagerHandle() override {
return &poolManager;
}
uint32_t getPeriodicOperationFrequency() const override {
return 0;
}
/**
* This function is used by the pool manager to get a valid dataset
* from a SID
* @param sid Corresponding structure ID
* @return
*/
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override {
return &dataset;
}
virtual LocalPoolObjectBase* getPoolObjectHandle(
lp_id_t localPoolId) override {
if(localPoolId == lpool::uint8VarId) {
return &testUint8;
}
else if(localPoolId == lpool::uint16Vec3Id) {
return &testUint16Vec;
}
else if(localPoolId == lpool::floatVarId) {
return &testFloat;
}
else if(localPoolId == lpool::int64Vec2Id) {
return &testInt64Vec;
}
else if(localPoolId == lpool::uint32VarId) {
return &testUint32;
}
else {
return &testUint8;
}
}
MessageQueueMockBase* getMockQueueHandle() const {
return dynamic_cast<MessageQueueMockBase*>(messageQueue);
}
ReturnValue_t subscribeWrapperSetUpdate() {
return poolManager.subscribeForSetUpdateMessages(lpool::testSetId,
objects::NO_OBJECT, MessageQueueIF::NO_QUEUE, false);
}
ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) {
return poolManager.subscribeForUpdatePackets(lpool::testSid, diagnostics,
false, objects::HK_RECEIVER_MOCK);
}
ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) {
return poolManager.subscribeForVariableUpdateMessages(localPoolId,
MessageQueueIF::NO_QUEUE, objects::NO_OBJECT, false);
}
void resetSubscriptionList() {
poolManager.clearReceiversList();
}
LocalDataPoolManager poolManager;
LocalPoolTestDataSet dataset;
private:
lp_var_t<uint8_t> testUint8 = lp_var_t<uint8_t>(this, lpool::uint8VarId,
&dataset);
lp_var_t<float> testFloat = lp_var_t<float>(this, lpool::floatVarId,
&dataset);
lp_var_t<uint32_t> testUint32 = lp_var_t<uint32_t>(this, lpool::uint32VarId);
lp_vec_t<uint16_t, 3> testUint16Vec = lp_vec_t<uint16_t, 3>(this,
lpool::uint16Vec3Id, &dataset);
lp_vec_t<int64_t, 2> testInt64Vec = lp_vec_t<int64_t, 2>(this,
lpool::int64Vec2Id);
MessageQueueIF* messageQueue = nullptr;
bool initialized = false;
bool initializedAfterTaskCreation = false;
};
#endif /* FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ */

View File

@ -0,0 +1,123 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
LocalPoolOwnerBase* poolOwner = objectManager->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK);
SECTION("Basic Tests") {
// very basic test.
lp_var_t<uint8_t> testVariable = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
REQUIRE(testVariable.read() == retval::CATCH_OK);
CHECK(testVariable.value == 0);
testVariable.value = 5;
REQUIRE(testVariable.commit() == retval::CATCH_OK);
REQUIRE(testVariable.read() == retval::CATCH_OK);
REQUIRE(testVariable.value == 5);
CHECK(not testVariable.isValid());
testVariable.setValid(true);
CHECK(testVariable.isValid());
CHECK(testVariable.commit(true) == retval::CATCH_OK);
testVariable.setReadWriteMode(pool_rwm_t::VAR_READ);
CHECK(testVariable.getReadWriteMode() == pool_rwm_t::VAR_READ);
testVariable.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE);
testVariable.setDataPoolId(22);
CHECK(testVariable.getDataPoolId() == 22);
testVariable.setDataPoolId(lpool::uint8VarId);
testVariable.setChanged(true);
CHECK(testVariable.hasChanged());
testVariable.setChanged(false);
gp_id_t globPoolId(objects::TEST_LOCAL_POOL_OWNER_BASE,
lpool::uint8VarId);
lp_var_t<uint8_t> testVariable2 = lp_var_t<uint8_t>(globPoolId);
REQUIRE(testVariable2.read() == retval::CATCH_OK);
CHECK(testVariable2 == 5);
CHECK(testVariable == testVariable2);
testVariable = 10;
CHECK(testVariable != 5);
//CHECK(not testVariable != testVariable2);
uint8_t variableRaw = 0;
uint8_t* varPtr = &variableRaw;
size_t maxSize = testVariable.getSerializedSize();
CHECK(maxSize == 1);
size_t serSize = 0;
CHECK(testVariable.serialize(&varPtr, &serSize, maxSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(variableRaw == 10);
const uint8_t* varConstPtr = &variableRaw;
testVariable = 5;
CHECK(testVariable.deSerialize(&varConstPtr, &serSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(testVariable == 10);
CHECK(testVariable != testVariable2);
CHECK(testVariable2 < testVariable);
CHECK(testVariable2 < 10);
CHECK(testVariable > 5);
CHECK(testVariable > testVariable2);
variableRaw = static_cast<uint8_t>(testVariable2);
CHECK(variableRaw == 5);
CHECK(testVariable == 10);
testVariable = testVariable2;
CHECK(testVariable == 5);
}
SECTION("ErrorHandling") {
// not try to use a local pool variable which does not exist
lp_var_t<uint8_t> invalidVariable = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
REQUIRE(invalidVariable.read() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
REQUIRE(invalidVariable.commit() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
// now try to access with wrong type
lp_var_t<int8_t> invalidVariable2 = lp_var_t<int8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
REQUIRE(invalidVariable2.read() ==
static_cast<int>(localpool::POOL_ENTRY_TYPE_CONFLICT));
lp_var_t<uint8_t> readOnlyVar = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId,
nullptr, pool_rwm_t::VAR_READ);
REQUIRE(readOnlyVar.commit() ==
static_cast<int>(PoolVariableIF::INVALID_READ_WRITE_MODE));
lp_var_t<uint8_t> writeOnlyVar = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId,
nullptr, pool_rwm_t::VAR_WRITE);
REQUIRE(writeOnlyVar.read() == static_cast<int>(
PoolVariableIF::INVALID_READ_WRITE_MODE));
lp_var_t<uint32_t> uint32tVar = lp_var_t<uint32_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint32VarId);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "LocalPoolVariable printout: " <<uint32tVar << std::endl;
#endif
// for code coverage. If program does not crash -> OK
lp_var_t<uint8_t> invalidObjectVar = lp_var_t<uint8_t>(
0xffffffff, lpool::uint8VarId);
gp_id_t globPoolId(0xffffffff,
lpool::uint8VarId);
lp_var_t<uint8_t> invalidObjectVar2 = lp_var_t<uint8_t>(globPoolId);
lp_var_t<uint8_t> invalidObjectVar3 = lp_var_t<uint8_t>(nullptr,
lpool::uint8VarId);
}
}

View File

@ -0,0 +1,120 @@
#include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <unittest/core/CatchDefinitions.h>
TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
LocalPoolOwnerBase* poolOwner = objectManager->
get<LocalPoolOwnerBase>(objects::TEST_LOCAL_POOL_OWNER_BASE);
REQUIRE(poolOwner != nullptr);
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK);
SECTION("BasicTest") {
// very basic test.
lp_vec_t<uint16_t, 3> testVector = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
REQUIRE(testVector.read() == retval::CATCH_OK);
testVector.value[0] = 5;
testVector.value[1] = 232;
testVector.value[2] = 32023;
REQUIRE(testVector.commit(true) == retval::CATCH_OK);
CHECK(testVector.isValid());
testVector.value[0] = 0;
testVector.value[1] = 0;
testVector.value[2] = 0;
CHECK(testVector.read() == retval::CATCH_OK);
CHECK(testVector.value[0] == 5);
CHECK(testVector.value[1] == 232);
CHECK(testVector.value[2] == 32023);
CHECK(testVector[0] == 5);
// This is invalid access, so the last value will be set instead.
// (we can't throw exceptions)
testVector[4] = 12;
CHECK(testVector[2] == 12);
CHECK(testVector.commit() == retval::CATCH_OK);
// Use read-only reference.
const lp_vec_t<uint16_t, 3>& roTestVec = testVector;
uint16_t valueOne = roTestVec[0];
CHECK(valueOne == 5);
uint16_t lastVal = roTestVec[25];
CHECK(lastVal == 12);
size_t maxSize = testVector.getSerializedSize();
CHECK(maxSize == 6);
uint16_t serializedVector[3];
uint8_t* vecPtr = reinterpret_cast<uint8_t*>(serializedVector);
size_t serSize = 0;
REQUIRE(testVector.serialize(&vecPtr, &serSize,
maxSize, SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(serSize == 6);
CHECK(serializedVector[0] == 5);
CHECK(serializedVector[1] == 232);
CHECK(serializedVector[2] == 12);
maxSize = 1;
REQUIRE(testVector.serialize(&vecPtr, &serSize,
maxSize, SerializeIF::Endianness::MACHINE) ==
static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
serializedVector[0] = 16;
serializedVector[1] = 7832;
serializedVector[2] = 39232;
const uint8_t* constVecPtr = reinterpret_cast<const uint8_t*>(
serializedVector);
REQUIRE(testVector.deSerialize(&constVecPtr, &serSize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
CHECK(testVector[0] == 16);
CHECK(testVector[1] == 7832);
CHECK(testVector[2] == 39232);
serSize = 1;
REQUIRE(testVector.deSerialize(&constVecPtr, &serSize,
SerializeIF::Endianness::MACHINE) ==
static_cast<int>(SerializeIF::STREAM_TOO_SHORT));
}
SECTION("ErrorHandling") {
// not try to use a local pool variable which does not exist
lp_vec_t<uint16_t, 3> invalidVector = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
REQUIRE(invalidVector.read() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
REQUIRE(invalidVector.commit() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
// now try to access with wrong type
lp_vec_t<uint32_t, 3> invalidVector2 = lp_vec_t<uint32_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
REQUIRE(invalidVector2.read() ==
static_cast<int>(localpool::POOL_ENTRY_TYPE_CONFLICT));
REQUIRE(invalidVector2.commit() ==
static_cast<int>(localpool::POOL_ENTRY_TYPE_CONFLICT));
lp_vec_t<uint16_t, 3> writeOnlyVec = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id,
nullptr, pool_rwm_t::VAR_WRITE);
REQUIRE(writeOnlyVec.read() ==
static_cast<int>(PoolVariableIF::INVALID_READ_WRITE_MODE));
lp_vec_t<uint16_t, 3> readOnlyVec = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id,
nullptr, pool_rwm_t::VAR_READ);
REQUIRE(readOnlyVec.commit() ==
static_cast<int>(PoolVariableIF::INVALID_READ_WRITE_MODE));
}
}

View File

@ -0,0 +1,20 @@
#ifndef FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_
#define FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_
#include <fsfw/housekeeping/AcceptsHkPacketsIF.h>
#include <fsfw/objectmanager/SystemObject.h>
class HkReceiverMock: public SystemObject, public AcceptsHkPacketsIF {
public:
HkReceiverMock(object_id_t objectId): SystemObject(objectId) {
}
MessageQueueId_t getHkQueue() const {
return MessageQueueIF::NO_QUEUE;
}
};
#endif /* FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ */

View File

@ -0,0 +1,121 @@
#ifndef FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_
#define FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/MessageQueueMessage.h>
#include <unittest/core/CatchDefinitions.h>
#include <cstring>
#include <queue>
class MessageQueueMockBase: public MessageQueueIF {
public:
MessageQueueId_t myQueueId = tconst::testQueueId;
uint8_t messageSentCounter = 0;
bool defaultDestSet = false;
bool messageSent = false;
bool wasMessageSent(uint8_t* messageSentCounter = nullptr,
bool resetCounter = true) {
bool tempMessageSent = messageSent;
messageSent = false;
if(messageSentCounter != nullptr) {
*messageSentCounter = this->messageSentCounter;
}
if(resetCounter) {
this->messageSentCounter = 0;
}
return tempMessageSent;
}
virtual ReturnValue_t reply( MessageQueueMessageIF* message ) {
//messageSent = true;
//lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
return sendMessage(myQueueId, message);
return HasReturnvaluesIF::RETURN_OK;
};
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom) {
return receiveMessage(message);
}
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) {
if(messagesSentQueue.empty()) {
return MessageQueueIF::EMPTY;
}
std::memcpy(message->getBuffer(), messagesSentQueue.front().getBuffer(),
message->getMessageSize());
messagesSentQueue.pop();
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
virtual MessageQueueId_t getLastPartner() const {
return myQueueId;
}
virtual MessageQueueId_t getId() const {
return myQueueId;
}
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false ) {
//messageSent = true;
//lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
//return HasReturnvaluesIF::RETURN_OK;
return sendMessage(sendTo, message);
}
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false ) {
//messageSent = true;
//lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
//return HasReturnvaluesIF::RETURN_OK;
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) {
//messageSent = true;
//lastMessage = *(dynamic_cast<MessageQueueMessage*>(message));
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault = false ) override {
messageSent = true;
messageSentCounter++;
MessageQueueMessage& messageRef = *(
dynamic_cast<MessageQueueMessage*>(message));
messagesSentQueue.push(messageRef);
return HasReturnvaluesIF::RETURN_OK;
}
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) {
myQueueId = defaultDestination;
defaultDestSet = true;
}
virtual MessageQueueId_t getDefaultDestination() const {
return myQueueId;
}
virtual bool isDefaultDestinationSet() const {
return defaultDestSet;
}
void clearMessages(bool clearCommandMessages = true) {
while(not messagesSentQueue.empty()) {
if(clearCommandMessages) {
CommandMessage message;
std::memcpy(message.getBuffer(),
messagesSentQueue.front().getBuffer(),
message.getMessageSize());
message.clear();
}
messagesSentQueue.pop();
}
}
private:
std::queue<MessageQueueMessage> messagesSentQueue;
//MessageQueueMessage lastMessage;
};
#endif /* FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ */

View File

@ -1,161 +1,161 @@
//#include <fsfw/storagemanager/LocalPool.h> #include <fsfw/storagemanager/LocalPool.h>
//#include <catch2/catch.hpp> #include <catch2/catch_test_macros.hpp>
//#include "../../core/CatchDefinitions.h" #include <unittest/core/CatchDefinitions.h>
//#include <array> #include <array>
// #include <cstring>
//TEST_CASE( "New Accessor" , "[NewAccessor]") {
// uint16_t numberOfElements[1] = {1}; TEST_CASE( "New Accessor" , "[NewAccessor]") {
// uint16_t sizeofElements[1] = {10}; LocalPool::LocalPoolConfig poolCfg = {{1, 10}};
// LocalPool<1> SimplePool = LocalPool<1>(0, sizeofElements, numberOfElements); LocalPool SimplePool = LocalPool(0, poolCfg);
// std::array<uint8_t, 20> testDataArray; std::array<uint8_t, 20> testDataArray;
// std::array<uint8_t, 20> receptionArray; std::array<uint8_t, 20> receptionArray;
// store_address_t testStoreId; store_address_t testStoreId;
// ReturnValue_t result = retval::CATCH_FAILED; ReturnValue_t result = retval::CATCH_FAILED;
//
// for(size_t i = 0; i < testDataArray.size(); i++) { for(size_t i = 0; i < testDataArray.size(); i++) {
// testDataArray[i] = i; testDataArray[i] = i;
// } }
// size_t size = 10; size_t size = 10;
//
// SECTION ("Simple tests getter functions") { SECTION ("Simple tests getter functions") {
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// auto resultPair = SimplePool.getData(testStoreId); auto resultPair = SimplePool.getData(testStoreId);
// REQUIRE(resultPair.first == retval::CATCH_OK); REQUIRE(resultPair.first == retval::CATCH_OK);
// resultPair.second.getDataCopy(receptionArray.data(), 20); resultPair.second.getDataCopy(receptionArray.data(), 20);
// CHECK(resultPair.second.getId() == testStoreId); CHECK(resultPair.second.getId() == testStoreId);
// CHECK(resultPair.second.size() == 10); CHECK(resultPair.second.size() == 10);
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
//
// std::copy(resultPair.second.data(), resultPair.second.data() + std::copy(resultPair.second.data(), resultPair.second.data() +
// resultPair.second.size(), receptionArray.data()); resultPair.second.size(), receptionArray.data());
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
//
// { {
// auto resultPairLoc = SimplePool.getData(testStoreId); auto resultPairLoc = SimplePool.getData(testStoreId);
// REQUIRE(resultPairLoc.first == retval::CATCH_OK); REQUIRE(resultPairLoc.first == retval::CATCH_OK);
// // data should be deleted when accessor goes out of scope. // data should be deleted when accessor goes out of scope.
// } }
// resultPair = SimplePool.getData(testStoreId); resultPair = SimplePool.getData(testStoreId);
// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
//
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// { {
// ConstStorageAccessor constAccessor(testStoreId); ConstStorageAccessor constAccessor(testStoreId);
// result = SimplePool.getData(testStoreId, constAccessor); result = SimplePool.getData(testStoreId, constAccessor);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// constAccessor.getDataCopy(receptionArray.data(), 20); constAccessor.getDataCopy(receptionArray.data(), 20);
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
// // likewise, data should be deleted when accessor gets out of scope. // likewise, data should be deleted when accessor gets out of scope.
// } }
// resultPair = SimplePool.getData(testStoreId); resultPair = SimplePool.getData(testStoreId);
// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
//
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
// { {
// resultPair = SimplePool.getData(testStoreId); resultPair = SimplePool.getData(testStoreId);
// REQUIRE(resultPair.first == retval::CATCH_OK); REQUIRE(resultPair.first == retval::CATCH_OK);
// resultPair.second.release(); resultPair.second.release();
// // now data should not be deleted anymore // now data should not be deleted anymore
// } }
// resultPair = SimplePool.getData(testStoreId); resultPair = SimplePool.getData(testStoreId);
// REQUIRE(resultPair.first == retval::CATCH_OK); REQUIRE(resultPair.first == retval::CATCH_OK);
// resultPair.second.getDataCopy(receptionArray.data(), 20); resultPair.second.getDataCopy(receptionArray.data(), 20);
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
// } }
//
//
// SECTION("Simple tests modify functions") { SECTION("Simple tests modify functions") {
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// { {
// StorageAccessor accessor(testStoreId); StorageAccessor accessor(testStoreId);
// result = SimplePool.modifyData(testStoreId, accessor); result = SimplePool.modifyData(testStoreId, accessor);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// CHECK(accessor.getId() == testStoreId); CHECK(accessor.getId() == testStoreId);
// CHECK(accessor.size() == 10); CHECK(accessor.size() == 10);
// accessor.getDataCopy(receptionArray.data(), 20); accessor.getDataCopy(receptionArray.data(), 20);
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
// std::copy(accessor.data(), accessor.data() + std::copy(accessor.data(), accessor.data() +
// accessor.size(), receptionArray.data()); accessor.size(), receptionArray.data());
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
// // data should be deleted when accessor goes out of scope // data should be deleted when accessor goes out of scope
// } }
// auto resultPair = SimplePool.getData(testStoreId); auto resultPair = SimplePool.getData(testStoreId);
// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
//
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// { {
// auto resultPairLoc = SimplePool.modifyData(testStoreId); auto resultPairLoc = SimplePool.modifyData(testStoreId);
// REQUIRE(resultPairLoc.first == retval::CATCH_OK); REQUIRE(resultPairLoc.first == retval::CATCH_OK);
// CHECK(resultPairLoc.second.getId() == testStoreId); CHECK(resultPairLoc.second.getId() == testStoreId);
// CHECK(resultPairLoc.second.size() == 10); CHECK(resultPairLoc.second.size() == 10);
// resultPairLoc.second.getDataCopy(receptionArray.data(), 20); resultPairLoc.second.getDataCopy(receptionArray.data(), 20);
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
// std::copy(resultPairLoc.second.data(), resultPairLoc.second.data() + std::copy(resultPairLoc.second.data(), resultPairLoc.second.data() +
// resultPairLoc.second.size(), receptionArray.data()); resultPairLoc.second.size(), receptionArray.data());
// for(size_t i = 0; i < size; i++) { for(size_t i = 0; i < size; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
// resultPairLoc.second.release(); resultPairLoc.second.release();
// // data should not be deleted when accessor goes out of scope // data should not be deleted when accessor goes out of scope
// } }
// resultPair = SimplePool.getData(testStoreId); resultPair = SimplePool.getData(testStoreId);
// REQUIRE(resultPair.first == retval::CATCH_OK); REQUIRE(resultPair.first == retval::CATCH_OK);
// } }
//
//
// SECTION("Write tests") { SECTION("Write tests") {
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// { {
// auto resultPair = SimplePool.modifyData(testStoreId); auto resultPair = SimplePool.modifyData(testStoreId);
// REQUIRE(resultPair.first == retval::CATCH_OK); REQUIRE(resultPair.first == retval::CATCH_OK);
// testDataArray[9] = 42; testDataArray[9] = 42;
// resultPair.second.write(testDataArray.data(), 10, 0); resultPair.second.write(testDataArray.data(), 10, 0);
// // now data should not be deleted // now data should not be deleted
// resultPair.second.release(); resultPair.second.release();
// } }
// auto resultConstPair = SimplePool.getData(testStoreId); auto resultConstPair = SimplePool.getData(testStoreId);
// REQUIRE(resultConstPair.first == retval::CATCH_OK); REQUIRE(resultConstPair.first == retval::CATCH_OK);
//
// resultConstPair.second.getDataCopy(receptionArray.data(), 10); resultConstPair.second.getDataCopy(receptionArray.data(), 10);
// for(size_t i = 0; i < size-1; i++) { for(size_t i = 0; i < size-1; i++) {
// CHECK(receptionArray[i] == i ); CHECK(receptionArray[i] == i );
// } }
// CHECK(receptionArray[9] == 42 ); CHECK(receptionArray[9] == 42 );
//
// auto resultPair = SimplePool.modifyData(testStoreId); auto resultPair = SimplePool.modifyData(testStoreId);
// REQUIRE(resultPair.first == retval::CATCH_OK); REQUIRE(resultPair.first == retval::CATCH_OK);
// result = resultPair.second.write(testDataArray.data(), 20, 0); result = resultPair.second.write(testDataArray.data(), 20, 0);
// REQUIRE(result == retval::CATCH_FAILED); REQUIRE(result == retval::CATCH_FAILED);
// result = resultPair.second.write(testDataArray.data(), 10, 5); result = resultPair.second.write(testDataArray.data(), 10, 5);
// REQUIRE(result == retval::CATCH_FAILED); REQUIRE(result == retval::CATCH_FAILED);
//
// memset(testDataArray.data(), 42, 5); std::memset(testDataArray.data(), 42, 5);
// result = resultPair.second.write(testDataArray.data(), 5, 5); result = resultPair.second.write(testDataArray.data(), 5, 5);
// REQUIRE(result == retval::CATCH_OK); REQUIRE(result == retval::CATCH_OK);
// resultConstPair = SimplePool.getData(testStoreId); resultConstPair = SimplePool.getData(testStoreId);
// resultPair.second.getDataCopy(receptionArray.data(), 20); resultPair.second.getDataCopy(receptionArray.data(), 20);
// for(size_t i = 5; i < 10; i++) { for(size_t i = 5; i < 10; i++) {
// CHECK(receptionArray[i] == 42 ); CHECK(receptionArray[i] == 42 );
// } }
//
// } }
//} }

View File

@ -8,8 +8,6 @@
TEST_CASE( "Local Pool Simple Tests [1 Pool]" , "[TestPool]") { TEST_CASE( "Local Pool Simple Tests [1 Pool]" , "[TestPool]") {
// uint16_t numberOfElements[1] = {1};
// uint16_t sizeofElements[1] = {10};
LocalPool::LocalPoolConfig config = {{1, 10}}; LocalPool::LocalPoolConfig config = {{1, 10}};
LocalPool simplePool(0, config); LocalPool simplePool(0, config);
std::array<uint8_t, 20> testDataArray; std::array<uint8_t, 20> testDataArray;

View File

@ -13,7 +13,19 @@ cmake_minimum_required(VERSION 3.13)
# set(CMAKE_VERBOSE TRUE) # set(CMAKE_VERBOSE TRUE)
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/buildsystem/cmake") set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
option(TMTC_TEST "Build binary for manual or automatic TMTC tests" FALSE)
option(GENERATE_COVERAGE
"Specify whether coverage data is generated with GCOV"
TRUE
)
if(TMTC_TEST)
set(LINK_CATCH2 FALSE)
else()
set(LINK_CATCH2 TRUE)
endif()
# Tests can be built with the Host OSAL or with the Linux OSAL. # Tests can be built with the Host OSAL or with the Linux OSAL.
if(NOT OS_FSFW) if(NOT OS_FSFW)
@ -53,6 +65,7 @@ set(FSFW_PATH fsfw)
set(CATCH2_PATH Catch2) set(CATCH2_PATH Catch2)
set(FSFW_TESTS_PATH fsfw/unittest) set(FSFW_TESTS_PATH fsfw/unittest)
set(TEST_SETUP_PATH unittest) set(TEST_SETUP_PATH unittest)
set(TMTC_TEST_PATH tests)
# Analyse different OS and architecture/target options and # Analyse different OS and architecture/target options and
# determine BSP_PATH # determine BSP_PATH
@ -71,6 +84,15 @@ else()
endif() endif()
endif() endif()
if(GENERATE_COVERAGE)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/cmake-modules)
if(CMAKE_COMPILER_IS_GNUCXX)
include(CodeCoverage)
# Add compile options on target base, we don't want coverage for Catch2
# append_coverage_compiler_flags()
endif()
endif()
set(FSFW_CONFIG_PATH testcfg) set(FSFW_CONFIG_PATH testcfg)
################################################################################ ################################################################################
@ -82,10 +104,16 @@ add_executable(${TARGET_NAME})
# Add subdirectories # Add subdirectories
add_subdirectory(${FSFW_PATH}) add_subdirectory(${FSFW_PATH})
add_subdirectory(${CATCH2_PATH})
add_subdirectory(${FSFW_CONFIG_PATH}) add_subdirectory(${FSFW_CONFIG_PATH})
if(LINK_CATCH2)
add_subdirectory(${CATCH2_PATH})
add_subdirectory(${FSFW_TESTS_PATH}) add_subdirectory(${FSFW_TESTS_PATH})
add_subdirectory(${TEST_SETUP_PATH}) add_subdirectory(${TEST_SETUP_PATH})
else()
add_subdirectory(${TMTC_TEST_PATH})
endif()
################################################################################ ################################################################################
# Post-Sources preparation # Post-Sources preparation
@ -94,8 +122,73 @@ add_subdirectory(${TEST_SETUP_PATH})
# Add libraries for all sources. # Add libraries for all sources.
target_link_libraries(${TARGET_NAME} PRIVATE target_link_libraries(${TARGET_NAME} PRIVATE
${LIB_FSFW_NAME} ${LIB_FSFW_NAME}
)
if(LINK_CATCH2)
target_link_libraries(${TARGET_NAME} PRIVATE
${CATCH2_TARGET} ${CATCH2_TARGET}
) )
endif()
if(GENERATE_COVERAGE)
if(CMAKE_COMPILER_IS_GNUCXX)
set(CODE_COVERAGE_VERBOSE TRUE)
include(CodeCoverage)
# Remove quotes.
separate_arguments(COVERAGE_COMPILER_FLAGS
NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}"
)
# Add compile options manually, we don't want coverage for Catch2
target_compile_options(${TARGET_NAME} PRIVATE
"${COVERAGE_COMPILER_FLAGS}"
)
target_compile_options(${LIB_FSFW_NAME} PRIVATE
"${COVERAGE_COMPILER_FLAGS}"
)
# Exclude internal unittest from coverage for now.
if(WIN32)
set(GCOVR_ADDITIONAL_ARGS
"--exclude-throw-branches"
"--exclude-unreachable-branches"
)
set(COVERAGE_EXCLUDES
"/c/msys64/mingw64/*" "Catch2"
"${CMAKE_CURRENT_SOURCE_DIR}/fsfw/unittest/internal"
)
elseif(UNIX)
set(COVERAGE_EXCLUDES
"/usr/include/*" "/usr/bin/*" "Catch2/*"
"fsfw/unittest/internal/*"
)
endif()
target_link_options(${TARGET_NAME} PRIVATE
-fprofile-arcs
-ftest-coverage
)
target_link_options(${LIB_FSFW_NAME} PRIVATE
-fprofile-arcs
-ftest-coverage
)
if(WIN32)
setup_target_for_coverage_gcovr_html(
NAME ${TARGET_NAME}_coverage
EXECUTABLE ${TARGET_NAME}
DEPENDENCIES ${TARGET_NAME}
)
else()
setup_target_for_coverage_lcov(
NAME ${TARGET_NAME}_coverage
EXECUTABLE ${TARGET_NAME}
DEPENDENCIES ${TARGET_NAME}
)
endif()
endif()
endif()
# Add include paths for all sources. # Add include paths for all sources.
target_include_directories(${TARGET_NAME} PRIVATE target_include_directories(${TARGET_NAME} PRIVATE
@ -147,8 +240,7 @@ if(NOT CMAKE_SIZE)
endif() endif()
endif() endif()
add_custom_command( add_custom_command(TARGET ${TARGET_NAME}
TARGET ${TARGET_NAME}
POST_BUILD POST_BUILD
COMMAND echo "Build directory: ${CMAKE_BINARY_DIR}" COMMAND echo "Build directory: ${CMAKE_BINARY_DIR}"
COMMAND echo "Target OSAL: ${OS_FSFW}" COMMAND echo "Target OSAL: ${OS_FSFW}"
@ -156,7 +248,7 @@ add_custom_command(
COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX} COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX}
) )
include (${CMAKE_CURRENT_SOURCE_DIR}/buildsystem/cmake/BuildType.cmake) include (${CMAKE_SCRIPT_PATH}/BuildType.cmake)
set_build_type() set_build_type()

View File

@ -4,16 +4,21 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
//! Used to determine whether C++ ostreams are used //! Used to determine whether C++ ostreams are used which can increase
//! Those can lead to code bloat. //! the binary size significantly. If this is disabled,
//! the C stdio functions can be used alternatively
#define FSFW_CPP_OSTREAM_ENABLED 1 #define FSFW_CPP_OSTREAM_ENABLED 1
//! Reduced printout to further decrease code size //! More FSFW related printouts depending on level. Useful for development.
//! Be careful, this also turns off most diagnostic prinouts! #define FSFW_VERBOSE_LEVEL 1
#define FSFW_ENHANCED_PRINTOUT 0
//! Can be used to enable additional debugging printouts for developing the FSFW //! Can be used to completely disable printouts, even the C stdio ones.
#define FSFW_PRINT_VERBOSITY_LEVEL 0 #if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0
#define FSFW_DISABLE_PRINTOUT 0
#endif
//! Can be used to disable the ANSI color sequences for C stdio.
#define FSFW_COLORED_OUTPUT 1
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one, //! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
//! additional output which requires the translation files translateObjects //! additional output which requires the translation files translateObjects
@ -49,7 +54,9 @@ static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
//! also determines how many commands a CSB service can handle in one cycle //! also determines how many commands a CSB service can handle in one cycle
//! simulataneously. This will increase the required RAM for //! simulataneously. This will increase the required RAM for
//! each CSB service ! //! each CSB service !
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 3; static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
} }
#endif /* CONFIG_FSFWCONFIG_H_ */ #endif /* CONFIG_FSFWCONFIG_H_ */

View File

@ -9,7 +9,20 @@ namespace objects {
enum sourceObjects: uint32_t { enum sourceObjects: uint32_t {
/* All addresses between start and end are reserved for the FSFW */ /* All addresses between start and end are reserved for the FSFW */
FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION, FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION,
FSFW_CONFIG_RESERVED_END = TM_STORE FSFW_CONFIG_RESERVED_END = TM_STORE,
CCSDS_DISTRIBUTOR = 10,
PUS_DISTRIBUTOR = 11,
TM_FUNNEL = 12,
UDP_BRIDGE = 15,
UDP_POLLING_TASK = 16,
TEST_ECHO_COM_IF = 20,
TEST_DEVICE = 21,
HK_RECEIVER_MOCK = 22,
TEST_LOCAL_POOL_OWNER_BASE = 25
}; };
} }

View File

@ -0,0 +1 @@
add_subdirectory(core)

View File

@ -5,3 +5,9 @@ target_sources(${TARGET_NAME} PRIVATE
CatchSetup.cpp CatchSetup.cpp
printChar.cpp printChar.cpp
) )
if(CUSTOM_UNITTEST_RUNNER)
target_sources(${TARGET_NAME} PRIVATE
CatchRunner.cpp
)
endif()

View File

@ -1,4 +1,5 @@
#include "CatchDefinitions.h" #include "CatchDefinitions.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/objectmanager/ObjectManagerIF.h> #include <fsfw/objectmanager/ObjectManagerIF.h>
StorageManagerIF* tglob::getIpcStoreHandle() { StorageManagerIF* tglob::getIpcStoreHandle() {
@ -7,7 +8,9 @@ StorageManagerIF* tglob::getIpcStoreHandle() {
} else { } else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Global object manager uninitialized" << std::endl; sif::error << "Global object manager uninitialized" << std::endl;
#endif #else
sif::printError("Global object manager uninitialized\n\r");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return nullptr; return nullptr;
} }
} }

View File

@ -1,11 +1,17 @@
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include "CatchFactory.h" #include "CatchFactory.h"
#include <fsfw/events/EventManager.h> #include <fsfw/events/EventManager.h>
#include <fsfw/health/HealthTable.h> #include <fsfw/health/HealthTable.h>
#include <fsfw/internalError/InternalErrorReporter.h> #include <fsfw/internalError/InternalErrorReporter.h>
#include <fsfw/objectmanager/frameworkObjects.h> #include <fsfw/objectmanager/frameworkObjects.h>
#include <fsfw/storagemanager/PoolManager.h> #include <fsfw/storagemanager/PoolManager.h>
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <fsfw/unittest/tests/datapoollocal/LocalPoolOwnerBase.h>
#include <fsfw/unittest/tests/mocks/HkReceiverMock.h>
/** /**
* @brief Produces system objects. * @brief Produces system objects.
@ -26,6 +32,9 @@ void Factory::produce(void) {
new HealthTable(objects::HEALTH_TABLE); new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new LocalPoolOwnerBase (objects::TEST_LOCAL_POOL_OWNER_BASE);
new HkReceiverMock(objects::HK_RECEIVER_MOCK);
{ {
PoolManager::LocalPoolConfig poolCfg = { PoolManager::LocalPoolConfig poolCfg = {
{100, 16}, {50, 32}, {25, 64} , {15, 128}, {5, 1024} {100, 16}, {50, 32}, {25, 64} , {15, 128}, {5, 1024}
@ -50,7 +59,23 @@ void Factory::produce(void) {
} }
void Factory::setStaticFrameworkObjectIds() { void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::packetSource = objects::NO_OBJECT;
PusServiceBase::packetDestination = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS;
LocalDataPoolManager::defaultHkDestination = objects::HK_RECEIVER_MOCK;
DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
TmPacketStored::timeStamperId = objects::NO_OBJECT;
} }

View File

@ -1,17 +1,16 @@
/** /**
* @file CatchSource.cpp * @file CatchRunner.cpp
* @brief Source file to compile catch framework. * @brief Source file to compile catch framework.
* @details All tests should be written in other files. * @details All tests should be written in other files.
* For eclipse console output, install ANSI Escape in Console * For eclipse console output, install ANSI Escape in Console
* from the eclipse market place to get colored characters. * from the eclipse market place to get colored characters.
*/ */
#ifndef NO_UNIT_TEST_FRAMEWORK #include <TestsConfig.h>
#define CATCH_CONFIG_RUNNER #define CATCH_CONFIG_COLOUR_WINDOWS
#include <catch2/catch.hpp>
#if CUSTOM_UNITTEST_RUNNER == 0 #include <catch2/catch_session.hpp>
extern int customSetup(); extern int customSetup();
@ -25,7 +24,3 @@ int main( int argc, char* argv[] ) {
return result; return result;
} }
#endif
#endif

View File

@ -1,21 +1,20 @@
#include <fsfw/unittest/core/CatchFactory.h> #include "CatchFactory.h"
#include "CatchDefinitions.h" #include "CatchDefinitions.h"
#include <testcfg/cdatapool/dataPoolInit.h>
#ifdef GCOV #ifdef GCOV
#include <gcov.h> #include <gcov.h>
#endif #endif
#include "../../objectmanager/ObjectManager.h" #include <fsfw/objectmanager/ObjectManager.h>
#include "../../objectmanager/ObjectManagerIF.h" #include <fsfw/objectmanager/ObjectManagerIF.h>
#include "../../storagemanager/StorageManagerIF.h" #include <fsfw/storagemanager/StorageManagerIF.h>
#include "../../serviceinterface/ServiceInterfaceStream.h" #include <fsfw/serviceinterface/ServiceInterfaceStream.h>
/* Global instantiations normally done in main.cpp */ /* Global instantiations normally done in main.cpp */
/* Initialize Data Pool */ /* Initialize Data Pool */
#if FSFW_CPP_OSTREAM_ENABLED == 1
namespace sif { namespace sif {
/* Set up output streams */ /* Set up output streams */
ServiceInterfaceStream debug("DEBUG"); ServiceInterfaceStream debug("DEBUG");
@ -23,6 +22,7 @@ ServiceInterfaceStream info("INFO");
ServiceInterfaceStream error("ERROR"); ServiceInterfaceStream error("ERROR");
ServiceInterfaceStream warning("WARNING"); ServiceInterfaceStream warning("WARNING");
} }
#endif
/* Global object manager */ /* Global object manager */
ObjectManagerIF *objectManager; ObjectManagerIF *objectManager;

View File

@ -1,4 +1,4 @@
#include <fsfw/unittest/core/printChar.h> #include "printChar.h"
#include <cstdio> #include <cstdio>
void printChar(const char* character, bool errStream) { void printChar(const char* character, bool errStream) {