#include "../datapoolglob/GlobalDataPool.h" #include "../datapoolglob/PoolRawAccess.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include "../serialize/EndianConverter.h" #include PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) : dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0), readWriteMode(setReadWriteMode) { memset(value, 0, sizeof(value)); if (dataSet != nullptr) { dataSet->registerVariable(this); } } PoolRawAccess::~PoolRawAccess() {} ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) { ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); if(result != HasReturnvaluesIF::RETURN_OK) { return result; } result = readWithoutLock(); ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); if(unlockResult != HasReturnvaluesIF::RETURN_OK) { sif::error << "GlobPoolVar::read: Could not unlock global data pool" << std::endl; } return result; } ReturnValue_t PoolRawAccess::readWithoutLock() { ReturnValue_t result = RETURN_FAILED; PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId); if (readOut != nullptr) { result = handleReadOut(readOut); if(result == RETURN_OK) { return result; } } else { result = READ_ENTRY_NON_EXISTENT; } handleReadError(result); return result; } ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) { ReturnValue_t result = RETURN_FAILED; valid = readOut->getValid(); if (readOut->getSize() > arrayEntry) { arraySize = readOut->getSize(); typeSize = readOut->getByteSize() / readOut->getSize(); type = readOut->getType(); if (typeSize <= sizeof(value)) { uint16_t arrayPosition = arrayEntry * typeSize; sizeTillEnd = readOut->getByteSize() - arrayPosition; uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition]; memcpy(value, ptr, typeSize); return RETURN_OK; } else { result = READ_TYPE_TOO_LARGE; } } else { //debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl; result = READ_INDEX_TOO_LARGE; } return result; } void PoolRawAccess::handleReadError(ReturnValue_t result) { sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId << std::dec << " failed, "; if(result == READ_TYPE_TOO_LARGE) { sif::error << "type too large." << std::endl; } else if(result == READ_INDEX_TOO_LARGE) { sif::error << "index too large." << std::endl; } else if(result == READ_ENTRY_NON_EXISTENT) { sif::error << "entry does not exist." << std::endl; } valid = INVALID; typeSize = 0; sizeTillEnd = 0; memset(value, 0, sizeof(value)); } ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) { ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); if(result != HasReturnvaluesIF::RETURN_OK) { return result; } result = commitWithoutLock(); ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); if(unlockResult != HasReturnvaluesIF::RETURN_OK) { sif::error << "GlobPoolVar::read: Could not unlock global data pool" << std::endl; } return result; } ReturnValue_t PoolRawAccess::commitWithoutLock() { PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId); if ((write_back != NULL) && (readWriteMode != VAR_READ)) { write_back->setValid(valid); uint8_t array_position = arrayEntry * typeSize; uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position]; memcpy(ptr, value, typeSize); return HasReturnvaluesIF::RETURN_OK; } else { return HasReturnvaluesIF::RETURN_FAILED; } } uint8_t* PoolRawAccess::getEntry() { return value; } ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer, size_t* writtenBytes, size_t max_size) { uint8_t* data_ptr = getEntry(); // debug << "PoolRawAccess::getEntry: Array position: " << // index * size_of_type << " Size of T: " << (int)size_of_type << // " ByteSize: " << byte_size << " Position: " << *size << std::endl; if (typeSize == 0) return DATA_POOL_ACCESS_FAILED; if (typeSize > max_size) return INCORRECT_SIZE; EndianConverter::convertBigEndian(buffer, data_ptr, typeSize); *writtenBytes = typeSize; return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size, size_t maxSize, Endianness streamEndianness) const { if (typeSize + *size <= maxSize) { switch(streamEndianness) { case(Endianness::BIG): EndianConverter::convertBigEndian(*buffer, value, typeSize); break; case(Endianness::LITTLE): EndianConverter::convertLittleEndian(*buffer, value, typeSize); break; case(Endianness::MACHINE): default: memcpy(*buffer, value, typeSize); break; } *size += typeSize; (*buffer) += typeSize; return HasReturnvaluesIF::RETURN_OK; } else { return SerializeIF::BUFFER_TOO_SHORT; } } Type PoolRawAccess::getType() { return type; } size_t PoolRawAccess::getSizeOfType() { return typeSize; } size_t PoolRawAccess::getArraySize(){ return arraySize; } uint32_t PoolRawAccess::getDataPoolId() const { return dataPoolId; } PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const { return readWriteMode; } ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer, size_t setSize) { if (typeSize == setSize) { EndianConverter::convertBigEndian(value, buffer, typeSize); return HasReturnvaluesIF::RETURN_OK; } else { sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: " "Internal" << (uint32_t) typeSize << ", Requested: " << setSize << std::endl; return INCORRECT_SIZE; } } bool PoolRawAccess::isValid() const { if (valid != INVALID) return true; else return false; } void PoolRawAccess::setValid(bool valid) { this->valid = valid; } size_t PoolRawAccess::getSizeTillEnd() const { return sizeTillEnd; } size_t PoolRawAccess::getSerializedSize() const { return typeSize; } ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) { if (*size >= typeSize) { switch(streamEndianness) { case(Endianness::BIG): EndianConverter::convertBigEndian(value, *buffer, typeSize); break; case(Endianness::LITTLE): EndianConverter::convertLittleEndian(value, *buffer, typeSize); break; case(Endianness::MACHINE): default: memcpy(value, *buffer, typeSize); break; } *size -= typeSize; *buffer += typeSize; return HasReturnvaluesIF::RETURN_OK; } else { return SerializeIF::STREAM_TOO_SHORT; } }