| 1060 | } |
| 1061 | |
| 1062 | DEBUG_ONLY_TEST_F(AsyncDataCacheTest, shrinkWithSsdWrite) { |
| 1063 | constexpr uint64_t kRamBytes = 128UL << 20; |
| 1064 | constexpr uint64_t kSsdBytes = 512UL << 20; |
| 1065 | constexpr int kDataSize = 4096; |
| 1066 | initializeCache(kRamBytes, kSsdBytes); |
| 1067 | const int numEntries{10}; |
| 1068 | std::vector<CachePin> cachePins; |
| 1069 | uint64_t offset = 0; |
| 1070 | for (int i = 0; i < numEntries; ++i) { |
| 1071 | cachePins.push_back(newEntry(offset, kDataSize)); |
| 1072 | offset += kDataSize; |
| 1073 | } |
| 1074 | for (auto& pin : cachePins) { |
| 1075 | pin.entry()->setExclusiveToShared(); |
| 1076 | } |
| 1077 | |
| 1078 | std::atomic_bool writeStartFlag{false}; |
| 1079 | folly::EventCount writeStartWait; |
| 1080 | std::atomic_bool writeWaitFlag{true}; |
| 1081 | folly::EventCount writeWait; |
| 1082 | SCOPED_TESTVALUE_SET( |
| 1083 | "bytedance::bolt::cache::SsdCache::write", |
| 1084 | std::function<void(const SsdCache*)>(([&](const SsdCache* cache) { |
| 1085 | writeStartFlag = true; |
| 1086 | writeStartWait.notifyAll(); |
| 1087 | writeWait.await([&]() { return !writeWaitFlag.load(); }); |
| 1088 | }))); |
| 1089 | |
| 1090 | // Starts a write thread running at background. |
| 1091 | std::thread ssdWriteThread([&]() { |
| 1092 | cache_->ssdCache()->startWrite(); |
| 1093 | cache_->saveToSsd(); |
| 1094 | }); |
| 1095 | |
| 1096 | // Wait for the write thread to start, and block it while do cache shrink. |
| 1097 | writeStartWait.await([&]() { return writeStartFlag.load(); }); |
| 1098 | ASSERT_TRUE(cache_->ssdCache()->writeInProgress()); |
| 1099 | |
| 1100 | cachePins.clear(); |
| 1101 | cache_->shrink(kRamBytes); |
| 1102 | auto stats = cache_->refreshStats(); |
| 1103 | // Shrink can only reclaim some entries but not all as some of the cache |
| 1104 | // entries have been pickup for ssd write which is not evictable. |
| 1105 | ASSERT_LT(stats.numEntries, numEntries); |
| 1106 | ASSERT_GT(stats.numEmptyEntries, 0); |
| 1107 | ASSERT_GT(stats.numEvict, 0); |
| 1108 | ASSERT_GT(stats.numShared, 0); |
| 1109 | ASSERT_EQ(stats.numExclusive, 0); |
| 1110 | ASSERT_EQ(stats.numWaitExclusive, 0); |
| 1111 | |
| 1112 | // Wait for write to complete. |
| 1113 | writeWaitFlag = false; |
| 1114 | writeWait.notifyAll(); |
| 1115 | ssdWriteThread.join(); |
| 1116 | while (cache_->ssdCache()->writeInProgress()) { |
| 1117 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); // NOLINT |
| 1118 | } |
| 1119 |
nothing calls this directly
no test coverage detected