zookeeper 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|