Browse code

libnetwork: remove zookeeper-related code and tests

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2021/12/16 21:30:34
Showing 19 changed files
... ...
@@ -114,7 +114,7 @@ type ScopeClientCfg struct {
114 114
 const (
115 115
 	// LocalScope indicates to store the KV object in local datastore such as boltdb
116 116
 	LocalScope = "local"
117
-	// GlobalScope indicates to store the KV object in global datastore such as consul/etcd/zookeeper
117
+	// GlobalScope indicates to store the KV object in global datastore such as consul/etcd
118 118
 	GlobalScope = "global"
119 119
 	// SwarmScope is not indicating a datastore location. It is defined here
120 120
 	// along with the other two scopes just for consistency.
... ...
@@ -27,7 +27,7 @@ Docker version 1.8.0-dev, build f39b9a0, experimental
27 27
 
28 28
 
29 29
 Multi-host networking uses a pluggable Key-Value store backend to distribute states using `libkv`.
30
-`libkv` supports multiple pluggable backends such as `consul`, `etcd` & `zookeeper` (more to come).
30
+`libkv` supports multiple pluggable backends such as `consul`, `etcd` (more to come).
31 31
 
32 32
 In this example we will use `consul`
33 33
 
... ...
@@ -8,13 +8,11 @@ import (
8 8
 	"github.com/docker/libkv/store/boltdb"
9 9
 	"github.com/docker/libkv/store/consul"
10 10
 	"github.com/docker/libkv/store/etcd"
11
-	"github.com/docker/libkv/store/zookeeper"
12 11
 	"github.com/sirupsen/logrus"
13 12
 )
14 13
 
15 14
 func registerKVStores() {
16 15
 	consul.Register()
17
-	zookeeper.Register()
18 16
 	etcd.Register()
19 17
 	boltdb.Register()
20 18
 }
... ...
@@ -149,9 +149,7 @@ function start_dnet() {
149 149
     # Try discovery URLs with or without path
150 150
     neigh_ip=""
151 151
     neighbors=""
152
-    if [ "$store" = "zookeeper" ]; then
153
-	read discovery provider address < <(parse_discovery_str zk://${bridge_ip}:2182)
154
-    elif [ "$store" = "etcd" ]; then
152
+    if [ "$store" = "etcd" ]; then
155 153
 	read discovery provider address < <(parse_discovery_str etcd://${bridge_ip}:42000/custom_prefix)
156 154
     elif [ "$store" = "consul" ]; then
157 155
 	read discovery provider address < <(parse_discovery_str consul://${bridge_ip}:8500/custom_prefix)
... ...
@@ -288,21 +286,6 @@ function stop_etcd() {
288 288
     docker rm -f dn_etcd || true
289 289
 }
290 290
 
291
-function start_zookeeper() {
292
-    stop_zookeeper
293
-    docker run -d \
294
-	   --name=zookeeper_server \
295
-	   -p 2182:2181 \
296
-	   -h zookeeper \
297
-	   dnephin/docker-zookeeper:3.4.6
298
-    sleep 2
299
-}
300
-
301
-function stop_zookeeper() {
302
-    echo "zookeeper started"
303
-    docker rm -f zookeeper_server || true
304
-}
305
-
306 291
 function test_overlay() {
307 292
     dnet_suffix=$1
308 293
 
309 294
deleted file mode 100644
... ...
@@ -1,8 +0,0 @@
1
-# -*- mode: sh -*-
2
-#!/usr/bin/env bats
3
-
4
-load helpers
5
-
6
-@test "Test overlay network with zookeeper" {
7
-    test_overlay zookeeper
8
-}
... ...
@@ -89,25 +89,6 @@ function run_overlay_consul_host_tests() {
89 89
 	unset _OVERLAY_HOST_MODE
90 90
 }
91 91
 
92
-function run_overlay_zk_tests() {
93
-	## Test overlay network with zookeeper
94
-	start_dnet 1 zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
95
-	cmap[dnet - 1 - zookeeper]=dnet-1-zookeeper
96
-	start_dnet 2 zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
97
-	cmap[dnet - 2 - zookeeper]=dnet-2-zookeeper
98
-	start_dnet 3 zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
99
-	cmap[dnet - 3 - zookeeper]=dnet-3-zookeeper
100
-
101
-	./integration-tmp/bin/bats ./test/integration/dnet/overlay-zookeeper.bats
102
-
103
-	stop_dnet 1 zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
104
-	unset cmap[dnet-1-zookeeper]
105
-	stop_dnet 2 zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
106
-	unset cmap[dnet-2-zookeeper]
107
-	stop_dnet 3 zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
108
-	unset cmap[dnet-3-zookeeper]
109
-}
110
-
111 92
 function run_overlay_etcd_tests() {
112 93
 	## Test overlay network with etcd
113 94
 	start_dnet 1 etcd 1>> ${INTEGRATION_ROOT}/test.log 2>&1
... ...
@@ -155,29 +136,6 @@ function run_multi_consul_tests() {
155 155
 	unset cmap[dnet-3-multi_consul]
156 156
 }
157 157
 
158
-function run_multi_zk_tests() {
159
-	# Test multi node configuration with a global scope test driver backed by zookeeper
160
-
161
-	## Setup
162
-	start_dnet 1 multi_zk zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
163
-	cmap[dnet - 1 - multi_zk]=dnet-1-multi_zk
164
-	start_dnet 2 multi_zk zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
165
-	cmap[dnet - 2 - multi_zk]=dnet-2-multi_zk
166
-	start_dnet 3 multi_zk zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
167
-	cmap[dnet - 3 - multi_zk]=dnet-3-multi_zk
168
-
169
-	## Run the test cases
170
-	./integration-tmp/bin/bats ./test/integration/dnet/multi.bats
171
-
172
-	## Teardown
173
-	stop_dnet 1 multi_zk 1>> ${INTEGRATION_ROOT}/test.log 2>&1
174
-	unset cmap[dnet-1-multi_zk]
175
-	stop_dnet 2 multi_zk 1>> ${INTEGRATION_ROOT}/test.log 2>&1
176
-	unset cmap[dnet-2-multi_zk]
177
-	stop_dnet 3 multi_zk 1>> ${INTEGRATION_ROOT}/test.log 2>&1
178
-	unset cmap[dnet-3-multi_zk]
179
-}
180
-
181 158
 function run_multi_etcd_tests() {
182 159
 	# Test multi node configuration with a global scope test driver backed by etcd
183 160
 
... ...
@@ -220,7 +178,7 @@ fi
220 220
 # Suite setup
221 221
 
222 222
 if [ -z "$SUITES" ]; then
223
-	suites="dnet multi_consul multi_zk multi_etcd  bridge overlay_consul overlay_consul_host overlay_zk overlay_etcd"
223
+	suites="dnet multi_consul multi_etcd  bridge overlay_consul overlay_consul_host overlay_etcd"
224 224
 else
225 225
 	suites="$SUITES"
226 226
 fi
... ...
@@ -231,12 +189,6 @@ if [[ ("$suites" =~ .*consul.*) || ("$suites" =~ .*bridge.*) ]]; then
231 231
 	cmap[pr_consul]=pr_consul
232 232
 fi
233 233
 
234
-if [[ "$suites" =~ .*zk.* ]]; then
235
-	echo "Starting zookeeper ..."
236
-	start_zookeeper 1>> ${INTEGRATION_ROOT}/test.log 2>&1
237
-	cmap[zookeeper_server]=zookeeper_server
238
-fi
239
-
240 234
 if [[ "$suites" =~ .*etcd.* ]]; then
241 235
 	echo "Starting etcd ..."
242 236
 	start_etcd 1>> ${INTEGRATION_ROOT}/test.log 2>&1
... ...
@@ -60,7 +60,6 @@ github.com/vishvananda/netlink                      f049be6f391489d3f374498fe0c8
60 60
 github.com/moby/ipvs                                4566ccea0e08d68e9614c3e7a64a23b850c4bb35 # v1.0.1
61 61
 github.com/google/btree                             479b5e81b0a93ec038d201b0b33d17db599531d3 # v1.0.1
62 62
 
63
-github.com/samuel/go-zookeeper                      d0e0d8e11f318e000a8cc434616d69e329edc374
64 63
 github.com/deckarep/golang-set                      ef32fa3046d9f249d399f98ebaf9be944430fd1d
65 64
 github.com/coreos/etcd                              973882f697a8db3d59815bf132c6c506434334bd # v3.3.27
66 65
 github.com/coreos/go-semver                         8ab6407b697782a06568d4b7f1db25550ec2e4c6 # v0.2.0
67 66
deleted file mode 100644
... ...
@@ -1,429 +0,0 @@
1
-package zookeeper
2
-
3
-import (
4
-	"strings"
5
-	"time"
6
-
7
-	"github.com/docker/libkv"
8
-	"github.com/docker/libkv/store"
9
-	zk "github.com/samuel/go-zookeeper/zk"
10
-)
11
-
12
-const (
13
-	// SOH control character
14
-	SOH = "\x01"
15
-
16
-	defaultTimeout = 10 * time.Second
17
-)
18
-
19
-// Zookeeper is the receiver type for
20
-// the Store interface
21
-type Zookeeper struct {
22
-	timeout time.Duration
23
-	client  *zk.Conn
24
-}
25
-
26
-type zookeeperLock struct {
27
-	client *zk.Conn
28
-	lock   *zk.Lock
29
-	key    string
30
-	value  []byte
31
-}
32
-
33
-// Register registers zookeeper to libkv
34
-func Register() {
35
-	libkv.AddStore(store.ZK, New)
36
-}
37
-
38
-// New creates a new Zookeeper client given a
39
-// list of endpoints and an optional tls config
40
-func New(endpoints []string, options *store.Config) (store.Store, error) {
41
-	s := &Zookeeper{}
42
-	s.timeout = defaultTimeout
43
-
44
-	// Set options
45
-	if options != nil {
46
-		if options.ConnectionTimeout != 0 {
47
-			s.setTimeout(options.ConnectionTimeout)
48
-		}
49
-	}
50
-
51
-	// Connect to Zookeeper
52
-	conn, _, err := zk.Connect(endpoints, s.timeout)
53
-	if err != nil {
54
-		return nil, err
55
-	}
56
-	s.client = conn
57
-
58
-	return s, nil
59
-}
60
-
61
-// setTimeout sets the timeout for connecting to Zookeeper
62
-func (s *Zookeeper) setTimeout(time time.Duration) {
63
-	s.timeout = time
64
-}
65
-
66
-// Get the value at "key", returns the last modified index
67
-// to use in conjunction to Atomic calls
68
-func (s *Zookeeper) Get(key string) (pair *store.KVPair, err error) {
69
-	resp, meta, err := s.client.Get(s.normalize(key))
70
-
71
-	if err != nil {
72
-		if err == zk.ErrNoNode {
73
-			return nil, store.ErrKeyNotFound
74
-		}
75
-		return nil, err
76
-	}
77
-
78
-	// FIXME handle very rare cases where Get returns the
79
-	// SOH control character instead of the actual value
80
-	if string(resp) == SOH {
81
-		return s.Get(store.Normalize(key))
82
-	}
83
-
84
-	pair = &store.KVPair{
85
-		Key:       key,
86
-		Value:     resp,
87
-		LastIndex: uint64(meta.Version),
88
-	}
89
-
90
-	return pair, nil
91
-}
92
-
93
-// createFullPath creates the entire path for a directory
94
-// that does not exist
95
-func (s *Zookeeper) createFullPath(path []string, ephemeral bool) error {
96
-	for i := 1; i <= len(path); i++ {
97
-		newpath := "/" + strings.Join(path[:i], "/")
98
-		if i == len(path) && ephemeral {
99
-			_, err := s.client.Create(newpath, []byte{}, zk.FlagEphemeral, zk.WorldACL(zk.PermAll))
100
-			return err
101
-		}
102
-		_, err := s.client.Create(newpath, []byte{}, 0, zk.WorldACL(zk.PermAll))
103
-		if err != nil {
104
-			// Skip if node already exists
105
-			if err != zk.ErrNodeExists {
106
-				return err
107
-			}
108
-		}
109
-	}
110
-	return nil
111
-}
112
-
113
-// Put a value at "key"
114
-func (s *Zookeeper) Put(key string, value []byte, opts *store.WriteOptions) error {
115
-	fkey := s.normalize(key)
116
-
117
-	exists, err := s.Exists(key)
118
-	if err != nil {
119
-		return err
120
-	}
121
-
122
-	if !exists {
123
-		if opts != nil && opts.TTL > 0 {
124
-			s.createFullPath(store.SplitKey(strings.TrimSuffix(key, "/")), true)
125
-		} else {
126
-			s.createFullPath(store.SplitKey(strings.TrimSuffix(key, "/")), false)
127
-		}
128
-	}
129
-
130
-	_, err = s.client.Set(fkey, value, -1)
131
-	return err
132
-}
133
-
134
-// Delete a value at "key"
135
-func (s *Zookeeper) Delete(key string) error {
136
-	err := s.client.Delete(s.normalize(key), -1)
137
-	if err == zk.ErrNoNode {
138
-		return store.ErrKeyNotFound
139
-	}
140
-	return err
141
-}
142
-
143
-// Exists checks if the key exists inside the store
144
-func (s *Zookeeper) Exists(key string) (bool, error) {
145
-	exists, _, err := s.client.Exists(s.normalize(key))
146
-	if err != nil {
147
-		return false, err
148
-	}
149
-	return exists, nil
150
-}
151
-
152
-// Watch for changes on a "key"
153
-// It returns a channel that will receive changes or pass
154
-// on errors. Upon creation, the current value will first
155
-// be sent to the channel. Providing a non-nil stopCh can
156
-// be used to stop watching.
157
-func (s *Zookeeper) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) {
158
-	// Get the key first
159
-	pair, err := s.Get(key)
160
-	if err != nil {
161
-		return nil, err
162
-	}
163
-
164
-	// Catch zk notifications and fire changes into the channel.
165
-	watchCh := make(chan *store.KVPair)
166
-	go func() {
167
-		defer close(watchCh)
168
-
169
-		// Get returns the current value to the channel prior
170
-		// to listening to any event that may occur on that key
171
-		watchCh <- pair
172
-		for {
173
-			_, _, eventCh, err := s.client.GetW(s.normalize(key))
174
-			if err != nil {
175
-				return
176
-			}
177
-			select {
178
-			case e := <-eventCh:
179
-				if e.Type == zk.EventNodeDataChanged {
180
-					if entry, err := s.Get(key); err == nil {
181
-						watchCh <- entry
182
-					}
183
-				}
184
-			case <-stopCh:
185
-				// There is no way to stop GetW so just quit
186
-				return
187
-			}
188
-		}
189
-	}()
190
-
191
-	return watchCh, nil
192
-}
193
-
194
-// WatchTree watches for changes on a "directory"
195
-// It returns a channel that will receive changes or pass
196
-// on errors. Upon creating a watch, the current childs values
197
-// will be sent to the channel .Providing a non-nil stopCh can
198
-// be used to stop watching.
199
-func (s *Zookeeper) WatchTree(directory string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) {
200
-	// List the childrens first
201
-	entries, err := s.List(directory)
202
-	if err != nil {
203
-		return nil, err
204
-	}
205
-
206
-	// Catch zk notifications and fire changes into the channel.
207
-	watchCh := make(chan []*store.KVPair)
208
-	go func() {
209
-		defer close(watchCh)
210
-
211
-		// List returns the children values to the channel
212
-		// prior to listening to any events that may occur
213
-		// on those keys
214
-		watchCh <- entries
215
-
216
-		for {
217
-			_, _, eventCh, err := s.client.ChildrenW(s.normalize(directory))
218
-			if err != nil {
219
-				return
220
-			}
221
-			select {
222
-			case e := <-eventCh:
223
-				if e.Type == zk.EventNodeChildrenChanged {
224
-					if kv, err := s.List(directory); err == nil {
225
-						watchCh <- kv
226
-					}
227
-				}
228
-			case <-stopCh:
229
-				// There is no way to stop GetW so just quit
230
-				return
231
-			}
232
-		}
233
-	}()
234
-
235
-	return watchCh, nil
236
-}
237
-
238
-// List child nodes of a given directory
239
-func (s *Zookeeper) List(directory string) ([]*store.KVPair, error) {
240
-	keys, stat, err := s.client.Children(s.normalize(directory))
241
-	if err != nil {
242
-		if err == zk.ErrNoNode {
243
-			return nil, store.ErrKeyNotFound
244
-		}
245
-		return nil, err
246
-	}
247
-
248
-	kv := []*store.KVPair{}
249
-
250
-	// FIXME Costly Get request for each child key..
251
-	for _, key := range keys {
252
-		pair, err := s.Get(strings.TrimSuffix(directory, "/") + s.normalize(key))
253
-		if err != nil {
254
-			// If node is not found: List is out of date, retry
255
-			if err == store.ErrKeyNotFound {
256
-				return s.List(directory)
257
-			}
258
-			return nil, err
259
-		}
260
-
261
-		kv = append(kv, &store.KVPair{
262
-			Key:       key,
263
-			Value:     []byte(pair.Value),
264
-			LastIndex: uint64(stat.Version),
265
-		})
266
-	}
267
-
268
-	return kv, nil
269
-}
270
-
271
-// DeleteTree deletes a range of keys under a given directory
272
-func (s *Zookeeper) DeleteTree(directory string) error {
273
-	pairs, err := s.List(directory)
274
-	if err != nil {
275
-		return err
276
-	}
277
-
278
-	var reqs []interface{}
279
-
280
-	for _, pair := range pairs {
281
-		reqs = append(reqs, &zk.DeleteRequest{
282
-			Path:    s.normalize(directory + "/" + pair.Key),
283
-			Version: -1,
284
-		})
285
-	}
286
-
287
-	_, err = s.client.Multi(reqs...)
288
-	return err
289
-}
290
-
291
-// AtomicPut put a value at "key" if the key has not been
292
-// modified in the meantime, throws an error if this is the case
293
-func (s *Zookeeper) AtomicPut(key string, value []byte, previous *store.KVPair, _ *store.WriteOptions) (bool, *store.KVPair, error) {
294
-	var lastIndex uint64
295
-
296
-	if previous != nil {
297
-		meta, err := s.client.Set(s.normalize(key), value, int32(previous.LastIndex))
298
-		if err != nil {
299
-			// Compare Failed
300
-			if err == zk.ErrBadVersion {
301
-				return false, nil, store.ErrKeyModified
302
-			}
303
-			return false, nil, err
304
-		}
305
-		lastIndex = uint64(meta.Version)
306
-	} else {
307
-		// Interpret previous == nil as create operation.
308
-		_, err := s.client.Create(s.normalize(key), value, 0, zk.WorldACL(zk.PermAll))
309
-		if err != nil {
310
-			// Directory does not exist
311
-			if err == zk.ErrNoNode {
312
-
313
-				// Create the directory
314
-				parts := store.SplitKey(strings.TrimSuffix(key, "/"))
315
-				parts = parts[:len(parts)-1]
316
-				if err = s.createFullPath(parts, false); err != nil {
317
-					// Failed to create the directory.
318
-					return false, nil, err
319
-				}
320
-
321
-				// Create the node
322
-				if _, err := s.client.Create(s.normalize(key), value, 0, zk.WorldACL(zk.PermAll)); err != nil {
323
-					// Node exist error (when previous nil)
324
-					if err == zk.ErrNodeExists {
325
-						return false, nil, store.ErrKeyExists
326
-					}
327
-					return false, nil, err
328
-				}
329
-
330
-			} else {
331
-				// Node Exists error (when previous nil)
332
-				if err == zk.ErrNodeExists {
333
-					return false, nil, store.ErrKeyExists
334
-				}
335
-
336
-				// Unhandled error
337
-				return false, nil, err
338
-			}
339
-		}
340
-		lastIndex = 0 // Newly created nodes have version 0.
341
-	}
342
-
343
-	pair := &store.KVPair{
344
-		Key:       key,
345
-		Value:     value,
346
-		LastIndex: lastIndex,
347
-	}
348
-
349
-	return true, pair, nil
350
-}
351
-
352
-// AtomicDelete deletes a value at "key" if the key
353
-// has not been modified in the meantime, throws an
354
-// error if this is the case
355
-func (s *Zookeeper) AtomicDelete(key string, previous *store.KVPair) (bool, error) {
356
-	if previous == nil {
357
-		return false, store.ErrPreviousNotSpecified
358
-	}
359
-
360
-	err := s.client.Delete(s.normalize(key), int32(previous.LastIndex))
361
-	if err != nil {
362
-		// Key not found
363
-		if err == zk.ErrNoNode {
364
-			return false, store.ErrKeyNotFound
365
-		}
366
-		// Compare failed
367
-		if err == zk.ErrBadVersion {
368
-			return false, store.ErrKeyModified
369
-		}
370
-		// General store error
371
-		return false, err
372
-	}
373
-	return true, nil
374
-}
375
-
376
-// NewLock returns a handle to a lock struct which can
377
-// be used to provide mutual exclusion on a key
378
-func (s *Zookeeper) NewLock(key string, options *store.LockOptions) (lock store.Locker, err error) {
379
-	value := []byte("")
380
-
381
-	// Apply options
382
-	if options != nil {
383
-		if options.Value != nil {
384
-			value = options.Value
385
-		}
386
-	}
387
-
388
-	lock = &zookeeperLock{
389
-		client: s.client,
390
-		key:    s.normalize(key),
391
-		value:  value,
392
-		lock:   zk.NewLock(s.client, s.normalize(key), zk.WorldACL(zk.PermAll)),
393
-	}
394
-
395
-	return lock, err
396
-}
397
-
398
-// Lock attempts to acquire the lock and blocks while
399
-// doing so. It returns a channel that is closed if our
400
-// lock is lost or if an error occurs
401
-func (l *zookeeperLock) Lock(stopChan chan struct{}) (<-chan struct{}, error) {
402
-	err := l.lock.Lock()
403
-
404
-	if err == nil {
405
-		// We hold the lock, we can set our value
406
-		// FIXME: The value is left behind
407
-		// (problematic for leader election)
408
-		_, err = l.client.Set(l.key, l.value, -1)
409
-	}
410
-
411
-	return make(chan struct{}), err
412
-}
413
-
414
-// Unlock the "key". Calling unlock while
415
-// not holding the lock will throw an error
416
-func (l *zookeeperLock) Unlock() error {
417
-	return l.lock.Unlock()
418
-}
419
-
420
-// Close closes the client connection
421
-func (s *Zookeeper) Close() {
422
-	s.client.Close()
423
-}
424
-
425
-// Normalize the key for usage in Zookeeper
426
-func (s *Zookeeper) normalize(key string) string {
427
-	key = store.Normalize(key)
428
-	return strings.TrimSuffix(key, "/")
429
-}
430 1
deleted file mode 100644
... ...
@@ -1,25 +0,0 @@
1
-Copyright (c) 2013, Samuel Stauffer <samuel@descolada.com>
2
-All rights reserved.
3
-
4
-Redistribution and use in source and binary forms, with or without
5
-modification, are permitted provided that the following conditions are met:
6
-
7
-* Redistributions of source code must retain the above copyright
8
-  notice, this list of conditions and the following disclaimer.
9
-* Redistributions in binary form must reproduce the above copyright
10
-  notice, this list of conditions and the following disclaimer in the
11
-  documentation and/or other materials provided with the distribution.
12
-* Neither the name of the author nor the
13
-  names of its contributors may be used to endorse or promote products
14
-  derived from this software without specific prior written permission.
15
-
16
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
-DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1
deleted file mode 100644
... ...
@@ -1,11 +0,0 @@
1
-Native Go Zookeeper Client Library
2
-===================================
3
-
4
-[![Build Status](https://travis-ci.org/samuel/go-zookeeper.png)](https://travis-ci.org/samuel/go-zookeeper)
5
-
6
-Documentation: http://godoc.org/github.com/samuel/go-zookeeper/zk
7
-
8
-License
9
-
10
-3-clause BSD. See LICENSE file.
11 1
deleted file mode 100644
... ...
@@ -1,844 +0,0 @@
1
-package zk
2
-
3
-/*
4
-TODO:
5
-* make sure a ping response comes back in a reasonable time
6
-
7
-Possible watcher events:
8
-* Event{Type: EventNotWatching, State: StateDisconnected, Path: path, Err: err}
9
-*/
10
-
11
-import (
12
-	"crypto/rand"
13
-	"encoding/binary"
14
-	"errors"
15
-	"fmt"
16
-	"io"
17
-	"log"
18
-	"net"
19
-	"strconv"
20
-	"strings"
21
-	"sync"
22
-	"sync/atomic"
23
-	"time"
24
-)
25
-
26
-var ErrNoServer = errors.New("zk: could not connect to a server")
27
-
28
-const (
29
-	bufferSize      = 1536 * 1024
30
-	eventChanSize   = 6
31
-	sendChanSize    = 16
32
-	protectedPrefix = "_c_"
33
-)
34
-
35
-type watchType int
36
-
37
-const (
38
-	watchTypeData  = iota
39
-	watchTypeExist = iota
40
-	watchTypeChild = iota
41
-)
42
-
43
-type watchPathType struct {
44
-	path  string
45
-	wType watchType
46
-}
47
-
48
-type Dialer func(network, address string, timeout time.Duration) (net.Conn, error)
49
-
50
-type Conn struct {
51
-	lastZxid  int64
52
-	sessionID int64
53
-	state     State // must be 32-bit aligned
54
-	xid       uint32
55
-	timeout   int32 // session timeout in milliseconds
56
-	passwd    []byte
57
-
58
-	dialer          Dialer
59
-	servers         []string
60
-	serverIndex     int // remember last server that was tried during connect to round-robin attempts to servers
61
-	lastServerIndex int // index of the last server that was successfully connected to and authenticated with
62
-	conn            net.Conn
63
-	eventChan       chan Event
64
-	shouldQuit      chan struct{}
65
-	pingInterval    time.Duration
66
-	recvTimeout     time.Duration
67
-	connectTimeout  time.Duration
68
-
69
-	sendChan     chan *request
70
-	requests     map[int32]*request // Xid -> pending request
71
-	requestsLock sync.Mutex
72
-	watchers     map[watchPathType][]chan Event
73
-	watchersLock sync.Mutex
74
-
75
-	// Debug (used by unit tests)
76
-	reconnectDelay time.Duration
77
-}
78
-
79
-type request struct {
80
-	xid        int32
81
-	opcode     int32
82
-	pkt        interface{}
83
-	recvStruct interface{}
84
-	recvChan   chan response
85
-
86
-	// Because sending and receiving happen in separate go routines, there's
87
-	// a possible race condition when creating watches from outside the read
88
-	// loop. We must ensure that a watcher gets added to the list synchronously
89
-	// with the response from the server on any request that creates a watch.
90
-	// In order to not hard code the watch logic for each opcode in the recv
91
-	// loop the caller can use recvFunc to insert some synchronously code
92
-	// after a response.
93
-	recvFunc func(*request, *responseHeader, error)
94
-}
95
-
96
-type response struct {
97
-	zxid int64
98
-	err  error
99
-}
100
-
101
-type Event struct {
102
-	Type   EventType
103
-	State  State
104
-	Path   string // For non-session events, the path of the watched node.
105
-	Err    error
106
-	Server string // For connection events
107
-}
108
-
109
-// Connect establishes a new connection to a pool of zookeeper servers
110
-// using the default net.Dialer. See ConnectWithDialer for further
111
-// information about session timeout.
112
-func Connect(servers []string, sessionTimeout time.Duration) (*Conn, <-chan Event, error) {
113
-	return ConnectWithDialer(servers, sessionTimeout, nil)
114
-}
115
-
116
-// ConnectWithDialer establishes a new connection to a pool of zookeeper
117
-// servers. The provided session timeout sets the amount of time for which
118
-// a session is considered valid after losing connection to a server. Within
119
-// the session timeout it's possible to reestablish a connection to a different
120
-// server and keep the same session. This is means any ephemeral nodes and
121
-// watches are maintained.
122
-func ConnectWithDialer(servers []string, sessionTimeout time.Duration, dialer Dialer) (*Conn, <-chan Event, error) {
123
-	if len(servers) == 0 {
124
-		return nil, nil, errors.New("zk: server list must not be empty")
125
-	}
126
-
127
-	recvTimeout := sessionTimeout * 2 / 3
128
-
129
-	srvs := make([]string, len(servers))
130
-
131
-	for i, addr := range servers {
132
-		if strings.Contains(addr, ":") {
133
-			srvs[i] = addr
134
-		} else {
135
-			srvs[i] = addr + ":" + strconv.Itoa(DefaultPort)
136
-		}
137
-	}
138
-
139
-	// Randomize the order of the servers to avoid creating hotspots
140
-	stringShuffle(srvs)
141
-
142
-	ec := make(chan Event, eventChanSize)
143
-	if dialer == nil {
144
-		dialer = net.DialTimeout
145
-	}
146
-	conn := Conn{
147
-		dialer:          dialer,
148
-		servers:         srvs,
149
-		serverIndex:     0,
150
-		lastServerIndex: -1,
151
-		conn:            nil,
152
-		state:           StateDisconnected,
153
-		eventChan:       ec,
154
-		shouldQuit:      make(chan struct{}),
155
-		recvTimeout:     recvTimeout,
156
-		pingInterval:    recvTimeout / 2,
157
-		connectTimeout:  1 * time.Second,
158
-		sendChan:        make(chan *request, sendChanSize),
159
-		requests:        make(map[int32]*request),
160
-		watchers:        make(map[watchPathType][]chan Event),
161
-		passwd:          emptyPassword,
162
-		timeout:         int32(sessionTimeout.Nanoseconds() / 1e6),
163
-
164
-		// Debug
165
-		reconnectDelay: 0,
166
-	}
167
-	go func() {
168
-		conn.loop()
169
-		conn.flushRequests(ErrClosing)
170
-		conn.invalidateWatches(ErrClosing)
171
-		close(conn.eventChan)
172
-	}()
173
-	return &conn, ec, nil
174
-}
175
-
176
-func (c *Conn) Close() {
177
-	close(c.shouldQuit)
178
-
179
-	select {
180
-	case <-c.queueRequest(opClose, &closeRequest{}, &closeResponse{}, nil):
181
-	case <-time.After(time.Second):
182
-	}
183
-}
184
-
185
-func (c *Conn) State() State {
186
-	return State(atomic.LoadInt32((*int32)(&c.state)))
187
-}
188
-
189
-func (c *Conn) setState(state State) {
190
-	atomic.StoreInt32((*int32)(&c.state), int32(state))
191
-	select {
192
-	case c.eventChan <- Event{Type: EventSession, State: state, Server: c.servers[c.serverIndex]}:
193
-	default:
194
-		// panic("zk: event channel full - it must be monitored and never allowed to be full")
195
-	}
196
-}
197
-
198
-func (c *Conn) connect() error {
199
-	c.setState(StateConnecting)
200
-	for {
201
-		c.serverIndex = (c.serverIndex + 1) % len(c.servers)
202
-		if c.serverIndex == c.lastServerIndex {
203
-			c.flushUnsentRequests(ErrNoServer)
204
-			select {
205
-			case <-time.After(time.Second):
206
-				// pass
207
-			case <-c.shouldQuit:
208
-				c.setState(StateDisconnected)
209
-				c.flushUnsentRequests(ErrClosing)
210
-				return ErrClosing
211
-			}
212
-		} else if c.lastServerIndex < 0 {
213
-			// lastServerIndex defaults to -1 to avoid a delay on the initial connect
214
-			c.lastServerIndex = 0
215
-		}
216
-
217
-		zkConn, err := c.dialer("tcp", c.servers[c.serverIndex], c.connectTimeout)
218
-		if err == nil {
219
-			c.conn = zkConn
220
-			c.setState(StateConnected)
221
-			return nil
222
-		}
223
-
224
-		log.Printf("Failed to connect to %s: %+v", c.servers[c.serverIndex], err)
225
-	}
226
-}
227
-
228
-func (c *Conn) loop() {
229
-	for {
230
-		if err := c.connect(); err != nil {
231
-			// c.Close() was called
232
-			return
233
-		}
234
-
235
-		err := c.authenticate()
236
-		switch {
237
-		case err == ErrSessionExpired:
238
-			c.invalidateWatches(err)
239
-		case err != nil && c.conn != nil:
240
-			c.conn.Close()
241
-		case err == nil:
242
-			c.lastServerIndex = c.serverIndex
243
-			closeChan := make(chan struct{}) // channel to tell send loop stop
244
-			var wg sync.WaitGroup
245
-
246
-			wg.Add(1)
247
-			go func() {
248
-				c.sendLoop(c.conn, closeChan)
249
-				c.conn.Close() // causes recv loop to EOF/exit
250
-				wg.Done()
251
-			}()
252
-
253
-			wg.Add(1)
254
-			go func() {
255
-				err = c.recvLoop(c.conn)
256
-				if err == nil {
257
-					panic("zk: recvLoop should never return nil error")
258
-				}
259
-				close(closeChan) // tell send loop to exit
260
-				wg.Done()
261
-			}()
262
-
263
-			wg.Wait()
264
-		}
265
-
266
-		c.setState(StateDisconnected)
267
-
268
-		// Yeesh
269
-		if err != io.EOF && err != ErrSessionExpired && !strings.Contains(err.Error(), "use of closed network connection") {
270
-			log.Println(err)
271
-		}
272
-
273
-		select {
274
-		case <-c.shouldQuit:
275
-			c.flushRequests(ErrClosing)
276
-			return
277
-		default:
278
-		}
279
-
280
-		if err != ErrSessionExpired {
281
-			err = ErrConnectionClosed
282
-		}
283
-		c.flushRequests(err)
284
-
285
-		if c.reconnectDelay > 0 {
286
-			select {
287
-			case <-c.shouldQuit:
288
-				return
289
-			case <-time.After(c.reconnectDelay):
290
-			}
291
-		}
292
-	}
293
-}
294
-
295
-func (c *Conn) flushUnsentRequests(err error) {
296
-	for {
297
-		select {
298
-		default:
299
-			return
300
-		case req := <-c.sendChan:
301
-			req.recvChan <- response{-1, err}
302
-		}
303
-	}
304
-}
305
-
306
-// Send error to all pending requests and clear request map
307
-func (c *Conn) flushRequests(err error) {
308
-	c.requestsLock.Lock()
309
-	for _, req := range c.requests {
310
-		req.recvChan <- response{-1, err}
311
-	}
312
-	c.requests = make(map[int32]*request)
313
-	c.requestsLock.Unlock()
314
-}
315
-
316
-// Send error to all watchers and clear watchers map
317
-func (c *Conn) invalidateWatches(err error) {
318
-	c.watchersLock.Lock()
319
-	defer c.watchersLock.Unlock()
320
-
321
-	if len(c.watchers) >= 0 {
322
-		for pathType, watchers := range c.watchers {
323
-			ev := Event{Type: EventNotWatching, State: StateDisconnected, Path: pathType.path, Err: err}
324
-			for _, ch := range watchers {
325
-				ch <- ev
326
-				close(ch)
327
-			}
328
-		}
329
-		c.watchers = make(map[watchPathType][]chan Event)
330
-	}
331
-}
332
-
333
-func (c *Conn) sendSetWatches() {
334
-	c.watchersLock.Lock()
335
-	defer c.watchersLock.Unlock()
336
-
337
-	if len(c.watchers) == 0 {
338
-		return
339
-	}
340
-
341
-	req := &setWatchesRequest{
342
-		RelativeZxid: c.lastZxid,
343
-		DataWatches:  make([]string, 0),
344
-		ExistWatches: make([]string, 0),
345
-		ChildWatches: make([]string, 0),
346
-	}
347
-	n := 0
348
-	for pathType, watchers := range c.watchers {
349
-		if len(watchers) == 0 {
350
-			continue
351
-		}
352
-		switch pathType.wType {
353
-		case watchTypeData:
354
-			req.DataWatches = append(req.DataWatches, pathType.path)
355
-		case watchTypeExist:
356
-			req.ExistWatches = append(req.ExistWatches, pathType.path)
357
-		case watchTypeChild:
358
-			req.ChildWatches = append(req.ChildWatches, pathType.path)
359
-		}
360
-		n++
361
-	}
362
-	if n == 0 {
363
-		return
364
-	}
365
-
366
-	go func() {
367
-		res := &setWatchesResponse{}
368
-		_, err := c.request(opSetWatches, req, res, nil)
369
-		if err != nil {
370
-			log.Printf("Failed to set previous watches: %s", err.Error())
371
-		}
372
-	}()
373
-}
374
-
375
-func (c *Conn) authenticate() error {
376
-	buf := make([]byte, 256)
377
-
378
-	// connect request
379
-
380
-	n, err := encodePacket(buf[4:], &connectRequest{
381
-		ProtocolVersion: protocolVersion,
382
-		LastZxidSeen:    c.lastZxid,
383
-		TimeOut:         c.timeout,
384
-		SessionID:       c.sessionID,
385
-		Passwd:          c.passwd,
386
-	})
387
-	if err != nil {
388
-		return err
389
-	}
390
-
391
-	binary.BigEndian.PutUint32(buf[:4], uint32(n))
392
-
393
-	c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout * 10))
394
-	_, err = c.conn.Write(buf[:n+4])
395
-	c.conn.SetWriteDeadline(time.Time{})
396
-	if err != nil {
397
-		return err
398
-	}
399
-
400
-	c.sendSetWatches()
401
-
402
-	// connect response
403
-
404
-	// package length
405
-	c.conn.SetReadDeadline(time.Now().Add(c.recvTimeout * 10))
406
-	_, err = io.ReadFull(c.conn, buf[:4])
407
-	c.conn.SetReadDeadline(time.Time{})
408
-	if err != nil {
409
-		// Sometimes zookeeper just drops connection on invalid session data,
410
-		// we prefer to drop session and start from scratch when that event
411
-		// occurs instead of dropping into loop of connect/disconnect attempts
412
-		c.sessionID = 0
413
-		c.passwd = emptyPassword
414
-		c.lastZxid = 0
415
-		c.setState(StateExpired)
416
-		return ErrSessionExpired
417
-	}
418
-
419
-	blen := int(binary.BigEndian.Uint32(buf[:4]))
420
-	if cap(buf) < blen {
421
-		buf = make([]byte, blen)
422
-	}
423
-
424
-	_, err = io.ReadFull(c.conn, buf[:blen])
425
-	if err != nil {
426
-		return err
427
-	}
428
-
429
-	r := connectResponse{}
430
-	_, err = decodePacket(buf[:blen], &r)
431
-	if err != nil {
432
-		return err
433
-	}
434
-	if r.SessionID == 0 {
435
-		c.sessionID = 0
436
-		c.passwd = emptyPassword
437
-		c.lastZxid = 0
438
-		c.setState(StateExpired)
439
-		return ErrSessionExpired
440
-	}
441
-
442
-	if c.sessionID != r.SessionID {
443
-		atomic.StoreUint32(&c.xid, 0)
444
-	}
445
-	c.timeout = r.TimeOut
446
-	c.sessionID = r.SessionID
447
-	c.passwd = r.Passwd
448
-	c.setState(StateHasSession)
449
-
450
-	return nil
451
-}
452
-
453
-func (c *Conn) sendLoop(conn net.Conn, closeChan <-chan struct{}) error {
454
-	pingTicker := time.NewTicker(c.pingInterval)
455
-	defer pingTicker.Stop()
456
-
457
-	buf := make([]byte, bufferSize)
458
-	for {
459
-		select {
460
-		case req := <-c.sendChan:
461
-			header := &requestHeader{req.xid, req.opcode}
462
-			n, err := encodePacket(buf[4:], header)
463
-			if err != nil {
464
-				req.recvChan <- response{-1, err}
465
-				continue
466
-			}
467
-
468
-			n2, err := encodePacket(buf[4+n:], req.pkt)
469
-			if err != nil {
470
-				req.recvChan <- response{-1, err}
471
-				continue
472
-			}
473
-
474
-			n += n2
475
-
476
-			binary.BigEndian.PutUint32(buf[:4], uint32(n))
477
-
478
-			c.requestsLock.Lock()
479
-			select {
480
-			case <-closeChan:
481
-				req.recvChan <- response{-1, ErrConnectionClosed}
482
-				c.requestsLock.Unlock()
483
-				return ErrConnectionClosed
484
-			default:
485
-			}
486
-			c.requests[req.xid] = req
487
-			c.requestsLock.Unlock()
488
-
489
-			conn.SetWriteDeadline(time.Now().Add(c.recvTimeout))
490
-			_, err = conn.Write(buf[:n+4])
491
-			conn.SetWriteDeadline(time.Time{})
492
-			if err != nil {
493
-				req.recvChan <- response{-1, err}
494
-				conn.Close()
495
-				return err
496
-			}
497
-		case <-pingTicker.C:
498
-			n, err := encodePacket(buf[4:], &requestHeader{Xid: -2, Opcode: opPing})
499
-			if err != nil {
500
-				panic("zk: opPing should never fail to serialize")
501
-			}
502
-
503
-			binary.BigEndian.PutUint32(buf[:4], uint32(n))
504
-
505
-			conn.SetWriteDeadline(time.Now().Add(c.recvTimeout))
506
-			_, err = conn.Write(buf[:n+4])
507
-			conn.SetWriteDeadline(time.Time{})
508
-			if err != nil {
509
-				conn.Close()
510
-				return err
511
-			}
512
-		case <-closeChan:
513
-			return nil
514
-		}
515
-	}
516
-}
517
-
518
-func (c *Conn) recvLoop(conn net.Conn) error {
519
-	buf := make([]byte, bufferSize)
520
-	for {
521
-		// package length
522
-		conn.SetReadDeadline(time.Now().Add(c.recvTimeout))
523
-		_, err := io.ReadFull(conn, buf[:4])
524
-		if err != nil {
525
-			return err
526
-		}
527
-
528
-		blen := int(binary.BigEndian.Uint32(buf[:4]))
529
-		if cap(buf) < blen {
530
-			buf = make([]byte, blen)
531
-		}
532
-
533
-		_, err = io.ReadFull(conn, buf[:blen])
534
-		conn.SetReadDeadline(time.Time{})
535
-		if err != nil {
536
-			return err
537
-		}
538
-
539
-		res := responseHeader{}
540
-		_, err = decodePacket(buf[:16], &res)
541
-		if err != nil {
542
-			return err
543
-		}
544
-
545
-		if res.Xid == -1 {
546
-			res := &watcherEvent{}
547
-			_, err := decodePacket(buf[16:16+blen], res)
548
-			if err != nil {
549
-				return err
550
-			}
551
-			ev := Event{
552
-				Type:  res.Type,
553
-				State: res.State,
554
-				Path:  res.Path,
555
-				Err:   nil,
556
-			}
557
-			select {
558
-			case c.eventChan <- ev:
559
-			default:
560
-			}
561
-			wTypes := make([]watchType, 0, 2)
562
-			switch res.Type {
563
-			case EventNodeCreated:
564
-				wTypes = append(wTypes, watchTypeExist)
565
-			case EventNodeDeleted, EventNodeDataChanged:
566
-				wTypes = append(wTypes, watchTypeExist, watchTypeData, watchTypeChild)
567
-			case EventNodeChildrenChanged:
568
-				wTypes = append(wTypes, watchTypeChild)
569
-			}
570
-			c.watchersLock.Lock()
571
-			for _, t := range wTypes {
572
-				wpt := watchPathType{res.Path, t}
573
-				if watchers := c.watchers[wpt]; watchers != nil && len(watchers) > 0 {
574
-					for _, ch := range watchers {
575
-						ch <- ev
576
-						close(ch)
577
-					}
578
-					delete(c.watchers, wpt)
579
-				}
580
-			}
581
-			c.watchersLock.Unlock()
582
-		} else if res.Xid == -2 {
583
-			// Ping response. Ignore.
584
-		} else if res.Xid < 0 {
585
-			log.Printf("Xid < 0 (%d) but not ping or watcher event", res.Xid)
586
-		} else {
587
-			if res.Zxid > 0 {
588
-				c.lastZxid = res.Zxid
589
-			}
590
-
591
-			c.requestsLock.Lock()
592
-			req, ok := c.requests[res.Xid]
593
-			if ok {
594
-				delete(c.requests, res.Xid)
595
-			}
596
-			c.requestsLock.Unlock()
597
-
598
-			if !ok {
599
-				log.Printf("Response for unknown request with xid %d", res.Xid)
600
-			} else {
601
-				if res.Err != 0 {
602
-					err = res.Err.toError()
603
-				} else {
604
-					_, err = decodePacket(buf[16:16+blen], req.recvStruct)
605
-				}
606
-				if req.recvFunc != nil {
607
-					req.recvFunc(req, &res, err)
608
-				}
609
-				req.recvChan <- response{res.Zxid, err}
610
-				if req.opcode == opClose {
611
-					return io.EOF
612
-				}
613
-			}
614
-		}
615
-	}
616
-}
617
-
618
-func (c *Conn) nextXid() int32 {
619
-	return int32(atomic.AddUint32(&c.xid, 1) & 0x7fffffff)
620
-}
621
-
622
-func (c *Conn) addWatcher(path string, watchType watchType) <-chan Event {
623
-	c.watchersLock.Lock()
624
-	defer c.watchersLock.Unlock()
625
-
626
-	ch := make(chan Event, 1)
627
-	wpt := watchPathType{path, watchType}
628
-	c.watchers[wpt] = append(c.watchers[wpt], ch)
629
-	return ch
630
-}
631
-
632
-func (c *Conn) queueRequest(opcode int32, req interface{}, res interface{}, recvFunc func(*request, *responseHeader, error)) <-chan response {
633
-	rq := &request{
634
-		xid:        c.nextXid(),
635
-		opcode:     opcode,
636
-		pkt:        req,
637
-		recvStruct: res,
638
-		recvChan:   make(chan response, 1),
639
-		recvFunc:   recvFunc,
640
-	}
641
-	c.sendChan <- rq
642
-	return rq.recvChan
643
-}
644
-
645
-func (c *Conn) request(opcode int32, req interface{}, res interface{}, recvFunc func(*request, *responseHeader, error)) (int64, error) {
646
-	r := <-c.queueRequest(opcode, req, res, recvFunc)
647
-	return r.zxid, r.err
648
-}
649
-
650
-func (c *Conn) AddAuth(scheme string, auth []byte) error {
651
-	_, err := c.request(opSetAuth, &setAuthRequest{Type: 0, Scheme: scheme, Auth: auth}, &setAuthResponse{}, nil)
652
-	return err
653
-}
654
-
655
-func (c *Conn) Children(path string) ([]string, *Stat, error) {
656
-	res := &getChildren2Response{}
657
-	_, err := c.request(opGetChildren2, &getChildren2Request{Path: path, Watch: false}, res, nil)
658
-	return res.Children, &res.Stat, err
659
-}
660
-
661
-func (c *Conn) ChildrenW(path string) ([]string, *Stat, <-chan Event, error) {
662
-	var ech <-chan Event
663
-	res := &getChildren2Response{}
664
-	_, err := c.request(opGetChildren2, &getChildren2Request{Path: path, Watch: true}, res, func(req *request, res *responseHeader, err error) {
665
-		if err == nil {
666
-			ech = c.addWatcher(path, watchTypeChild)
667
-		}
668
-	})
669
-	if err != nil {
670
-		return nil, nil, nil, err
671
-	}
672
-	return res.Children, &res.Stat, ech, err
673
-}
674
-
675
-func (c *Conn) Get(path string) ([]byte, *Stat, error) {
676
-	res := &getDataResponse{}
677
-	_, err := c.request(opGetData, &getDataRequest{Path: path, Watch: false}, res, nil)
678
-	return res.Data, &res.Stat, err
679
-}
680
-
681
-// GetW returns the contents of a znode and sets a watch
682
-func (c *Conn) GetW(path string) ([]byte, *Stat, <-chan Event, error) {
683
-	var ech <-chan Event
684
-	res := &getDataResponse{}
685
-	_, err := c.request(opGetData, &getDataRequest{Path: path, Watch: true}, res, func(req *request, res *responseHeader, err error) {
686
-		if err == nil {
687
-			ech = c.addWatcher(path, watchTypeData)
688
-		}
689
-	})
690
-	if err != nil {
691
-		return nil, nil, nil, err
692
-	}
693
-	return res.Data, &res.Stat, ech, err
694
-}
695
-
696
-func (c *Conn) Set(path string, data []byte, version int32) (*Stat, error) {
697
-	res := &setDataResponse{}
698
-	_, err := c.request(opSetData, &SetDataRequest{path, data, version}, res, nil)
699
-	return &res.Stat, err
700
-}
701
-
702
-func (c *Conn) Create(path string, data []byte, flags int32, acl []ACL) (string, error) {
703
-	res := &createResponse{}
704
-	_, err := c.request(opCreate, &CreateRequest{path, data, acl, flags}, res, nil)
705
-	return res.Path, err
706
-}
707
-
708
-// CreateProtectedEphemeralSequential fixes a race condition if the server crashes
709
-// after it creates the node. On reconnect the session may still be valid so the
710
-// ephemeral node still exists. Therefore, on reconnect we need to check if a node
711
-// with a GUID generated on create exists.
712
-func (c *Conn) CreateProtectedEphemeralSequential(path string, data []byte, acl []ACL) (string, error) {
713
-	var guid [16]byte
714
-	_, err := io.ReadFull(rand.Reader, guid[:16])
715
-	if err != nil {
716
-		return "", err
717
-	}
718
-	guidStr := fmt.Sprintf("%x", guid)
719
-
720
-	parts := strings.Split(path, "/")
721
-	parts[len(parts)-1] = fmt.Sprintf("%s%s-%s", protectedPrefix, guidStr, parts[len(parts)-1])
722
-	rootPath := strings.Join(parts[:len(parts)-1], "/")
723
-	protectedPath := strings.Join(parts, "/")
724
-
725
-	var newPath string
726
-	for i := 0; i < 3; i++ {
727
-		newPath, err = c.Create(protectedPath, data, FlagEphemeral|FlagSequence, acl)
728
-		switch err {
729
-		case ErrSessionExpired:
730
-			// No need to search for the node since it can't exist. Just try again.
731
-		case ErrConnectionClosed:
732
-			children, _, err := c.Children(rootPath)
733
-			if err != nil {
734
-				return "", err
735
-			}
736
-			for _, p := range children {
737
-				parts := strings.Split(p, "/")
738
-				if pth := parts[len(parts)-1]; strings.HasPrefix(pth, protectedPrefix) {
739
-					if g := pth[len(protectedPrefix) : len(protectedPrefix)+32]; g == guidStr {
740
-						return rootPath + "/" + p, nil
741
-					}
742
-				}
743
-			}
744
-		case nil:
745
-			return newPath, nil
746
-		default:
747
-			return "", err
748
-		}
749
-	}
750
-	return "", err
751
-}
752
-
753
-func (c *Conn) Delete(path string, version int32) error {
754
-	_, err := c.request(opDelete, &DeleteRequest{path, version}, &deleteResponse{}, nil)
755
-	return err
756
-}
757
-
758
-func (c *Conn) Exists(path string) (bool, *Stat, error) {
759
-	res := &existsResponse{}
760
-	_, err := c.request(opExists, &existsRequest{Path: path, Watch: false}, res, nil)
761
-	exists := true
762
-	if err == ErrNoNode {
763
-		exists = false
764
-		err = nil
765
-	}
766
-	return exists, &res.Stat, err
767
-}
768
-
769
-func (c *Conn) ExistsW(path string) (bool, *Stat, <-chan Event, error) {
770
-	var ech <-chan Event
771
-	res := &existsResponse{}
772
-	_, err := c.request(opExists, &existsRequest{Path: path, Watch: true}, res, func(req *request, res *responseHeader, err error) {
773
-		if err == nil {
774
-			ech = c.addWatcher(path, watchTypeData)
775
-		} else if err == ErrNoNode {
776
-			ech = c.addWatcher(path, watchTypeExist)
777
-		}
778
-	})
779
-	exists := true
780
-	if err == ErrNoNode {
781
-		exists = false
782
-		err = nil
783
-	}
784
-	if err != nil {
785
-		return false, nil, nil, err
786
-	}
787
-	return exists, &res.Stat, ech, err
788
-}
789
-
790
-func (c *Conn) GetACL(path string) ([]ACL, *Stat, error) {
791
-	res := &getAclResponse{}
792
-	_, err := c.request(opGetAcl, &getAclRequest{Path: path}, res, nil)
793
-	return res.Acl, &res.Stat, err
794
-}
795
-
796
-func (c *Conn) SetACL(path string, acl []ACL, version int32) (*Stat, error) {
797
-	res := &setAclResponse{}
798
-	_, err := c.request(opSetAcl, &setAclRequest{Path: path, Acl: acl, Version: version}, res, nil)
799
-	return &res.Stat, err
800
-}
801
-
802
-func (c *Conn) Sync(path string) (string, error) {
803
-	res := &syncResponse{}
804
-	_, err := c.request(opSync, &syncRequest{Path: path}, res, nil)
805
-	return res.Path, err
806
-}
807
-
808
-type MultiResponse struct {
809
-	Stat   *Stat
810
-	String string
811
-}
812
-
813
-// Multi executes multiple ZooKeeper operations or none of them. The provided
814
-// ops must be one of *CreateRequest, *DeleteRequest, *SetDataRequest, or
815
-// *CheckVersionRequest.
816
-func (c *Conn) Multi(ops ...interface{}) ([]MultiResponse, error) {
817
-	req := &multiRequest{
818
-		Ops:        make([]multiRequestOp, 0, len(ops)),
819
-		DoneHeader: multiHeader{Type: -1, Done: true, Err: -1},
820
-	}
821
-	for _, op := range ops {
822
-		var opCode int32
823
-		switch op.(type) {
824
-		case *CreateRequest:
825
-			opCode = opCreate
826
-		case *SetDataRequest:
827
-			opCode = opSetData
828
-		case *DeleteRequest:
829
-			opCode = opDelete
830
-		case *CheckVersionRequest:
831
-			opCode = opCheck
832
-		default:
833
-			return nil, fmt.Errorf("uknown operation type %T", op)
834
-		}
835
-		req.Ops = append(req.Ops, multiRequestOp{multiHeader{opCode, false, -1}, op})
836
-	}
837
-	res := &multiResponse{}
838
-	_, err := c.request(opMulti, req, res, nil)
839
-	mr := make([]MultiResponse, len(res.Ops))
840
-	for i, op := range res.Ops {
841
-		mr[i] = MultiResponse{Stat: op.Stat, String: op.String}
842
-	}
843
-	return mr, err
844
-}
845 1
deleted file mode 100644
... ...
@@ -1,242 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"errors"
5
-)
6
-
7
-const (
8
-	protocolVersion = 0
9
-
10
-	DefaultPort = 2181
11
-)
12
-
13
-const (
14
-	opNotify       = 0
15
-	opCreate       = 1
16
-	opDelete       = 2
17
-	opExists       = 3
18
-	opGetData      = 4
19
-	opSetData      = 5
20
-	opGetAcl       = 6
21
-	opSetAcl       = 7
22
-	opGetChildren  = 8
23
-	opSync         = 9
24
-	opPing         = 11
25
-	opGetChildren2 = 12
26
-	opCheck        = 13
27
-	opMulti        = 14
28
-	opClose        = -11
29
-	opSetAuth      = 100
30
-	opSetWatches   = 101
31
-	// Not in protocol, used internally
32
-	opWatcherEvent = -2
33
-)
34
-
35
-const (
36
-	EventNodeCreated         = EventType(1)
37
-	EventNodeDeleted         = EventType(2)
38
-	EventNodeDataChanged     = EventType(3)
39
-	EventNodeChildrenChanged = EventType(4)
40
-
41
-	EventSession     = EventType(-1)
42
-	EventNotWatching = EventType(-2)
43
-)
44
-
45
-var (
46
-	eventNames = map[EventType]string{
47
-		EventNodeCreated:         "EventNodeCreated",
48
-		EventNodeDeleted:         "EventNodeDeleted",
49
-		EventNodeDataChanged:     "EventNodeDataChanged",
50
-		EventNodeChildrenChanged: "EventNodeChildrenChanged",
51
-		EventSession:             "EventSession",
52
-		EventNotWatching:         "EventNotWatching",
53
-	}
54
-)
55
-
56
-const (
57
-	StateUnknown           = State(-1)
58
-	StateDisconnected      = State(0)
59
-	StateConnecting        = State(1)
60
-	StateSyncConnected     = State(3)
61
-	StateAuthFailed        = State(4)
62
-	StateConnectedReadOnly = State(5)
63
-	StateSaslAuthenticated = State(6)
64
-	StateExpired           = State(-112)
65
-	// StateAuthFailed        = State(-113)
66
-
67
-	StateConnected  = State(100)
68
-	StateHasSession = State(101)
69
-)
70
-
71
-const (
72
-	FlagEphemeral = 1
73
-	FlagSequence  = 2
74
-)
75
-
76
-var (
77
-	stateNames = map[State]string{
78
-		StateUnknown:           "StateUnknown",
79
-		StateDisconnected:      "StateDisconnected",
80
-		StateSyncConnected:     "StateSyncConnected",
81
-		StateConnectedReadOnly: "StateConnectedReadOnly",
82
-		StateSaslAuthenticated: "StateSaslAuthenticated",
83
-		StateExpired:           "StateExpired",
84
-		StateAuthFailed:        "StateAuthFailed",
85
-		StateConnecting:        "StateConnecting",
86
-		StateConnected:         "StateConnected",
87
-		StateHasSession:        "StateHasSession",
88
-	}
89
-)
90
-
91
-type State int32
92
-
93
-func (s State) String() string {
94
-	if name := stateNames[s]; name != "" {
95
-		return name
96
-	}
97
-	return "Unknown"
98
-}
99
-
100
-type ErrCode int32
101
-
102
-var (
103
-	ErrConnectionClosed        = errors.New("zk: connection closed")
104
-	ErrUnknown                 = errors.New("zk: unknown error")
105
-	ErrAPIError                = errors.New("zk: api error")
106
-	ErrNoNode                  = errors.New("zk: node does not exist")
107
-	ErrNoAuth                  = errors.New("zk: not authenticated")
108
-	ErrBadVersion              = errors.New("zk: version conflict")
109
-	ErrNoChildrenForEphemerals = errors.New("zk: ephemeral nodes may not have children")
110
-	ErrNodeExists              = errors.New("zk: node already exists")
111
-	ErrNotEmpty                = errors.New("zk: node has children")
112
-	ErrSessionExpired          = errors.New("zk: session has been expired by the server")
113
-	ErrInvalidACL              = errors.New("zk: invalid ACL specified")
114
-	ErrAuthFailed              = errors.New("zk: client authentication failed")
115
-	ErrClosing                 = errors.New("zk: zookeeper is closing")
116
-	ErrNothing                 = errors.New("zk: no server responsees to process")
117
-	ErrSessionMoved            = errors.New("zk: session moved to another server, so operation is ignored")
118
-
119
-	// ErrInvalidCallback         = errors.New("zk: invalid callback specified")
120
-	errCodeToError = map[ErrCode]error{
121
-		0:                          nil,
122
-		errAPIError:                ErrAPIError,
123
-		errNoNode:                  ErrNoNode,
124
-		errNoAuth:                  ErrNoAuth,
125
-		errBadVersion:              ErrBadVersion,
126
-		errNoChildrenForEphemerals: ErrNoChildrenForEphemerals,
127
-		errNodeExists:              ErrNodeExists,
128
-		errNotEmpty:                ErrNotEmpty,
129
-		errSessionExpired:          ErrSessionExpired,
130
-		// errInvalidCallback:         ErrInvalidCallback,
131
-		errInvalidAcl:   ErrInvalidACL,
132
-		errAuthFailed:   ErrAuthFailed,
133
-		errClosing:      ErrClosing,
134
-		errNothing:      ErrNothing,
135
-		errSessionMoved: ErrSessionMoved,
136
-	}
137
-)
138
-
139
-func (e ErrCode) toError() error {
140
-	if err, ok := errCodeToError[e]; ok {
141
-		return err
142
-	}
143
-	return ErrUnknown
144
-}
145
-
146
-const (
147
-	errOk = 0
148
-	// System and server-side errors
149
-	errSystemError          = -1
150
-	errRuntimeInconsistency = -2
151
-	errDataInconsistency    = -3
152
-	errConnectionLoss       = -4
153
-	errMarshallingError     = -5
154
-	errUnimplemented        = -6
155
-	errOperationTimeout     = -7
156
-	errBadArguments         = -8
157
-	errInvalidState         = -9
158
-	// API errors
159
-	errAPIError                = ErrCode(-100)
160
-	errNoNode                  = ErrCode(-101) // *
161
-	errNoAuth                  = ErrCode(-102)
162
-	errBadVersion              = ErrCode(-103) // *
163
-	errNoChildrenForEphemerals = ErrCode(-108)
164
-	errNodeExists              = ErrCode(-110) // *
165
-	errNotEmpty                = ErrCode(-111)
166
-	errSessionExpired          = ErrCode(-112)
167
-	errInvalidCallback         = ErrCode(-113)
168
-	errInvalidAcl              = ErrCode(-114)
169
-	errAuthFailed              = ErrCode(-115)
170
-	errClosing                 = ErrCode(-116)
171
-	errNothing                 = ErrCode(-117)
172
-	errSessionMoved            = ErrCode(-118)
173
-)
174
-
175
-// Constants for ACL permissions
176
-const (
177
-	PermRead = 1 << iota
178
-	PermWrite
179
-	PermCreate
180
-	PermDelete
181
-	PermAdmin
182
-	PermAll = 0x1f
183
-)
184
-
185
-var (
186
-	emptyPassword = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
187
-	opNames       = map[int32]string{
188
-		opNotify:       "notify",
189
-		opCreate:       "create",
190
-		opDelete:       "delete",
191
-		opExists:       "exists",
192
-		opGetData:      "getData",
193
-		opSetData:      "setData",
194
-		opGetAcl:       "getACL",
195
-		opSetAcl:       "setACL",
196
-		opGetChildren:  "getChildren",
197
-		opSync:         "sync",
198
-		opPing:         "ping",
199
-		opGetChildren2: "getChildren2",
200
-		opCheck:        "check",
201
-		opMulti:        "multi",
202
-		opClose:        "close",
203
-		opSetAuth:      "setAuth",
204
-		opSetWatches:   "setWatches",
205
-
206
-		opWatcherEvent: "watcherEvent",
207
-	}
208
-)
209
-
210
-type EventType int32
211
-
212
-func (t EventType) String() string {
213
-	if name := eventNames[t]; name != "" {
214
-		return name
215
-	}
216
-	return "Unknown"
217
-}
218
-
219
-// Mode is used to build custom server modes (leader|follower|standalone).
220
-type Mode uint8
221
-
222
-func (m Mode) String() string {
223
-	if name := modeNames[m]; name != "" {
224
-		return name
225
-	}
226
-	return "unknown"
227
-}
228
-
229
-const (
230
-	ModeUnknown    Mode = iota
231
-	ModeLeader     Mode = iota
232
-	ModeFollower   Mode = iota
233
-	ModeStandalone Mode = iota
234
-)
235
-
236
-var (
237
-	modeNames = map[Mode]string{
238
-		ModeLeader:     "leader",
239
-		ModeFollower:   "follower",
240
-		ModeStandalone: "standalone",
241
-	}
242
-)
243 1
deleted file mode 100644
... ...
@@ -1,288 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"bufio"
5
-	"bytes"
6
-	"fmt"
7
-	"io/ioutil"
8
-	"math/big"
9
-	"net"
10
-	"regexp"
11
-	"strconv"
12
-	"time"
13
-)
14
-
15
-// FLWSrvr is a FourLetterWord helper function. In particular, this function pulls the srvr output
16
-// from the zookeeper instances and parses the output. A slice of *ServerStats structs are returned
17
-// as well as a boolean value to indicate whether this function processed successfully.
18
-//
19
-// If the boolean value is false there was a problem. If the *ServerStats slice is empty or nil,
20
-// then the error happened before we started to obtain 'srvr' values. Otherwise, one of the
21
-// servers had an issue and the "Error" value in the struct should be inspected to determine
22
-// which server had the issue.
23
-func FLWSrvr(servers []string, timeout time.Duration) ([]*ServerStats, bool) {
24
-	// different parts of the regular expression that are required to parse the srvr output
25
-	var (
26
-		zrVer   = `^Zookeeper version: ([A-Za-z0-9\.\-]+), built on (\d\d/\d\d/\d\d\d\d \d\d:\d\d [A-Za-z0-9:\+\-]+)`
27
-		zrLat   = `^Latency min/avg/max: (\d+)/(\d+)/(\d+)`
28
-		zrNet   = `^Received: (\d+).*\n^Sent: (\d+).*\n^Connections: (\d+).*\n^Outstanding: (\d+)`
29
-		zrState = `^Zxid: (0x[A-Za-z0-9]+).*\n^Mode: (\w+).*\n^Node count: (\d+)`
30
-	)
31
-
32
-	// build the regex from the pieces above
33
-	re, err := regexp.Compile(fmt.Sprintf(`(?m:\A%v.*\n%v.*\n%v.*\n%v)`, zrVer, zrLat, zrNet, zrState))
34
-
35
-	if err != nil {
36
-		return nil, false
37
-	}
38
-
39
-	imOk := true
40
-	servers = FormatServers(servers)
41
-	ss := make([]*ServerStats, len(servers))
42
-
43
-	for i := range ss {
44
-		response, err := fourLetterWord(servers[i], "srvr", timeout)
45
-
46
-		if err != nil {
47
-			ss[i] = &ServerStats{Error: err}
48
-			imOk = false
49
-			continue
50
-		}
51
-
52
-		match := re.FindAllStringSubmatch(string(response), -1)[0][1:]
53
-
54
-		if match == nil {
55
-			err := fmt.Errorf("unable to parse fields from zookeeper response (no regex matches)")
56
-			ss[i] = &ServerStats{Error: err}
57
-			imOk = false
58
-			continue
59
-		}
60
-
61
-		// determine current server
62
-		var srvrMode Mode
63
-		switch match[10] {
64
-		case "leader":
65
-			srvrMode = ModeLeader
66
-		case "follower":
67
-			srvrMode = ModeFollower
68
-		case "standalone":
69
-			srvrMode = ModeStandalone
70
-		default:
71
-			srvrMode = ModeUnknown
72
-		}
73
-
74
-		buildTime, err := time.Parse("01/02/2006 15:04 MST", match[1])
75
-
76
-		if err != nil {
77
-			ss[i] = &ServerStats{Error: err}
78
-			imOk = false
79
-			continue
80
-		}
81
-
82
-		parsedInt, err := strconv.ParseInt(match[9], 0, 64)
83
-
84
-		if err != nil {
85
-			ss[i] = &ServerStats{Error: err}
86
-			imOk = false
87
-			continue
88
-		}
89
-
90
-		// the ZxID value is an int64 with two int32s packed inside
91
-		// the high int32 is the epoch (i.e., number of leader elections)
92
-		// the low int32 is the counter
93
-		epoch := int32(parsedInt >> 32)
94
-		counter := int32(parsedInt & 0xFFFFFFFF)
95
-
96
-		// within the regex above, these values must be numerical
97
-		// so we can avoid useless checking of the error return value
98
-		minLatency, _ := strconv.ParseInt(match[2], 0, 64)
99
-		avgLatency, _ := strconv.ParseInt(match[3], 0, 64)
100
-		maxLatency, _ := strconv.ParseInt(match[4], 0, 64)
101
-		recv, _ := strconv.ParseInt(match[5], 0, 64)
102
-		sent, _ := strconv.ParseInt(match[6], 0, 64)
103
-		cons, _ := strconv.ParseInt(match[7], 0, 64)
104
-		outs, _ := strconv.ParseInt(match[8], 0, 64)
105
-		ncnt, _ := strconv.ParseInt(match[11], 0, 64)
106
-
107
-		ss[i] = &ServerStats{
108
-			Sent:        sent,
109
-			Received:    recv,
110
-			NodeCount:   ncnt,
111
-			MinLatency:  minLatency,
112
-			AvgLatency:  avgLatency,
113
-			MaxLatency:  maxLatency,
114
-			Connections: cons,
115
-			Outstanding: outs,
116
-			Epoch:       epoch,
117
-			Counter:     counter,
118
-			BuildTime:   buildTime,
119
-			Mode:        srvrMode,
120
-			Version:     match[0],
121
-		}
122
-	}
123
-
124
-	return ss, imOk
125
-}
126
-
127
-// FLWRuok is a FourLetterWord helper function. In particular, this function
128
-// pulls the ruok output from each server.
129
-func FLWRuok(servers []string, timeout time.Duration) []bool {
130
-	servers = FormatServers(servers)
131
-	oks := make([]bool, len(servers))
132
-
133
-	for i := range oks {
134
-		response, err := fourLetterWord(servers[i], "ruok", timeout)
135
-
136
-		if err != nil {
137
-			continue
138
-		}
139
-
140
-		if bytes.Equal(response[:4], []byte("imok")) {
141
-			oks[i] = true
142
-		}
143
-	}
144
-	return oks
145
-}
146
-
147
-// FLWCons is a FourLetterWord helper function. In particular, this function
148
-// pulls the ruok output from each server.
149
-//
150
-// As with FLWSrvr, the boolean value indicates whether one of the requests had
151
-// an issue. The Clients struct has an Error value that can be checked.
152
-func FLWCons(servers []string, timeout time.Duration) ([]*ServerClients, bool) {
153
-	var (
154
-		zrAddr = `^ /((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):(?:\d+))\[\d+\]`
155
-		zrPac  = `\(queued=(\d+),recved=(\d+),sent=(\d+),sid=(0x[A-Za-z0-9]+),lop=(\w+),est=(\d+),to=(\d+),`
156
-		zrSesh = `lcxid=(0x[A-Za-z0-9]+),lzxid=(0x[A-Za-z0-9]+),lresp=(\d+),llat=(\d+),minlat=(\d+),avglat=(\d+),maxlat=(\d+)\)`
157
-	)
158
-
159
-	re, err := regexp.Compile(fmt.Sprintf("%v%v%v", zrAddr, zrPac, zrSesh))
160
-
161
-	if err != nil {
162
-		return nil, false
163
-	}
164
-
165
-	servers = FormatServers(servers)
166
-	sc := make([]*ServerClients, len(servers))
167
-	imOk := true
168
-
169
-	for i := range sc {
170
-		response, err := fourLetterWord(servers[i], "cons", timeout)
171
-
172
-		if err != nil {
173
-			sc[i] = &ServerClients{Error: err}
174
-			imOk = false
175
-			continue
176
-		}
177
-
178
-		scan := bufio.NewScanner(bytes.NewReader(response))
179
-
180
-		var clients []*ServerClient
181
-
182
-		for scan.Scan() {
183
-			line := scan.Bytes()
184
-
185
-			if len(line) == 0 {
186
-				continue
187
-			}
188
-
189
-			m := re.FindAllStringSubmatch(string(line), -1)
190
-
191
-			if m == nil {
192
-				err := fmt.Errorf("unable to parse fields from zookeeper response (no regex matches)")
193
-				sc[i] = &ServerClients{Error: err}
194
-				imOk = false
195
-				continue
196
-			}
197
-
198
-			match := m[0][1:]
199
-
200
-			queued, _ := strconv.ParseInt(match[1], 0, 64)
201
-			recvd, _ := strconv.ParseInt(match[2], 0, 64)
202
-			sent, _ := strconv.ParseInt(match[3], 0, 64)
203
-			sid, _ := strconv.ParseInt(match[4], 0, 64)
204
-			est, _ := strconv.ParseInt(match[6], 0, 64)
205
-			timeout, _ := strconv.ParseInt(match[7], 0, 32)
206
-			lresp, _ := strconv.ParseInt(match[10], 0, 64)
207
-			llat, _ := strconv.ParseInt(match[11], 0, 32)
208
-			minlat, _ := strconv.ParseInt(match[12], 0, 32)
209
-			avglat, _ := strconv.ParseInt(match[13], 0, 32)
210
-			maxlat, _ := strconv.ParseInt(match[14], 0, 32)
211
-
212
-			// zookeeper returns a value, '0xffffffffffffffff', as the
213
-			// Lzxid for PING requests in the 'cons' output.
214
-			// unfortunately, in Go that is an invalid int64 and is not represented
215
-			// as -1.
216
-			// However, converting the string value to a big.Int and then back to
217
-			// and int64 properly sets the value to -1
218
-			lzxid, ok := new(big.Int).SetString(match[9], 0)
219
-
220
-			var errVal error
221
-
222
-			if !ok {
223
-				errVal = fmt.Errorf("failed to convert lzxid value to big.Int")
224
-				imOk = false
225
-			}
226
-
227
-			lcxid, ok := new(big.Int).SetString(match[8], 0)
228
-
229
-			if !ok && errVal == nil {
230
-				errVal = fmt.Errorf("failed to convert lcxid value to big.Int")
231
-				imOk = false
232
-			}
233
-
234
-			clients = append(clients, &ServerClient{
235
-				Queued:        queued,
236
-				Received:      recvd,
237
-				Sent:          sent,
238
-				SessionID:     sid,
239
-				Lcxid:         lcxid.Int64(),
240
-				Lzxid:         lzxid.Int64(),
241
-				Timeout:       int32(timeout),
242
-				LastLatency:   int32(llat),
243
-				MinLatency:    int32(minlat),
244
-				AvgLatency:    int32(avglat),
245
-				MaxLatency:    int32(maxlat),
246
-				Established:   time.Unix(est, 0),
247
-				LastResponse:  time.Unix(lresp, 0),
248
-				Addr:          match[0],
249
-				LastOperation: match[5],
250
-				Error:         errVal,
251
-			})
252
-		}
253
-
254
-		sc[i] = &ServerClients{Clients: clients}
255
-	}
256
-
257
-	return sc, imOk
258
-}
259
-
260
-func fourLetterWord(server, command string, timeout time.Duration) ([]byte, error) {
261
-	conn, err := net.DialTimeout("tcp", server, timeout)
262
-
263
-	if err != nil {
264
-		return nil, err
265
-	}
266
-
267
-	// the zookeeper server should automatically close this socket
268
-	// once the command has been processed, but better safe than sorry
269
-	defer conn.Close()
270
-
271
-	conn.SetWriteDeadline(time.Now().Add(timeout))
272
-
273
-	_, err = conn.Write([]byte(command))
274
-
275
-	if err != nil {
276
-		return nil, err
277
-	}
278
-
279
-	conn.SetReadDeadline(time.Now().Add(timeout))
280
-
281
-	resp, err := ioutil.ReadAll(conn)
282
-
283
-	if err != nil {
284
-		return nil, err
285
-	}
286
-
287
-	return resp, nil
288
-}
289 1
deleted file mode 100644
... ...
@@ -1,131 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"errors"
5
-	"fmt"
6
-	"strconv"
7
-	"strings"
8
-)
9
-
10
-var (
11
-	ErrDeadlock  = errors.New("zk: trying to acquire a lock twice")
12
-	ErrNotLocked = errors.New("zk: not locked")
13
-)
14
-
15
-type Lock struct {
16
-	c        *Conn
17
-	path     string
18
-	acl      []ACL
19
-	lockPath string
20
-	seq      int
21
-}
22
-
23
-func NewLock(c *Conn, path string, acl []ACL) *Lock {
24
-	return &Lock{
25
-		c:    c,
26
-		path: path,
27
-		acl:  acl,
28
-	}
29
-}
30
-
31
-func parseSeq(path string) (int, error) {
32
-	parts := strings.Split(path, "-")
33
-	return strconv.Atoi(parts[len(parts)-1])
34
-}
35
-
36
-func (l *Lock) Lock() error {
37
-	if l.lockPath != "" {
38
-		return ErrDeadlock
39
-	}
40
-
41
-	prefix := fmt.Sprintf("%s/lock-", l.path)
42
-
43
-	path := ""
44
-	var err error
45
-	for i := 0; i < 3; i++ {
46
-		path, err = l.c.CreateProtectedEphemeralSequential(prefix, []byte{}, l.acl)
47
-		if err == ErrNoNode {
48
-			// Create parent node.
49
-			parts := strings.Split(l.path, "/")
50
-			pth := ""
51
-			for _, p := range parts[1:] {
52
-				pth += "/" + p
53
-				_, err := l.c.Create(pth, []byte{}, 0, l.acl)
54
-				if err != nil && err != ErrNodeExists {
55
-					return err
56
-				}
57
-			}
58
-		} else if err == nil {
59
-			break
60
-		} else {
61
-			return err
62
-		}
63
-	}
64
-	if err != nil {
65
-		return err
66
-	}
67
-
68
-	seq, err := parseSeq(path)
69
-	if err != nil {
70
-		return err
71
-	}
72
-
73
-	for {
74
-		children, _, err := l.c.Children(l.path)
75
-		if err != nil {
76
-			return err
77
-		}
78
-
79
-		lowestSeq := seq
80
-		prevSeq := 0
81
-		prevSeqPath := ""
82
-		for _, p := range children {
83
-			s, err := parseSeq(p)
84
-			if err != nil {
85
-				return err
86
-			}
87
-			if s < lowestSeq {
88
-				lowestSeq = s
89
-			}
90
-			if s < seq && s > prevSeq {
91
-				prevSeq = s
92
-				prevSeqPath = p
93
-			}
94
-		}
95
-
96
-		if seq == lowestSeq {
97
-			// Acquired the lock
98
-			break
99
-		}
100
-
101
-		// Wait on the node next in line for the lock
102
-		_, _, ch, err := l.c.GetW(l.path + "/" + prevSeqPath)
103
-		if err != nil && err != ErrNoNode {
104
-			return err
105
-		} else if err != nil && err == ErrNoNode {
106
-			// try again
107
-			continue
108
-		}
109
-
110
-		ev := <-ch
111
-		if ev.Err != nil {
112
-			return ev.Err
113
-		}
114
-	}
115
-
116
-	l.seq = seq
117
-	l.lockPath = path
118
-	return nil
119
-}
120
-
121
-func (l *Lock) Unlock() error {
122
-	if l.lockPath == "" {
123
-		return ErrNotLocked
124
-	}
125
-	if err := l.c.Delete(l.lockPath, -1); err != nil {
126
-		return err
127
-	}
128
-	l.lockPath = ""
129
-	l.seq = 0
130
-	return nil
131
-}
132 1
deleted file mode 100644
... ...
@@ -1,119 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"fmt"
5
-	"io"
6
-	"io/ioutil"
7
-	"math/rand"
8
-	"os"
9
-	"path/filepath"
10
-	"time"
11
-)
12
-
13
-type TestServer struct {
14
-	Port int
15
-	Path string
16
-	Srv  *Server
17
-}
18
-
19
-type TestCluster struct {
20
-	Path    string
21
-	Servers []TestServer
22
-}
23
-
24
-func StartTestCluster(size int, stdout, stderr io.Writer) (*TestCluster, error) {
25
-	tmpPath, err := ioutil.TempDir("", "gozk")
26
-	if err != nil {
27
-		return nil, err
28
-	}
29
-	success := false
30
-	startPort := int(rand.Int31n(6000) + 10000)
31
-	cluster := &TestCluster{Path: tmpPath}
32
-	defer func() {
33
-		if !success {
34
-			cluster.Stop()
35
-		}
36
-	}()
37
-	for serverN := 0; serverN < size; serverN++ {
38
-		srvPath := filepath.Join(tmpPath, fmt.Sprintf("srv%d", serverN))
39
-		if err := os.Mkdir(srvPath, 0700); err != nil {
40
-			return nil, err
41
-		}
42
-		port := startPort + serverN*3
43
-		cfg := ServerConfig{
44
-			ClientPort: port,
45
-			DataDir:    srvPath,
46
-		}
47
-		for i := 0; i < size; i++ {
48
-			cfg.Servers = append(cfg.Servers, ServerConfigServer{
49
-				ID:                 i + 1,
50
-				Host:               "127.0.0.1",
51
-				PeerPort:           startPort + i*3 + 1,
52
-				LeaderElectionPort: startPort + i*3 + 2,
53
-			})
54
-		}
55
-		cfgPath := filepath.Join(srvPath, "zoo.cfg")
56
-		fi, err := os.Create(cfgPath)
57
-		if err != nil {
58
-			return nil, err
59
-		}
60
-		err = cfg.Marshall(fi)
61
-		fi.Close()
62
-		if err != nil {
63
-			return nil, err
64
-		}
65
-
66
-		fi, err = os.Create(filepath.Join(srvPath, "myid"))
67
-		if err != nil {
68
-			return nil, err
69
-		}
70
-		_, err = fmt.Fprintf(fi, "%d\n", serverN+1)
71
-		fi.Close()
72
-		if err != nil {
73
-			return nil, err
74
-		}
75
-
76
-		srv := &Server{
77
-			ConfigPath: cfgPath,
78
-			Stdout:     stdout,
79
-			Stderr:     stderr,
80
-		}
81
-		if err := srv.Start(); err != nil {
82
-			return nil, err
83
-		}
84
-		cluster.Servers = append(cluster.Servers, TestServer{
85
-			Path: srvPath,
86
-			Port: cfg.ClientPort,
87
-			Srv:  srv,
88
-		})
89
-	}
90
-	success = true
91
-	time.Sleep(time.Second) // Give the server time to become active. Should probably actually attempt to connect to verify.
92
-	return cluster, nil
93
-}
94
-
95
-func (ts *TestCluster) Connect(idx int) (*Conn, error) {
96
-	zk, _, err := Connect([]string{fmt.Sprintf("127.0.0.1:%d", ts.Servers[idx].Port)}, time.Second*15)
97
-	return zk, err
98
-}
99
-
100
-func (ts *TestCluster) ConnectAll() (*Conn, <-chan Event, error) {
101
-	return ts.ConnectAllTimeout(time.Second * 15)
102
-}
103
-
104
-func (ts *TestCluster) ConnectAllTimeout(sessionTimeout time.Duration) (*Conn, <-chan Event, error) {
105
-	hosts := make([]string, len(ts.Servers))
106
-	for i, srv := range ts.Servers {
107
-		hosts[i] = fmt.Sprintf("127.0.0.1:%d", srv.Port)
108
-	}
109
-	zk, ch, err := Connect(hosts, sessionTimeout)
110
-	return zk, ch, err
111
-}
112
-
113
-func (ts *TestCluster) Stop() error {
114
-	for _, srv := range ts.Servers {
115
-		srv.Srv.Stop()
116
-	}
117
-	defer os.RemoveAll(ts.Path)
118
-	return nil
119
-}
120 1
deleted file mode 100644
... ...
@@ -1,136 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"fmt"
5
-	"io"
6
-	"os"
7
-	"os/exec"
8
-	"path/filepath"
9
-)
10
-
11
-type ErrMissingServerConfigField string
12
-
13
-func (e ErrMissingServerConfigField) Error() string {
14
-	return fmt.Sprintf("zk: missing server config field '%s'", string(e))
15
-}
16
-
17
-const (
18
-	DefaultServerTickTime                 = 2000
19
-	DefaultServerInitLimit                = 10
20
-	DefaultServerSyncLimit                = 5
21
-	DefaultServerAutoPurgeSnapRetainCount = 3
22
-	DefaultPeerPort                       = 2888
23
-	DefaultLeaderElectionPort             = 3888
24
-)
25
-
26
-type ServerConfigServer struct {
27
-	ID                 int
28
-	Host               string
29
-	PeerPort           int
30
-	LeaderElectionPort int
31
-}
32
-
33
-type ServerConfig struct {
34
-	TickTime                 int    // Number of milliseconds of each tick
35
-	InitLimit                int    // Number of ticks that the initial synchronization phase can take
36
-	SyncLimit                int    // Number of ticks that can pass between sending a request and getting an acknowledgement
37
-	DataDir                  string // Direcrory where the snapshot is stored
38
-	ClientPort               int    // Port at which clients will connect
39
-	AutoPurgeSnapRetainCount int    // Number of snapshots to retain in dataDir
40
-	AutoPurgePurgeInterval   int    // Purge task internal in hours (0 to disable auto purge)
41
-	Servers                  []ServerConfigServer
42
-}
43
-
44
-func (sc ServerConfig) Marshall(w io.Writer) error {
45
-	if sc.DataDir == "" {
46
-		return ErrMissingServerConfigField("dataDir")
47
-	}
48
-	fmt.Fprintf(w, "dataDir=%s\n", sc.DataDir)
49
-	if sc.TickTime <= 0 {
50
-		sc.TickTime = DefaultServerTickTime
51
-	}
52
-	fmt.Fprintf(w, "tickTime=%d\n", sc.TickTime)
53
-	if sc.InitLimit <= 0 {
54
-		sc.InitLimit = DefaultServerInitLimit
55
-	}
56
-	fmt.Fprintf(w, "initLimit=%d\n", sc.InitLimit)
57
-	if sc.SyncLimit <= 0 {
58
-		sc.SyncLimit = DefaultServerSyncLimit
59
-	}
60
-	fmt.Fprintf(w, "syncLimit=%d\n", sc.SyncLimit)
61
-	if sc.ClientPort <= 0 {
62
-		sc.ClientPort = DefaultPort
63
-	}
64
-	fmt.Fprintf(w, "clientPort=%d\n", sc.ClientPort)
65
-	if sc.AutoPurgePurgeInterval > 0 {
66
-		if sc.AutoPurgeSnapRetainCount <= 0 {
67
-			sc.AutoPurgeSnapRetainCount = DefaultServerAutoPurgeSnapRetainCount
68
-		}
69
-		fmt.Fprintf(w, "autopurge.snapRetainCount=%d\n", sc.AutoPurgeSnapRetainCount)
70
-		fmt.Fprintf(w, "autopurge.purgeInterval=%d\n", sc.AutoPurgePurgeInterval)
71
-	}
72
-	if len(sc.Servers) > 0 {
73
-		for _, srv := range sc.Servers {
74
-			if srv.PeerPort <= 0 {
75
-				srv.PeerPort = DefaultPeerPort
76
-			}
77
-			if srv.LeaderElectionPort <= 0 {
78
-				srv.LeaderElectionPort = DefaultLeaderElectionPort
79
-			}
80
-			fmt.Fprintf(w, "server.%d=%s:%d:%d\n", srv.ID, srv.Host, srv.PeerPort, srv.LeaderElectionPort)
81
-		}
82
-	}
83
-	return nil
84
-}
85
-
86
-var jarSearchPaths = []string{
87
-	"zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
88
-	"../zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
89
-	"/usr/share/java/zookeeper-*.jar",
90
-	"/usr/local/zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
91
-	"/usr/local/Cellar/zookeeper/*/libexec/contrib/fatjar/zookeeper-*-fatjar.jar",
92
-}
93
-
94
-func findZookeeperFatJar() string {
95
-	var paths []string
96
-	zkPath := os.Getenv("ZOOKEEPER_PATH")
97
-	if zkPath == "" {
98
-		paths = jarSearchPaths
99
-	} else {
100
-		paths = []string{filepath.Join(zkPath, "contrib/fatjar/zookeeper-*-fatjar.jar")}
101
-	}
102
-	for _, path := range paths {
103
-		matches, _ := filepath.Glob(path)
104
-		// TODO: could sort by version and pick latest
105
-		if len(matches) > 0 {
106
-			return matches[0]
107
-		}
108
-	}
109
-	return ""
110
-}
111
-
112
-type Server struct {
113
-	JarPath        string
114
-	ConfigPath     string
115
-	Stdout, Stderr io.Writer
116
-
117
-	cmd *exec.Cmd
118
-}
119
-
120
-func (srv *Server) Start() error {
121
-	if srv.JarPath == "" {
122
-		srv.JarPath = findZookeeperFatJar()
123
-		if srv.JarPath == "" {
124
-			return fmt.Errorf("zk: unable to find server jar")
125
-		}
126
-	}
127
-	srv.cmd = exec.Command("java", "-jar", srv.JarPath, "server", srv.ConfigPath)
128
-	srv.cmd.Stdout = srv.Stdout
129
-	srv.cmd.Stderr = srv.Stderr
130
-	return srv.cmd.Start()
131
-}
132
-
133
-func (srv *Server) Stop() error {
134
-	srv.cmd.Process.Signal(os.Kill)
135
-	return srv.cmd.Wait()
136
-}
137 1
deleted file mode 100644
... ...
@@ -1,633 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"encoding/binary"
5
-	"errors"
6
-	"reflect"
7
-	"runtime"
8
-	"time"
9
-)
10
-
11
-var (
12
-	ErrUnhandledFieldType = errors.New("zk: unhandled field type")
13
-	ErrPtrExpected        = errors.New("zk: encode/decode expect a non-nil pointer to struct")
14
-	ErrShortBuffer        = errors.New("zk: buffer too small")
15
-)
16
-
17
-type ACL struct {
18
-	Perms  int32
19
-	Scheme string
20
-	ID     string
21
-}
22
-
23
-type Stat struct {
24
-	Czxid          int64 // The zxid of the change that caused this znode to be created.
25
-	Mzxid          int64 // The zxid of the change that last modified this znode.
26
-	Ctime          int64 // The time in milliseconds from epoch when this znode was created.
27
-	Mtime          int64 // The time in milliseconds from epoch when this znode was last modified.
28
-	Version        int32 // The number of changes to the data of this znode.
29
-	Cversion       int32 // The number of changes to the children of this znode.
30
-	Aversion       int32 // The number of changes to the ACL of this znode.
31
-	EphemeralOwner int64 // The session id of the owner of this znode if the znode is an ephemeral node. If it is not an ephemeral node, it will be zero.
32
-	DataLength     int32 // The length of the data field of this znode.
33
-	NumChildren    int32 // The number of children of this znode.
34
-	Pzxid          int64 // last modified children
35
-}
36
-
37
-// ServerClient is the information for a single Zookeeper client and its session.
38
-// This is used to parse/extract the output fo the `cons` command.
39
-type ServerClient struct {
40
-	Queued        int64
41
-	Received      int64
42
-	Sent          int64
43
-	SessionID     int64
44
-	Lcxid         int64
45
-	Lzxid         int64
46
-	Timeout       int32
47
-	LastLatency   int32
48
-	MinLatency    int32
49
-	AvgLatency    int32
50
-	MaxLatency    int32
51
-	Established   time.Time
52
-	LastResponse  time.Time
53
-	Addr          string
54
-	LastOperation string // maybe?
55
-	Error         error
56
-}
57
-
58
-// ServerClients is a struct for the FLWCons() function. It's used to provide
59
-// the list of Clients.
60
-//
61
-// This is needed because FLWCons() takes multiple servers.
62
-type ServerClients struct {
63
-	Clients []*ServerClient
64
-	Error   error
65
-}
66
-
67
-// ServerStats is the information pulled from the Zookeeper `stat` command.
68
-type ServerStats struct {
69
-	Sent        int64
70
-	Received    int64
71
-	NodeCount   int64
72
-	MinLatency  int64
73
-	AvgLatency  int64
74
-	MaxLatency  int64
75
-	Connections int64
76
-	Outstanding int64
77
-	Epoch       int32
78
-	Counter     int32
79
-	BuildTime   time.Time
80
-	Mode        Mode
81
-	Version     string
82
-	Error       error
83
-}
84
-
85
-type requestHeader struct {
86
-	Xid    int32
87
-	Opcode int32
88
-}
89
-
90
-type responseHeader struct {
91
-	Xid  int32
92
-	Zxid int64
93
-	Err  ErrCode
94
-}
95
-
96
-type multiHeader struct {
97
-	Type int32
98
-	Done bool
99
-	Err  ErrCode
100
-}
101
-
102
-type auth struct {
103
-	Type   int32
104
-	Scheme string
105
-	Auth   []byte
106
-}
107
-
108
-// Generic request structs
109
-
110
-type pathRequest struct {
111
-	Path string
112
-}
113
-
114
-type PathVersionRequest struct {
115
-	Path    string
116
-	Version int32
117
-}
118
-
119
-type pathWatchRequest struct {
120
-	Path  string
121
-	Watch bool
122
-}
123
-
124
-type pathResponse struct {
125
-	Path string
126
-}
127
-
128
-type statResponse struct {
129
-	Stat Stat
130
-}
131
-
132
-//
133
-
134
-type CheckVersionRequest PathVersionRequest
135
-type closeRequest struct{}
136
-type closeResponse struct{}
137
-
138
-type connectRequest struct {
139
-	ProtocolVersion int32
140
-	LastZxidSeen    int64
141
-	TimeOut         int32
142
-	SessionID       int64
143
-	Passwd          []byte
144
-}
145
-
146
-type connectResponse struct {
147
-	ProtocolVersion int32
148
-	TimeOut         int32
149
-	SessionID       int64
150
-	Passwd          []byte
151
-}
152
-
153
-type CreateRequest struct {
154
-	Path  string
155
-	Data  []byte
156
-	Acl   []ACL
157
-	Flags int32
158
-}
159
-
160
-type createResponse pathResponse
161
-type DeleteRequest PathVersionRequest
162
-type deleteResponse struct{}
163
-
164
-type errorResponse struct {
165
-	Err int32
166
-}
167
-
168
-type existsRequest pathWatchRequest
169
-type existsResponse statResponse
170
-type getAclRequest pathRequest
171
-
172
-type getAclResponse struct {
173
-	Acl  []ACL
174
-	Stat Stat
175
-}
176
-
177
-type getChildrenRequest pathRequest
178
-
179
-type getChildrenResponse struct {
180
-	Children []string
181
-}
182
-
183
-type getChildren2Request pathWatchRequest
184
-
185
-type getChildren2Response struct {
186
-	Children []string
187
-	Stat     Stat
188
-}
189
-
190
-type getDataRequest pathWatchRequest
191
-
192
-type getDataResponse struct {
193
-	Data []byte
194
-	Stat Stat
195
-}
196
-
197
-type getMaxChildrenRequest pathRequest
198
-
199
-type getMaxChildrenResponse struct {
200
-	Max int32
201
-}
202
-
203
-type getSaslRequest struct {
204
-	Token []byte
205
-}
206
-
207
-type pingRequest struct{}
208
-type pingResponse struct{}
209
-
210
-type setAclRequest struct {
211
-	Path    string
212
-	Acl     []ACL
213
-	Version int32
214
-}
215
-
216
-type setAclResponse statResponse
217
-
218
-type SetDataRequest struct {
219
-	Path    string
220
-	Data    []byte
221
-	Version int32
222
-}
223
-
224
-type setDataResponse statResponse
225
-
226
-type setMaxChildren struct {
227
-	Path string
228
-	Max  int32
229
-}
230
-
231
-type setSaslRequest struct {
232
-	Token string
233
-}
234
-
235
-type setSaslResponse struct {
236
-	Token string
237
-}
238
-
239
-type setWatchesRequest struct {
240
-	RelativeZxid int64
241
-	DataWatches  []string
242
-	ExistWatches []string
243
-	ChildWatches []string
244
-}
245
-
246
-type setWatchesResponse struct{}
247
-
248
-type syncRequest pathRequest
249
-type syncResponse pathResponse
250
-
251
-type setAuthRequest auth
252
-type setAuthResponse struct{}
253
-
254
-type multiRequestOp struct {
255
-	Header multiHeader
256
-	Op     interface{}
257
-}
258
-type multiRequest struct {
259
-	Ops        []multiRequestOp
260
-	DoneHeader multiHeader
261
-}
262
-type multiResponseOp struct {
263
-	Header multiHeader
264
-	String string
265
-	Stat   *Stat
266
-}
267
-type multiResponse struct {
268
-	Ops        []multiResponseOp
269
-	DoneHeader multiHeader
270
-}
271
-
272
-func (r *multiRequest) Encode(buf []byte) (int, error) {
273
-	total := 0
274
-	for _, op := range r.Ops {
275
-		op.Header.Done = false
276
-		n, err := encodePacketValue(buf[total:], reflect.ValueOf(op))
277
-		if err != nil {
278
-			return total, err
279
-		}
280
-		total += n
281
-	}
282
-	r.DoneHeader.Done = true
283
-	n, err := encodePacketValue(buf[total:], reflect.ValueOf(r.DoneHeader))
284
-	if err != nil {
285
-		return total, err
286
-	}
287
-	total += n
288
-
289
-	return total, nil
290
-}
291
-
292
-func (r *multiRequest) Decode(buf []byte) (int, error) {
293
-	r.Ops = make([]multiRequestOp, 0)
294
-	r.DoneHeader = multiHeader{-1, true, -1}
295
-	total := 0
296
-	for {
297
-		header := &multiHeader{}
298
-		n, err := decodePacketValue(buf[total:], reflect.ValueOf(header))
299
-		if err != nil {
300
-			return total, err
301
-		}
302
-		total += n
303
-		if header.Done {
304
-			r.DoneHeader = *header
305
-			break
306
-		}
307
-
308
-		req := requestStructForOp(header.Type)
309
-		if req == nil {
310
-			return total, ErrAPIError
311
-		}
312
-		n, err = decodePacketValue(buf[total:], reflect.ValueOf(req))
313
-		if err != nil {
314
-			return total, err
315
-		}
316
-		total += n
317
-		r.Ops = append(r.Ops, multiRequestOp{*header, req})
318
-	}
319
-	return total, nil
320
-}
321
-
322
-func (r *multiResponse) Decode(buf []byte) (int, error) {
323
-	r.Ops = make([]multiResponseOp, 0)
324
-	r.DoneHeader = multiHeader{-1, true, -1}
325
-	total := 0
326
-	for {
327
-		header := &multiHeader{}
328
-		n, err := decodePacketValue(buf[total:], reflect.ValueOf(header))
329
-		if err != nil {
330
-			return total, err
331
-		}
332
-		total += n
333
-		if header.Done {
334
-			r.DoneHeader = *header
335
-			break
336
-		}
337
-
338
-		res := multiResponseOp{Header: *header}
339
-		var w reflect.Value
340
-		switch header.Type {
341
-		default:
342
-			return total, ErrAPIError
343
-		case opCreate:
344
-			w = reflect.ValueOf(&res.String)
345
-		case opSetData:
346
-			res.Stat = new(Stat)
347
-			w = reflect.ValueOf(res.Stat)
348
-		case opCheck, opDelete:
349
-		}
350
-		if w.IsValid() {
351
-			n, err := decodePacketValue(buf[total:], w)
352
-			if err != nil {
353
-				return total, err
354
-			}
355
-			total += n
356
-		}
357
-		r.Ops = append(r.Ops, res)
358
-	}
359
-	return total, nil
360
-}
361
-
362
-type watcherEvent struct {
363
-	Type  EventType
364
-	State State
365
-	Path  string
366
-}
367
-
368
-type decoder interface {
369
-	Decode(buf []byte) (int, error)
370
-}
371
-
372
-type encoder interface {
373
-	Encode(buf []byte) (int, error)
374
-}
375
-
376
-func decodePacket(buf []byte, st interface{}) (n int, err error) {
377
-	defer func() {
378
-		if r := recover(); r != nil {
379
-			if e, ok := r.(runtime.Error); ok && e.Error() == "runtime error: slice bounds out of range" {
380
-				err = ErrShortBuffer
381
-			} else {
382
-				panic(r)
383
-			}
384
-		}
385
-	}()
386
-
387
-	v := reflect.ValueOf(st)
388
-	if v.Kind() != reflect.Ptr || v.IsNil() {
389
-		return 0, ErrPtrExpected
390
-	}
391
-	return decodePacketValue(buf, v)
392
-}
393
-
394
-func decodePacketValue(buf []byte, v reflect.Value) (int, error) {
395
-	rv := v
396
-	kind := v.Kind()
397
-	if kind == reflect.Ptr {
398
-		if v.IsNil() {
399
-			v.Set(reflect.New(v.Type().Elem()))
400
-		}
401
-		v = v.Elem()
402
-		kind = v.Kind()
403
-	}
404
-
405
-	n := 0
406
-	switch kind {
407
-	default:
408
-		return n, ErrUnhandledFieldType
409
-	case reflect.Struct:
410
-		if de, ok := rv.Interface().(decoder); ok {
411
-			return de.Decode(buf)
412
-		} else if de, ok := v.Interface().(decoder); ok {
413
-			return de.Decode(buf)
414
-		} else {
415
-			for i := 0; i < v.NumField(); i++ {
416
-				field := v.Field(i)
417
-				n2, err := decodePacketValue(buf[n:], field)
418
-				n += n2
419
-				if err != nil {
420
-					return n, err
421
-				}
422
-			}
423
-		}
424
-	case reflect.Bool:
425
-		v.SetBool(buf[n] != 0)
426
-		n++
427
-	case reflect.Int32:
428
-		v.SetInt(int64(binary.BigEndian.Uint32(buf[n : n+4])))
429
-		n += 4
430
-	case reflect.Int64:
431
-		v.SetInt(int64(binary.BigEndian.Uint64(buf[n : n+8])))
432
-		n += 8
433
-	case reflect.String:
434
-		ln := int(binary.BigEndian.Uint32(buf[n : n+4]))
435
-		v.SetString(string(buf[n+4 : n+4+ln]))
436
-		n += 4 + ln
437
-	case reflect.Slice:
438
-		switch v.Type().Elem().Kind() {
439
-		default:
440
-			count := int(binary.BigEndian.Uint32(buf[n : n+4]))
441
-			n += 4
442
-			values := reflect.MakeSlice(v.Type(), count, count)
443
-			v.Set(values)
444
-			for i := 0; i < count; i++ {
445
-				n2, err := decodePacketValue(buf[n:], values.Index(i))
446
-				n += n2
447
-				if err != nil {
448
-					return n, err
449
-				}
450
-			}
451
-		case reflect.Uint8:
452
-			ln := int(int32(binary.BigEndian.Uint32(buf[n : n+4])))
453
-			if ln < 0 {
454
-				n += 4
455
-				v.SetBytes(nil)
456
-			} else {
457
-				bytes := make([]byte, ln)
458
-				copy(bytes, buf[n+4:n+4+ln])
459
-				v.SetBytes(bytes)
460
-				n += 4 + ln
461
-			}
462
-		}
463
-	}
464
-	return n, nil
465
-}
466
-
467
-func encodePacket(buf []byte, st interface{}) (n int, err error) {
468
-	defer func() {
469
-		if r := recover(); r != nil {
470
-			if e, ok := r.(runtime.Error); ok && e.Error() == "runtime error: slice bounds out of range" {
471
-				err = ErrShortBuffer
472
-			} else {
473
-				panic(r)
474
-			}
475
-		}
476
-	}()
477
-
478
-	v := reflect.ValueOf(st)
479
-	if v.Kind() != reflect.Ptr || v.IsNil() {
480
-		return 0, ErrPtrExpected
481
-	}
482
-	return encodePacketValue(buf, v)
483
-}
484
-
485
-func encodePacketValue(buf []byte, v reflect.Value) (int, error) {
486
-	rv := v
487
-	for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
488
-		v = v.Elem()
489
-	}
490
-
491
-	n := 0
492
-	switch v.Kind() {
493
-	default:
494
-		return n, ErrUnhandledFieldType
495
-	case reflect.Struct:
496
-		if en, ok := rv.Interface().(encoder); ok {
497
-			return en.Encode(buf)
498
-		} else if en, ok := v.Interface().(encoder); ok {
499
-			return en.Encode(buf)
500
-		} else {
501
-			for i := 0; i < v.NumField(); i++ {
502
-				field := v.Field(i)
503
-				n2, err := encodePacketValue(buf[n:], field)
504
-				n += n2
505
-				if err != nil {
506
-					return n, err
507
-				}
508
-			}
509
-		}
510
-	case reflect.Bool:
511
-		if v.Bool() {
512
-			buf[n] = 1
513
-		} else {
514
-			buf[n] = 0
515
-		}
516
-		n++
517
-	case reflect.Int32:
518
-		binary.BigEndian.PutUint32(buf[n:n+4], uint32(v.Int()))
519
-		n += 4
520
-	case reflect.Int64:
521
-		binary.BigEndian.PutUint64(buf[n:n+8], uint64(v.Int()))
522
-		n += 8
523
-	case reflect.String:
524
-		str := v.String()
525
-		binary.BigEndian.PutUint32(buf[n:n+4], uint32(len(str)))
526
-		copy(buf[n+4:n+4+len(str)], []byte(str))
527
-		n += 4 + len(str)
528
-	case reflect.Slice:
529
-		switch v.Type().Elem().Kind() {
530
-		default:
531
-			count := v.Len()
532
-			startN := n
533
-			n += 4
534
-			for i := 0; i < count; i++ {
535
-				n2, err := encodePacketValue(buf[n:], v.Index(i))
536
-				n += n2
537
-				if err != nil {
538
-					return n, err
539
-				}
540
-			}
541
-			binary.BigEndian.PutUint32(buf[startN:startN+4], uint32(count))
542
-		case reflect.Uint8:
543
-			if v.IsNil() {
544
-				binary.BigEndian.PutUint32(buf[n:n+4], uint32(0xffffffff))
545
-				n += 4
546
-			} else {
547
-				bytes := v.Bytes()
548
-				binary.BigEndian.PutUint32(buf[n:n+4], uint32(len(bytes)))
549
-				copy(buf[n+4:n+4+len(bytes)], bytes)
550
-				n += 4 + len(bytes)
551
-			}
552
-		}
553
-	}
554
-	return n, nil
555
-}
556
-
557
-func requestStructForOp(op int32) interface{} {
558
-	switch op {
559
-	case opClose:
560
-		return &closeRequest{}
561
-	case opCreate:
562
-		return &CreateRequest{}
563
-	case opDelete:
564
-		return &DeleteRequest{}
565
-	case opExists:
566
-		return &existsRequest{}
567
-	case opGetAcl:
568
-		return &getAclRequest{}
569
-	case opGetChildren:
570
-		return &getChildrenRequest{}
571
-	case opGetChildren2:
572
-		return &getChildren2Request{}
573
-	case opGetData:
574
-		return &getDataRequest{}
575
-	case opPing:
576
-		return &pingRequest{}
577
-	case opSetAcl:
578
-		return &setAclRequest{}
579
-	case opSetData:
580
-		return &SetDataRequest{}
581
-	case opSetWatches:
582
-		return &setWatchesRequest{}
583
-	case opSync:
584
-		return &syncRequest{}
585
-	case opSetAuth:
586
-		return &setAuthRequest{}
587
-	case opCheck:
588
-		return &CheckVersionRequest{}
589
-	case opMulti:
590
-		return &multiRequest{}
591
-	}
592
-	return nil
593
-}
594
-
595
-func responseStructForOp(op int32) interface{} {
596
-	switch op {
597
-	case opClose:
598
-		return &closeResponse{}
599
-	case opCreate:
600
-		return &createResponse{}
601
-	case opDelete:
602
-		return &deleteResponse{}
603
-	case opExists:
604
-		return &existsResponse{}
605
-	case opGetAcl:
606
-		return &getAclResponse{}
607
-	case opGetChildren:
608
-		return &getChildrenResponse{}
609
-	case opGetChildren2:
610
-		return &getChildren2Response{}
611
-	case opGetData:
612
-		return &getDataResponse{}
613
-	case opPing:
614
-		return &pingResponse{}
615
-	case opSetAcl:
616
-		return &setAclResponse{}
617
-	case opSetData:
618
-		return &setDataResponse{}
619
-	case opSetWatches:
620
-		return &setWatchesResponse{}
621
-	case opSync:
622
-		return &syncResponse{}
623
-	case opWatcherEvent:
624
-		return &watcherEvent{}
625
-	case opSetAuth:
626
-		return &setAuthResponse{}
627
-	// case opCheck:
628
-	// 	return &checkVersionResponse{}
629
-	case opMulti:
630
-		return &multiResponse{}
631
-	}
632
-	return nil
633
-}
634 1
deleted file mode 100644
... ...
@@ -1,148 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"encoding/binary"
5
-	"fmt"
6
-	"io"
7
-	"net"
8
-	"sync"
9
-)
10
-
11
-var (
12
-	requests     = make(map[int32]int32) // Map of Xid -> Opcode
13
-	requestsLock = &sync.Mutex{}
14
-)
15
-
16
-func trace(conn1, conn2 net.Conn, client bool) {
17
-	defer conn1.Close()
18
-	defer conn2.Close()
19
-	buf := make([]byte, 10*1024)
20
-	init := true
21
-	for {
22
-		_, err := io.ReadFull(conn1, buf[:4])
23
-		if err != nil {
24
-			fmt.Println("1>", client, err)
25
-			return
26
-		}
27
-
28
-		blen := int(binary.BigEndian.Uint32(buf[:4]))
29
-
30
-		_, err = io.ReadFull(conn1, buf[4:4+blen])
31
-		if err != nil {
32
-			fmt.Println("2>", client, err)
33
-			return
34
-		}
35
-
36
-		var cr interface{}
37
-		opcode := int32(-1)
38
-		readHeader := true
39
-		if client {
40
-			if init {
41
-				cr = &connectRequest{}
42
-				readHeader = false
43
-			} else {
44
-				xid := int32(binary.BigEndian.Uint32(buf[4:8]))
45
-				opcode = int32(binary.BigEndian.Uint32(buf[8:12]))
46
-				requestsLock.Lock()
47
-				requests[xid] = opcode
48
-				requestsLock.Unlock()
49
-				cr = requestStructForOp(opcode)
50
-				if cr == nil {
51
-					fmt.Printf("Unknown opcode %d\n", opcode)
52
-				}
53
-			}
54
-		} else {
55
-			if init {
56
-				cr = &connectResponse{}
57
-				readHeader = false
58
-			} else {
59
-				xid := int32(binary.BigEndian.Uint32(buf[4:8]))
60
-				zxid := int64(binary.BigEndian.Uint64(buf[8:16]))
61
-				errnum := int32(binary.BigEndian.Uint32(buf[16:20]))
62
-				if xid != -1 || zxid != -1 {
63
-					requestsLock.Lock()
64
-					found := false
65
-					opcode, found = requests[xid]
66
-					if !found {
67
-						opcode = 0
68
-					}
69
-					delete(requests, xid)
70
-					requestsLock.Unlock()
71
-				} else {
72
-					opcode = opWatcherEvent
73
-				}
74
-				cr = responseStructForOp(opcode)
75
-				if cr == nil {
76
-					fmt.Printf("Unknown opcode %d\n", opcode)
77
-				}
78
-				if errnum != 0 {
79
-					cr = &struct{}{}
80
-				}
81
-			}
82
-		}
83
-		opname := "."
84
-		if opcode != -1 {
85
-			opname = opNames[opcode]
86
-		}
87
-		if cr == nil {
88
-			fmt.Printf("%+v %s %+v\n", client, opname, buf[4:4+blen])
89
-		} else {
90
-			n := 4
91
-			hdrStr := ""
92
-			if readHeader {
93
-				var hdr interface{}
94
-				if client {
95
-					hdr = &requestHeader{}
96
-				} else {
97
-					hdr = &responseHeader{}
98
-				}
99
-				if n2, err := decodePacket(buf[n:n+blen], hdr); err != nil {
100
-					fmt.Println(err)
101
-				} else {
102
-					n += n2
103
-				}
104
-				hdrStr = fmt.Sprintf(" %+v", hdr)
105
-			}
106
-			if _, err := decodePacket(buf[n:n+blen], cr); err != nil {
107
-				fmt.Println(err)
108
-			}
109
-			fmt.Printf("%+v %s%s %+v\n", client, opname, hdrStr, cr)
110
-		}
111
-
112
-		init = false
113
-
114
-		written, err := conn2.Write(buf[:4+blen])
115
-		if err != nil {
116
-			fmt.Println("3>", client, err)
117
-			return
118
-		} else if written != 4+blen {
119
-			fmt.Printf("Written != read: %d != %d\n", written, blen)
120
-			return
121
-		}
122
-	}
123
-}
124
-
125
-func handleConnection(addr string, conn net.Conn) {
126
-	zkConn, err := net.Dial("tcp", addr)
127
-	if err != nil {
128
-		fmt.Println(err)
129
-		return
130
-	}
131
-	go trace(conn, zkConn, true)
132
-	trace(zkConn, conn, false)
133
-}
134
-
135
-func StartTracer(listenAddr, serverAddr string) {
136
-	ln, err := net.Listen("tcp", listenAddr)
137
-	if err != nil {
138
-		panic(err)
139
-	}
140
-	for {
141
-		conn, err := ln.Accept()
142
-		if err != nil {
143
-			fmt.Println(err)
144
-			continue
145
-		}
146
-		go handleConnection(serverAddr, conn)
147
-	}
148
-}
149 1
deleted file mode 100644
... ...
@@ -1,54 +0,0 @@
1
-package zk
2
-
3
-import (
4
-	"crypto/sha1"
5
-	"encoding/base64"
6
-	"fmt"
7
-	"math/rand"
8
-	"strconv"
9
-	"strings"
10
-)
11
-
12
-// AuthACL produces an ACL list containing a single ACL which uses the
13
-// provided permissions, with the scheme "auth", and ID "", which is used
14
-// by ZooKeeper to represent any authenticated user.
15
-func AuthACL(perms int32) []ACL {
16
-	return []ACL{{perms, "auth", ""}}
17
-}
18
-
19
-// WorldACL produces an ACL list containing a single ACL which uses the
20
-// provided permissions, with the scheme "world", and ID "anyone", which
21
-// is used by ZooKeeper to represent any user at all.
22
-func WorldACL(perms int32) []ACL {
23
-	return []ACL{{perms, "world", "anyone"}}
24
-}
25
-
26
-func DigestACL(perms int32, user, password string) []ACL {
27
-	userPass := []byte(fmt.Sprintf("%s:%s", user, password))
28
-	h := sha1.New()
29
-	if n, err := h.Write(userPass); err != nil || n != len(userPass) {
30
-		panic("SHA1 failed")
31
-	}
32
-	digest := base64.StdEncoding.EncodeToString(h.Sum(nil))
33
-	return []ACL{{perms, "digest", fmt.Sprintf("%s:%s", user, digest)}}
34
-}
35
-
36
-// FormatServers takes a slice of addresses, and makes sure they are in a format
37
-// that resembles <addr>:<port>. If the server has no port provided, the
38
-// DefaultPort constant is added to the end.
39
-func FormatServers(servers []string) []string {
40
-	for i := range servers {
41
-		if !strings.Contains(servers[i], ":") {
42
-			servers[i] = servers[i] + ":" + strconv.Itoa(DefaultPort)
43
-		}
44
-	}
45
-	return servers
46
-}
47
-
48
-// stringShuffle performs a Fisher-Yates shuffle on a slice of strings
49
-func stringShuffle(s []string) {
50
-	for i := len(s) - 1; i > 0; i-- {
51
-		j := rand.Intn(i + 1)
52
-		s[i], s[j] = s[j], s[i]
53
-	}
54
-}