zookeeper 0.4.3 → 0.4.4
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 +3 -2
- data/Rakefile +2 -4
- data/ext/zookeeper_c.c +37 -27
- data/ext/zookeeper_lib.c +41 -26
- data/ext/zookeeper_lib.h +2 -0
- data/lib/zookeeper.rb +38 -29
- data/zookeeper.gemspec +5 -5
- metadata +7 -7
data/CHANGELOG
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
v0.4.
|
2
|
-
|
1
|
+
v0.4.4 Fix race condition on close, possible data corruption on async get.
|
2
|
+
|
3
|
+
v0.4.3 Fix a handful of memory-related bugs, fix SIGSEGV on master change, reduce latency of event handling, fix compilation on OSX.
|
3
4
|
|
4
5
|
v0.4.2 Add options to Zookeeper#initialize, silence most Zookeeper logs.
|
5
6
|
|
data/Rakefile
CHANGED
@@ -2,10 +2,8 @@ require 'echoe'
|
|
2
2
|
|
3
3
|
Echoe.new("zookeeper") do |p|
|
4
4
|
p.author = "Phillip Pearson, Eric Maland, Evan Weaver, Brian Wickman"
|
5
|
-
p.project = "
|
5
|
+
p.project = "twitter"
|
6
6
|
p.summary = "An interface to the Zookeeper distributed configuration server."
|
7
|
-
p.url = "https://github.com/twitter/zookeeper"
|
8
|
-
p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
|
9
7
|
p.clean_pattern += ["ext/lib", "ext/include", "ext/c", "ext/bin", "ext/conftest.dSYM"]
|
10
8
|
p.rdoc_pattern = /README|TODO|LICENSE|CHANGELOG|BENCH|COMPAT|zookeeper_c.c|zookeeper.rb/
|
11
|
-
end
|
9
|
+
end
|
data/ext/zookeeper_c.c
CHANGED
@@ -26,6 +26,7 @@ struct zkrb_instance_data {
|
|
26
26
|
zhandle_t *zh;
|
27
27
|
clientid_t myid;
|
28
28
|
zkrb_queue_t *queue;
|
29
|
+
int pending_close;
|
29
30
|
};
|
30
31
|
|
31
32
|
typedef enum {
|
@@ -99,13 +100,14 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
|
99
100
|
free_zkrb_instance_data,
|
100
101
|
zk_local_ctx);
|
101
102
|
zk_local_ctx->queue = zkrb_queue_alloc();
|
103
|
+
zk_local_ctx->pending_close = 0;
|
102
104
|
|
103
105
|
zoo_deterministic_conn_order(0);
|
104
106
|
|
105
107
|
zkrb_calling_context *ctx =
|
106
108
|
zkrb_calling_context_alloc(ZKRB_GLOBAL_REQ, zk_local_ctx->queue);
|
107
109
|
|
108
|
-
zk_local_ctx->zh =
|
110
|
+
zk_local_ctx->zh =
|
109
111
|
zookeeper_init(
|
110
112
|
RSTRING_PTR(hostPort),
|
111
113
|
zkrb_state_callback,
|
@@ -113,7 +115,7 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
|
113
115
|
&zk_local_ctx->myid,
|
114
116
|
ctx,
|
115
117
|
0);
|
116
|
-
|
118
|
+
|
117
119
|
#warning [wickman] TODO handle this properly on the Ruby side rather than C side
|
118
120
|
if (!zk_local_ctx->zh) {
|
119
121
|
rb_raise(rb_eRuntimeError, "error connecting to zookeeper: %d", errno);
|
@@ -156,10 +158,10 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
|
156
158
|
|
157
159
|
static VALUE method_get_children(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
|
158
160
|
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
159
|
-
|
161
|
+
|
160
162
|
struct String_vector strings;
|
161
163
|
struct Stat stat;
|
162
|
-
|
164
|
+
|
163
165
|
int rc;
|
164
166
|
switch (call_type) {
|
165
167
|
case SYNC:
|
@@ -169,11 +171,11 @@ static VALUE method_get_children(VALUE self, VALUE reqid, VALUE path, VALUE asyn
|
|
169
171
|
case SYNC_WATCH:
|
170
172
|
rc = zoo_wget_children2(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, &strings, &stat);
|
171
173
|
break;
|
172
|
-
|
174
|
+
|
173
175
|
case ASYNC:
|
174
176
|
rc = zoo_aget_children2(zk->zh, RSTRING_PTR(path), 0, zkrb_strings_stat_callback, data_ctx);
|
175
177
|
break;
|
176
|
-
|
178
|
+
|
177
179
|
case ASYNC_WATCH:
|
178
180
|
rc = zoo_awget_children2(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_strings_stat_callback, data_ctx);
|
179
181
|
break;
|
@@ -190,7 +192,7 @@ static VALUE method_get_children(VALUE self, VALUE reqid, VALUE path, VALUE asyn
|
|
190
192
|
|
191
193
|
static VALUE method_exists(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
|
192
194
|
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
193
|
-
|
195
|
+
|
194
196
|
struct Stat stat;
|
195
197
|
|
196
198
|
int rc;
|
@@ -202,11 +204,11 @@ static VALUE method_exists(VALUE self, VALUE reqid, VALUE path, VALUE async, VAL
|
|
202
204
|
case SYNC_WATCH:
|
203
205
|
rc = zoo_wexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, &stat);
|
204
206
|
break;
|
205
|
-
|
207
|
+
|
206
208
|
case ASYNC:
|
207
209
|
rc = zoo_aexists(zk->zh, RSTRING_PTR(path), 0, zkrb_stat_callback, data_ctx);
|
208
210
|
break;
|
209
|
-
|
211
|
+
|
210
212
|
case ASYNC_WATCH:
|
211
213
|
rc = zoo_awexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_stat_callback, data_ctx);
|
212
214
|
break;
|
@@ -223,12 +225,12 @@ static VALUE method_exists(VALUE self, VALUE reqid, VALUE path, VALUE async, VAL
|
|
223
225
|
static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE async, VALUE acls, VALUE flags) {
|
224
226
|
VALUE watch = Qfalse;
|
225
227
|
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
226
|
-
|
228
|
+
|
227
229
|
if (data != Qnil) Check_Type(data, T_STRING);
|
228
230
|
Check_Type(flags, T_FIXNUM);
|
229
231
|
const char *data_ptr = (data == Qnil) ? NULL : RSTRING_PTR(data);
|
230
232
|
size_t data_len = (data == Qnil) ? -1 : RSTRING_LEN(data);
|
231
|
-
|
233
|
+
|
232
234
|
struct ACL_vector *aclptr = NULL;
|
233
235
|
if (acls != Qnil) { aclptr = zkrb_ruby_to_aclvector(acls); }
|
234
236
|
char realpath[16384];
|
@@ -261,10 +263,10 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
|
|
261
263
|
}
|
262
264
|
|
263
265
|
static VALUE method_delete(VALUE self, VALUE reqid, VALUE path, VALUE version, VALUE async) {
|
264
|
-
VALUE watch = Qfalse;
|
266
|
+
VALUE watch = Qfalse;
|
265
267
|
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
266
268
|
Check_Type(version, T_FIXNUM);
|
267
|
-
|
269
|
+
|
268
270
|
int rc = 0;
|
269
271
|
switch (call_type) {
|
270
272
|
case SYNC:
|
@@ -293,7 +295,7 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
|
|
293
295
|
struct Stat stat;
|
294
296
|
|
295
297
|
int rc;
|
296
|
-
|
298
|
+
|
297
299
|
switch (call_type) {
|
298
300
|
case SYNC:
|
299
301
|
rc = zoo_get(zk->zh, RSTRING_PTR(path), 0, data, &data_len, &stat);
|
@@ -302,11 +304,11 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
|
|
302
304
|
case SYNC_WATCH:
|
303
305
|
rc = zoo_wget(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, data, &data_len, &stat);
|
304
306
|
break;
|
305
|
-
|
307
|
+
|
306
308
|
case ASYNC:
|
307
309
|
rc = zoo_aget(zk->zh, RSTRING_PTR(path), 0, zkrb_data_callback, data_ctx);
|
308
310
|
break;
|
309
|
-
|
311
|
+
|
310
312
|
case ASYNC_WATCH:
|
311
313
|
rc = zoo_awget(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_data_callback, data_ctx);
|
312
314
|
break;
|
@@ -329,7 +331,7 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
|
|
329
331
|
static VALUE method_set(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE async, VALUE version) {
|
330
332
|
VALUE watch = Qfalse;
|
331
333
|
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
332
|
-
|
334
|
+
|
333
335
|
struct Stat stat;
|
334
336
|
if (data != Qnil) Check_Type(data, T_STRING);
|
335
337
|
const char *data_ptr = (data == Qnil) ? NULL : RSTRING_PTR(data);
|
@@ -389,7 +391,7 @@ static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
|
|
389
391
|
|
390
392
|
struct ACL_vector acls;
|
391
393
|
struct Stat stat;
|
392
|
-
|
394
|
+
|
393
395
|
int rc;
|
394
396
|
switch (call_type) {
|
395
397
|
case SYNC:
|
@@ -421,12 +423,7 @@ static VALUE method_get_next_event(VALUE self) {
|
|
421
423
|
for (;;) {
|
422
424
|
zkrb_event_t *event = zkrb_dequeue(zk->queue, 1);
|
423
425
|
|
424
|
-
/*
|
425
|
-
* If no events found, wait for an event by using rb_thread_select() on the
|
426
|
-
* queue's pipe. Note that the ZK handle might be closed while we're
|
427
|
-
* waiting; if this happens, the rb_thread_select() will fail, and we can't
|
428
|
-
* safely touch the "zk" instance handle.
|
429
|
-
*/
|
426
|
+
/* Wait for an event using rb_thread_select() on the queue's pipe */
|
430
427
|
if (event == NULL) {
|
431
428
|
int fd = zk->queue->pipe_read;
|
432
429
|
fd_set rset;
|
@@ -440,6 +437,9 @@ static VALUE method_get_next_event(VALUE self) {
|
|
440
437
|
if (read(fd, buf, sizeof(buf)) == -1)
|
441
438
|
rb_raise(rb_eRuntimeError, "read failed: %d", errno);
|
442
439
|
|
440
|
+
if (zk->pending_close)
|
441
|
+
return Qnil;
|
442
|
+
|
443
443
|
continue;
|
444
444
|
}
|
445
445
|
|
@@ -463,6 +463,15 @@ static VALUE method_client_id(VALUE self) {
|
|
463
463
|
return UINT2NUM(id->client_id);
|
464
464
|
}
|
465
465
|
|
466
|
+
static VALUE method_signal_pending_close(VALUE self) {
|
467
|
+
FETCH_DATA_PTR(self, zk);
|
468
|
+
|
469
|
+
zk->pending_close = 1;
|
470
|
+
zkrb_signal(zk->queue);
|
471
|
+
|
472
|
+
return Qnil;
|
473
|
+
}
|
474
|
+
|
466
475
|
static VALUE method_close(VALUE self) {
|
467
476
|
FETCH_DATA_PTR(self, zk);
|
468
477
|
|
@@ -517,8 +526,9 @@ static void zkrb_define_methods(void) {
|
|
517
526
|
DEFINE_METHOD(get, 4);
|
518
527
|
DEFINE_METHOD(set, 5);
|
519
528
|
DEFINE_METHOD(set_acl, 5);
|
520
|
-
DEFINE_METHOD(get_acl, 3);
|
529
|
+
DEFINE_METHOD(get_acl, 3);
|
521
530
|
DEFINE_METHOD(client_id, 0);
|
531
|
+
DEFINE_METHOD(signal_pending_close, 0);
|
522
532
|
DEFINE_METHOD(close, 0);
|
523
533
|
DEFINE_METHOD(deterministic_conn_order, 1);
|
524
534
|
DEFINE_METHOD(is_unrecoverable, 0);
|
@@ -528,11 +538,11 @@ static void zkrb_define_methods(void) {
|
|
528
538
|
// DEFINE_METHOD(add_auth, 3);
|
529
539
|
// DEFINE_METHOD(async, 1);
|
530
540
|
|
531
|
-
// methods for the ruby-side event manager
|
541
|
+
// methods for the ruby-side event manager
|
532
542
|
DEFINE_METHOD(get_next_event, 0);
|
533
543
|
DEFINE_METHOD(has_events, 0);
|
534
544
|
|
535
|
-
// Make these class methods?
|
545
|
+
// Make these class methods?
|
536
546
|
DEFINE_METHOD(set_debug_level, 1);
|
537
547
|
DEFINE_METHOD(zerror, 1);
|
538
548
|
}
|
data/ext/zookeeper_lib.c
CHANGED
@@ -69,6 +69,14 @@ zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q, int need_lock) {
|
|
69
69
|
}
|
70
70
|
}
|
71
71
|
|
72
|
+
void zkrb_signal(zkrb_queue_t *q) {
|
73
|
+
pthread_mutex_lock(&zkrb_q_mutex);
|
74
|
+
ssize_t ret = write(q->pipe_write, "0", 1); /* Wake up Ruby listener */
|
75
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
76
|
+
if (ret == -1)
|
77
|
+
rb_raise(rb_eRuntimeError, "write to pipe failed: %d", errno);
|
78
|
+
}
|
79
|
+
|
72
80
|
zkrb_queue_t *zkrb_queue_alloc(void) {
|
73
81
|
int pfd[2];
|
74
82
|
if (pipe(pfd) == -1)
|
@@ -187,14 +195,14 @@ VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
|
|
187
195
|
case ZKRB_DATA: {
|
188
196
|
struct zkrb_data_completion *data_ctx = event->completion.data_completion;
|
189
197
|
if (ZKRBDebugging) zkrb_print_stat(data_ctx->stat);
|
190
|
-
rb_hash_aset(hash, GET_SYM("data"), data_ctx->data ?
|
198
|
+
rb_hash_aset(hash, GET_SYM("data"), data_ctx->data ? rb_str_new(data_ctx->data, data_ctx->data_len) : Qnil);
|
191
199
|
rb_hash_aset(hash, GET_SYM("stat"), data_ctx->stat ? zkrb_stat_to_rarray(data_ctx->stat) : Qnil);
|
192
200
|
break;
|
193
201
|
}
|
194
202
|
case ZKRB_STAT: {
|
195
203
|
struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
|
196
204
|
rb_hash_aset(hash, GET_SYM("stat"), stat_ctx->stat ? zkrb_stat_to_rarray(stat_ctx->stat) : Qnil);
|
197
|
-
break;
|
205
|
+
break;
|
198
206
|
}
|
199
207
|
case ZKRB_STRING: {
|
200
208
|
struct zkrb_string_completion *string_ctx = event->completion.string_completion;
|
@@ -328,14 +336,21 @@ void zkrb_data_callback(
|
|
328
336
|
struct zkrb_data_completion *dc = malloc(sizeof(struct zkrb_data_completion));
|
329
337
|
dc->data = NULL;
|
330
338
|
dc->stat = NULL;
|
331
|
-
|
339
|
+
dc->data_len = 0;
|
340
|
+
|
341
|
+
if (value != NULL) {
|
342
|
+
dc->data = malloc(value_len);
|
343
|
+
dc->data_len = value_len;
|
344
|
+
memcpy(dc->data, value, value_len);
|
345
|
+
}
|
346
|
+
|
332
347
|
if (stat != NULL) { dc->stat = malloc(sizeof(struct Stat)); memcpy(dc->stat, stat, sizeof(struct Stat)); }
|
333
348
|
|
334
349
|
ZKH_SETUP_EVENT(queue, event);
|
335
350
|
event->rc = rc;
|
336
351
|
event->type = ZKRB_DATA;
|
337
352
|
event->completion.data_completion = dc;
|
338
|
-
|
353
|
+
|
339
354
|
zkrb_enqueue(queue, event);
|
340
355
|
}
|
341
356
|
|
@@ -354,7 +369,7 @@ void zkrb_stat_callback(
|
|
354
369
|
event->rc = rc;
|
355
370
|
event->type = ZKRB_STAT;
|
356
371
|
event->completion.stat_completion = sc;
|
357
|
-
|
372
|
+
|
358
373
|
zkrb_enqueue(queue, event);
|
359
374
|
}
|
360
375
|
|
@@ -374,7 +389,7 @@ void zkrb_string_callback(
|
|
374
389
|
event->rc = rc;
|
375
390
|
event->type = ZKRB_STRING;
|
376
391
|
event->completion.string_completion = sc;
|
377
|
-
|
392
|
+
|
378
393
|
zkrb_enqueue(queue, event);
|
379
394
|
}
|
380
395
|
|
@@ -393,7 +408,7 @@ void zkrb_strings_callback(
|
|
393
408
|
event->rc = rc;
|
394
409
|
event->type = ZKRB_STRINGS;
|
395
410
|
event->completion.strings_completion = sc;
|
396
|
-
|
411
|
+
|
397
412
|
zkrb_enqueue(queue, event);
|
398
413
|
}
|
399
414
|
|
@@ -413,7 +428,7 @@ void zkrb_strings_stat_callback(
|
|
413
428
|
event->rc = rc;
|
414
429
|
event->type = ZKRB_STRINGS_STAT;
|
415
430
|
event->completion.strings_stat_completion = sc;
|
416
|
-
|
431
|
+
|
417
432
|
zkrb_enqueue(queue, event);
|
418
433
|
}
|
419
434
|
|
@@ -428,7 +443,7 @@ void zkrb_void_callback(
|
|
428
443
|
event->rc = rc;
|
429
444
|
event->type = ZKRB_VOID;
|
430
445
|
event->completion.void_completion = NULL;
|
431
|
-
|
446
|
+
|
432
447
|
zkrb_enqueue(queue, event);
|
433
448
|
}
|
434
449
|
|
@@ -449,7 +464,7 @@ void zkrb_acl_callback(
|
|
449
464
|
event->rc = rc;
|
450
465
|
event->type = ZKRB_ACL;
|
451
466
|
event->completion.acl_completion = ac;
|
452
|
-
|
467
|
+
|
453
468
|
/* should be synchronized */
|
454
469
|
zkrb_enqueue(queue, event);
|
455
470
|
}
|
@@ -487,22 +502,22 @@ struct ACL_vector * zkrb_ruby_to_aclvector(VALUE acl_ary) {
|
|
487
502
|
#warning [wickman] TODO test zkrb_ruby_to_aclvector
|
488
503
|
struct ACL zkrb_ruby_to_acl(VALUE rubyacl) {
|
489
504
|
struct ACL acl;
|
490
|
-
|
505
|
+
|
491
506
|
VALUE perms = rb_iv_get(rubyacl, "@perms");
|
492
507
|
VALUE rubyid = rb_iv_get(rubyacl, "@id");
|
493
508
|
acl.perms = NUM2INT(perms);
|
494
509
|
acl.id = zkrb_ruby_to_id(rubyid);
|
495
|
-
|
510
|
+
|
496
511
|
return acl;
|
497
512
|
}
|
498
513
|
|
499
514
|
#warning [wickman] TODO zkrb_ruby_to_id error checking? test
|
500
515
|
struct Id zkrb_ruby_to_id(VALUE rubyid) {
|
501
516
|
struct Id id;
|
502
|
-
|
517
|
+
|
503
518
|
VALUE scheme = rb_iv_get(rubyid, "@scheme");
|
504
519
|
VALUE ident = rb_iv_get(rubyid, "@id");
|
505
|
-
|
520
|
+
|
506
521
|
if (scheme != Qnil) {
|
507
522
|
id.scheme = malloc(RSTRING_LEN(scheme) + 1);
|
508
523
|
strncpy(id.scheme, RSTRING_PTR(scheme), RSTRING_LEN(scheme));
|
@@ -518,7 +533,7 @@ struct Id zkrb_ruby_to_id(VALUE rubyid) {
|
|
518
533
|
} else {
|
519
534
|
id.id = NULL;
|
520
535
|
}
|
521
|
-
|
536
|
+
|
522
537
|
return id;
|
523
538
|
}
|
524
539
|
|
@@ -542,17 +557,17 @@ VALUE zkrb_string_vector_to_ruby(struct String_vector *string_vector) {
|
|
542
557
|
|
543
558
|
VALUE zkrb_stat_to_rarray(const struct Stat* stat) {
|
544
559
|
return rb_ary_new3(11,
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
560
|
+
LL2NUM(stat->czxid),
|
561
|
+
LL2NUM(stat->mzxid),
|
562
|
+
LL2NUM(stat->ctime),
|
563
|
+
LL2NUM(stat->mtime),
|
564
|
+
INT2NUM(stat->version),
|
565
|
+
INT2NUM(stat->cversion),
|
566
|
+
INT2NUM(stat->aversion),
|
567
|
+
LL2NUM(stat->ephemeralOwner),
|
568
|
+
INT2NUM(stat->dataLength),
|
569
|
+
INT2NUM(stat->numChildren),
|
570
|
+
LL2NUM(stat->pzxid));
|
556
571
|
}
|
557
572
|
|
558
573
|
VALUE zkrb_stat_to_rhash(const struct Stat *stat) {
|
data/ext/zookeeper_lib.h
CHANGED
@@ -26,6 +26,7 @@ extern pthread_mutex_t zkrb_q_mutex;
|
|
26
26
|
|
27
27
|
struct zkrb_data_completion {
|
28
28
|
char *data;
|
29
|
+
int data_len;
|
29
30
|
struct Stat *stat;
|
30
31
|
};
|
31
32
|
|
@@ -108,6 +109,7 @@ void zkrb_event_free(zkrb_event_t *ptr);
|
|
108
109
|
void zkrb_enqueue(zkrb_queue_t *queue, zkrb_event_t *elt);
|
109
110
|
zkrb_event_t * zkrb_peek(zkrb_queue_t *queue);
|
110
111
|
zkrb_event_t * zkrb_dequeue(zkrb_queue_t *queue, int need_lock);
|
112
|
+
void zkrb_signal(zkrb_queue_t *queue);
|
111
113
|
|
112
114
|
void zkrb_print_stat(const struct Stat *s);
|
113
115
|
|
data/lib/zookeeper.rb
CHANGED
@@ -22,7 +22,7 @@ class Zookeeper < CZookeeper
|
|
22
22
|
ZOO_LOG_LEVEL_WARN = 2
|
23
23
|
ZOO_LOG_LEVEL_INFO = 3
|
24
24
|
ZOO_LOG_LEVEL_DEBUG = 4
|
25
|
-
|
25
|
+
|
26
26
|
def reopen(timeout = 10)
|
27
27
|
init(@host)
|
28
28
|
if timeout > 0
|
@@ -34,6 +34,7 @@ class Zookeeper < CZookeeper
|
|
34
34
|
end
|
35
35
|
# flushes all outstanding watcher reqs.
|
36
36
|
@watcher_reqs = { ZKRB_GLOBAL_CB_REQ => { :watcher => get_default_global_watcher } }
|
37
|
+
setup_dispatch_thread!
|
37
38
|
state
|
38
39
|
end
|
39
40
|
|
@@ -44,7 +45,6 @@ class Zookeeper < CZookeeper
|
|
44
45
|
@current_req_id = 1
|
45
46
|
@host = host
|
46
47
|
return nil if reopen(timeout) != Zookeeper::ZOO_CONNECTED_STATE
|
47
|
-
setup_dispatch_thread!
|
48
48
|
end
|
49
49
|
|
50
50
|
public
|
@@ -52,14 +52,14 @@ public
|
|
52
52
|
assert_open
|
53
53
|
assert_supported_keys(options, [:path, :watcher, :watcher_context, :callback, :callback_context])
|
54
54
|
assert_required_keys(options, [:path])
|
55
|
-
|
55
|
+
|
56
56
|
req_id = setup_call(options)
|
57
57
|
rc, value, stat = super(req_id, options[:path], options[:callback], options[:watcher])
|
58
58
|
|
59
59
|
rv = { :req_id => req_id, :rc => rc }
|
60
60
|
options[:callback] ? rv : rv.merge(:data => value, :stat => Stat.new(stat))
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
def set(options = {})
|
64
64
|
assert_open
|
65
65
|
assert_supported_keys(options, [:path, :data, :version, :callback, :callback_context])
|
@@ -72,7 +72,7 @@ public
|
|
72
72
|
rv = { :req_id => req_id, :rc => rc }
|
73
73
|
options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
def get_children(options = {})
|
77
77
|
assert_open
|
78
78
|
assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
|
@@ -96,34 +96,34 @@ public
|
|
96
96
|
rv = { :req_id => req_id, :rc => rc }
|
97
97
|
options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
def create(options = {})
|
101
101
|
assert_open
|
102
102
|
assert_supported_keys(options, [:path, :data, :acl, :ephemeral, :sequence, :callback, :callback_context])
|
103
103
|
assert_required_keys(options, [:path])
|
104
|
-
|
104
|
+
|
105
105
|
flags = 0
|
106
106
|
flags |= ZOO_EPHEMERAL if options[:ephemeral]
|
107
107
|
flags |= ZOO_SEQUENCE if options[:sequence]
|
108
108
|
|
109
109
|
options[:acl] ||= ZOO_OPEN_ACL_UNSAFE
|
110
|
-
|
110
|
+
|
111
111
|
req_id = setup_call(options)
|
112
112
|
rc, newpath = super(req_id, options[:path], options[:data], options[:callback], options[:acl], flags)
|
113
|
-
|
113
|
+
|
114
114
|
rv = { :req_id => req_id, :rc => rc }
|
115
|
-
options[:callback] ? rv : rv.merge(:path => newpath)
|
115
|
+
options[:callback] ? rv : rv.merge(:path => newpath)
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
def delete(options = {})
|
119
119
|
assert_open
|
120
120
|
assert_supported_keys(options, [:path, :version, :callback, :callback_context])
|
121
121
|
assert_required_keys(options, [:path])
|
122
122
|
options[:version] ||= -1
|
123
|
-
|
123
|
+
|
124
124
|
req_id = setup_call(options)
|
125
125
|
rc = super(req_id, options[:path], options[:version], options[:callback])
|
126
|
-
|
126
|
+
|
127
127
|
{ :req_id => req_id, :rc => rc }
|
128
128
|
end
|
129
129
|
|
@@ -132,46 +132,55 @@ public
|
|
132
132
|
assert_supported_keys(options, [:path, :acl, :version, :callback, :callback_context])
|
133
133
|
assert_required_keys(options, [:path, :acl])
|
134
134
|
options[:version] ||= -1
|
135
|
-
|
135
|
+
|
136
136
|
req_id = setup_call(options)
|
137
137
|
rc = super(req_id, options[:path], options[:acl], options[:callback], options[:version])
|
138
|
-
|
138
|
+
|
139
139
|
{ :req_id => req_id, :rc => rc }
|
140
140
|
end
|
141
|
-
|
141
|
+
|
142
142
|
def get_acl(options = {})
|
143
143
|
assert_open
|
144
144
|
assert_supported_keys(options, [:path, :callback, :callback_context])
|
145
145
|
assert_required_keys(options, [:path])
|
146
|
-
|
146
|
+
|
147
147
|
req_id = setup_call(options)
|
148
148
|
rc, acls, stat = super(req_id, options[:path], options[:callback])
|
149
|
-
|
149
|
+
|
150
150
|
rv = { :req_id => req_id, :rc => rc }
|
151
151
|
options[:callback] ? rv : rv.merge(:acl => acls, :stat => Stat.new(stat))
|
152
152
|
end
|
153
153
|
|
154
|
+
# To close a Zk handle, first shutdown the dispatcher thread; this is done by
|
155
|
+
# signalling the waiting thread that there is a pending close. We then release
|
156
|
+
# the C-land Zk state.
|
157
|
+
def close
|
158
|
+
signal_pending_close
|
159
|
+
@dispatcher.join
|
160
|
+
super
|
161
|
+
end
|
162
|
+
|
154
163
|
private
|
155
164
|
def setup_dispatch_thread!
|
156
165
|
@dispatcher = Thread.new {
|
157
166
|
while true do
|
158
|
-
|
167
|
+
hash = get_next_event
|
168
|
+
break if hash.nil? # Pending close => exit dispatcher thread
|
169
|
+
dispatch_event(hash)
|
159
170
|
end
|
160
171
|
}
|
161
172
|
end
|
162
173
|
|
163
|
-
def
|
164
|
-
hash = get_next_event
|
165
|
-
|
174
|
+
def dispatch_event(hash)
|
166
175
|
is_completion = hash.has_key?(:rc)
|
167
|
-
|
176
|
+
|
168
177
|
hash[:stat] = Stat.new(hash[:stat]) if hash.has_key?(:stat)
|
169
178
|
hash[:acl] = hash[:acl].map { |acl| ACL.new(acl) } if hash[:acl]
|
170
|
-
|
179
|
+
|
171
180
|
callback_context = is_completion ? get_completion(hash[:req_id]) : get_watcher(hash[:req_id])
|
172
181
|
callback = is_completion ? callback_context[:callback] : callback_context[:watcher]
|
173
182
|
hash[:context] = callback_context[:context]
|
174
|
-
|
183
|
+
|
175
184
|
# TODO: Eventually enforce derivation from Zookeeper::Callback
|
176
185
|
if callback.respond_to?(:call)
|
177
186
|
callback.call(hash)
|
@@ -179,7 +188,7 @@ private
|
|
179
188
|
# puts "dispatch_next_callback found non-callback => #{callback.inspect}"
|
180
189
|
end
|
181
190
|
end
|
182
|
-
|
191
|
+
|
183
192
|
def setup_call(opts)
|
184
193
|
req_id = nil
|
185
194
|
@req_mutex.synchronize {
|
@@ -190,7 +199,7 @@ private
|
|
190
199
|
}
|
191
200
|
req_id
|
192
201
|
end
|
193
|
-
|
202
|
+
|
194
203
|
def setup_watcher(req_id, call_opts)
|
195
204
|
@watcher_reqs[req_id] = { :watcher => call_opts[:watcher],
|
196
205
|
:context => call_opts[:watcher_context] }
|
@@ -200,13 +209,13 @@ private
|
|
200
209
|
@completion_reqs[req_id] = { :callback => call_opts[:callback],
|
201
210
|
:context => call_opts[:callback_context] }
|
202
211
|
end
|
203
|
-
|
212
|
+
|
204
213
|
def get_watcher(req_id)
|
205
214
|
@req_mutex.synchronize {
|
206
215
|
req_id != ZKRB_GLOBAL_CB_REQ ? @watcher_reqs.delete(req_id) : @watcher_reqs[req_id]
|
207
216
|
}
|
208
217
|
end
|
209
|
-
|
218
|
+
|
210
219
|
def get_completion(req_id)
|
211
220
|
@req_mutex.synchronize { @completion_reqs.delete(req_id) }
|
212
221
|
end
|
data/zookeeper.gemspec
CHANGED
@@ -2,21 +2,21 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{zookeeper}
|
5
|
-
s.version = "0.4.
|
5
|
+
s.version = "0.4.4"
|
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.date = %q{2011-
|
9
|
+
s.date = %q{2011-03-30}
|
10
10
|
s.description = %q{An interface to the Zookeeper distributed configuration server.}
|
11
11
|
s.email = %q{}
|
12
12
|
s.extensions = ["ext/extconf.rb"]
|
13
13
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "ext/zookeeper_c.c", "lib/zookeeper.rb"]
|
14
14
|
s.files = ["CHANGELOG", "LICENSE", "README", "Rakefile", "examples/cloud_config.rb", "ext/extconf.rb", "ext/zkc-3.3.2.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", "test/test_basic.rb", "test/test_callback1.rb", "test/test_close.rb", "test/test_esoteric.rb", "test/test_watcher1.rb", "test/test_watcher2.rb", "Manifest", "zookeeper.gemspec"]
|
15
|
-
s.homepage = %q{
|
15
|
+
s.homepage = %q{http://twitter.github.com/twitter/zookeeper/}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Zookeeper", "--main", "README"]
|
17
17
|
s.require_paths = ["lib", "ext"]
|
18
|
-
s.rubyforge_project = %q{
|
19
|
-
s.rubygems_version = %q{1.
|
18
|
+
s.rubyforge_project = %q{twitter}
|
19
|
+
s.rubygems_version = %q{1.6.1}
|
20
20
|
s.summary = %q{An interface to the Zookeeper distributed configuration server.}
|
21
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"]
|
22
22
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zookeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 4
|
10
|
+
version: 0.4.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Phillip Pearson, Eric Maland, Evan Weaver, Brian Wickman
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-03-30 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -57,7 +57,7 @@ files:
|
|
57
57
|
- Manifest
|
58
58
|
- zookeeper.gemspec
|
59
59
|
has_rdoc: true
|
60
|
-
homepage:
|
60
|
+
homepage: http://twitter.github.com/twitter/zookeeper/
|
61
61
|
licenses: []
|
62
62
|
|
63
63
|
post_install_message:
|
@@ -92,8 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
version: "1.2"
|
93
93
|
requirements: []
|
94
94
|
|
95
|
-
rubyforge_project:
|
96
|
-
rubygems_version: 1.
|
95
|
+
rubyforge_project: twitter
|
96
|
+
rubygems_version: 1.6.1
|
97
97
|
signing_key:
|
98
98
|
specification_version: 3
|
99
99
|
summary: An interface to the Zookeeper distributed configuration server.
|