diff --git a/src/server/db_slice.cc b/src/server/db_slice.cc index 24dfabbf9..5109574b4 100644 --- a/src/server/db_slice.cc +++ b/src/server/db_slice.cc @@ -328,7 +328,6 @@ void DbSlice::AutoUpdater::Run() { if (fields_.action == DestructorAction::kDoNothing) { return; } - // TBD add logic to update iterator if needed as we can now preempt in cb // Check that AutoUpdater does not run after a key was removed. // If this CHECK() failed for you, it probably means that you deleted a key while having an auto @@ -336,17 +335,23 @@ void DbSlice::AutoUpdater::Run() { DCHECK(IsValid(fields_.db_slice->db_arr_[fields_.db_ind]->prime.Find(fields_.key))) << "Key was removed before PostUpdate() - this is a bug!"; - // Make sure that the DB has not changed in size since this object was created. - // Adding or removing elements from the DB may invalidate iterators. - CHECK_EQ(fields_.db_size, fields_.db_slice->DbSize(fields_.db_ind)) - << "Attempting to run post-update after DB was modified"; - - CHECK_EQ(fields_.deletion_count, fields_.db_slice->deletion_count_) - << "Attempting to run post-update after a deletion was issued"; - DCHECK(fields_.action == DestructorAction::kRun); CHECK_NE(fields_.db_slice, nullptr); + if (shard_set->IsTieringEnabled()) { + // When triering is enabled we can preempt on write to disk, therefore it can be invalidated + // until we run the post updated. + fields_.it = fields_.db_slice->db_arr_[fields_.db_ind]->Launder(fields_.it, fields_.key); + } else { + // Make sure that the DB has not changed in size since this object was created. + // Adding or removing elements from the DB may invalidate iterators. + CHECK_EQ(fields_.db_size, fields_.db_slice->DbSize(fields_.db_ind)) + << "Attempting to run post-update after DB was modified"; + + CHECK_EQ(fields_.deletion_count, fields_.db_slice->deletion_count_) + << "Attempting to run post-update after a deletion was issued"; + } + fields_.db_slice->PostUpdate(fields_.db_ind, fields_.it, fields_.key, fields_.orig_heap_size); Cancel(); // Reset to not run again } diff --git a/src/server/table.cc b/src/server/table.cc index 53cbcb16b..17d92e8f7 100644 --- a/src/server/table.cc +++ b/src/server/table.cc @@ -116,4 +116,11 @@ void DbTable::Clear() { stats = DbTableStats{}; } +PrimeIterator DbTable::Launder(PrimeIterator it, std::string_view key) { + if (!it.IsOccupied() || it->first != key) { + it = prime.Find(key); + } + return it; +} + } // namespace dfly diff --git a/src/server/table.h b/src/server/table.h index 948920211..014a213a2 100644 --- a/src/server/table.h +++ b/src/server/table.h @@ -144,6 +144,7 @@ struct DbTable : boost::intrusive_ref_counterfirst != key) { - it = pt->Find(key); - if (it.is_done()) { - // Entry was remove from db while reading from disk. (background expire task) - return it; - } - entry = &it->second; + // Read will preempt, update iterator if needed. + DbTable* table = db_slice_.GetDBTable(db_index); + it = table->Launder(it, key); + if (it.is_done()) { + // Entry was remove from db while reading from disk. (background expire task) + return it; } + entry = &it->second; if (!entry->IsExternal()) { // Because 2 reads can happen at the same time, then if the other read