1
0
forked from fsfw/fsfw
Files
action
container
contrib
controller
coordinates
datalinklayer
datapool
CMakeLists.txt
DataSetIF.h
HkSwitchHelper.cpp
HkSwitchHelper.h
PoolDataSetBase.cpp
PoolDataSetBase.h
PoolDataSetIF.h
PoolEntry.cpp
PoolEntry.h
PoolEntryIF.h
PoolReadGuard.h
PoolVarList.h
PoolVariableIF.h
ReadCommitIF.h
ReadCommitIFAttorney.h
SharedDataSetIF.h
datapoollocal
defaultcfg
devicehandlers
doc
events
fdir
globalfunctions
health
housekeeping
internalError
ipc
logo
memory
modes
monitoring
objectmanager
osal
parameters
power
pus
returnvalues
rmap
serialize
serviceinterface
storagemanager
subsystem
tasks
tcdistribution
thermal
timemanager
tmstorage
tmtcpacket
tmtcservices
unittest
.gitignore
.gitmodules
CHANGELOG
CMakeLists.txt
FSFWVersion.h
LICENSE
NOTICE
README.md
fsfw.mk
fsfw/datapool/PoolDataSetBase.cpp

234 lines
8.4 KiB
C++

#include "PoolDataSetBase.h"
#include "ReadCommitIFAttorney.h"
#include "../serviceinterface/ServiceInterface.h"
#include <cstring>
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxFillCount):
registeredVariables(registeredVariablesArray),
maxFillCount(maxFillCount) {}
PoolDataSetBase::~PoolDataSetBase() {}
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF *variable) {
if(registeredVariables == nullptr) {
/* Underlying container invalid */
return HasReturnvaluesIF::RETURN_FAILED;
}
if (state != States::STATE_SET_UNINITIALISED) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::registerVariable: Call made in wrong position." << std::endl;
#else
sif::printError("DataSet::registerVariable: Call made in wrong position.");
#endif
return DataSetIF::DATA_SET_UNINITIALISED;
}
if (variable == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::registerVariable: Pool variable is nullptr." << std::endl;
#else
sif::printError("DataSet::registerVariable: Pool variable is nullptr.\n");
#endif
return DataSetIF::POOL_VAR_NULL;
}
if (fillCount >= maxFillCount) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::registerVariable: DataSet is full." << std::endl;
#else
sif::printError("DataSet::registerVariable: DataSet is full.\n");
#endif
return DataSetIF::DATA_SET_FULL;
}
registeredVariables[fillCount] = variable;
fillCount++;
return HasReturnvaluesIF::RETURN_OK;
}
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(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) {
result = readVariable(count);
if(result != RETURN_OK) {
error = result;
}
}
state = States::STATE_SET_WAS_READ;
unlockDataPool();
}
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PoolDataSetBase::read: Call made in wrong position. Don't forget to "
"commit member datasets!" << std::endl;
#else
sif::printWarning("PoolDataSetBase::read: Call made in wrong position. Don't forget to "
"commit member datasets!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
result = SET_WAS_ALREADY_READ;
}
if(error != HasReturnvaluesIF::RETURN_OK) {
result = error;
}
return result;
}
uint16_t PoolDataSetBase::getFillCount() const {
return fillCount;
}
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(registeredVariables[count] == nullptr) {
/* Configuration error. */
return HasReturnvaluesIF::RETURN_FAILED;
}
/* These checks are often performed by the respective variable implementation too, but I guess
a double check does not hurt. */
if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_WRITE and
registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
if(protectEveryReadCommitCall) {
result = registeredVariables[count]->read(timeoutTypeForSingleVars,
mutexTimeoutForSingleVars);
}
else {
/* The readWithoutLock function is protected, so we use the attorney here */
result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]);
}
if(result != HasReturnvaluesIF::RETURN_OK) {
result = INVALID_PARAMETER_DEFINITION;
}
}
return result;
}
ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
if (state == States::STATE_SET_WAS_READ) {
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
return HasReturnvaluesIF::RETURN_OK;
}
else {
return handleUnreadDatasetCommit(timeoutType, 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) and
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
if(protectEveryReadCommitCall) {
registeredVariables[count]->commit(timeoutTypeForSingleVars,
mutexTimeoutForSingleVars);
}
else {
/* The commitWithoutLock function is protected, so we use the attorney here */
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
}
}
}
state = States::STATE_SET_UNINITIALISED;
unlockDataPool();
}
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) {
if ((registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE) and
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
if(protectEveryReadCommitCall) {
result = registeredVariables[count]->commit(timeoutTypeForSingleVars,
mutexTimeoutForSingleVars);
}
else {
/* The commitWithoutLock function is protected, so we use the attorney here */
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
}
} else if (registeredVariables[count]->getDataPoolId()
!= PoolVariableIF::NO_PARAMETER) {
if (result != COMMITING_WITHOUT_READING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::commit(): commit-without-read call made "
"with non write-only variable." << std::endl;
#endif
result = COMMITING_WITHOUT_READING;
}
}
}
state = States::STATE_SET_UNINITIALISED;
unlockDataPool();
return result;
}
ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PoolDataSetBase::unlockDataPool() {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size,
const size_t maxSize, SerializeIF::Endianness streamEndianness) const {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
for (uint16_t count = 0; count < fillCount; count++) {
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
return result;
}
ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
for (uint16_t count = 0; count < fillCount; count++) {
result = registeredVariables[count]->deSerialize(buffer, size,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
return result;
}
size_t PoolDataSetBase::getSerializedSize() const {
uint32_t size = 0;
for (uint16_t count = 0; count < fillCount; count++) {
size += registeredVariables[count]->getSerializedSize();
}
return size;
}
void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
this->registeredVariables = variablesContainer;
}
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;
}