Skip to content

Commit

Permalink
tracker: maintain Match < Next invariant
Browse files Browse the repository at this point in the history
This commit documents the meaning of Match and Next field in the
Progress struct. It also ensures that the invariant is maintained in all
code places that initialize or modify these fields.

Signed-off-by: Pavel Kalinnikov <[email protected]>
  • Loading branch information
pav-kv committed Feb 15, 2024
1 parent 4d9f2f0 commit 53007f4
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 28 deletions.
2 changes: 1 addition & 1 deletion confchange/confchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ func (c Changer) initProgress(cfg *tracker.Config, trk tracker.ProgressMap, id u
// at all (and will thus likely need a snapshot), though the app may
// have applied a snapshot out of band before adding the replica (thus
// making the first index the better choice).
Next: c.LastIndex,
Match: 0,
Next: max(c.LastIndex, 1), // invariant: Match < Next
Inflights: tracker.NewInflights(c.Tracker.MaxInflight, c.Tracker.MaxInflightBytes),
IsLearner: isLearner,
// When a node is first added, we should mark it as recently active.
Expand Down
6 changes: 3 additions & 3 deletions confchange/testdata/joint_autoleave.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ simple
v1
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1

# Autoleave is reflected in the config.
enter-joint autoleave=true
v2 v3
----
voters=(1 2 3)&&(1) autoleave
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1
3: StateProbe match=0 next=1

Expand All @@ -24,6 +24,6 @@ config is already joint
leave-joint
----
voters=(1 2 3)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1
3: StateProbe match=0 next=1
6 changes: 3 additions & 3 deletions confchange/testdata/joint_idempotency.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ simple
v1
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1

enter-joint
r1 r2 r9 v2 v3 v4 v2 v3 v4 l2 l2 r4 r4 l1 l1
----
voters=(3)&&(1) learners=(2) learners_next=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1 learner
3: StateProbe match=0 next=1

leave-joint
----
voters=(3) learners=(1 2)
1: StateProbe match=0 next=0 learner
1: StateProbe match=0 next=1 learner
2: StateProbe match=0 next=1 learner
3: StateProbe match=0 next=1
6 changes: 3 additions & 3 deletions confchange/testdata/joint_learners_next.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ simple
v1
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1

enter-joint
v2 l1
----
voters=(2)&&(1) learners_next=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1

leave-joint
----
voters=(2) learners=(1)
1: StateProbe match=0 next=0 learner
1: StateProbe match=0 next=1 learner
2: StateProbe match=0 next=1
10 changes: 5 additions & 5 deletions confchange/testdata/simple_idempotency.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,33 @@ simple
v1
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1

simple
v1
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1

simple
v2
----
voters=(1 2)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=2

simple
l1
----
voters=(2) learners=(1)
1: StateProbe match=0 next=0 learner
1: StateProbe match=0 next=1 learner
2: StateProbe match=0 next=2

simple
l1
----
voters=(2) learners=(1)
1: StateProbe match=0 next=0 learner
1: StateProbe match=0 next=1 learner
2: StateProbe match=0 next=2

simple
Expand Down
14 changes: 7 additions & 7 deletions confchange/testdata/simple_promote_demote.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ simple
v1
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1

simple
v2
----
voters=(1 2)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1

simple
v3
----
voters=(1 2 3)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1
3: StateProbe match=0 next=2

Expand All @@ -27,7 +27,7 @@ simple
l1 v1
----
voters=(1 2 3)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1
3: StateProbe match=0 next=2

Expand All @@ -36,7 +36,7 @@ simple
l2
----
voters=(1 3) learners=(2)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1 learner
3: StateProbe match=0 next=2

Expand All @@ -46,7 +46,7 @@ simple
v2 l2
----
voters=(1 3) learners=(2)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1 learner
3: StateProbe match=0 next=2

Expand All @@ -55,6 +55,6 @@ simple
v2
----
voters=(1 2 3)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1
3: StateProbe match=0 next=2
6 changes: 3 additions & 3 deletions confchange/testdata/update.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ simple
v1
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1

simple
v2 u1
----
voters=(1 2)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1

simple
u1 u2 u3 u1 u2 u3
----
voters=(1 2)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
2: StateProbe match=0 next=1
2 changes: 1 addition & 1 deletion confchange/testdata/zero.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ simple
v1 r0 v0 l0
----
voters=(1)
1: StateProbe match=0 next=0
1: StateProbe match=0 next=1
11 changes: 9 additions & 2 deletions tracker/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@ import (
// strewn around `*raft.raft`. Additionally, some fields are only used when in a
// certain State. All of this isn't ideal.
type Progress struct {
Match, Next uint64
// Match is the index up to which the follower's log is known to match the
// leader's.
Match uint64
// Next is the log index of the next entry to send to this follower. All
// entries with indices in (Match, Next) interval are already in flight.
//
// Invariant: 0 <= Match < Next.
Next uint64

// State defines how the leader should interact with the follower.
//
// When in StateProbe, leader sends at most one replication message
Expand Down Expand Up @@ -208,7 +216,6 @@ func (pr *Progress) MaybeDecrTo(rejected, matchHint uint64) bool {
return false
}

// Next index shall always be larger than match index.
pr.Next = max(min(rejected, matchHint+1), pr.Match+1)
pr.MsgAppFlowPaused = false
return true
Expand Down

0 comments on commit 53007f4

Please sign in to comment.