Skip to content

Commit

Permalink
if a node sends a Prepare and it is behind we send it a Fixed as well…
Browse files Browse the repository at this point in the history
… as the nack.
  • Loading branch information
simbo1905 committed Dec 14, 2024
1 parent b1213db commit 023dc58
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 4 deletions.
12 changes: 9 additions & 3 deletions trex2-lib/src/main/java/com/github/trex_paxos/TrexNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ private void algorithm(TrexMessage input,
if (number.lessThan(progress.highestPromised()) || logIndex <= progress.highestFixedIndex()) {
// nack a low nextPrepareMessage else any nextPrepareMessage for a fixed slot sending any accepts they are missing
messages.add(nack(prepare));
// if the other node is behind tell them that the slot is fixed. this will force them to catchup.
if( logIndex < progress.highestFixedIndex() ) {
journal.readAccept(progress.highestFixedIndex())
.ifPresent(fixedAccept ->
messages.add(new Fixed(nodeIdentifier, fixedAccept.slot(), fixedAccept.number())));
}
} else if (number.greaterThan(progress.highestPromised())) {
// ack a higher nextPrepareMessage
final var newProgress = progress.withHighestPromised(number);
Expand Down Expand Up @@ -320,9 +326,9 @@ case Catchup(final byte replyTo, _, final var otherFixedIndex, final var otherHi

/// If the other node has seen a higher promise then we must increase our term
/// to be higher. We do not update our promise as we would be doing that in a learning
/// message which is not part of the protocol. Instead, we bump or term. Next time we
/// produce an `accept` we will use our term and do a self accept to that which will
/// bump pur promise. We do not want to alter the promise when not an `accept` or `prepare` message.
/// message which is not part of the protocol. Instead, we bump or term. Next time we
/// produce an `accept` we will use our term and do a self accept to that which will
/// bump pur promise. We do not want to alter the promise when not an `accept` or `prepare` message.
if (otherHighestPromised.greaterThan(progress.highestPromised())) {
if (role == TrexRole.LEAD) {
assert this.term != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public Optional<Accept> readAccept(long logIndex) {
assert commands.isEmpty();

// Should get either nothing or a single prepare response.
assert messages.size() <= 1;
assert messages.size() <= 2;

// Verify response
if (!messages.isEmpty()) {
Expand Down Expand Up @@ -134,6 +134,13 @@ public Optional<Accept> readAccept(long logIndex) {
assert response.journaledAccept().isEmpty();
}
}

if( messages.size() == 2 ) {
assert testCase.fixedSlotRelation == ArbitraryValues.FixedSlotRelation.LESS;
var fixed = (Fixed) messages.getLast();
assert fixed.from() == nodeId;
assert fixed.slot() == otherIndex;
}
}

// Verify role changes
Expand All @@ -148,6 +155,7 @@ public Optional<Accept> readAccept(long logIndex) {
/// Provides test cases covering all combinations of relationships between
/// the node under test and the prepare message properties
@Provide
@SuppressWarnings("unused")
Arbitrary<TestCase> testCases() {
return Combinators.combine(
Arbitraries.of(ArbitraryValues.RoleState.values()),
Expand Down

0 comments on commit 023dc58

Please sign in to comment.