Browse Source

discovery: store size inside /[cluster]/config

Xiang Li 11 years ago
parent
commit
6081311db5
2 changed files with 42 additions and 34 deletions
  1. 22 13
      discovery/discovery.go
  2. 20 21
      discovery/discovery_test.go

+ 22 - 13
discovery/discovery.go

@@ -14,7 +14,7 @@ import (
 
 var (
 	ErrInvalidURL    = errors.New("discovery: invalid URL")
-	ErrBadCluster    = errors.New("discovery: bad key/value inside cluster")
+	ErrBadSizeKey    = errors.New("discovery: size key is bad")
 	ErrSizeNotFound  = errors.New("discovery: size key not found")
 	ErrTokenNotFound = errors.New("discovery: token not found")
 	ErrDuplicateID   = errors.New("discovery: found duplicate id")
@@ -69,25 +69,34 @@ func (d *discovery) createSelf() error {
 }
 
 func (d *discovery) checkCluster() (client.Nodes, int, error) {
-	resp, err := d.c.Get(d.cluster)
+	configKey := path.Join("/", d.cluster, "config")
+	// find cluster size
+	resp, err := d.c.Get(path.Join(configKey, "size"))
 	if err != nil {
+		if err == client.ErrKeyNoExist {
+			return nil, 0, ErrSizeNotFound
+		}
 		return nil, 0, err
 	}
-	nodes := resp.Node.Nodes
-	snodes := SortableNodes{nodes}
-	sort.Sort(snodes)
-
-	// find cluster size
-	if nodes[0].Key != path.Join("/", d.cluster, "size") {
-		return nil, 0, ErrSizeNotFound
+	size, err := strconv.Atoi(resp.Node.Value)
+	if err != nil {
+		return nil, 0, ErrBadSizeKey
 	}
-	size, err := strconv.Atoi(nodes[0].Value)
+
+	resp, err = d.c.Get(d.cluster)
 	if err != nil {
-		return nil, 0, ErrBadCluster
+		return nil, 0, err
+	}
+	nodes := make(client.Nodes, 0)
+	// append non-config keys to nodes
+	for _, n := range resp.Node.Nodes {
+		if !strings.HasPrefix(n.Key, configKey) {
+			nodes = append(nodes, n)
+		}
 	}
 
-	// remove size key from nodes
-	nodes = nodes[1:]
+	snodes := SortableNodes{nodes}
+	sort.Sort(snodes)
 
 	// find self position
 	for i := range nodes {

+ 20 - 21
discovery/discovery_test.go

@@ -25,7 +25,7 @@ func TestCheckCluster(t *testing.T) {
 		{
 			// self is in the size range
 			client.Nodes{
-				{Key: "/1000/size", Value: "3", CreatedIndex: 1},
+				{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
 				{Key: self, CreatedIndex: 2},
 				{Key: "/1000/2", CreatedIndex: 3},
 				{Key: "/1000/3", CreatedIndex: 4},
@@ -37,7 +37,7 @@ func TestCheckCluster(t *testing.T) {
 		{
 			// self is in the size range
 			client.Nodes{
-				{Key: "/1000/size", Value: "3", CreatedIndex: 1},
+				{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
 				{Key: "/1000/2", CreatedIndex: 2},
 				{Key: "/1000/3", CreatedIndex: 3},
 				{Key: self, CreatedIndex: 4},
@@ -49,7 +49,7 @@ func TestCheckCluster(t *testing.T) {
 		{
 			// self is out of the size range
 			client.Nodes{
-				{Key: "/1000/size", Value: "3", CreatedIndex: 1},
+				{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
 				{Key: "/1000/2", CreatedIndex: 2},
 				{Key: "/1000/3", CreatedIndex: 3},
 				{Key: "/1000/4", CreatedIndex: 4},
@@ -61,7 +61,7 @@ func TestCheckCluster(t *testing.T) {
 		{
 			// self is not in the cluster
 			client.Nodes{
-				{Key: "/1000/size", Value: "3", CreatedIndex: 1},
+				{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
 				{Key: "/1000/2", CreatedIndex: 2},
 				{Key: "/1000/3", CreatedIndex: 3},
 			},
@@ -70,7 +70,7 @@ func TestCheckCluster(t *testing.T) {
 		},
 		{
 			client.Nodes{
-				{Key: "/1000/size", Value: "3", CreatedIndex: 1},
+				{Key: "/1000/config/size", Value: "3", CreatedIndex: 1},
 				{Key: "/1000/2", CreatedIndex: 2},
 				{Key: "/1000/3", CreatedIndex: 3},
 				{Key: "/1000/4", CreatedIndex: 4},
@@ -81,34 +81,33 @@ func TestCheckCluster(t *testing.T) {
 		{
 			// bad size key
 			client.Nodes{
-				{Key: "/1000/size", Value: "bad", CreatedIndex: 1},
+				{Key: "/1000/config/size", Value: "bad", CreatedIndex: 1},
 			},
-			ErrBadCluster,
+			ErrBadSizeKey,
 			0,
 		},
 		{
 			// no size key
-			client.Nodes{
-				{Key: self, CreatedIndex: 1},
-			},
+			client.Nodes{},
 			ErrSizeNotFound,
 			0,
 		},
 	}
 
 	for i, tt := range tests {
-		resp := &client.Response{
-			Node: &client.Node{
-				Key:   cluster,
-				Nodes: tt.nodes,
-			},
-		}
-
-		c := &clientWithResp{
-			rs: []*client.Response{resp},
+		rs := make([]*client.Response, 0)
+		if len(tt.nodes) > 0 {
+			rs = append(rs, &client.Response{Node: tt.nodes[0]})
+			rs = append(rs, &client.Response{
+				Node: &client.Node{
+					Key:   cluster,
+					Nodes: tt.nodes,
+				},
+			})
 		}
-
+		c := &clientWithResp{rs: rs}
 		d := discovery{cluster: cluster, id: 1, c: c}
+
 		ns, size, err := d.checkCluster()
 		if err != tt.werr {
 			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
@@ -277,7 +276,7 @@ func (c *clientWithResp) Create(key string, value string, ttl time.Duration) (*c
 
 func (c *clientWithResp) Get(key string) (*client.Response, error) {
 	if len(c.rs) == 0 {
-		return &client.Response{}, nil
+		return &client.Response{}, client.ErrKeyNoExist
 	}
 	r := c.rs[0]
 	c.rs = c.rs[1:]