Merge pull request #10864 from tbg/learner-snap

raft: allow voter to become learner through snapshot
This commit is contained in:
Tobias Grieger 2019-07-11 15:48:09 +02:00 committed by GitHub
commit b2274efee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 11 additions and 15 deletions

View File

@ -1374,16 +1374,6 @@ func (r *raft) restore(s pb.Snapshot) bool {
return false
}
// The normal peer can't become learner.
if !r.isLearner {
for _, id := range s.Metadata.ConfState.Learners {
if id == r.id {
r.logger.Errorf("%x can't become learner when restores snapshot [index: %d, term: %d]", r.id, s.Metadata.Index, s.Metadata.Term)
return false
}
}
}
r.raftLog.restore(s)
// Reset the configuration and add the (potentially updated) peers in anew.

View File

@ -2777,9 +2777,15 @@ func TestRestoreWithLearner(t *testing.T) {
}
}
// TestRestoreInvalidLearner verfies that a normal peer can't become learner again
// when restores snapshot.
func TestRestoreInvalidLearner(t *testing.T) {
// TestRestoreVoterToLearner verifies that a normal peer can be downgraded to a
// learner through a snapshot. At the time of writing, we don't allow
// configuration changes to do this directly, but note that the snapshot may
// compress multiple changes to the configuration into one: the voter could have
// been removed, then readded as a learner and the snapshot reflects both
// changes. In that case, a voter receives a snapshot telling it that it is now
// a learner. In fact, the node has to accept that snapshot, or it is
// permanently cut off from the Raft log.
func TestRestoreVoterToLearner(t *testing.T) {
s := pb.Snapshot{
Metadata: pb.SnapshotMetadata{
Index: 11, // magic number
@ -2794,8 +2800,8 @@ func TestRestoreInvalidLearner(t *testing.T) {
if sm.isLearner {
t.Errorf("%x is learner, want not", sm.id)
}
if ok := sm.restore(s); ok {
t.Error("restore succeed, want fail")
if ok := sm.restore(s); !ok {
t.Error("restore failed unexpectedly")
}
}