Skip to content
This repository was archived by the owner on Jun 4, 2019. It is now read-only.

Commit 73f9c0f

Browse files
committed
Merge pull request #13 from philips/cluster-flag
etcdctl: add support for the -C flag
2 parents eb45b0c + 0c37fcc commit 73f9c0f

27 files changed

Lines changed: 410 additions & 127 deletions

etcdctl.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ import (
88
)
99

1010
var (
11-
cluster = flag.String("C", "0.0.0.0:4001", "a list of machine addresses in the cluster")
12-
client = etcd.NewClient()
11+
client *etcd.Client
1312
)
1413

1514
func main() {
15+
cluster := ClusterValue{"http://localhost:4001"}
16+
flag.Var(&cluster, "C", "a comma seperated list of machine addresses in the cluster e.g. 127.0.0.1:4001,127.0.0.1:4002")
1617
flag.Parse()
1718

19+
client = etcd.NewClient(cluster.GetMachines())
20+
1821
args := flag.Args()
1922

2023
if len(args) == 0 {

flags.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"strings"
5+
)
6+
7+
type ClusterValue struct {
8+
machines string
9+
}
10+
11+
func (c *ClusterValue) String() string {
12+
return c.machines
13+
}
14+
15+
func (c *ClusterValue) Set(value string) error {
16+
if len(value) == 0 {
17+
return nil
18+
}
19+
20+
c.machines = value
21+
22+
return nil
23+
}
24+
25+
func (c *ClusterValue) GetMachines() []string {
26+
return strings.Split(c.machines, ",")
27+
}

third_party/github.com/coreos/etcd/error/error.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2013 CoreOS Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package error
218

319
import (

third_party/github.com/coreos/etcd/store/keyword_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2013 CoreOS Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package store
218

319
import (

third_party/github.com/coreos/etcd/store/keywords.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2013 CoreOS Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package store
218

319
import (

third_party/github.com/coreos/etcd/store/stats.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2013 CoreOS Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package store
218

319
import (

third_party/github.com/coreos/etcd/store/store.go

Lines changed: 106 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
1+
/*
2+
Copyright 2013 CoreOS Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package store
218

319
import (
420
"encoding/json"
521
"fmt"
6-
etcdErr "github.com/coreos/etcd/error"
722
"path"
823
"strconv"
924
"sync"
1025
"time"
26+
27+
etcdErr "github.com/coreos/etcd/error"
1128
)
1229

1330
//------------------------------------------------------------------------------
@@ -325,75 +342,81 @@ func (s *Store) Get(key string) ([]byte, error) {
325342
return json.Marshal(resps)
326343
}
327344

328-
func (s *Store) RawGet(key string) ([]*Response, error) {
329-
// Update stats
330-
s.BasicStats.Gets++
345+
func (s *Store) rawGetNode(key string, node *Node) ([]*Response, error) {
346+
resps := make([]*Response, 1)
331347

332-
key = path.Clean("/" + key)
333-
334-
nodes, keys, ok := s.Tree.list(key)
348+
isExpire := !node.ExpireTime.Equal(PERMANENT)
335349

336-
if ok {
350+
resps[0] = &Response{
351+
Action: "GET",
352+
Index: s.Index,
353+
Key: key,
354+
Value: node.Value,
355+
}
337356

338-
node, ok := nodes.(*Node)
357+
// Update ttl
358+
if isExpire {
359+
TTL := int64(node.ExpireTime.Sub(time.Now()) / time.Second)
360+
resps[0].Expiration = &node.ExpireTime
361+
resps[0].TTL = TTL
362+
}
339363

340-
if ok {
341-
resps := make([]*Response, 1)
364+
return resps, nil
365+
}
342366

343-
isExpire := !node.ExpireTime.Equal(PERMANENT)
367+
func (s *Store) rawGetNodeList(key string, keys []string, nodes []*Node) ([]*Response, error) {
368+
resps := make([]*Response, len(nodes))
344369

345-
resps[0] = &Response{
346-
Action: "GET",
347-
Index: s.Index,
348-
Key: key,
349-
Value: node.Value,
350-
}
370+
// TODO: check if nodes and keys are the same length
371+
for i := 0; i < len(nodes); i++ {
372+
var TTL int64
373+
var isExpire bool = false
351374

352-
// Update ttl
353-
if isExpire {
354-
TTL := int64(node.ExpireTime.Sub(time.Now()) / time.Second)
355-
resps[0].Expiration = &node.ExpireTime
356-
resps[0].TTL = TTL
357-
}
375+
isExpire = !nodes[i].ExpireTime.Equal(PERMANENT)
358376

359-
return resps, nil
377+
resps[i] = &Response{
378+
Action: "GET",
379+
Index: s.Index,
380+
Key: path.Join(key, keys[i]),
360381
}
361382

362-
nodes, _ := nodes.([]*Node)
363-
364-
resps := make([]*Response, len(nodes))
365-
for i := 0; i < len(nodes); i++ {
366-
367-
var TTL int64
368-
var isExpire bool = false
383+
if len(nodes[i].Value) != 0 {
384+
resps[i].Value = nodes[i].Value
385+
} else {
386+
resps[i].Dir = true
387+
}
369388

370-
isExpire = !nodes[i].ExpireTime.Equal(PERMANENT)
389+
// Update ttl
390+
if isExpire {
391+
TTL = int64(nodes[i].ExpireTime.Sub(time.Now()) / time.Second)
392+
resps[i].Expiration = &nodes[i].ExpireTime
393+
resps[i].TTL = TTL
394+
}
371395

372-
resps[i] = &Response{
373-
Action: "GET",
374-
Index: s.Index,
375-
Key: path.Join(key, keys[i]),
376-
}
396+
}
377397

378-
if len(nodes[i].Value) != 0 {
379-
resps[i].Value = nodes[i].Value
380-
} else {
381-
resps[i].Dir = true
382-
}
398+
return resps, nil
399+
}
383400

384-
// Update ttl
385-
if isExpire {
386-
TTL = int64(nodes[i].ExpireTime.Sub(time.Now()) / time.Second)
387-
resps[i].Expiration = &nodes[i].ExpireTime
388-
resps[i].TTL = TTL
389-
}
401+
func (s *Store) RawGet(key string) ([]*Response, error) {
402+
// Update stats
403+
s.BasicStats.Gets++
390404

391-
}
405+
key = path.Clean("/" + key)
392406

393-
return resps, nil
407+
nodes, keys, ok := s.Tree.list(key)
408+
if !ok {
409+
return nil, etcdErr.NewError(100, "get: "+key)
394410
}
395411

396-
return nil, etcdErr.NewError(100, "get: "+key)
412+
switch node := nodes.(type) {
413+
case *Node:
414+
return s.rawGetNode(key, node)
415+
case []*Node:
416+
return s.rawGetNodeList(key, keys, node)
417+
default:
418+
panic("invalid cast ")
419+
}
397420
}
398421

399422
func (s *Store) Delete(key string, index uint64) ([]byte, error) {
@@ -415,43 +438,41 @@ func (s *Store) internalDelete(key string, index uint64) ([]byte, error) {
415438

416439
node, ok := s.Tree.get(key)
417440

418-
if ok {
419-
420-
resp := Response{
421-
Action: "DELETE",
422-
Key: key,
423-
PrevValue: node.Value,
424-
Index: index,
425-
}
441+
if !ok {
442+
return nil, etcdErr.NewError(100, "delete: "+key)
443+
}
426444

427-
if node.ExpireTime.Equal(PERMANENT) {
445+
resp := Response{
446+
Action: "DELETE",
447+
Key: key,
448+
PrevValue: node.Value,
449+
Index: index,
450+
}
428451

429-
s.Tree.delete(key)
452+
if node.ExpireTime.Equal(PERMANENT) {
430453

431-
} else {
432-
resp.Expiration = &node.ExpireTime
433-
// Kill the expire go routine
434-
node.update <- PERMANENT
435-
s.Tree.delete(key)
454+
s.Tree.delete(key)
436455

437-
}
456+
} else {
457+
resp.Expiration = &node.ExpireTime
458+
// Kill the expire go routine
459+
node.update <- PERMANENT
460+
s.Tree.delete(key)
438461

439-
msg, err := json.Marshal(resp)
462+
}
440463

441-
s.watcher.notify(resp)
464+
msg, err := json.Marshal(resp)
442465

443-
// notify the messager
444-
if s.messager != nil && err == nil {
445-
s.messager <- string(msg)
446-
}
466+
s.watcher.notify(resp)
447467

448-
s.addToResponseMap(index, &resp)
468+
// notify the messager
469+
if s.messager != nil && err == nil {
470+
s.messager <- string(msg)
471+
}
449472

450-
return msg, err
473+
s.addToResponseMap(index, &resp)
451474

452-
} else {
453-
return nil, etcdErr.NewError(100, "delete: "+key)
454-
}
475+
return msg, err
455476
}
456477

457478
// Set the value of the key to the value if the given prevValue is equal to the value of the key
@@ -465,12 +486,16 @@ func (s *Store) TestAndSet(key string, prevValue string, value string, expireTim
465486
resp := s.internalGet(key)
466487

467488
if resp == nil {
468-
return nil, etcdErr.NewError(100, "testandset: "+key)
489+
if prevValue != "" {
490+
errmsg := fmt.Sprintf("TestAndSet: key not found and previousValue is not empty %s:%s ", key, prevValue)
491+
return nil, etcdErr.NewError(100, errmsg)
492+
}
493+
return s.internalSet(key, value, expireTime, index)
469494
}
470495

471496
if resp.Value == prevValue {
472497

473-
// If test success, do set
498+
// If test succeed, do set
474499
return s.internalSet(key, value, expireTime, index)
475500
} else {
476501

0 commit comments

Comments
 (0)