diff --git a/receiver/src/data_cache.cpp b/receiver/src/data_cache.cpp index 02f963e28c079dc6e7a42514d56b705d498ab3da..8355ba2b3c90e530bf2d61e6affe59e6c2fe8f89 100644 --- a/receiver/src/data_cache.cpp +++ b/receiver/src/data_cache.cpp @@ -1,4 +1,5 @@ #include "data_cache.h" +#include "data_cache.h" #include <iostream> #include <chrono> @@ -97,22 +98,27 @@ bool Intersects(uint64_t left1, uint64_t right1, uint64_t left2, uint64_t right2 } bool DataCache::CleanOldSlots(uint64_t size) { - uint64_t n_del = 0; + int64_t last_del = -1; + bool was_intersecting = false; for (uint64_t i = 0; i < meta_.size(); i++) { uint64_t start_position = (uint8_t*) meta_[i]->addr - cache_.get(); if (Intersects(start_position, start_position + meta_[i]->size, cur_pointer_ - size, cur_pointer_)) { - n_del++; + last_del = i; + was_intersecting = true; } else { - break; + if (cur_pointer_ - size > 0 || was_intersecting) { + break; // if we (re)started from 0, the intersecting slot might be not number 0, so we don't break until intersection was found + } } } - for (uint64_t i = 0; i < n_del; i++) { + for (int i = 0; i <= last_del; i++) { if (meta_[i]->lock > 0) return false; } - meta_.erase(meta_.begin(), meta_.begin() + n_del); - + if (last_del >=0) { + meta_.erase(meta_.begin(), meta_.begin() + last_del + 1); + } return true; } @@ -129,4 +135,4 @@ bool DataCache::UnlockSlot(CacheMeta* meta) { return true; } -} \ No newline at end of file +} diff --git a/receiver/unittests/test_datacache.cpp b/receiver/unittests/test_datacache.cpp index 1994fdad2fe0d07d99c545e8058098f697ecc751..d305c50051bdd7ba628ef6f69722dd3e842edbca 100644 --- a/receiver/unittests/test_datacache.cpp +++ b/receiver/unittests/test_datacache.cpp @@ -122,18 +122,29 @@ TEST_F(DataCacheTests, PrepareToReadFailsIfTooCloseToCurrentPointer) { } TEST_F(DataCacheTests, GetFreeSlotRemovesOldMetadataRecords) { + DataCache cache{expected_cache_size, 0}; CacheMeta* meta3, *meta4, *meta5; CacheMeta* meta; - cache.GetFreeSlotAndLock(10, &meta1); + auto addr = cache.GetFreeSlotAndLock(10, &meta1); cache.GetFreeSlotAndLock(10, &meta2); cache.GetFreeSlotAndLock(expected_cache_size - 30, &meta3); + auto id1 = meta1->id; + auto id2 = meta2->id; + auto id3 = meta3->id; + + cache.UnlockSlot(meta1); + cache.UnlockSlot(meta2); + cache.UnlockSlot(meta3); + cache.GetFreeSlotAndLock(10, &meta4); + auto id4 = meta4->id; + cache.UnlockSlot(meta4); cache.GetFreeSlotAndLock(30, &meta5); - uint8_t* addr1 = (uint8_t*) cache.GetSlotToReadAndLock(meta1->id, 10, &meta); - uint8_t* addr2 = (uint8_t*) cache.GetSlotToReadAndLock(meta2->id, 10, &meta); - uint8_t* addr3 = (uint8_t*) cache.GetSlotToReadAndLock(meta3->id, expected_cache_size - 30, &meta); - uint8_t* addr4 = (uint8_t*) cache.GetSlotToReadAndLock(meta4->id, 10, &meta); + uint8_t* addr1 = (uint8_t*) cache.GetSlotToReadAndLock(id1, 10, &meta); + uint8_t* addr2 = (uint8_t*) cache.GetSlotToReadAndLock(id2, 10, &meta); + uint8_t* addr3 = (uint8_t*) cache.GetSlotToReadAndLock(id3, expected_cache_size - 30, &meta); + uint8_t* addr4 = (uint8_t*) cache.GetSlotToReadAndLock(id4, 10, &meta); ASSERT_THAT(addr1, Eq(nullptr)); ASSERT_THAT(addr2, Eq(nullptr)); @@ -142,6 +153,48 @@ TEST_F(DataCacheTests, GetFreeSlotRemovesOldMetadataRecords) { ASSERT_THAT(meta->size, Eq(10)); } +TEST_F(DataCacheTests, GetFreeSlotRemovesOldWhenCrossTheBoundary) { + DataCache cache{expected_cache_size, 0}; + CacheMeta* meta1, *meta2, *meta3; + CacheMeta* meta4,*meta5,*meta; + auto addr1_alloc = cache.GetFreeSlotAndLock(expected_cache_size/3-1, &meta1); + auto addr2_alloc = cache.GetFreeSlotAndLock(expected_cache_size/3-1, &meta2); + auto addr3_alloc = cache.GetFreeSlotAndLock(expected_cache_size/3-1, &meta3); + auto id1 = meta1->id; + auto id2 = meta2->id; + auto id3 = meta3->id; + cache.UnlockSlot(meta1); + cache.UnlockSlot(meta2); + cache.UnlockSlot(meta3); + auto addr4_alloc = cache.GetFreeSlotAndLock(expected_cache_size/2+5, &meta4); + auto id4 = meta4->id; + cache.UnlockSlot(meta4); + auto addr5_alloc = cache.GetFreeSlotAndLock(expected_cache_size/2+5, &meta5); + auto id5 = meta5->id; + + uint8_t* addr1 = (uint8_t*) cache.GetSlotToReadAndLock(id1, expected_cache_size/3-1, &meta); + uint8_t* addr2 = (uint8_t*) cache.GetSlotToReadAndLock(id2, expected_cache_size/3-1, &meta); + uint8_t* addr3 = (uint8_t*) cache.GetSlotToReadAndLock(id3, expected_cache_size/3-1, &meta); + uint8_t* addr4 = (uint8_t*) cache.GetSlotToReadAndLock(id4, expected_cache_size/2+5, &meta); + uint8_t* addr5 = (uint8_t*) cache.GetSlotToReadAndLock(id5, expected_cache_size/2+5, &meta); + + ASSERT_THAT(addr1_alloc, Ne(nullptr)); + ASSERT_THAT(addr2_alloc, Ne(nullptr)); + ASSERT_THAT(addr3_alloc, Ne(nullptr)); + ASSERT_THAT(addr4_alloc, Ne(nullptr)); + ASSERT_THAT(addr5_alloc, Ne(nullptr)); + + ASSERT_THAT(addr1, Eq(nullptr)); + ASSERT_THAT(addr2, Eq(nullptr)); + ASSERT_THAT(addr3, Eq(nullptr)); + ASSERT_THAT(addr4, Eq(nullptr)); + ASSERT_THAT(addr5, Ne(nullptr)); + + + ASSERT_THAT(meta->size, Eq(expected_cache_size/2+5)); +} + + TEST_F(DataCacheTests, GetSlotToReadSizeOk) { CacheMeta* meta;