Browse Source

raft: add create cluster of itself

Yicheng Qin 11 years ago
parent
commit
5cad4e595c
2 changed files with 48 additions and 15 deletions
  1. 20 4
      raft/node.go
  2. 28 11
      raft/node_test.go

+ 20 - 4
raft/node.go

@@ -13,7 +13,7 @@ type tick int
 
 type ConfigCmd struct {
 	Type string
-	Addr   int
+	Addr int
 }
 
 type Node struct {
@@ -28,16 +28,15 @@ type Node struct {
 	addr int
 }
 
-func New(addr int, peers []int, heartbeat, election tick) *Node {
+func New(addr int, heartbeat, election tick) *Node {
 	if election < heartbeat*3 {
 		panic("election is least three times as heartbeat [election: %d, heartbeat: %d]")
 	}
 
 	n := &Node{
-		sm:        newStateMachine(addr, peers),
 		heartbeat: heartbeat,
 		election:  election,
-		addr: addr,
+		addr:      addr,
 	}
 
 	return n
@@ -49,6 +48,23 @@ func (n *Node) Propose(data []byte) {
 	n.Step(m)
 }
 
+func (n *Node) StartCluster() {
+	if n.sm != nil {
+		panic("node is started")
+	}
+	n.sm = newStateMachine(n.addr, []int{n.addr})
+	n.Step(Message{Type: msgHup})
+	n.Step(n.confMessage(&ConfigCmd{Type: "add", Addr: n.addr}))
+	n.Next()
+}
+
+func (n *Node) Start() {
+	if n.sm != nil {
+		panic("node is started")
+	}
+	n.sm = newStateMachine(n.addr, nil)
+}
+
 func (n *Node) Add(addr int) {
 	n.Step(n.confMessage(&ConfigCmd{Type: "add", Addr: addr}))
 }

+ 28 - 11
raft/node_test.go

@@ -10,7 +10,8 @@ const (
 )
 
 func TestTickMsgHub(t *testing.T) {
-	n := New(0, []int{0, 1, 2}, defaultHeartbeat, defaultElection)
+	n := New(0, defaultHeartbeat, defaultElection)
+	n.sm = newStateMachine(0, []int{0, 1, 2})
 
 	for i := 0; i < defaultElection+1; i++ {
 		n.Tick()
@@ -30,7 +31,8 @@ func TestTickMsgHub(t *testing.T) {
 
 func TestTickMsgBeat(t *testing.T) {
 	k := 3
-	n := New(0, []int{0, 1, 2}, defaultHeartbeat, defaultElection)
+	n := New(0, defaultHeartbeat, defaultElection)
+	n.sm = newStateMachine(0, []int{0, 1, 2})
 
 	n.Step(Message{Type: msgHup}) // become leader please
 	for _, m := range n.Msgs() {
@@ -70,7 +72,8 @@ func TestResetElapse(t *testing.T) {
 	}
 
 	for i, tt := range tests {
-		n := New(0, []int{0, 1, 2}, defaultHeartbeat, defaultElection)
+		n := New(0, defaultHeartbeat, defaultElection)
+		n.sm = newStateMachine(0, []int{0, 1, 2})
 		n.sm.term = 2
 
 		n.Tick()
@@ -85,24 +88,38 @@ func TestResetElapse(t *testing.T) {
 	}
 }
 
-func TestAdd(t *testing.T) {
-	n := New(0, []int{0}, defaultHeartbeat, defaultElection)
+func TestStartCluster(t *testing.T) {
+	n := New(0, defaultHeartbeat, defaultElection)
+	n.StartCluster()
 
-	n.sm.becomeCandidate()
-	n.sm.becomeLeader()
+	if len(n.sm.ins) != 1 {
+		t.Errorf("k = %d, want 1", len(n.sm.ins))
+	}
+	if n.sm.addr != 0 {
+		t.Errorf("addr = %d, want 0", n.sm.addr)
+	}
+	if n.sm.state != stateLeader {
+		t.Errorf("state = %s, want %s", n.sm.state, stateLeader)
+	}
+}
+
+func TestAdd(t *testing.T) {
+	n := New(0, defaultHeartbeat, defaultElection)
+	n.StartCluster()
 	n.Add(1)
 	n.Next()
 
 	if len(n.sm.ins) != 2 {
 		t.Errorf("k = %d, want 2", len(n.sm.ins))
 	}
+	if n.sm.addr != 0 {
+		t.Errorf("addr = %d, want 0", n.sm.addr)
+	}
 }
 
 func TestRemove(t *testing.T) {
-	n := New(0, []int{0}, defaultHeartbeat, defaultElection)
-
-	n.sm.becomeCandidate()
-	n.sm.becomeLeader()
+	n := New(0, defaultHeartbeat, defaultElection)
+	n.StartCluster()
 	n.Add(1)
 	n.Next()
 	n.Remove(0)