Strict Serializability Verifier may incorrectly handle blind writes when witnessed before the writing operation ACKs

patch by Benedict; reviewed by Alex Petrov for CASSANDRA-20905
This commit is contained in:
Benedict Elliott Smith 2025-09-15 21:34:15 +01:00
parent bf2c1c124e
commit c7de33c597
8 changed files with 12 additions and 12 deletions

4
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "modules/accord"] [submodule "modules/accord"]
path = modules/accord path = modules/accord
url = https://github.com/apache/cassandra-accord.git url = https://github.com/belliottsmith/cassandra-accord.git
branch = trunk branch = 20905-ssverifier

@ -1 +1 @@
Subproject commit 9c7f856c3e1f10c6f985495702edb844cfee2b80 Subproject commit ff4119fa45ad9700cfa94cd50b5cd4af9dd0b7a4

View File

@ -22,7 +22,7 @@ import javax.annotation.Nullable;
public interface HistoryValidator public interface HistoryValidator
{ {
Checker witness(int start, int end); Checker witness(Object witnessedBy, int start, int end);
void print(@Nullable Integer pk); void print(@Nullable Integer pk);

View File

@ -37,7 +37,7 @@ public class LinearizabilityValidator implements HistoryValidator
} }
@Override @Override
public Checker witness(int start, int end) public Checker witness(Object witnessedBy, int start, int end)
{ {
return new Checker() return new Checker()
{ {

View File

@ -35,11 +35,11 @@ public class LoggingHistoryValidator implements HistoryValidator
} }
@Override @Override
public Checker witness(int start, int end) public Checker witness(Object witnessedBy, int start, int end)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Witness(start=").append(start).append(", end=").append(end).append(")\n"); sb.append("Witness(start=").append(start).append(", end=").append(end).append(")\n");
Checker sub = delegate.witness(start, end); Checker sub = delegate.witness(witnessedBy, start, end);
return new Checker() return new Checker()
{ {
@Override @Override

View File

@ -203,7 +203,7 @@ public class PairOfSequencesAccordSimulation extends AbstractPairOfSequencesPaxo
IntHashSet seen = new IntHashSet(); IntHashSet seen = new IntHashSet();
//TODO if there isn't a value then we get empty read, which then doesn't make it into the QueryResult //TODO if there isn't a value then we get empty read, which then doesn't make it into the QueryResult
// given the fact that we always run with the partitions defined this should be fine // given the fact that we always run with the partitions defined this should be fine
try (HistoryValidator.Checker checker = validator.witness(outcome.start, outcome.end)) try (HistoryValidator.Checker checker = validator.witness(outcome, outcome.start, outcome.end))
{ {
while (result.hasNext()) while (result.hasNext())
{ {

View File

@ -43,7 +43,7 @@ public class StrictSerializabilityValidator implements HistoryValidator
} }
@Override @Override
public Checker witness(int start, int end) public Checker witness(Object witnessedBy, int start, int end)
{ {
verifier.begin(); verifier.begin();
return new Checker() return new Checker()
@ -63,7 +63,7 @@ public class StrictSerializabilityValidator implements HistoryValidator
@Override @Override
public void close() public void close()
{ {
convertHistoryViolation(() -> verifier.apply("", start, end)); convertHistoryViolation(() -> verifier.apply(witnessedBy, start, end));
} }
}; };
} }

View File

@ -326,7 +326,7 @@ public class HistoryValidatorTest
{ {
String type = events.length == 1 ? "single" : "multiple"; String type = events.length == 1 ? "single" : "multiple";
logger.info("[Validator={}, Observation=({}, {}, {})] Validating {} {}}", validator.getClass().getSimpleName(), ob.id, ob.start, ob.end, type, events); logger.info("[Validator={}, Observation=({}, {}, {})] Validating {} {}}", validator.getClass().getSimpleName(), ob.id, ob.start, ob.end, type, events);
try (HistoryValidator.Checker check = validator.witness(ob.start, ob.end)) try (HistoryValidator.Checker check = validator.witness(ob, ob.start, ob.end))
{ {
for (Event e : events) for (Event e : events)
e.process(ob, check); e.process(ob, check);
@ -477,7 +477,7 @@ public class HistoryValidatorTest
void process(HistoryValidator validator) void process(HistoryValidator validator)
{ {
try (HistoryValidator.Checker check = validator.witness(start, end)) try (HistoryValidator.Checker check = validator.witness("", start, end))
{ {
for (Operation a : actions) for (Operation a : actions)
a.check(check); a.check(check);