-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathetcd.go
129 lines (116 loc) · 2.33 KB
/
etcd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package etcd
import (
"context"
"fmt"
"math/rand"
"strings"
"time"
"github.com/fperf/fperf"
"go.etcd.io/etcd/clientv3"
)
func init() {
fperf.Register("etcd", New, "etcd benchmark")
}
// Op is the operation type issued to etcd
type Op string
// Operations
const (
Put Op = "put"
Get Op = "get"
Range Op = "range"
Delete Op = "delete"
)
type client struct {
etcd *clientv3.Client
space *keySpace
op Op
}
// New creates a fperf client
func New(fs *fperf.FlagSet) fperf.Client {
var keySize int
var op Op
fs.IntVar(&keySize, "key-size", 4, "length of the random key")
fs.Parse()
args := fs.Args()
if len(args) == 0 {
op = Put
} else {
op = Op(args[0])
}
return &client{
space: newKeySpace(keySize),
op: op,
}
}
// Dial to etcd
func (c *client) Dial(addr string) error {
endpoints := strings.Split(addr, ",")
cli, err := clientv3.New(clientv3.Config{
Endpoints: endpoints,
DialTimeout: 2 * time.Second,
})
if err != nil {
return err
}
c.etcd = cli
return nil
}
// Request etcd
func (c *client) Request() error {
switch c.op {
case Put:
return doPut(c)
case Get:
return doGet(c)
case Range:
return doRange(c)
case Delete:
return doDelete(c)
}
return fmt.Errorf("unknown op %s", c.op)
}
func doPut(c *client) error {
key := c.space.randKey()
value := key
_, err := c.etcd.Put(context.Background(), key, value)
return err
}
func doGet(c *client) error {
_, err := c.etcd.Get(context.Background(), c.space.randKey())
return err
}
func doDelete(c *client) error {
_, err := c.etcd.Delete(context.Background(), c.space.randKey())
return err
}
func doRange(c *client) error {
start, end := c.space.randRange()
_, err := c.etcd.Get(context.Background(), start, clientv3.WithRange(end))
return err
}
type keySpace struct {
r *rand.Rand
nbytes int
}
func newKeySpace(nbytes int) *keySpace {
return &keySpace{
r: rand.New(rand.NewSource(time.Now().Unix())),
nbytes: nbytes,
}
}
func (ks *keySpace) randKey() string {
p := make([]byte, ks.nbytes)
ks.r.Read(p)
return string(p)
}
func (ks *keySpace) randRange() (string, string) {
start := []byte(ks.randKey())
if len(start) == 0 {
return "", ""
}
// the max range is 256 according to the last bytes of start
end := make([]byte, len(start))
copy(end, start)
end[len(end)-1] = 0xFF
return string(start), string(end)
}