@@ -30,6 +30,8 @@ namespace {
3030constexpr auto kLogTag = " DefaultCache" ;
3131constexpr auto kExpirySuffix = " ::expiry" ;
3232constexpr auto kMaxDiskSize = std::uint64_t (-1 );
33+ constexpr auto kMinDiskUsedThreshold = 0 .85f ;
34+ constexpr auto kMaxDiskUsedThreshold = 0 .9f ;
3335
3436// current epoch time contains 10 digits.
3537constexpr auto kExpiryValueSize = 10 ;
@@ -73,14 +75,12 @@ void PurgeDiskItem(const std::string& key, olp::cache::DiskCache& disk_cache,
7375 removed_data_size += data_size;
7476}
7577
76- size_t StoreExpiry (const std::string& key, olp::cache::DiskCache& disk_cache ,
78+ size_t StoreExpiry (const std::string& key, leveldb::WriteBatch& batch ,
7779 time_t expiry) {
7880 auto expiry_key = CreateExpiryKey (key);
7981 auto time_str = std::to_string (
8082 expiry + olp::cache::InMemoryCache::DefaultTimeProvider ()());
81- if (!disk_cache.Put (expiry_key, time_str)) {
82- return 0 ;
83- }
83+ batch.Put (expiry_key, time_str);
8484
8585 return expiry_key.size () + time_str.size ();
8686}
@@ -261,9 +261,7 @@ bool DefaultCacheImpl::Remove(const std::string& key) {
261261
262262 if (mutable_cache_) {
263263 uint64_t removed_data_size = 0 ;
264- if (!mutable_cache_->Remove (key, removed_data_size)) {
265- return false ;
266- }
264+ PurgeDiskItem (key, *mutable_cache_, removed_data_size);
267265
268266 mutable_cache_data_size_ -= removed_data_size;
269267 }
@@ -301,9 +299,6 @@ void DefaultCacheImpl::InitializeLru() {
301299 settings_.eviction_policy == EvictionPolicy::kLeastRecentlyUsed ) {
302300 mutable_cache_lru_ =
303301 std::make_unique<DiskLruCache>(settings_.max_disk_storage );
304- }
305-
306- if (mutable_cache_lru_) {
307302 OLP_SDK_LOG_INFO_F (kLogTag , " Initializing mutable lru cache." );
308303 }
309304
@@ -315,27 +310,18 @@ void DefaultCacheImpl::InitializeLru() {
315310 const auto & value = it->value ();
316311 mutable_cache_data_size_ += key.size () + value.size ();
317312
318- if (mutable_cache_lru_) {
319- // Skip expiry keys
320- if (IsExpiryKey (key)) {
321- continue ;
322- }
323-
313+ if (mutable_cache_lru_ && !IsExpiryKey (key)) {
324314 ++count;
325315 mutable_cache_lru_->Insert (key, value.size ());
326316 }
327317 }
328318
329- if (mutable_cache_lru_) {
330- const int64_t elapsed =
331- std::chrono::duration_cast<std::chrono::milliseconds>(
332- std::chrono::steady_clock::now () - start)
333- .count ();
334- OLP_SDK_LOG_INFO_F (kLogTag ,
335- " Mutable lru cache initialized: items=%" PRIu32
336- " , time=%" PRId64 " ms" ,
337- count, elapsed);
338- }
319+ const int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
320+ std::chrono::steady_clock::now () - start)
321+ .count ();
322+ OLP_SDK_LOG_INFO_F (
323+ kLogTag , " Cache initialized, items=%" PRIu32 " , time=%" PRId64 " ms" ,
324+ count, elapsed);
339325}
340326
341327void DefaultCacheImpl::RemoveKeyLru (const std::string& key) {
@@ -371,6 +357,53 @@ bool DefaultCacheImpl::PromoteKeyLru(const std::string& key) {
371357 return true ;
372358}
373359
360+ uint64_t DefaultCacheImpl::MaybeEvictData (leveldb::WriteBatch& batch) {
361+ if (!mutable_cache_ || !mutable_cache_lru_) {
362+ return 0 ;
363+ }
364+
365+ const auto max_size = kMaxDiskUsedThreshold * settings_.max_disk_storage ;
366+ if (mutable_cache_data_size_ < max_size) {
367+ return 0 ;
368+ }
369+
370+ const auto start = std::chrono::steady_clock::now ();
371+ int64_t evicted = 0u ;
372+ auto count = 0u ;
373+ const auto min_size = kMinDiskUsedThreshold * settings_.max_disk_storage ;
374+ for (auto it = mutable_cache_lru_->rbegin ();
375+ it != mutable_cache_lru_->rend () &&
376+ mutable_cache_data_size_ - evicted > min_size;) {
377+ const auto & key = it->key ();
378+ const auto expiry_key = CreateExpiryKey (key);
379+ auto expiry_value = mutable_cache_->Get (expiry_key);
380+ if (expiry_value) {
381+ evicted += expiry_key.size () + kExpiryValueSize ;
382+ batch.Delete (expiry_key);
383+ }
384+ evicted += key.size () + it->value ();
385+ ++count;
386+
387+ if (memory_cache_) {
388+ memory_cache_->Remove (it->key ());
389+ }
390+
391+ batch.Delete (key);
392+ mutable_cache_lru_->Erase (it);
393+ it = mutable_cache_lru_->rbegin ();
394+ }
395+
396+ int64_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
397+ std::chrono::steady_clock::now () - start)
398+ .count ();
399+ OLP_SDK_LOG_INFO_F (kLogTag ,
400+ " Evicted from mutable cache, items=%" PRId32
401+ " , time=%" PRId64 " ms, size=%" PRIu64,
402+ count, elapsed, evicted);
403+
404+ return evicted;
405+ }
406+
374407bool DefaultCacheImpl::PutMutableCache (const std::string& key,
375408 const leveldb::Slice& value,
376409 time_t expiry) {
@@ -387,20 +420,23 @@ bool DefaultCacheImpl::PutMutableCache(const std::string& key,
387420 return false ;
388421 }
389422
390- uint64_t data_size_change = 0u ;
423+ uint64_t added_data_size = 0u ;
424+ auto batch = std::make_unique<leveldb::WriteBatch>();
425+ batch->Put (key, value);
426+ added_data_size += key.size () + item_size;
427+
391428 if (IsExpiryValid (expiry)) {
392- auto expiry_data_size = StoreExpiry (key, *mutable_cache_, expiry);
393- if (expiry_data_size == 0 ) {
394- return false ;
395- }
396- data_size_change += expiry_data_size;
429+ added_data_size += StoreExpiry (key, *batch, expiry);
397430 }
398- data_size_change += key.size () + item_size;
399431
400- if (!mutable_cache_->Put (key, value)) {
432+ auto removed_data_size = MaybeEvictData (*batch);
433+
434+ auto result = mutable_cache_->ApplyBatch (std::move (batch));
435+ if (!result.IsSuccessful ()) {
401436 return false ;
402437 }
403- mutable_cache_data_size_ += data_size_change;
438+ mutable_cache_data_size_ += added_data_size;
439+ mutable_cache_data_size_ -= removed_data_size;
404440
405441 if (mutable_cache_lru_) {
406442 const auto result = mutable_cache_lru_->InsertOrAssign (key, item_size);
0 commit comments