From 131da3085695bb13797254a32c8ccc8da21d545f Mon Sep 17 00:00:00 2001 From: Calle Wilund Date: Mon, 31 May 2021 16:18:27 +0000 Subject: [PATCH] table: Always use explicit commitlog discard + clear out rp_set Fixes #8733 If a memtable flush is still pending when we call table::clear(), we can end up doing a "discard-all" call to commitlog, followed by a per-segment-count (using rp_set) _later_. This will foobar our internal usage counts and quite probably cause assertion failures. Fixed by always doing per-memtable explicit discard call. But to ensure this works, since a memtable being flushed remains on memtable list for a while (why?), we must also ensure we clear out the rp_set on discard. Closes #8766 --- memtable.hh | 4 ++-- table.cc | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/memtable.hh b/memtable.hh index 3a78c734f7..5752880408 100644 --- a/memtable.hh +++ b/memtable.hh @@ -272,8 +272,8 @@ public: const db::replay_position& replay_position() const { return _replay_position; } - const db::rp_set& rp_set() const { - return _rp_set; + db::rp_set rp_set() { + return std::exchange(_rp_set, {}); } friend class iterator_reader; diff --git a/table.cc b/table.cc index b801c4a9ea..7a9ae7f41f 100644 --- a/table.cc +++ b/table.cc @@ -1504,7 +1504,9 @@ bool table::can_flush() const { future<> table::clear() { _memtables->clear_and_add(); if (_commitlog) { - _commitlog->discard_completed_segments(_schema->id()); + for (auto& t : *_memtables) { + _commitlog->discard_completed_segments(_schema->id(), t->rp_set()); + } } return _cache.invalidate(row_cache::external_updater([] { /* There is no underlying mutation source */ })); }