server: refactor add

This commit is contained in:
Yicheng Qin 2014-07-15 11:55:58 -07:00
parent 3ea913e76a
commit 83e1fe77c8
2 changed files with 59 additions and 42 deletions

View File

@ -42,7 +42,7 @@ const (
) )
var ( var (
removeTmpErr = fmt.Errorf("remove: try again") tmpErr = fmt.Errorf("try again")
serverStopErr = fmt.Errorf("server is stopped") serverStopErr = fmt.Errorf("server is stopped")
) )
@ -199,7 +199,6 @@ func (s *Server) Join() {
func (s *Server) Add(id int64, raftPubAddr string, pubAddr string) error { func (s *Server) Add(id int64, raftPubAddr string, pubAddr string) error {
p := path.Join(v2machineKVPrefix, fmt.Sprint(id)) p := path.Join(v2machineKVPrefix, fmt.Sprint(id))
index := s.Index()
_, err := s.Get(p, false, false) _, err := s.Get(p, false, false)
if err == nil { if err == nil {
@ -208,26 +207,33 @@ func (s *Server) Add(id int64, raftPubAddr string, pubAddr string) error {
if v, ok := err.(*etcdErr.Error); !ok || v.ErrorCode != etcdErr.EcodeKeyNotFound { if v, ok := err.(*etcdErr.Error); !ok || v.ErrorCode != etcdErr.EcodeKeyNotFound {
return err return err
} }
for {
w, err := s.Watch(p, true, false, 0)
if err != nil {
log.Println("add error:", err)
return tmpErr
}
select { select {
case s.addNodeC <- raft.Config{NodeId: id, Addr: raftPubAddr, Context: []byte(pubAddr)}: case s.addNodeC <- raft.Config{NodeId: id, Addr: raftPubAddr, Context: []byte(pubAddr)}:
case <-s.stop: case <-s.stop:
return fmt.Errorf("server is stopped") return serverStopErr
}
w, err := s.Watch(p, true, false, index+1)
if err != nil {
return err
} }
select { select {
case v := <-w.EventChan: case v := <-w.EventChan:
if v.Action == store.Set { if v.Action == store.Set {
return nil return nil
} }
index = v.Index() log.Println("add error: action =", v.Action)
return tmpErr
case <-time.After(4 * defaultHeartbeat * s.tickDuration): case <-time.After(4 * defaultHeartbeat * s.tickDuration):
w.Remove()
log.Println("add error: wait timeout")
return tmpErr
case <-s.stop: case <-s.stop:
return fmt.Errorf("server is stopped") w.Remove()
} return serverStopErr
} }
} }
@ -249,7 +255,8 @@ func (s *Server) Remove(id int64) error {
// removal target is self // removal target is self
w, err := s.Watch(p, true, false, v.Index()+1) w, err := s.Watch(p, true, false, v.Index()+1)
if err != nil { if err != nil {
return removeTmpErr log.Println("remove error:", err)
return tmpErr
} }
select { select {
@ -257,10 +264,12 @@ func (s *Server) Remove(id int64) error {
if v.Action == store.Delete { if v.Action == store.Delete {
return nil return nil
} }
return removeTmpErr log.Println("remove error: action =", v.Action)
return tmpErr
case <-time.After(4 * defaultHeartbeat * s.tickDuration): case <-time.After(4 * defaultHeartbeat * s.tickDuration):
w.Remove() w.Remove()
return removeTmpErr log.Println("remove error: wait timeout")
return tmpErr
case <-s.stop: case <-s.stop:
w.Remove() w.Remove()
return serverStopErr return serverStopErr
@ -284,18 +293,21 @@ func (s *Server) run() {
func (s *Server) runParticipant() { func (s *Server) runParticipant() {
node := s.node node := s.node
addNodeC := s.addNodeC
removeNodeC := s.removeNodeC
recv := s.t.recv recv := s.t.recv
ticker := time.NewTicker(s.tickDuration) ticker := time.NewTicker(s.tickDuration)
v2SyncTicker := time.NewTicker(time.Millisecond * 500) v2SyncTicker := time.NewTicker(time.Millisecond * 500)
var proposal chan v2Proposal var proposal chan v2Proposal
var addNodeC, removeNodeC chan raft.Config
for { for {
if node.HasLeader() { if node.HasLeader() {
proposal = s.proposal proposal = s.proposal
addNodeC = s.addNodeC
removeNodeC = s.removeNodeC
} else { } else {
proposal = nil proposal = nil
addNodeC = nil
removeNodeC = nil
} }
select { select {
case p := <-proposal: case p := <-proposal:

View File

@ -5,7 +5,6 @@ import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
"runtime"
"testing" "testing"
"time" "time"
@ -101,31 +100,37 @@ func TestAdd(t *testing.T) {
go es[0].Bootstrap() go es[0].Bootstrap()
for i := 1; i < tt.size; i++ { for i := 1; i < tt.size; i++ {
var index uint64 id := int64(i)
for { for {
lead := es[0].node.Leader() lead := es[0].node.Leader()
if lead != -1 { if lead == -1 {
index = es[lead].Index() time.Sleep(defaultElection * es[0].tickDuration)
ne := es[i] continue
if err := es[lead].Add(ne.id, ne.raftPubAddr, ne.pubAddr); err == nil { }
err := es[lead].Add(id, es[id].raftPubAddr, es[id].pubAddr)
if err == nil {
break break
} }
switch err {
case tmpErr:
time.Sleep(defaultElection * es[0].tickDuration)
case serverStopErr:
t.Fatalf("#%d on %d: unexpected stop", i, lead)
default:
t.Fatal(err)
} }
runtime.Gosched()
} }
go es[i].run() go es[i].run()
for j := 0; j <= i; j++ { for j := 0; j <= i; j++ {
w, err := es[j].Watch(v2machineKVPrefix, true, false, index+1) p := fmt.Sprintf("%s/%d", v2machineKVPrefix, id)
w, err := es[j].Watch(p, false, false, 1)
if err != nil { if err != nil {
t.Errorf("#%d on %d: %v", i, j, err) t.Errorf("#%d on %d: %v", i, j, err)
break break
} }
v := <-w.EventChan <-w.EventChan
ww := fmt.Sprintf("%s/%d", v2machineKVPrefix, i)
if v.Node.Key != ww {
t.Errorf("#%d on %d: path = %v, want %v", i, j, v.Node.Key, ww)
}
} }
} }
@ -169,7 +174,7 @@ func TestRemove(t *testing.T) {
break break
} }
switch err { switch err {
case removeTmpErr: case tmpErr:
time.Sleep(defaultElection * 5 * time.Millisecond) time.Sleep(defaultElection * 5 * time.Millisecond)
case serverStopErr: case serverStopErr:
if lead == id { if lead == id {