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:
commit
543e0d4649
@ -107,14 +107,16 @@ else()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(WARNING_FLAGS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wshadow=local
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
)
|
||||
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
||||
set(FSFW_WARNING_FLAGS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wshadow=local
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
@ -135,8 +137,7 @@ target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||
)
|
||||
|
||||
# Machine specific options can be set with the ABI_FLAGS variable.
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
${WARNING_FLAGS}
|
||||
${FSFW_WARNING_FLAGS}
|
||||
${COMPILER_FLAGS}
|
||||
)
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "ArrayList.h"
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
/**
|
||||
* @brief An associative container which allows multiple entries of the same key.
|
||||
|
@ -4,7 +4,7 @@
|
||||
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
|
||||
object_id_t parentId, size_t commandQueueDepth):
|
||||
ControllerBase(objectId, parentId, commandQueueDepth),
|
||||
localPoolManager(this, commandQueue),
|
||||
poolManager(this, commandQueue),
|
||||
actionHelper(this, commandQueue) {
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
|
||||
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::initializeLocalDataPool(
|
||||
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
// needs to be overriden and implemented by child class.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@ -26,10 +26,6 @@ object_id_t ExtendedControllerBase::getObjectId() const {
|
||||
return SystemObject::getObjectId();
|
||||
}
|
||||
|
||||
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
|
||||
return &localPoolManager;
|
||||
}
|
||||
|
||||
uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const {
|
||||
return this->executingTask->getPeriodMs();
|
||||
}
|
||||
@ -40,7 +36,7 @@ ReturnValue_t ExtendedControllerBase::handleCommandMessage(
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return localPoolManager.handleHousekeepingMessage(message);
|
||||
return poolManager.handleHousekeepingMessage(message);
|
||||
}
|
||||
|
||||
void ExtendedControllerBase::handleQueue() {
|
||||
@ -64,7 +60,7 @@ void ExtendedControllerBase::handleQueue() {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = localPoolManager.handleHousekeepingMessage(&command);
|
||||
result = poolManager.handleHousekeepingMessage(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
@ -88,16 +84,16 @@ ReturnValue_t ExtendedControllerBase::initialize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
return localPoolManager.initialize(commandQueue);
|
||||
return poolManager.initialize(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
|
||||
return localPoolManager.initializeAfterTaskCreation();
|
||||
return poolManager.initializeAfterTaskCreation();
|
||||
}
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
localPoolManager.performHkOperation();
|
||||
poolManager.performHkOperation();
|
||||
performControlOperation();
|
||||
return RETURN_OK;
|
||||
}
|
||||
@ -113,3 +109,7 @@ LocalPoolDataSetBase* ExtendedControllerBase::getDataSetHandle(sid_t sid) {
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
|
||||
return &poolManager;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
protected:
|
||||
LocalDataPoolManager localPoolManager;
|
||||
LocalDataPoolManager poolManager;
|
||||
ActionHelper actionHelper;
|
||||
|
||||
/**
|
||||
@ -58,11 +58,11 @@ protected:
|
||||
size_t size) override;
|
||||
|
||||
/** HasLocalDatapoolIF overrides */
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual object_id_t getObjectId() const override;
|
||||
virtual ReturnValue_t initializeLocalDataPool(
|
||||
LocalDataPool& localDataPoolMap,
|
||||
localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual uint32_t getPeriodicOperationFrequency() const override;
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
};
|
||||
|
@ -38,11 +38,12 @@ ReturnValue_t PoolDataSetBase::registerVariable(
|
||||
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 error = result;
|
||||
if (state == States::STATE_SET_UNINITIALISED) {
|
||||
lockDataPool(lockTimeout);
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = readVariable(count);
|
||||
if(result != RETURN_OK) {
|
||||
@ -86,7 +87,9 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
|
||||
!= PoolVariableIF::NO_PARAMETER)
|
||||
{
|
||||
if(protectEveryReadCommitCall) {
|
||||
result = registeredVariables[count]->read(mutexTimeout);
|
||||
result = registeredVariables[count]->read(
|
||||
timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
result = registeredVariables[count]->readWithoutLock();
|
||||
@ -99,25 +102,29 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
|
||||
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) {
|
||||
handleAlreadyReadDatasetCommit(lockTimeout);
|
||||
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return handleUnreadDatasetCommit(lockTimeout);
|
||||
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) {
|
||||
lockDataPool(lockTimeout);
|
||||
void PoolDataSetBase::handleAlreadyReadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if (registeredVariables[count]->getReadWriteMode()
|
||||
!= PoolVariableIF::VAR_READ
|
||||
&& registeredVariables[count]->getDataPoolId()
|
||||
!= PoolVariableIF::NO_PARAMETER) {
|
||||
if(protectEveryReadCommitCall) {
|
||||
registeredVariables[count]->commit(mutexTimeout);
|
||||
registeredVariables[count]->commit(
|
||||
timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
registeredVariables[count]->commitWithoutLock();
|
||||
@ -128,16 +135,19 @@ void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) {
|
||||
unlockDataPool();
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) {
|
||||
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
lockDataPool(lockTimeout);
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if (registeredVariables[count]->getReadWriteMode()
|
||||
== PoolVariableIF::VAR_WRITE
|
||||
&& registeredVariables[count]->getDataPoolId()
|
||||
!= PoolVariableIF::NO_PARAMETER) {
|
||||
if(protectEveryReadCommitCall) {
|
||||
result = registeredVariables[count]->commit(mutexTimeout);
|
||||
result = registeredVariables[count]->commit(
|
||||
timeoutTypeForSingleVars,
|
||||
mutexTimeoutForSingleVars);
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -206,8 +217,14 @@ void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
|
||||
this->registeredVariables = variablesContainer;
|
||||
}
|
||||
|
||||
void PoolDataSetBase::setReadCommitProtectionBehaviour(
|
||||
bool protectEveryReadCommit, uint32_t mutexTimeout) {
|
||||
this->protectEveryReadCommitCall = protectEveryReadCommit;
|
||||
this->mutexTimeout = mutexTimeout;
|
||||
PoolVariableIF** PoolDataSetBase::getContainer() const {
|
||||
return registeredVariables;
|
||||
}
|
||||
|
||||
void PoolDataSetBase::setReadCommitProtectionBehaviour(
|
||||
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType,
|
||||
uint32_t mutexTimeout) {
|
||||
this->protectEveryReadCommitCall = protectEveryReadCommit;
|
||||
this->timeoutTypeForSingleVars = timeoutType;
|
||||
this->mutexTimeoutForSingleVars = mutexTimeout;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "PoolDataSetIF.h"
|
||||
#include "PoolVariableIF.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
#include "../ipc/MutexIF.h"
|
||||
|
||||
/**
|
||||
@ -62,8 +63,9 @@ public:
|
||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||
* commit() in between
|
||||
*/
|
||||
virtual ReturnValue_t read(uint32_t lockTimeout =
|
||||
MutexIF::BLOCKING) override;
|
||||
virtual ReturnValue_t read(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
/**
|
||||
* @brief The commit call initializes writing back the registered variables.
|
||||
* @details
|
||||
@ -82,8 +84,9 @@ public:
|
||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||
* contains non write-only variables
|
||||
*/
|
||||
virtual ReturnValue_t commit(uint32_t lockTimeout =
|
||||
MutexIF::BLOCKING) override;
|
||||
virtual ReturnValue_t commit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
|
||||
/**
|
||||
* Register the passed pool variable instance into the data set.
|
||||
@ -97,8 +100,9 @@ public:
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c RETURN_OK
|
||||
*/
|
||||
virtual ReturnValue_t lockDataPool(uint32_t timeoutMs =
|
||||
MutexIF::BLOCKING) override;
|
||||
virtual ReturnValue_t lockDataPool(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
/**
|
||||
* Provides the means to unlock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
@ -116,16 +120,16 @@ public:
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* Can be used to individually protect every read and commit call.
|
||||
* @param protectEveryReadCommit
|
||||
* @param mutexTimeout
|
||||
*/
|
||||
void setReadCommitProtectionBehaviour(bool protectEveryReadCommit,
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t mutexTimeout = 20);
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Can be used to individually protect every read and commit call.
|
||||
* @param protectEveryReadCommit
|
||||
* @param mutexTimeout
|
||||
*/
|
||||
void setReadCommitProtectionBehaviour(bool protectEveryReadCommit,
|
||||
uint32_t mutexTimeout = 20);
|
||||
|
||||
/**
|
||||
* @brief The fill_count attribute ensures that the variables
|
||||
* register in the correct array position and that the maximum
|
||||
@ -154,14 +158,20 @@ protected:
|
||||
const size_t maxFillCount = 0;
|
||||
|
||||
void setContainer(PoolVariableIF** variablesContainer);
|
||||
PoolVariableIF** getContainer() const;
|
||||
|
||||
private:
|
||||
bool protectEveryReadCommitCall = false;
|
||||
uint32_t mutexTimeout = 20;
|
||||
MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t mutexTimeoutForSingleVars = 20;
|
||||
|
||||
ReturnValue_t readVariable(uint16_t count);
|
||||
void handleAlreadyReadDatasetCommit(uint32_t lockTimeout);
|
||||
ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout);
|
||||
void handleAlreadyReadDatasetCommit(
|
||||
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_ */
|
||||
|
@ -18,7 +18,10 @@ public:
|
||||
* thread-safety
|
||||
* @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.
|
||||
* @return Unlock operation result
|
||||
|
@ -25,6 +25,7 @@ class PoolVariableIF : public SerializeIF,
|
||||
public:
|
||||
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_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
|
||||
|
||||
static constexpr bool VALID = 1;
|
||||
static constexpr bool INVALID = 0;
|
||||
|
@ -1,7 +1,8 @@
|
||||
#ifndef 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
|
||||
@ -10,8 +11,10 @@
|
||||
class ReadCommitIF {
|
||||
public:
|
||||
virtual ~ReadCommitIF() {}
|
||||
virtual ReturnValue_t read(uint32_t mutexTimeout) = 0;
|
||||
virtual ReturnValue_t commit(uint32_t mutexTimeout) = 0;
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) = 0;
|
||||
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@ -19,11 +22,11 @@ protected:
|
||||
//! members with commit and read semantics where the lock is only necessary
|
||||
//! once.
|
||||
virtual ReturnValue_t readWithoutLock() {
|
||||
return read(20);
|
||||
return read(MutexIF::TimeoutType::WAITING, 20);
|
||||
}
|
||||
|
||||
virtual ReturnValue_t commitWithoutLock() {
|
||||
return commit(20);
|
||||
return commit(MutexIF::TimeoutType::WAITING, 20);
|
||||
}
|
||||
};
|
||||
|
||||
|
27
datapoollocal/AccessLocalPoolF.h
Normal file
27
datapoollocal/AccessLocalPoolF.h
Normal 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_ */
|
@ -5,4 +5,6 @@ target_sources(${LIB_FSFW_NAME}
|
||||
LocalPoolDataSetBase.cpp
|
||||
LocalPoolObjectBase.cpp
|
||||
SharedLocalDataSet.cpp
|
||||
)
|
||||
)
|
||||
|
||||
add_subdirectory(internal)
|
@ -1,105 +1,66 @@
|
||||
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
|
||||
#define FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
|
||||
|
||||
#include "locPoolDefinitions.h"
|
||||
#include "localPoolDefinitions.h"
|
||||
#include "LocalDataPoolManager.h"
|
||||
|
||||
#include "../datapool/PoolEntryIF.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
#include "../housekeeping/HousekeepingMessage.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class LocalDataPoolManager;
|
||||
class AccessPoolManagerIF;
|
||||
class ProvidesDataPoolSubscriptionIF;
|
||||
class LocalPoolDataSetBase;
|
||||
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
|
||||
* data pool (not the managing class). It defines the relationship
|
||||
* between the local data pool owner and the LocalDataPoolManager.
|
||||
* @brief This interface is implemented by classes which posses a local data pool (not the
|
||||
* managing class). It defines the relationship between the local data pool owner
|
||||
* and the LocalDataPoolManager.
|
||||
* @details
|
||||
* Any class implementing this interface shall also have a LocalDataPoolManager
|
||||
* member class which contains the actual pool data structure
|
||||
* and exposes the public interface for it.
|
||||
* This is required because the pool entries are templates, which makes
|
||||
* specifying an interface rather difficult. The local data pool can be
|
||||
* accessed by using the LocalPoolVariable, LocalPoolVector or LocalDataSet
|
||||
* classes.
|
||||
* Any class implementing this interface shall also have a LocalDataPoolManager member class which
|
||||
* contains the actual pool data structure and exposes the public interface for it.
|
||||
* The local data pool can be accessed using helper classes by using the
|
||||
* LocalPoolVariable, LocalPoolVector or LocalDataSet classes. Every local pool variable can
|
||||
* be uniquely identified by a global pool ID (gp_id_t) and every dataset tied
|
||||
* to a pool manager can be uniqely identified by a global structure ID (sid_t).
|
||||
*
|
||||
* 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 {
|
||||
friend class HasLocalDpIFManagerAttorney;
|
||||
friend class HasLocalDpIFUserAttorney;
|
||||
public:
|
||||
virtual~ HasLocalDataPoolIF() {};
|
||||
virtual~ HasLocalDataPoolIF() {};
|
||||
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF;
|
||||
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
|
||||
|
||||
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
|
||||
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
|
||||
virtual object_id_t getObjectId() const = 0;
|
||||
|
||||
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
|
||||
/** Command queue for housekeeping messages. */
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
||||
virtual object_id_t getObjectId() const = 0;
|
||||
/**
|
||||
* Is used by pool owner to initialize the pool map once
|
||||
* The manager instance shall also be passed to this function.
|
||||
* It can be used to subscribe for periodic packets for for updates.
|
||||
*/
|
||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) = 0;
|
||||
|
||||
/** Command queue for housekeeping messages. */
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
||||
/**
|
||||
* Is used by pool owner to initialize the pool map once
|
||||
* The manager instance shall also be passed to this function.
|
||||
* It can be used to subscribe for periodic packets for for updates.
|
||||
*/
|
||||
virtual ReturnValue_t initializeLocalDataPool(
|
||||
LocalDataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) = 0;
|
||||
|
||||
/** Can be used to get a handle to the local data pool manager. */
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
|
||||
|
||||
/**
|
||||
* Returns the minimum sampling frequency in milliseconds, which will
|
||||
* usually be the period the pool owner performs its periodic operation.
|
||||
* @return
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* Returns the minimum sampling frequency in milliseconds, which will
|
||||
* usually be the period the pool owner performs its periodic operation.
|
||||
* @return
|
||||
*/
|
||||
virtual uint32_t getPeriodicOperationFrequency() const = 0;
|
||||
|
||||
/**
|
||||
* @brief This function will be called by the manager if an update
|
||||
* notification is received.
|
||||
* @details
|
||||
* @details HasLocalDataPoolIF
|
||||
* Can be overriden by the child class to handle changed datasets.
|
||||
* @param sid
|
||||
* @param storeId If a snapshot was requested, data will be located inside
|
||||
@ -124,18 +85,81 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
/* These function can be implemented by pool owner, as they are required
|
||||
* by the housekeeping message interface */
|
||||
virtual ReturnValue_t addDataSet(sid_t sid) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
};
|
||||
virtual ReturnValue_t removeDataSet(sid_t sid) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
};
|
||||
virtual ReturnValue_t changeCollectionInterval(sid_t sid,
|
||||
float newIntervalSeconds) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
};
|
||||
/**
|
||||
* 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) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
};
|
||||
virtual ReturnValue_t removeDataSet(sid_t sid) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
};
|
||||
virtual ReturnValue_t changeCollectionInterval(sid_t sid, float newIntervalSeconds) {
|
||||
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_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,10 @@
|
||||
#ifndef 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/HousekeepingMessage.h"
|
||||
#include "../housekeeping/PeriodicHousekeepingHelper.h"
|
||||
@ -15,6 +17,7 @@
|
||||
#include "../ipc/MutexHelper.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace Factory {
|
||||
void setStaticFrameworkObjectIds();
|
||||
@ -22,6 +25,8 @@ void setStaticFrameworkObjectIds();
|
||||
|
||||
class LocalPoolDataSetBase;
|
||||
class HousekeepingPacketUpdate;
|
||||
class HasLocalDataPoolIF;
|
||||
class LocalDataPool;
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @author R. Mueller
|
||||
*/
|
||||
class LocalDataPoolManager {
|
||||
template<typename T> friend class LocalPoolVariable;
|
||||
template<typename T, uint16_t vecSize> friend class LocalPoolVector;
|
||||
friend class LocalPoolDataSetBase;
|
||||
class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF,
|
||||
public AccessPoolManagerIF {
|
||||
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:
|
||||
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
|
||||
@ -116,7 +125,7 @@ public:
|
||||
*/
|
||||
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
||||
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
|
||||
@ -130,7 +139,7 @@ public:
|
||||
*/
|
||||
ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled,
|
||||
bool isDiagnostics,
|
||||
object_id_t packetDestination = defaultHkDestination);
|
||||
object_id_t packetDestination = defaultHkDestination) override;
|
||||
|
||||
/**
|
||||
* @brief Subscribe for a notification message which will be sent
|
||||
@ -149,7 +158,7 @@ public:
|
||||
ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot);
|
||||
bool generateSnapshot) override;
|
||||
|
||||
/**
|
||||
* @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,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot);
|
||||
bool generateSnapshot) override;
|
||||
|
||||
MutexIF* getLocalPoolMutex() override;
|
||||
|
||||
/**
|
||||
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||
@ -247,8 +258,18 @@ public:
|
||||
LocalDataPoolManager(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:
|
||||
LocalDataPool localPoolMap;
|
||||
localpool::DataPool localPoolMap;
|
||||
//! Every housekeeping data manager has a mutex to protect access
|
||||
//! to it's data pool.
|
||||
MutexIF* mutex = nullptr;
|
||||
@ -367,6 +388,11 @@ private:
|
||||
ReturnValue_t& status);
|
||||
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket,
|
||||
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) {
|
||||
auto poolIter = localPoolMap.find(localPoolId);
|
||||
if (poolIter == localPoolMap.end()) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "HousekeepingManager::fechPoolEntry: Pool entry "
|
||||
"not found." << std::endl;
|
||||
#endif
|
||||
return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND;
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_NOT_FOUND);
|
||||
return localpool::POOL_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
||||
if(*poolEntry == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "HousekeepingManager::fetchPoolEntry:"
|
||||
" Pool entry not found." << std::endl;
|
||||
#endif
|
||||
return HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT;
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
||||
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ LocalDataSet::LocalDataSet(HasLocalDataPoolIF *hkOwner, uint32_t setId,
|
||||
const size_t maxNumberOfVariables):
|
||||
LocalPoolDataSetBase(hkOwner, setId, nullptr, maxNumberOfVariables),
|
||||
poolVarList(maxNumberOfVariables) {
|
||||
this->setContainer(poolVarList.data());
|
||||
this->setContainer(poolVarList.data());
|
||||
}
|
||||
|
||||
LocalDataSet::LocalDataSet(sid_t sid, const size_t maxNumberOfVariables):
|
||||
LocalPoolDataSetBase(sid, nullptr, maxNumberOfVariables),
|
||||
poolVarList(maxNumberOfVariables) {
|
||||
this->setContainer(poolVarList.data());
|
||||
poolVarList(maxNumberOfVariables) {
|
||||
this->setContainer(poolVarList.data());
|
||||
}
|
||||
|
||||
LocalDataSet::~LocalDataSet() {}
|
||||
|
@ -7,7 +7,7 @@
|
||||
class LocalDataSet: public LocalPoolDataSetBase {
|
||||
public:
|
||||
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
||||
const size_t maxSize);
|
||||
const size_t maxSize);
|
||||
LocalDataSet(sid_t sid, const size_t maxSize);
|
||||
virtual~ LocalDataSet();
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#include "HasLocalDataPoolIF.h"
|
||||
#include "internal/HasLocalDpIFUserAttorney.h"
|
||||
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../housekeeping/PeriodicHousekeepingHelper.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
@ -15,15 +19,22 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
|
||||
<< "invalid!" << std::endl;
|
||||
#endif
|
||||
#else
|
||||
sif::printError("LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
|
||||
"invalid!\n\r");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
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.ownerSetId = setId;
|
||||
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
|
||||
// Data creators get a periodic helper for periodic HK data generation.
|
||||
if(periodicHandling) {
|
||||
periodicHelper = new PeriodicHousekeepingHelper(this);
|
||||
@ -33,26 +44,40 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
||||
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
|
||||
PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxNumberOfVariables):
|
||||
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
||||
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
||||
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
|
||||
sid.objectId);
|
||||
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() {
|
||||
if(periodicHelper != nullptr) {
|
||||
delete periodicHelper;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t LocalPoolDataSetBase::lockDataPool(uint32_t timeoutMs) {
|
||||
if(hkManager != nullptr) {
|
||||
MutexIF* mutex = hkManager->getMutexHandle();
|
||||
return mutex->lockMutex(MutexIF::TimeoutType::WAITING, timeoutMs);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t LocalPoolDataSetBase::lockDataPool(
|
||||
MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) {
|
||||
if(mutexIfSingleDataCreator != nullptr) {
|
||||
return mutexIfSingleDataCreator->lockMutex(timeoutType, timeoutMs);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer,
|
||||
@ -128,11 +153,10 @@ ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer(
|
||||
}
|
||||
|
||||
ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
|
||||
if(hkManager != nullptr) {
|
||||
MutexIF* mutex = hkManager->getMutexHandle();
|
||||
return mutex->unlockMutex();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
if(mutexIfSingleDataCreator != nullptr) {
|
||||
return mutexIfSingleDataCreator->unlockMutex();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
|
||||
@ -150,9 +174,12 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
|
||||
size, maxSize, streamEndianness);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalDataSet::serializeLocalPoolIds: Serialization"
|
||||
" error!" << std::endl;
|
||||
#endif
|
||||
sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: "
|
||||
<< "Serialization error!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalPoolDataSetBase::serializeLocalPoolIds: "
|
||||
"Serialization error!\n\r");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
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 {
|
||||
if(position > 7) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "Pool Raw Access: Bit setting invalid position"
|
||||
sif::warning << "LocalPoolDataSetBase::bitSetter: Invalid position!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalPoolDataSetBase::bitSetter: "
|
||||
"Invalid position!\n\r");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -244,14 +274,10 @@ void LocalPoolDataSetBase::initializePeriodicHelper(
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::setChanged(bool changed) {
|
||||
// TODO: Make this configurable?
|
||||
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
|
||||
this->changed = changed;
|
||||
}
|
||||
|
||||
bool LocalPoolDataSetBase::hasChanged() const {
|
||||
// TODO: Make this configurable?
|
||||
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -273,12 +299,10 @@ bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte,
|
||||
}
|
||||
|
||||
bool LocalPoolDataSetBase::isValid() const {
|
||||
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5);
|
||||
return this->valid;
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
|
||||
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5);
|
||||
if(setEntriesRecursively) {
|
||||
for(size_t idx = 0; idx < this->getFillCount(); idx++) {
|
||||
registeredVariables[idx] -> setValid(valid);
|
||||
@ -287,8 +311,9 @@ void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
|
||||
this->valid = valid;
|
||||
}
|
||||
|
||||
void LocalPoolDataSetBase::setReadCommitProtectionBehaviour(
|
||||
bool protectEveryReadCommit, uint32_t mutexTimeout) {
|
||||
PoolDataSetBase::setReadCommitProtectionBehaviour(protectEveryReadCommit,
|
||||
mutexTimeout);
|
||||
object_id_t LocalPoolDataSetBase::getCreatorObjectId() {
|
||||
if(poolManager != nullptr) {
|
||||
return poolManager->getCreatorObjectId();
|
||||
}
|
||||
return objects::NO_OBJECT;
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
|
||||
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
|
||||
|
||||
#include "HasLocalDataPoolIF.h"
|
||||
#include "MarkChangedIF.h"
|
||||
#include "localPoolDefinitions.h"
|
||||
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapool/PoolDataSetBase.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class LocalDataPoolManager;
|
||||
class HasLocalDataPoolIF;
|
||||
class PeriodicHousekeepingHelper;
|
||||
|
||||
/**
|
||||
@ -41,167 +41,185 @@ class PeriodicHousekeepingHelper;
|
||||
*
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class LocalPoolDataSetBase: public PoolDataSetBase,
|
||||
class LocalPoolDataSetBase:
|
||||
public PoolDataSetBase,
|
||||
public MarkChangedIF {
|
||||
friend class LocalDataPoolManager;
|
||||
friend class PeriodicHousekeepingHelper;
|
||||
friend class LocalPoolDataSetAttorney;
|
||||
friend class PeriodicHousekeepingHelper;
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the creator of local pool data.
|
||||
* @details
|
||||
* This constructor also initializes the components required for
|
||||
* periodic handling.
|
||||
*/
|
||||
LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
||||
uint32_t setId, PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxNumberOfVariables, bool periodicHandling = true);
|
||||
/**
|
||||
* @brief Constructor for the creator of local pool data.
|
||||
* @details
|
||||
* This constructor also initializes the components required for
|
||||
* periodic handling.
|
||||
*/
|
||||
LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
||||
uint32_t setId, PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxNumberOfVariables, bool periodicHandling = true);
|
||||
|
||||
/**
|
||||
* @brief Constructor for users of local pool data.
|
||||
* @details
|
||||
* @param sid Unique identifier of dataset consisting of object ID and
|
||||
* set ID.
|
||||
* @param registeredVariablesArray
|
||||
* @param maxNumberOfVariables
|
||||
*/
|
||||
LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxNumberOfVariables);
|
||||
/**
|
||||
* @brief Constructor for users of the local pool data, which need
|
||||
* to access data created by one (!) HK manager.
|
||||
* @details
|
||||
* Unlike the first constructor, no component for periodic handling
|
||||
* will be initiated.
|
||||
* @param sid Unique identifier of dataset consisting of object ID and
|
||||
* set ID.
|
||||
* @param registeredVariablesArray
|
||||
* @param maxNumberOfVariables
|
||||
*/
|
||||
LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxNumberOfVariables);
|
||||
|
||||
/**
|
||||
* @brief The destructor automatically manages writing the valid
|
||||
* information of variables.
|
||||
* @details
|
||||
* In case the data set was read out, but not committed(indicated by state),
|
||||
* the destructor parses all variables that are still registered to the set.
|
||||
* For each, the valid flag in the data pool is set to "invalid".
|
||||
*/
|
||||
~LocalPoolDataSetBase();
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* @brief The destructor automatically manages writing the valid
|
||||
* information of variables.
|
||||
* @details
|
||||
* In case the data set was read out, but not committed(indicated by state),
|
||||
* the destructor parses all variables that are still registered to the set.
|
||||
* For each, the valid flag in the data pool is set to "invalid".
|
||||
*/
|
||||
~LocalPoolDataSetBase();
|
||||
|
||||
void setValidityBufferGeneration(bool withValidityBuffer);
|
||||
void setValidityBufferGeneration(bool withValidityBuffer);
|
||||
|
||||
sid_t getSid() const;
|
||||
sid_t getSid() const;
|
||||
|
||||
/** SerializeIF overrides */
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
size_t getSerializedSize() const override;
|
||||
/** SerializeIF overrides */
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
size_t getSerializedSize() const override;
|
||||
|
||||
/**
|
||||
* Special version of the serilization function which appends a
|
||||
* validity buffer at the end. Each bit of this validity buffer
|
||||
* denotes whether the container data set entries are valid from left
|
||||
* to right, MSB first. (length = ceil(N/8), N = number of pool variables)
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param maxSize
|
||||
* @param bigEndian
|
||||
* @param withValidityBuffer
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t serializeWithValidityBuffer(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const;
|
||||
ReturnValue_t deSerializeWithValidityBuffer(const uint8_t** buffer,
|
||||
size_t *size, SerializeIF::Endianness streamEndianness);
|
||||
ReturnValue_t serializeLocalPoolIds(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness,
|
||||
bool serializeFillCount = true) const;
|
||||
uint8_t getLocalPoolIdsSerializedSize(bool serializeFillCount = true) const;
|
||||
/**
|
||||
* Special version of the serilization function which appends a
|
||||
* validity buffer at the end. Each bit of this validity buffer
|
||||
* denotes whether the container data set entries are valid from left
|
||||
* to right, MSB first. (length = ceil(N/8), N = number of pool variables)
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param maxSize
|
||||
* @param bigEndian
|
||||
* @param withValidityBuffer
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t serializeWithValidityBuffer(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const;
|
||||
ReturnValue_t deSerializeWithValidityBuffer(const uint8_t** buffer,
|
||||
size_t *size, SerializeIF::Endianness streamEndianness);
|
||||
ReturnValue_t serializeLocalPoolIds(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness,
|
||||
bool serializeFillCount = true) const;
|
||||
uint8_t getLocalPoolIdsSerializedSize(bool serializeFillCount = true) const;
|
||||
|
||||
/**
|
||||
* Set the dataset valid or invalid. These calls are mutex protected.
|
||||
* @param setEntriesRecursively
|
||||
* If this is true, all contained datasets will also be set recursively.
|
||||
*/
|
||||
void setValidity(bool valid, bool setEntriesRecursively);
|
||||
bool isValid() const override;
|
||||
/**
|
||||
* Set the dataset valid or invalid. These calls are mutex protected.
|
||||
* @param setEntriesRecursively
|
||||
* If this is true, all contained datasets will also be set recursively.
|
||||
*/
|
||||
void setValidity(bool valid, bool setEntriesRecursively);
|
||||
bool isValid() const override;
|
||||
|
||||
/**
|
||||
* These calls are mutex protected.
|
||||
* @param changed
|
||||
*/
|
||||
void setChanged(bool changed) override;
|
||||
bool hasChanged() const override;
|
||||
/**
|
||||
* These calls are mutex protected.
|
||||
* @param changed
|
||||
*/
|
||||
void setChanged(bool changed) override;
|
||||
bool hasChanged() const override;
|
||||
|
||||
object_id_t getCreatorObjectId();
|
||||
protected:
|
||||
sid_t sid;
|
||||
uint32_t mutexTimeout = 20;
|
||||
MutexIF* mutex = nullptr;
|
||||
sid_t sid;
|
||||
//! This mutex is used if the data is created by one object only.
|
||||
MutexIF* mutexIfSingleDataCreator = nullptr;
|
||||
|
||||
bool diagnostic = false;
|
||||
void setDiagnostic(bool diagnostics);
|
||||
bool isDiagnostics() const;
|
||||
bool diagnostic = false;
|
||||
void setDiagnostic(bool diagnostics);
|
||||
bool isDiagnostics() const;
|
||||
|
||||
/**
|
||||
* Used for periodic generation.
|
||||
*/
|
||||
bool reportingEnabled = false;
|
||||
void setReportingEnabled(bool enabled);
|
||||
bool getReportingEnabled() const;
|
||||
/**
|
||||
* Used for periodic generation.
|
||||
*/
|
||||
bool reportingEnabled = false;
|
||||
void setReportingEnabled(bool enabled);
|
||||
bool getReportingEnabled() const;
|
||||
|
||||
void initializePeriodicHelper(float collectionInterval,
|
||||
dur_millis_t minimumPeriodicInterval,
|
||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5);
|
||||
void initializePeriodicHelper(float collectionInterval,
|
||||
dur_millis_t minimumPeriodicInterval,
|
||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5);
|
||||
|
||||
/**
|
||||
* If the valid state of a dataset is always relevant to the whole
|
||||
* data set we can use this flag.
|
||||
*/
|
||||
bool valid = false;
|
||||
/**
|
||||
* If the valid state of a dataset is always relevant to the whole
|
||||
* data set we can use this flag.
|
||||
*/
|
||||
bool valid = false;
|
||||
|
||||
/**
|
||||
* Can be used to mark the dataset as changed, which is used
|
||||
* by the LocalDataPoolManager to send out update messages.
|
||||
*/
|
||||
bool changed = false;
|
||||
/**
|
||||
* Can be used to mark the dataset as changed, which is used
|
||||
* by the LocalDataPoolManager to send out update messages.
|
||||
*/
|
||||
bool changed = false;
|
||||
|
||||
/**
|
||||
* Specify whether the validity buffer is serialized too when serializing
|
||||
* or deserializing the packet. Each bit of the validity buffer will
|
||||
* contain the validity state of the pool variables from left to right.
|
||||
* The size of validity buffer thus will be ceil(N / 8) with N = number of
|
||||
* pool variables.
|
||||
*/
|
||||
bool withValidityBuffer = true;
|
||||
/**
|
||||
* Specify whether the validity buffer is serialized too when serializing
|
||||
* or deserializing the packet. Each bit of the validity buffer will
|
||||
* contain the validity state of the pool variables from left to right.
|
||||
* The size of validity buffer thus will be ceil(N / 8) with N = number of
|
||||
* pool variables.
|
||||
*/
|
||||
bool withValidityBuffer = true;
|
||||
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate locking
|
||||
* the global data pool.
|
||||
* @details
|
||||
* It makes use of the lockDataPool method offered by the DataPool class.
|
||||
*/
|
||||
ReturnValue_t lockDataPool(uint32_t timeoutMs) override;
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate
|
||||
* unlocking the global data pool
|
||||
* @details
|
||||
* It makes use of the freeDataPoolLock method offered by the DataPool class.
|
||||
*/
|
||||
ReturnValue_t unlockDataPool() override;
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate locking
|
||||
* the global data pool.
|
||||
* @details
|
||||
* It makes use of the lockDataPool method offered by the DataPool class.
|
||||
*/
|
||||
ReturnValue_t lockDataPool(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) override;
|
||||
|
||||
LocalDataPoolManager* hkManager = nullptr;
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate
|
||||
* unlocking the global data pool
|
||||
* @details
|
||||
* It makes use of the freeDataPoolLock method offered by the DataPool class.
|
||||
*/
|
||||
ReturnValue_t unlockDataPool() override;
|
||||
|
||||
/**
|
||||
* Set n-th bit of a byte, with n being the position from 0
|
||||
* (most significant bit) to 7 (least significant bit)
|
||||
*/
|
||||
void bitSetter(uint8_t* byte, uint8_t position) const;
|
||||
bool bitGetter(const uint8_t* byte, uint8_t position) const;
|
||||
/**
|
||||
* Set n-th bit of a byte, with n being the position from 0
|
||||
* (most significant bit) to 7 (least significant bit)
|
||||
*/
|
||||
void bitSetter(uint8_t* byte, uint8_t position) const;
|
||||
bool bitGetter(const uint8_t* byte, uint8_t position) const;
|
||||
|
||||
PeriodicHousekeepingHelper* periodicHelper = nullptr;
|
||||
PeriodicHousekeepingHelper* periodicHelper = nullptr;
|
||||
LocalDataPoolManager* poolManager = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
#include "LocalPoolObjectBase.h"
|
||||
#include "LocalDataPoolManager.h"
|
||||
#include "internal/HasLocalDpIFUserAttorney.h"
|
||||
#include "HasLocalDataPoolIF.h"
|
||||
|
||||
LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId,
|
||||
HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode): localPoolId(poolId),
|
||||
readWriteMode(setReadWriteMode) {
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
|
||||
LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
|
||||
DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
||||
localPoolId(poolId), readWriteMode(setReadWriteMode) {
|
||||
if(poolId == PoolVariableIF::NO_PARAMETER) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
|
||||
@ -17,23 +21,24 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId,
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
hkManager = hkOwner->getHkManagerHandle();
|
||||
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
hkManager = poolManAccessor->getHkManagerHandle();
|
||||
|
||||
if (dataSet != nullptr) {
|
||||
dataSet->registerVariable(this);
|
||||
}
|
||||
}
|
||||
|
||||
LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode): localPoolId(poolId),
|
||||
readWriteMode(setReadWriteMode) {
|
||||
LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF *dataSet,
|
||||
pool_rwm_t setReadWriteMode):
|
||||
localPoolId(poolId), readWriteMode(setReadWriteMode) {
|
||||
if(poolId == PoolVariableIF::NO_PARAMETER) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
|
||||
<< "which is the NO_PARAMETER value!" << std::endl;
|
||||
#endif
|
||||
}
|
||||
HasLocalDataPoolIF* hkOwner =
|
||||
objectManager->get<HasLocalDataPoolIF>(poolOwner);
|
||||
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(poolOwner);
|
||||
if(hkOwner == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPoolVariable: The supplied pool owner did not "
|
||||
@ -42,7 +47,12 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
hkManager = hkOwner->getHkManagerHandle();
|
||||
|
||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
if(accessor != nullptr) {
|
||||
hkManager = accessor->getHkManagerHandle();
|
||||
}
|
||||
|
||||
if(dataSet != nullptr) {
|
||||
dataSet->registerVariable(this);
|
||||
}
|
||||
@ -77,5 +87,44 @@ bool LocalPoolObjectBase::hasChanged() const {
|
||||
}
|
||||
|
||||
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 */
|
||||
}
|
||||
|
@ -2,10 +2,20 @@
|
||||
#define FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_
|
||||
|
||||
#include "MarkChangedIF.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "localPoolDefinitions.h"
|
||||
|
||||
#include "../objectmanager/SystemObjectIF.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,
|
||||
public HasReturnvaluesIF,
|
||||
public MarkChangedIF {
|
||||
@ -54,10 +64,10 @@ protected:
|
||||
ReadWriteMode_t readWriteMode = pool_rwm_t::VAR_READ_WRITE;
|
||||
|
||||
//! @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_ */
|
||||
|
@ -4,9 +4,12 @@
|
||||
#include "LocalPoolObjectBase.h"
|
||||
#include "HasLocalDataPoolIF.h"
|
||||
#include "LocalDataPoolManager.h"
|
||||
#include "AccessLocalPoolF.h"
|
||||
#include "internal/LocalDpManagerAttorney.h"
|
||||
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
|
||||
@ -24,147 +27,160 @@
|
||||
template<typename T>
|
||||
class LocalPoolVariable: public LocalPoolObjectBase {
|
||||
public:
|
||||
//! Default ctor is forbidden.
|
||||
LocalPoolVariable() = delete;
|
||||
//! Default ctor is forbidden.
|
||||
LocalPoolVariable() = delete;
|
||||
|
||||
/**
|
||||
* This constructor is used by the data creators to have pool variable
|
||||
* instances which can also be stored in datasets.
|
||||
*
|
||||
* It does not fetch the current value from the data pool, which
|
||||
* has to be done by calling the read() operation.
|
||||
* Datasets can be used to access multiple local pool entries in an
|
||||
* efficient way. A pointer to a dataset can be passed to register
|
||||
* the pool variable in that dataset directly.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
*/
|
||||
LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
/**
|
||||
* This constructor is used by the data creators to have pool variable
|
||||
* instances which can also be stored in datasets.
|
||||
*
|
||||
* It does not fetch the current value from the data pool, which
|
||||
* has to be done by calling the read() operation.
|
||||
* Datasets can be used to access multiple local pool entries in an
|
||||
* efficient way. A pointer to a dataset can be passed to register
|
||||
* the pool variable in that dataset directly.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
*/
|
||||
LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
|
||||
/**
|
||||
* This constructor is used by data users like controllers to have
|
||||
* access to the local pool variables of data creators by supplying
|
||||
* the respective creator object ID.
|
||||
*
|
||||
* It does not fetch the current value from the data pool, which
|
||||
* has to be done by calling the read() operation.
|
||||
* Datasets can be used to access multiple local pool entries in an
|
||||
* efficient way. A pointer to a dataset can be passed to register
|
||||
* the pool variable in that dataset directly.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner object ID of the pool owner.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
*
|
||||
*/
|
||||
LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
/**
|
||||
* Variation which takes the global unique identifier of a pool variable.
|
||||
* @param globalPoolId
|
||||
* @param dataSet
|
||||
* @param setReadWriteMode
|
||||
*/
|
||||
LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
/**
|
||||
* This constructor is used by data users like controllers to have
|
||||
* access to the local pool variables of data creators by supplying
|
||||
* the respective creator object ID.
|
||||
*
|
||||
* It does not fetch the current value from the data pool, which
|
||||
* has to be done by calling the read() operation.
|
||||
* Datasets can be used to access multiple local pool entries in an
|
||||
* efficient way. A pointer to a dataset can be passed to register
|
||||
* the pool variable in that dataset directly.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner object ID of the pool owner.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
*
|
||||
*/
|
||||
LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
/**
|
||||
* Variation which takes the global unique identifier of a pool variable.
|
||||
* @param globalPoolId
|
||||
* @param dataSet
|
||||
* @param setReadWriteMode
|
||||
*/
|
||||
LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
|
||||
virtual~ LocalPoolVariable() {};
|
||||
virtual~ LocalPoolVariable() {};
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details The user can work on this attribute
|
||||
* just like he would on a simple local variable.
|
||||
*/
|
||||
T value = 0;
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details The user can work on this attribute
|
||||
* just like he would on a simple local variable.
|
||||
*/
|
||||
T value = 0;
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the data pool and copies all array values and the valid
|
||||
* information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*
|
||||
*/
|
||||
ReturnValue_t read(dur_millis_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the local valid flag is written back as well.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(dur_millis_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the data pool and copies all array values and the valid
|
||||
* information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*
|
||||
*/
|
||||
ReturnValue_t read(MutexIF::TimeoutType timeoutType =
|
||||
MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the local valid flag is written back as well.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(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 LocalPoolVariable<T>& newPoolVariable);
|
||||
LocalPoolVariable<T> &operator=(const T& newValue);
|
||||
LocalPoolVariable<T> &operator=(const LocalPoolVariable<T>& newPoolVariable);
|
||||
|
||||
//! Explicit type conversion operator. Allows casting the class to
|
||||
//! its template type to perform operations on value.
|
||||
explicit operator T() const;
|
||||
//! Explicit type conversion operator. Allows casting the class to
|
||||
//! its template type to perform operations on value.
|
||||
explicit operator T() const;
|
||||
|
||||
bool operator==(const LocalPoolVariable<T>& other) const;
|
||||
bool operator==(const T& other) const;
|
||||
bool operator==(const LocalPoolVariable<T>& other) const;
|
||||
bool operator==(const T& other) const;
|
||||
|
||||
bool operator!=(const LocalPoolVariable<T>& other) const;
|
||||
bool operator!=(const T& other) const;
|
||||
bool operator!=(const LocalPoolVariable<T>& other) const;
|
||||
bool operator!=(const T& other) const;
|
||||
|
||||
bool operator<(const LocalPoolVariable<T>& other) const;
|
||||
bool operator<(const T& other) const;
|
||||
bool operator<(const LocalPoolVariable<T>& other) const;
|
||||
bool operator<(const T& other) const;
|
||||
|
||||
bool operator>(const LocalPoolVariable<T>& other) const;
|
||||
bool operator>(const T& other) const;
|
||||
bool operator>(const LocalPoolVariable<T>& other) const;
|
||||
bool operator>(const T& other) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
// std::ostream is the type for object std::cout
|
||||
template <typename U>
|
||||
friend std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVariable<U> &var);
|
||||
// std::ostream is the type for object std::cout
|
||||
template <typename U>
|
||||
friend std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVariable<U> &var);
|
||||
#endif
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#include "LocalPoolVariable.tpp"
|
||||
|
@ -7,109 +7,127 @@
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner,
|
||||
lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner,
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId,
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
||||
dataSet, setReadWriteMode){}
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
||||
dataSet, setReadWriteMode){}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::read(dur_millis_t lockTimeout) {
|
||||
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING,
|
||||
lockTimeout);
|
||||
return readWithoutLock();
|
||||
inline ReturnValue_t LocalPoolVariable<T>::read(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return readWithoutLock();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "LocalPoolVar: Invalid read write "
|
||||
"mode for read() call." << std::endl;
|
||||
#endif
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
if(result != RETURN_OK or poolEntry == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PoolVector: Read of local pool variable of object "
|
||||
<< std::hex << std::setw(8) << std::setfill('0')
|
||||
<< hkManager->getOwner() << " and lp ID " << localPoolId
|
||||
<< std::dec << " failed." << std::setfill(' ') << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
this->value = *(poolEntry->address);
|
||||
this->valid = poolEntry->valid;
|
||||
return RETURN_OK;
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
//ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVariable", result,
|
||||
false, ownerObjectId, localPoolId);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::commit(dur_millis_t lockTimeout) {
|
||||
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING,
|
||||
lockTimeout);
|
||||
return commitWithoutLock();
|
||||
inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid,
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
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();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "LocalPoolVariable: Invalid read write "
|
||||
"mode for commit() call." << std::endl;
|
||||
#endif
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PoolVector: Read of local pool variable of object "
|
||||
"0x" << std::hex << std::setw(8) << std::setfill('0') <<
|
||||
hkManager->getOwner() << " and lp ID 0x" << localPoolId <<
|
||||
std::dec << " failed.\n" << std::flush;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
*(poolEntry->address) = this->value;
|
||||
poolEntry->valid = this->valid;
|
||||
return RETURN_OK;
|
||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
//ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVariable", result,
|
||||
false, ownerObjectId, localPoolId);
|
||||
return result;
|
||||
}
|
||||
|
||||
*(poolEntry->getDataPtr()) = this->value;
|
||||
poolEntry->setValid(this->valid);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t max_size, SerializeIF::Endianness streamEndianness) const {
|
||||
return SerializeAdapter::serialize(&value,
|
||||
buffer, size ,max_size, streamEndianness);
|
||||
inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer,
|
||||
size_t* size, const size_t max_size,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
return SerializeAdapter::serialize(&value,
|
||||
buffer, size ,max_size, streamEndianness);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer,
|
||||
size_t* size, SerializeIF::Endianness streamEndianness) {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||
size_t* size, SerializeIF::Endianness streamEndianness) {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
template<typename T>
|
||||
inline std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVariable<T> &var) {
|
||||
const LocalPoolVariable<T> &var) {
|
||||
out << var.value;
|
||||
return out;
|
||||
}
|
||||
@ -117,63 +135,68 @@ inline std::ostream& operator<< (std::ostream &out,
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>::operator T() const {
|
||||
return value;
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(const T& newValue) {
|
||||
inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(
|
||||
const T& newValue) {
|
||||
value = newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator =(
|
||||
const LocalPoolVariable<T>& newPoolVariable) {
|
||||
value = newPoolVariable.value;
|
||||
return *this;
|
||||
const LocalPoolVariable<T>& newPoolVariable) {
|
||||
value = newPoolVariable.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator ==(const LocalPoolVariable<T> &other) const {
|
||||
return this->value == other.value;
|
||||
inline bool LocalPoolVariable<T>::operator ==(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return this->value == other.value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator ==(const T &other) const {
|
||||
return this->value == other;
|
||||
return this->value == other;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator !=(const LocalPoolVariable<T> &other) const {
|
||||
return not (*this == other);
|
||||
inline bool LocalPoolVariable<T>::operator !=(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator !=(const T &other) const {
|
||||
return not (*this == other);
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator <(const LocalPoolVariable<T> &other) const {
|
||||
return this->value < other.value;
|
||||
inline bool LocalPoolVariable<T>::operator <(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return this->value < other.value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator <(const T &other) const {
|
||||
return this->value < other;
|
||||
return this->value < other;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator >(const LocalPoolVariable<T> &other) const {
|
||||
return not (*this < other);
|
||||
inline bool LocalPoolVariable<T>::operator >(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return not (*this < other);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator >(const T &other) const {
|
||||
return not (*this < other);
|
||||
return not (*this < other);
|
||||
}
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */
|
||||
|
@ -2,12 +2,14 @@
|
||||
#define FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
|
||||
|
||||
#include "LocalPoolObjectBase.h"
|
||||
#include "internal/LocalDpManagerAttorney.h"
|
||||
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -33,136 +35,149 @@
|
||||
template<typename T, uint16_t vectorSize>
|
||||
class LocalPoolVector: public LocalPoolObjectBase {
|
||||
public:
|
||||
LocalPoolVector() = delete;
|
||||
/**
|
||||
* This constructor is used by the data creators to have pool variable
|
||||
* instances which can also be stored in datasets.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
LocalPoolVector() = delete;
|
||||
/**
|
||||
* This constructor is used by the data creators to have pool variable
|
||||
* instances which can also be stored in datasets.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
|
||||
/**
|
||||
* This constructor is used by data users like controllers to have
|
||||
* access to the local pool variables of data creators by supplying
|
||||
* the respective creator object ID.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
/**
|
||||
* Variation which takes the unique global identifier of a local pool
|
||||
* vector.
|
||||
* @param globalPoolId
|
||||
* @param dataSet
|
||||
* @param setReadWriteMode
|
||||
*/
|
||||
LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
/**
|
||||
* This constructor is used by data users like controllers to have
|
||||
* access to the local pool variables of data creators by supplying
|
||||
* the respective creator object ID.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
/**
|
||||
* Variation which takes the unique global identifier of a local pool
|
||||
* vector.
|
||||
* @param globalPoolId
|
||||
* @param dataSet
|
||||
* @param setReadWriteMode
|
||||
*/
|
||||
LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details
|
||||
* The user can work on this attribute just like he would on a local
|
||||
* array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~LocalPoolVector() {};
|
||||
/**
|
||||
* @brief The operation returns the number of array entries
|
||||
* in this variable.
|
||||
*/
|
||||
uint8_t getSize() {
|
||||
return vectorSize;
|
||||
}
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details
|
||||
* The user can work on this attribute just like he would on a local
|
||||
* array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~LocalPoolVector() {};
|
||||
/**
|
||||
* @brief The operation returns the number of array entries
|
||||
* in this variable.
|
||||
*/
|
||||
uint8_t getSize() {
|
||||
return vectorSize;
|
||||
}
|
||||
|
||||
T& operator [](int i);
|
||||
const T &operator [](int i) const;
|
||||
T& operator [](size_t i);
|
||||
const T &operator [](size_t i) const;
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndiannes) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndiannes) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the data pool and copies all array values and the valid
|
||||
* information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the local valid flag is written back as well.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the data pool and copies all array values and the valid
|
||||
* information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(MutexIF::TimeoutType timeoutType =
|
||||
MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the local valid flag is written back as well.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(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:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// std::ostream is the type for object std::cout
|
||||
template <typename U, uint16_t otherSize>
|
||||
friend std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVector<U, otherSize> &var);
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
// std::ostream is the type for object std::cout
|
||||
template <typename U, uint16_t otherSize>
|
||||
friend std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVector<U, otherSize> &var);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
@ -7,152 +7,161 @@
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(
|
||||
HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
||||
dataSet, setReadWriteMode) {}
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
||||
dataSet, setReadWriteMode) {}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(uint32_t lockTimeout) {
|
||||
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING,
|
||||
lockTimeout);
|
||||
return readWithoutLock();
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return readWithoutLock();
|
||||
}
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "LocalPoolVar: Invalid read write "
|
||||
"mode for read() call." << std::endl;
|
||||
#endif
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
memset(this->value, 0, vectorSize * sizeof(T));
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
memset(this->value, 0, vectorSize * sizeof(T));
|
||||
|
||||
if(result != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PoolVector: Read of local pool variable of object "
|
||||
"0x" << std::hex << std::setw(8) << std::setfill('0') <<
|
||||
hkManager->getOwner() << "and lp ID 0x" << localPoolId <<
|
||||
std::dec << " failed." << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->value, poolEntry->address, poolEntry->getByteSize());
|
||||
this->valid = poolEntry->valid;
|
||||
return RETURN_OK;
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", result, true, targetObjectId,
|
||||
localPoolId);
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
|
||||
this->valid = poolEntry->getValid();
|
||||
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>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
|
||||
uint32_t lockTimeout) {
|
||||
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING,
|
||||
lockTimeout);
|
||||
return commitWithoutLock();
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return commitWithoutLock();
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "LocalPoolVar: Invalid read write "
|
||||
"mode for commit() call." << std::endl;
|
||||
#endif
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PoolVector: Read of local pool variable of object "
|
||||
"0x" << std::hex << std::setw(8) << std::setfill('0') <<
|
||||
hkManager->getOwner() << " and lp ID 0x" << localPoolId <<
|
||||
std::dec << " failed.\n" << std::flush;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
std::memcpy(poolEntry->address, this->value, poolEntry->getByteSize());
|
||||
poolEntry->valid = this->valid;
|
||||
return RETURN_OK;
|
||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", result, false, targetObjectId,
|
||||
localPoolId);
|
||||
return result;
|
||||
}
|
||||
std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
|
||||
poolEntry->setValid(this->valid);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline T& LocalPoolVector<T, vectorSize>::operator [](int i) {
|
||||
if(i <= vectorSize) {
|
||||
return value[i];
|
||||
}
|
||||
// If this happens, I have to set some value. I consider this
|
||||
// a configuration error, but I wont exit here.
|
||||
inline T& LocalPoolVector<T, vectorSize>::operator [](size_t i) {
|
||||
if(i < vectorSize) {
|
||||
return value[i];
|
||||
}
|
||||
// If this happens, I have to set some value. I consider this
|
||||
// a configuration error, but I wont exit here.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPoolVector: Invalid index. Setting or returning"
|
||||
" last value!" << std::endl;
|
||||
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
||||
" last value!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
|
||||
" last value!\n");
|
||||
#endif
|
||||
return value[i];
|
||||
return value[vectorSize - 1];
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline const T& LocalPoolVector<T, vectorSize>::operator [](int i) const {
|
||||
if(i <= vectorSize) {
|
||||
return value[i];
|
||||
}
|
||||
// If this happens, I have to set some value. I consider this
|
||||
// a configuration error, but I wont exit here.
|
||||
inline const T& LocalPoolVector<T, vectorSize>::operator [](size_t i) const {
|
||||
if(i < vectorSize) {
|
||||
return value[i];
|
||||
}
|
||||
// If this happens, I have to set some value. I consider this
|
||||
// a configuration error, but I wont exit here.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPoolVector: Invalid index. Setting or returning"
|
||||
" last value!" << std::endl;
|
||||
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
||||
" last value!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
|
||||
" last value!\n");
|
||||
#endif
|
||||
return value[i];
|
||||
return value[vectorSize - 1];
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::serialize(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||
result = SerializeAdapter::serialize(&(value[i]), buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||
result = SerializeAdapter::serialize(&(value[i]), buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline size_t LocalPoolVector<T, vectorSize>::getSerializedSize() const {
|
||||
return vectorSize * SerializeAdapter::getSerializedSize(value);
|
||||
return vectorSize * SerializeAdapter::getSerializedSize(value);
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::deSerialize(
|
||||
const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVector<T, vectorSize> &var) {
|
||||
@ -166,5 +175,6 @@ inline std::ostream& operator<< (std::ostream &out,
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ */
|
||||
|
@ -1,7 +1,8 @@
|
||||
#ifndef FSFW_DATAPOOLLOCAL_POOLREADHELPER_H_
|
||||
#define FSFW_DATAPOOLLOCAL_POOLREADHELPER_H_
|
||||
|
||||
#include <fsfw/datapoollocal/LocalPoolDataSetBase.h>
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include <FSFWConfig.h>
|
||||
|
||||
/**
|
||||
@ -9,33 +10,40 @@
|
||||
*/
|
||||
class PoolReadHelper {
|
||||
public:
|
||||
PoolReadHelper(ReadCommitIF* readObject, uint32_t mutexTimeout = 20):
|
||||
readObject(readObject), mutexTimeout(mutexTimeout) {
|
||||
if(readObject != nullptr) {
|
||||
readResult = readObject->read(mutexTimeout);
|
||||
#if FSFW_PRINT_VERBOSITY_LEVEL == 1
|
||||
PoolReadHelper(ReadCommitIF* readObject,
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t mutexTimeout = 20):
|
||||
readObject(readObject), mutexTimeout(mutexTimeout) {
|
||||
if(readObject != nullptr) {
|
||||
readResult = readObject->read(timeoutType, mutexTimeout);
|
||||
if(readResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_VERBOSE_LEVEL == 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_CPP_OSTREAM_ENABLED == 1 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t getReadResult() const {
|
||||
return readResult;
|
||||
}
|
||||
ReturnValue_t getReadResult() const {
|
||||
return readResult;
|
||||
}
|
||||
|
||||
~PoolReadHelper() {
|
||||
if(readObject != nullptr) {
|
||||
readObject->commit(mutexTimeout);
|
||||
}
|
||||
~PoolReadHelper() {
|
||||
if(readObject != nullptr) {
|
||||
readObject->commit(timeoutType, mutexTimeout);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ReadCommitIF* readObject = nullptr;
|
||||
ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK;
|
||||
uint32_t mutexTimeout = 20;
|
||||
ReadCommitIF* readObject = nullptr;
|
||||
ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK;
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t mutexTimeout = 20;
|
||||
};
|
||||
|
||||
|
||||
|
83
datapoollocal/ProvidesDataPoolSubscriptionIF.h
Normal file
83
datapoollocal/ProvidesDataPoolSubscriptionIF.h
Normal 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_ */
|
@ -6,7 +6,15 @@
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#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 SharedDataSetIF {
|
||||
public:
|
||||
|
@ -20,26 +20,24 @@
|
||||
template <uint8_t NUM_VARIABLES>
|
||||
class StaticLocalDataSet: public LocalPoolDataSetBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor used by data owner and creator like device handlers.
|
||||
* This constructor also initialized the components required for
|
||||
* periodic handling.
|
||||
* @param hkOwner
|
||||
* @param setId
|
||||
*/
|
||||
StaticLocalDataSet(HasLocalDataPoolIF* hkOwner,
|
||||
uint32_t setId): LocalPoolDataSetBase(hkOwner, setId, nullptr,
|
||||
NUM_VARIABLES) {
|
||||
/**
|
||||
* Constructor used by data owner and creator like device handlers.
|
||||
* This constructor also initialized the components required for
|
||||
* periodic handling.
|
||||
* @param hkOwner
|
||||
* @param setId
|
||||
*/
|
||||
StaticLocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId):
|
||||
LocalPoolDataSetBase(hkOwner, setId, nullptr, NUM_VARIABLES) {
|
||||
this->setContainer(poolVarList.data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used by data users like controllers.
|
||||
* @param hkOwner
|
||||
* @param setId
|
||||
*/
|
||||
StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr,
|
||||
NUM_VARIABLES) {
|
||||
/**
|
||||
* Constructor used by data users like controllers.
|
||||
* @param hkOwner
|
||||
* @param setId
|
||||
*/
|
||||
StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr, NUM_VARIABLES) {
|
||||
this->setContainer(poolVarList.data());
|
||||
}
|
||||
|
||||
|
5
datapoollocal/internal/CMakeLists.txt
Normal file
5
datapoollocal/internal/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HasLocalDpIFUserAttorney.cpp
|
||||
HasLocalDpIFManagerAttorney.cpp
|
||||
)
|
18
datapoollocal/internal/HasLocalDpIFManagerAttorney.cpp
Normal file
18
datapoollocal/internal/HasLocalDpIFManagerAttorney.cpp
Normal 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();
|
||||
}
|
22
datapoollocal/internal/HasLocalDpIFManagerAttorney.h
Normal file
22
datapoollocal/internal/HasLocalDpIFManagerAttorney.h
Normal 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_ */
|
7
datapoollocal/internal/HasLocalDpIFUserAttorney.cpp
Normal file
7
datapoollocal/internal/HasLocalDpIFUserAttorney.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "HasLocalDpIFUserAttorney.h"
|
||||
#include "../AccessLocalPoolF.h"
|
||||
#include "../HasLocalDataPoolIF.h"
|
||||
|
||||
AccessPoolManagerIF* HasLocalDpIFUserAttorney::getAccessorHandle(HasLocalDataPoolIF *clientIF) {
|
||||
return clientIF->getAccessorHandle();
|
||||
}
|
18
datapoollocal/internal/HasLocalDpIFUserAttorney.h
Normal file
18
datapoollocal/internal/HasLocalDpIFUserAttorney.h
Normal 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_ */
|
32
datapoollocal/internal/LocalDpManagerAttorney.h
Normal file
32
datapoollocal/internal/LocalDpManagerAttorney.h
Normal 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_ */
|
39
datapoollocal/internal/LocalPoolDataSetAttorney.h
Normal file
39
datapoollocal/internal/LocalPoolDataSetAttorney.h
Normal 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_ */
|
@ -1,10 +1,13 @@
|
||||
#ifndef FSFW_DATAPOOLLOCAL_LOCPOOLDEFINITIONS_H_
|
||||
#define FSFW_DATAPOOLLOCAL_LOCPOOLDEFINITIONS_H_
|
||||
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_
|
||||
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include "../datapool/PoolEntryIF.h"
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#include "../objectmanager/frameworkObjects.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @brief Type definition for local pool entries.
|
||||
*/
|
||||
@ -12,10 +15,21 @@ using lp_id_t = uint32_t;
|
||||
|
||||
namespace localpool {
|
||||
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 {
|
||||
static constexpr uint64_t INVALID_SID = -1;
|
||||
@ -26,8 +40,8 @@ union sid_t {
|
||||
sid_t(): raw(INVALID_SID) {}
|
||||
|
||||
sid_t(object_id_t objectId, uint32_t setId):
|
||||
objectId(objectId),
|
||||
ownerSetId(setId) {}
|
||||
objectId(objectId),
|
||||
ownerSetId(setId) {}
|
||||
|
||||
struct {
|
||||
object_id_t objectId ;
|
||||
@ -57,29 +71,30 @@ 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 {
|
||||
static constexpr uint64_t INVALID_GPID = -1;
|
||||
static constexpr uint64_t INVALID_GPID = -1;
|
||||
static constexpr uint32_t INVALID_OBJECT_ID = objects::NO_OBJECT;
|
||||
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
|
||||
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
|
||||
|
||||
gp_id_t(): raw(INVALID_GPID) {}
|
||||
gp_id_t(): raw(INVALID_GPID) {}
|
||||
|
||||
gp_id_t(object_id_t objectId, lp_id_t localPoolId):
|
||||
objectId(objectId),
|
||||
localPoolId(localPoolId) {}
|
||||
gp_id_t(object_id_t objectId, lp_id_t localPoolId):
|
||||
objectId(objectId),
|
||||
localPoolId(localPoolId) {}
|
||||
|
||||
struct {
|
||||
object_id_t objectId;
|
||||
lp_id_t localPoolId;
|
||||
};
|
||||
struct {
|
||||
object_id_t objectId;
|
||||
lp_id_t localPoolId;
|
||||
};
|
||||
|
||||
uint64_t raw;
|
||||
uint64_t raw;
|
||||
|
||||
bool notSet() const {
|
||||
return raw == INVALID_GPID;
|
||||
}
|
||||
bool notSet() const {
|
||||
return raw == INVALID_GPID;
|
||||
}
|
||||
|
||||
bool operator==(const sid_t& other) const {
|
||||
return raw == other.raw;
|
||||
@ -90,4 +105,4 @@ union gp_id_t {
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_LOCPOOLDEFINITIONS_H_ */
|
||||
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_ */
|
@ -2,7 +2,7 @@
|
||||
#include "AcceptsDeviceResponsesIF.h"
|
||||
#include "DeviceTmReportingWrapper.h"
|
||||
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../objectmanager/ObjectManager.h"
|
||||
#include "../storagemanager/StorageManagerIF.h"
|
||||
#include "../thermal/ThermalComponentIF.h"
|
||||
@ -13,9 +13,6 @@
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
#include "../datapoollocal/LocalPoolVariable.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||
object_id_t DeviceHandlerBase::rawDataReceiverId = 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),
|
||||
deviceCommunicationId(deviceCommunication), comCookie(comCookie),
|
||||
healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this),
|
||||
actionHelper(this, nullptr), hkManager(this, nullptr),
|
||||
actionHelper(this, nullptr), poolManager(this, nullptr),
|
||||
childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance),
|
||||
hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr),
|
||||
switchOffWasReported(false), childTransitionDelay(5000),
|
||||
@ -39,13 +36,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
|
||||
cookieInfo.state = COOKIE_UNUSED;
|
||||
cookieInfo.pendingCommand = deviceCommandMap.end();
|
||||
if (comCookie == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex
|
||||
<< 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
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
|
||||
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
|
||||
}
|
||||
if (this->fdirInstance == nullptr) {
|
||||
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId,
|
||||
@ -115,7 +107,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
||||
doGetRead();
|
||||
// This will be performed after datasets have been updated by the
|
||||
// custom device implementation.
|
||||
hkManager.performHkOperation();
|
||||
poolManager.performHkOperation();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -132,30 +124,24 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
communicationInterface = objectManager->get<DeviceCommunicationIF>(
|
||||
deviceCommunicationId);
|
||||
if (communicationInterface == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DeviceHandlerBase::initialize: Communication interface "
|
||||
"invalid." << std::endl;
|
||||
sif::error << "Make sure it is set up properly and implements"
|
||||
" DeviceCommunicationIF" << std::endl;
|
||||
#endif
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
|
||||
ObjectManagerIF::CHILD_INIT_FAILED,
|
||||
"Passed communication IF invalid");
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
result = communicationInterface->initializeInterface(comCookie);
|
||||
if (result != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DeviceHandlerBase::initialize: Initializing "
|
||||
"communication interface failed!" << std::endl;
|
||||
#endif
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
|
||||
ObjectManagerIF::CHILD_INIT_FAILED,
|
||||
"ComIF initialization failed");
|
||||
return result;
|
||||
}
|
||||
|
||||
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (IPCStore == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DeviceHandlerBase::initialize: IPC store not set up in "
|
||||
"factory." << std::endl;
|
||||
#endif
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
|
||||
ObjectManagerIF::CHILD_INIT_FAILED, "IPC Store not set up");
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
|
||||
@ -164,11 +150,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
AcceptsDeviceResponsesIF>(rawDataReceiverId);
|
||||
|
||||
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
|
||||
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"
|
||||
" and implements AcceptsDeviceResponsesIF" << std::endl;
|
||||
#else
|
||||
sif::printError("Make sure the raw receiver object is set up "
|
||||
"properly and implements AcceptsDeviceResponsesIF\n");
|
||||
#endif
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
@ -178,11 +168,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
if(powerSwitcherId != objects::NO_OBJECT) {
|
||||
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
|
||||
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
|
||||
sif::error << "DeviceHandlerBase::initialize: Power switcher "
|
||||
<< "object ID set but no valid object found." << std::endl;
|
||||
sif::error << "Make sure the raw receiver object is set up properly"
|
||||
<< " and implements PowerSwitchIF" << std::endl;
|
||||
sif::error << "Make sure the power switcher object is set up "
|
||||
<< "properly and implements PowerSwitchIF" << std::endl;
|
||||
#else
|
||||
sif::printError("Make sure the power switcher object is set up "
|
||||
"properly and implements PowerSwitchIF\n");
|
||||
#endif
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
}
|
||||
@ -216,7 +210,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = hkManager.initialize(commandQueue);
|
||||
result = poolManager.initialize(commandQueue);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -229,7 +223,8 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
thermalSet->heaterRequest.value =
|
||||
ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
thermalSet->commit(PoolVariableIF::VALID);
|
||||
thermalSet->heaterRequest.setValid(true);
|
||||
thermalSet->commit();
|
||||
}
|
||||
|
||||
}
|
||||
@ -285,7 +280,7 @@ void DeviceHandlerBase::readCommandQueue() {
|
||||
return;
|
||||
}
|
||||
|
||||
result = hkManager.handleHousekeepingMessage(&command);
|
||||
result = poolManager.handleHousekeepingMessage(&command);
|
||||
if (result == RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
@ -555,17 +550,17 @@ void DeviceHandlerBase::replyReturnvalueToCommand(ReturnValue_t status,
|
||||
|
||||
void DeviceHandlerBase::replyToCommand(ReturnValue_t status,
|
||||
uint32_t parameter) {
|
||||
//Check if we reply to a raw command.
|
||||
// Check if we reply to a raw command.
|
||||
if (cookieInfo.pendingCommand->first == RAW_COMMAND_ID) {
|
||||
if (status == NO_REPLY_EXPECTED) {
|
||||
status = RETURN_OK;
|
||||
}
|
||||
replyReturnvalueToCommand(status, parameter);
|
||||
//Always delete data from a raw command.
|
||||
// Always delete data from a raw command.
|
||||
IPCStore->deleteData(storedRawData);
|
||||
return;
|
||||
}
|
||||
//Check if we were externally commanded.
|
||||
// Check if we were externally commanded.
|
||||
if (cookieInfo.pendingCommand->second.sendReplyTo != NO_COMMANDER) {
|
||||
MessageQueueId_t queueId = cookieInfo.pendingCommand->second.sendReplyTo;
|
||||
if (status == NO_REPLY_EXPECTED) {
|
||||
@ -580,15 +575,17 @@ void DeviceHandlerBase::replyToCommand(ReturnValue_t status,
|
||||
|
||||
void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter,
|
||||
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()) {
|
||||
//Is most likely periodic reply. Silent return.
|
||||
return;
|
||||
}
|
||||
//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);
|
||||
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) {
|
||||
actionHelper.finish(info->sendReplyTo, iter->first, status);
|
||||
}
|
||||
@ -605,7 +602,7 @@ void DeviceHandlerBase::doSendWrite() {
|
||||
if (result == RETURN_OK) {
|
||||
cookieInfo.state = COOKIE_WRITE_SENT;
|
||||
} else {
|
||||
//always generate a failure event, so that FDIR knows what's up
|
||||
// always generate a failure event, so that FDIR knows what's up
|
||||
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result,
|
||||
cookieInfo.pendingCommand->first);
|
||||
replyToCommand(result);
|
||||
@ -720,10 +717,9 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
|
||||
case RETURN_OK:
|
||||
handleReply(receivedData, foundId, foundLen);
|
||||
if(foundLen == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!"
|
||||
" Packet parsing will be stuck." << std::endl;
|
||||
#endif
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"parseReply", ObjectManagerIF::CHILD_INIT_FAILED,
|
||||
"Found length is one, parsing might be stuck");
|
||||
}
|
||||
break;
|
||||
case APERIODIC_REPLY: {
|
||||
@ -734,6 +730,9 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
|
||||
foundId);
|
||||
}
|
||||
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
|
||||
sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!"
|
||||
" Packet parsing will be stuck." << std::endl;
|
||||
@ -746,7 +745,8 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
|
||||
case IGNORE_FULL_PACKET:
|
||||
return;
|
||||
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);
|
||||
triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen);
|
||||
break;
|
||||
@ -967,7 +967,8 @@ ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) {
|
||||
}
|
||||
|
||||
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) {
|
||||
return _MODE_TO_ON;
|
||||
}
|
||||
@ -1290,12 +1291,11 @@ void DeviceHandlerBase::buildInternalCommand(void) {
|
||||
if (mode == MODE_NORMAL) {
|
||||
result = buildNormalDeviceCommand(&deviceCommandId);
|
||||
if (result == BUSY) {
|
||||
//so we can track misconfigurations
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << std::hex << getObjectId()
|
||||
<< ": DHB::buildInternalCommand: Busy" << std::dec
|
||||
<< std::endl;
|
||||
#endif
|
||||
// so we can track misconfigurations
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"buildInternalCommand",
|
||||
HasReturnvaluesIF::RETURN_FAILED,
|
||||
"Busy.");
|
||||
result = NOTHING_TO_SEND; //no need to report this
|
||||
}
|
||||
}
|
||||
@ -1319,12 +1319,15 @@ void DeviceHandlerBase::buildInternalCommand(void) {
|
||||
if (iter == deviceCommandMap.end()) {
|
||||
result = COMMAND_NOT_SUPPORTED;
|
||||
} else if (iter->second.isExecuting) {
|
||||
//so we can track misconfigurations
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << std::hex << getObjectId()
|
||||
<< ": DHB::buildInternalCommand: Command "
|
||||
<< deviceCommandId << " isExecuting" << std::dec
|
||||
<< std::endl;
|
||||
#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
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"buildInternalCommand",
|
||||
HasReturnvaluesIF::RETURN_FAILED,
|
||||
output);
|
||||
#endif
|
||||
// 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
|
||||
@ -1418,7 +1421,7 @@ void DeviceHandlerBase::performOperationHook() {
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(
|
||||
LocalDataPool &localDataPoolMap,
|
||||
localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) {
|
||||
if(thermalSet != nullptr) {
|
||||
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
|
||||
@ -1429,18 +1432,13 @@ ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
|
||||
return &hkManager;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
||||
// In this function, the task handle should be valid if the task
|
||||
// was implemented correctly. We still check to be 1000 % sure :-)
|
||||
if(executingTask != nullptr) {
|
||||
pstIntervalMs = executingTask->getPeriodMs();
|
||||
}
|
||||
this->hkManager.initializeAfterTaskCreation();
|
||||
this->poolManager.initializeAfterTaskCreation();
|
||||
|
||||
if(setStartupImmediately) {
|
||||
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;
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "DeviceHandlerFailureIsolation.h"
|
||||
#include "DeviceHandlerThermalSet.h"
|
||||
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../serviceinterface/serviceInterfaceDefintions.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
@ -512,11 +514,14 @@ protected:
|
||||
* @param localDataPoolMap
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initializeLocalDataPool(LocalDataPool& localDataPoolMap,
|
||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
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
|
||||
@ -646,7 +651,7 @@ protected:
|
||||
/** Action helper for HasActionsIF */
|
||||
ActionHelper actionHelper;
|
||||
/** Housekeeping Manager */
|
||||
LocalDataPoolManager hkManager;
|
||||
LocalDataPoolManager poolManager;
|
||||
|
||||
/**
|
||||
* @brief Information about commands
|
||||
@ -1111,7 +1116,7 @@ private:
|
||||
/**
|
||||
* @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!!
|
||||
* (it is _MODE_POWER_DOWN during this modes)
|
||||
@ -1190,7 +1195,8 @@ private:
|
||||
* Check if the RMAP sendWrite action was successful.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
void doGetWrite(void);
|
||||
@ -1206,9 +1212,9 @@ private:
|
||||
/**
|
||||
* Check the getRead reply and the contained data.
|
||||
*
|
||||
* If data was received scanForReply() and, if successful, handleReply() are called.
|
||||
* If the current mode is @c MODE_RAW, the received packet is sent to the commanding object
|
||||
* via commandQueue.
|
||||
* If data was received scanForReply() and, if successful, handleReply()
|
||||
* are called. If the current mode is @c MODE_RAW, the received packet
|
||||
* is sent to the commanding object via commandQueue.
|
||||
*/
|
||||
void doGetRead(void);
|
||||
|
||||
@ -1227,7 +1233,7 @@ private:
|
||||
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);
|
||||
|
||||
@ -1247,6 +1253,11 @@ private:
|
||||
|
||||
void handleTransitionToOnMode(Mode_t commandedMode,
|
||||
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_ */
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
#include "DeviceHandlerMessage.h"
|
||||
|
||||
#include "../datapoollocal/localPoolDefinitions.h"
|
||||
#include "../action/HasActionsIF.h"
|
||||
#include "../datapoollocal/locPoolDefinitions.h"
|
||||
#include "../events/Event.h"
|
||||
#include "../modes/HasModesIF.h"
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
|
@ -162,9 +162,15 @@ void EventManager::printEvent(EventMessage* message) {
|
||||
#endif
|
||||
|
||||
void EventManager::lockMutex() {
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
}
|
||||
|
||||
void EventManager::unlockMutex() {
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
||||
void EventManager::setMutexTimeout(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) {
|
||||
this->timeoutType = timeoutType;
|
||||
this->timeoutMs = timeoutMs;
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
EventManager(object_id_t setObjectId);
|
||||
virtual ~EventManager();
|
||||
|
||||
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
||||
|
||||
MessageQueueId_t getEventReportQueue();
|
||||
|
||||
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
|
||||
@ -51,6 +53,8 @@ protected:
|
||||
std::map<MessageQueueId_t, EventMatchTree> listenerList;
|
||||
|
||||
MutexIF* mutex = nullptr;
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t timeoutMs = 20;
|
||||
|
||||
static const uint8_t N_POOLS = 3;
|
||||
LocalPool factoryBackend;
|
||||
|
1
fsfw.mk
1
fsfw.mk
@ -10,6 +10,7 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/internal/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp)
|
||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "arrayprinter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include <bitset>
|
||||
|
||||
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 << "[";
|
||||
#else
|
||||
sif::printInfo("Printing data with size %zu: [", size);
|
||||
#endif
|
||||
if(type == OutputType::HEX) {
|
||||
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::endl;
|
||||
#else
|
||||
// how much memory to reserve for printout?
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -54,6 +58,8 @@ void arrayprinter::printDec(const uint8_t *data, size_t size,
|
||||
}
|
||||
}
|
||||
sif::info << "]" << std::endl;
|
||||
#else
|
||||
// how much memory to reserve for printout?
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -65,5 +71,7 @@ void arrayprinter::printBin(const uint8_t *data, size_t size) {
|
||||
std::bitset<8>(data[i]) << ",\n" << std::flush;
|
||||
}
|
||||
sif::info << "]" << std::endl;
|
||||
#else
|
||||
// how much memory to reserve for printout?
|
||||
#endif
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
|
||||
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
|
||||
|
||||
#include "../datapoollocal/locPoolDefinitions.h"
|
||||
#include "../datapoollocal/localPoolDefinitions.h"
|
||||
#include "../ipc/CommandMessage.h"
|
||||
#include "../ipc/FwMessageTypes.h"
|
||||
#include "../objectmanager/frameworkObjects.h"
|
||||
|
@ -21,11 +21,11 @@ public:
|
||||
InternalErrorDataset(object_id_t objectId):
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
|
||||
uint32_t messageQueueDepth): SystemObject(setObjectId),
|
||||
@ -23,13 +23,13 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
||||
internalErrorDataset.read(INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
internalErrorDataset.read(timeoutType, timeoutMs);
|
||||
|
||||
uint32_t newQueueHits = getAndResetQueueHits();
|
||||
uint32_t newTmHits = getAndResetTmHits();
|
||||
uint32_t newStoreHits = getAndResetStoreHits();
|
||||
|
||||
#if FSFW_ENHANCED_PRINTOUT == 1
|
||||
#if FSFW_VERBOSE_LEVEL == 1
|
||||
if(diagnosticPrintout) {
|
||||
if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
||||
#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 << "TM errors: " << newTmHits << 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
|
||||
}
|
||||
}
|
||||
@ -46,8 +51,8 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
||||
internalErrorDataset.queueHits.value += newQueueHits;
|
||||
internalErrorDataset.storeHits.value += newStoreHits;
|
||||
internalErrorDataset.tmHits.value += newTmHits;
|
||||
|
||||
internalErrorDataset.commit(INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
internalErrorDataset.commit(timeoutType, timeoutMs);
|
||||
|
||||
poolManager.performHkOperation();
|
||||
|
||||
@ -69,7 +74,7 @@ void InternalErrorReporter::lostTm() {
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetQueueHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = queueHits;
|
||||
queueHits = 0;
|
||||
mutex->unlockMutex();
|
||||
@ -78,21 +83,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() {
|
||||
|
||||
uint32_t InternalErrorReporter::getQueueHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = queueHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementQueueHits() {
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
queueHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetTmHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = tmHits;
|
||||
tmHits = 0;
|
||||
mutex->unlockMutex();
|
||||
@ -101,14 +106,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() {
|
||||
|
||||
uint32_t InternalErrorReporter::getTmHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = tmHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementTmHits() {
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
tmHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
@ -119,7 +124,7 @@ void InternalErrorReporter::storeFull() {
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetStoreHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = storeHits;
|
||||
storeHits = 0;
|
||||
mutex->unlockMutex();
|
||||
@ -128,14 +133,14 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() {
|
||||
|
||||
uint32_t InternalErrorReporter::getStoreHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = storeHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementStoreHits() {
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
storeHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
@ -149,7 +154,7 @@ MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
|
||||
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(errorPoolIds::TM_HITS,
|
||||
new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS,
|
||||
@ -162,10 +167,6 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
|
||||
return &poolManager;
|
||||
}
|
||||
|
||||
dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const {
|
||||
return this->executingTask->getPeriodMs();
|
||||
}
|
||||
@ -190,3 +191,12 @@ ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
|
||||
return poolManager.initializeAfterTaskCreation();
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) {
|
||||
this->timeoutType = timeoutType;
|
||||
this->timeoutMs = timeoutMs;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
|
||||
return &poolManager;
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ class InternalErrorReporter: public SystemObject,
|
||||
public InternalErrorReporterIF,
|
||||
public HasLocalDataPoolIF {
|
||||
public:
|
||||
static constexpr uint8_t INTERNAL_ERROR_MUTEX_TIMEOUT = 20;
|
||||
|
||||
InternalErrorReporter(object_id_t setObjectId,
|
||||
uint32_t messageQueueDepth = 5);
|
||||
@ -34,16 +33,19 @@ public:
|
||||
*/
|
||||
void setDiagnosticPrintout(bool enable);
|
||||
|
||||
void setMutexTimeout(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs);
|
||||
|
||||
virtual ~InternalErrorReporter();
|
||||
|
||||
virtual object_id_t getObjectId() const override;
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
virtual ReturnValue_t initializeLocalDataPool(
|
||||
LocalDataPool& localDataPoolMap,
|
||||
localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual dur_millis_t getPeriodicOperationFrequency() const override;
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
LocalDataPoolManager* getHkManagerHandle() override;
|
||||
|
||||
virtual ReturnValue_t initialize() override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
@ -61,7 +63,11 @@ protected:
|
||||
LocalDataPoolManager poolManager;
|
||||
|
||||
PeriodicTaskIF* executingTask = nullptr;
|
||||
|
||||
MutexIF* mutex = nullptr;
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t timeoutMs = 20;
|
||||
|
||||
sid_t internalErrorSid;
|
||||
InternalErrorDataset internalErrorDataset;
|
||||
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
/**
|
||||
* Different types of timeout for the mutex lock.
|
||||
*/
|
||||
enum TimeoutType {
|
||||
enum class TimeoutType {
|
||||
POLLING, //!< If mutex is not available, return immediately
|
||||
WAITING, //!< Wait a specified time for the mutex to become available
|
||||
BLOCKING //!< Block indefinitely until the mutex becomes available.
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "MonitoringIF.h"
|
||||
#include "MonitoringMessageContent.h"
|
||||
|
||||
#include "../datapoollocal/locPoolDefinitions.h"
|
||||
#include "../datapoollocal/localPoolDefinitions.h"
|
||||
#include "../events/EventManagerIF.h"
|
||||
#include "../parameters/HasParametersIF.h"
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
#ifndef MONITORINGMESSAGECONTENT_H_
|
||||
#define MONITORINGMESSAGECONTENT_H_
|
||||
#ifndef FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_
|
||||
#define FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_
|
||||
|
||||
#include "HasMonitorsIF.h"
|
||||
#include "MonitoringIF.h"
|
||||
#include "../datapoollocal/locPoolDefinitions.h"
|
||||
|
||||
#include "../datapoollocal/localPoolDefinitions.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../serialize/SerialBufferAdapter.h"
|
||||
#include "../serialize/SerialFixedArrayListAdapter.h"
|
||||
@ -85,4 +86,4 @@ private:
|
||||
template<typename T>
|
||||
object_id_t MonitoringReportContent<T>::timeStamperId = 0;
|
||||
|
||||
#endif /* MONITORINGMESSAGECONTENT_H_ */
|
||||
#endif /* FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_ */
|
||||
|
@ -163,7 +163,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
||||
if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -178,7 +178,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
if (timeMutex == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
||||
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
|
||||
ReturnValue_t result = timeMutex->lockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -217,7 +217,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
if(timeMutex == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
|
||||
ReturnValue_t result = timeMutex->lockMutex();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
@ -4,16 +4,16 @@
|
||||
Mutex::Mutex() {}
|
||||
|
||||
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
if(timeoutType == MutexIF::BLOCKING) {
|
||||
if(timeoutType == TimeoutType::BLOCKING) {
|
||||
mutex.lock();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else if(timeoutType == MutexIF::POLLING) {
|
||||
else if(timeoutType == TimeoutType::POLLING) {
|
||||
if(mutex.try_lock()) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
}
|
||||
else if(timeoutMs > MutexIF::POLLING){
|
||||
else if(timeoutType == TimeoutType::WAITING){
|
||||
auto chronoMs = std::chrono::milliseconds(timeoutMs);
|
||||
if(mutex.try_lock_for(chronoMs)) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
@ -22,7 +22,6 @@ public:
|
||||
|
||||
std::timed_mutex* getMutexHandle();
|
||||
private:
|
||||
//bool locked = false;
|
||||
std::timed_mutex mutex;
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
#include "BinarySemaphore.h"
|
||||
#include "../../serviceinterface/ServiceInterfacePrinter.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
extern "C" {
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
}
|
||||
|
||||
|
||||
BinarySemaphore::BinarySemaphore() {
|
||||
// Using unnamed semaphores for now
|
||||
@ -113,7 +114,8 @@ uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) {
|
||||
}
|
||||
else if(result != 0 and errno == EINVAL) {
|
||||
// Could be called from interrupt, use lightweight printf
|
||||
printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n");
|
||||
sif::printError("BinarySemaphore::getSemaphoreCounter: "
|
||||
"Invalid semaphore\n");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
@ -128,13 +130,17 @@ void BinarySemaphore::initSemaphore(uint8_t initCount) {
|
||||
switch(errno) {
|
||||
case(EINVAL):
|
||||
// Value exceeds SEM_VALUE_MAX
|
||||
case(ENOSYS):
|
||||
// System does not support process-shared semaphores
|
||||
case(ENOSYS): {
|
||||
// System does not support process-shared semaphores
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "BinarySemaphore: Init failed with" << strerror(errno)
|
||||
<< std::endl;
|
||||
sif::error << "BinarySemaphore: Init failed with "
|
||||
<< strerror(errno) << std::endl;
|
||||
#else
|
||||
sif::printError("BinarySemaphore: Init failed with %s\n",
|
||||
strerror(errno));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
||||
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -197,7 +197,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
if(timeMutex==NULL){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING);
|
||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
@ -209,13 +209,13 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::checkOrCreateClockMutex(){
|
||||
if(timeMutex==NULL){
|
||||
if(timeMutex == nullptr){
|
||||
MutexFactory* mutexFactory = MutexFactory::instance();
|
||||
if (mutexFactory == NULL) {
|
||||
if (mutexFactory == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
timeMutex = mutexFactory->createMutex();
|
||||
if (timeMutex == NULL) {
|
||||
if (timeMutex == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#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):
|
||||
maxCount(maxCount), initCount(initCount) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "MessageQueue.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
|
||||
#include <fstream>
|
||||
@ -121,14 +121,16 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
default: {
|
||||
// Failed either the first time or the second time
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex
|
||||
<< name << std::dec << " failed with status: "
|
||||
<< strerror(errno) << std::endl;
|
||||
sif::error << "MessageQueue::MessageQueue: Creating Queue " << name
|
||||
<< " failed with status: " << strerror(errno) << std::endl;
|
||||
#else
|
||||
sif::printError("MessageQueue::MessageQueue: Creating Queue %s"
|
||||
" failed with status: %s\n", name, strerror(errno));
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "PosixThread.h"
|
||||
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
@ -146,16 +146,22 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
||||
strerror(status) << std::endl;
|
||||
#endif
|
||||
if(errno == ENOMEM) {
|
||||
uint64_t stackMb = stackSize/10e6;
|
||||
size_t stackMb = stackSize/10e6;
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Insufficient memory for"
|
||||
" the requested " << stackMb << " MB" << std::endl;
|
||||
#else
|
||||
sif::printError("PosixThread::createTask: Insufficient memory for "
|
||||
"the requested %zu MB\n", stackMb);
|
||||
#endif
|
||||
}
|
||||
else if(errno == EINVAL) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PosixThread::createTask: Wrong alignment argument!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printError("PosixThread::createTask: "
|
||||
"Wrong alignment argument!\n");
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "TcUnixUdpPollingTask.h"
|
||||
#include "../../globalfunctions/arrayprinter.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId,
|
||||
object_id_t tmtcUnixUdpBridge, size_t frameSize,
|
||||
double timeoutSeconds): SystemObject(objectId),
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "TmTcUnixUdpBridge.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
#include "../../ipc/MutexHelper.h"
|
||||
|
||||
#include <errno.h>
|
||||
@ -188,12 +188,16 @@ void TmTcUnixUdpBridge::handleBindError() {
|
||||
|
||||
void TmTcUnixUdpBridge::handleSendError() {
|
||||
switch(errno) {
|
||||
default:
|
||||
default: {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmTcUnixBridge::handleSendError: "
|
||||
<< strerror(errno) << std::endl;
|
||||
#else
|
||||
sif::printError("TmTcUnixBridge::handleSendError: %s\n",
|
||||
strerror(errno));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){
|
||||
|
@ -30,11 +30,11 @@ Mutex::~Mutex() {
|
||||
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType =
|
||||
TimeoutType::BLOCKING, uint32_t timeoutMs) {
|
||||
rtems_status_code status = RTEMS_INVALID_ID;
|
||||
if(timeoutMs == MutexIF::TimeoutType::BLOCKING) {
|
||||
if(timeoutType == MutexIF::TimeoutType::BLOCKING) {
|
||||
status = rtems_semaphore_obtain(mutexId,
|
||||
RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
}
|
||||
else if(timeoutMs == MutexIF::TimeoutType::POLLING) {
|
||||
else if(timeoutType == MutexIF::TimeoutType::POLLING) {
|
||||
timeoutMs = RTEMS_NO_TIMEOUT;
|
||||
status = rtems_semaphore_obtain(mutexId,
|
||||
RTEMS_NO_WAIT, 0);
|
||||
|
@ -65,8 +65,8 @@ ReturnValue_t Fuse::check() {
|
||||
set.read();
|
||||
if (!healthHelper.healthTable->isHealthy(getObjectId())) {
|
||||
setAllMonitorsToUnchecked();
|
||||
set.commit(PoolVariableIF::INVALID);
|
||||
return RETURN_OK;
|
||||
set.setValidity(false, true);
|
||||
return set.commit();
|
||||
}
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
checkFuseState();
|
||||
@ -206,7 +206,8 @@ float Fuse::getPower() {
|
||||
|
||||
void Fuse::setDataPoolEntriesInvalid() {
|
||||
set.read();
|
||||
set.commit(PoolVariableIF::INVALID);
|
||||
set.setValidity(false, true);
|
||||
set.commit();
|
||||
}
|
||||
|
||||
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
|
@ -97,7 +97,8 @@ void PowerSensor::checkCommandQueue() {
|
||||
|
||||
void PowerSensor::setDataPoolEntriesInvalid() {
|
||||
powerSensorSet.read();
|
||||
powerSensorSet.commit(PoolVariableIF::INVALID);
|
||||
powerSensorSet.setValidity(false, true);
|
||||
powerSensorSet.commit();
|
||||
}
|
||||
|
||||
float PowerSensor::getPower() {
|
||||
|
@ -3,7 +3,9 @@
|
||||
ReturnValue_t unitt::put_error(std::string errorId) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Unit Tester error: Failed at test ID "
|
||||
<< errorId << "\n" << std::flush;
|
||||
#endif
|
||||
<< errorId << std::endl;
|
||||
#else
|
||||
sif::printError("Unit Tester error: Failed at test ID 0x%08x", errorId);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
@ -2,9 +2,10 @@
|
||||
#define UNITTEST_INTERNAL_UNITTDEFINITIONS_H_
|
||||
|
||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace tv {
|
||||
// POD test values
|
||||
|
@ -13,7 +13,7 @@
|
||||
void testmutex::testMutex() {
|
||||
std::string id = "[testMutex]";
|
||||
MutexIF* mutex = MutexFactory::instance()->createMutex();
|
||||
auto result = mutex->lockMutex(MutexIF::POLLING);
|
||||
auto result = mutex->lockMutex(MutexIF::TimeoutType::POLLING);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
unitt::put_error(id);
|
||||
}
|
||||
|
@ -2,5 +2,6 @@ add_subdirectory(action)
|
||||
add_subdirectory(container)
|
||||
add_subdirectory(osal)
|
||||
add_subdirectory(serialize)
|
||||
add_subdirectory(datapoollocal)
|
||||
add_subdirectory(storagemanager)
|
||||
|
||||
|
@ -4,9 +4,12 @@
|
||||
|
||||
#include <fsfw/action/ActionHelper.h>
|
||||
#include <fsfw/ipc/CommandMessage.h>
|
||||
#include <fsfw/unittest/tests/mocks/MessageQueueMockBase.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
|
||||
TEST_CASE( "Action Helper" , "[ActionHelper]") {
|
||||
ActionHelperOwnerMockBase testDhMock;
|
||||
|
@ -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_ */
|
||||
|
@ -1,45 +1,48 @@
|
||||
//#include <fsfw/container/PlacementFactory.h>
|
||||
//#include <fsfw/storagemanager/LocalPool.h>
|
||||
//#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
//#include <fsfw/container/ArrayList.h>
|
||||
//
|
||||
//#include <catch2/catch.hpp>
|
||||
//#include "../../core/CatchDefinitions.h"
|
||||
//
|
||||
//TEST_CASE( "PlacementFactory Tests", "[TestPlacementFactory]") {
|
||||
// INFO("PlacementFactory Tests");
|
||||
//
|
||||
// const uint16_t element_sizes[3] = {sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t)};
|
||||
// const uint16_t n_elements[3] = {1, 1, 1};
|
||||
// LocalPool<3> storagePool(0x1, element_sizes, n_elements, false, true);
|
||||
// PlacementFactory factory(&storagePool);
|
||||
//
|
||||
// SECTION("Pool overload"){
|
||||
// store_address_t address;
|
||||
// uint8_t* ptr = nullptr;
|
||||
// REQUIRE(storagePool.getFreeElement(&address, sizeof(ArrayList<uint32_t, uint16_t>), &ptr)
|
||||
// == static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
|
||||
// ArrayList<uint32_t, uint16_t>* list2 = factory.generate<ArrayList<uint32_t, uint16_t> >(80);
|
||||
// REQUIRE(list2 == nullptr);
|
||||
// }
|
||||
//
|
||||
// SECTION("Test generate and destroy"){
|
||||
// uint64_t* number = factory.generate<uint64_t>(32000);
|
||||
// REQUIRE(number != nullptr);
|
||||
// REQUIRE(*number == 32000);
|
||||
// store_address_t address;
|
||||
// uint8_t* ptr = nullptr;
|
||||
// REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
|
||||
// == static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
|
||||
// uint64_t* number2 = factory.generate<uint64_t>(12345);
|
||||
// REQUIRE(number2 == nullptr);
|
||||
// REQUIRE(factory.destroy(number) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
|
||||
// REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
|
||||
// == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
|
||||
// REQUIRE(storagePool.deleteData(address) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
|
||||
//
|
||||
// //Check that PlacementFactory checks for nullptr
|
||||
// ptr = nullptr;
|
||||
// REQUIRE(factory.destroy(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
|
||||
// }
|
||||
//}
|
||||
#include <fsfw/container/PlacementFactory.h>
|
||||
#include <fsfw/storagemanager/LocalPool.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/container/ArrayList.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <unittest/core/CatchDefinitions.h>
|
||||
|
||||
TEST_CASE( "PlacementFactory Tests", "[TestPlacementFactory]") {
|
||||
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 n_elements[3] = {1, 1, 1};
|
||||
LocalPool storagePool(0x1, poolCfg, false, true);
|
||||
PlacementFactory factory(&storagePool);
|
||||
|
||||
SECTION("Pool overload"){
|
||||
store_address_t address;
|
||||
uint8_t* ptr = nullptr;
|
||||
REQUIRE(storagePool.getFreeElement(&address, sizeof(ArrayList<uint32_t, uint16_t>), &ptr)
|
||||
== static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
|
||||
ArrayList<uint32_t, uint16_t>* list2 = factory.generate<ArrayList<uint32_t, uint16_t> >(80);
|
||||
REQUIRE(list2 == nullptr);
|
||||
}
|
||||
|
||||
SECTION("Test generate and destroy"){
|
||||
uint64_t* number = factory.generate<uint64_t>(32000);
|
||||
REQUIRE(number != nullptr);
|
||||
REQUIRE(*number == 32000);
|
||||
store_address_t address;
|
||||
uint8_t* ptr = nullptr;
|
||||
REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
|
||||
== static_cast<int>(StorageManagerIF::DATA_TOO_LARGE));
|
||||
uint64_t* number2 = factory.generate<uint64_t>(12345);
|
||||
REQUIRE(number2 == nullptr);
|
||||
REQUIRE(factory.destroy(number) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
|
||||
REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr)
|
||||
== static_cast<int>(HasReturnvaluesIF::RETURN_OK));
|
||||
REQUIRE(storagePool.deleteData(address) == static_cast<int>(HasReturnvaluesIF::RETURN_OK));
|
||||
|
||||
//Check that PlacementFactory checks for nullptr
|
||||
ptr = nullptr;
|
||||
REQUIRE(factory.destroy(ptr) == static_cast<int>(HasReturnvaluesIF::RETURN_FAILED));
|
||||
}
|
||||
}
|
||||
|
6
unittest/tests/datapoollocal/CMakeLists.txt
Normal file
6
unittest/tests/datapoollocal/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
LocalPoolVariableTest.cpp
|
||||
LocalPoolVectorTest.cpp
|
||||
DataSetTest.cpp
|
||||
LocalPoolManagerTest.cpp
|
||||
)
|
23
unittest/tests/datapoollocal/DataSetTest.cpp
Normal file
23
unittest/tests/datapoollocal/DataSetTest.cpp
Normal 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
122
unittest/tests/datapoollocal/LocalPoolManagerTest.cpp
Normal file
122
unittest/tests/datapoollocal/LocalPoolManagerTest.cpp
Normal 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));
|
||||
}
|
||||
}
|
||||
|
197
unittest/tests/datapoollocal/LocalPoolOwnerBase.h
Normal file
197
unittest/tests/datapoollocal/LocalPoolOwnerBase.h
Normal 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_ */
|
123
unittest/tests/datapoollocal/LocalPoolVariableTest.cpp
Normal file
123
unittest/tests/datapoollocal/LocalPoolVariableTest.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
120
unittest/tests/datapoollocal/LocalPoolVectorTest.cpp
Normal file
120
unittest/tests/datapoollocal/LocalPoolVectorTest.cpp
Normal 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
20
unittest/tests/mocks/HkReceiverMock.h
Normal file
20
unittest/tests/mocks/HkReceiverMock.h
Normal 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_ */
|
121
unittest/tests/mocks/MessageQueueMockBase.h
Normal file
121
unittest/tests/mocks/MessageQueueMockBase.h
Normal 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_ */
|
@ -1,161 +1,161 @@
|
||||
//#include <fsfw/storagemanager/LocalPool.h>
|
||||
//#include <catch2/catch.hpp>
|
||||
//#include "../../core/CatchDefinitions.h"
|
||||
//#include <array>
|
||||
//
|
||||
//TEST_CASE( "New Accessor" , "[NewAccessor]") {
|
||||
// uint16_t numberOfElements[1] = {1};
|
||||
// uint16_t sizeofElements[1] = {10};
|
||||
// LocalPool<1> SimplePool = LocalPool<1>(0, sizeofElements, numberOfElements);
|
||||
// std::array<uint8_t, 20> testDataArray;
|
||||
// std::array<uint8_t, 20> receptionArray;
|
||||
// store_address_t testStoreId;
|
||||
// ReturnValue_t result = retval::CATCH_FAILED;
|
||||
//
|
||||
// for(size_t i = 0; i < testDataArray.size(); i++) {
|
||||
// testDataArray[i] = i;
|
||||
// }
|
||||
// size_t size = 10;
|
||||
//
|
||||
// SECTION ("Simple tests getter functions") {
|
||||
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// auto resultPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
// resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
// CHECK(resultPair.second.getId() == testStoreId);
|
||||
// CHECK(resultPair.second.size() == 10);
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
//
|
||||
// std::copy(resultPair.second.data(), resultPair.second.data() +
|
||||
// resultPair.second.size(), receptionArray.data());
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// auto resultPairLoc = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPairLoc.first == retval::CATCH_OK);
|
||||
// // data should be deleted when accessor goes out of scope.
|
||||
// }
|
||||
// resultPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
//
|
||||
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// {
|
||||
// ConstStorageAccessor constAccessor(testStoreId);
|
||||
// result = SimplePool.getData(testStoreId, constAccessor);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// constAccessor.getDataCopy(receptionArray.data(), 20);
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
// // likewise, data should be deleted when accessor gets out of scope.
|
||||
// }
|
||||
// resultPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
//
|
||||
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
// {
|
||||
// resultPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
// resultPair.second.release();
|
||||
// // now data should not be deleted anymore
|
||||
// }
|
||||
// resultPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
// resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// SECTION("Simple tests modify functions") {
|
||||
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// {
|
||||
// StorageAccessor accessor(testStoreId);
|
||||
// result = SimplePool.modifyData(testStoreId, accessor);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// CHECK(accessor.getId() == testStoreId);
|
||||
// CHECK(accessor.size() == 10);
|
||||
// accessor.getDataCopy(receptionArray.data(), 20);
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
// std::copy(accessor.data(), accessor.data() +
|
||||
// accessor.size(), receptionArray.data());
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
// // data should be deleted when accessor goes out of scope
|
||||
// }
|
||||
// auto resultPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
//
|
||||
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// {
|
||||
// auto resultPairLoc = SimplePool.modifyData(testStoreId);
|
||||
// REQUIRE(resultPairLoc.first == retval::CATCH_OK);
|
||||
// CHECK(resultPairLoc.second.getId() == testStoreId);
|
||||
// CHECK(resultPairLoc.second.size() == 10);
|
||||
// resultPairLoc.second.getDataCopy(receptionArray.data(), 20);
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
// std::copy(resultPairLoc.second.data(), resultPairLoc.second.data() +
|
||||
// resultPairLoc.second.size(), receptionArray.data());
|
||||
// for(size_t i = 0; i < size; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
// resultPairLoc.second.release();
|
||||
// // data should not be deleted when accessor goes out of scope
|
||||
// }
|
||||
// resultPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// SECTION("Write tests") {
|
||||
// result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// {
|
||||
// auto resultPair = SimplePool.modifyData(testStoreId);
|
||||
// REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
// testDataArray[9] = 42;
|
||||
// resultPair.second.write(testDataArray.data(), 10, 0);
|
||||
// // now data should not be deleted
|
||||
// resultPair.second.release();
|
||||
// }
|
||||
// auto resultConstPair = SimplePool.getData(testStoreId);
|
||||
// REQUIRE(resultConstPair.first == retval::CATCH_OK);
|
||||
//
|
||||
// resultConstPair.second.getDataCopy(receptionArray.data(), 10);
|
||||
// for(size_t i = 0; i < size-1; i++) {
|
||||
// CHECK(receptionArray[i] == i );
|
||||
// }
|
||||
// CHECK(receptionArray[9] == 42 );
|
||||
//
|
||||
// auto resultPair = SimplePool.modifyData(testStoreId);
|
||||
// REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
// result = resultPair.second.write(testDataArray.data(), 20, 0);
|
||||
// REQUIRE(result == retval::CATCH_FAILED);
|
||||
// result = resultPair.second.write(testDataArray.data(), 10, 5);
|
||||
// REQUIRE(result == retval::CATCH_FAILED);
|
||||
//
|
||||
// memset(testDataArray.data(), 42, 5);
|
||||
// result = resultPair.second.write(testDataArray.data(), 5, 5);
|
||||
// REQUIRE(result == retval::CATCH_OK);
|
||||
// resultConstPair = SimplePool.getData(testStoreId);
|
||||
// resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
// for(size_t i = 5; i < 10; i++) {
|
||||
// CHECK(receptionArray[i] == 42 );
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//}
|
||||
#include <fsfw/storagemanager/LocalPool.h>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <unittest/core/CatchDefinitions.h>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
TEST_CASE( "New Accessor" , "[NewAccessor]") {
|
||||
LocalPool::LocalPoolConfig poolCfg = {{1, 10}};
|
||||
LocalPool SimplePool = LocalPool(0, poolCfg);
|
||||
std::array<uint8_t, 20> testDataArray;
|
||||
std::array<uint8_t, 20> receptionArray;
|
||||
store_address_t testStoreId;
|
||||
ReturnValue_t result = retval::CATCH_FAILED;
|
||||
|
||||
for(size_t i = 0; i < testDataArray.size(); i++) {
|
||||
testDataArray[i] = i;
|
||||
}
|
||||
size_t size = 10;
|
||||
|
||||
SECTION ("Simple tests getter functions") {
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
auto resultPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
CHECK(resultPair.second.getId() == testStoreId);
|
||||
CHECK(resultPair.second.size() == 10);
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
|
||||
std::copy(resultPair.second.data(), resultPair.second.data() +
|
||||
resultPair.second.size(), receptionArray.data());
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
|
||||
{
|
||||
auto resultPairLoc = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPairLoc.first == retval::CATCH_OK);
|
||||
// data should be deleted when accessor goes out of scope.
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
{
|
||||
ConstStorageAccessor constAccessor(testStoreId);
|
||||
result = SimplePool.getData(testStoreId, constAccessor);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
constAccessor.getDataCopy(receptionArray.data(), 20);
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
// likewise, data should be deleted when accessor gets out of scope.
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
{
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
resultPair.second.release();
|
||||
// now data should not be deleted anymore
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SECTION("Simple tests modify functions") {
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
{
|
||||
StorageAccessor accessor(testStoreId);
|
||||
result = SimplePool.modifyData(testStoreId, accessor);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
CHECK(accessor.getId() == testStoreId);
|
||||
CHECK(accessor.size() == 10);
|
||||
accessor.getDataCopy(receptionArray.data(), 20);
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
std::copy(accessor.data(), accessor.data() +
|
||||
accessor.size(), receptionArray.data());
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
// data should be deleted when accessor goes out of scope
|
||||
}
|
||||
auto resultPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
{
|
||||
auto resultPairLoc = SimplePool.modifyData(testStoreId);
|
||||
REQUIRE(resultPairLoc.first == retval::CATCH_OK);
|
||||
CHECK(resultPairLoc.second.getId() == testStoreId);
|
||||
CHECK(resultPairLoc.second.size() == 10);
|
||||
resultPairLoc.second.getDataCopy(receptionArray.data(), 20);
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
std::copy(resultPairLoc.second.data(), resultPairLoc.second.data() +
|
||||
resultPairLoc.second.size(), receptionArray.data());
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
resultPairLoc.second.release();
|
||||
// data should not be deleted when accessor goes out of scope
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
}
|
||||
|
||||
|
||||
SECTION("Write tests") {
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
{
|
||||
auto resultPair = SimplePool.modifyData(testStoreId);
|
||||
REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
testDataArray[9] = 42;
|
||||
resultPair.second.write(testDataArray.data(), 10, 0);
|
||||
// now data should not be deleted
|
||||
resultPair.second.release();
|
||||
}
|
||||
auto resultConstPair = SimplePool.getData(testStoreId);
|
||||
REQUIRE(resultConstPair.first == retval::CATCH_OK);
|
||||
|
||||
resultConstPair.second.getDataCopy(receptionArray.data(), 10);
|
||||
for(size_t i = 0; i < size-1; i++) {
|
||||
CHECK(receptionArray[i] == i );
|
||||
}
|
||||
CHECK(receptionArray[9] == 42 );
|
||||
|
||||
auto resultPair = SimplePool.modifyData(testStoreId);
|
||||
REQUIRE(resultPair.first == retval::CATCH_OK);
|
||||
result = resultPair.second.write(testDataArray.data(), 20, 0);
|
||||
REQUIRE(result == retval::CATCH_FAILED);
|
||||
result = resultPair.second.write(testDataArray.data(), 10, 5);
|
||||
REQUIRE(result == retval::CATCH_FAILED);
|
||||
|
||||
std::memset(testDataArray.data(), 42, 5);
|
||||
result = resultPair.second.write(testDataArray.data(), 5, 5);
|
||||
REQUIRE(result == retval::CATCH_OK);
|
||||
resultConstPair = SimplePool.getData(testStoreId);
|
||||
resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
for(size_t i = 5; i < 10; i++) {
|
||||
CHECK(receptionArray[i] == 42 );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,6 @@
|
||||
|
||||
|
||||
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 simplePool(0, config);
|
||||
std::array<uint8_t, 20> testDataArray;
|
||||
|
@ -13,7 +13,19 @@ cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
# 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.
|
||||
if(NOT OS_FSFW)
|
||||
@ -53,6 +65,7 @@ set(FSFW_PATH fsfw)
|
||||
set(CATCH2_PATH Catch2)
|
||||
set(FSFW_TESTS_PATH fsfw/unittest)
|
||||
set(TEST_SETUP_PATH unittest)
|
||||
set(TMTC_TEST_PATH tests)
|
||||
|
||||
# Analyse different OS and architecture/target options and
|
||||
# determine BSP_PATH
|
||||
@ -71,6 +84,15 @@ else()
|
||||
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)
|
||||
|
||||
################################################################################
|
||||
@ -82,10 +104,16 @@ add_executable(${TARGET_NAME})
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(${FSFW_PATH})
|
||||
add_subdirectory(${CATCH2_PATH})
|
||||
add_subdirectory(${FSFW_CONFIG_PATH})
|
||||
add_subdirectory(${FSFW_TESTS_PATH})
|
||||
add_subdirectory(${TEST_SETUP_PATH})
|
||||
|
||||
if(LINK_CATCH2)
|
||||
add_subdirectory(${CATCH2_PATH})
|
||||
add_subdirectory(${FSFW_TESTS_PATH})
|
||||
add_subdirectory(${TEST_SETUP_PATH})
|
||||
else()
|
||||
add_subdirectory(${TMTC_TEST_PATH})
|
||||
endif()
|
||||
|
||||
|
||||
################################################################################
|
||||
# Post-Sources preparation
|
||||
@ -94,9 +122,74 @@ add_subdirectory(${TEST_SETUP_PATH})
|
||||
# Add libraries for all sources.
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||
${LIB_FSFW_NAME}
|
||||
${CATCH2_TARGET}
|
||||
)
|
||||
|
||||
if(LINK_CATCH2)
|
||||
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||
${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.
|
||||
target_include_directories(${TARGET_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
@ -147,8 +240,7 @@ if(NOT CMAKE_SIZE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${TARGET_NAME}
|
||||
add_custom_command(TARGET ${TARGET_NAME}
|
||||
POST_BUILD
|
||||
COMMAND echo "Build directory: ${CMAKE_BINARY_DIR}"
|
||||
COMMAND echo "Target OSAL: ${OS_FSFW}"
|
||||
@ -156,7 +248,7 @@ add_custom_command(
|
||||
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()
|
||||
|
||||
|
||||
|
@ -4,16 +4,21 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
//! Used to determine whether C++ ostreams are used
|
||||
//! Those can lead to code bloat.
|
||||
//! Used to determine whether C++ ostreams are used which can increase
|
||||
//! the binary size significantly. If this is disabled,
|
||||
//! the C stdio functions can be used alternatively
|
||||
#define FSFW_CPP_OSTREAM_ENABLED 1
|
||||
|
||||
//! Reduced printout to further decrease code size
|
||||
//! Be careful, this also turns off most diagnostic prinouts!
|
||||
#define FSFW_ENHANCED_PRINTOUT 0
|
||||
//! More FSFW related printouts depending on level. Useful for development.
|
||||
#define FSFW_VERBOSE_LEVEL 1
|
||||
|
||||
//! Can be used to enable additional debugging printouts for developing the FSFW
|
||||
#define FSFW_PRINT_VERBOSITY_LEVEL 0
|
||||
//! Can be used to completely disable printouts, even the C stdio ones.
|
||||
#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,
|
||||
//! 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
|
||||
//! simulataneously. This will increase the required RAM for
|
||||
//! 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_ */
|
||||
|
@ -9,7 +9,20 @@ namespace objects {
|
||||
enum sourceObjects: uint32_t {
|
||||
/* All addresses between start and end are reserved for the FSFW */
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
|
1
unittest/user/unittest/CMakeLists.txt
Normal file
1
unittest/user/unittest/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
add_subdirectory(core)
|
@ -5,3 +5,9 @@ target_sources(${TARGET_NAME} PRIVATE
|
||||
CatchSetup.cpp
|
||||
printChar.cpp
|
||||
)
|
||||
|
||||
if(CUSTOM_UNITTEST_RUNNER)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
CatchRunner.cpp
|
||||
)
|
||||
endif()
|
@ -1,4 +1,5 @@
|
||||
#include "CatchDefinitions.h"
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||
|
||||
StorageManagerIF* tglob::getIpcStoreHandle() {
|
||||
@ -7,7 +8,9 @@ StorageManagerIF* tglob::getIpcStoreHandle() {
|
||||
} else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,17 @@
|
||||
#include <fsfw/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include "CatchFactory.h"
|
||||
|
||||
#include <fsfw/events/EventManager.h>
|
||||
#include <fsfw/health/HealthTable.h>
|
||||
|
||||
#include <fsfw/internalError/InternalErrorReporter.h>
|
||||
#include <fsfw/objectmanager/frameworkObjects.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.
|
||||
@ -26,6 +32,9 @@ void Factory::produce(void) {
|
||||
new HealthTable(objects::HEALTH_TABLE);
|
||||
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
|
||||
|
||||
new LocalPoolOwnerBase (objects::TEST_LOCAL_POOL_OWNER_BASE);
|
||||
new HkReceiverMock(objects::HK_RECEIVER_MOCK);
|
||||
|
||||
{
|
||||
PoolManager::LocalPoolConfig poolCfg = {
|
||||
{100, 16}, {50, 32}, {25, 64} , {15, 128}, {5, 1024}
|
||||
@ -50,7 +59,23 @@ void Factory::produce(void) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,17 +1,16 @@
|
||||
/**
|
||||
* @file CatchSource.cpp
|
||||
* @file CatchRunner.cpp
|
||||
* @brief Source file to compile catch framework.
|
||||
* @details All tests should be written in other files.
|
||||
* For eclipse console output, install ANSI Escape in Console
|
||||
* from the eclipse market place to get colored characters.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNIT_TEST_FRAMEWORK
|
||||
#include <TestsConfig.h>
|
||||
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include <catch2/catch.hpp>
|
||||
#define CATCH_CONFIG_COLOUR_WINDOWS
|
||||
|
||||
#if CUSTOM_UNITTEST_RUNNER == 0
|
||||
#include <catch2/catch_session.hpp>
|
||||
|
||||
extern int customSetup();
|
||||
|
||||
@ -25,7 +24,3 @@ int main( int argc, char* argv[] ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,21 +1,20 @@
|
||||
#include <fsfw/unittest/core/CatchFactory.h>
|
||||
#include "CatchFactory.h"
|
||||
#include "CatchDefinitions.h"
|
||||
#include <testcfg/cdatapool/dataPoolInit.h>
|
||||
|
||||
#ifdef GCOV
|
||||
#include <gcov.h>
|
||||
#endif
|
||||
|
||||
#include "../../objectmanager/ObjectManager.h"
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../storagemanager/StorageManagerIF.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/objectmanager/ObjectManagerIF.h>
|
||||
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
|
||||
/* Global instantiations normally done in main.cpp */
|
||||
/* Initialize Data Pool */
|
||||
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
namespace sif {
|
||||
/* Set up output streams */
|
||||
ServiceInterfaceStream debug("DEBUG");
|
||||
@ -23,6 +22,7 @@ ServiceInterfaceStream info("INFO");
|
||||
ServiceInterfaceStream error("ERROR");
|
||||
ServiceInterfaceStream warning("WARNING");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Global object manager */
|
||||
ObjectManagerIF *objectManager;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <fsfw/unittest/core/printChar.h>
|
||||
#include "printChar.h"
|
||||
#include <cstdio>
|
||||
|
||||
void printChar(const char* character, bool errStream) {
|
||||
|
Loading…
Reference in New Issue
Block a user