fix(server): Sync FLUSH with tiering (#3098)

* fix(server): Sync FLUSH with tiering

Signed-off-by: Vladislav Oleshko <vlad@dragonflydb.io>
This commit is contained in:
Vladislav 2024-05-30 16:50:12 +03:00 committed by GitHub
parent ba0f2932e5
commit 137bd313ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 71 additions and 13 deletions

View file

@ -704,7 +704,15 @@ void DbSlice::FlushSlots(cluster::SlotRanges slot_ranges) {
}
void DbSlice::FlushDbIndexes(const std::vector<DbIndex>& indexes) {
// TODO: to add preeemptiveness by yielding inside clear.
// Async cleanup can only be performed if no tiered entries exist
bool async_cleanup = true;
for (DbIndex index : indexes) {
async_cleanup &= db_arr_[index]->stats.tiered_entries == 0;
}
if (!async_cleanup)
ClearEntriesOnFlush(indexes, db_arr_, false);
DbTableArray flush_db_arr(db_arr_.size());
for (DbIndex index : indexes) {
auto& db = db_arr_[index];
@ -715,19 +723,11 @@ void DbSlice::FlushDbIndexes(const std::vector<DbIndex>& indexes) {
CreateDb(index);
std::swap(db_arr_[index]->trans_locks, flush_db_arr[index]->trans_locks);
}
CHECK(fetched_items_.empty());
auto cb = [this, flush_db_arr = std::move(flush_db_arr)]() mutable {
for (auto& db_ptr : flush_db_arr) {
if (db_ptr && db_ptr->stats.tiered_entries > 0) {
for (auto it = db_ptr->prime.begin(); it != db_ptr->prime.end(); ++it) {
if (it->second.IsExternal())
PerformDeletion(Iterator::FromPrime(it), db_ptr.get());
}
DCHECK_EQ(0u, db_ptr->stats.tiered_entries);
db_ptr.reset();
}
}
CHECK(fetched_items_.empty());
auto cb = [this, async_cleanup, indexes, flush_db_arr = std::move(flush_db_arr)]() mutable {
if (async_cleanup)
ClearEntriesOnFlush(indexes, flush_db_arr, true);
flush_db_arr.clear();
ServerState::tlocal()->DecommitMemory(ServerState::kDataHeap | ServerState::kBackingHeap |
ServerState::kGlibcmalloc);
@ -1382,6 +1382,30 @@ void DbSlice::InvalidateSlotWatches(const cluster::SlotSet& slot_ids) {
}
}
void DbSlice::ClearEntriesOnFlush(absl::Span<const DbIndex> indices, const DbTableArray& db_arr,
bool async) {
for (auto index : indices) {
const auto& db_ptr = db_arr[index];
if (!db_ptr || db_ptr->stats.tiered_entries == 0)
continue;
// Delete all tiered entries
PrimeTable::Cursor cursor;
do {
cursor = db_ptr->prime.Traverse(cursor, [&](PrimeIterator it) {
if (it->second.IsExternal())
PerformDeletion(it, db_ptr.get());
});
} while (cursor && db_ptr->stats.tiered_entries > 0);
// Wait for delete operations to finish in sync
while (!async && db_ptr->stats.tiered_entries > 0) {
LOG_EVERY_T(ERROR, 0.5) << "Long wait for tiered entry delete on flush";
ThisFiber::SleepFor(1ms);
}
}
}
void DbSlice::SetDocDeletionCallback(DocDeletionCallback ddcb) {
doc_del_cb_ = std::move(ddcb);
}