2022-02-02 10:29:30 +01:00
|
|
|
#include <cmath>
|
|
|
|
#include <cstring>
|
2021-01-06 21:14:23 +01:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/datapoollocal.h"
|
2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/globalfunctions/bitutility.h"
|
2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/housekeeping/PeriodicHousekeepingHelper.h"
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/objectmanager/ObjectManager.h"
|
2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/serialize/SerializeAdapter.h"
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
|
|
#include "internal/HasLocalDpIFUserAttorney.h"
|
2020-10-01 12:05:24 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, uint32_t setId,
|
|
|
|
PoolVariableIF **registeredVariablesArray,
|
|
|
|
const size_t maxNumberOfVariables, bool periodicHandling)
|
|
|
|
: PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
|
|
|
if (hkOwner == nullptr) {
|
|
|
|
// Configuration error.
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
|
|
|
|
<< "invalid!" << std::endl;
|
2021-01-06 21:14:23 +01:00
|
|
|
#else
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::printError(
|
|
|
|
"LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
|
|
|
|
"invalid!\n\r");
|
2021-01-06 21:14:23 +01:00
|
|
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
2022-02-02 10:29:30 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
AccessPoolManagerIF *accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
|
|
|
|
|
|
|
if (accessor != nullptr) {
|
|
|
|
poolManager = accessor->getPoolManagerHandle();
|
|
|
|
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
|
|
|
}
|
|
|
|
|
|
|
|
this->sid.objectId = hkOwner->getObjectId();
|
|
|
|
this->sid.ownerSetId = setId;
|
|
|
|
|
|
|
|
/* Data creators get a periodic helper for periodic HK data generation. */
|
|
|
|
if (periodicHandling) {
|
|
|
|
periodicHelper = new PeriodicHousekeepingHelper(this);
|
|
|
|
}
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, PoolVariableIF **registeredVariablesArray,
|
|
|
|
const size_t maxNumberOfVariables)
|
|
|
|
: PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
|
|
|
HasLocalDataPoolIF *hkOwner = ObjectManager::instance()->get<HasLocalDataPoolIF>(sid.objectId);
|
|
|
|
if (hkOwner != nullptr) {
|
|
|
|
AccessPoolManagerIF *accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
|
|
|
if (accessor != nullptr) {
|
|
|
|
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
|
|
|
poolManager = accessor->getPoolManagerHandle();
|
2021-01-13 12:41:24 +01:00
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2021-01-13 12:41:24 +01:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
this->sid = sid;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2021-03-18 20:09:19 +01:00
|
|
|
LocalPoolDataSetBase::LocalPoolDataSetBase(PoolVariableIF **registeredVariablesArray,
|
2022-02-02 10:29:30 +01:00
|
|
|
const size_t maxNumberOfVariables,
|
|
|
|
bool protectEveryReadCommitCall)
|
|
|
|
: PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
|
|
|
this->setReadCommitProtectionBehaviour(protectEveryReadCommitCall);
|
2021-01-06 21:14:23 +01:00
|
|
|
}
|
|
|
|
|
2020-10-01 12:05:24 +02:00
|
|
|
LocalPoolDataSetBase::~LocalPoolDataSetBase() {
|
2022-02-02 10:29:30 +01:00
|
|
|
/* We only delete objects which were created in the class constructor */
|
|
|
|
if (periodicHelper != nullptr) {
|
|
|
|
delete periodicHelper;
|
|
|
|
}
|
|
|
|
/* In case set was read but not comitted, we commit all variables with an invalid state */
|
|
|
|
if (state == States::STATE_SET_WAS_READ) {
|
|
|
|
for (uint16_t count = 0; count < fillCount; count++) {
|
|
|
|
if (registeredVariables[count] != nullptr) {
|
|
|
|
registeredVariables[count]->setValid(false);
|
|
|
|
registeredVariables[count]->commit(MutexIF::TimeoutType::WAITING, 20);
|
|
|
|
}
|
2021-02-06 14:15:56 +01:00
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t LocalPoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
|
|
|
|
uint32_t timeoutMs) {
|
|
|
|
if (mutexIfSingleDataCreator != nullptr) {
|
|
|
|
return mutexIfSingleDataCreator->lockMutex(timeoutType, timeoutMs);
|
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(
|
|
|
|
uint8_t **buffer, size_t *size, size_t maxSize,
|
|
|
|
SerializeIF::Endianness streamEndianness) const {
|
2022-08-15 20:28:16 +02:00
|
|
|
ReturnValue_t result = returnvalue::OK;
|
2022-02-02 10:29:30 +01:00
|
|
|
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
|
|
|
|
uint8_t *validityPtr = nullptr;
|
2022-05-01 17:48:49 +02:00
|
|
|
#if defined(_MSC_VER) || defined(__clang__)
|
2022-04-30 19:02:41 +02:00
|
|
|
// Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
|
|
|
// with a non constant size specifier. The Apple compiler (LLVM) will not accept
|
|
|
|
// the initialization of a variable sized array
|
2022-05-01 17:48:49 +02:00
|
|
|
std::vector<uint8_t> validityMask(validityMaskSize, 0);
|
2022-02-02 10:29:30 +01:00
|
|
|
validityPtr = validityMask.data();
|
2021-03-16 14:46:05 +01:00
|
|
|
#else
|
2022-04-30 19:02:41 +02:00
|
|
|
uint8_t validityMask[validityMaskSize] = {};
|
2022-02-02 10:29:30 +01:00
|
|
|
validityPtr = validityMask;
|
2021-03-16 14:46:05 +01:00
|
|
|
#endif
|
2022-02-02 10:29:30 +01:00
|
|
|
uint8_t validBufferIndex = 0;
|
|
|
|
uint8_t validBufferIndexBit = 0;
|
|
|
|
for (uint16_t count = 0; count < fillCount; count++) {
|
|
|
|
if (registeredVariables[count]->isValid()) {
|
|
|
|
/* Set bit at correct position */
|
|
|
|
bitutil::set(validityPtr + validBufferIndex, validBufferIndexBit);
|
|
|
|
}
|
|
|
|
if (validBufferIndexBit == 7) {
|
|
|
|
validBufferIndex++;
|
|
|
|
validBufferIndexBit = 0;
|
|
|
|
} else {
|
|
|
|
validBufferIndexBit++;
|
2021-01-13 12:41:24 +01:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
2021-01-13 12:41:24 +01:00
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*size + validityMaskSize > maxSize) {
|
|
|
|
return SerializeIF::BUFFER_TOO_SHORT;
|
|
|
|
}
|
|
|
|
// copy validity buffer to end
|
|
|
|
std::memcpy(*buffer, validityPtr, validityMaskSize);
|
|
|
|
*size += validityMaskSize;
|
|
|
|
return result;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer(
|
2022-02-02 10:29:30 +01:00
|
|
|
const uint8_t **buffer, size_t *size, SerializeIF::Endianness streamEndianness) {
|
2022-08-15 20:28:16 +02:00
|
|
|
ReturnValue_t result = returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
for (uint16_t count = 0; count < fillCount; count++) {
|
|
|
|
result = registeredVariables[count]->deSerialize(buffer, size, streamEndianness);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
2021-01-13 12:41:24 +01:00
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*size < std::ceil(static_cast<float>(fillCount) / 8.0)) {
|
|
|
|
return SerializeIF::STREAM_TOO_SHORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t validBufferIndex = 0;
|
|
|
|
uint8_t validBufferIndexBit = 0;
|
|
|
|
for (uint16_t count = 0; count < fillCount; count++) {
|
|
|
|
// set validity buffer here.
|
|
|
|
bool nextVarValid = false;
|
|
|
|
bitutil::get(*buffer + validBufferIndex, validBufferIndexBit, nextVarValid);
|
|
|
|
registeredVariables[count]->setValid(nextVarValid);
|
|
|
|
|
|
|
|
if (validBufferIndexBit == 7) {
|
|
|
|
validBufferIndex++;
|
|
|
|
validBufferIndexBit = 0;
|
|
|
|
} else {
|
|
|
|
validBufferIndexBit++;
|
2021-01-13 12:41:24 +01:00
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
return result;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
2020-12-03 13:00:04 +01:00
|
|
|
|
2020-10-01 12:05:24 +02:00
|
|
|
ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (mutexIfSingleDataCreator != nullptr) {
|
|
|
|
return mutexIfSingleDataCreator->unlockMutex();
|
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t **buffer, size_t *size,
|
|
|
|
size_t maxSize,
|
|
|
|
SerializeIF::Endianness streamEndianness,
|
|
|
|
bool serializeFillCount) const {
|
|
|
|
/* Serialize fill count as uint8_t */
|
|
|
|
uint8_t fillCount = this->fillCount;
|
|
|
|
if (serializeFillCount) {
|
|
|
|
SerializeAdapter::serialize(&fillCount, buffer, size, maxSize, streamEndianness);
|
|
|
|
}
|
|
|
|
for (uint16_t count = 0; count < fillCount; count++) {
|
|
|
|
lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId();
|
|
|
|
auto result =
|
|
|
|
SerializeAdapter::serialize(¤tPoolId, buffer, size, maxSize, streamEndianness);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: "
|
|
|
|
<< "Serialization error!" << std::endl;
|
2021-01-06 21:14:23 +01:00
|
|
|
#else
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::printWarning(
|
|
|
|
"LocalPoolDataSetBase::serializeLocalPoolIds: "
|
|
|
|
"Serialization error!\n\r");
|
2021-01-06 21:14:23 +01:00
|
|
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
2021-01-13 12:41:24 +01:00
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
uint8_t LocalPoolDataSetBase::getLocalPoolIdsSerializedSize(bool serializeFillCount) const {
|
|
|
|
if (serializeFillCount) {
|
|
|
|
return fillCount * sizeof(lp_id_t) + sizeof(uint8_t);
|
|
|
|
} else {
|
|
|
|
return fillCount * sizeof(lp_id_t);
|
|
|
|
}
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t LocalPoolDataSetBase::getSerializedSize() const {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (withValidityBuffer) {
|
|
|
|
uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
|
|
|
|
return validityMaskSize + PoolDataSetBase::getSerializedSize();
|
|
|
|
} else {
|
|
|
|
return PoolDataSetBase::getSerializedSize();
|
|
|
|
}
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
void LocalPoolDataSetBase::setValidityBufferGeneration(bool withValidityBuffer) {
|
|
|
|
this->withValidityBuffer = withValidityBuffer;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t LocalPoolDataSetBase::deSerialize(const uint8_t **buffer, size_t *size,
|
|
|
|
SerializeIF::Endianness streamEndianness) {
|
|
|
|
if (withValidityBuffer) {
|
|
|
|
return this->deSerializeWithValidityBuffer(buffer, size, streamEndianness);
|
|
|
|
} else {
|
|
|
|
return PoolDataSetBase::deSerialize(buffer, size, streamEndianness);
|
|
|
|
}
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
|
|
|
SerializeIF::Endianness streamEndianness) const {
|
|
|
|
if (withValidityBuffer) {
|
|
|
|
return this->serializeWithValidityBuffer(buffer, size, maxSize, streamEndianness);
|
|
|
|
} else {
|
|
|
|
return PoolDataSetBase::serialize(buffer, size, maxSize, streamEndianness);
|
|
|
|
}
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) { this->diagnostic = isDiagnostics; }
|
2020-10-01 12:05:24 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
bool LocalPoolDataSetBase::isDiagnostics() const { return diagnostic; }
|
2020-10-01 12:05:24 +02:00
|
|
|
|
|
|
|
void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
|
2022-02-02 10:29:30 +01:00
|
|
|
this->reportingEnabled = reportingEnabled;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
|
2020-10-01 12:05:24 +02:00
|
|
|
|
2021-03-11 12:04:54 +01:00
|
|
|
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
|
2022-02-02 10:29:30 +01:00
|
|
|
dur_millis_t minimumPeriodicInterval,
|
|
|
|
uint8_t nonDiagIntervalFactor) {
|
|
|
|
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }
|
2020-10-01 12:05:24 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
bool LocalPoolDataSetBase::hasChanged() const { return changed; }
|
2020-10-01 12:05:24 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
sid_t LocalPoolDataSetBase::getSid() const { return sid; }
|
2020-10-01 12:05:24 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
bool LocalPoolDataSetBase::isValid() const { return this->valid; }
|
2020-10-01 12:05:24 +02:00
|
|
|
|
|
|
|
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (setEntriesRecursively) {
|
|
|
|
for (size_t idx = 0; idx < this->getFillCount(); idx++) {
|
|
|
|
registeredVariables[idx]->setValid(valid);
|
2021-01-13 12:41:24 +01:00
|
|
|
}
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
this->valid = valid;
|
2020-10-01 12:05:24 +02:00
|
|
|
}
|
2020-12-26 23:57:23 +01:00
|
|
|
|
2021-01-12 00:13:49 +01:00
|
|
|
object_id_t LocalPoolDataSetBase::getCreatorObjectId() {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (poolManager != nullptr) {
|
|
|
|
return poolManager->getCreatorObjectId();
|
|
|
|
}
|
|
|
|
return objects::NO_OBJECT;
|
2021-01-11 16:33:02 +01:00
|
|
|
}
|
2021-02-28 16:17:07 +01:00
|
|
|
|
2021-03-04 17:27:03 +01:00
|
|
|
void LocalPoolDataSetBase::setAllVariablesReadOnly() {
|
2022-02-02 10:29:30 +01:00
|
|
|
for (size_t idx = 0; idx < this->getFillCount(); idx++) {
|
|
|
|
registeredVariables[idx]->setReadWriteMode(pool_rwm_t::VAR_READ);
|
|
|
|
}
|
2021-03-04 17:27:03 +01:00
|
|
|
}
|
2021-03-10 21:17:08 +01:00
|
|
|
|
|
|
|
float LocalPoolDataSetBase::getCollectionInterval() const {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (periodicHelper != nullptr) {
|
|
|
|
return periodicHelper->getCollectionIntervalInSeconds();
|
|
|
|
} else {
|
|
|
|
return 0.0;
|
|
|
|
}
|
2021-03-10 21:17:08 +01:00
|
|
|
}
|
2022-02-03 10:37:07 +01:00
|
|
|
|
|
|
|
void LocalPoolDataSetBase::printSet() { return; }
|