diff --git a/olp-cpp-sdk-core/include/olp/core/cache/DefaultCache.h b/olp-cpp-sdk-core/include/olp/core/cache/DefaultCache.h index b5784ff6b..0b68a484b 100644 --- a/olp-cpp-sdk-core/include/olp/core/cache/DefaultCache.h +++ b/olp-cpp-sdk-core/include/olp/core/cache/DefaultCache.h @@ -261,6 +261,47 @@ class CORE_API DefaultCache : public KeyValueCache { */ void Promote(const std::string& key) override; + /** + * @brief Gets the binary data from the cache. + * + * @param key The key that is used to look for the binary data. + * + * @return The binary data or an error if the data could not be retrieved from + * the cache. + */ + OperationOutcome Read(const std::string& key) override; + + /** + * @brief Stores the raw binary data as a value in the cache. + * + * @param key The key for this value. + * @param value The binary data that should be stored. + * @param expiry The expiry time (in seconds) of the key-value pair. + * + * @return An error if the data could not be written to the cache. + */ + OperationOutcomeEmpty Write(const std::string& key, const ValueTypePtr& value, + time_t expiry) override; + + /** + * @brief Removes the key-value pair from the cache. + * + * @param key The key for the value. + * + * @return An error if the data could not be removed from the cache. + */ + OperationOutcomeEmpty Delete(const std::string& key) override; + + /** + * @brief Removes the values with the keys that match the given + * prefix from the cache. + * + * @param prefix The prefix that matches the keys. + * + * @return An error if the data could not be removed from the cache. + */ + OperationOutcomeEmpty DeleteByPrefix(const std::string& prefix) override; + /** * @brief Gets size of the corresponding cache. * diff --git a/olp-cpp-sdk-core/include/olp/core/cache/KeyValueCache.h b/olp-cpp-sdk-core/include/olp/core/cache/KeyValueCache.h index ed6521bc1..742f86749 100644 --- a/olp-cpp-sdk-core/include/olp/core/cache/KeyValueCache.h +++ b/olp-cpp-sdk-core/include/olp/core/cache/KeyValueCache.h @@ -27,6 +27,9 @@ #include #include +#include +#include +#include #include #include @@ -36,6 +39,10 @@ namespace cache { using Encoder = std::function; using Decoder = std::function; +template +using OperationOutcome = client::ApiResponse; +using OperationOutcomeEmpty = OperationOutcome; + /// An interface for a cache that expects a key-value pair. class CORE_API KeyValueCache { public: @@ -181,6 +188,62 @@ class CORE_API KeyValueCache { * @param key The key to promote in the cache LRU. */ virtual void Promote(const std::string& key) { OLP_SDK_CORE_UNUSED(key); } + + /** + * @brief Gets the binary data from the cache. + * + * @param key The key that is used to look for the binary data. + * + * @return The binary data or an error if the data could not be retrieved from + * the cache. + */ + virtual OperationOutcome Read(const std::string& key) { + OLP_SDK_CORE_UNUSED(key); + return client::ApiError(client::ErrorCode::Unknown, "Not implemented"); + } + + /** + * @brief Stores the raw binary data as a value in the cache. + * + * @param key The key for this value. + * @param value The binary data that should be stored. + * @param expiry The expiry time (in seconds) of the key-value pair. + * + * @return An error if the data could not be written to the cache. + */ + virtual OperationOutcomeEmpty Write(const std::string& key, + const ValueTypePtr& value, + time_t expiry = kDefaultExpiry) { + OLP_SDK_CORE_UNUSED(key); + OLP_SDK_CORE_UNUSED(value); + OLP_SDK_CORE_UNUSED(expiry); + return client::ApiError(client::ErrorCode::Unknown, "Not implemented"); + } + + /** + * @brief Removes the key-value pair from the cache. + * + * @param key The key for the value. + * + * @return An error if the data could not be removed from the cache. + */ + virtual OperationOutcomeEmpty Delete(const std::string& key) { + OLP_SDK_CORE_UNUSED(key); + return client::ApiError(client::ErrorCode::Unknown, "Not implemented"); + } + + /** + * @brief Removes the values with the keys that match the given + * prefix from the cache. + * + * @param prefix The prefix that matches the keys. + * + * @return An error if the data could not be removed from the cache. + */ + virtual OperationOutcomeEmpty DeleteByPrefix(const std::string& prefix) { + OLP_SDK_CORE_UNUSED(prefix); + return client::ApiError(client::ErrorCode::Unknown, "Not implemented"); + } }; } // namespace cache diff --git a/olp-cpp-sdk-core/src/cache/DefaultCache.cpp b/olp-cpp-sdk-core/src/cache/DefaultCache.cpp index db4c26ee4..c31a7e593 100644 --- a/olp-cpp-sdk-core/src/cache/DefaultCache.cpp +++ b/olp-cpp-sdk-core/src/cache/DefaultCache.cpp @@ -90,5 +90,24 @@ uint64_t DefaultCache::Size(uint64_t new_size) { return impl_->Size(new_size); } void DefaultCache::Promote(const std::string& key) { impl_->Promote(key); } +OperationOutcome DefaultCache::Read( + const std::string& key) { + return impl_->Read(key); +} + +OperationOutcomeEmpty DefaultCache::Write( + const std::string& key, const KeyValueCache::ValueTypePtr& value, + time_t expiry) { + return impl_->Write(key, value, expiry); +} + +OperationOutcomeEmpty DefaultCache::Delete(const std::string& key) { + return impl_->Delete(key); +} + +OperationOutcomeEmpty DefaultCache::DeleteByPrefix(const std::string& prefix) { + return impl_->DeleteByPrefix(prefix); +} + } // namespace cache } // namespace olp diff --git a/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.cpp b/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.cpp index bb0011c30..605ceb58c 100644 --- a/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.cpp +++ b/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.cpp @@ -33,6 +33,7 @@ namespace { using CacheType = olp::cache::DefaultCache::CacheType; using StorageOpenResult = olp::cache::DefaultCache::StorageOpenResult; +using NoError = olp::client::ApiNoResult; constexpr auto kLogTag = "DefaultCache"; constexpr auto kExpirySuffix = "::expiry"; @@ -63,33 +64,35 @@ time_t GetRemainingExpiryTime(const std::string& key, olp::cache::DiskCache& disk_cache) { auto expiry_key = CreateExpiryKey(key); auto expiry = olp::cache::KeyValueCache::kDefaultExpiry; - auto expiry_value = disk_cache.Get(expiry_key); - if (expiry_value) { - expiry = std::stoll(*expiry_value); + auto expiry_result = disk_cache.Get(expiry_key); + if (expiry_result) { + std::string expiry_value(expiry_result.GetResult()->begin(), + expiry_result.GetResult()->end()); + expiry = std::stoll(expiry_value); expiry -= olp::cache::InMemoryCache::DefaultTimeProvider()(); } return expiry; } -bool PurgeDiskItem(const std::string& key, olp::cache::DiskCache& disk_cache, - uint64_t& removed_data_size) { - bool result = true; +olp::cache::OperationOutcomeEmpty PurgeDiskItem( + const std::string& key, olp::cache::DiskCache& disk_cache, + uint64_t& removed_data_size) { auto expiry_key = CreateExpiryKey(key); uint64_t data_size = 0u; - if (!disk_cache.Remove(key, data_size)) { + auto result = disk_cache.Remove(key, data_size); + if (!result) { OLP_SDK_LOG_ERROR_F(kLogTag, "PurgeDiskItem failed to remove key='%s'", key.c_str()); - result = false; } removed_data_size += data_size; - if (!disk_cache.Remove(expiry_key, data_size)) { + result = disk_cache.Remove(expiry_key, data_size); + if (!result) { OLP_SDK_LOG_ERROR_F(kLogTag, "PurgeDiskItem failed to remove expiry_key='%s'", expiry_key.c_str()); - result = false; } removed_data_size += data_size; @@ -289,35 +292,13 @@ bool DefaultCacheImpl::Put(const std::string& key, const boost::any& value, } } - return PutMutableCache(key, encoded_item, expiry); + return PutMutableCache(key, encoded_item, expiry).IsSuccessful(); } bool DefaultCacheImpl::Put(const std::string& key, const KeyValueCache::ValueTypePtr value, time_t expiry) { - if (!value) { - return false; - } - - std::lock_guard lock(cache_lock_); - if (!is_open_) { - return false; - } - - if (memory_cache_) { - const auto size = value->size(); - const bool result = memory_cache_->Put( - key, value, GetExpiryForMemoryCache(key, expiry), size); - if (!result && size > settings_.max_memory_cache_size && !mutable_cache_) { - OLP_SDK_LOG_INFO_F(kLogTag, - "Failed to store value in memory cache %s, size %d", - key.c_str(), static_cast(size)); - } - } - - leveldb::Slice slice(reinterpret_cast(value->data()), - value->size()); - return PutMutableCache(key, slice, expiry); + return Write(key, value, expiry).IsSuccessful(); } boost::any DefaultCacheImpl::Get(const std::string& key, @@ -352,99 +333,18 @@ boost::any DefaultCacheImpl::Get(const std::string& key, } KeyValueCache::ValueTypePtr DefaultCacheImpl::Get(const std::string& key) { - std::lock_guard lock(cache_lock_); - if (!is_open_) { - return nullptr; - } - - if (memory_cache_) { - auto value = memory_cache_->Get(key); - if (!value.empty()) { - PromoteKeyLru(key); - return boost::any_cast(value); - } - } - - KeyValueCache::ValueTypePtr value = nullptr; - time_t expiry = KeyValueCache::kDefaultExpiry; - - auto result = GetFromDiskCache(key, value, expiry); - if (result && value) { - if (memory_cache_) { - memory_cache_->Put(key, value, GetExpiryForMemoryCache(key, expiry), - value->size()); - } - - return value; + if (auto read_result = Read(key)) { + return read_result.MoveResult(); } return nullptr; } bool DefaultCacheImpl::Remove(const std::string& key) { - std::lock_guard lock(cache_lock_); - - if (!is_open_) { - return false; - } - - // In case the key is protected do not remove it - if (protected_keys_.IsProtected(key)) { - OLP_SDK_LOG_INFO_F(kLogTag, - "Remove() called on a protected key, ignoring, key='%s'", - key.c_str()); - - return false; - } - - // protected data could be removed by user - if (memory_cache_) { - memory_cache_->Remove(key); - } - - RemoveKeyLru(key); - - if (mutable_cache_) { - uint64_t removed_data_size = 0; - bool purge_passed = PurgeDiskItem(key, *mutable_cache_, removed_data_size); - mutable_cache_data_size_ -= removed_data_size; - - if (!purge_passed) { - OLP_SDK_LOG_ERROR_F(kLogTag, "Remove() failed to purge item, key='%s'", - key.c_str()); - return false; - } - } - - return true; + return Delete(key).IsSuccessful(); } bool DefaultCacheImpl::RemoveKeysWithPrefix(const std::string& key) { - std::lock_guard lock(cache_lock_); - - if (!is_open_) { - return false; - } - - auto filter = [&](const std::string& cache_key) { - return protected_keys_.IsProtected(cache_key); - }; - - if (memory_cache_) { - memory_cache_->RemoveKeysWithPrefix(key, filter); - } - - // No need to check here for protected key as these are not added to LRU from - // the start - RemoveKeysWithPrefixLru(key); - - if (mutable_cache_) { - uint64_t removed_data_size = 0; - auto result = - mutable_cache_->RemoveKeysWithPrefix(key, removed_data_size, filter); - mutable_cache_data_size_ -= removed_data_size; - return result; - } - return true; + return DeleteByPrefix(key).IsSuccessful(); } bool DefaultCacheImpl::Contains(const std::string& key) const { @@ -762,11 +662,10 @@ int64_t DefaultCacheImpl::MaybeUpdatedProtectedKeys( return 0; } -bool DefaultCacheImpl::PutMutableCache(const std::string& key, - const leveldb::Slice& value, - time_t expiry) { +OperationOutcomeEmpty DefaultCacheImpl::PutMutableCache( + const std::string& key, const leveldb::Slice& value, time_t expiry) { if (!mutable_cache_) { - return true; + return NoError(); } // can't put new item if cache is full and eviction disabled @@ -775,7 +674,9 @@ bool DefaultCacheImpl::PutMutableCache(const std::string& key, key.size() + kExpirySuffixLength + kExpiryValueSize; if (!mutable_cache_lru_ && expected_size > settings_.max_disk_storage) { - return false; + // FIXME: This error is not correct + return client::ApiError(client::ErrorCode::CacheIO, + "Cache is full and eviction is disabled"); } uint64_t added_data_size = 0u; @@ -792,8 +693,8 @@ bool DefaultCacheImpl::PutMutableCache(const std::string& key, auto updated_data_size = MaybeUpdatedProtectedKeys(*batch); auto result = mutable_cache_->ApplyBatch(std::move(batch)); - if (!result.IsSuccessful()) { - return false; + if (!result) { + return result; } mutable_cache_data_size_ += added_data_size; mutable_cache_data_size_ -= removed_data_size; @@ -809,11 +710,13 @@ bool DefaultCacheImpl::PutMutableCache(const std::string& key, OLP_SDK_LOG_WARNING_F( kLogTag, "Failed to store value in mutable LRU cache, key %s", key.c_str()); - return false; + // FIXME: This error is not correct + return client::ApiError(client::ErrorCode::CacheIO, + "Failed to store in mutable LRU cache"); } } - return true; + return NoError(); } DefaultCache::StorageOpenResult DefaultCacheImpl::SetupStorage() { @@ -916,9 +819,9 @@ DefaultCache::StorageOpenResult DefaultCacheImpl::SetupMutableCache() { } // read protected keys - KeyValueCache::ValueTypePtr value = nullptr; - auto result = mutable_cache_->Get(kProtectedKeys, value); - if (result && value) { + auto result = mutable_cache_->Get(kProtectedKeys); + if (result) { + auto value = result.MoveResult(); if (!protected_keys_.Deserialize(value)) { OLP_SDK_LOG_WARNING(kLogTag, "Deserialize protected keys failed"); } @@ -954,19 +857,20 @@ void DefaultCacheImpl::DestroyCache(DefaultCache::CacheType type) { } } -bool DefaultCacheImpl::GetFromDiskCache(const std::string& key, - KeyValueCache::ValueTypePtr& value, - time_t& expiry) { +OperationOutcomeEmpty DefaultCacheImpl::GetFromDiskCache( + const std::string& key, KeyValueCache::ValueTypePtr& value, + time_t& expiry) { // Make sure we do not get a dirty entry value = nullptr; expiry = KeyValueCache::kDefaultExpiry; if (protected_cache_) { - auto result = protected_cache_->Get(key, value); - if (result && value && !value->empty()) { + auto result = protected_cache_->Get(key); + if (result) { + value = result.MoveResult(); expiry = GetRemainingExpiryTime(key, *protected_cache_); if (expiry > 0) { - return true; + return NoError(); } value = nullptr; } @@ -983,11 +887,16 @@ bool DefaultCacheImpl::GetFromDiskCache(const std::string& key, OLP_SDK_LOG_DEBUG_F(kLogTag, "Key not found in LRU, and not protected, key='%s'", key.c_str()); - return false; + return client::ApiError::NotFound(); } - auto result = mutable_cache_->Get(key, value); - return result && value; + auto result = mutable_cache_->Get(key); + if (!result) { + return result.GetError(); + } + + value = result.MoveResult(); + return NoError(); } // Data expired in cache -> remove, but not protected keys @@ -1001,7 +910,7 @@ bool DefaultCacheImpl::GetFromDiskCache(const std::string& key, RemoveKeyLru(key); } - return false; + return client::ApiError::NotFound(); } boost::optional> @@ -1146,5 +1055,131 @@ void DefaultCacheImpl::Promote(const std::string& key) { } } +OperationOutcome DefaultCacheImpl::Read( + const std::string& key) { + std::lock_guard lock(cache_lock_); + if (!is_open_) { + return client::ApiError::PreconditionFailed(); + } + + if (memory_cache_) { + auto value = memory_cache_->Get(key); + if (!value.empty()) { + PromoteKeyLru(key); + return boost::any_cast(value); + } + } + + KeyValueCache::ValueTypePtr value = nullptr; + time_t expiry = KeyValueCache::kDefaultExpiry; + + auto result = GetFromDiskCache(key, value, expiry); + if (result && value) { + if (memory_cache_) { + memory_cache_->Put(key, value, GetExpiryForMemoryCache(key, expiry), + value->size()); + } + + return value; + } + return client::ApiError::NotFound(); +} + +OperationOutcomeEmpty DefaultCacheImpl::Write( + const std::string& key, const KeyValueCache::ValueTypePtr& value, + time_t expiry) { + if (!value) { + return client::ApiError::InvalidArgument(); + } + + std::lock_guard lock(cache_lock_); + if (!is_open_) { + return client::ApiError::PreconditionFailed(); + } + + if (memory_cache_) { + const auto size = value->size(); + const bool result = memory_cache_->Put( + key, value, GetExpiryForMemoryCache(key, expiry), size); + if (!result && size > settings_.max_memory_cache_size && !mutable_cache_) { + OLP_SDK_LOG_INFO_F(kLogTag, + "Failed to store value in memory cache %s, size %d", + key.c_str(), static_cast(size)); + } + } + + leveldb::Slice slice(reinterpret_cast(value->data()), + value->size()); + return PutMutableCache(key, slice, expiry); +} + +OperationOutcomeEmpty DefaultCacheImpl::Delete(const std::string& key) { + std::lock_guard lock(cache_lock_); + + if (!is_open_) { + return client::ApiError::PreconditionFailed(); + } + + // In case the key is protected do not remove it + if (protected_keys_.IsProtected(key)) { + OLP_SDK_LOG_INFO_F(kLogTag, + "Remove() called on a protected key, ignoring, key='%s'", + key.c_str()); + + return client::ApiError::PreconditionFailed(); + } + + // protected data could be removed by user + if (memory_cache_) { + memory_cache_->Remove(key); + } + + RemoveKeyLru(key); + + if (mutable_cache_) { + uint64_t removed_data_size = 0; + auto purge_result = PurgeDiskItem(key, *mutable_cache_, removed_data_size); + mutable_cache_data_size_ -= removed_data_size; + + if (!purge_result) { + OLP_SDK_LOG_ERROR_F(kLogTag, "Remove() failed to purge item, key='%s'", + key.c_str()); + return purge_result; + } + } + + return NoError(); +} + +OperationOutcomeEmpty DefaultCacheImpl::DeleteByPrefix( + const std::string& prefix) { + std::lock_guard lock(cache_lock_); + + if (!is_open_) { + return client::ApiError::PreconditionFailed(); + } + + auto filter = [&](const std::string& cache_key) { + return protected_keys_.IsProtected(cache_key); + }; + + if (memory_cache_) { + memory_cache_->RemoveKeysWithPrefix(prefix, filter); + } + + // No need to check here for protected key as these are not added to LRU from + // the start + RemoveKeysWithPrefixLru(prefix); + + if (mutable_cache_) { + uint64_t removed_data_size = 0; + auto result = + mutable_cache_->RemoveKeysWithPrefix(prefix, removed_data_size, filter); + mutable_cache_data_size_ -= removed_data_size; + return result; + } + return NoError(); +} + } // namespace cache } // namespace olp diff --git a/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.h b/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.h index cc1eaa557..6abefbb15 100644 --- a/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.h +++ b/olp-cpp-sdk-core/src/cache/DefaultCacheImpl.h @@ -68,6 +68,13 @@ class DefaultCacheImpl { bool IsProtected(const std::string& key) const; void Promote(const std::string& key); + OperationOutcome Read(const std::string& key); + OperationOutcomeEmpty Write(const std::string& key, + const KeyValueCache::ValueTypePtr& value, + time_t expiry); + OperationOutcomeEmpty Delete(const std::string& key); + OperationOutcomeEmpty DeleteByPrefix(const std::string& prefix); + uint64_t Size(DefaultCache::CacheType type) const; uint64_t Size(uint64_t new_size); @@ -153,8 +160,9 @@ class DefaultCacheImpl { int64_t MaybeUpdatedProtectedKeys(leveldb::WriteBatch& batch); /// Puts data into the mutable cache - bool PutMutableCache(const std::string& key, const leveldb::Slice& value, - time_t expiry); + OperationOutcomeEmpty PutMutableCache(const std::string& key, + const leveldb::Slice& value, + time_t expiry); DefaultCache::StorageOpenResult SetupStorage(); @@ -164,8 +172,9 @@ class DefaultCacheImpl { void DestroyCache(DefaultCache::CacheType type); - bool GetFromDiskCache(const std::string& key, - KeyValueCache::ValueTypePtr& value, time_t& expiry); + OperationOutcomeEmpty GetFromDiskCache(const std::string& key, + KeyValueCache::ValueTypePtr& value, + time_t& expiry); boost::optional> GetFromDiscCache( const std::string& key); diff --git a/olp-cpp-sdk-core/src/cache/DiskCache.cpp b/olp-cpp-sdk-core/src/cache/DiskCache.cpp index 20a47fb58..562397c45 100644 --- a/olp-cpp-sdk-core/src/cache/DiskCache.cpp +++ b/olp-cpp-sdk-core/src/cache/DiskCache.cpp @@ -120,7 +120,7 @@ client::ApiError GetApiError(const leveldb::Status& status) { code = client::ErrorCode::InvalidArgument; } if (status.IsCorruption() || status.IsIOError()) { - code = client::ErrorCode::InternalFailure; + code = client::ErrorCode::CacheIO; } if (status.IsNotSupportedError()) { code = client::ErrorCode::BadRequest; @@ -338,28 +338,13 @@ bool DiskCache::Put(const std::string& key, leveldb::Slice slice) { return true; } -boost::optional DiskCache::Get(const std::string& key) { +OperationOutcome DiskCache::Get( + const std::string& key) { if (!database_) { OLP_SDK_LOG_ERROR(kLogTag, "Get: Database is not initialized"); - return boost::none; + return client::ApiError::PreconditionFailed(); } - std::string res; - leveldb::ReadOptions options; - options.verify_checksums = check_crc_; - return database_->Get(options, ToLeveldbSlice(key), &res).ok() - ? boost::optional(std::move(res)) - : boost::none; -} - -bool DiskCache::Get(const std::string& key, - KeyValueCache::ValueTypePtr& value) { - if (!database_) { - OLP_SDK_LOG_ERROR(kLogTag, "Get: Database is not initialized"); - return false; - } - - value = nullptr; leveldb::ReadOptions options; options.verify_checksums = check_crc_; auto iterator = NewIterator(options); @@ -368,12 +353,12 @@ bool DiskCache::Get(const std::string& key, if (iterator->Valid() && iterator->key() == key) { auto slice_value = iterator->value(); if (!slice_value.empty()) { - value = std::make_shared( + return std::make_shared( slice_value.data(), slice_value.data() + slice_value.size()); } } - return true; + return client::ApiError::NotFound(); } bool DiskCache::Contains(const std::string& key) { @@ -389,11 +374,12 @@ bool DiskCache::Contains(const std::string& key) { return (iterator->Valid() && iterator->key() == key); } -bool DiskCache::Remove(const std::string& key, uint64_t& removed_data_size) { +DiskCache::OperationOutcome<> DiskCache::Remove(const std::string& key, + uint64_t& removed_data_size) { removed_data_size = 0u; if (!database_) { OLP_SDK_LOG_ERROR(kLogTag, "Remove: Database is not initialized"); - return false; + return client::ApiError::PreconditionFailed(); } uint64_t data_size = 0u; @@ -406,12 +392,13 @@ bool DiskCache::Remove(const std::string& key, uint64_t& removed_data_size) { leveldb::WriteOptions write_options; write_options.sync = enforce_immediate_flush_; - auto result = database_->Delete(write_options, key).ok(); - if (result) { + auto result = database_->Delete(write_options, key); + if (result.ok()) { removed_data_size = data_size; + return NoError{}; } - return result; + return GetApiError(result); } std::unique_ptr DiskCache::NewIterator( @@ -423,7 +410,7 @@ std::unique_ptr DiskCache::NewIterator( return std::unique_ptr(database_->NewIterator(options)); } -DiskCache::OperationOutcome DiskCache::ApplyBatch( +DiskCache::OperationOutcome<> DiskCache::ApplyBatch( std::unique_ptr batch) { if (!database_) { OLP_SDK_LOG_ERROR(kLogTag, "ApplyBatch: Database is not initialized"); @@ -465,9 +452,9 @@ DiskCache::OperationOutcome DiskCache::ApplyBatch( return NoError{}; } -bool DiskCache::RemoveKeysWithPrefix(const std::string& prefix, - uint64_t& removed_data_size, - const RemoveFilterFunc& filter) { +DiskCache::OperationOutcome<> DiskCache::RemoveKeysWithPrefix( + const std::string& prefix, uint64_t& removed_data_size, + const RemoveFilterFunc& filter) { uint64_t data_size = 0u; removed_data_size = 0u; @@ -479,7 +466,7 @@ bool DiskCache::RemoveKeysWithPrefix(const std::string& prefix, if (!iterator) { OLP_SDK_LOG_WARNING(kLogTag, "RemoveKeysWithPrefix: Database is uninitialized"); - return false; + return client::ApiError::PreconditionFailed(); } auto batch = std::make_unique(); @@ -514,7 +501,7 @@ bool DiskCache::RemoveKeysWithPrefix(const std::string& prefix, } removed_data_size = data_size; - return result.IsSuccessful(); + return result; } leveldb::Status DiskCache::InitializeDB(const StorageSettings& settings, diff --git a/olp-cpp-sdk-core/src/cache/DiskCache.h b/olp-cpp-sdk-core/src/cache/DiskCache.h index 4903c6253..54ee2d167 100644 --- a/olp-cpp-sdk-core/src/cache/DiskCache.h +++ b/olp-cpp-sdk-core/src/cache/DiskCache.h @@ -101,7 +101,8 @@ class DiskCache { using NoError = client::ApiNoResult; /// Operation result type - using OperationOutcome = client::ApiResponse; + template + using OperationOutcome = client::ApiResponse; /// Will be used to filter out keys to be removed in case they are protected. using RemoveFilterFunc = std::function; @@ -128,18 +129,15 @@ class DiskCache { /// take a very long time, so use with care. void Compact(); - OperationOutcome OpenError() const { return error_; } + OperationOutcome<> OpenError() const { return error_; } bool Put(const std::string& key, leveldb::Slice slice); - /// @deprecated Please use Get(const std::string&, - /// KeyValueCache::ValueTypePtr&) instead. - boost::optional Get(const std::string& key); - - bool Get(const std::string& key, KeyValueCache::ValueTypePtr& value); + OperationOutcome Get(const std::string& key); /// Remove single key/value from DB. - bool Remove(const std::string& key, uint64_t& removed_data_size); + OperationOutcome<> Remove(const std::string& key, + uint64_t& removed_data_size); /// Get a new leveldb cache iterator. Use options.fill_cache = false for bulk /// scans. @@ -147,12 +145,12 @@ class DiskCache { /// Allow batch writing so that we can delete and write multiple values at /// the same time. - OperationOutcome ApplyBatch(std::unique_ptr batch); + OperationOutcome<> ApplyBatch(std::unique_ptr batch); /// Empty prefix deleted everything from DB. Returns size of removed data. - bool RemoveKeysWithPrefix(const std::string& prefix, - uint64_t& removed_data_size, - const RemoveFilterFunc& filter = nullptr); + OperationOutcome<> RemoveKeysWithPrefix( + const std::string& prefix, uint64_t& removed_data_size, + const RemoveFilterFunc& filter = nullptr); /// Check if cache contains data with the key. bool Contains(const std::string& key); @@ -183,7 +181,7 @@ class DiskCache { std::atomic compacting_{false}; /// Used to asynchronously call database_->CompactRange(). std::thread compaction_thread_; - OperationOutcome error_; + OperationOutcome<> error_; }; } // namespace cache diff --git a/olp-cpp-sdk-core/tests/cache/DefaultCacheImplTest.cpp b/olp-cpp-sdk-core/tests/cache/DefaultCacheImplTest.cpp index d21ebd657..338489678 100644 --- a/olp-cpp-sdk-core/tests/cache/DefaultCacheImplTest.cpp +++ b/olp-cpp-sdk-core/tests/cache/DefaultCacheImplTest.cpp @@ -122,7 +122,7 @@ class DefaultCacheImplHelper : public cache::DefaultCacheImpl { return false; } - return disk_cache->Get(key) != boost::none; + return disk_cache->Get(key).IsSuccessful(); } uint64_t CalculateExpirySize(const std::string& key) const { @@ -132,7 +132,12 @@ class DefaultCacheImplHelper : public cache::DefaultCacheImpl { return 0u; } - const auto expiry_str = disk_cache->Get(expiry_key).get_value_or({}); + auto expiry_result = disk_cache->Get(expiry_key); + if (!expiry_result) { + return 0u; + } + std::string expiry_str(expiry_result.GetResult()->begin(), + expiry_result.GetResult()->end()); if (expiry_str.empty()) { return 0u; } diff --git a/olp-cpp-sdk-dataservice-read/tests/CatalogCacheRepositoryTest.cpp b/olp-cpp-sdk-dataservice-read/tests/CatalogCacheRepositoryTest.cpp index 1788fd22d..e5a0472c8 100644 --- a/olp-cpp-sdk-dataservice-read/tests/CatalogCacheRepositoryTest.cpp +++ b/olp-cpp-sdk-dataservice-read/tests/CatalogCacheRepositoryTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 HERE Europe B.V. + * Copyright (C) 2020-2024 HERE Europe B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,23 +26,21 @@ namespace { -using namespace olp; -using namespace olp::dataservice::read; - constexpr auto kCatalog = "hrn:here:data::olp-here-test:catalog"; -TEST(PartitionsCacheRepositoryTest, DefaultExpiry) { - const auto hrn = client::HRN::FromString(kCatalog); +TEST(CatalogCacheRepositoryTest, DefaultExpiry) { + const auto hrn = olp::client::HRN::FromString(kCatalog); - model::Catalog model_catalog; + olp::dataservice::read::model::Catalog model_catalog; { SCOPED_TRACE("Disable expiration"); const auto default_expiry = std::chrono::seconds::max(); - std::shared_ptr cache = + std::shared_ptr cache = olp::client::OlpClientSettingsFactory::CreateDefaultCache({}); - repository::CatalogCacheRepository repository(hrn, cache, default_expiry); + olp::dataservice::read::repository::CatalogCacheRepository repository( + hrn, cache, default_expiry); repository.Put(model_catalog); const auto result = repository.Get(); @@ -54,9 +52,10 @@ TEST(PartitionsCacheRepositoryTest, DefaultExpiry) { SCOPED_TRACE("Expired"); const auto default_expiry = std::chrono::seconds(-1); - std::shared_ptr cache = + std::shared_ptr cache = olp::client::OlpClientSettingsFactory::CreateDefaultCache({}); - repository::CatalogCacheRepository repository(hrn, cache, default_expiry); + olp::dataservice::read::repository::CatalogCacheRepository repository( + hrn, cache, default_expiry); repository.Put(model_catalog); const auto result = repository.Get();