mvcc, mutation_partition: Document guarantees in case merging succeeds

It's not obvious that invariants for partial merge do not hold for a
completed merge.

This is due to the fact that an empty source partition, which is
always empty after merge, is always fully continuous.
This commit is contained in:
Tomasz Grabiec
2022-12-08 12:07:32 +01:00
parent 8ae78ffebd
commit c7f7377ea3
4 changed files with 13 additions and 0 deletions

View File

@@ -1295,6 +1295,9 @@ public:
// object contains at least all the writes it contained before the call (monotonicity). It may contain partial writes.
// Also, some progress is always guaranteed (liveness).
//
// If returns stop_iteration::yes, then the sum of this and p is NO LONGER the same as before the call,
// the state of p is undefined and should not be used for reading.
//
// The operation can be driven to completion like this:
//
// apply_resume res;

View File

@@ -475,9 +475,14 @@ stop_iteration mutation_partition_v2::apply_monotonically(const schema& s, mutat
lb_i = {};
}
++app_stats.row_writes;
// We must not return stop_iteration::no if we removed the last element from p._rows.
// Otherwise, p_i will be left empty, and thus fully continuous, violating the
// invariant that the sum of this and p has the same continuity as before merging.
if (made_progress && need_preempt() && p_i != p._rows.end()) {
return stop_iteration::no;
}
made_progress = true;
}
if (prev_compacted && lb_i != _rows.end()) {

View File

@@ -188,6 +188,9 @@ public:
// object contains at least all the writes it contained before the call (monotonicity). It may contain partial writes.
// Also, some progress is always guaranteed (liveness).
//
// If returns stop_iteration::yes, then the sum of this and p is NO LONGER the same as before the call,
// the state of p is undefined and should not be used for reading.
//
// The operation can be driven to completion like this:
//
// apply_resume res;

View File

@@ -196,6 +196,8 @@ stop_iteration partition_snapshot::merge_partition_versions(mutation_application
if (do_stop_iteration == stop_iteration::no) {
return stop_iteration::no;
}
// If do_stop_iteration is yes, we have to remove the previous version.
// It now appears as fully continuous because it is empty.
_version_merging_state.reset();
if (prev->is_referenced()) {
_version.release();