commitlog: Fix double clearing of _segment_allocating shared_future.

Fixes #10020

Previous fix 445e1d3 tried to close one double invocation,  but added
another, since it failed to ensure all potential nullings of the opt
shared_future happened before a new allocator could reset it.

This simplifies the code by making clearing the shared_future a
pre-requisite for resolving its contents (as read by waiters).

Also removes any need for try-catch etc.

Closes #10024
This commit is contained in:
Calle Wilund
2022-02-02 16:12:00 +00:00
committed by Avi Kivity
parent cb6630040d
commit 1e66043412

View File

@@ -1626,21 +1626,19 @@ future<db::commitlog::segment_manager::sseg_ptr> db::commitlog::segment_manager:
// the old one has terminated with either result or exception.
// Do all waiting through the shared_future
if (!_segment_allocating) {
_segment_allocating.emplace(new_segment().discard_result());
}
try {
co_await _segment_allocating->get_future(timeout);
// once we've managed to get a result, any of us, the
// shared_future should be released.
_segment_allocating = std::nullopt;
} catch (timed_out_error&) {
throw; // not thrown by new_segment. Just no result yet.
} catch (...) {
// once we've managed to get a result, any of us, the
// shared_future should be released.
_segment_allocating = std::nullopt;
throw;
auto f = new_segment();
// must check that we are not already done.
if (f.available()) {
f.get(); // maybe force exception
continue;
}
_segment_allocating.emplace(f.discard_result().finally([this] {
// clear the shared_future _before_ resolving its contents
// (i.e. with result of this finally)
_segment_allocating = std::nullopt;
}));
}
co_await _segment_allocating->get_future(timeout);
}
}