@@ -271,14 +271,15 @@ template util::fb2::Future<size_t> TieredStorage::Modify(DbIndex dbid, std::stri
271
271
const PrimeValue& value,
272
272
std::function<size_t (std::string*)> modf);
273
273
274
- void TieredStorage::Stash (DbIndex dbid, string_view key, PrimeValue* value) {
275
- CHECK (!value->IsExternal () && !value->HasIoPending ());
274
+ bool TieredStorage::TryStash (DbIndex dbid, string_view key, PrimeValue* value) {
275
+ if (!ShouldStash (*value))
276
+ return false ;
276
277
277
278
// TODO: When we are low on memory we should introduce a back-pressure, to avoid OOMs
278
279
// with a lot of underutilized disk space.
279
280
if (op_manager_->GetStats ().pending_stash_cnt >= write_depth_limit_) {
280
281
++stats_.stash_overflow_cnt ;
281
- return ;
282
+ return false ;
282
283
}
283
284
284
285
string buf;
@@ -298,7 +299,10 @@ void TieredStorage::Stash(DbIndex dbid, string_view key, PrimeValue* value) {
298
299
if (ec) {
299
300
LOG (ERROR) << " Stash failed immediately" << ec.message ();
300
301
visit ([this ](auto id) { op_manager_->ClearIoPending (id); }, id);
302
+ return false ;
301
303
}
304
+
305
+ return true ;
302
306
}
303
307
304
308
void TieredStorage::Delete (DbIndex dbid, PrimeValue* value) {
@@ -318,10 +322,6 @@ void TieredStorage::CancelStash(DbIndex dbid, std::string_view key, PrimeValue*
318
322
value->SetIoPending (false );
319
323
}
320
324
321
- bool TieredStorage::ShouldStash (const PrimeValue& pv) const {
322
- return !pv.IsExternal () && pv.ObjType () == OBJ_STRING && pv.Size () >= kMinValueSize ;
323
- }
324
-
325
325
float TieredStorage::WriteDepthUsage () const {
326
326
return 1 .0f * op_manager_->GetStats ().pending_stash_cnt / write_depth_limit_;
327
327
}
@@ -364,30 +364,26 @@ void TieredStorage::RunOffloading(DbIndex dbid) {
364
364
if (SliceSnapshot::IsSnaphotInProgress ())
365
365
return ;
366
366
367
- PrimeTable& table = op_manager_->db_slice_ ->GetDBTable (dbid)->prime ;
368
- int stash_limit = write_depth_limit_ - op_manager_->GetStats ().pending_stash_cnt ;
369
- if (stash_limit <= 0 )
370
- return ;
371
-
372
- std::string tmp;
373
- auto cb = [this , dbid, &tmp, &stash_limit](PrimeIterator it) {
374
- if (it->second .HasIoPending () || it->second .IsExternal ())
375
- return ;
376
-
377
- if (ShouldStash (it->second )) {
378
- Stash (dbid, it->first .GetSlice (&tmp), &it->second );
379
- stash_limit--;
380
- }
367
+ auto cb = [this , dbid, tmp = std::string{}](PrimeIterator it) mutable {
368
+ TryStash (dbid, it->first .GetSlice (&tmp), &it->second );
381
369
};
382
370
371
+ PrimeTable& table = op_manager_->db_slice_ ->GetDBTable (dbid)->prime ;
383
372
PrimeTable::Cursor start_cursor{};
384
373
385
374
// Loop while we haven't traversed all entries or reached our stash io device limit.
386
375
// Keep number of iterations below resonable limit to keep datastore always responsive
387
376
size_t iterations = 0 ;
388
377
do {
378
+ if (op_manager_->GetStats ().pending_stash_cnt >= write_depth_limit_)
379
+ break ;
389
380
offloading_cursor_ = table.TraverseBySegmentOrder (offloading_cursor_, cb);
390
- } while (offloading_cursor_ != start_cursor && stash_limit > 0 && iterations++ < 500 );
381
+ } while (offloading_cursor_ != start_cursor && iterations++ < 500 );
382
+ }
383
+
384
+ bool TieredStorage::ShouldStash (const PrimeValue& pv) const {
385
+ return !pv.IsExternal () && !pv.HasIoPending () && pv.ObjType () == OBJ_STRING &&
386
+ pv.Size () >= kMinValueSize ;
391
387
}
392
388
393
389
} // namespace dfly
0 commit comments