Fix peer timer race condition.

pull/820/head
Ben Johnson 2013-06-04 09:35:43 -04:00
parent c544519c7c
commit 8efbb1535e
3 changed files with 15 additions and 11 deletions

12
peer.go
View File

@ -35,8 +35,10 @@ func NewPeer(server *Server, name string, heartbeatTimeout time.Duration) *Peer
heartbeatTimer: NewTimer(heartbeatTimeout, heartbeatTimeout),
}
// Start the heartbeat timeout.
go p.heartbeatTimeoutFunc()
// Start the heartbeat timeout and wait for the goroutine to start.
c := make(chan bool)
go p.heartbeatTimeoutFunc(c)
<-c
return p
}
@ -149,10 +151,8 @@ func (p *Peer) sendFlushRequest(req *AppendEntriesRequest) (uint64, bool, error)
//--------------------------------------
// Listens to the heartbeat timeout and flushes an AppendEntries RPC.
func (p *Peer) heartbeatTimeoutFunc() {
// Initialize the timer here since there can be a delay before this
// goroutine actually starts.
p.heartbeatTimer.Reset()
func (p *Peer) heartbeatTimeoutFunc(startChannel chan bool) {
startChannel <- true
for {
// Grab the current timer channel.

View File

@ -721,6 +721,9 @@ func (s *Server) AddPeer(name string) error {
// Only add the peer if it doesn't have the same name.
if s.name != name {
peer := NewPeer(s, name, s.heartbeatTimeout)
if s.state == Leader {
peer.resume()
}
s.peers[peer.name] = peer
}

View File

@ -343,7 +343,8 @@ func TestServerMultiNode(t *testing.T) {
mutex.Lock()
s := servers[peer.name]
mutex.Unlock()
return s.RequestVote(req)
resp, err := s.RequestVote(req)
return resp, err
}
transporter.sendAppendEntriesRequestFunc = func(server *Server, peer *Peer, req *AppendEntriesRequest) (*AppendEntriesResponse, error) {
mutex.Lock()
@ -375,7 +376,7 @@ func TestServerMultiNode(t *testing.T) {
servers[name] = server
mutex.Unlock()
}
time.Sleep(500 * time.Millisecond)
time.Sleep(100 * time.Millisecond)
// Check that two peers exist on leader.
mutex.Lock()
@ -385,9 +386,9 @@ func TestServerMultiNode(t *testing.T) {
mutex.Unlock()
// Stop the first server and wait for a re-election.
time.Sleep(500 * time.Millisecond)
time.Sleep(100 * time.Millisecond)
leader.Stop()
time.Sleep(500 * time.Millisecond)
time.Sleep(100 * time.Millisecond)
// Check that either server 2 or 3 is the leader now.
mutex.Lock()