zookeeper 0.4.4 → 0.9.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.
Files changed (48) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG +95 -0
  3. data/Gemfile +17 -0
  4. data/Manifest +8 -2
  5. data/README.markdown +59 -0
  6. data/Rakefile +137 -7
  7. data/ext/.gitignore +6 -0
  8. data/ext/Rakefile +51 -0
  9. data/ext/c_zookeeper.rb +212 -0
  10. data/ext/dbg.h +53 -0
  11. data/ext/depend +5 -0
  12. data/ext/extconf.rb +44 -15
  13. data/ext/generate_gvl_code.rb +316 -0
  14. data/ext/zkc-3.3.5.tar.gz +0 -0
  15. data/ext/zkrb_wrapper.c +731 -0
  16. data/ext/zkrb_wrapper.h +330 -0
  17. data/ext/zkrb_wrapper_compat.c +15 -0
  18. data/ext/zkrb_wrapper_compat.h +11 -0
  19. data/ext/zookeeper_base.rb +211 -0
  20. data/ext/zookeeper_c.c +268 -97
  21. data/ext/zookeeper_lib.c +157 -92
  22. data/ext/zookeeper_lib.h +12 -6
  23. data/java/zookeeper_base.rb +477 -0
  24. data/lib/zookeeper/acls.rb +10 -1
  25. data/lib/zookeeper/callbacks.rb +5 -3
  26. data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
  27. data/lib/zookeeper/common.rb +174 -0
  28. data/lib/zookeeper/constants.rb +31 -28
  29. data/lib/zookeeper/em_client.rb +55 -0
  30. data/lib/zookeeper/exceptions.rb +10 -2
  31. data/lib/zookeeper/stat.rb +11 -2
  32. data/lib/zookeeper/version.rb +6 -0
  33. data/lib/zookeeper.rb +155 -122
  34. data/notes.txt +14 -0
  35. data/spec/c_zookeeper_spec.rb +50 -0
  36. data/spec/chrooted_connection_spec.rb +81 -0
  37. data/spec/default_watcher_spec.rb +41 -0
  38. data/spec/em_spec.rb +51 -0
  39. data/spec/log4j.properties +17 -0
  40. data/spec/shared/all_success_return_values.rb +10 -0
  41. data/spec/shared/connection_examples.rb +1018 -0
  42. data/spec/spec_helper.rb +119 -0
  43. data/spec/support/progress_formatter.rb +15 -0
  44. data/spec/zookeeper_spec.rb +24 -0
  45. data/zookeeper.gemspec +37 -25
  46. metadata +78 -34
  47. data/README +0 -42
  48. data/ext/zkc-3.3.2.tar.gz +0 -0
data/ext/zookeeper_c.c CHANGED
@@ -2,6 +2,7 @@
2
2
  * Phillip Pearson <pp@myelin.co.nz>
3
3
  * Eric Maland <eric@twitter.com>
4
4
  * Brian Wickman <wickman@twitter.com>
5
+ * Jonathan D. Simms <slyphon@gmail.com>
5
6
  *
6
7
  * This fork is a 90% rewrite of the original. It takes a more evented
7
8
  * approach to isolate the ZK state machine from the ruby interpreter via an
@@ -17,16 +18,24 @@
17
18
  #include <stdio.h>
18
19
  #include <stdlib.h>
19
20
  #include <unistd.h>
21
+ #include <sys/fcntl.h>
22
+ #include <pthread.h>
23
+ #include <inttypes.h>
20
24
 
21
25
  #include "zookeeper_lib.h"
26
+ #include "zkrb_wrapper.h"
27
+ #include "dbg.h"
22
28
 
23
29
  static VALUE Zookeeper = Qnil;
30
+ static VALUE ZookeeperClientId = Qnil;
31
+
32
+ // slyphon: possibly add a lock to this for synchronizing during get_next_event
24
33
 
25
34
  struct zkrb_instance_data {
26
35
  zhandle_t *zh;
27
36
  clientid_t myid;
28
37
  zkrb_queue_t *queue;
29
- int pending_close;
38
+ long object_id; // the ruby object this instance data is associated with
30
39
  };
31
40
 
32
41
  typedef enum {
@@ -39,21 +48,28 @@ typedef enum {
39
48
  #define IS_SYNC(zkrbcall) ((zkrbcall)==SYNC || (zkrbcall)==SYNC_WATCH)
40
49
  #define IS_ASYNC(zkrbcall) ((zkrbcall)==ASYNC || (zkrbcall)==ASYNC_WATCH)
41
50
 
51
+
42
52
  static int destroy_zkrb_instance(struct zkrb_instance_data* ptr) {
43
53
  int rv = ZOK;
44
54
 
45
55
  if (ptr->zh) {
46
56
  const void *ctx = zoo_get_context(ptr->zh);
47
57
  /* Note that after zookeeper_close() returns, ZK handle is invalid */
58
+ zkrb_debug("obj_id: %lx, calling zookeeper_close", ptr->object_id);
48
59
  rv = zookeeper_close(ptr->zh);
60
+ zkrb_debug("obj_id: %lx, zookeeper_close returned %d", ptr->object_id, rv);
49
61
  free((void *) ctx);
50
62
  }
51
63
 
52
64
  #warning [wickman] TODO: fire off warning if queue is not empty
53
- if (ptr->queue) zkrb_queue_free(ptr->queue);
65
+ if (ptr->queue) {
66
+ zkrb_debug("obj_id: %lx, freeing queue pointer: %p", ptr->object_id, ptr->queue);
67
+ zkrb_queue_free(ptr->queue);
68
+ }
54
69
 
55
70
  ptr->zh = NULL;
56
71
  ptr->queue = NULL;
72
+
57
73
  return rv;
58
74
  }
59
75
 
@@ -63,16 +79,65 @@ static void free_zkrb_instance_data(struct zkrb_instance_data* ptr) {
63
79
 
64
80
  static void print_zkrb_instance_data(struct zkrb_instance_data* ptr) {
65
81
  fprintf(stderr, "zkrb_instance_data (%p) {\n", ptr);
66
- fprintf(stderr, " zh = %p\n", ptr->zh);
67
- fprintf(stderr, " { state = %d }\n", zoo_state(ptr->zh));
68
- fprintf(stderr, " id = %llx\n", ptr->myid.client_id);
69
- fprintf(stderr, " q = %p\n", ptr->queue);
82
+ fprintf(stderr, " zh = %p\n", ptr->zh);
83
+ fprintf(stderr, " { state = %d }\n", zoo_state(ptr->zh));
84
+ fprintf(stderr, " id = %"PRId64"\n", ptr->myid.client_id); // PRId64 defined in inttypes.h
85
+ fprintf(stderr, " q = %p\n", ptr->queue);
86
+ fprintf(stderr, " obj_id = %lx\n", ptr->object_id);
70
87
  fprintf(stderr, "}\n");
71
88
  }
72
89
 
73
- static VALUE method_init(int argc, VALUE* argv, VALUE self) {
90
+ // cargo culted from io.c
91
+ static VALUE zkrb_new_instance _((VALUE));
92
+
93
+ static VALUE zkrb_new_instance(VALUE args) {
94
+ return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
95
+ }
96
+
97
+ static int zkrb_dup(int orig) {
98
+ int fd;
99
+
100
+ fd = dup(orig);
101
+ if (fd < 0) {
102
+ if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
103
+ rb_gc();
104
+ fd = dup(orig);
105
+ }
106
+ if (fd < 0) {
107
+ rb_sys_fail(0);
108
+ }
109
+ }
110
+ return fd;
111
+ }
112
+
113
+ #if 0
114
+ static VALUE create_selectable_io(zkrb_queue_t *q) {
115
+ // rb_cIO is the ruby IO class?
116
+
117
+ int pipe, state, read_fd;
118
+ VALUE args[3], reader;
119
+
120
+ read_fd = zkrb_dup(q->pipe_read);
121
+
122
+ args[0] = rb_cIO;
123
+ args[1] = INT2NUM(read_fd);
124
+ args[2] = INT2FIX(O_RDONLY);
125
+ reader = rb_protect(zkrb_new_instance, (VALUE)args, &state);
126
+
127
+ if (state) {
128
+ rb_jump_tag(state);
129
+ }
130
+
131
+ return reader;
132
+ }
133
+ #endif
134
+
135
+ #define session_timeout_msec(self) rb_iv_get(self, "@_session_timeout_msec")
136
+
137
+ static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
74
138
  VALUE hostPort;
75
139
  VALUE options;
140
+
76
141
  rb_scan_args(argc, argv, "11", &hostPort, &options);
77
142
 
78
143
  if (NIL_P(options)) {
@@ -89,29 +154,30 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
89
154
  zoo_set_debug_level(0); // no log messages
90
155
  } else {
91
156
  Check_Type(log_level, T_FIXNUM);
92
- zoo_set_debug_level(log_level);
157
+ zoo_set_debug_level((int)log_level);
93
158
  }
94
159
 
160
+
95
161
  VALUE data;
96
162
  struct zkrb_instance_data *zk_local_ctx;
97
- data = Data_Make_Struct(Zookeeper,
98
- struct zkrb_instance_data,
99
- 0,
100
- free_zkrb_instance_data,
101
- zk_local_ctx);
163
+ data = Data_Make_Struct(Zookeeper, struct zkrb_instance_data, 0, free_zkrb_instance_data, zk_local_ctx);
102
164
  zk_local_ctx->queue = zkrb_queue_alloc();
103
- zk_local_ctx->pending_close = 0;
165
+
166
+ if (zk_local_ctx->queue == NULL)
167
+ rb_raise(rb_eRuntimeError, "could not allocate zkrb queue!");
104
168
 
105
169
  zoo_deterministic_conn_order(0);
106
170
 
107
171
  zkrb_calling_context *ctx =
108
172
  zkrb_calling_context_alloc(ZKRB_GLOBAL_REQ, zk_local_ctx->queue);
109
173
 
174
+ zk_local_ctx->object_id = FIX2LONG(rb_obj_id(self));
175
+
110
176
  zk_local_ctx->zh =
111
177
  zookeeper_init(
112
178
  RSTRING_PTR(hostPort),
113
179
  zkrb_state_callback,
114
- 10000,
180
+ session_timeout_msec(self),
115
181
  &zk_local_ctx->myid,
116
182
  ctx,
117
183
  0);
@@ -121,40 +187,42 @@ static VALUE method_init(int argc, VALUE* argv, VALUE self) {
121
187
  rb_raise(rb_eRuntimeError, "error connecting to zookeeper: %d", errno);
122
188
  }
123
189
 
124
- rb_iv_set(self, "@data", data);
190
+ rb_iv_set(self, "@_data", data);
191
+ rb_funcall(self, rb_intern("zkc_set_running_and_notify!"), 0);
125
192
 
193
+ error:
126
194
  return Qnil;
127
195
  }
128
196
 
129
- #define FETCH_DATA_PTR(x, y) \
130
- struct zkrb_instance_data * y; \
131
- Data_Get_Struct(rb_iv_get(x, "@data"), struct zkrb_instance_data, y); \
132
- if ((y)->zh == NULL) \
197
+ #define FETCH_DATA_PTR(X, Y) \
198
+ struct zkrb_instance_data * Y; \
199
+ Data_Get_Struct(rb_iv_get(X, "@_data"), struct zkrb_instance_data, Y); \
200
+ if ((Y)->zh == NULL) \
133
201
  rb_raise(rb_eRuntimeError, "zookeeper handle is closed")
134
202
 
135
203
  #define STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, cb_ctx, w_ctx, call_type) \
136
- if (TYPE(reqid) != T_FIXNUM && TYPE(reqid) != T_BIGNUM) { \
137
- rb_raise(rb_eTypeError, "reqid must be Fixnum/Bignum"); \
138
- return Qnil; \
139
- } \
140
- Check_Type(path, T_STRING); \
141
- struct zkrb_instance_data * zk; \
142
- Data_Get_Struct(rb_iv_get(self, "@data"), struct zkrb_instance_data, zk); \
143
- if (!zk->zh) \
144
- rb_raise(rb_eRuntimeError, "zookeeper handle is closed"); \
145
- zkrb_calling_context* cb_ctx = \
146
- (async != Qfalse && async != Qnil) ? \
147
- zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
148
- NULL; \
149
- zkrb_calling_context* w_ctx = \
150
- (watch != Qfalse && watch != Qnil) ? \
151
- zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
152
- NULL; \
153
- int a = (async != Qfalse && async != Qnil); \
154
- int w = (watch != Qfalse && watch != Qnil); \
155
- zkrb_call_type call_type; \
156
- if (a) { if (w) { call_type = ASYNC_WATCH; } else { call_type = ASYNC; } } \
157
- else { if (w) { call_type = SYNC_WATCH; } else { call_type = SYNC; } }
204
+ if (TYPE(reqid) != T_FIXNUM && TYPE(reqid) != T_BIGNUM) { \
205
+ rb_raise(rb_eTypeError, "reqid must be Fixnum/Bignum"); \
206
+ return Qnil; \
207
+ } \
208
+ Check_Type(path, T_STRING); \
209
+ struct zkrb_instance_data * zk; \
210
+ Data_Get_Struct(rb_iv_get(self, "@_data"), struct zkrb_instance_data, zk); \
211
+ if (!zk->zh) \
212
+ rb_raise(rb_eRuntimeError, "zookeeper handle is closed"); \
213
+ zkrb_calling_context* cb_ctx = \
214
+ (async != Qfalse && async != Qnil) ? \
215
+ zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
216
+ NULL; \
217
+ zkrb_calling_context* w_ctx = \
218
+ (watch != Qfalse && watch != Qnil) ? \
219
+ zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
220
+ NULL; \
221
+ int a_ = (async != Qfalse && async != Qnil); \
222
+ int w_ = (watch != Qfalse && watch != Qnil); \
223
+ zkrb_call_type call_type; \
224
+ if (a_) { if (w_) { call_type = ASYNC_WATCH; } else { call_type = ASYNC; } } \
225
+ else { if (w_) { call_type = SYNC_WATCH; } else { call_type = SYNC; } }
158
226
 
159
227
  static VALUE method_get_children(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
160
228
  STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
@@ -165,19 +233,19 @@ static VALUE method_get_children(VALUE self, VALUE reqid, VALUE path, VALUE asyn
165
233
  int rc;
166
234
  switch (call_type) {
167
235
  case SYNC:
168
- rc = zoo_get_children2(zk->zh, RSTRING_PTR(path), 0, &strings, &stat);
236
+ rc = zkrb_call_zoo_get_children2(zk->zh, RSTRING_PTR(path), 0, &strings, &stat);
169
237
  break;
170
238
 
171
239
  case SYNC_WATCH:
172
- rc = zoo_wget_children2(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, &strings, &stat);
240
+ rc = zkrb_call_zoo_wget_children2(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, &strings, &stat);
173
241
  break;
174
242
 
175
243
  case ASYNC:
176
- rc = zoo_aget_children2(zk->zh, RSTRING_PTR(path), 0, zkrb_strings_stat_callback, data_ctx);
244
+ rc = zkrb_call_zoo_aget_children2(zk->zh, RSTRING_PTR(path), 0, zkrb_strings_stat_callback, data_ctx);
177
245
  break;
178
246
 
179
247
  case ASYNC_WATCH:
180
- rc = zoo_awget_children2(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_strings_stat_callback, data_ctx);
248
+ rc = zkrb_call_zoo_awget_children2(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_strings_stat_callback, data_ctx);
181
249
  break;
182
250
  }
183
251
 
@@ -198,19 +266,19 @@ static VALUE method_exists(VALUE self, VALUE reqid, VALUE path, VALUE async, VAL
198
266
  int rc;
199
267
  switch (call_type) {
200
268
  case SYNC:
201
- rc = zoo_exists(zk->zh, RSTRING_PTR(path), 0, &stat);
269
+ rc = zkrb_call_zoo_exists(zk->zh, RSTRING_PTR(path), 0, &stat);
202
270
  break;
203
271
 
204
272
  case SYNC_WATCH:
205
- rc = zoo_wexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, &stat);
273
+ rc = zkrb_call_zoo_wexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, &stat);
206
274
  break;
207
275
 
208
276
  case ASYNC:
209
- rc = zoo_aexists(zk->zh, RSTRING_PTR(path), 0, zkrb_stat_callback, data_ctx);
277
+ rc = zkrb_call_zoo_aexists(zk->zh, RSTRING_PTR(path), 0, zkrb_stat_callback, data_ctx);
210
278
  break;
211
279
 
212
280
  case ASYNC_WATCH:
213
- rc = zoo_awexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_stat_callback, data_ctx);
281
+ rc = zkrb_call_zoo_awexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_stat_callback, data_ctx);
214
282
  break;
215
283
  }
216
284
 
@@ -222,6 +290,19 @@ static VALUE method_exists(VALUE self, VALUE reqid, VALUE path, VALUE async, VAL
222
290
  return output;
223
291
  }
224
292
 
293
+ // this method is *only* called asynchronously
294
+ static VALUE method_sync(VALUE self, VALUE reqid, VALUE path) {
295
+ VALUE async = Qtrue;
296
+ VALUE watch = Qfalse;
297
+ int rc;
298
+
299
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
300
+
301
+ rc = zkrb_call_zoo_async(zk->zh, RSTRING_PTR(path), zkrb_string_callback, data_ctx);
302
+
303
+ return INT2FIX(rc);
304
+ }
305
+
225
306
  static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE async, VALUE acls, VALUE flags) {
226
307
  VALUE watch = Qfalse;
227
308
  STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
@@ -238,10 +319,13 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
238
319
  int rc;
239
320
  switch (call_type) {
240
321
  case SYNC:
241
- rc = zoo_create(zk->zh, RSTRING_PTR(path), data_ptr, data_len, aclptr, FIX2INT(flags), realpath, sizeof(realpath));
322
+ // casting data_len to int is OK as you can only store 1MB in zookeeper
323
+ rc = zkrb_call_zoo_create(zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, aclptr, FIX2INT(flags), realpath, sizeof(realpath));
324
+
242
325
  break;
243
326
  case ASYNC:
244
- rc = zoo_acreate(zk->zh, RSTRING_PTR(path), data_ptr, data_len, aclptr, FIX2INT(flags), zkrb_string_callback, data_ctx);
327
+ rc = zkrb_call_zoo_acreate(zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, aclptr, FIX2INT(flags), zkrb_string_callback, data_ctx);
328
+
245
329
  break;
246
330
  default:
247
331
  /* TODO(wickman) raise proper argument error */
@@ -249,6 +333,7 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
249
333
  break;
250
334
  }
251
335
 
336
+
252
337
  if (aclptr) {
253
338
  deallocate_ACL_vector(aclptr);
254
339
  free(aclptr);
@@ -270,10 +355,10 @@ static VALUE method_delete(VALUE self, VALUE reqid, VALUE path, VALUE version, V
270
355
  int rc = 0;
271
356
  switch (call_type) {
272
357
  case SYNC:
273
- rc = zoo_delete(zk->zh, RSTRING_PTR(path), FIX2INT(version));
358
+ rc = zkrb_call_zoo_delete(zk->zh, RSTRING_PTR(path), FIX2INT(version));
274
359
  break;
275
360
  case ASYNC:
276
- rc = zoo_adelete(zk->zh, RSTRING_PTR(path), FIX2INT(version), zkrb_void_callback, data_ctx);
361
+ rc = zkrb_call_zoo_adelete(zk->zh, RSTRING_PTR(path), FIX2INT(version), zkrb_void_callback, data_ctx);
277
362
  break;
278
363
  default:
279
364
  /* TODO(wickman) raise proper argument error */
@@ -298,19 +383,19 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
298
383
 
299
384
  switch (call_type) {
300
385
  case SYNC:
301
- rc = zoo_get(zk->zh, RSTRING_PTR(path), 0, data, &data_len, &stat);
386
+ rc = zkrb_call_zoo_get(zk->zh, RSTRING_PTR(path), 0, data, &data_len, &stat);
302
387
  break;
303
388
 
304
389
  case SYNC_WATCH:
305
- rc = zoo_wget(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, data, &data_len, &stat);
390
+ rc = zkrb_call_zoo_wget(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, data, &data_len, &stat);
306
391
  break;
307
392
 
308
393
  case ASYNC:
309
- rc = zoo_aget(zk->zh, RSTRING_PTR(path), 0, zkrb_data_callback, data_ctx);
394
+ rc = zkrb_call_zoo_aget(zk->zh, RSTRING_PTR(path), 0, zkrb_data_callback, data_ctx);
310
395
  break;
311
396
 
312
397
  case ASYNC_WATCH:
313
- rc = zoo_awget(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_data_callback, data_ctx);
398
+ rc = zkrb_call_zoo_awget(zk->zh, RSTRING_PTR(path), zkrb_state_callback, watch_ctx, zkrb_data_callback, data_ctx);
314
399
  break;
315
400
  }
316
401
 
@@ -340,10 +425,10 @@ static VALUE method_set(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE a
340
425
  int rc;
341
426
  switch (call_type) {
342
427
  case SYNC:
343
- rc = zoo_set2(zk->zh, RSTRING_PTR(path), data_ptr, data_len, FIX2INT(version), &stat);
428
+ rc = zkrb_call_zoo_set2(zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, FIX2INT(version), &stat);
344
429
  break;
345
430
  case ASYNC:
346
- rc = zoo_aset(zk->zh, RSTRING_PTR(path), data_ptr, data_len, FIX2INT(version),
431
+ rc = zkrb_call_zoo_aset(zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, FIX2INT(version),
347
432
  zkrb_stat_callback, data_ctx);
348
433
  break;
349
434
  default:
@@ -368,10 +453,10 @@ static VALUE method_set_acl(VALUE self, VALUE reqid, VALUE path, VALUE acls, VAL
368
453
  int rc;
369
454
  switch (call_type) {
370
455
  case SYNC:
371
- rc = zoo_set_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr);
456
+ rc = zkrb_call_zoo_set_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr);
372
457
  break;
373
458
  case ASYNC:
374
- rc = zoo_aset_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr, zkrb_void_callback, data_ctx);
459
+ rc = zkrb_call_zoo_aset_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr, zkrb_void_callback, data_ctx);
375
460
  break;
376
461
  default:
377
462
  /* TODO(wickman) raise proper argument error */
@@ -395,10 +480,10 @@ static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
395
480
  int rc;
396
481
  switch (call_type) {
397
482
  case SYNC:
398
- rc = zoo_get_acl(zk->zh, RSTRING_PTR(path), &acls, &stat);
483
+ rc = zkrb_call_zoo_get_acl(zk->zh, RSTRING_PTR(path), &acls, &stat);
399
484
  break;
400
485
  case ASYNC:
401
- rc = zoo_aget_acl(zk->zh, RSTRING_PTR(path), zkrb_acl_callback, data_ctx);
486
+ rc = zkrb_call_zoo_aget_acl(zk->zh, RSTRING_PTR(path), zkrb_acl_callback, data_ctx);
402
487
  break;
403
488
  default:
404
489
  /* TODO(wickman) raise proper argument error */
@@ -416,37 +501,58 @@ static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
416
501
  return output;
417
502
  }
418
503
 
419
- static VALUE method_get_next_event(VALUE self) {
504
+ #define is_running(self) RTEST(rb_iv_get(self, "@_running"))
505
+ #define is_closed(self) RTEST(rb_iv_get(self, "@_closed"))
506
+ #define is_shutting_down(self) RTEST(rb_iv_get(self, "@_shutting_down"))
507
+
508
+ static VALUE method_get_next_event(VALUE self, VALUE blocking) {
509
+ // dbg.h
510
+ check_debug(!is_closed(self), "we are closed, not trying to get event");
511
+
420
512
  char buf[64];
421
513
  FETCH_DATA_PTR(self, zk);
422
514
 
423
515
  for (;;) {
516
+ check_debug(!is_closed(self), "we're closed in the middle of method_get_next_event, bailing");
517
+
424
518
  zkrb_event_t *event = zkrb_dequeue(zk->queue, 1);
425
519
 
426
520
  /* Wait for an event using rb_thread_select() on the queue's pipe */
427
521
  if (event == NULL) {
428
- int fd = zk->queue->pipe_read;
429
- fd_set rset;
522
+ if (NIL_P(blocking) || (blocking == Qfalse)) {
523
+ goto error;
524
+ }
525
+ else {
526
+ // if we're shutting down, don't enter this section, we don't want to block
527
+ check_debug(!is_shutting_down(self), "method_get_next_event, we're shutting down, don't enter blocking section");
430
528
 
431
- FD_ZERO(&rset);
432
- FD_SET(fd, &rset);
529
+ int fd = zk->queue->pipe_read;
530
+ ssize_t bytes_read = 0;
433
531
 
434
- if (rb_thread_select(fd + 1, &rset, NULL, NULL, NULL) == -1)
435
- rb_raise(rb_eRuntimeError, "select failed: %d", errno);
532
+ // wait for an fd to become readable, opposite of rb_thread_fd_writable
533
+ rb_thread_wait_fd(fd);
436
534
 
437
- if (read(fd, buf, sizeof(buf)) == -1)
438
- rb_raise(rb_eRuntimeError, "read failed: %d", errno);
535
+ // clear all bytes here, we'll catch all the events on subsequent calls
536
+ // (until we run out of events)
537
+ bytes_read = read(fd, buf, sizeof(buf));
439
538
 
440
- if (zk->pending_close)
441
- return Qnil;
539
+ if (bytes_read == -1) {
540
+ rb_raise(rb_eRuntimeError, "read failed: %d", errno);
541
+ }
442
542
 
443
- continue;
543
+ zkrb_debug_inst(self, "read %zd bytes from the queue (%p)'s pipe", bytes_read, zk->queue);
544
+
545
+ continue;
546
+ }
444
547
  }
445
548
 
446
549
  VALUE hash = zkrb_event_to_ruby(event);
447
550
  zkrb_event_free(event);
448
551
  return hash;
449
552
  }
553
+
554
+ error:
555
+ return Qnil;
450
556
  }
451
557
 
452
558
  static VALUE method_has_events(VALUE self) {
@@ -457,27 +563,39 @@ static VALUE method_has_events(VALUE self) {
457
563
  return rb_event;
458
564
  }
459
565
 
460
- static VALUE method_client_id(VALUE self) {
461
- FETCH_DATA_PTR(self, zk);
462
- const clientid_t *id = zoo_client_id(zk->zh);
463
- return UINT2NUM(id->client_id);
464
- }
465
566
 
466
- static VALUE method_signal_pending_close(VALUE self) {
467
- FETCH_DATA_PTR(self, zk);
567
+ // wake up the event loop, used when shutting down
568
+ static VALUE method_wake_event_loop_bang(VALUE self) {
569
+ FETCH_DATA_PTR(self, zk);
468
570
 
469
- zk->pending_close = 1;
571
+ zkrb_debug_inst(self, "Waking event loop: %p", zk->queue);
470
572
  zkrb_signal(zk->queue);
471
573
 
472
574
  return Qnil;
473
- }
575
+ };
474
576
 
475
- static VALUE method_close(VALUE self) {
577
+ static VALUE method_close_handle(VALUE self) {
476
578
  FETCH_DATA_PTR(self, zk);
477
579
 
580
+ if (ZKRBDebugging) {
581
+ /* fprintf(stderr, "CLOSING ZK INSTANCE: obj_id %lx", FIX2LONG(rb_obj_id(self)));*/
582
+ zkrb_debug_inst(self, "CLOSING_ZK_INSTANCE");
583
+ print_zkrb_instance_data(zk);
584
+ }
585
+
586
+ // this is a value on the ruby side we can check to see if destroy_zkrb_instance
587
+ // has been called
588
+ rb_iv_set(self, "@_closed", Qtrue);
589
+
590
+ zkrb_debug_inst(self, "calling destroy_zkrb_instance");
591
+
478
592
  /* Note that after zookeeper_close() returns, ZK handle is invalid */
479
593
  int rc = destroy_zkrb_instance(zk);
480
- return INT2FIX(rc);
594
+
595
+ zkrb_debug("destroy_zkrb_instance returned: %d", rc);
596
+
597
+ return Qnil;
598
+ /* return INT2FIX(rc);*/
481
599
  }
482
600
 
483
601
  static VALUE method_deterministic_conn_order(VALUE self, VALUE yn) {
@@ -490,7 +608,7 @@ static VALUE method_is_unrecoverable(VALUE self) {
490
608
  return is_unrecoverable(zk->zh) == ZINVALIDSTATE ? Qtrue : Qfalse;
491
609
  }
492
610
 
493
- static VALUE method_state(VALUE self) {
611
+ static VALUE method_zkrb_state(VALUE self) {
494
612
  FETCH_DATA_PTR(self, zk);
495
613
  return INT2NUM(zoo_state(zk->zh));
496
614
  }
@@ -500,8 +618,30 @@ static VALUE method_recv_timeout(VALUE self) {
500
618
  return INT2NUM(zoo_recv_timeout(zk->zh));
501
619
  }
502
620
 
503
- // how do you make a class method??
504
- static VALUE method_set_debug_level(VALUE self, VALUE level) {
621
+ /*static VALUE method_client_id(VALUE self) {*/
622
+ /* FETCH_DATA_PTR(self, zk);*/
623
+ /* const clientid_t *id = zoo_client_id(zk->zh);*/
624
+ /* return UINT2NUM(id->client_id);*/
625
+ /*}*/
626
+
627
+
628
+ // returns a CZookeeper::ClientId object with the values set for session_id and passwd
629
+ static VALUE method_client_id(VALUE self) {
630
+ FETCH_DATA_PTR(self, zk);
631
+ const clientid_t *cid = zoo_client_id(zk->zh);
632
+
633
+ VALUE session_id = LL2NUM(cid->client_id);
634
+ VALUE passwd = rb_str_new2(cid->passwd);
635
+
636
+ VALUE client_id_obj = rb_class_new_instance(0, RARRAY_PTR(rb_ary_new()), ZookeeperClientId);
637
+
638
+ rb_funcall(client_id_obj, rb_intern("session_id="), 1, session_id);
639
+ rb_funcall(client_id_obj, rb_intern("passwd="), 1, passwd);
640
+
641
+ return client_id_obj;
642
+ }
643
+
644
+ static VALUE klass_method_zkrb_set_debug_level(VALUE klass, VALUE level) {
505
645
  Check_Type(level, T_FIXNUM);
506
646
  ZKRBDebugging = (FIX2INT(level) == ZOO_LOG_LEVEL_DEBUG);
507
647
  zoo_set_debug_level(FIX2INT(level));
@@ -518,7 +658,8 @@ static void zkrb_define_methods(void) {
518
658
  #define DEFINE_CLASS_METHOD(method, args) { \
519
659
  rb_define_singleton_method(Zookeeper, #method, method_ ## method, args); }
520
660
 
521
- DEFINE_METHOD(init, -1);
661
+ // the number after the method name should be actual arity of C function - 1
662
+ DEFINE_METHOD(zkrb_init, -1);
522
663
  DEFINE_METHOD(get_children, 4);
523
664
  DEFINE_METHOD(exists, 4);
524
665
  DEFINE_METHOD(create, 6);
@@ -528,27 +669,57 @@ static void zkrb_define_methods(void) {
528
669
  DEFINE_METHOD(set_acl, 5);
529
670
  DEFINE_METHOD(get_acl, 3);
530
671
  DEFINE_METHOD(client_id, 0);
531
- DEFINE_METHOD(signal_pending_close, 0);
532
- DEFINE_METHOD(close, 0);
672
+ DEFINE_METHOD(close_handle, 0);
533
673
  DEFINE_METHOD(deterministic_conn_order, 1);
534
674
  DEFINE_METHOD(is_unrecoverable, 0);
535
675
  DEFINE_METHOD(recv_timeout, 1);
536
- DEFINE_METHOD(state, 0);
676
+ DEFINE_METHOD(zkrb_state, 0);
677
+ DEFINE_METHOD(sync, 2);
678
+
537
679
  // TODO
538
680
  // DEFINE_METHOD(add_auth, 3);
539
- // DEFINE_METHOD(async, 1);
540
681
 
541
682
  // methods for the ruby-side event manager
542
- DEFINE_METHOD(get_next_event, 0);
683
+ DEFINE_METHOD(get_next_event, 1);
543
684
  DEFINE_METHOD(has_events, 0);
544
685
 
545
686
  // Make these class methods?
546
- DEFINE_METHOD(set_debug_level, 1);
547
687
  DEFINE_METHOD(zerror, 1);
688
+
689
+ rb_define_singleton_method(Zookeeper, "set_zkrb_debug_level", klass_method_zkrb_set_debug_level, 1);
690
+
691
+ rb_attr(Zookeeper, rb_intern("selectable_io"), 1, 0, Qtrue);
692
+ rb_define_method(Zookeeper, "wake_event_loop!", method_wake_event_loop_bang, 0);
693
+
548
694
  }
695
+
696
+ // class CZookeeper::ClientId
697
+ // attr_accessor :session_id, :passwd
698
+ //
699
+ // def initialize(session_id, passwd)
700
+ // @session_id = session_id
701
+ // @passwd = passwd
702
+ // end
703
+ // end
704
+
705
+ static VALUE zkrb_client_id_method_initialize(VALUE self) {
706
+ rb_iv_set(self, "@session_id", Qnil);
707
+ rb_iv_set(self, "@passwd", Qnil);
708
+ return Qnil;
709
+ }
710
+
711
+
549
712
  void Init_zookeeper_c() {
550
713
  ZKRBDebugging = 0;
714
+
551
715
  /* initialize Zookeeper class */
552
716
  Zookeeper = rb_define_class("CZookeeper", rb_cObject);
553
717
  zkrb_define_methods();
718
+
719
+ ZookeeperClientId = rb_define_class_under(Zookeeper, "ClientId", rb_cObject);
720
+ rb_define_method(ZookeeperClientId, "initialize", zkrb_client_id_method_initialize, 0);
721
+ rb_define_attr(ZookeeperClientId, "session_id", 1, 1);
722
+ rb_define_attr(ZookeeperClientId, "passwd", 1, 1);
554
723
  }
724
+
725
+ // vim:ts=2:sw=2:sts=2:et