zookeeper 0.4.2 → 0.4.3
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 -0
- data/Rakefile +1 -1
- data/ext/extconf.rb +4 -3
- data/ext/zookeeper_c.c +79 -29
- data/ext/zookeeper_lib.c +97 -38
- data/ext/zookeeper_lib.h +5 -2
- data/lib/zookeeper.rb +0 -2
- data/test/test_basic.rb +1 -4
- data/zookeeper.gemspec +4 -5
- metadata +7 -7
data/CHANGELOG
CHANGED
data/Rakefile
CHANGED
@@ -4,7 +4,7 @@ Echoe.new("zookeeper") do |p|
|
|
4
4
|
p.author = "Phillip Pearson, Eric Maland, Evan Weaver, Brian Wickman"
|
5
5
|
p.project = "fauna"
|
6
6
|
p.summary = "An interface to the Zookeeper distributed configuration server."
|
7
|
-
p.url = "
|
7
|
+
p.url = "https://github.com/twitter/zookeeper"
|
8
8
|
p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
|
9
9
|
p.clean_pattern += ["ext/lib", "ext/include", "ext/c", "ext/bin", "ext/conftest.dSYM"]
|
10
10
|
p.rdoc_pattern = /README|TODO|LICENSE|CHANGELOG|BENCH|COMPAT|zookeeper_c.c|zookeeper.rb/
|
data/ext/extconf.rb
CHANGED
@@ -15,10 +15,11 @@ if ENV['DEBUG']
|
|
15
15
|
puts "Setting debug flags."
|
16
16
|
$CFLAGS << " -O0 -ggdb -DHAVE_DEBUG"
|
17
17
|
$EXTRA_CONF = " --enable-debug"
|
18
|
+
$CFLAGS.gsub!(/ -O[^0] /, ' ')
|
18
19
|
end
|
19
20
|
|
20
21
|
$includes = " -I#{HERE}/include"
|
21
|
-
$libraries = " -L#{HERE}/lib"
|
22
|
+
$libraries = " -L#{HERE}/lib -L#{RbConfig::CONFIG['libdir']}"
|
22
23
|
$CFLAGS = "#{$includes} #{$libraries} #{$CFLAGS}"
|
23
24
|
$LDFLAGS = "#{$libraries} #{$LDFLAGS}"
|
24
25
|
$LIBPATH = ["#{HERE}/lib"]
|
@@ -33,9 +34,9 @@ Dir.chdir(HERE) do
|
|
33
34
|
raise "'#{cmd}' failed" unless system(cmd)
|
34
35
|
|
35
36
|
Dir.chdir(BUNDLE_PATH) do
|
36
|
-
puts(cmd = "env CFLAGS='-fPIC #{$CFLAGS}' LDFLAGS='-fPIC #{$LDFLAGS}' ./configure --prefix=#{HERE} --without-cppunit --disable-dependency-tracking #{$EXTRA_CONF} 2>&1")
|
37
|
+
puts(cmd = "env CC=gcc CXX=g++ CFLAGS='-fPIC #{$CFLAGS}' LDFLAGS='-fPIC #{$LDFLAGS}' ./configure --prefix=#{HERE} --without-cppunit --disable-dependency-tracking #{$EXTRA_CONF} 2>&1")
|
37
38
|
raise "'#{cmd}' failed" unless system(cmd)
|
38
|
-
puts(cmd = "make CXXFLAGS='#{$CXXFLAGS}' || true 2>&1")
|
39
|
+
puts(cmd = "make CXXFLAGS='#{$CXXFLAGS}' CFLAGS='-fPIC #{$CFLAGS}' LDFLAGS='-fPIC #{$LDFLAGS}' || true 2>&1")
|
39
40
|
raise "'#{cmd}' failed" unless system(cmd)
|
40
41
|
puts(cmd = "make install || true 2>&1")
|
41
42
|
raise "'#{cmd}' failed" unless system(cmd)
|
data/ext/zookeeper_c.c
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
#include <errno.h>
|
17
17
|
#include <stdio.h>
|
18
18
|
#include <stdlib.h>
|
19
|
+
#include <unistd.h>
|
19
20
|
|
20
21
|
#include "zookeeper_lib.h"
|
21
22
|
|
@@ -37,21 +38,34 @@ typedef enum {
|
|
37
38
|
#define IS_SYNC(zkrbcall) ((zkrbcall)==SYNC || (zkrbcall)==SYNC_WATCH)
|
38
39
|
#define IS_ASYNC(zkrbcall) ((zkrbcall)==ASYNC || (zkrbcall)==ASYNC_WATCH)
|
39
40
|
|
40
|
-
static
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
static int destroy_zkrb_instance(struct zkrb_instance_data* ptr) {
|
42
|
+
int rv = ZOK;
|
43
|
+
|
44
|
+
if (ptr->zh) {
|
45
|
+
const void *ctx = zoo_get_context(ptr->zh);
|
46
|
+
/* Note that after zookeeper_close() returns, ZK handle is invalid */
|
47
|
+
rv = zookeeper_close(ptr->zh);
|
48
|
+
free((void *) ctx);
|
44
49
|
}
|
50
|
+
|
51
|
+
#warning [wickman] TODO: fire off warning if queue is not empty
|
45
52
|
if (ptr->queue) zkrb_queue_free(ptr->queue);
|
53
|
+
|
54
|
+
ptr->zh = NULL;
|
46
55
|
ptr->queue = NULL;
|
56
|
+
return rv;
|
57
|
+
}
|
58
|
+
|
59
|
+
static void free_zkrb_instance_data(struct zkrb_instance_data* ptr) {
|
60
|
+
destroy_zkrb_instance(ptr);
|
47
61
|
}
|
48
62
|
|
49
63
|
static void print_zkrb_instance_data(struct zkrb_instance_data* ptr) {
|
50
|
-
fprintf(stderr, "zkrb_instance_data (%
|
51
|
-
fprintf(stderr, " zh = %
|
64
|
+
fprintf(stderr, "zkrb_instance_data (%p) {\n", ptr);
|
65
|
+
fprintf(stderr, " zh = %p\n", ptr->zh);
|
52
66
|
fprintf(stderr, " { state = %d }\n", zoo_state(ptr->zh));
|
53
67
|
fprintf(stderr, " id = %llx\n", ptr->myid.client_id);
|
54
|
-
fprintf(stderr, " q = %
|
68
|
+
fprintf(stderr, " q = %p\n", ptr->queue);
|
55
69
|
fprintf(stderr, "}\n");
|
56
70
|
}
|
57
71
|
|
@@ -78,7 +92,7 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
|
78
92
|
}
|
79
93
|
|
80
94
|
VALUE data;
|
81
|
-
struct zkrb_instance_data *zk_local_ctx
|
95
|
+
struct zkrb_instance_data *zk_local_ctx;
|
82
96
|
data = Data_Make_Struct(Zookeeper,
|
83
97
|
struct zkrb_instance_data,
|
84
98
|
0,
|
@@ -110,9 +124,11 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
|
110
124
|
return Qnil;
|
111
125
|
}
|
112
126
|
|
113
|
-
#define FETCH_DATA_PTR(x, y)
|
114
|
-
struct zkrb_instance_data * y;
|
115
|
-
Data_Get_Struct(rb_iv_get(x, "@data"), struct zkrb_instance_data, y)
|
127
|
+
#define FETCH_DATA_PTR(x, y) \
|
128
|
+
struct zkrb_instance_data * y; \
|
129
|
+
Data_Get_Struct(rb_iv_get(x, "@data"), struct zkrb_instance_data, y); \
|
130
|
+
if ((y)->zh == NULL) \
|
131
|
+
rb_raise(rb_eRuntimeError, "zookeeper handle is closed")
|
116
132
|
|
117
133
|
#define STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, cb_ctx, w_ctx, call_type) \
|
118
134
|
if (TYPE(reqid) != T_FIXNUM && TYPE(reqid) != T_BIGNUM) { \
|
@@ -122,6 +138,8 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
|
122
138
|
Check_Type(path, T_STRING); \
|
123
139
|
struct zkrb_instance_data * zk; \
|
124
140
|
Data_Get_Struct(rb_iv_get(self, "@data"), struct zkrb_instance_data, zk); \
|
141
|
+
if (!zk->zh) \
|
142
|
+
rb_raise(rb_eRuntimeError, "zookeeper handle is closed"); \
|
125
143
|
zkrb_calling_context* cb_ctx = \
|
126
144
|
(async != Qfalse && async != Qnil) ? \
|
127
145
|
zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
|
@@ -206,7 +224,6 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
|
|
206
224
|
VALUE watch = Qfalse;
|
207
225
|
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
208
226
|
|
209
|
-
struct Stat stat;
|
210
227
|
if (data != Qnil) Check_Type(data, T_STRING);
|
211
228
|
Check_Type(flags, T_FIXNUM);
|
212
229
|
const char *data_ptr = (data == Qnil) ? NULL : RSTRING_PTR(data);
|
@@ -220,11 +237,9 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
|
|
220
237
|
switch (call_type) {
|
221
238
|
case SYNC:
|
222
239
|
rc = zoo_create(zk->zh, RSTRING_PTR(path), data_ptr, data_len, aclptr, FIX2INT(flags), realpath, sizeof(realpath));
|
223
|
-
if (aclptr != NULL) deallocate_ACL_vector(aclptr);
|
224
240
|
break;
|
225
241
|
case ASYNC:
|
226
242
|
rc = zoo_acreate(zk->zh, RSTRING_PTR(path), data_ptr, data_len, aclptr, FIX2INT(flags), zkrb_string_callback, data_ctx);
|
227
|
-
if (aclptr != NULL) deallocate_ACL_vector(aclptr);
|
228
243
|
break;
|
229
244
|
default:
|
230
245
|
/* TODO(wickman) raise proper argument error */
|
@@ -232,6 +247,11 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
|
|
232
247
|
break;
|
233
248
|
}
|
234
249
|
|
250
|
+
if (aclptr) {
|
251
|
+
deallocate_ACL_vector(aclptr);
|
252
|
+
free(aclptr);
|
253
|
+
}
|
254
|
+
|
235
255
|
VALUE output = rb_ary_new();
|
236
256
|
rb_ary_push(output, INT2FIX(rc));
|
237
257
|
if (IS_SYNC(call_type) && rc == ZOK) {
|
@@ -295,7 +315,10 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
|
|
295
315
|
VALUE output = rb_ary_new();
|
296
316
|
rb_ary_push(output, INT2FIX(rc));
|
297
317
|
if (IS_SYNC(call_type) && rc == ZOK) {
|
298
|
-
|
318
|
+
if (data_len == -1)
|
319
|
+
rb_ary_push(output, Qnil); /* No data associated with path */
|
320
|
+
else
|
321
|
+
rb_ary_push(output, rb_str_new(data, data_len));
|
299
322
|
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
300
323
|
}
|
301
324
|
free(data);
|
@@ -344,11 +367,9 @@ static VALUE method_set_acl(VALUE self, VALUE reqid, VALUE path, VALUE acls, VAL
|
|
344
367
|
switch (call_type) {
|
345
368
|
case SYNC:
|
346
369
|
rc = zoo_set_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr);
|
347
|
-
deallocate_ACL_vector(aclptr);
|
348
370
|
break;
|
349
371
|
case ASYNC:
|
350
372
|
rc = zoo_aset_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr, zkrb_void_callback, data_ctx);
|
351
|
-
deallocate_ACL_vector(aclptr);
|
352
373
|
break;
|
353
374
|
default:
|
354
375
|
/* TODO(wickman) raise proper argument error */
|
@@ -356,6 +377,9 @@ static VALUE method_set_acl(VALUE self, VALUE reqid, VALUE path, VALUE acls, VAL
|
|
356
377
|
break;
|
357
378
|
}
|
358
379
|
|
380
|
+
deallocate_ACL_vector(aclptr);
|
381
|
+
free(aclptr);
|
382
|
+
|
359
383
|
return INT2FIX(rc);
|
360
384
|
}
|
361
385
|
|
@@ -380,32 +404,57 @@ static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
|
|
380
404
|
break;
|
381
405
|
}
|
382
406
|
|
383
|
-
// do we need to deallocate the strings in the acl vector????
|
384
407
|
VALUE output = rb_ary_new();
|
385
408
|
rb_ary_push(output, INT2FIX(rc));
|
386
409
|
if (IS_SYNC(call_type) && rc == ZOK) {
|
387
410
|
rb_ary_push(output, zkrb_acl_vector_to_ruby(&acls));
|
388
411
|
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
412
|
+
deallocate_ACL_vector(&acls);
|
389
413
|
}
|
390
414
|
return output;
|
391
415
|
}
|
392
416
|
|
393
417
|
static VALUE method_get_next_event(VALUE self) {
|
418
|
+
char buf[64];
|
394
419
|
FETCH_DATA_PTR(self, zk);
|
395
|
-
if (zk->queue == NULL) return Qnil;
|
396
|
-
|
397
|
-
zkrb_event_t *event = zkrb_dequeue(zk->queue);
|
398
|
-
if (event == NULL) return Qnil;
|
399
420
|
|
400
|
-
|
401
|
-
|
402
|
-
|
421
|
+
for (;;) {
|
422
|
+
zkrb_event_t *event = zkrb_dequeue(zk->queue, 1);
|
423
|
+
|
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
|
+
*/
|
430
|
+
if (event == NULL) {
|
431
|
+
int fd = zk->queue->pipe_read;
|
432
|
+
fd_set rset;
|
433
|
+
|
434
|
+
FD_ZERO(&rset);
|
435
|
+
FD_SET(fd, &rset);
|
436
|
+
|
437
|
+
if (rb_thread_select(fd + 1, &rset, NULL, NULL, NULL) == -1)
|
438
|
+
rb_raise(rb_eRuntimeError, "select failed: %d", errno);
|
439
|
+
|
440
|
+
if (read(fd, buf, sizeof(buf)) == -1)
|
441
|
+
rb_raise(rb_eRuntimeError, "read failed: %d", errno);
|
442
|
+
|
443
|
+
continue;
|
444
|
+
}
|
445
|
+
|
446
|
+
VALUE hash = zkrb_event_to_ruby(event);
|
447
|
+
zkrb_event_free(event);
|
448
|
+
return hash;
|
449
|
+
}
|
403
450
|
}
|
404
451
|
|
405
452
|
static VALUE method_has_events(VALUE self) {
|
453
|
+
VALUE rb_event;
|
406
454
|
FETCH_DATA_PTR(self, zk);
|
407
|
-
|
408
|
-
|
455
|
+
|
456
|
+
rb_event = zkrb_peek(zk->queue) != NULL ? Qtrue : Qfalse;
|
457
|
+
return rb_event;
|
409
458
|
}
|
410
459
|
|
411
460
|
static VALUE method_client_id(VALUE self) {
|
@@ -416,7 +465,9 @@ static VALUE method_client_id(VALUE self) {
|
|
416
465
|
|
417
466
|
static VALUE method_close(VALUE self) {
|
418
467
|
FETCH_DATA_PTR(self, zk);
|
419
|
-
|
468
|
+
|
469
|
+
/* Note that after zookeeper_close() returns, ZK handle is invalid */
|
470
|
+
int rc = destroy_zkrb_instance(zk);
|
420
471
|
return INT2FIX(rc);
|
421
472
|
}
|
422
473
|
|
@@ -487,7 +538,6 @@ static void zkrb_define_methods(void) {
|
|
487
538
|
}
|
488
539
|
void Init_zookeeper_c() {
|
489
540
|
ZKRBDebugging = 0;
|
490
|
-
|
491
541
|
/* initialize Zookeeper class */
|
492
542
|
Zookeeper = rb_define_class("CZookeeper", rb_cObject);
|
493
543
|
zkrb_define_methods();
|
data/ext/zookeeper_lib.c
CHANGED
@@ -14,58 +14,98 @@ wickman@twitter.com
|
|
14
14
|
#include <errno.h>
|
15
15
|
#include <stdio.h>
|
16
16
|
#include <stdlib.h>
|
17
|
+
#include <pthread.h>
|
18
|
+
#include <unistd.h>
|
17
19
|
|
18
20
|
#define GET_SYM(str) ID2SYM(rb_intern(str))
|
19
21
|
|
20
22
|
int ZKRBDebugging;
|
21
23
|
|
24
|
+
pthread_mutex_t zkrb_q_mutex = PTHREAD_MUTEX_INITIALIZER;
|
25
|
+
|
22
26
|
/* push/pop is a misnomer, this is a queue */
|
23
|
-
#warning [wickman] TODO enqueue, peek, dequeue => pthread_mutex_lock
|
24
27
|
void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
|
28
|
+
pthread_mutex_lock(&zkrb_q_mutex);
|
29
|
+
if (q == NULL || q->tail == NULL) {
|
30
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
31
|
+
return;
|
32
|
+
}
|
25
33
|
q->tail->event = elt;
|
26
34
|
q->tail->next = (struct zkrb_event_ll_t *) malloc(sizeof(struct zkrb_event_ll_t));
|
27
35
|
q->tail = q->tail->next;
|
28
36
|
q->tail->event = NULL;
|
29
37
|
q->tail->next = NULL;
|
38
|
+
ssize_t ret = write(q->pipe_write, "0", 1); /* Wake up Ruby listener */
|
39
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
40
|
+
if (ret == -1)
|
41
|
+
rb_raise(rb_eRuntimeError, "write to pipe failed: %d", errno);
|
30
42
|
}
|
31
43
|
|
32
44
|
zkrb_event_t * zkrb_peek(zkrb_queue_t *q) {
|
33
|
-
|
34
|
-
|
35
|
-
|
45
|
+
pthread_mutex_lock(&zkrb_q_mutex);
|
46
|
+
zkrb_event_t *event = NULL;
|
47
|
+
if (q != NULL && q->head != NULL && q->head->event != NULL) {
|
48
|
+
event = q->head->event;
|
49
|
+
}
|
50
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
51
|
+
return event;
|
36
52
|
}
|
37
53
|
|
38
|
-
zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q) {
|
39
|
-
if (
|
54
|
+
zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q, int need_lock) {
|
55
|
+
if (need_lock)
|
56
|
+
pthread_mutex_lock(&zkrb_q_mutex);
|
57
|
+
if (q == NULL || q->head == NULL || q->head->event == NULL) {
|
58
|
+
if (need_lock)
|
59
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
40
60
|
return NULL;
|
41
61
|
} else {
|
42
62
|
struct zkrb_event_ll_t *old_root = q->head;
|
43
63
|
q->head = q->head->next;
|
44
64
|
zkrb_event_t *rv = old_root->event;
|
45
65
|
free(old_root);
|
66
|
+
if (need_lock)
|
67
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
46
68
|
return rv;
|
47
69
|
}
|
48
70
|
}
|
49
71
|
|
50
72
|
zkrb_queue_t *zkrb_queue_alloc(void) {
|
73
|
+
int pfd[2];
|
74
|
+
if (pipe(pfd) == -1)
|
75
|
+
rb_raise(rb_eRuntimeError, "create of pipe failed: %d", errno);
|
76
|
+
|
77
|
+
pthread_mutex_lock(&zkrb_q_mutex);
|
51
78
|
zkrb_queue_t *rq = malloc(sizeof(zkrb_queue_t));
|
52
79
|
rq->head = malloc(sizeof(struct zkrb_event_ll_t));
|
53
80
|
rq->head->event = NULL; rq->head->next = NULL;
|
54
81
|
rq->tail = rq->head;
|
82
|
+
rq->pipe_read = pfd[0];
|
83
|
+
rq->pipe_write = pfd[1];
|
84
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
85
|
+
|
55
86
|
return rq;
|
56
87
|
}
|
57
88
|
|
58
89
|
void zkrb_queue_free(zkrb_queue_t *queue) {
|
59
|
-
|
60
|
-
|
61
|
-
|
90
|
+
pthread_mutex_lock(&zkrb_q_mutex);
|
91
|
+
if (queue == NULL) {
|
92
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
|
96
|
+
zkrb_event_t *elt;
|
97
|
+
while ((elt = zkrb_dequeue(queue, 0)) != NULL) {
|
62
98
|
zkrb_event_free(elt);
|
63
99
|
}
|
100
|
+
free(queue->head);
|
101
|
+
close(queue->pipe_read);
|
102
|
+
close(queue->pipe_write);
|
64
103
|
free(queue);
|
104
|
+
pthread_mutex_unlock(&zkrb_q_mutex);
|
65
105
|
}
|
66
106
|
|
67
107
|
zkrb_event_t *zkrb_event_alloc(void) {
|
68
|
-
zkrb_event_t *rv
|
108
|
+
zkrb_event_t *rv = (zkrb_event_t *) malloc(sizeof(zkrb_event_t));
|
69
109
|
return rv;
|
70
110
|
}
|
71
111
|
|
@@ -75,16 +115,19 @@ void zkrb_event_free(zkrb_event_t *event) {
|
|
75
115
|
struct zkrb_data_completion *data_ctx = event->completion.data_completion;
|
76
116
|
free(data_ctx->data);
|
77
117
|
free(data_ctx->stat);
|
118
|
+
free(data_ctx);
|
78
119
|
break;
|
79
120
|
}
|
80
121
|
case ZKRB_STAT: {
|
81
122
|
struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
|
82
123
|
free(stat_ctx->stat);
|
124
|
+
free(stat_ctx);
|
83
125
|
break;
|
84
126
|
}
|
85
127
|
case ZKRB_STRING: {
|
86
128
|
struct zkrb_string_completion *string_ctx = event->completion.string_completion;
|
87
129
|
free(string_ctx->value);
|
130
|
+
free(string_ctx);
|
88
131
|
break;
|
89
132
|
}
|
90
133
|
case ZKRB_STRINGS: {
|
@@ -92,6 +135,7 @@ void zkrb_event_free(zkrb_event_t *event) {
|
|
92
135
|
int k;
|
93
136
|
for (k = 0; k < strings_ctx->values->count; ++k) free(strings_ctx->values->data[k]);
|
94
137
|
free(strings_ctx->values);
|
138
|
+
free(strings_ctx);
|
95
139
|
break;
|
96
140
|
}
|
97
141
|
case ZKRB_STRINGS_STAT: {
|
@@ -100,6 +144,7 @@ void zkrb_event_free(zkrb_event_t *event) {
|
|
100
144
|
for (k = 0; k < strings_stat_ctx->values->count; ++k) free(strings_stat_ctx->values->data[k]);
|
101
145
|
free(strings_stat_ctx->values);
|
102
146
|
free(strings_stat_ctx->stat);
|
147
|
+
free(strings_stat_ctx);
|
103
148
|
break;
|
104
149
|
}
|
105
150
|
case ZKRB_ACL: {
|
@@ -109,11 +154,13 @@ void zkrb_event_free(zkrb_event_t *event) {
|
|
109
154
|
free(acl_ctx->acl);
|
110
155
|
}
|
111
156
|
free(acl_ctx->stat);
|
157
|
+
free(acl_ctx);
|
112
158
|
break;
|
113
159
|
}
|
114
160
|
case ZKRB_WATCHER: {
|
115
161
|
struct zkrb_watcher_completion *watcher_ctx = event->completion.watcher_completion;
|
116
162
|
free(watcher_ctx->path);
|
163
|
+
free(watcher_ctx);
|
117
164
|
break;
|
118
165
|
}
|
119
166
|
case ZKRB_VOID: {
|
@@ -214,30 +261,33 @@ zkrb_calling_context *zkrb_calling_context_alloc(int64_t req_id, zkrb_queue_t *q
|
|
214
261
|
}
|
215
262
|
|
216
263
|
void zkrb_print_calling_context(zkrb_calling_context *ctx) {
|
217
|
-
fprintf(stderr, "calling context (
|
264
|
+
fprintf(stderr, "calling context (%p){\n", ctx);
|
218
265
|
fprintf(stderr, "\treq_id = %lld\n", ctx->req_id);
|
219
|
-
fprintf(stderr, "\tqueue =
|
266
|
+
fprintf(stderr, "\tqueue = %p\n", ctx->queue);
|
220
267
|
fprintf(stderr, "}\n");
|
221
268
|
}
|
222
269
|
|
223
270
|
/*
|
224
271
|
process completions that get queued to the watcher queue, translate events
|
225
272
|
to completions that the ruby side dispatches via callbacks.
|
273
|
+
|
274
|
+
The calling_ctx can be thought of as the outer shell that we discard in
|
275
|
+
this macro after pulling out the gooey delicious center.
|
226
276
|
*/
|
227
277
|
|
228
278
|
#define ZKH_SETUP_EVENT(qptr, eptr) \
|
229
279
|
zkrb_calling_context *ctx = (zkrb_calling_context *) calling_ctx; \
|
230
|
-
zkrb_event_t *eptr = zkrb_event_alloc();
|
280
|
+
zkrb_event_t *eptr = zkrb_event_alloc(); \
|
231
281
|
eptr->req_id = ctx->req_id; \
|
232
|
-
|
233
|
-
|
282
|
+
zkrb_queue_t *qptr = ctx->queue; \
|
283
|
+
if (eptr->req_id != ZKRB_GLOBAL_REQ) free(ctx)
|
234
284
|
|
235
285
|
void zkrb_state_callback(
|
236
286
|
zhandle_t *zh, int type, int state, const char *path, void *calling_ctx) {
|
237
287
|
/* logging */
|
238
288
|
if (ZKRBDebugging) {
|
239
289
|
fprintf(stderr, "ZOOKEEPER_C_STATE WATCHER "
|
240
|
-
"type = %d, state = %d, path =
|
290
|
+
"type = %d, state = %d, path = %p, value = %s\n",
|
241
291
|
type, state, (void *) path, path ? path : "NULL");
|
242
292
|
}
|
243
293
|
|
@@ -245,13 +295,22 @@ void zkrb_state_callback(
|
|
245
295
|
struct zkrb_watcher_completion *wc = malloc(sizeof(struct zkrb_watcher_completion));
|
246
296
|
wc->type = type;
|
247
297
|
wc->state = state;
|
248
|
-
wc->path =
|
249
|
-
|
298
|
+
wc->path = strdup(path);
|
299
|
+
|
300
|
+
// This is unfortunate copy-pasta from ZKH_SETUP_EVENT with one change: we
|
301
|
+
// check type instead of the req_id to see if we need to free the ctx.
|
302
|
+
zkrb_calling_context *ctx = (zkrb_calling_context *) calling_ctx;
|
303
|
+
zkrb_event_t *event = zkrb_event_alloc();
|
304
|
+
event->req_id = ctx->req_id;
|
305
|
+
zkrb_queue_t *queue = ctx->queue;
|
306
|
+
if (type != ZOO_SESSION_EVENT) {
|
307
|
+
free(ctx);
|
308
|
+
ctx = NULL;
|
309
|
+
}
|
250
310
|
|
251
|
-
ZKH_SETUP_EVENT(queue, event);
|
252
311
|
event->type = ZKRB_WATCHER;
|
253
312
|
event->completion.watcher_completion = wc;
|
254
|
-
|
313
|
+
|
255
314
|
zkrb_enqueue(queue, event);
|
256
315
|
}
|
257
316
|
|
@@ -267,7 +326,8 @@ void zkrb_data_callback(
|
|
267
326
|
|
268
327
|
/* copy data completion */
|
269
328
|
struct zkrb_data_completion *dc = malloc(sizeof(struct zkrb_data_completion));
|
270
|
-
dc->data =
|
329
|
+
dc->data = NULL;
|
330
|
+
dc->stat = NULL;
|
271
331
|
if (value != NULL) { dc->data = malloc(value_len); memcpy(dc->data, value, value_len); }
|
272
332
|
if (stat != NULL) { dc->stat = malloc(sizeof(struct Stat)); memcpy(dc->stat, stat, sizeof(struct Stat)); }
|
273
333
|
|
@@ -307,7 +367,8 @@ void zkrb_string_callback(
|
|
307
367
|
|
308
368
|
struct zkrb_string_completion *sc = malloc(sizeof(struct zkrb_string_completion));
|
309
369
|
sc->value = NULL;
|
310
|
-
if (string
|
370
|
+
if (string)
|
371
|
+
sc->value = strdup(string);
|
311
372
|
|
312
373
|
ZKH_SETUP_EVENT(queue, event);
|
313
374
|
event->rc = rc;
|
@@ -321,7 +382,7 @@ void zkrb_strings_callback(
|
|
321
382
|
int rc, const struct String_vector *strings, const void *calling_ctx) {
|
322
383
|
if (ZKRBDebugging) {
|
323
384
|
fprintf(stderr, "ZOOKEEPER_C_STRINGS WATCHER "
|
324
|
-
"rc = %d (%s), calling_ctx =
|
385
|
+
"rc = %d (%s), calling_ctx = %p\n", rc, zerror(rc), calling_ctx);
|
325
386
|
}
|
326
387
|
|
327
388
|
/* copy string vector */
|
@@ -340,7 +401,7 @@ void zkrb_strings_stat_callback(
|
|
340
401
|
int rc, const struct String_vector *strings, const struct Stat *stat, const void *calling_ctx) {
|
341
402
|
if (ZKRBDebugging) {
|
342
403
|
fprintf(stderr, "ZOOKEEPER_C_STRINGS_STAT WATCHER "
|
343
|
-
"rc = %d (%s), calling_ctx =
|
404
|
+
"rc = %d (%s), calling_ctx = %p\n", rc, zerror(rc), calling_ctx);
|
344
405
|
}
|
345
406
|
|
346
407
|
struct zkrb_strings_stat_completion *sc = malloc(sizeof(struct zkrb_strings_stat_completion));
|
@@ -351,7 +412,7 @@ void zkrb_strings_stat_callback(
|
|
351
412
|
ZKH_SETUP_EVENT(queue, event);
|
352
413
|
event->rc = rc;
|
353
414
|
event->type = ZKRB_STRINGS_STAT;
|
354
|
-
event->completion.
|
415
|
+
event->completion.strings_stat_completion = sc;
|
355
416
|
|
356
417
|
zkrb_enqueue(queue, event);
|
357
418
|
}
|
@@ -379,7 +440,8 @@ void zkrb_acl_callback(
|
|
379
440
|
}
|
380
441
|
|
381
442
|
struct zkrb_acl_completion *ac = malloc(sizeof(struct zkrb_acl_completion));
|
382
|
-
ac->acl =
|
443
|
+
ac->acl = NULL;
|
444
|
+
ac->stat = NULL;
|
383
445
|
if (acls != NULL) { ac->acl = zkrb_clone_acl_vector(acls); }
|
384
446
|
if (stat != NULL) { ac->stat = malloc(sizeof(struct Stat)); memcpy(ac->stat, stat, sizeof(struct Stat)); }
|
385
447
|
|
@@ -450,7 +512,7 @@ struct Id zkrb_ruby_to_id(VALUE rubyid) {
|
|
450
512
|
}
|
451
513
|
|
452
514
|
if (ident != Qnil) {
|
453
|
-
id.id
|
515
|
+
id.id = malloc(RSTRING_LEN(ident) + 1);
|
454
516
|
strncpy(id.id, RSTRING_PTR(ident), RSTRING_LEN(ident));
|
455
517
|
id.id[RSTRING_LEN(ident)] = '\0';
|
456
518
|
} else {
|
@@ -461,8 +523,8 @@ struct Id zkrb_ruby_to_id(VALUE rubyid) {
|
|
461
523
|
}
|
462
524
|
|
463
525
|
VALUE zkrb_acl_vector_to_ruby(struct ACL_vector *acl_vector) {
|
464
|
-
int i
|
465
|
-
VALUE ary =
|
526
|
+
int i;
|
527
|
+
VALUE ary = rb_ary_new2(acl_vector->count);
|
466
528
|
for(i = 0; i < acl_vector->count; i++) {
|
467
529
|
rb_ary_push(ary, zkrb_acl_to_ruby(acl_vector->data+i));
|
468
530
|
}
|
@@ -470,8 +532,8 @@ VALUE zkrb_acl_vector_to_ruby(struct ACL_vector *acl_vector) {
|
|
470
532
|
}
|
471
533
|
|
472
534
|
VALUE zkrb_string_vector_to_ruby(struct String_vector *string_vector) {
|
473
|
-
int i
|
474
|
-
VALUE ary =
|
535
|
+
int i;
|
536
|
+
VALUE ary = rb_ary_new2(string_vector->count);
|
475
537
|
for(i = 0; i < string_vector->count; i++) {
|
476
538
|
rb_ary_push(ary, rb_str_new2(string_vector->data[i]));
|
477
539
|
}
|
@@ -516,23 +578,20 @@ struct ACL_vector * zkrb_clone_acl_vector(struct ACL_vector * src) {
|
|
516
578
|
int k;
|
517
579
|
for (k = 0; k < src->count; ++k) {
|
518
580
|
struct ACL * elt = &src->data[k];
|
519
|
-
dst->data[k].id.scheme =
|
520
|
-
dst->data[k].id.id =
|
521
|
-
strcpy(dst->data[k].id.scheme, elt->id.scheme);
|
522
|
-
strcpy(dst->data[k].id.id, elt->id.id);
|
581
|
+
dst->data[k].id.scheme = strdup(elt->id.scheme);
|
582
|
+
dst->data[k].id.id = strdup(elt->id.id);
|
523
583
|
dst->data[k].perms = elt->perms;
|
524
584
|
}
|
525
585
|
return dst;
|
526
586
|
}
|
527
587
|
|
528
588
|
#warning [wickman] TODO test zkrb_clone_string_vector
|
529
|
-
struct String_vector * zkrb_clone_string_vector(struct String_vector * src) {
|
589
|
+
struct String_vector * zkrb_clone_string_vector(const struct String_vector * src) {
|
530
590
|
struct String_vector * dst = malloc(sizeof(struct String_vector));
|
531
591
|
allocate_String_vector(dst, src->count);
|
532
592
|
int k;
|
533
593
|
for (k = 0; k < src->count; ++k) {
|
534
|
-
dst->data[k] =
|
535
|
-
strcpy(dst->data[k], src->data[k]);
|
594
|
+
dst->data[k] = strdup(src->data[k]);
|
536
595
|
}
|
537
596
|
return dst;
|
538
597
|
}
|
data/ext/zookeeper_lib.h
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
#endif
|
23
23
|
|
24
24
|
extern int ZKRBDebugging;
|
25
|
+
extern pthread_mutex_t zkrb_q_mutex;
|
25
26
|
|
26
27
|
struct zkrb_data_completion {
|
27
28
|
char *data;
|
@@ -94,6 +95,8 @@ struct zkrb_event_ll_t {
|
|
94
95
|
typedef struct {
|
95
96
|
struct zkrb_event_ll_t *head;
|
96
97
|
struct zkrb_event_ll_t *tail;
|
98
|
+
int pipe_read;
|
99
|
+
int pipe_write;
|
97
100
|
} zkrb_queue_t;
|
98
101
|
|
99
102
|
zkrb_queue_t * zkrb_queue_alloc(void);
|
@@ -104,7 +107,7 @@ void zkrb_event_free(zkrb_event_t *ptr);
|
|
104
107
|
/* push/pop is a misnomer, this is a queue */
|
105
108
|
void zkrb_enqueue(zkrb_queue_t *queue, zkrb_event_t *elt);
|
106
109
|
zkrb_event_t * zkrb_peek(zkrb_queue_t *queue);
|
107
|
-
zkrb_event_t * zkrb_dequeue(zkrb_queue_t *queue);
|
110
|
+
zkrb_event_t * zkrb_dequeue(zkrb_queue_t *queue, int need_lock);
|
108
111
|
|
109
112
|
void zkrb_print_stat(const struct Stat *s);
|
110
113
|
|
@@ -154,7 +157,7 @@ VALUE zkrb_stat_to_rhash(const struct Stat* stat);
|
|
154
157
|
|
155
158
|
struct ACL_vector * zkrb_ruby_to_aclvector(VALUE acl_ary);
|
156
159
|
struct ACL_vector * zkrb_clone_acl_vector(struct ACL_vector * src);
|
157
|
-
struct String_vector * zkrb_clone_string_vector(struct String_vector * src);
|
160
|
+
struct String_vector * zkrb_clone_string_vector(const struct String_vector * src);
|
158
161
|
struct ACL zkrb_ruby_to_acl(VALUE rubyacl);
|
159
162
|
struct Id zkrb_ruby_to_id(VALUE rubyid);
|
160
163
|
|
data/lib/zookeeper.rb
CHANGED
@@ -156,14 +156,12 @@ private
|
|
156
156
|
@dispatcher = Thread.new {
|
157
157
|
while true do
|
158
158
|
dispatch_next_callback
|
159
|
-
sleep 0.1
|
160
159
|
end
|
161
160
|
}
|
162
161
|
end
|
163
162
|
|
164
163
|
def dispatch_next_callback
|
165
164
|
hash = get_next_event
|
166
|
-
return nil unless hash
|
167
165
|
|
168
166
|
is_completion = hash.has_key?(:rc)
|
169
167
|
|
data/test/test_basic.rb
CHANGED
data/zookeeper.gemspec
CHANGED
@@ -2,26 +2,25 @@
|
|
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.3"
|
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-02-09}
|
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{https://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
18
|
s.rubyforge_project = %q{fauna}
|
19
|
-
s.rubygems_version = %q{1.
|
19
|
+
s.rubygems_version = %q{1.5.0}
|
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
|
|
23
23
|
if s.respond_to? :specification_version then
|
24
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
24
|
s.specification_version = 3
|
26
25
|
|
27
26
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
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:
|
5
|
-
prerelease:
|
4
|
+
hash: 9
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 3
|
10
|
+
version: 0.4.3
|
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-02-09 00:00:00 -08: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: https://github.com/twitter/zookeeper
|
61
61
|
licenses: []
|
62
62
|
|
63
63
|
post_install_message:
|
@@ -93,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements: []
|
94
94
|
|
95
95
|
rubyforge_project: fauna
|
96
|
-
rubygems_version: 1.
|
96
|
+
rubygems_version: 1.5.0
|
97
97
|
signing_key:
|
98
98
|
specification_version: 3
|
99
99
|
summary: An interface to the Zookeeper distributed configuration server.
|