Files
fsfw/datapool/PoolDataSetBase.cpp
T

230 lines
8.2 KiB
C++
Raw Normal View History

2020-09-06 15:23:38 +02:00
#include "PoolDataSetBase.h"
2021-02-28 13:48:53 +01:00
#include "ReadCommitIFAttorney.h"
2021-02-28 13:56:16 +01:00
#include "../serviceinterface/ServiceInterface.h"
2021-02-28 13:48:53 +01:00
2021-02-06 14:15:56 +01:00
#include <cstring>
2020-09-06 15:23:38 +02:00
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxFillCount):
registeredVariables(registeredVariablesArray),
2021-03-11 00:18:17 +01:00
maxFillCount(maxFillCount) {}
2020-09-06 15:23:38 +02:00
PoolDataSetBase::~PoolDataSetBase() {}
2021-02-28 13:52:07 +01:00
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF *variable) {
2021-02-28 13:48:53 +01:00
if (state != States::STATE_SET_UNINITIALISED) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2021-02-28 14:54:03 +01:00
sif::error << "DataSet::registerVariable: Call made in wrong position." << std::endl;
#else
sif::printError("DataSet::registerVariable: Call made in wrong position.");
#endif
2021-02-28 13:48:53 +01:00
return DataSetIF::DATA_SET_UNINITIALISED;
}
if (variable == nullptr) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2021-02-28 14:54:03 +01:00
sif::error << "DataSet::registerVariable: Pool variable is nullptr." << std::endl;
#else
sif::printError("DataSet::registerVariable: Pool variable is nullptr.\n");
#endif
2021-02-28 13:48:53 +01:00
return DataSetIF::POOL_VAR_NULL;
}
if (fillCount >= maxFillCount) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2021-02-28 14:54:03 +01:00
sif::error << "DataSet::registerVariable: DataSet is full." << std::endl;
#else
sif::printError("DataSet::registerVariable: DataSet is full.\n");
#endif
2021-02-28 13:48:53 +01:00
return DataSetIF::DATA_SET_FULL;
}
registeredVariables[fillCount] = variable;
fillCount++;
return HasReturnvaluesIF::RETURN_OK;
2020-09-06 15:23:38 +02:00
}
2021-01-13 11:53:34 +01:00
ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType,
2021-02-28 13:48:53 +01:00
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 {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2021-02-28 13:52:07 +01:00
sif::error << "DataSet::read(): Call made in wrong position. Don't forget to commit"
2021-02-28 13:48:53 +01:00
" member datasets!" << std::endl;
2021-02-28 13:52:07 +01:00
#else
sif::printError("DataSet::read(): Call made in wrong position. Don't forget to commit"
" member datasets!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
2021-02-28 13:48:53 +01:00
result = SET_WAS_ALREADY_READ;
}
2020-12-27 01:15:52 +01:00
2021-02-28 13:48:53 +01:00
if(error != HasReturnvaluesIF::RETURN_OK) {
result = error;
}
return result;
2020-09-06 15:23:38 +02:00
}
uint16_t PoolDataSetBase::getFillCount() const {
return fillCount;
}
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
2021-02-28 13:48:53 +01:00
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. */
2021-02-28 13:52:07 +01:00
if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_WRITE and
registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
2021-02-28 13:48:53 +01:00
if(protectEveryReadCommitCall) {
2021-02-28 13:52:07 +01:00
result = registeredVariables[count]->read(timeoutTypeForSingleVars,
2021-02-28 13:48:53 +01:00
mutexTimeoutForSingleVars);
}
else {
2021-02-28 14:41:43 +01:00
/* The readWithoutLock function is protected, so we use the attorney here */
2021-02-28 13:48:53 +01:00
result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]);
}
if(result != HasReturnvaluesIF::RETURN_OK) {
result = INVALID_PARAMETER_DEFINITION;
}
}
return result;
2020-09-06 15:23:38 +02:00
}
2021-01-13 11:53:34 +01:00
ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType,
2021-02-28 13:48:53 +01:00
uint32_t lockTimeout) {
if (state == States::STATE_SET_WAS_READ) {
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
return HasReturnvaluesIF::RETURN_OK;
}
else {
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
}
2020-09-06 15:23:38 +02:00
}
2021-01-13 11:53:34 +01:00
void PoolDataSetBase::handleAlreadyReadDatasetCommit(
2021-02-28 13:48:53 +01:00
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) {
2021-02-28 13:52:07 +01:00
if ((registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ) and
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
2021-02-28 13:48:53 +01:00
if(protectEveryReadCommitCall) {
2021-02-28 13:52:07 +01:00
registeredVariables[count]->commit(timeoutTypeForSingleVars,
2021-02-28 13:48:53 +01:00
mutexTimeoutForSingleVars);
}
else {
2021-02-28 14:41:43 +01:00
/* The commitWithoutLock function is protected, so we use the attorney here */
2021-02-28 13:48:53 +01:00
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
}
}
}
state = States::STATE_SET_UNINITIALISED;
unlockDataPool();
2020-09-06 15:23:38 +02:00
}
2021-01-13 11:53:34 +01:00
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(
2021-02-28 13:48:53 +01:00
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) {
2021-02-28 13:52:07 +01:00
if ((registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE) and
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
2021-02-28 13:48:53 +01:00
if(protectEveryReadCommitCall) {
2021-02-28 13:52:07 +01:00
result = registeredVariables[count]->commit(timeoutTypeForSingleVars,
2021-02-28 13:48:53 +01:00
mutexTimeoutForSingleVars);
}
else {
2021-02-28 14:41:43 +01:00
/* The commitWithoutLock function is protected, so we use the attorney here */
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
2021-02-28 13:48:53 +01:00
}
} else if (registeredVariables[count]->getDataPoolId()
!= PoolVariableIF::NO_PARAMETER) {
if (result != COMMITING_WITHOUT_READING) {
2021-01-03 14:16:52 +01:00
#if FSFW_CPP_OSTREAM_ENABLED == 1
2021-02-28 13:48:53 +01:00
sif::error << "DataSet::commit(): commit-without-read call made "
"with non write-only variable." << std::endl;
#endif
2021-02-28 13:48:53 +01:00
result = COMMITING_WITHOUT_READING;
}
}
}
state = States::STATE_SET_UNINITIALISED;
unlockDataPool();
return result;
2020-09-06 15:23:38 +02:00
}
2021-01-13 11:53:34 +01:00
ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
2021-02-28 13:48:53 +01:00
uint32_t lockTimeout) {
return HasReturnvaluesIF::RETURN_OK;
2020-09-06 15:23:38 +02:00
}
ReturnValue_t PoolDataSetBase::unlockDataPool() {
2021-02-28 13:48:53 +01:00
return HasReturnvaluesIF::RETURN_OK;
2020-09-06 15:23:38 +02:00
}
ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size,
2021-02-28 13:48:53 +01:00
const size_t maxSize, SerializeIF::Endianness streamEndianness) const {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
for (uint16_t count = 0; count < fillCount; count++) {
2021-02-28 13:52:07 +01:00
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
2021-02-28 13:48:53 +01:00
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
return result;
2020-09-06 15:23:38 +02:00
}
ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
2021-02-28 13:48:53 +01:00
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;
2020-09-06 15:23:38 +02:00
}
size_t PoolDataSetBase::getSerializedSize() const {
2021-02-28 13:48:53 +01:00
uint32_t size = 0;
for (uint16_t count = 0; count < fillCount; count++) {
size += registeredVariables[count]->getSerializedSize();
}
return size;
2020-09-06 15:23:38 +02:00
}
void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
this->registeredVariables = variablesContainer;
}
2021-01-13 11:53:34 +01:00
PoolVariableIF** PoolDataSetBase::getContainer() const {
2021-02-28 13:48:53 +01:00
return registeredVariables;
2021-01-13 11:53:34 +01:00
}
void PoolDataSetBase::setReadCommitProtectionBehaviour(
2021-02-28 13:48:53 +01:00
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType,
uint32_t mutexTimeout) {
this->protectEveryReadCommitCall = protectEveryReadCommit;
this->timeoutTypeForSingleVars = timeoutType;
this->mutexTimeoutForSingleVars = mutexTimeout;
}