对raft_test.go 里的这个测试函数有疑问。在newStorage的时候,所有Raft的RaftLog会存在一个empty的Log,也就是Index和Term都是0。那么初始化之后sm1会存在2个Log,一个是(0, 0), 一个是(1, 1) [左边数字代表Index, 右边代表Term]。在sm1成功当选Leader后,应该要append一个新的Log(2, 3),并把RaftLog广播给所有节点。那这样的话,len(sm.entries) 不应该等于3吗?为什么等于2?如果我的理解错了,请麻烦指出,谢谢。
func TestLeaderElectionOverwriteNewerLogs2AB(t *testing.T) {
cfg := func(c *Config) {
c.peers = idsBySize(5)
}
// This network represents the results of the following sequence of
// events:
// - Node 1 won the election in term 1.
// - Node 1 replicated a log entry to node 2 but died before sending
// it to other nodes.
// - Node 3 won the second election in term 2.
// - Node 3 wrote an entry to its logs but died without sending it
// to any other nodes.
//
// At this point, nodes 1, 2, and 3 all have uncommitted entries in
// their logs and could win an election at term 3. The winner's log
// entry overwrites the losers'. (TestLeaderSyncFollowerLog tests
// the case where older log entries are overwritten, so this test
// focuses on the case where the newer entries are lost).
n := newNetworkWithConfig(cfg,
entsWithConfig(cfg, 1), // Node 1: Won first election
entsWithConfig(cfg, 1), // Node 2: Got logs from node 1
entsWithConfig(cfg, 2), // Node 3: Won second election
votedWithConfig(cfg, 3, 2), // Node 4: Voted but didn't get logs
votedWithConfig(cfg, 3, 2)) // Node 5: Voted but didn't get logs
// Node 1 campaigns. The election fails because a quorum of nodes
// know about the election that already happened at term 2. Node 1's
// term is pushed ahead to 2.
n.send(pb.Message{From: 1, To: 1, MsgType: pb.MessageType_MsgHup})
sm1 := n.peers[1].(*Raft)
if sm1.State != StateFollower {
t.Errorf("state = %s, want StateFollower", sm1.State)
}
if sm1.Term != 2 {
t.Errorf("term = %d, want 2", sm1.Term)
}
// Node 1 campaigns again with a higher term. This time it succeeds.
n.send(pb.Message{From: 1, To: 1, MsgType: pb.MessageType_MsgHup})
if sm1.State != StateLeader {
t.Errorf("state = %s, want StateLeader", sm1.State)
}
if sm1.Term != 3 {
t.Errorf("term = %d, want 3", sm1.Term)
}
// fmt.Printf("sm2: %d %d\
", sm2.RaftLog.entries[1].Index, sm2.RaftLog.entries[1].Term)
// Now all nodes agree on a log entry with term 1 at index 1 (and
// term 3 at index 2).
for i := range n.peers {
sm := n.peers[i].(*Raft)
entries := sm.RaftLog.entries
if len(entries) != 2 {
t.Fatalf("node %d: len(entries) == %d, want 2", i, len(entries))
}
if entries[0].Term != 1 {
t.Errorf("node %d: term at index 1 == %d, want 1", i, entries[0].Term)
}
if entries[1].Term != 3 {
t.Errorf("node %d: term at index 2 == %d, want 3", i, entries[1].Term)
}
}
}