zookeeper 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +4 -1
- data/Manifest +1 -7
- data/README +0 -41
- data/ext/extconf.rb +1 -1
- data/ext/zookeeper_c.c +19 -6
- data/ext/zookeeper_lib.c +13 -2
- data/ext/zookeeper_lib.h +1 -1
- data/lib/zookeeper/callbacks.rb +1 -1
- data/lib/zookeeper/exceptions.rb +1 -0
- data/lib/zookeeper.rb +36 -13
- data/test/test_close.rb +16 -0
- data/zookeeper.gemspec +6 -8
- metadata +14 -29
- data/examples/cloud_config.rb +0 -125
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
data/CHANGELOG
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
v0.3.2. Handle close, closed connections and expired sessions a little more gracefully.
|
1
2
|
|
2
|
-
v0.3.
|
3
|
+
v0.3.1. ACL bugfix.
|
4
|
+
|
5
|
+
v0.3.0. Wickman's rewrite, breaks dependencies from myelin/emaland port.
|
3
6
|
|
4
7
|
v0.2.2. Fix compatibility with stock Leopard fat-binary Ruby.
|
5
8
|
|
data/Manifest
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
LICENSE
|
3
|
-
Manifest
|
4
3
|
README
|
5
4
|
Rakefile
|
6
|
-
examples/cloud_config.rb
|
7
5
|
ext/extconf.rb
|
8
6
|
ext/zkc-3.3.1.tar.gz
|
9
7
|
ext/zookeeper_c.c
|
@@ -15,8 +13,4 @@ lib/zookeeper/callbacks.rb
|
|
15
13
|
lib/zookeeper/constants.rb
|
16
14
|
lib/zookeeper/exceptions.rb
|
17
15
|
lib/zookeeper/stat.rb
|
18
|
-
|
19
|
-
test/test_callback1.rb
|
20
|
-
test/test_esoteric.rb
|
21
|
-
test/test_watcher1.rb
|
22
|
-
test/test_watcher2.rb
|
16
|
+
Manifest
|
data/README
CHANGED
@@ -4,14 +4,10 @@ An interface to the Zookeeper distributed configuration server.
|
|
4
4
|
|
5
5
|
== License
|
6
6
|
|
7
|
-
<<<<<<< HEAD
|
8
|
-
Copyright 2008 Phillip Pearson, and 2010 Twitter, Inc. Licensed under the MIT License. See the included LICENSE file. Portions copyright 2008-2010 the Apache Software Foundation, licensed under the Apache 2 license, and used with permission.
|
9
|
-
=======
|
10
7
|
Copyright 2008 Phillip Pearson, and 2010 Twitter, Inc. Licensed under the
|
11
8
|
MIT License. See the included LICENSE file. Portions copyright 2008-2010
|
12
9
|
the Apache Software Foundation, licensed under the Apache 2 license, and
|
13
10
|
used with permission.
|
14
|
-
>>>>>>> wickman
|
15
11
|
|
16
12
|
== Install
|
17
13
|
|
@@ -24,42 +20,6 @@ Connect to a server:
|
|
24
20
|
require 'rubygems'
|
25
21
|
require 'zookeeper'
|
26
22
|
z = Zookeeper.new("localhost:2181")
|
27
|
-
<<<<<<< HEAD
|
28
|
-
|
29
|
-
Create, set and read nodes:
|
30
|
-
|
31
|
-
z.create("/bacon", "text to be stored in the new node", 0)
|
32
|
-
data, stat = z.get("/bacon")
|
33
|
-
# => ["text to be stored in the new node"...]
|
34
|
-
|
35
|
-
z.set("/bacon", "an entirely different line of text", stat.version)
|
36
|
-
z.set("/bacon", "this won't work", stat.version)
|
37
|
-
# CZookeeper::BadVersionError: expected version does not match actual version
|
38
|
-
|
39
|
-
data, stat = z.get("/bacon")
|
40
|
-
# => ["an entirely different line of text"...]
|
41
|
-
z.delete("/bacon", stat.version)
|
42
|
-
|
43
|
-
Create ephemeral and sequence nodes:
|
44
|
-
|
45
|
-
z.create("/parent", "parent node", 0)
|
46
|
-
|
47
|
-
z.create("/parent/test-",
|
48
|
-
"an ordered ephemeral node",
|
49
|
-
Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE)
|
50
|
-
# => "/parent/test-0"
|
51
|
-
|
52
|
-
z.create("/parent/test-",
|
53
|
-
"an ordered ephemeral node",
|
54
|
-
Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE)
|
55
|
-
# => "/parent/test-1"
|
56
|
-
|
57
|
-
Acquire locks:
|
58
|
-
|
59
|
-
z.try_acquire "/parent/lock-", "content for the lock file" do |have_lock|
|
60
|
-
puts have_lock ? "we have the lock" : "we don't have the lock"
|
61
|
-
end
|
62
|
-
=======
|
63
23
|
z.get_children(:path => "/")
|
64
24
|
|
65
25
|
== Idioms
|
@@ -80,4 +40,3 @@ Acquire locks:
|
|
80
40
|
Calls take a dictionary of parameters. With the exception of set_acl, the
|
81
41
|
only required parameter is :path. Each call returns a dictionary with at
|
82
42
|
minimum two keys :req_id and :rc.
|
83
|
-
>>>>>>> wickman
|
data/ext/extconf.rb
CHANGED
@@ -33,7 +33,7 @@ Dir.chdir(HERE) do
|
|
33
33
|
raise "'#{cmd}' failed" unless system(cmd)
|
34
34
|
|
35
35
|
Dir.chdir(BUNDLE_PATH) do
|
36
|
-
puts(cmd = "env CFLAGS='-fPIC #{$CFLAGS}' LDFLAGS='-fPIC #{$LDFLAGS}' ./configure --prefix=#{HERE} --without-cppunit --disable-
|
36
|
+
puts(cmd = "env CFLAGS='-fPIC #{$CFLAGS}' LDFLAGS='-fPIC #{$LDFLAGS}' ./configure --prefix=#{HERE} --without-cppunit --disable-dependency-tracking #{$EXTRA_CONF} 2>&1")
|
37
37
|
raise "'#{cmd}' failed" unless system(cmd)
|
38
38
|
puts(cmd = "make CXXFLAGS='#{$CXXFLAGS}' || true 2>&1")
|
39
39
|
raise "'#{cmd}' failed" unless system(cmd)
|
data/ext/zookeeper_c.c
CHANGED
@@ -38,14 +38,24 @@ typedef enum {
|
|
38
38
|
#define IS_ASYNC(zkrbcall) ((zkrbcall)==ASYNC || (zkrbcall)==ASYNC_WATCH)
|
39
39
|
|
40
40
|
static void free_zkrb_instance_data(struct zkrb_instance_data* ptr) {
|
41
|
-
#warning [wickman] TODO: free queue
|
42
41
|
#warning [wickman] TODO: fire off warning if queue is not empty
|
43
42
|
if (ptr->zh && zoo_state(ptr->zh) == ZOO_CONNECTED_STATE) {
|
44
43
|
zookeeper_close(ptr->zh);
|
45
44
|
}
|
45
|
+
if (ptr->queue) zkrb_queue_free(ptr->queue);
|
46
|
+
ptr->queue = NULL;
|
46
47
|
}
|
47
48
|
|
48
|
-
static
|
49
|
+
static void print_zkrb_instance_data(struct zkrb_instance_data* ptr) {
|
50
|
+
fprintf(stderr, "zkrb_instance_data (%x) {\n", ptr);
|
51
|
+
fprintf(stderr, " zh = %x\n", ptr->zh);
|
52
|
+
fprintf(stderr, " { state = %d }\n", zoo_state(ptr->zh));
|
53
|
+
fprintf(stderr, " id = %llx\n", ptr->myid.client_id);
|
54
|
+
fprintf(stderr, " q = %x\n", ptr->queue);
|
55
|
+
fprintf(stderr, "}\n");
|
56
|
+
}
|
57
|
+
|
58
|
+
static VALUE method_init(VALUE self, VALUE hostPort) {
|
49
59
|
Check_Type(hostPort, T_STRING);
|
50
60
|
|
51
61
|
VALUE data;
|
@@ -96,11 +106,11 @@ static VALUE method_initialize(VALUE self, VALUE hostPort) {
|
|
96
106
|
Data_Get_Struct(rb_iv_get(self, "@data"), struct zkrb_instance_data, zk); \
|
97
107
|
zkrb_calling_context* cb_ctx = \
|
98
108
|
(async != Qfalse && async != Qnil) ? \
|
99
|
-
zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) :
|
109
|
+
zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
|
100
110
|
NULL; \
|
101
111
|
zkrb_calling_context* w_ctx = \
|
102
112
|
(watch != Qfalse && watch != Qnil) ? \
|
103
|
-
zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) :
|
113
|
+
zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
|
104
114
|
NULL; \
|
105
115
|
int a = (async != Qfalse && async != Qnil); \
|
106
116
|
int w = (watch != Qfalse && watch != Qnil); \
|
@@ -234,7 +244,6 @@ static VALUE method_delete(VALUE self, VALUE reqid, VALUE path, VALUE version, V
|
|
234
244
|
return INT2FIX(rc);
|
235
245
|
}
|
236
246
|
|
237
|
-
|
238
247
|
#define MAX_ZNODE_SIZE 1048576
|
239
248
|
|
240
249
|
static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
|
@@ -246,6 +255,7 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
|
|
246
255
|
struct Stat stat;
|
247
256
|
|
248
257
|
int rc;
|
258
|
+
|
249
259
|
switch (call_type) {
|
250
260
|
case SYNC:
|
251
261
|
rc = zoo_get(zk->zh, RSTRING(path)->ptr, 0, data, &data_len, &stat);
|
@@ -271,6 +281,7 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
|
|
271
281
|
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
272
282
|
}
|
273
283
|
free(data);
|
284
|
+
|
274
285
|
return output;
|
275
286
|
}
|
276
287
|
|
@@ -363,6 +374,7 @@ static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
|
|
363
374
|
|
364
375
|
static VALUE method_get_next_event(VALUE self) {
|
365
376
|
FETCH_DATA_PTR(self, zk);
|
377
|
+
if (zk->queue == NULL) return Qnil;
|
366
378
|
|
367
379
|
zkrb_event_t *event = zkrb_dequeue(zk->queue);
|
368
380
|
if (event == NULL) return Qnil;
|
@@ -374,6 +386,7 @@ static VALUE method_get_next_event(VALUE self) {
|
|
374
386
|
|
375
387
|
static VALUE method_has_events(VALUE self) {
|
376
388
|
FETCH_DATA_PTR(self, zk);
|
389
|
+
if (zk->queue == NULL) return Qfalse;
|
377
390
|
return zkrb_peek(zk->queue) != NULL ? Qtrue : Qfalse;
|
378
391
|
}
|
379
392
|
|
@@ -427,7 +440,7 @@ static void zkrb_define_methods(void) {
|
|
427
440
|
#define DEFINE_CLASS_METHOD(method, args) { \
|
428
441
|
rb_define_singleton_method(Zookeeper, #method, method_ ## method, args); }
|
429
442
|
|
430
|
-
DEFINE_METHOD(
|
443
|
+
DEFINE_METHOD(init, 1);
|
431
444
|
DEFINE_METHOD(get_children, 4);
|
432
445
|
DEFINE_METHOD(exists, 4);
|
433
446
|
DEFINE_METHOD(create, 6);
|
data/ext/zookeeper_lib.c
CHANGED
@@ -55,6 +55,15 @@ zkrb_queue_t *zkrb_queue_alloc(void) {
|
|
55
55
|
return rq;
|
56
56
|
}
|
57
57
|
|
58
|
+
void zkrb_queue_free(zkrb_queue_t *queue) {
|
59
|
+
if (queue == NULL) return;
|
60
|
+
zkrb_event_t *elt = NULL;
|
61
|
+
while ((elt = zkrb_dequeue(queue)) != NULL) {
|
62
|
+
zkrb_event_free(elt);
|
63
|
+
}
|
64
|
+
free(queue);
|
65
|
+
}
|
66
|
+
|
58
67
|
zkrb_event_t *zkrb_event_alloc(void) {
|
59
68
|
zkrb_event_t *rv = (zkrb_event_t *) malloc(sizeof(zkrb_event_t));
|
60
69
|
return rv;
|
@@ -122,11 +131,11 @@ void zkrb_event_free(zkrb_event_t *event) {
|
|
122
131
|
allocated on the proper thread stack */
|
123
132
|
VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
|
124
133
|
VALUE hash = rb_hash_new();
|
125
|
-
|
134
|
+
|
126
135
|
rb_hash_aset(hash, GET_SYM("req_id"), LL2NUM(event->req_id));
|
127
136
|
if (event->type != ZKRB_WATCHER)
|
128
137
|
rb_hash_aset(hash, GET_SYM("rc"), INT2FIX(event->rc));
|
129
|
-
|
138
|
+
|
130
139
|
switch (event->type) {
|
131
140
|
case ZKRB_DATA: {
|
132
141
|
struct zkrb_data_completion *data_ctx = event->completion.data_completion;
|
@@ -435,6 +444,7 @@ struct Id zkrb_ruby_to_id(VALUE rubyid) {
|
|
435
444
|
if (scheme != Qnil) {
|
436
445
|
id.scheme = malloc(RSTRING(scheme)->len + 1);
|
437
446
|
strncpy(id.scheme, RSTRING(scheme)->ptr, RSTRING(scheme)->len);
|
447
|
+
id.scheme[RSTRING(scheme)->len] = '\0';
|
438
448
|
} else {
|
439
449
|
id.scheme = NULL;
|
440
450
|
}
|
@@ -442,6 +452,7 @@ struct Id zkrb_ruby_to_id(VALUE rubyid) {
|
|
442
452
|
if (ident != Qnil) {
|
443
453
|
id.id = malloc(RSTRING(ident)->len + 1);
|
444
454
|
strncpy(id.id, RSTRING(ident)->ptr, RSTRING(ident)->len);
|
455
|
+
id.id[RSTRING(ident)->len] = '\0';
|
445
456
|
} else {
|
446
457
|
id.id = NULL;
|
447
458
|
}
|
data/ext/zookeeper_lib.h
CHANGED
@@ -87,10 +87,10 @@ typedef struct {
|
|
87
87
|
} zkrb_queue_t;
|
88
88
|
|
89
89
|
zkrb_queue_t * zkrb_queue_alloc(void);
|
90
|
+
void zkrb_queue_free(zkrb_queue_t *queue);
|
90
91
|
zkrb_event_t * zkrb_event_alloc(void);
|
91
92
|
void zkrb_event_free(zkrb_event_t *ptr);
|
92
93
|
|
93
|
-
|
94
94
|
/* push/pop is a misnomer, this is a queue */
|
95
95
|
void zkrb_enqueue(zkrb_queue_t *queue, zkrb_event_t *elt);
|
96
96
|
zkrb_event_t * zkrb_peek(zkrb_queue_t *queue);
|
data/lib/zookeeper/callbacks.rb
CHANGED
data/lib/zookeeper/exceptions.rb
CHANGED
@@ -52,6 +52,7 @@ module ZookeeperExceptions
|
|
52
52
|
class Closing < ZookeeperException; end
|
53
53
|
class Nothing < ZookeeperException; end
|
54
54
|
class SessionMoved < ZookeeperException; end
|
55
|
+
class ConnectionClosed < ZookeeperException; end # this is a Ruby client exception
|
55
56
|
|
56
57
|
def self.by_code(code)
|
57
58
|
case code
|
data/lib/zookeeper.rb
CHANGED
@@ -23,28 +23,33 @@ class Zookeeper < CZookeeper
|
|
23
23
|
ZOO_LOG_LEVEL_INFO = 3
|
24
24
|
ZOO_LOG_LEVEL_DEBUG = 4
|
25
25
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
@completion_reqs = {}
|
29
|
-
@req_mutex = Mutex.new
|
30
|
-
@current_req_id = 1
|
31
|
-
super(host)
|
32
|
-
|
26
|
+
def reopen(timeout = 10)
|
27
|
+
init(@host)
|
33
28
|
if timeout > 0
|
34
29
|
time_to_stop = Time.now + timeout
|
35
30
|
until state == Zookeeper::ZOO_CONNECTED_STATE
|
36
31
|
break if Time.now > time_to_stop
|
37
32
|
sleep 0.1
|
38
33
|
end
|
39
|
-
|
40
|
-
return nil if state != Zookeeper::ZOO_CONNECTED_STATE
|
41
34
|
end
|
35
|
+
# flushes all outstanding watcher reqs.
|
36
|
+
@watcher_reqs = { ZKRB_GLOBAL_CB_REQ => { :watcher => get_default_global_watcher } }
|
37
|
+
state
|
38
|
+
end
|
42
39
|
|
40
|
+
def initialize(host, timeout = 10)
|
41
|
+
@watcher_reqs = {}
|
42
|
+
@completion_reqs = {}
|
43
|
+
@req_mutex = Mutex.new
|
44
|
+
@current_req_id = 1
|
45
|
+
@host = host
|
46
|
+
return nil if reopen(timeout) != Zookeeper::ZOO_CONNECTED_STATE
|
43
47
|
setup_dispatch_thread!
|
44
48
|
end
|
45
|
-
|
46
|
-
public
|
49
|
+
|
50
|
+
public
|
47
51
|
def get(options = {})
|
52
|
+
assert_open
|
48
53
|
assert_supported_keys(options, [:path, :watcher, :watcher_context, :callback, :callback_context])
|
49
54
|
assert_required_keys(options, [:path])
|
50
55
|
|
@@ -56,6 +61,7 @@ public
|
|
56
61
|
end
|
57
62
|
|
58
63
|
def set(options = {})
|
64
|
+
assert_open
|
59
65
|
assert_supported_keys(options, [:path, :data, :version, :callback, :callback_context])
|
60
66
|
assert_required_keys(options, [:path])
|
61
67
|
options[:version] ||= -1
|
@@ -68,6 +74,7 @@ public
|
|
68
74
|
end
|
69
75
|
|
70
76
|
def get_children(options = {})
|
77
|
+
assert_open
|
71
78
|
assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
|
72
79
|
assert_required_keys(options, [:path])
|
73
80
|
|
@@ -79,6 +86,7 @@ public
|
|
79
86
|
end
|
80
87
|
|
81
88
|
def stat(options = {})
|
89
|
+
assert_open
|
82
90
|
assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
|
83
91
|
assert_required_keys(options, [:path])
|
84
92
|
|
@@ -90,6 +98,7 @@ public
|
|
90
98
|
end
|
91
99
|
|
92
100
|
def create(options = {})
|
101
|
+
assert_open
|
93
102
|
assert_supported_keys(options, [:path, :data, :acl, :ephemeral, :sequence, :callback, :callback_context])
|
94
103
|
assert_required_keys(options, [:path])
|
95
104
|
|
@@ -107,6 +116,7 @@ public
|
|
107
116
|
end
|
108
117
|
|
109
118
|
def delete(options = {})
|
119
|
+
assert_open
|
110
120
|
assert_supported_keys(options, [:path, :version, :callback, :callback_context])
|
111
121
|
assert_required_keys(options, [:path])
|
112
122
|
options[:version] ||= -1
|
@@ -118,6 +128,7 @@ public
|
|
118
128
|
end
|
119
129
|
|
120
130
|
def set_acl(options = {})
|
131
|
+
assert_open
|
121
132
|
assert_supported_keys(options, [:path, :acl, :version, :callback, :callback_context])
|
122
133
|
assert_required_keys(options, [:path, :acl])
|
123
134
|
options[:version] ||= -1
|
@@ -129,6 +140,7 @@ public
|
|
129
140
|
end
|
130
141
|
|
131
142
|
def get_acl(options = {})
|
143
|
+
assert_open
|
132
144
|
assert_supported_keys(options, [:path, :callback, :callback_context])
|
133
145
|
assert_required_keys(options, [:path])
|
134
146
|
|
@@ -166,7 +178,7 @@ private
|
|
166
178
|
if callback.respond_to?(:call)
|
167
179
|
callback.call(hash)
|
168
180
|
else
|
169
|
-
puts "dispatch_next_callback found non-callback => #{callback.inspect}"
|
181
|
+
# puts "dispatch_next_callback found non-callback => #{callback.inspect}"
|
170
182
|
end
|
171
183
|
end
|
172
184
|
|
@@ -211,12 +223,23 @@ public
|
|
211
223
|
end
|
212
224
|
|
213
225
|
private
|
226
|
+
# TODO: Make all global puts configurable
|
214
227
|
def get_default_global_watcher
|
215
228
|
Proc.new { |args|
|
216
|
-
puts "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}"
|
229
|
+
# puts "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}"
|
230
|
+
true
|
217
231
|
}
|
218
232
|
end
|
219
233
|
|
234
|
+
# if either of these happen, the user will need to renegotiate a connection via reopen
|
235
|
+
def assert_open
|
236
|
+
if state == ZOO_EXPIRED_SESSION_STATE
|
237
|
+
raise ZookeeperException::SessionExpired
|
238
|
+
elsif state != Zookeeper::ZOO_CONNECTED_STATE
|
239
|
+
raise ZookeeperException::ConnectionClosed
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
220
243
|
def assert_supported_keys(args, supported)
|
221
244
|
unless (args.keys - supported).empty?
|
222
245
|
raise ZookeeperException::BadArguments,
|
data/test/test_close.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'zookeeper'
|
3
|
+
z = Zookeeper.new("localhost:2181")
|
4
|
+
path = "/testing_node"
|
5
|
+
z.get(:path => path)
|
6
|
+
z.create(:path => path, :data => "initial value", :ephemeral => true)
|
7
|
+
z.get(:path => path)
|
8
|
+
z.close()
|
9
|
+
sleep 5
|
10
|
+
begin
|
11
|
+
z.get(:path => path)
|
12
|
+
rescue Exception => e
|
13
|
+
puts "Rescued exception #{e.inspect}"
|
14
|
+
end
|
15
|
+
z.reopen
|
16
|
+
z.get(:path => path)
|
data/zookeeper.gemspec
CHANGED
@@ -2,31 +2,29 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{zookeeper}
|
5
|
-
s.version = "0.3.
|
5
|
+
s.version = "0.3.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Phillip Pearson, Eric Maland, Evan Weaver, Brian Wickman"]
|
9
|
-
s.
|
10
|
-
s.date = %q{2010-07-03}
|
9
|
+
s.date = %q{2010-08-17}
|
11
10
|
s.description = %q{An interface to the Zookeeper distributed configuration server.}
|
12
11
|
s.email = %q{}
|
13
12
|
s.extensions = ["ext/extconf.rb"]
|
14
13
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "ext/zookeeper_c.c", "lib/zookeeper.rb"]
|
15
|
-
s.files = ["CHANGELOG", "LICENSE", "
|
14
|
+
s.files = ["CHANGELOG", "LICENSE", "README", "Rakefile", "ext/extconf.rb", "ext/zkc-3.3.1.tar.gz", "ext/zookeeper_c.c", "ext/zookeeper_lib.c", "ext/zookeeper_lib.h", "lib/zookeeper.rb", "lib/zookeeper/acls.rb", "lib/zookeeper/callbacks.rb", "lib/zookeeper/constants.rb", "lib/zookeeper/exceptions.rb", "lib/zookeeper/stat.rb", "Manifest", "zookeeper.gemspec", "test/test_basic.rb", "test/test_callback1.rb", "test/test_close.rb", "test/test_esoteric.rb", "test/test_watcher1.rb", "test/test_watcher2.rb"]
|
16
15
|
s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/zookeeper/}
|
17
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Zookeeper", "--main", "README"]
|
18
17
|
s.require_paths = ["lib", "ext"]
|
19
18
|
s.rubyforge_project = %q{fauna}
|
20
|
-
s.rubygems_version = %q{1.3.
|
21
|
-
s.signing_key = %q{/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-private_key.pem}
|
19
|
+
s.rubygems_version = %q{1.3.7}
|
22
20
|
s.summary = %q{An interface to the Zookeeper distributed configuration server.}
|
23
|
-
s.test_files = ["test/test_basic.rb", "test/test_callback1.rb", "test/test_esoteric.rb", "test/test_watcher1.rb", "test/test_watcher2.rb"]
|
21
|
+
s.test_files = ["test/test_basic.rb", "test/test_callback1.rb", "test/test_close.rb", "test/test_esoteric.rb", "test/test_watcher1.rb", "test/test_watcher2.rb"]
|
24
22
|
|
25
23
|
if s.respond_to? :specification_version then
|
26
24
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
27
25
|
s.specification_version = 3
|
28
26
|
|
29
|
-
if Gem::Version.new(Gem::
|
27
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
30
28
|
else
|
31
29
|
end
|
32
30
|
else
|
metadata
CHANGED
@@ -1,41 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zookeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
9
|
+
- 2
|
10
|
+
version: 0.3.2
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Phillip Pearson, Eric Maland, Evan Weaver, Brian Wickman
|
13
14
|
autorequire:
|
14
15
|
bindir: bin
|
15
|
-
cert_chain:
|
16
|
-
- |
|
17
|
-
-----BEGIN CERTIFICATE-----
|
18
|
-
MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQUFADA9MQ0wCwYDVQQDDARldmFu
|
19
|
-
MRgwFgYKCZImiZPyLGQBGRYIY2xvdWRidXIxEjAQBgoJkiaJk/IsZAEZFgJzdDAe
|
20
|
-
Fw0wNzA5MTYxMDMzMDBaFw0wODA5MTUxMDMzMDBaMD0xDTALBgNVBAMMBGV2YW4x
|
21
|
-
GDAWBgoJkiaJk/IsZAEZFghjbG91ZGJ1cjESMBAGCgmSJomT8ixkARkWAnN0MIIB
|
22
|
-
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5C0Io89nyApnr+PvbNFge9Vs
|
23
|
-
yRWAlGBUEMahpXp28VrrfXZT0rAW7JBo4PlCE3jl4nE4dzE6gAdItSycjTosrw7A
|
24
|
-
Ir5+xoyl4Vb35adv56TIQQXvNz+BzlqnkAY5JN0CSBRTQb6mxS3hFyD/h4qgDosj
|
25
|
-
R2RFVzHqSxCS8xq4Ny8uzOwOi+Xyu4w67fI5JvnPvMxqrlR1eaIQHmxnf76RzC46
|
26
|
-
QO5QhufjAYGGXd960XzbQsQyTDUYJzrvT7AdOfiyZzKQykKt8dEpDn+QPjFTnGnT
|
27
|
-
QmgJBX5WJN0lHF2l1sbv3gh4Kn1tZu+kTUqeXY6ShAoDTyvZRiFqQdwh8w2lTQID
|
28
|
-
AQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU+WqJz3xQ
|
29
|
-
XSea1hRvvHWcIMgeeC4wDQYJKoZIhvcNAQEFBQADggEBAGLZ75jfOEW8Nsl26CTt
|
30
|
-
JFrWxQTcQT/UljeefVE3xYr7lc9oQjbqO3FOyued3qW7TaNEtZfSHoYeUSMYbpw1
|
31
|
-
XAwocIPuSRFDGM4B+hgQGVDx8PMGiJKom4qLXjO40UZsR7QyN/u869Vj45LURm6h
|
32
|
-
MBcPeqCASI+WNprj9+uZa2kmHiitrFqqfMBNlm5IFbn9XeYSta9AHVvs5QQqV2m5
|
33
|
-
hIPfLqCyxsn/YgOGvo6iwyQTWyTswamaAC3HRWZxIS1sfn/Ssqa7E7oQMkv5FAXr
|
34
|
-
x5rKePfXINf8XTJczkl9OBEYdE9aNdJsJpXD0asLgGVwBICS5Bjohp6mizJcDC1+
|
35
|
-
yZ0=
|
36
|
-
-----END CERTIFICATE-----
|
16
|
+
cert_chain: []
|
37
17
|
|
38
|
-
date: 2010-
|
18
|
+
date: 2010-08-17 00:00:00 -07:00
|
39
19
|
default_executable:
|
40
20
|
dependencies: []
|
41
21
|
|
@@ -54,10 +34,8 @@ extra_rdoc_files:
|
|
54
34
|
files:
|
55
35
|
- CHANGELOG
|
56
36
|
- LICENSE
|
57
|
-
- Manifest
|
58
37
|
- README
|
59
38
|
- Rakefile
|
60
|
-
- examples/cloud_config.rb
|
61
39
|
- ext/extconf.rb
|
62
40
|
- ext/zkc-3.3.1.tar.gz
|
63
41
|
- ext/zookeeper_c.c
|
@@ -69,12 +47,14 @@ files:
|
|
69
47
|
- lib/zookeeper/constants.rb
|
70
48
|
- lib/zookeeper/exceptions.rb
|
71
49
|
- lib/zookeeper/stat.rb
|
50
|
+
- Manifest
|
51
|
+
- zookeeper.gemspec
|
72
52
|
- test/test_basic.rb
|
73
53
|
- test/test_callback1.rb
|
54
|
+
- test/test_close.rb
|
74
55
|
- test/test_esoteric.rb
|
75
56
|
- test/test_watcher1.rb
|
76
57
|
- test/test_watcher2.rb
|
77
|
-
- zookeeper.gemspec
|
78
58
|
has_rdoc: true
|
79
59
|
homepage: http://blog.evanweaver.com/files/doc/fauna/zookeeper/
|
80
60
|
licenses: []
|
@@ -91,16 +71,20 @@ require_paths:
|
|
91
71
|
- lib
|
92
72
|
- ext
|
93
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
94
75
|
requirements:
|
95
76
|
- - ">="
|
96
77
|
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
97
79
|
segments:
|
98
80
|
- 0
|
99
81
|
version: "0"
|
100
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
101
84
|
requirements:
|
102
85
|
- - ">="
|
103
86
|
- !ruby/object:Gem::Version
|
87
|
+
hash: 11
|
104
88
|
segments:
|
105
89
|
- 1
|
106
90
|
- 2
|
@@ -108,13 +92,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
92
|
requirements: []
|
109
93
|
|
110
94
|
rubyforge_project: fauna
|
111
|
-
rubygems_version: 1.3.
|
95
|
+
rubygems_version: 1.3.7
|
112
96
|
signing_key:
|
113
97
|
specification_version: 3
|
114
98
|
summary: An interface to the Zookeeper distributed configuration server.
|
115
99
|
test_files:
|
116
100
|
- test/test_basic.rb
|
117
101
|
- test/test_callback1.rb
|
102
|
+
- test/test_close.rb
|
118
103
|
- test/test_esoteric.rb
|
119
104
|
- test/test_watcher1.rb
|
120
105
|
- test/test_watcher2.rb
|
data/examples/cloud_config.rb
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
require "rubygems"
|
2
|
-
require "zookeeper"
|
3
|
-
|
4
|
-
# A basic cloud-based YAML config library. Ruby Zookeeper client example.
|
5
|
-
#
|
6
|
-
# If you pass in a file as 'zk:/foo.yml/blah' it will go out to zookeeper.
|
7
|
-
# Otherwise the file is assumed to be local. The yml file will get parsed
|
8
|
-
# and cached locally, and keys after the .yml get interpreted as keys into
|
9
|
-
# the YAML.
|
10
|
-
#
|
11
|
-
# e.g. get(zk:/config/service.yml/key1/key2/key3..) =>
|
12
|
-
# zk.get(:path => /config/service.yml)
|
13
|
-
# yaml <= YAML.parse(data)
|
14
|
-
# yaml[key1][key2][key3]...
|
15
|
-
#
|
16
|
-
# If keys are unspecified, it returns the parsed YAML as one big object
|
17
|
-
#
|
18
|
-
# TODO if staleness is set to 0, read in YAML immediately before next
|
19
|
-
# get(...)
|
20
|
-
|
21
|
-
class CloudConfig
|
22
|
-
class NodeNotFound < StandardError; end
|
23
|
-
class BadPathError < StandardError; end
|
24
|
-
|
25
|
-
DEFAULT_SERVERS = "localhost:2181"
|
26
|
-
|
27
|
-
def initialize(zkservers = DEFAULT_SERVERS, staleness = 15) # maximum allowed staleness in seconds
|
28
|
-
@staleness = staleness
|
29
|
-
@lock = Mutex.new
|
30
|
-
@zkservers = DEFAULT_SERVERS
|
31
|
-
|
32
|
-
# cache
|
33
|
-
@data = {}
|
34
|
-
@zkcb = Zookeeper::WatcherCallback.new { dirty_callback(@zkcb.context) }
|
35
|
-
@zk = nil
|
36
|
-
end
|
37
|
-
|
38
|
-
def get(node)
|
39
|
-
filename, keys = extract_filename(node)
|
40
|
-
|
41
|
-
# read(filename) is potentially a zk call, so do not hold the lock during the read
|
42
|
-
if @lock.synchronize { !@data.has_key?(filename) }
|
43
|
-
d = YAML.load(read(filename))
|
44
|
-
@lock.synchronize { @data[filename] = d }
|
45
|
-
end
|
46
|
-
|
47
|
-
# synchronized b/c we potentially have a background thread updating data nodes from zk
|
48
|
-
# if keys is empty, return the whole file, otherwise roll up the keys
|
49
|
-
@lock.synchronize {
|
50
|
-
keys.empty? ? @data[filename] : keys.inject(@data[filename]) { |hash, key| hash[key] }
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
# todo:
|
55
|
-
# factor get-and-watch into a different subsystem (so you can have
|
56
|
-
# polling stat() ops on local filesystem.)
|
57
|
-
def read(yaml)
|
58
|
-
# read yaml file and register watcher. if watcher fires, set up
|
59
|
-
# background thread to do read and update data.
|
60
|
-
if yaml.match(/^zk:/)
|
61
|
-
@zk ||= init_zk
|
62
|
-
yaml = yaml['zk:'.length..-1] # strip off zk: from zk:/config/path.yml
|
63
|
-
resp = get_and_register(yaml)
|
64
|
-
|
65
|
-
if resp[:rc] != Zookeeper::ZOK
|
66
|
-
@zk.unregister_watcher(resp[:req_id])
|
67
|
-
raise NodeNotFound
|
68
|
-
end
|
69
|
-
|
70
|
-
resp[:data]
|
71
|
-
else
|
72
|
-
raise NodeNotFound unless File.exists?(yaml)
|
73
|
-
File.read(yaml)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def extract_filename(node)
|
78
|
-
path_elements = node.split("/")
|
79
|
-
|
80
|
-
yamlindex = path_elements.map{ |x| x.match("\.yml$") != nil }.index(true)
|
81
|
-
raise BadPathError unless yamlindex
|
82
|
-
|
83
|
-
yamlname = path_elements[0..yamlindex].join '/'
|
84
|
-
yamlkeys = path_elements[(yamlindex+1)..-1]
|
85
|
-
|
86
|
-
return yamlname, yamlkeys
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
def init_zk
|
91
|
-
Zookeeper.new(@zkservers)
|
92
|
-
end
|
93
|
-
|
94
|
-
def get_and_register(znode)
|
95
|
-
@zk.get(:path => znode, :watcher => @zkcb,
|
96
|
-
:watcher_context => { :path => znode,
|
97
|
-
:wait => rand(@staleness) })
|
98
|
-
end
|
99
|
-
|
100
|
-
def dirty_callback(context)
|
101
|
-
path = context[:path]
|
102
|
-
wait = context[:wait]
|
103
|
-
|
104
|
-
# Fire off a background update that waits a randomized period of time up
|
105
|
-
# to @staleness seconds.
|
106
|
-
Thread.new do
|
107
|
-
sleep wait
|
108
|
-
background_update(path)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def background_update(zkpath)
|
113
|
-
# do a synchronous get/register a new watcher
|
114
|
-
resp = get_and_register(zkpath)
|
115
|
-
if resp[:rc] != Zookeeper::ZOK
|
116
|
-
# puts "Unable to read #{zkpath} from Zookeeper!" @logger.error
|
117
|
-
zk.unregister_watcher(resp[:req_id])
|
118
|
-
else
|
119
|
-
# puts "Updating data."
|
120
|
-
d = YAML.load(resp[:data])
|
121
|
-
@lock.synchronize { @data["zk:#{zkpath}"] = d }
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
data.tar.gz.sig
DELETED
Binary file
|
metadata.gz.sig
DELETED
Binary file
|