Skip to content

Commit b8263e5

Browse files
committed
memtable_list: safely futurize clear_and_add
Following a4be927 that reverted 2325c56 due to scylladb#10421, this patch reintroduces an async version of memtable_list::clear_and_add that calls clear_gently safely after replacing the _memtables vector with a new one so that writes and flushes can continue in he foreground while the old memtables are cleared. Fixes scylladb#10281 Signed-off-by: Benny Halevy <[email protected]>
1 parent aae532a commit b8263e5

File tree

3 files changed

+19
-12
lines changed

3 files changed

+19
-12
lines changed

replica/database.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,20 @@ lw_shared_ptr<memtable> memtable_list::new_memtable() {
15741574
return make_lw_shared<memtable>(_current_schema(), *_dirty_memory_manager, _table_stats, this, _compaction_scheduling_group);
15751575
}
15761576

1577+
// Synchronously swaps the active memtable with a new, empty one,
1578+
// then, clears the existing memtable(s) asynchronously.
1579+
// Exception safe.
1580+
future<> memtable_list::clear_and_add() {
1581+
std::vector<replica::shared_memtable> new_memtables;
1582+
new_memtables.emplace_back(new_memtable());
1583+
auto old_memtables = std::exchange(_memtables, std::move(new_memtables));
1584+
// Now that the existing _memtables vector is swapped with new_memtables
1585+
// the function can yield for clearing the old_memtables.
1586+
for (auto& smt : old_memtables) {
1587+
co_await smt->clear_gently();
1588+
}
1589+
}
1590+
15771591
} // namespace replica
15781592

15791593
future<flush_permit> flush_permit::reacquire_sstable_write_permit() && {

replica/database.hh

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,17 +219,10 @@ public:
219219
}
220220
}
221221

222-
// Clears the active memtable and adds a new, empty one.
222+
// Synchronously swaps the active memtable with a new, empty one,
223+
// then, clears the existing memtable(s) asynchronously.
223224
// Exception safe.
224-
void clear_and_add() {
225-
auto mt = new_memtable();
226-
_memtables.clear();
227-
// emplace_back might throw only if _memtables was empty
228-
// on entry. Otherwise, we rely on clear() not to release
229-
// the vector capacity (See https://en.cppreference.com/w/cpp/container/vector/clear)
230-
// and lw_shared_ptr being nothrow move constructible.
231-
_memtables.emplace_back(std::move(mt));
232-
}
225+
future<> clear_and_add();
233226

234227
size_t size() const {
235228
return _memtables.size();

replica/table.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,8 +1502,8 @@ future<> table::clear() {
15021502
_commitlog->discard_completed_segments(_schema->id(), t->get_and_discard_rp_set());
15031503
}
15041504
}
1505-
_memtables->clear_and_add();
1506-
return _cache.invalidate(row_cache::external_updater([] { /* There is no underlying mutation source */ }));
1505+
co_await _memtables->clear_and_add();
1506+
co_await _cache.invalidate(row_cache::external_updater([] { /* There is no underlying mutation source */ }));
15071507
}
15081508

15091509
// NOTE: does not need to be futurized, but might eventually, depending on

0 commit comments

Comments
 (0)