Changes to pool access classes

1. PoolRawAccessHelper is more robust now and has better error handling
2. PoolRawAccess: Removed an unneeded constructor value, moved serialize
further to the top. Added new returnvalues and more precise error
handling for read() call
3. DataSet: Made MAX Number of data pool entries public so it can be
used by pool raw access error handling
This commit is contained in:
Robin Müller 2020-01-10 00:57:09 +01:00
parent 59b25bee86
commit 0ce67de8c8
5 changed files with 199 additions and 150 deletions

View File

@ -37,44 +37,11 @@
* \ingroup data_pool * \ingroup data_pool
*/ */
class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF { class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF {
private:
public:
//SHOULDDO we could use a linked list of datapool variables //SHOULDDO we could use a linked list of datapool variables
static const uint8_t DATA_SET_MAX_SIZE = 63; //!< This definition sets the maximum number of variables to register in one DataSet. static const uint8_t DATA_SET_MAX_SIZE = 63; //!< This definition sets the maximum number of variables to register in one DataSet.
/**
* \brief This array represents all pool variables registered in this set.
* \details It has a maximum size of DATA_SET_MAX_SIZE.
*/
PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE];
/**
* \brief The fill_count attribute ensures that the variables register in the correct array
* position and that the maximum number of variables is not exceeded.
*/
uint16_t fill_count;
/**
* States of the seet.
*/
enum States {
DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
DATA_SET_WAS_READ //!< DATA_SET_WAS_READ
};
/**
* \brief state manages the internal state of the data set, which is important e.g. for the
* behavior on destruction.
*/
States state;
/**
* \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.
*/
uint8_t lockDataPool();
/**
* \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.
*/
uint8_t freeDataPoolLock();
public:
static const uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS; static const uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS;
static const ReturnValue_t INVALID_PARAMETER_DEFINITION = static const ReturnValue_t INVALID_PARAMETER_DEFINITION =
MAKE_RETURN_CODE( 0x01 ); MAKE_RETURN_CODE( 0x01 );
@ -165,6 +132,40 @@ public:
ReturnValue_t serializeRawFromIdBuffer(uint8_t ** buffer, uint32_t * size, ReturnValue_t serializeRawFromIdBuffer(uint8_t ** buffer, uint32_t * size,
const uint32_t max_size, bool bigEndian, uint32_t * poolIdBuffer, const uint32_t max_size, bool bigEndian, uint32_t * poolIdBuffer,
uint32_t poolIdSize); uint32_t poolIdSize);
private:
/**
* \brief This array represents all pool variables registered in this set.
* \details It has a maximum size of DATA_SET_MAX_SIZE.
*/
PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE];
/**
* \brief The fill_count attribute ensures that the variables register in the correct array
* position and that the maximum number of variables is not exceeded.
*/
uint16_t fill_count;
/**
* States of the seet.
*/
enum States {
DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
DATA_SET_WAS_READ //!< DATA_SET_WAS_READ
};
/**
* \brief state manages the internal state of the data set, which is important e.g. for the
* behavior on destruction.
*/
States state;
/**
* \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.
*/
uint8_t lockDataPool();
/**
* \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.
*/
uint8_t freeDataPoolLock();
}; };
#endif /* DATASET_H_ */ #endif /* DATASET_H_ */

View File

@ -5,8 +5,7 @@
#include <framework/osal/Endiness.h> #include <framework/osal/Endiness.h>
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode, DataSetIF* data_set, ReadWriteMode_t setReadWriteMode) :
bool registerVectors) :
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize( dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize(
0), arraySize(0), sizeTillEnd(0), readWriteMode(setReadWriteMode) { 0), arraySize(0), sizeTillEnd(0), readWriteMode(setReadWriteMode) {
memset(value, 0, sizeof(value)); memset(value, 0, sizeof(value));
@ -20,6 +19,7 @@ PoolRawAccess::~PoolRawAccess() {
} }
ReturnValue_t PoolRawAccess::read() { ReturnValue_t PoolRawAccess::read() {
ReturnValue_t result = RETURN_FAILED;
PoolEntryIF* read_out = ::dataPool.getRawData(dataPoolId); PoolEntryIF* read_out = ::dataPool.getRawData(dataPoolId);
if (read_out != NULL) { if (read_out != NULL) {
valid = read_out->getValid(); valid = read_out->getValid();
@ -35,21 +35,30 @@ ReturnValue_t PoolRawAccess::read() {
memcpy(value, ptr, typeSize); memcpy(value, ptr, typeSize);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
//Error value type too large. result = READ_TYPE_TOO_LARGE;
} }
} else { } else {
//Error index requested too large result = READ_INDEX_TOO_LARGE;
} }
} else { } else {
//Error entry does not exist. result = READ_ENTRY_NON_EXISTENT;
} }
error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
<< std::dec << " failed." << std::endl; << std::dec << " failed, ";
if(result == READ_TYPE_TOO_LARGE) {
error << "type too large." << std::endl;
}
else if(result == READ_INDEX_TOO_LARGE) {
error << "index too large." << std::endl;
}
else {
error << "entry does not exist." << std::endl;
}
valid = INVALID; valid = INVALID;
typeSize = 0; typeSize = 0;
sizeTillEnd = 0; sizeTillEnd = 0;
memset(value, 0, sizeof(value)); memset(value, 0, sizeof(value));
return HasReturnvaluesIF::RETURN_FAILED; return result;
} }
ReturnValue_t PoolRawAccess::commit() { ReturnValue_t PoolRawAccess::commit() {
@ -90,6 +99,32 @@ ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const {
if (typeSize + *size <= max_size) {
if (bigEndian) {
#ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) {
(*buffer)[count] = value[typeSize - count - 1];
}
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(*buffer, value, typeSize);
#endif
} else {
memcpy(*buffer, value, typeSize);
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
Type PoolRawAccess::getType() { Type PoolRawAccess::getType() {
return type; return type;
} }
@ -146,29 +181,6 @@ uint16_t PoolRawAccess::getSizeTillEnd() const {
return sizeTillEnd; return sizeTillEnd;
} }
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const {
if (typeSize + *size <= max_size) {
if (bigEndian) {
#ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) {
(*buffer)[count] = value[typeSize - count - 1];
}
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(*buffer, value, typeSize);
#endif
} else {
memcpy(*buffer, value, typeSize);
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
uint32_t PoolRawAccess::getSerializedSize() const { uint32_t PoolRawAccess::getSerializedSize() const {
return typeSize; return typeSize;

View File

@ -15,70 +15,17 @@
* data pool access. * data pool access.
* @ingroup data_pool * @ingroup data_pool
*/ */
class PoolRawAccess: public PoolVariableIF { class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
private:
/**
* \brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored.
*/
uint32_t dataPoolId;
/**
* \brief The array entry that is fetched from the data pool.
*/
uint8_t arrayEntry;
/**
* \brief The valid information as it was stored in the data pool is copied to this attribute.
*/
uint8_t valid;
/**
* \brief This value contains the type of the data pool entry.
*/
Type type;
/**
* \brief This value contains the size of the data pool entry type in bytes.
*/
uint8_t typeSize;
/**
* The size of the DP array (single values return 1)
*/
uint8_t arraySize;
/**
* The size (in bytes) from the selected entry till the end of this DataPool variable.
*/
uint16_t sizeTillEnd;
/**
* \brief The information whether the class is read-write or read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
static const uint8_t RAW_MAX_SIZE = sizeof(double);
protected:
/**
* \brief This is a call to read the value from the global data pool.
* \details When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The operation does NOT provide any mutual exclusive protection by itself !
* If reading from the data pool without information about the type is desired,
* initialize the raw pool access by supplying a data set and using the data set
* read function, which calls this read function.
*/
ReturnValue_t read();
/**
* \brief The commit call writes back the variable's value 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 valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
*
*/
ReturnValue_t commit();
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS; static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02); static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
static const uint8_t RAW_MAX_SIZE = sizeof(double);
uint8_t value[RAW_MAX_SIZE]; uint8_t value[RAW_MAX_SIZE];
//PoolRawAccess();
/** /**
* This constructor is used to access a data pool entry with a * This constructor is used to access a data pool entry with a
* given ID if the target type is not known. A DataSet object is supplied * given ID if the target type is not known. A DataSet object is supplied
@ -96,25 +43,13 @@ public:
*/ */
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry, PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode = DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
PoolVariableIF::VAR_READ,bool registerVectors = false); PoolVariableIF::VAR_READ);
/** /**
* \brief The classes destructor is empty. If commit() was not called, the local value is * \brief The classes destructor is empty. If commit() was not called, the local value is
* discarded and not written back to the data pool. * discarded and not written back to the data pool.
*/ */
~PoolRawAccess(); ~PoolRawAccess();
/**
* @brief Serialize raw pool entry into provided buffer directly
* @param buffer Provided buffer. Raw pool data will be copied here
* @param size [out] Increment provided size value by serialized size
* @param max_size Maximum allowed serialization size
* @param bigEndian Specify endianess
* @return - @c RETURN_OK if serialization was successfull
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
*/
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const;
/** /**
* \brief This operation returns a pointer to the entry fetched. * \brief This operation returns a pointer to the entry fetched.
* \details Return pointer to the buffer containing the raw data * \details Return pointer to the buffer containing the raw data
@ -136,6 +71,19 @@ public:
*/ */
ReturnValue_t getEntryEndianSafe(uint8_t* buffer, uint32_t* size, ReturnValue_t getEntryEndianSafe(uint8_t* buffer, uint32_t* size,
uint32_t max_size); uint32_t max_size);
/**
* @brief Serialize raw pool entry into provided buffer directly
* @param buffer Provided buffer. Raw pool data will be copied here
* @param size [out] Increment provided size value by serialized size
* @param max_size Maximum allowed serialization size
* @param bigEndian Specify endianess
* @return - @c RETURN_OK if serialization was successfull
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
*/
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const;
/** /**
* With this method, the content can be set from a big endian buffer safely. * With this method, the content can be set from a big endian buffer safely.
* @param buffer Pointer to the data to set * @param buffer Pointer to the data to set
@ -181,6 +129,67 @@ public:
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian); bool bigEndian);
protected:
/**
* \brief This is a call to read the value from the global data pool.
* \details When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The operation does NOT provide any mutual exclusive protection by itself !
* If reading from the data pool without information about the type is desired,
* initialize the raw pool access by supplying a data set and using the data set
* read function, which calls this read function.
* @return -@c RETURN_OK Read successfull
* -@c READ_TYPE_TOO_LARGE
* -@c READ_INDEX_TOO_LARGE
* -@c READ_ENTRY_NON_EXISTENT
*/
ReturnValue_t read();
/**
* \brief The commit call writes back the variable's value 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 valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
*
*/
ReturnValue_t commit();
private:
/**
* \brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored.
*/
uint32_t dataPoolId;
/**
* \brief The array entry that is fetched from the data pool.
*/
uint8_t arrayEntry;
/**
* \brief The valid information as it was stored in the data pool is copied to this attribute.
*/
uint8_t valid;
/**
* \brief This value contains the type of the data pool entry.
*/
Type type;
/**
* \brief This value contains the size of the data pool entry type in bytes.
*/
uint8_t typeSize;
/**
* The size of the DP array (single values return 1)
*/
uint8_t arraySize;
/**
* The size (in bytes) from the selected entry till the end of this DataPool variable.
*/
uint16_t sizeTillEnd;
/**
* \brief The information whether the class is read-write or read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
}; };
#endif /* POOLRAWACCESS_H_ */ #endif /* POOLRAWACCESS_H_ */

View File

@ -78,45 +78,70 @@ ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer(Serializa
ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization(uint32_t currentPoolId,SerializationArgs argStruct, ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization(uint32_t currentPoolId,SerializationArgs argStruct,
bool withValidMask, uint8_t * validityMask) { bool withValidMask, uint8_t * validityMask) {
ReturnValue_t result; ReturnValue_t result = RETURN_FAILED;
uint8_t arrayPosition = 0; uint8_t arrayPosition = 0;
uint8_t counter = 0;
bool poolEntrySerialized = false; bool poolEntrySerialized = false;
//info << "Pool Raw Access Helper: Handling Pool ID: " << std::hex << currentPoolId << std::endl; info << "Pool Raw Access Helper: Handling Pool ID: " << std::hex << currentPoolId << std::endl;
while(not poolEntrySerialized) { while(not poolEntrySerialized) {
if(counter > DataSet::DATA_SET_MAX_SIZE) {
error << "Pool Raw Access Helper: Config error, max. number of possible data set variables exceeded" << std::endl;
return result;
}
counter ++;
DataSet currentDataSet = DataSet(); DataSet currentDataSet = DataSet();
PoolRawAccess currentPoolRawAccess(currentPoolId,arrayPosition,&currentDataSet,PoolVariableIF::VAR_READ); PoolRawAccess currentPoolRawAccess(currentPoolId,arrayPosition,&currentDataSet,PoolVariableIF::VAR_READ);
result = currentDataSet.read(); result = currentDataSet.read();
if (result != RETURN_OK) { if (result != RETURN_OK) {
debug << std::hex << "Pool Raw Access Helper: Error reading raw dataset" << std::dec << std::endl; debug << std::hex << "Pool Raw Access Helper: Error reading raw dataset with returncode "
<< result << std::dec << std::endl;
return result; return result;
} }
uint8_t remainingSize = currentPoolRawAccess.getSizeTillEnd() - currentPoolRawAccess.getSizeOfType();
if(remainingSize == 0) { result = checkRemainingSize(&currentPoolRawAccess, &poolEntrySerialized, &arrayPosition);
poolEntrySerialized = true; if(result != RETURN_OK) {
} error << "Pool Raw Access Helper: Configuration Error at pool ID " << std::hex << currentPoolId
else if(remainingSize > 0) { << ". Size till end smaller than 0" << std::dec << std::endl;
arrayPosition += currentPoolRawAccess.getSizeOfType() / 8;
}
else {
error << "Pool Raw Access Helper: Configuration Error. Size till end smaller than 0" << std::endl;
return result; return result;
} }
// set valid mask bit if necessary // set valid mask bit if necessary
if(withValidMask) { if(withValidMask) {
if(currentPoolRawAccess.isValid()) { if(currentPoolRawAccess.isValid()) {
handleMaskModification(validityMask); handleMaskModification(validityMask);
} }
} }
result = currentDataSet.serialize(argStruct.buffer, argStruct.size, result = currentDataSet.serialize(argStruct.buffer, argStruct.size,
argStruct.max_size, argStruct.bigEndian); argStruct.max_size, argStruct.bigEndian);
if (result != RETURN_OK) { if (result != RETURN_OK) {
debug << "Pool Raw Access Helper: Error serializing pool data into send buffer" << std::endl; debug << "Pool Raw Access Helper: Error serializing pool data with ID 0x" << std::hex <<
currentPoolId << " into send buffer with return code " << result << std::dec << std::endl;
return result; return result;
} }
} }
return result; return result;
} }
ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess * currentPoolRawAccess,
bool * isSerialized, uint8_t * arrayPosition) {
int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() - currentPoolRawAccess->getSizeOfType();
if(remainingSize == 0) {
*isSerialized = true;
}
else if(remainingSize > 0) {
*arrayPosition += currentPoolRawAccess->getSizeOfType();
}
else {
return RETURN_FAILED;
}
return RETURN_OK;
}
void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) { void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) {
validityMask[validBufferIndex] = validityMask[validBufferIndex] =
bitSetter(validityMask[validBufferIndex], validBufferIndexBit, true); bitSetter(validityMask[validBufferIndex], validBufferIndexBit, true);

View File

@ -90,6 +90,8 @@ private:
ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId,SerializationArgs argStruct, ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId,SerializationArgs argStruct,
bool withValidMask = false, uint8_t * validityMask = NULL); bool withValidMask = false, uint8_t * validityMask = NULL);
ReturnValue_t checkRemainingSize(PoolRawAccess * currentPoolRawAccess,
bool * isSerialized, uint8_t * arrayPosition);
void handleMaskModification(uint8_t * validityMask); void handleMaskModification(uint8_t * validityMask);
/** /**
* Sets specific bit of a byte * Sets specific bit of a byte