@@ -85,6 +85,7 @@ class TieredStorage::ShardOpManager : public tiering::OpManager {
8585
8686 // Clear IO pending flag for entry
8787 void ClearIoPending (OpManager::KeyRef key) {
88+ UnblockBackpressure (key, false );
8889 if (auto pv = Find (key); pv) {
8990 pv->SetStashPending (false );
9091 stats_.total_cancels ++;
@@ -143,6 +144,7 @@ class TieredStorage::ShardOpManager : public tiering::OpManager {
143144 // Find entry by key in db_slice and store external segment in place of original value.
144145 // Update memory stats
145146 void SetExternal (OpManager::KeyRef key, tiering::DiskSegment segment) {
147+ UnblockBackpressure (key, true );
146148 if (auto * pv = Find (key); pv) {
147149 auto * stats = GetDbTableStats (key.first );
148150
@@ -169,6 +171,12 @@ class TieredStorage::ShardOpManager : public tiering::OpManager {
169171 SetExternal ({sub_dbid, sub_key}, sub_segment);
170172 }
171173
174+ // If any backpressure (throttling) is active, notify that the operation finished
175+ void UnblockBackpressure (OpManager::KeyRef id, bool result) {
176+ if (auto node = ts_->stash_backpressure_ .extract (id); !node.empty ())
177+ node.mapped ().Resolve (result);
178+ }
179+
172180 struct {
173181 uint64_t total_stashes = 0 , total_cancels = 0 , total_fetches = 0 ;
174182 uint64_t total_defrags = 0 ;
@@ -309,6 +317,8 @@ error_code TieredStorage::Open(string_view base_path) {
309317}
310318
311319void TieredStorage::Close () {
320+ for (auto & [_, f] : stash_backpressure_)
321+ f.Resolve (false );
312322 op_manager_->Close ();
313323}
314324
@@ -350,9 +360,10 @@ template TieredStorage::TResult<size_t> TieredStorage::Modify(
350360 DbIndex dbid, std::string_view key, const PrimeValue& value,
351361 std::function<size_t (std::string*)> modf);
352362
353- bool TieredStorage::TryStash (DbIndex dbid, string_view key, PrimeValue* value) {
363+ std::optional<util::fb2::Future<bool >> TieredStorage::TryStash (DbIndex dbid, string_view key,
364+ PrimeValue* value, bool provide_bp) {
354365 if (!ShouldStash (*value))
355- return false ;
366+ return {} ;
356367
357368 // This invariant should always hold because ShouldStash tests for IoPending flag.
358369 CHECK (!bins_->IsPending (dbid, key));
@@ -361,7 +372,7 @@ bool TieredStorage::TryStash(DbIndex dbid, string_view key, PrimeValue* value) {
361372 // with a lot of underutilized disk space.
362373 if (op_manager_->GetStats ().pending_stash_cnt >= config_.write_depth_limit ) {
363374 ++stats_.stash_overflow_cnt ;
364- return false ;
375+ return {} ;
365376 }
366377
367378 StringOrView raw_string = value->GetRawString ();
@@ -375,15 +386,21 @@ bool TieredStorage::TryStash(DbIndex dbid, string_view key, PrimeValue* value) {
375386 } else if (auto bin = bins_->Stash (dbid, key, raw_string.view ()); bin) {
376387 id = bin->first ;
377388 ec = op_manager_->Stash (id, bin->second );
389+ } else {
390+ return {}; // Silently added to bin
378391 }
379392
380393 if (ec) {
381394 LOG_IF (ERROR, ec != errc::file_too_large) << " Stash failed immediately" << ec.message ();
382395 visit ([this ](auto id) { op_manager_->ClearIoPending (id); }, id);
383- return false ;
396+ return {} ;
384397 }
385398
386- return true ;
399+ // If we are in the active offloading phase, throttle stashes by providing backpressure future
400+ if (provide_bp && ShouldOffload ())
401+ return stash_backpressure_[{dbid, string{key}}];
402+
403+ return {};
387404}
388405
389406void TieredStorage::Delete (DbIndex dbid, PrimeValue* value) {
@@ -405,6 +422,11 @@ void TieredStorage::Delete(DbIndex dbid, PrimeValue* value) {
405422
406423void TieredStorage::CancelStash (DbIndex dbid, std::string_view key, PrimeValue* value) {
407424 DCHECK (value->HasStashPending ());
425+
426+ // If any previous write was happening, it has been cancelled
427+ if (auto node = stash_backpressure_.extract (make_pair (dbid, key)); !node.empty ())
428+ std::move (node.mapped ()).Resolve (false );
429+
408430 if (OccupiesWholePages (value->Size ())) {
409431 op_manager_->Delete (KeyRef (dbid, key));
410432 } else if (auto bin = bins_->Delete (dbid, key); bin) {
0 commit comments