discovery: store size inside /[cluster]/config

release-2.0
Xiang Li 2014-09-22 13:54:21 -07:00
parent 00d1daaf1e
commit 6081311db5
2 changed files with 44 additions and 36 deletions

View File

@ -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,26 +69,35 @@ 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
}
size, err := strconv.Atoi(resp.Node.Value)
if err != nil {
return nil, 0, ErrBadSizeKey
}
resp, err = d.c.Get(d.cluster)
if err != nil {
return nil, 0, err
}
nodes := resp.Node.Nodes
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)
}
}
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(nodes[0].Value)
if err != nil {
return nil, 0, ErrBadCluster
}
// remove size key from nodes
nodes = nodes[1:]
// find self position
for i := range nodes {
if nodes[i].Key == d.selfKey() {

View File

@ -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,
},
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: []*client.Response{resp},
}
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:]