]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/cache/cache_reservation_manager_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / cache / cache_reservation_manager_test.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 #include "cache/cache_reservation_manager.h"
10
11 #include <cstddef>
12 #include <cstring>
13 #include <memory>
14
15 #include "cache/cache_entry_roles.h"
16 #include "rocksdb/cache.h"
17 #include "rocksdb/slice.h"
18 #include "test_util/testharness.h"
19 #include "util/coding.h"
20
21 namespace ROCKSDB_NAMESPACE {
22 class CacheReservationManagerTest : public ::testing::Test {
23 protected:
24 static constexpr std::size_t kSizeDummyEntry =
25 CacheReservationManagerImpl<CacheEntryRole::kMisc>::GetDummyEntrySize();
26 static constexpr std::size_t kCacheCapacity = 4096 * kSizeDummyEntry;
27 static constexpr int kNumShardBits = 0; // 2^0 shard
28 static constexpr std::size_t kMetaDataChargeOverhead = 10000;
29
30 std::shared_ptr<Cache> cache = NewLRUCache(kCacheCapacity, kNumShardBits);
31 std::shared_ptr<CacheReservationManager> test_cache_rev_mng;
32
33 CacheReservationManagerTest() {
34 test_cache_rev_mng =
35 std::make_shared<CacheReservationManagerImpl<CacheEntryRole::kMisc>>(
36 cache);
37 }
38 };
39
40 TEST_F(CacheReservationManagerTest, GenerateCacheKey) {
41 std::size_t new_mem_used = 1 * kSizeDummyEntry;
42 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
43 ASSERT_EQ(s, Status::OK());
44 ASSERT_GE(cache->GetPinnedUsage(), 1 * kSizeDummyEntry);
45 ASSERT_LT(cache->GetPinnedUsage(),
46 1 * kSizeDummyEntry + kMetaDataChargeOverhead);
47
48 // Next unique Cache key
49 CacheKey ckey = CacheKey::CreateUniqueForCacheLifetime(cache.get());
50 // Get to the underlying values
51 uint64_t* ckey_data = reinterpret_cast<uint64_t*>(&ckey);
52 // Back it up to the one used by CRM (using CacheKey implementation details)
53 ckey_data[1]--;
54
55 // Specific key (subject to implementation details)
56 EXPECT_EQ(ckey_data[0], 0);
57 EXPECT_EQ(ckey_data[1], 2);
58
59 Cache::Handle* handle = cache->Lookup(ckey.AsSlice());
60 EXPECT_NE(handle, nullptr)
61 << "Failed to generate the cache key for the dummy entry correctly";
62 // Clean up the returned handle from Lookup() to prevent memory leak
63 cache->Release(handle);
64 }
65
66 TEST_F(CacheReservationManagerTest, KeepCacheReservationTheSame) {
67 std::size_t new_mem_used = 1 * kSizeDummyEntry;
68 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
69 ASSERT_EQ(s, Status::OK());
70 ASSERT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
71 1 * kSizeDummyEntry);
72 ASSERT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used);
73 std::size_t initial_pinned_usage = cache->GetPinnedUsage();
74 ASSERT_GE(initial_pinned_usage, 1 * kSizeDummyEntry);
75 ASSERT_LT(initial_pinned_usage,
76 1 * kSizeDummyEntry + kMetaDataChargeOverhead);
77
78 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
79 EXPECT_EQ(s, Status::OK())
80 << "Failed to keep cache reservation the same when new_mem_used equals "
81 "to current cache reservation";
82 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
83 1 * kSizeDummyEntry)
84 << "Failed to bookkeep correctly when new_mem_used equals to current "
85 "cache reservation";
86 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
87 << "Failed to bookkeep the used memory correctly when new_mem_used "
88 "equals to current cache reservation";
89 EXPECT_EQ(cache->GetPinnedUsage(), initial_pinned_usage)
90 << "Failed to keep underlying dummy entries the same when new_mem_used "
91 "equals to current cache reservation";
92 }
93
94 TEST_F(CacheReservationManagerTest,
95 IncreaseCacheReservationByMultiplesOfDummyEntrySize) {
96 std::size_t new_mem_used = 2 * kSizeDummyEntry;
97 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
98 EXPECT_EQ(s, Status::OK())
99 << "Failed to increase cache reservation correctly";
100 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
101 2 * kSizeDummyEntry)
102 << "Failed to bookkeep cache reservation increase correctly";
103 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
104 << "Failed to bookkeep the used memory correctly";
105 EXPECT_GE(cache->GetPinnedUsage(), 2 * kSizeDummyEntry)
106 << "Failed to increase underlying dummy entries in cache correctly";
107 EXPECT_LT(cache->GetPinnedUsage(),
108 2 * kSizeDummyEntry + kMetaDataChargeOverhead)
109 << "Failed to increase underlying dummy entries in cache correctly";
110 }
111
112 TEST_F(CacheReservationManagerTest,
113 IncreaseCacheReservationNotByMultiplesOfDummyEntrySize) {
114 std::size_t new_mem_used = 2 * kSizeDummyEntry + kSizeDummyEntry / 2;
115 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
116 EXPECT_EQ(s, Status::OK())
117 << "Failed to increase cache reservation correctly";
118 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
119 3 * kSizeDummyEntry)
120 << "Failed to bookkeep cache reservation increase correctly";
121 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
122 << "Failed to bookkeep the used memory correctly";
123 EXPECT_GE(cache->GetPinnedUsage(), 3 * kSizeDummyEntry)
124 << "Failed to increase underlying dummy entries in cache correctly";
125 EXPECT_LT(cache->GetPinnedUsage(),
126 3 * kSizeDummyEntry + kMetaDataChargeOverhead)
127 << "Failed to increase underlying dummy entries in cache correctly";
128 }
129
130 TEST(CacheReservationManagerIncreaseReservcationOnFullCacheTest,
131 IncreaseCacheReservationOnFullCache) {
132 ;
133 constexpr std::size_t kSizeDummyEntry =
134 CacheReservationManagerImpl<CacheEntryRole::kMisc>::GetDummyEntrySize();
135 constexpr std::size_t kSmallCacheCapacity = 4 * kSizeDummyEntry;
136 constexpr std::size_t kBigCacheCapacity = 4096 * kSizeDummyEntry;
137 constexpr std::size_t kMetaDataChargeOverhead = 10000;
138
139 LRUCacheOptions lo;
140 lo.capacity = kSmallCacheCapacity;
141 lo.num_shard_bits = 0; // 2^0 shard
142 lo.strict_capacity_limit = true;
143 std::shared_ptr<Cache> cache = NewLRUCache(lo);
144 std::shared_ptr<CacheReservationManager> test_cache_rev_mng =
145 std::make_shared<CacheReservationManagerImpl<CacheEntryRole::kMisc>>(
146 cache);
147
148 std::size_t new_mem_used = kSmallCacheCapacity + 1;
149 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
150 EXPECT_EQ(s, Status::MemoryLimit())
151 << "Failed to return status to indicate failure of dummy entry insertion "
152 "during cache reservation on full cache";
153 EXPECT_GE(test_cache_rev_mng->GetTotalReservedCacheSize(),
154 1 * kSizeDummyEntry)
155 << "Failed to bookkeep correctly before cache resevation failure happens "
156 "due to full cache";
157 EXPECT_LE(test_cache_rev_mng->GetTotalReservedCacheSize(),
158 kSmallCacheCapacity)
159 << "Failed to bookkeep correctly (i.e, bookkeep only successful dummy "
160 "entry insertions) when encountering cache resevation failure due to "
161 "full cache";
162 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
163 << "Failed to bookkeep the used memory correctly";
164 EXPECT_GE(cache->GetPinnedUsage(), 1 * kSizeDummyEntry)
165 << "Failed to insert underlying dummy entries correctly when "
166 "encountering cache resevation failure due to full cache";
167 EXPECT_LE(cache->GetPinnedUsage(), kSmallCacheCapacity)
168 << "Failed to insert underlying dummy entries correctly when "
169 "encountering cache resevation failure due to full cache";
170
171 new_mem_used = kSmallCacheCapacity / 2; // 2 dummy entries
172 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
173 EXPECT_EQ(s, Status::OK())
174 << "Failed to decrease cache reservation after encountering cache "
175 "reservation failure due to full cache";
176 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
177 2 * kSizeDummyEntry)
178 << "Failed to bookkeep cache reservation decrease correctly after "
179 "encountering cache reservation due to full cache";
180 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
181 << "Failed to bookkeep the used memory correctly";
182 EXPECT_GE(cache->GetPinnedUsage(), 2 * kSizeDummyEntry)
183 << "Failed to release underlying dummy entries correctly on cache "
184 "reservation decrease after encountering cache resevation failure due "
185 "to full cache";
186 EXPECT_LT(cache->GetPinnedUsage(),
187 2 * kSizeDummyEntry + kMetaDataChargeOverhead)
188 << "Failed to release underlying dummy entries correctly on cache "
189 "reservation decrease after encountering cache resevation failure due "
190 "to full cache";
191
192 // Create cache full again for subsequent tests
193 new_mem_used = kSmallCacheCapacity + 1;
194 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
195 EXPECT_EQ(s, Status::MemoryLimit())
196 << "Failed to return status to indicate failure of dummy entry insertion "
197 "during cache reservation on full cache";
198 EXPECT_GE(test_cache_rev_mng->GetTotalReservedCacheSize(),
199 1 * kSizeDummyEntry)
200 << "Failed to bookkeep correctly before cache resevation failure happens "
201 "due to full cache";
202 EXPECT_LE(test_cache_rev_mng->GetTotalReservedCacheSize(),
203 kSmallCacheCapacity)
204 << "Failed to bookkeep correctly (i.e, bookkeep only successful dummy "
205 "entry insertions) when encountering cache resevation failure due to "
206 "full cache";
207 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
208 << "Failed to bookkeep the used memory correctly";
209 EXPECT_GE(cache->GetPinnedUsage(), 1 * kSizeDummyEntry)
210 << "Failed to insert underlying dummy entries correctly when "
211 "encountering cache resevation failure due to full cache";
212 EXPECT_LE(cache->GetPinnedUsage(), kSmallCacheCapacity)
213 << "Failed to insert underlying dummy entries correctly when "
214 "encountering cache resevation failure due to full cache";
215
216 // Increase cache capacity so the previously failed insertion can fully
217 // succeed
218 cache->SetCapacity(kBigCacheCapacity);
219 new_mem_used = kSmallCacheCapacity + 1;
220 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
221 EXPECT_EQ(s, Status::OK())
222 << "Failed to increase cache reservation after increasing cache capacity "
223 "and mitigating cache full error";
224 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
225 5 * kSizeDummyEntry)
226 << "Failed to bookkeep cache reservation increase correctly after "
227 "increasing cache capacity and mitigating cache full error";
228 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
229 << "Failed to bookkeep the used memory correctly";
230 EXPECT_GE(cache->GetPinnedUsage(), 5 * kSizeDummyEntry)
231 << "Failed to insert underlying dummy entries correctly after increasing "
232 "cache capacity and mitigating cache full error";
233 EXPECT_LT(cache->GetPinnedUsage(),
234 5 * kSizeDummyEntry + kMetaDataChargeOverhead)
235 << "Failed to insert underlying dummy entries correctly after increasing "
236 "cache capacity and mitigating cache full error";
237 }
238
239 TEST_F(CacheReservationManagerTest,
240 DecreaseCacheReservationByMultiplesOfDummyEntrySize) {
241 std::size_t new_mem_used = 2 * kSizeDummyEntry;
242 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
243 ASSERT_EQ(s, Status::OK());
244 ASSERT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
245 2 * kSizeDummyEntry);
246 ASSERT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used);
247 ASSERT_GE(cache->GetPinnedUsage(), 2 * kSizeDummyEntry);
248 ASSERT_LT(cache->GetPinnedUsage(),
249 2 * kSizeDummyEntry + kMetaDataChargeOverhead);
250
251 new_mem_used = 1 * kSizeDummyEntry;
252 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
253 EXPECT_EQ(s, Status::OK())
254 << "Failed to decrease cache reservation correctly";
255 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
256 1 * kSizeDummyEntry)
257 << "Failed to bookkeep cache reservation decrease correctly";
258 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
259 << "Failed to bookkeep the used memory correctly";
260 EXPECT_GE(cache->GetPinnedUsage(), 1 * kSizeDummyEntry)
261 << "Failed to decrease underlying dummy entries in cache correctly";
262 EXPECT_LT(cache->GetPinnedUsage(),
263 1 * kSizeDummyEntry + kMetaDataChargeOverhead)
264 << "Failed to decrease underlying dummy entries in cache correctly";
265 }
266
267 TEST_F(CacheReservationManagerTest,
268 DecreaseCacheReservationNotByMultiplesOfDummyEntrySize) {
269 std::size_t new_mem_used = 2 * kSizeDummyEntry;
270 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
271 ASSERT_EQ(s, Status::OK());
272 ASSERT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
273 2 * kSizeDummyEntry);
274 ASSERT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used);
275 ASSERT_GE(cache->GetPinnedUsage(), 2 * kSizeDummyEntry);
276 ASSERT_LT(cache->GetPinnedUsage(),
277 2 * kSizeDummyEntry + kMetaDataChargeOverhead);
278
279 new_mem_used = kSizeDummyEntry / 2;
280 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
281 EXPECT_EQ(s, Status::OK())
282 << "Failed to decrease cache reservation correctly";
283 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
284 1 * kSizeDummyEntry)
285 << "Failed to bookkeep cache reservation decrease correctly";
286 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
287 << "Failed to bookkeep the used memory correctly";
288 EXPECT_GE(cache->GetPinnedUsage(), 1 * kSizeDummyEntry)
289 << "Failed to decrease underlying dummy entries in cache correctly";
290 EXPECT_LT(cache->GetPinnedUsage(),
291 1 * kSizeDummyEntry + kMetaDataChargeOverhead)
292 << "Failed to decrease underlying dummy entries in cache correctly";
293 }
294
295 TEST(CacheReservationManagerWithDelayedDecreaseTest,
296 DecreaseCacheReservationWithDelayedDecrease) {
297 constexpr std::size_t kSizeDummyEntry =
298 CacheReservationManagerImpl<CacheEntryRole::kMisc>::GetDummyEntrySize();
299 constexpr std::size_t kCacheCapacity = 4096 * kSizeDummyEntry;
300 constexpr std::size_t kMetaDataChargeOverhead = 10000;
301
302 LRUCacheOptions lo;
303 lo.capacity = kCacheCapacity;
304 lo.num_shard_bits = 0;
305 std::shared_ptr<Cache> cache = NewLRUCache(lo);
306 std::shared_ptr<CacheReservationManager> test_cache_rev_mng =
307 std::make_shared<CacheReservationManagerImpl<CacheEntryRole::kMisc>>(
308 cache, true /* delayed_decrease */);
309
310 std::size_t new_mem_used = 8 * kSizeDummyEntry;
311 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
312 ASSERT_EQ(s, Status::OK());
313 ASSERT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
314 8 * kSizeDummyEntry);
315 ASSERT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used);
316 std::size_t initial_pinned_usage = cache->GetPinnedUsage();
317 ASSERT_GE(initial_pinned_usage, 8 * kSizeDummyEntry);
318 ASSERT_LT(initial_pinned_usage,
319 8 * kSizeDummyEntry + kMetaDataChargeOverhead);
320
321 new_mem_used = 6 * kSizeDummyEntry;
322 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
323 EXPECT_EQ(s, Status::OK()) << "Failed to delay decreasing cache reservation";
324 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
325 8 * kSizeDummyEntry)
326 << "Failed to bookkeep correctly when delaying cache reservation "
327 "decrease";
328 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
329 << "Failed to bookkeep the used memory correctly";
330 EXPECT_EQ(cache->GetPinnedUsage(), initial_pinned_usage)
331 << "Failed to delay decreasing underlying dummy entries in cache";
332
333 new_mem_used = 7 * kSizeDummyEntry;
334 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
335 EXPECT_EQ(s, Status::OK()) << "Failed to delay decreasing cache reservation";
336 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
337 8 * kSizeDummyEntry)
338 << "Failed to bookkeep correctly when delaying cache reservation "
339 "decrease";
340 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
341 << "Failed to bookkeep the used memory correctly";
342 EXPECT_EQ(cache->GetPinnedUsage(), initial_pinned_usage)
343 << "Failed to delay decreasing underlying dummy entries in cache";
344
345 new_mem_used = 6 * kSizeDummyEntry - 1;
346 s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
347 EXPECT_EQ(s, Status::OK())
348 << "Failed to decrease cache reservation correctly when new_mem_used < "
349 "GetTotalReservedCacheSize() * 3 / 4 on delayed decrease mode";
350 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(),
351 6 * kSizeDummyEntry)
352 << "Failed to bookkeep correctly when new_mem_used < "
353 "GetTotalReservedCacheSize() * 3 / 4 on delayed decrease mode";
354 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), new_mem_used)
355 << "Failed to bookkeep the used memory correctly";
356 EXPECT_GE(cache->GetPinnedUsage(), 6 * kSizeDummyEntry)
357 << "Failed to decrease underlying dummy entries in cache when "
358 "new_mem_used < GetTotalReservedCacheSize() * 3 / 4 on delayed "
359 "decrease mode";
360 EXPECT_LT(cache->GetPinnedUsage(),
361 6 * kSizeDummyEntry + kMetaDataChargeOverhead)
362 << "Failed to decrease underlying dummy entries in cache when "
363 "new_mem_used < GetTotalReservedCacheSize() * 3 / 4 on delayed "
364 "decrease mode";
365 }
366
367 TEST(CacheReservationManagerDestructorTest,
368 ReleaseRemainingDummyEntriesOnDestruction) {
369 constexpr std::size_t kSizeDummyEntry =
370 CacheReservationManagerImpl<CacheEntryRole::kMisc>::GetDummyEntrySize();
371 constexpr std::size_t kCacheCapacity = 4096 * kSizeDummyEntry;
372 constexpr std::size_t kMetaDataChargeOverhead = 10000;
373
374 LRUCacheOptions lo;
375 lo.capacity = kCacheCapacity;
376 lo.num_shard_bits = 0;
377 std::shared_ptr<Cache> cache = NewLRUCache(lo);
378 {
379 std::shared_ptr<CacheReservationManager> test_cache_rev_mng =
380 std::make_shared<CacheReservationManagerImpl<CacheEntryRole::kMisc>>(
381 cache);
382 std::size_t new_mem_used = 1 * kSizeDummyEntry;
383 Status s = test_cache_rev_mng->UpdateCacheReservation(new_mem_used);
384 ASSERT_EQ(s, Status::OK());
385 ASSERT_GE(cache->GetPinnedUsage(), 1 * kSizeDummyEntry);
386 ASSERT_LT(cache->GetPinnedUsage(),
387 1 * kSizeDummyEntry + kMetaDataChargeOverhead);
388 }
389 EXPECT_EQ(cache->GetPinnedUsage(), 0 * kSizeDummyEntry)
390 << "Failed to release remaining underlying dummy entries in cache in "
391 "CacheReservationManager's destructor";
392 }
393
394 TEST(CacheReservationHandleTest, HandleTest) {
395 constexpr std::size_t kOneGigabyte = 1024 * 1024 * 1024;
396 constexpr std::size_t kSizeDummyEntry = 256 * 1024;
397 constexpr std::size_t kMetaDataChargeOverhead = 10000;
398
399 LRUCacheOptions lo;
400 lo.capacity = kOneGigabyte;
401 lo.num_shard_bits = 0;
402 std::shared_ptr<Cache> cache = NewLRUCache(lo);
403
404 std::shared_ptr<CacheReservationManager> test_cache_rev_mng(
405 std::make_shared<CacheReservationManagerImpl<CacheEntryRole::kMisc>>(
406 cache));
407
408 std::size_t mem_used = 0;
409 const std::size_t incremental_mem_used_handle_1 = 1 * kSizeDummyEntry;
410 const std::size_t incremental_mem_used_handle_2 = 2 * kSizeDummyEntry;
411 std::unique_ptr<CacheReservationManager::CacheReservationHandle> handle_1,
412 handle_2;
413
414 // To test consecutive CacheReservationManager::MakeCacheReservation works
415 // correctly in terms of returning the handle as well as updating cache
416 // reservation and the latest total memory used
417 Status s = test_cache_rev_mng->MakeCacheReservation(
418 incremental_mem_used_handle_1, &handle_1);
419 mem_used = mem_used + incremental_mem_used_handle_1;
420 ASSERT_EQ(s, Status::OK());
421 EXPECT_TRUE(handle_1 != nullptr);
422 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(), mem_used);
423 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), mem_used);
424 EXPECT_GE(cache->GetPinnedUsage(), mem_used);
425 EXPECT_LT(cache->GetPinnedUsage(), mem_used + kMetaDataChargeOverhead);
426
427 s = test_cache_rev_mng->MakeCacheReservation(incremental_mem_used_handle_2,
428 &handle_2);
429 mem_used = mem_used + incremental_mem_used_handle_2;
430 ASSERT_EQ(s, Status::OK());
431 EXPECT_TRUE(handle_2 != nullptr);
432 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(), mem_used);
433 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), mem_used);
434 EXPECT_GE(cache->GetPinnedUsage(), mem_used);
435 EXPECT_LT(cache->GetPinnedUsage(), mem_used + kMetaDataChargeOverhead);
436
437 // To test
438 // CacheReservationManager::CacheReservationHandle::~CacheReservationHandle()
439 // works correctly in releasing the cache reserved for the handle
440 handle_1.reset();
441 EXPECT_TRUE(handle_1 == nullptr);
442 mem_used = mem_used - incremental_mem_used_handle_1;
443 EXPECT_EQ(test_cache_rev_mng->GetTotalReservedCacheSize(), mem_used);
444 EXPECT_EQ(test_cache_rev_mng->GetTotalMemoryUsed(), mem_used);
445 EXPECT_GE(cache->GetPinnedUsage(), mem_used);
446 EXPECT_LT(cache->GetPinnedUsage(), mem_used + kMetaDataChargeOverhead);
447
448 // To test the actual CacheReservationManager object won't be deallocated
449 // as long as there remain handles pointing to it.
450 // We strongly recommend deallocating CacheReservationManager object only
451 // after all its handles are deallocated to keep things easy to reasonate
452 test_cache_rev_mng.reset();
453 EXPECT_GE(cache->GetPinnedUsage(), mem_used);
454 EXPECT_LT(cache->GetPinnedUsage(), mem_used + kMetaDataChargeOverhead);
455
456 handle_2.reset();
457 // The CacheReservationManager object is now deallocated since all the handles
458 // and its original pointer is gone
459 mem_used = mem_used - incremental_mem_used_handle_2;
460 EXPECT_EQ(mem_used, 0);
461 EXPECT_EQ(cache->GetPinnedUsage(), mem_used);
462 }
463 } // namespace ROCKSDB_NAMESPACE
464
465 int main(int argc, char** argv) {
466 ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
467 ::testing::InitGoogleTest(&argc, argv);
468 return RUN_ALL_TESTS();
469 }