mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #1809 from xiang90/unstable
raft: stableTo checks term matching
This commit is contained in:
commit
92d4112feb
@ -187,7 +187,7 @@ func (l *raftLog) appliedTo(i uint64) {
|
|||||||
l.applied = i
|
l.applied = i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *raftLog) stableTo(i uint64) { l.unstable.stableTo(i) }
|
func (l *raftLog) stableTo(i, t uint64) { l.unstable.stableTo(i, t) }
|
||||||
|
|
||||||
func (l *raftLog) stableSnapTo(i uint64) { l.unstable.stableSnapTo(i) }
|
func (l *raftLog) stableSnapTo(i uint64) { l.unstable.stableSnapTo(i) }
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ func TestUnstableEnts(t *testing.T) {
|
|||||||
|
|
||||||
ents := raftLog.unstableEntries()
|
ents := raftLog.unstableEntries()
|
||||||
if l := len(ents); l > 0 {
|
if l := len(ents); l > 0 {
|
||||||
raftLog.stableTo(ents[l-1].Index)
|
raftLog.stableTo(ents[l-1].Index, ents[l-i].Term)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ents, tt.wents) {
|
if !reflect.DeepEqual(ents, tt.wents) {
|
||||||
t.Errorf("#%d: unstableEnts = %+v, want %+v", i, ents, tt.wents)
|
t.Errorf("#%d: unstableEnts = %+v, want %+v", i, ents, tt.wents)
|
||||||
@ -438,18 +438,58 @@ func TestCommitTo(t *testing.T) {
|
|||||||
|
|
||||||
func TestStableTo(t *testing.T) {
|
func TestStableTo(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
stable uint64
|
stablei uint64
|
||||||
|
stablet uint64
|
||||||
wunstable uint64
|
wunstable uint64
|
||||||
}{
|
}{
|
||||||
{1, 2},
|
{1, 1, 2},
|
||||||
{2, 3},
|
{2, 2, 3},
|
||||||
|
{2, 1, 1}, // bad term
|
||||||
|
{3, 1, 1}, // bad index
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
raftLog := newLog(NewMemoryStorage())
|
raftLog := newLog(NewMemoryStorage())
|
||||||
raftLog.append(0, []pb.Entry{{}, {}}...)
|
raftLog.append(0, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}...)
|
||||||
raftLog.stableTo(tt.stable)
|
raftLog.stableTo(tt.stablei, tt.stablet)
|
||||||
if raftLog.unstable.offset != tt.wunstable {
|
if raftLog.unstable.offset != tt.wunstable {
|
||||||
t.Errorf("#%d: unstable = %d, want %d", i, raftLog.unstable, tt.wunstable)
|
t.Errorf("#%d: unstable = %d, want %d", i, raftLog.unstable.offset, tt.wunstable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStableToWithSnap(t *testing.T) {
|
||||||
|
snapi, snapt := uint64(5), uint64(2)
|
||||||
|
tests := []struct {
|
||||||
|
stablei uint64
|
||||||
|
stablet uint64
|
||||||
|
newEnts []pb.Entry
|
||||||
|
|
||||||
|
wunstable uint64
|
||||||
|
}{
|
||||||
|
{snapi + 1, snapt, nil, snapi + 1},
|
||||||
|
{snapi, snapt, nil, snapi + 1},
|
||||||
|
{snapi - 1, snapt, nil, snapi + 1},
|
||||||
|
|
||||||
|
{snapi + 1, snapt + 1, nil, snapi + 1},
|
||||||
|
{snapi, snapt + 1, nil, snapi + 1},
|
||||||
|
{snapi - 1, snapt + 1, nil, snapi + 1},
|
||||||
|
|
||||||
|
{snapi + 1, snapt, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 2},
|
||||||
|
{snapi, snapt, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1},
|
||||||
|
{snapi - 1, snapt, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1},
|
||||||
|
|
||||||
|
{snapi + 1, snapt + 1, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1},
|
||||||
|
{snapi, snapt + 1, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1},
|
||||||
|
{snapi - 1, snapt + 1, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1},
|
||||||
|
}
|
||||||
|
for i, tt := range tests {
|
||||||
|
s := NewMemoryStorage()
|
||||||
|
s.ApplySnapshot(pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: snapi, Term: snapt}})
|
||||||
|
raftLog := newLog(s)
|
||||||
|
raftLog.append(raftLog.lastIndex(), tt.newEnts...)
|
||||||
|
raftLog.stableTo(tt.stablei, tt.stablet)
|
||||||
|
if raftLog.unstable.offset != tt.wunstable {
|
||||||
|
t.Errorf("#%d: unstable = %d, want %d", i, raftLog.unstable.offset, tt.wunstable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,7 @@
|
|||||||
|
|
||||||
package raft
|
package raft
|
||||||
|
|
||||||
import (
|
import pb "github.com/coreos/etcd/raft/raftpb"
|
||||||
"log"
|
|
||||||
|
|
||||||
pb "github.com/coreos/etcd/raft/raftpb"
|
|
||||||
)
|
|
||||||
|
|
||||||
// unstable.entris[i] has raft log position i+unstable.offset.
|
// unstable.entris[i] has raft log position i+unstable.offset.
|
||||||
// Note that unstable.offset may be less than the highest log
|
// Note that unstable.offset may be less than the highest log
|
||||||
@ -77,13 +73,18 @@ func (u *unstable) maybeTerm(i uint64) (uint64, bool) {
|
|||||||
return u.entries[i-u.offset].Term, true
|
return u.entries[i-u.offset].Term, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unstable) stableTo(i uint64) {
|
func (u *unstable) stableTo(i, t uint64) {
|
||||||
if i < u.offset || i+1-u.offset > uint64(len(u.entries)) {
|
gt, ok := u.maybeTerm(i)
|
||||||
log.Panicf("stableTo(%d) is out of range [unstable(%d), len(unstableEnts)(%d)]",
|
if !ok {
|
||||||
i, u.offset, len(u.entries))
|
return
|
||||||
|
}
|
||||||
|
// if i < offest, term is matched with the snapshot
|
||||||
|
// only update the unstalbe entries if term is matched with
|
||||||
|
// an unstable entry.
|
||||||
|
if gt == t && i >= u.offset {
|
||||||
|
u.entries = u.entries[i+1-u.offset:]
|
||||||
|
u.offset = i + 1
|
||||||
}
|
}
|
||||||
u.entries = u.entries[i+1-u.offset:]
|
|
||||||
u.offset = i + 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unstable) stableSnapTo(i uint64) {
|
func (u *unstable) stableSnapTo(i uint64) {
|
||||||
|
@ -209,6 +209,7 @@ func (n *node) run(r *raft) {
|
|||||||
var readyc chan Ready
|
var readyc chan Ready
|
||||||
var advancec chan struct{}
|
var advancec chan struct{}
|
||||||
var prevLastUnstablei uint64
|
var prevLastUnstablei uint64
|
||||||
|
var prevLastUnstablet uint64
|
||||||
var havePrevLastUnstablei bool
|
var havePrevLastUnstablei bool
|
||||||
var prevSnapi uint64
|
var prevSnapi uint64
|
||||||
var rd Ready
|
var rd Ready
|
||||||
@ -284,6 +285,7 @@ func (n *node) run(r *raft) {
|
|||||||
}
|
}
|
||||||
if len(rd.Entries) > 0 {
|
if len(rd.Entries) > 0 {
|
||||||
prevLastUnstablei = rd.Entries[len(rd.Entries)-1].Index
|
prevLastUnstablei = rd.Entries[len(rd.Entries)-1].Index
|
||||||
|
prevLastUnstablet = rd.Entries[len(rd.Entries)-1].Term
|
||||||
havePrevLastUnstablei = true
|
havePrevLastUnstablei = true
|
||||||
}
|
}
|
||||||
if !IsEmptyHardState(rd.HardState) {
|
if !IsEmptyHardState(rd.HardState) {
|
||||||
@ -303,7 +305,7 @@ func (n *node) run(r *raft) {
|
|||||||
r.raftLog.appliedTo(prevHardSt.Commit)
|
r.raftLog.appliedTo(prevHardSt.Commit)
|
||||||
}
|
}
|
||||||
if havePrevLastUnstablei {
|
if havePrevLastUnstablei {
|
||||||
r.raftLog.stableTo(prevLastUnstablei)
|
r.raftLog.stableTo(prevLastUnstablei, prevLastUnstablet)
|
||||||
havePrevLastUnstablei = false
|
havePrevLastUnstablei = false
|
||||||
}
|
}
|
||||||
r.raftLog.stableSnapTo(prevSnapi)
|
r.raftLog.stableSnapTo(prevSnapi)
|
||||||
|
@ -902,7 +902,7 @@ func commitNoopEntry(r *raft, s *MemoryStorage) {
|
|||||||
r.readMessages()
|
r.readMessages()
|
||||||
s.Append(r.raftLog.unstableEntries())
|
s.Append(r.raftLog.unstableEntries())
|
||||||
r.raftLog.appliedTo(r.raftLog.committed)
|
r.raftLog.appliedTo(r.raftLog.committed)
|
||||||
r.raftLog.stableTo(r.raftLog.lastIndex())
|
r.raftLog.stableTo(r.raftLog.lastIndex(), r.raftLog.lastTerm())
|
||||||
}
|
}
|
||||||
|
|
||||||
func acceptAndReply(m pb.Message) pb.Message {
|
func acceptAndReply(m pb.Message) pb.Message {
|
||||||
|
@ -31,7 +31,7 @@ import (
|
|||||||
func nextEnts(r *raft, s *MemoryStorage) (ents []pb.Entry) {
|
func nextEnts(r *raft, s *MemoryStorage) (ents []pb.Entry) {
|
||||||
// Transfer all unstable entries to "stable" storage.
|
// Transfer all unstable entries to "stable" storage.
|
||||||
s.Append(r.raftLog.unstableEntries())
|
s.Append(r.raftLog.unstableEntries())
|
||||||
r.raftLog.stableTo(r.raftLog.lastIndex())
|
r.raftLog.stableTo(r.raftLog.lastIndex(), r.raftLog.lastTerm())
|
||||||
|
|
||||||
ents = r.raftLog.nextEnts()
|
ents = r.raftLog.nextEnts()
|
||||||
r.raftLog.appliedTo(r.raftLog.committed)
|
r.raftLog.appliedTo(r.raftLog.committed)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user