slyphon-zookeeper 0.1.7-java → 0.2.0-java
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/.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);
|