Browse Source

standby: fix leader var race

Yicheng Qin 11 years ago
parent
commit
0b77b42cad
2 changed files with 22 additions and 6 deletions
  1. 4 2
      etcd/etcd_test.go
  2. 18 4
      etcd/standby.go

+ 4 - 2
etcd/etcd_test.go

@@ -242,13 +242,15 @@ func TestBecomeStandby(t *testing.T) {
 
 		waitMode(standbyMode, es[i])
 
+		var leader int64
 		for k := 0; k < 4; k++ {
-			if es[i].s.leader != noneId {
+			leader, _ = es[i].s.leaderInfo()
+			if leader != noneId {
 				break
 			}
 			time.Sleep(20 * time.Millisecond)
 		}
-		if g := es[i].s.leader; g != lead {
+		if g := leader; g != lead {
 			t.Errorf("#%d: lead = %d, want %d", i, g, lead)
 		}
 

+ 18 - 4
etcd/standby.go

@@ -5,6 +5,7 @@ import (
 	"log"
 	"net/http"
 	"strconv"
+	"sync"
 	"time"
 
 	"github.com/coreos/etcd/config"
@@ -27,6 +28,7 @@ type standby struct {
 
 	leader      int64
 	leaderAddr  string
+	mu          sync.RWMutex
 	clusterConf *config.ClusterConfig
 
 	stopc chan struct{}
@@ -87,11 +89,24 @@ func (s *standby) stop() {
 	close(s.stopc)
 }
 
+func (s *standby) leaderInfo() (int64, string) {
+	s.mu.RLock()
+	defer s.mu.RUnlock()
+	return s.leader, s.leaderAddr
+}
+
+func (s *standby) setLeaderInfo(leader int64, leaderAddr string) {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	s.leader, s.leaderAddr = leader, leaderAddr
+}
+
 func (s *standby) serveRedirect(w http.ResponseWriter, r *http.Request) error {
-	if s.leader == noneId {
+	leader, leaderAddr := s.leaderInfo()
+	if leader == noneId {
 		return fmt.Errorf("no leader in the cluster")
 	}
-	redirectAddr, err := buildRedirectURL(s.leaderAddr, r.URL)
+	redirectAddr, err := buildRedirectURL(leaderAddr, r.URL)
 	if err != nil {
 		return err
 	}
@@ -117,8 +132,7 @@ func (s *standby) syncCluster() error {
 				if err != nil {
 					return err
 				}
-				s.leader = id
-				s.leaderAddr = machine.PeerURL
+				s.setLeaderInfo(id, machine.PeerURL)
 			}
 		}
 		s.clusterConf = config