|
@@ -3,6 +3,7 @@ package raft
|
|
|
import (
|
|
import (
|
|
|
"errors"
|
|
"errors"
|
|
|
"log"
|
|
"log"
|
|
|
|
|
+ "reflect"
|
|
|
|
|
|
|
|
pb "github.com/coreos/etcd/raft/raftpb"
|
|
pb "github.com/coreos/etcd/raft/raftpb"
|
|
|
"github.com/coreos/etcd/third_party/code.google.com/p/go.net/context"
|
|
"github.com/coreos/etcd/third_party/code.google.com/p/go.net/context"
|
|
@@ -18,11 +19,13 @@ var (
|
|
|
type SoftState struct {
|
|
type SoftState struct {
|
|
|
Lead int64
|
|
Lead int64
|
|
|
RaftState StateType
|
|
RaftState StateType
|
|
|
|
|
+ Nodes []int64
|
|
|
ShouldStop bool
|
|
ShouldStop bool
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (a *SoftState) equal(b *SoftState) bool {
|
|
func (a *SoftState) equal(b *SoftState) bool {
|
|
|
- return a.Lead == b.Lead && a.RaftState == b.RaftState && a.ShouldStop == b.ShouldStop
|
|
|
|
|
|
|
+ nodeeq := reflect.DeepEqual(a.Nodes, b.Nodes)
|
|
|
|
|
+ return a.Lead == b.Lead && a.RaftState == b.RaftState && a.ShouldStop == b.ShouldStop && nodeeq
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Ready encapsulates the entries and messages that are ready to read,
|
|
// Ready encapsulates the entries and messages that are ready to read,
|
|
@@ -56,6 +59,12 @@ type Ready struct {
|
|
|
Messages []pb.Message
|
|
Messages []pb.Message
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+type compact struct {
|
|
|
|
|
+ index int64
|
|
|
|
|
+ nodes []int64
|
|
|
|
|
+ data []byte
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func isHardStateEqual(a, b pb.HardState) bool {
|
|
func isHardStateEqual(a, b pb.HardState) bool {
|
|
|
return a.Term == b.Term && a.Vote == b.Vote && a.Commit == b.Commit
|
|
return a.Term == b.Term && a.Vote == b.Vote && a.Commit == b.Commit
|
|
|
}
|
|
}
|
|
@@ -96,7 +105,7 @@ type Node interface {
|
|
|
// Stop performs any necessary termination of the Node
|
|
// Stop performs any necessary termination of the Node
|
|
|
Stop()
|
|
Stop()
|
|
|
// Compact
|
|
// Compact
|
|
|
- Compact(d []byte)
|
|
|
|
|
|
|
+ Compact(index int64, nodes []int64, d []byte)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// StartNode returns a new Node given a unique raft id, a list of raft peers, and
|
|
// StartNode returns a new Node given a unique raft id, a list of raft peers, and
|
|
@@ -141,7 +150,7 @@ func RestartNode(id int64, peers []int64, election, heartbeat int, snapshot *pb.
|
|
|
type node struct {
|
|
type node struct {
|
|
|
propc chan pb.Message
|
|
propc chan pb.Message
|
|
|
recvc chan pb.Message
|
|
recvc chan pb.Message
|
|
|
- compactc chan []byte
|
|
|
|
|
|
|
+ compactc chan compact
|
|
|
confc chan pb.ConfChange
|
|
confc chan pb.ConfChange
|
|
|
readyc chan Ready
|
|
readyc chan Ready
|
|
|
tickc chan struct{}
|
|
tickc chan struct{}
|
|
@@ -152,7 +161,7 @@ func newNode() node {
|
|
|
return node{
|
|
return node{
|
|
|
propc: make(chan pb.Message),
|
|
propc: make(chan pb.Message),
|
|
|
recvc: make(chan pb.Message),
|
|
recvc: make(chan pb.Message),
|
|
|
- compactc: make(chan []byte),
|
|
|
|
|
|
|
+ compactc: make(chan compact),
|
|
|
confc: make(chan pb.ConfChange),
|
|
confc: make(chan pb.ConfChange),
|
|
|
readyc: make(chan Ready),
|
|
readyc: make(chan Ready),
|
|
|
tickc: make(chan struct{}),
|
|
tickc: make(chan struct{}),
|
|
@@ -200,8 +209,8 @@ func (n *node) run(r *raft) {
|
|
|
r.Step(m)
|
|
r.Step(m)
|
|
|
case m := <-n.recvc:
|
|
case m := <-n.recvc:
|
|
|
r.Step(m) // raft never returns an error
|
|
r.Step(m) // raft never returns an error
|
|
|
- case d := <-n.compactc:
|
|
|
|
|
- r.compact(d)
|
|
|
|
|
|
|
+ case c := <-n.compactc:
|
|
|
|
|
+ r.compact(c.index, c.nodes, c.data)
|
|
|
case cc := <-n.confc:
|
|
case cc := <-n.confc:
|
|
|
switch cc.Type {
|
|
switch cc.Type {
|
|
|
case pb.ConfChangeAddNode:
|
|
case pb.ConfChangeAddNode:
|
|
@@ -299,9 +308,9 @@ func (n *node) ApplyConfChange(cc pb.ConfChange) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (n *node) Compact(d []byte) {
|
|
|
|
|
|
|
+func (n *node) Compact(index int64, nodes []int64, d []byte) {
|
|
|
select {
|
|
select {
|
|
|
- case n.compactc <- d:
|
|
|
|
|
|
|
+ case n.compactc <- compact{index, nodes, d}:
|
|
|
case <-n.done:
|
|
case <-n.done:
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|