From 6e5f029a641ba7c77f85ea9e1d1f1a58d1a58b9a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 15 Oct 2020 12:47:21 +0200 Subject: [PATCH] type usage improved, getFillCoutn implemented --- storagemanager/LocalPool.cpp | 48 ++++++++++++++++++++++++++++--- storagemanager/LocalPool.h | 24 +++++++++------- storagemanager/PoolManager.cpp | 11 ++++++- storagemanager/PoolManager.h | 32 ++++++++++++++++++--- storagemanager/StorageManagerIF.h | 13 ++++++++- 5 files changed, 108 insertions(+), 20 deletions(-) diff --git a/storagemanager/LocalPool.cpp b/storagemanager/LocalPool.cpp index 8bb684d7..bffde367 100644 --- a/storagemanager/LocalPool.cpp +++ b/storagemanager/LocalPool.cpp @@ -2,12 +2,12 @@ #include #include -LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig poolConfig, +LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig, bool registered, bool spillsToHigherPools): SystemObject(setObjectId, registered), NUMBER_OF_POOLS(poolConfig.size()), spillsToHigherPools(spillsToHigherPools) { - uint16_t index = 0; + max_pools_t index = 0; for (const auto& currentPoolConfig: poolConfig) { this->numberOfElements[index] = currentPoolConfig.first; this->elementSizes[index] = currentPoolConfig.second; @@ -246,7 +246,7 @@ void LocalPool::write(store_address_t storeId, const uint8_t *data, sizeLists[storeId.poolIndex][storeId.packetIndex] = size; } -LocalPool::size_type LocalPool::getPageSize(uint16_t poolIndex) { +LocalPool::size_type LocalPool::getPageSize(max_pools_t poolIndex) { if (poolIndex < NUMBER_OF_POOLS) { return elementSizes[poolIndex]; } @@ -255,6 +255,10 @@ LocalPool::size_type LocalPool::getPageSize(uint16_t poolIndex) { } } +void LocalPool::setToSpillToHigherPools(bool enable) { + this->spillsToHigherPools = enable; +} + ReturnValue_t LocalPool::getPoolIndex(size_t packetSize, uint16_t *poolIndex, uint16_t startAtIndex) { for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) { @@ -274,7 +278,7 @@ LocalPool::size_type LocalPool::getRawPosition(store_address_t storeId) { return storeId.packetIndex * elementSizes[storeId.poolIndex]; } -ReturnValue_t LocalPool::findEmpty(uint16_t poolIndex, uint16_t *element) { +ReturnValue_t LocalPool::findEmpty(n_pool_elem_t poolIndex, uint16_t *element) { ReturnValue_t status = DATA_STORAGE_FULL; for (uint16_t foundElement = 0; foundElement < numberOfElements[poolIndex]; foundElement++) { @@ -301,4 +305,40 @@ size_t LocalPool::getTotalSize(size_t* additionalSize) { } void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) { + if(bytesWritten == nullptr or buffer == nullptr) { + return; + } + + uint16_t reservedHits = 0; + uint8_t idx = 0; + uint16_t sum = 0; + for(; idx < NUMBER_OF_POOLS; idx ++) { + for(const auto& size: sizeLists[idx]) { + if(size != STORAGE_FREE) { + reservedHits++; + } + buffer[idx] = static_cast(reservedHits) / + numberOfElements[idx] * 100; + *bytesWritten += 1; + sum += buffer[idx]; + } + } + idx++; + buffer[idx] = sum / NUMBER_OF_POOLS; + *bytesWritten += 1; +} + + +void LocalPool::clearPage(max_pools_t pageIndex) { + if(pageIndex >= NUMBER_OF_POOLS) { + return; + } + + // Mark the storage as free + for(auto& size: sizeLists[pageIndex]) { + size = STORAGE_FREE; + } + + // Set all the page content to 0. + std::memset(store[pageIndex].data(), 0, elementSizes[pageIndex]); } diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 5c30c58f..db771152 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -30,10 +30,9 @@ */ class LocalPool: public SystemObject, public StorageManagerIF { public: - using size_type = size_t; - using poolElementSize = size_type; - using numberPoolElements = uint16_t; - using LocalPoolCfgPair = std::pair; + using pool_elem_size_t = size_type; + using n_pool_elem_t = uint16_t; + using LocalPoolCfgPair = std::pair; // The configuration needs to be provided with the pool sizes ascending // but the number of pool elements as the first value is more intuitive. @@ -68,7 +67,7 @@ public: * @details * This must be less than the maximum number of pools (currently 0xff). */ - const uint8_t NUMBER_OF_POOLS; + const max_pools_t NUMBER_OF_POOLS; /** * @brief This is the default constructor for a pool manager instance. @@ -90,8 +89,11 @@ public: * @param spillsToHigherPools A variable to determine whether * higher n pools are used if the store is full. */ - LocalPool(object_id_t setObjectId, const LocalPoolConfig poolConfig, + LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig, bool registered = false, bool spillsToHigherPools = false); + + void setToSpillToHigherPools(bool enable); + /** * @brief In the LocalPool's destructor all allocated memory is freed. */ @@ -132,15 +134,17 @@ public: /** * Get the fill count of the pool. Each character inside the provided * buffer will be assigned to a rounded percentage fill count for each - * page. The last written byte (at the index number of pools + 1) + * page. The last written byte (at the index bytesWritten - 1) * will contain the total fill count of the pool as a mean of the - * percentages. + * percentages of single pages. * @param buffer * @param maxSize */ void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) override; void clearStore() override; + void clearPage(max_pools_t pageIndex) override; + ReturnValue_t initialize() override; protected: /** @@ -206,7 +210,7 @@ private: * @param pool_index The pool in which to look. * @return Returns the size of an element or 0. */ - size_type getPageSize(uint16_t poolIndex); + size_type getPageSize(max_pools_t poolIndex); /** * @brief This helper method looks up a fitting pool for a given size. @@ -237,7 +241,7 @@ private: * @return - #RETURN_OK on success, * - #DATA_STORAGE_FULL if the store is full */ - ReturnValue_t findEmpty(uint16_t poolIndex, uint16_t* element); + ReturnValue_t findEmpty(n_pool_elem_t poolIndex, uint16_t* element); InternalErrorReporterIF *internalErrorReporter = nullptr; }; diff --git a/storagemanager/PoolManager.cpp b/storagemanager/PoolManager.cpp index e7a7d9cf..85376b28 100644 --- a/storagemanager/PoolManager.cpp +++ b/storagemanager/PoolManager.cpp @@ -2,7 +2,7 @@ #include PoolManager::PoolManager(object_id_t setObjectId, - const LocalPoolConfig localPoolConfig): + const LocalPoolConfig& localPoolConfig): LocalPool(setObjectId, localPoolConfig, true) { mutex = MutexFactory::instance()->createMutex(); } @@ -49,3 +49,12 @@ void PoolManager::setMutexTimeout( uint32_t mutexTimeoutMs) { this->mutexTimeoutMs = mutexTimeoutMs; } + +ReturnValue_t PoolManager::lockMutex(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + return mutex->lockMutex(timeoutType, timeoutMs); +} + +ReturnValue_t PoolManager::unlockMutex() { + return mutex->unlockMutex(); +} diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index b1781b9b..5786a225 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -9,13 +9,20 @@ /** * @brief The PoolManager class provides an intermediate data storage with * a fixed pool size policy for inter-process communication. - * @details Uses local pool calls but is thread safe by protecting the call - * with a lock. + * @details + * Uses local pool calls but is thread safe by protecting most calls + * with a lock. The developer can lock the pool with the provided API + * if the lock needs to persists beyond the function call. + * + * Other than that, the class provides the same interface as the LocalPool + * class. The class is always registered as a system object as it is assumed + * it will always be used concurrently (if this is not the case, it is + * recommended to use the LocalPool class instead). * @author Bastian Baetz */ class PoolManager: public LocalPool { public: - PoolManager(object_id_t setObjectId, const LocalPoolConfig poolConfig); + PoolManager(object_id_t setObjectId, const LocalPoolConfig& poolConfig); /** * @brief In the PoolManager's destructor all allocated memory @@ -23,6 +30,12 @@ public: */ virtual ~PoolManager(); + /** + * Set the default mutex timeout for internal calls. + * @param mutexTimeoutMs + */ + void setMutexTimeout(uint32_t mutexTimeoutMs); + /** * @brief LocalPool overrides for thread-safety. Decorator function * which wraps LocalPool calls with a mutex protection. @@ -31,7 +44,18 @@ public: ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; - void setMutexTimeout(uint32_t mutexTimeoutMs); + /** + * The developer is allowed to lock the mutex in case the lock needs + * to persist beyond the function calls which are not protected by the + * class. + * @param timeoutType + * @param timeoutMs + * @return + */ + ReturnValue_t lockMutex(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs); + ReturnValue_t unlockMutex(); + protected: //! Default mutex timeout value to prevent permanent blocking. uint32_t mutexTimeoutMs = 20; diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index d22ed661..769616d7 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -28,6 +28,9 @@ using ConstAccessorPair = std::pair; */ class StorageManagerIF : public HasReturnvaluesIF { public: + using size_type = size_t; + using max_pools_t = uint8_t; + static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. @@ -40,7 +43,9 @@ public: static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. + //!< Indicates an invalid (i.e unused) storage address. + static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; + /** * @brief This is the empty virtual destructor as required for C++ interfaces. */ @@ -165,6 +170,12 @@ public: */ virtual void clearStore() = 0; + /** + * Clears a page in the store. Use with care! + * @param pageIndex + */ + virtual void clearPage(uint8_t pageIndex) = 0; + /** * Get the fill count of the pool. The exact form will be implementation * dependant.