@@ -124,6 +124,98 @@ class AllocatorMemoryTiersTest : public AllocatorTest<AllocatorT> {
124
124
ASSERT (handle != nullptr );
125
125
ASSERT_NO_THROW (alloc->insertOrReplace (handle));
126
126
}
127
+
128
+ void testMultiTiersRemoveDuringEviction () {
129
+ bool quit = false ;
130
+ typename AllocatorT::Config config;
131
+ config.setCacheSize (4 * Slab::kSize );
132
+ config.enableCachePersistence (" /tmp" );
133
+ config.configureMemoryTiers ({
134
+ MemoryTierCacheConfig::fromShm ()
135
+ .setRatio (1 ).setMemBind ({0 }),
136
+ MemoryTierCacheConfig::fromShm ()
137
+ .setRatio (1 ).setMemBind ({0 })
138
+ });
139
+
140
+ std::unique_ptr<AllocatorT> alloc;
141
+ std::unique_ptr<std::thread> t;
142
+
143
+ const auto moveCb = [&] (typename AllocatorT::Item& oldItem,
144
+ typename AllocatorT::Item& newItem,
145
+ typename AllocatorT::Item* /* parentPtr */ ) {
146
+ memcpy (newItem.getMemory (), oldItem.getMemory (), oldItem.getSize ());
147
+ auto key = oldItem.getKey ();
148
+ t = std::make_unique<std::thread>([&](){ alloc->remove (key); });
149
+ // sleep to make sure async thread calls remove(key)
150
+ std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
151
+ quit = true ;
152
+ };
153
+ config.enableMovingOnSlabRelease (moveCb, {} /* ChainedItemsMoveSync */ ,
154
+ -1 /* movingAttemptsLimit */ );
155
+
156
+ alloc = std::make_unique<AllocatorT>(AllocatorT::SharedMemNew, config);
157
+ ASSERT (alloc != nullptr );
158
+ auto pool = alloc->addPool (" default" , alloc->getCacheMemoryStats ().cacheSize );
159
+
160
+ int i = 0 ;
161
+ while (!quit) {
162
+ auto handle = alloc->allocate (pool, std::to_string (++i), std::string (" value" ).size ());
163
+ ASSERT (handle != nullptr );
164
+ ASSERT_NO_THROW (alloc->insertOrReplace (handle));
165
+ }
166
+
167
+ t->join ();
168
+ }
169
+
170
+ void testMultiTiersReplaceDuringEviction () {
171
+ bool quit = false ;
172
+ typename AllocatorT::Config config;
173
+ config.setCacheSize (4 * Slab::kSize );
174
+ config.enableCachePersistence (" /tmp" );
175
+ config.configureMemoryTiers ({
176
+ MemoryTierCacheConfig::fromShm ()
177
+ .setRatio (1 ).setMemBind ({0 }),
178
+ MemoryTierCacheConfig::fromShm ()
179
+ .setRatio (1 ).setMemBind ({0 })
180
+ });
181
+
182
+ std::unique_ptr<AllocatorT> alloc;
183
+ PoolId pool;
184
+ std::unique_ptr<std::thread> t;
185
+
186
+ const auto moveCb = [&] (typename AllocatorT::Item& oldItem,
187
+ typename AllocatorT::Item& newItem,
188
+ typename AllocatorT::Item* /* parentPtr */ ) {
189
+ memcpy (newItem.getMemory (), oldItem.getMemory (), oldItem.getSize ());
190
+ auto key = oldItem.getKey ();
191
+ if (!quit) {
192
+ // we need to replace only once because subsequent allocate calls
193
+ // will cause evictions recursevly
194
+ quit = true ;
195
+ t = std::make_unique<std::thread>([&](){
196
+ auto handle = alloc->allocate (pool, key, std::string (" new value" ).size ());
197
+ ASSERT_NO_THROW (alloc->insertOrReplace (handle));
198
+ });
199
+ // sleep to make sure async thread calls remove(key)
200
+ std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
201
+ }
202
+ };
203
+ config.enableMovingOnSlabRelease (moveCb, {} /* ChainedItemsMoveSync */ ,
204
+ -1 /* movingAttemptsLimit */ );
205
+
206
+ alloc = std::make_unique<AllocatorT>(AllocatorT::SharedMemNew, config);
207
+ ASSERT (alloc != nullptr );
208
+ pool = alloc->addPool (" default" , alloc->getCacheMemoryStats ().cacheSize );
209
+
210
+ int i = 0 ;
211
+ while (!quit) {
212
+ auto handle = alloc->allocate (pool, std::to_string (++i), std::string (" value" ).size ());
213
+ ASSERT (handle != nullptr );
214
+ ASSERT_NO_THROW (alloc->insertOrReplace (handle));
215
+ }
216
+
217
+ t->join ();
218
+ }
127
219
};
128
220
} // namespace tests
129
221
} // namespace cachelib
0 commit comments