-
Notifications
You must be signed in to change notification settings - Fork 40
/
registry.go
141 lines (125 loc) · 2.76 KB
/
registry.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
130
131
132
133
134
135
136
137
138
139
140
141
package main
import (
"encoding/hex"
"encoding/json"
"errors"
"flag"
"fmt"
"strings"
"time"
cb "github.com/couchbaselabs/go-couchbase"
)
var serverId string
var nodeKeys = flag.Int("nodeKeys", 0, "number of additional node keys")
func init() {
flag.StringVar(&serverId, "nodeID", "",
"Node ID (defaults to what's stored in guid file or arbitrary)")
}
const nodeListPrefix = "/@nodes"
var nodeListKeys = []string{nodeListPrefix}
func initNodeListKeys() {
for i := 0; i < *nodeKeys; i++ {
nodeListKeys = append(nodeListKeys,
fmt.Sprintf("%v.%v", nodeListPrefix, i))
}
}
// List of names of nodes
type NodeRegistry struct {
Nodes map[string]int64 `json:"nodes"`
LastModTime time.Time `json:"lastModTime"`
LastModBy string `json:"lastModBy"`
}
func validateServerId(s string) error {
invalid := errors.New("Invalid server id: " + s)
switch {
case len(s) == 0:
return invalid
case s[0] == '/' || s[0] == '@':
return invalid
}
return nil
}
type errslice []error
func (e errslice) Error() string {
es := []string{}
for _, err := range e {
es = append(es, err.Error())
}
return "{Errors: " + strings.Join(es, ", ") + "}"
}
func setInNodeRegistry(nodeID string, size int64) error {
rv := errslice{}
for _, k := range nodeListKeys {
err := couchbase.Update(k, 0, func(in []byte) ([]byte, error) {
reg := NodeRegistry{}
err := json.Unmarshal(in, ®)
if err == nil {
reg.Nodes[nodeID] = size
} else {
reg.Nodes = map[string]int64{
nodeID: size,
}
}
reg.LastModTime = time.Now().UTC()
reg.LastModBy = serverId
return json.Marshal(reg)
})
if err != nil {
rv = append(rv, err)
}
}
if len(rv) == 0 {
return nil
}
return rv
}
func removeFromNodeRegistry(nodeID string) error {
rv := errslice{}
for _, k := range nodeListKeys {
err := couchbase.Update(k, 0, func(in []byte) ([]byte, error) {
reg := NodeRegistry{}
err := json.Unmarshal(in, ®)
if err == nil {
delete(reg.Nodes, nodeID)
} else {
return nil, cb.UpdateCancel
}
reg.LastModTime = time.Now().UTC()
reg.LastModBy = serverId
return json.Marshal(reg)
})
if err != nil {
rv = append(rv, err)
}
}
if len(rv) == 0 {
return nil
}
return rv
}
func retrieveNodeRegistry() (NodeRegistry, error) {
reg := NodeRegistry{}
var err error
for _, k := range nodeListKeys {
err = couchbase.Get(k, ®)
if err == nil {
return reg, nil
}
}
return reg, err
}
func initServerId() error {
var err error
var bytes []byte
if len(bytes) > 0 && err == nil {
serverId = strings.TrimSpace(string(bytes))
} else {
if serverId == "" {
h := getHash()
t := time.Now().UTC().Format(time.RFC3339Nano)
h.Write([]byte(t))
serverId = hex.EncodeToString(h.Sum(nil))[:8]
}
}
return err
}