slyphon-zookeeper 0.1.7-java → 0.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/ext/zookeeper_base.rb +46 -16
- data/ext/zookeeper_c.c +99 -16
- data/ext/zookeeper_lib.c +23 -7
- data/java/zookeeper_base.rb +154 -37
- data/lib/zookeeper/common.rb +7 -21
- data/lib/zookeeper/em_client.rb +135 -0
- data/lib/zookeeper.rb +72 -1
- data/slyphon-zookeeper.gemspec +2 -2
- data/spec/em_spec.rb +138 -0
- data/spec/spec_helper.rb +19 -0
- metadata +141 -107
data/.gitignore
CHANGED
data/ext/zookeeper_base.rb
CHANGED
@@ -16,7 +16,8 @@ class ZookeeperBase < CZookeeper
|
|
16
16
|
ZOO_LOG_LEVEL_WARN = 2
|
17
17
|
ZOO_LOG_LEVEL_INFO = 3
|
18
18
|
ZOO_LOG_LEVEL_DEBUG = 4
|
19
|
-
|
19
|
+
|
20
|
+
|
20
21
|
def reopen(timeout = 10, watcher=nil)
|
21
22
|
watcher ||= @default_watcher
|
22
23
|
|
@@ -26,13 +27,15 @@ class ZookeeperBase < CZookeeper
|
|
26
27
|
set_default_global_watcher(&watcher)
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
@start_stop_mutex.synchronize do
|
31
|
+
init(@host)
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
if timeout > 0
|
34
|
+
time_to_stop = Time.now + timeout
|
35
|
+
until state == Zookeeper::ZOO_CONNECTED_STATE
|
36
|
+
break if Time.now > time_to_stop
|
37
|
+
sleep 0.1
|
38
|
+
end
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
@@ -46,9 +49,12 @@ class ZookeeperBase < CZookeeper
|
|
46
49
|
@current_req_id = 1
|
47
50
|
@host = host
|
48
51
|
|
52
|
+
@start_stop_mutex = Mutex.new
|
53
|
+
|
49
54
|
watcher ||= get_default_global_watcher
|
50
55
|
|
51
|
-
@_running = nil
|
56
|
+
@_running = nil # used by the C layer
|
57
|
+
@_closed = false # also used by the C layer
|
52
58
|
|
53
59
|
yield self if block_given?
|
54
60
|
|
@@ -76,12 +82,32 @@ class ZookeeperBase < CZookeeper
|
|
76
82
|
end
|
77
83
|
|
78
84
|
def close
|
79
|
-
@
|
80
|
-
|
81
|
-
|
82
|
-
|
85
|
+
@start_stop_mutex.synchronize do
|
86
|
+
@_running = false if @_running
|
87
|
+
end
|
88
|
+
|
89
|
+
if @dispatcher
|
90
|
+
wake_event_loop! unless @_closed
|
91
|
+
@dispatcher.join
|
92
|
+
end
|
93
|
+
|
94
|
+
@start_stop_mutex.synchronize do
|
95
|
+
unless @_closed
|
96
|
+
close_handle
|
97
|
+
|
98
|
+
# this is set up in the C init method, but it's easier to
|
99
|
+
# do the teardown here
|
100
|
+
begin
|
101
|
+
@selectable_io.close if @selectable_io
|
102
|
+
rescue IOError
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
83
107
|
|
84
|
-
|
108
|
+
def set_debug_level(int)
|
109
|
+
warn "DEPRECATION WARNING: #{self.class.name}#set_debug_level, it has moved to the class level and will be removed in a future release"
|
110
|
+
self.class.set_debug_level(int)
|
85
111
|
end
|
86
112
|
|
87
113
|
# set the watcher object/proc that will receive all global events (such as session/state events)
|
@@ -92,16 +118,20 @@ class ZookeeperBase < CZookeeper
|
|
92
118
|
end
|
93
119
|
end
|
94
120
|
|
95
|
-
|
121
|
+
def closed?
|
122
|
+
@start_stop_mutex.synchronize { false|@_closed }
|
123
|
+
end
|
124
|
+
|
96
125
|
def running?
|
97
|
-
false|@_running
|
126
|
+
@start_stop_mutex.synchronize { false|@_running }
|
98
127
|
end
|
99
128
|
|
129
|
+
protected
|
100
130
|
def setup_dispatch_thread!
|
101
131
|
@dispatcher = Thread.new do
|
102
132
|
while running?
|
103
133
|
begin # calling user code, so protect ourselves
|
104
|
-
dispatch_next_callback
|
134
|
+
dispatch_next_callback
|
105
135
|
rescue Exception => e
|
106
136
|
$stderr.puts "Error in dispatch thread, #{e.class}: #{e.message}\n" << e.backtrace.map{|n| "\t#{n}"}.join("\n")
|
107
137
|
end
|
data/ext/zookeeper_c.c
CHANGED
@@ -17,11 +17,16 @@
|
|
17
17
|
#include <stdio.h>
|
18
18
|
#include <stdlib.h>
|
19
19
|
#include <unistd.h>
|
20
|
+
#include <sys/fcntl.h>
|
21
|
+
#include <pthread.h>
|
20
22
|
|
21
23
|
#include "zookeeper_lib.h"
|
22
24
|
|
25
|
+
|
23
26
|
static VALUE Zookeeper = Qnil;
|
24
27
|
|
28
|
+
// slyphon: possibly add a lock to this for synchronizing during get_next_event
|
29
|
+
|
25
30
|
struct zkrb_instance_data {
|
26
31
|
zhandle_t *zh;
|
27
32
|
clientid_t myid;
|
@@ -69,9 +74,53 @@ static void print_zkrb_instance_data(struct zkrb_instance_data* ptr) {
|
|
69
74
|
fprintf(stderr, "}\n");
|
70
75
|
}
|
71
76
|
|
77
|
+
// cargo culted from io.c
|
78
|
+
static VALUE zkrb_new_instance _((VALUE));
|
79
|
+
|
80
|
+
static VALUE zkrb_new_instance(VALUE args) {
|
81
|
+
return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
|
82
|
+
}
|
83
|
+
|
84
|
+
static int zkrb_dup(int orig) {
|
85
|
+
int fd;
|
86
|
+
|
87
|
+
fd = dup(orig);
|
88
|
+
if (fd < 0) {
|
89
|
+
if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
|
90
|
+
rb_gc();
|
91
|
+
fd = dup(orig);
|
92
|
+
}
|
93
|
+
if (fd < 0) {
|
94
|
+
rb_sys_fail(0);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
return fd;
|
98
|
+
}
|
99
|
+
|
100
|
+
static VALUE create_selectable_io(zkrb_queue_t *q) {
|
101
|
+
// rb_cIO is the ruby IO class?
|
102
|
+
|
103
|
+
int pipe, state, read_fd;
|
104
|
+
VALUE args[3], reader;
|
105
|
+
|
106
|
+
read_fd = zkrb_dup(q->pipe_read);
|
107
|
+
|
108
|
+
args[0] = rb_cIO;
|
109
|
+
args[1] = INT2NUM(read_fd);
|
110
|
+
args[2] = INT2FIX(O_RDONLY);
|
111
|
+
reader = rb_protect(zkrb_new_instance, (VALUE)args, &state);
|
112
|
+
|
113
|
+
if (state) {
|
114
|
+
rb_jump_tag(state);
|
115
|
+
}
|
116
|
+
|
117
|
+
return reader;
|
118
|
+
}
|
119
|
+
|
72
120
|
static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
73
121
|
VALUE hostPort;
|
74
122
|
VALUE options;
|
123
|
+
|
75
124
|
rb_scan_args(argc, argv, "11", &hostPort, &options);
|
76
125
|
|
77
126
|
if (NIL_P(options)) {
|
@@ -121,8 +170,10 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
|
|
121
170
|
}
|
122
171
|
|
123
172
|
rb_iv_set(self, "@data", data);
|
173
|
+
rb_iv_set(self, "@selectable_io", create_selectable_io(zk_local_ctx->queue));
|
124
174
|
rb_iv_set(self, "@_running", Qtrue);
|
125
175
|
|
176
|
+
|
126
177
|
return Qnil;
|
127
178
|
}
|
128
179
|
|
@@ -421,7 +472,10 @@ static int is_running(VALUE self) {
|
|
421
472
|
return RTEST(rval);
|
422
473
|
}
|
423
474
|
|
424
|
-
|
475
|
+
|
476
|
+
/* slyphon: NEED TO PROTECT THIS AGAINST SHUTDOWN */
|
477
|
+
|
478
|
+
static VALUE method_get_next_event(VALUE self, VALUE blocking) {
|
425
479
|
char buf[64];
|
426
480
|
FETCH_DATA_PTR(self, zk);
|
427
481
|
|
@@ -439,19 +493,35 @@ static VALUE method_get_next_event(VALUE self) {
|
|
439
493
|
|
440
494
|
/* Wait for an event using rb_thread_select() on the queue's pipe */
|
441
495
|
if (event == NULL) {
|
442
|
-
|
443
|
-
|
496
|
+
if (NIL_P(blocking) || (blocking == Qfalse)) {
|
497
|
+
return Qnil; // no event for us
|
498
|
+
}
|
499
|
+
else {
|
500
|
+
int fd = zk->queue->pipe_read;
|
501
|
+
ssize_t bytes_read = 0;
|
502
|
+
|
503
|
+
fd_set rset; // a file descriptor set for use w/ select()
|
504
|
+
|
505
|
+
FD_ZERO(&rset); // FD_ZERO clears the set
|
506
|
+
FD_SET(fd, &rset); // FD_SET adds fd to the rset
|
444
507
|
|
445
|
-
|
446
|
-
|
508
|
+
// first arg is nfds: "the highest-numbered file descriptor in any of the three sets, plus 1"
|
509
|
+
// why? F*** you, that's why!
|
447
510
|
|
448
|
-
|
449
|
-
|
511
|
+
if (rb_thread_select(fd + 1, &rset, NULL, NULL, NULL) == -1)
|
512
|
+
rb_raise(rb_eRuntimeError, "select failed: %d", errno);
|
450
513
|
|
451
|
-
|
452
|
-
rb_raise(rb_eRuntimeError, "read failed: %d", errno);
|
514
|
+
bytes_read = read(fd, buf, sizeof(buf));
|
453
515
|
|
454
|
-
|
516
|
+
if (bytes_read == -1) {
|
517
|
+
rb_raise(rb_eRuntimeError, "read failed: %d", errno);
|
518
|
+
}
|
519
|
+
else if (ZKRBDebugging) {
|
520
|
+
fprintf(stderr, "read %d bytes from the queue's pipe\n", bytes_read);
|
521
|
+
}
|
522
|
+
|
523
|
+
continue;
|
524
|
+
}
|
455
525
|
}
|
456
526
|
|
457
527
|
VALUE hash = zkrb_event_to_ruby(event);
|
@@ -493,11 +563,22 @@ static VALUE method_wake_event_loop_bang(VALUE self) {
|
|
493
563
|
// return Qnil;
|
494
564
|
// }
|
495
565
|
|
496
|
-
static VALUE
|
566
|
+
static VALUE method_close_handle(VALUE self) {
|
497
567
|
FETCH_DATA_PTR(self, zk);
|
498
568
|
|
569
|
+
if (ZKRBDebugging) {
|
570
|
+
fprintf(stderr, "CLOSING ZK INSTANCE:");
|
571
|
+
print_zkrb_instance_data(zk);
|
572
|
+
}
|
573
|
+
|
574
|
+
// this is a value on the ruby side we can check to see if destroy_zkrb_instance
|
575
|
+
// has been called
|
576
|
+
rb_iv_set(self, "@_closed", Qtrue);
|
577
|
+
|
578
|
+
|
499
579
|
/* Note that after zookeeper_close() returns, ZK handle is invalid */
|
500
580
|
int rc = destroy_zkrb_instance(zk);
|
581
|
+
|
501
582
|
return INT2FIX(rc);
|
502
583
|
}
|
503
584
|
|
@@ -521,8 +602,7 @@ static VALUE method_recv_timeout(VALUE self) {
|
|
521
602
|
return INT2NUM(zoo_recv_timeout(zk->zh));
|
522
603
|
}
|
523
604
|
|
524
|
-
|
525
|
-
static VALUE method_set_debug_level(VALUE self, VALUE level) {
|
605
|
+
static VALUE klass_method_set_debug_level(VALUE klass, VALUE level) {
|
526
606
|
Check_Type(level, T_FIXNUM);
|
527
607
|
ZKRBDebugging = (FIX2INT(level) == ZOO_LOG_LEVEL_DEBUG);
|
528
608
|
zoo_set_debug_level(FIX2INT(level));
|
@@ -549,7 +629,7 @@ static void zkrb_define_methods(void) {
|
|
549
629
|
DEFINE_METHOD(set_acl, 5);
|
550
630
|
DEFINE_METHOD(get_acl, 3);
|
551
631
|
DEFINE_METHOD(client_id, 0);
|
552
|
-
DEFINE_METHOD(
|
632
|
+
DEFINE_METHOD(close_handle, 0);
|
553
633
|
DEFINE_METHOD(deterministic_conn_order, 1);
|
554
634
|
DEFINE_METHOD(is_unrecoverable, 0);
|
555
635
|
DEFINE_METHOD(recv_timeout, 1);
|
@@ -559,13 +639,16 @@ static void zkrb_define_methods(void) {
|
|
559
639
|
// DEFINE_METHOD(async, 1);
|
560
640
|
|
561
641
|
// methods for the ruby-side event manager
|
562
|
-
DEFINE_METHOD(get_next_event,
|
642
|
+
DEFINE_METHOD(get_next_event, 1);
|
563
643
|
DEFINE_METHOD(has_events, 0);
|
564
644
|
|
565
645
|
// Make these class methods?
|
566
|
-
DEFINE_METHOD(set_debug_level, 1);
|
567
646
|
DEFINE_METHOD(zerror, 1);
|
568
647
|
|
648
|
+
rb_define_singleton_method(Zookeeper, "set_debug_level", klass_method_set_debug_level, 1);
|
649
|
+
|
650
|
+
rb_attr(Zookeeper, rb_intern("selectable_io"), 1, 0, Qtrue);
|
651
|
+
|
569
652
|
rb_define_method(Zookeeper, "wake_event_loop!", method_wake_event_loop_bang, 0);
|
570
653
|
}
|
571
654
|
|
data/ext/zookeeper_lib.c
CHANGED
@@ -140,18 +140,26 @@ void zkrb_event_free(zkrb_event_t *event) {
|
|
140
140
|
}
|
141
141
|
case ZKRB_STRINGS: {
|
142
142
|
struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
|
143
|
-
|
144
|
-
|
145
|
-
|
143
|
+
if (strings_ctx->values != NULL) {
|
144
|
+
int k;
|
145
|
+
for (k = 0; k < strings_ctx->values->count; ++k) free(strings_ctx->values->data[k]);
|
146
|
+
free(strings_ctx->values);
|
147
|
+
}
|
146
148
|
free(strings_ctx);
|
147
149
|
break;
|
148
150
|
}
|
149
151
|
case ZKRB_STRINGS_STAT: {
|
150
152
|
struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
153
|
+
if (strings_stat_ctx->values != NULL) {
|
154
|
+
int k;
|
155
|
+
for (k = 0; k < strings_stat_ctx->values->count; ++k) free(strings_stat_ctx->values->data[k]);
|
156
|
+
free(strings_stat_ctx->values);
|
157
|
+
}
|
158
|
+
|
159
|
+
if (strings_stat_ctx->stat != NULL) {
|
160
|
+
free(strings_stat_ctx->stat);
|
161
|
+
}
|
162
|
+
|
155
163
|
free(strings_stat_ctx);
|
156
164
|
break;
|
157
165
|
}
|
@@ -200,33 +208,40 @@ VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
|
|
200
208
|
break;
|
201
209
|
}
|
202
210
|
case ZKRB_STAT: {
|
211
|
+
if (ZKRBDebugging) fprintf(stderr, "zkrb_event_to_ruby ZKRB_STAT\n");
|
203
212
|
struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
|
204
213
|
rb_hash_aset(hash, GET_SYM("stat"), stat_ctx->stat ? zkrb_stat_to_rarray(stat_ctx->stat) : Qnil);
|
205
214
|
break;
|
206
215
|
}
|
207
216
|
case ZKRB_STRING: {
|
217
|
+
if (ZKRBDebugging) fprintf(stderr, "zkrb_event_to_ruby ZKRB_STRING\n");
|
208
218
|
struct zkrb_string_completion *string_ctx = event->completion.string_completion;
|
209
219
|
rb_hash_aset(hash, GET_SYM("string"), string_ctx->value ? rb_str_new2(string_ctx->value) : Qnil);
|
210
220
|
break;
|
211
221
|
}
|
212
222
|
case ZKRB_STRINGS: {
|
223
|
+
if (ZKRBDebugging) fprintf(stderr, "zkrb_event_to_ruby ZKRB_STRINGS\n");
|
213
224
|
struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
|
214
225
|
rb_hash_aset(hash, GET_SYM("strings"), strings_ctx->values ? zkrb_string_vector_to_ruby(strings_ctx->values) : Qnil);
|
215
226
|
break;
|
216
227
|
}
|
217
228
|
case ZKRB_STRINGS_STAT: {
|
229
|
+
if (ZKRBDebugging) fprintf(stderr, "zkrb_event_to_ruby ZKRB_STRINGS_STAT\n");
|
218
230
|
struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
|
219
231
|
rb_hash_aset(hash, GET_SYM("strings"), strings_stat_ctx->values ? zkrb_string_vector_to_ruby(strings_stat_ctx->values) : Qnil);
|
220
232
|
rb_hash_aset(hash, GET_SYM("stat"), strings_stat_ctx->stat ? zkrb_stat_to_rarray(strings_stat_ctx->stat) : Qnil);
|
221
233
|
break;
|
222
234
|
}
|
223
235
|
case ZKRB_ACL: {
|
236
|
+
if (ZKRBDebugging) fprintf(stderr, "zkrb_event_to_ruby ZKRB_ACL\n");
|
224
237
|
struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
|
225
238
|
rb_hash_aset(hash, GET_SYM("acl"), acl_ctx->acl ? zkrb_acl_vector_to_ruby(acl_ctx->acl) : Qnil);
|
226
239
|
rb_hash_aset(hash, GET_SYM("stat"), acl_ctx->stat ? zkrb_stat_to_rarray(acl_ctx->stat) : Qnil);
|
227
240
|
break;
|
228
241
|
}
|
229
242
|
case ZKRB_WATCHER: {
|
243
|
+
if (ZKRBDebugging) fprintf(stderr, "zkrb_event_to_ruby ZKRB_WATCHER\n");
|
244
|
+
struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
|
230
245
|
struct zkrb_watcher_completion *watcher_ctx = event->completion.watcher_completion;
|
231
246
|
rb_hash_aset(hash, GET_SYM("type"), INT2FIX(watcher_ctx->type));
|
232
247
|
rb_hash_aset(hash, GET_SYM("state"), INT2FIX(watcher_ctx->state));
|
@@ -422,6 +437,7 @@ void zkrb_strings_stat_callback(
|
|
422
437
|
struct zkrb_strings_stat_completion *sc = malloc(sizeof(struct zkrb_strings_stat_completion));
|
423
438
|
sc->stat = NULL;
|
424
439
|
if (stat != NULL) { sc->stat = malloc(sizeof(struct Stat)); memcpy(sc->stat, stat, sizeof(struct Stat)); }
|
440
|
+
|
425
441
|
sc->values = (strings != NULL) ? zkrb_clone_string_vector(strings) : NULL;
|
426
442
|
|
427
443
|
ZKH_SETUP_EVENT(queue, event);
|