zookeeper-ng 1.5.2.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.ctags_paths +1 -0
  3. data/.dotfiles/ruby-gemset +1 -0
  4. data/.dotfiles/ruby-version +1 -0
  5. data/.dotfiles/rvmrc +2 -0
  6. data/.github/workflows/build.yml +57 -0
  7. data/.gitignore +19 -0
  8. data/.gitmodules +3 -0
  9. data/CHANGELOG +408 -0
  10. data/Gemfile +30 -0
  11. data/Guardfile +8 -0
  12. data/LICENSE +23 -0
  13. data/Manifest +29 -0
  14. data/README.markdown +62 -0
  15. data/Rakefile +121 -0
  16. data/cause-abort.rb +117 -0
  17. data/ext/.gitignore +6 -0
  18. data/ext/Rakefile +41 -0
  19. data/ext/c_zookeeper.rb +398 -0
  20. data/ext/common.h +17 -0
  21. data/ext/dbg.h +53 -0
  22. data/ext/depend +5 -0
  23. data/ext/event_lib.c +740 -0
  24. data/ext/event_lib.h +175 -0
  25. data/ext/extconf.rb +103 -0
  26. data/ext/generate_gvl_code.rb +321 -0
  27. data/ext/patches/zkc-3.3.5-network.patch +24 -0
  28. data/ext/patches/zkc-3.4.5-buffer-overflow.patch +11 -0
  29. data/ext/patches/zkc-3.4.5-config.patch +5454 -0
  30. data/ext/patches/zkc-3.4.5-fetch-and-add.patch +16 -0
  31. data/ext/patches/zkc-3.4.5-logging.patch +41 -0
  32. data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
  33. data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
  34. data/ext/zkc-3.4.5.tar.gz +0 -0
  35. data/ext/zkrb.c +1080 -0
  36. data/ext/zkrb_wrapper.c +775 -0
  37. data/ext/zkrb_wrapper.h +350 -0
  38. data/ext/zkrb_wrapper_compat.c +15 -0
  39. data/ext/zkrb_wrapper_compat.h +11 -0
  40. data/ext/zookeeper_base.rb +256 -0
  41. data/java/java_base.rb +501 -0
  42. data/lib/zookeeper/acls.rb +44 -0
  43. data/lib/zookeeper/callbacks.rb +108 -0
  44. data/lib/zookeeper/client.rb +30 -0
  45. data/lib/zookeeper/client_methods.rb +282 -0
  46. data/lib/zookeeper/common/queue_with_pipe.rb +110 -0
  47. data/lib/zookeeper/common.rb +122 -0
  48. data/lib/zookeeper/compatibility.rb +138 -0
  49. data/lib/zookeeper/constants.rb +97 -0
  50. data/lib/zookeeper/continuation.rb +223 -0
  51. data/lib/zookeeper/core_ext.rb +58 -0
  52. data/lib/zookeeper/em_client.rb +55 -0
  53. data/lib/zookeeper/exceptions.rb +135 -0
  54. data/lib/zookeeper/forked.rb +19 -0
  55. data/lib/zookeeper/latch.rb +34 -0
  56. data/lib/zookeeper/logger/forwarding_logger.rb +84 -0
  57. data/lib/zookeeper/logger.rb +39 -0
  58. data/lib/zookeeper/monitor.rb +19 -0
  59. data/lib/zookeeper/rake_tasks.rb +165 -0
  60. data/lib/zookeeper/request_registry.rb +153 -0
  61. data/lib/zookeeper/stat.rb +21 -0
  62. data/lib/zookeeper/version.rb +4 -0
  63. data/lib/zookeeper.rb +115 -0
  64. data/notes.txt +14 -0
  65. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  66. data/spec/c_zookeeper_spec.rb +51 -0
  67. data/spec/chrooted_connection_spec.rb +83 -0
  68. data/spec/compatibilty_spec.rb +8 -0
  69. data/spec/default_watcher_spec.rb +41 -0
  70. data/spec/em_spec.rb +51 -0
  71. data/spec/ext/zookeeper_base_spec.rb +19 -0
  72. data/spec/forked_connection_spec.rb +122 -0
  73. data/spec/latch_spec.rb +24 -0
  74. data/spec/log4j.properties +17 -0
  75. data/spec/shared/all_success_return_values.rb +10 -0
  76. data/spec/shared/connection_examples.rb +1081 -0
  77. data/spec/spec_helper.rb +61 -0
  78. data/spec/support/00_logging.rb +38 -0
  79. data/spec/support/10_spawn_zookeeper.rb +20 -0
  80. data/spec/support/progress_formatter.rb +15 -0
  81. data/spec/support/zookeeper_spec_helpers.rb +96 -0
  82. data/spec/zookeeper_spec.rb +24 -0
  83. data/zookeeper.gemspec +46 -0
  84. data/zoomonkey/duplicates +3 -0
  85. data/zoomonkey/zoomonkey.rb +194 -0
  86. metadata +185 -0
data/ext/zkrb.c ADDED
@@ -0,0 +1,1080 @@
1
+ /* Ruby wrapper for the Zookeeper C API
2
+ * Phillip Pearson <pp@myelin.co.nz>
3
+ * Eric Maland <eric@twitter.com>
4
+ * Brian Wickman <wickman@twitter.com>
5
+ * Jonathan D. Simms <slyphon@gmail.com>
6
+ *
7
+ * This fork is a 90% rewrite of the original. It takes a more evented
8
+ * approach to isolate the ZK state machine from the ruby interpreter via an
9
+ * event queue. It's similar to the ZookeeperFFI version except that it
10
+ * actually works on MRI 1.8.
11
+ *
12
+ *----------------
13
+ * (slyphon)
14
+ *
15
+ * Wickman's implementation was linked against the 'mt' version of the zookeeper
16
+ * library, which is multithreaded at the zookeeper level and is subsequently
17
+ * much more difficult to get to behave properly with the ruby runtime (which
18
+ * he did, and I could never have written).
19
+ *
20
+ * The current implementation has been converted to use the 'st' version of the
21
+ * zookeeper library, which is single threaded and requires a ruby-side event
22
+ * loop. This is essentially a ruby port of the code running in the 'mt'
23
+ * library, with one important difference: It's running in ruby-land. The
24
+ * reason this change is so important is that it's virtually impossible to
25
+ * provide a fork-safe library when you have native threads you don't own
26
+ * running around. If you fork when a thread holds a mutex, and that thread
27
+ * is not the fork-caller, that mutex can never be unlocked, and is therefore
28
+ * a ticking time-bomb in the child. The only way to guarantee safety is to
29
+ * either replace all of your mutexes and conditions and such after a fork
30
+ * (which is what we do on the ruby side), or avoid the problem altogether
31
+ * and not use a multithreaded library on the backend. Since we can't replace
32
+ * mutexes in the zookeeper code, we opt for the latter solution.
33
+ *
34
+ * The ruby code runs the event loop in a thread that will never cause a fork()
35
+ * to occur. This way, when fork() is called, the event thread will be dead
36
+ * in the child, guaranteeing that the child can safely be cleaned up.
37
+ *
38
+ * In that cleanup, there is a nasty (and brutishly effective) hack that makes
39
+ * the fork case work. We keep track of the pid that allocated the
40
+ * zkrb_instance_data_t, and if at destruction time we see that a fork has
41
+ * happened, we reach inside the zookeeper handle (zk->zh), and close the
42
+ * open socket it's got before calling zookeeper_close. This prevents
43
+ * corruption of the client/server state. Without this code, zookeeper_close
44
+ * in the child would actually send an "Ok, we're closing" message with the
45
+ * parent's session id, causing the parent to hit an assert() case in
46
+ * zookeeper_process, and cause a SIGABRT. With this code in place, we get back
47
+ * a ZCONNECTIONLOSS from zookeeper_close in the child (which we ignore), and
48
+ * the parent continues on.
49
+ *
50
+ * You will notice below we undef 'THREADED', which would be set if we were
51
+ * using the 'mt' library. We also conditionally include additional cases
52
+ * ('SYNC', 'SYNC_WATCH') inside of some of the methods defined here. These
53
+ * would be valid when running the 'mt' library, but since we have a ruby layer
54
+ * to provide a sync front-end to an async backend, these cases should never be
55
+ * hit, and instead will raise exceptions.
56
+ *
57
+ * NOTE: This file depends on exception classes defined in lib/zookeeper/exceptions.rb
58
+ *
59
+ * -------
60
+ *
61
+ * @rectalogic: any time you create a ruby value in C, and so there are no
62
+ * references to it in the VM except for your variable, and you then call into
63
+ * the VM (allowing a GC), and your reference is on the stack, then it needs to
64
+ * be volatile
65
+ *
66
+ */
67
+
68
+ #include "ruby.h"
69
+
70
+ #ifdef ZKRB_RUBY_187
71
+ #include "rubyio.h"
72
+ #else
73
+ #include "ruby/io.h"
74
+ #endif
75
+
76
+ #ifndef HAVE_RB_THREAD_FD_SELECT
77
+ #define rb_fdset_t fd_set
78
+ #define rb_fd_isset(n, f) FD_ISSET(n, f)
79
+ #define rb_fd_init(f) FD_ZERO(f)
80
+ #define rb_fd_zero(f) FD_ZERO(f)
81
+ #define rb_fd_set(n, f) FD_SET(n, f)
82
+ #define rb_fd_clr(n, f) FD_CLR(n, f)
83
+ #define rb_fd_term(f)
84
+ #define rb_thread_fd_select rb_thread_select
85
+ #endif
86
+
87
+ #include "zookeeper/zookeeper.h"
88
+ #include <errno.h>
89
+ #include <stdio.h>
90
+ #include <stdlib.h>
91
+ #include <unistd.h>
92
+ #include <sys/fcntl.h>
93
+ #include <pthread.h>
94
+ #include <inttypes.h>
95
+ #include <time.h>
96
+ #include <arpa/inet.h>
97
+ #include <netinet/in.h>
98
+
99
+ #include "common.h"
100
+ #include "event_lib.h"
101
+ #include "zkrb_wrapper.h"
102
+ #include "dbg.h"
103
+
104
+ static VALUE mZookeeper = Qnil; // the Zookeeper module
105
+ static VALUE CZookeeper = Qnil; // the Zookeeper::CZookeeper class
106
+ static VALUE ZookeeperClientId = Qnil;
107
+ static VALUE mZookeeperExceptions = Qnil; // the Zookeeper::Exceptions module
108
+ static VALUE eHandleClosedException = Qnil; // raised when we don't have a valid handle in FETCH_DATA_PTR
109
+
110
+ // slyphon: possibly add a lock to this for synchronizing during get_next_event
111
+
112
+ struct zkrb_instance_data {
113
+ zhandle_t *zh;
114
+ clientid_t myid;
115
+ zkrb_queue_t *queue;
116
+ long object_id; // the ruby object this instance data is associated with
117
+ pid_t orig_pid;
118
+ };
119
+
120
+ typedef struct zkrb_instance_data zkrb_instance_data_t;
121
+
122
+ typedef enum {
123
+ SYNC = 0,
124
+ ASYNC = 1,
125
+ SYNC_WATCH = 2,
126
+ ASYNC_WATCH = 3
127
+ } zkrb_call_type;
128
+
129
+ inline static const char* call_type_to_str(zkrb_call_type ct) {
130
+ const char *rv = NULL;
131
+ switch (ct) {
132
+ case SYNC:
133
+ rv="SYNC";
134
+ break;
135
+ case ASYNC:
136
+ rv="ASYNC";
137
+ break;
138
+ case SYNC_WATCH:
139
+ rv="SYNC_WATCH";
140
+ break;
141
+ case ASYNC_WATCH:
142
+ rv="ASYNC_WATCH";
143
+ break;
144
+ }
145
+ return rv;
146
+ }
147
+
148
+ inline static void assert_valid_params(VALUE reqid, VALUE path) {
149
+ switch (TYPE(reqid)) {
150
+ case T_FIXNUM:
151
+ case T_BIGNUM:
152
+ break;
153
+ default:
154
+ rb_raise(rb_eTypeError, "reqid must be Fixnum/Bignum");
155
+ }
156
+
157
+ Check_Type(path, T_STRING);
158
+ }
159
+
160
+ inline static zkrb_call_type get_call_type(VALUE async, VALUE watch) {
161
+ if (RTEST(async)) {
162
+ return RTEST(watch) ? ASYNC_WATCH : ASYNC;
163
+ } else {
164
+ return RTEST(watch) ? SYNC_WATCH : SYNC;
165
+ }
166
+ }
167
+
168
+ inline static void raise_invalid_call_type_err(zkrb_call_type call_type) {
169
+ rb_raise(rb_eRuntimeError, "hit the default case, call_type: %s", call_type_to_str(call_type));
170
+ }
171
+
172
+ #define IS_SYNC(zkrbcall) ((zkrbcall)==SYNC || (zkrbcall)==SYNC_WATCH)
173
+ #define IS_ASYNC(zkrbcall) ((zkrbcall)==ASYNC || (zkrbcall)==ASYNC_WATCH)
174
+
175
+ #define FETCH_DATA_PTR(SELF, ZK) \
176
+ zkrb_instance_data_t * ZK; \
177
+ Data_Get_Struct(rb_iv_get(SELF, "@_data"), zkrb_instance_data_t, ZK); \
178
+ if ((ZK)->zh == NULL) \
179
+ rb_raise(eHandleClosedException, "zookeeper handle is closed")
180
+
181
+ #define STANDARD_PREAMBLE(SELF, ZK, REQID, PATH, ASYNC, WATCH, CALL_TYPE) \
182
+ assert_valid_params(REQID, PATH); \
183
+ FETCH_DATA_PTR(SELF, ZK); \
184
+ zkrb_call_type CALL_TYPE = get_call_type(ASYNC, WATCH); \
185
+
186
+ #define CTX_ALLOC(ZK,REQID) zkrb_calling_context_alloc(NUM2LL(REQID), ZK->queue)
187
+
188
+ static void hexbufify(char *dest, const char *src, int len) {
189
+ int i=0;
190
+
191
+ for (i=0; i < len; i++) {
192
+ sprintf(&dest[i*2], "%x", src[i]);
193
+ }
194
+ }
195
+
196
+ inline static int we_are_forked(zkrb_instance_data_t *zk) {
197
+ int rv=0;
198
+
199
+ if ((!!zk) && (zk->orig_pid != getpid())) {
200
+ rv=1;
201
+ }
202
+
203
+ return rv;
204
+ }
205
+
206
+ static int destroy_zkrb_instance(zkrb_instance_data_t* zk) {
207
+ int rv = ZOK;
208
+
209
+ zkrb_debug("destroy_zkrb_instance, zk_local_ctx: %p, zh: %p, queue: %p", zk, zk->zh, zk->queue);
210
+
211
+ if (zk->zh) {
212
+ const void *ctx = zoo_get_context(zk->zh);
213
+ /* Note that after zookeeper_close() returns, ZK handle is invalid */
214
+ zkrb_debug("obj_id: %lx, calling zookeeper_close", zk->object_id);
215
+
216
+ if (we_are_forked(zk)) {
217
+ zkrb_debug("FORK DETECTED! orig_pid: %d, current pid: %d, "
218
+ "using socket-closing hack before zookeeper_close", zk->orig_pid, getpid());
219
+
220
+ int fd = ((int *)zk->zh)[0]; // nasty, brutish, and wonderfully effective hack (see above)
221
+ close(fd);
222
+
223
+ }
224
+
225
+ rv = zookeeper_close(zk->zh);
226
+
227
+ zkrb_debug("obj_id: %lx, zookeeper_close returned %d, calling context: %p", zk->object_id, rv, ctx);
228
+ zkrb_calling_context_free((zkrb_calling_context *) ctx);
229
+ }
230
+
231
+ zk->zh = NULL;
232
+
233
+ if (zk->queue) {
234
+ zkrb_debug("obj_id: %lx, freeing queue pointer: %p", zk->object_id, zk->queue);
235
+ zkrb_queue_free(zk->queue);
236
+ }
237
+
238
+ zk->queue = NULL;
239
+
240
+ return rv;
241
+ }
242
+
243
+ static void free_zkrb_instance_data(zkrb_instance_data_t* ptr) {
244
+ destroy_zkrb_instance(ptr);
245
+ }
246
+
247
+ VALUE alloc_zkrb_instance(VALUE klass) {
248
+ zkrb_instance_data_t* zk = ZALLOC_N(zkrb_instance_data_t, 1);
249
+ return Data_Wrap_Struct(klass, NULL, free_zkrb_instance_data, zk);
250
+ }
251
+
252
+ static void print_zkrb_instance_data(zkrb_instance_data_t* ptr) {
253
+ fprintf(stderr, "zkrb_instance_data (%p) {\n", ptr);
254
+ fprintf(stderr, " zh = %p\n", ptr->zh);
255
+ fprintf(stderr, " { state = %d }\n", zoo_state(ptr->zh));
256
+ fprintf(stderr, " id = %"PRId64"\n", ptr->myid.client_id); // PRId64 defined in inttypes.h
257
+ fprintf(stderr, " q = %p\n", ptr->queue);
258
+ fprintf(stderr, " obj_id = %lx\n", ptr->object_id);
259
+ fprintf(stderr, "}\n");
260
+ }
261
+
262
+ #define receive_timeout_msec(self) rb_iv_get(self, "@_receive_timeout_msec")
263
+
264
+ inline static void zkrb_debug_clientid_t(const clientid_t *cid) {
265
+ int pass_len = sizeof(cid->passwd);
266
+ int hex_len = 2 * pass_len + 1;
267
+ char buf[hex_len];
268
+ hexbufify(buf, cid->passwd, pass_len);
269
+
270
+ zkrb_debug("myid, client_id: %"PRId64", passwd: %*s", cid->client_id, hex_len, buf);
271
+ }
272
+
273
+ static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
274
+ VALUE hostPort=Qnil;
275
+ VALUE options=Qnil;
276
+
277
+ rb_scan_args(argc, argv, "11", &hostPort, &options);
278
+
279
+ if (NIL_P(options)) {
280
+ options = rb_hash_new();
281
+ } else {
282
+ Check_Type(options, T_HASH);
283
+ }
284
+
285
+ Check_Type(hostPort, T_STRING);
286
+
287
+ // Look up :zkc_log_level
288
+ // VALUE log_level = rb_hash_aref(options, ID2SYM(rb_intern("zkc_log_level")));
289
+ // if (NIL_P(log_level)) {
290
+ // zoo_set_debug_level(0); // no log messages
291
+ // } else {
292
+ // Check_Type(log_level, T_FIXNUM);
293
+ // zoo_set_debug_level(FIX2INT(log_level));
294
+ // }
295
+
296
+ volatile VALUE data;
297
+ zkrb_instance_data_t *zk_local_ctx;
298
+ data = Data_Make_Struct(CZookeeper, zkrb_instance_data_t, 0, free_zkrb_instance_data, zk_local_ctx);
299
+
300
+ // Look up :session_id and :session_passwd
301
+ VALUE session_id = rb_hash_aref(options, ID2SYM(rb_intern("session_id")));
302
+ VALUE password = rb_hash_aref(options, ID2SYM(rb_intern("session_passwd")));
303
+ if (!NIL_P(session_id) && !NIL_P(password)) {
304
+ Check_Type(password, T_STRING);
305
+
306
+ zk_local_ctx->myid.client_id = NUM2LL(session_id);
307
+ strncpy(zk_local_ctx->myid.passwd, RSTRING_PTR(password), 16);
308
+ }
309
+
310
+ zk_local_ctx->queue = zkrb_queue_alloc();
311
+
312
+ if (zk_local_ctx->queue == NULL)
313
+ rb_raise(rb_eRuntimeError, "could not allocate zkrb queue!");
314
+
315
+ zoo_deterministic_conn_order(0);
316
+
317
+ zkrb_calling_context *ctx =
318
+ zkrb_calling_context_alloc(ZKRB_GLOBAL_REQ, zk_local_ctx->queue);
319
+
320
+ zk_local_ctx->object_id = FIX2LONG(rb_obj_id(self));
321
+
322
+ zk_local_ctx->zh =
323
+ zookeeper_init(
324
+ RSTRING_PTR(hostPort), // const char *host
325
+ zkrb_state_callback, // watcher_fn
326
+ receive_timeout_msec(self), // recv_timeout
327
+ &zk_local_ctx->myid, // cilentid_t
328
+ ctx, // void *context
329
+ 0); // flags
330
+
331
+ zkrb_debug("method_zkrb_init, zk_local_ctx: %p, zh: %p, queue: %p, calling_ctx: %p",
332
+ zk_local_ctx, zk_local_ctx->zh, zk_local_ctx->queue, ctx);
333
+
334
+ if (!zk_local_ctx->zh) {
335
+ rb_raise(rb_eRuntimeError, "error connecting to zookeeper: %d", errno);
336
+ }
337
+
338
+ zk_local_ctx->orig_pid = getpid();
339
+
340
+ rb_iv_set(self, "@_data", data);
341
+ rb_funcall(self, rb_intern("zkc_set_running_and_notify!"), 0);
342
+
343
+ return Qnil;
344
+ }
345
+
346
+ static VALUE method_get_children(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
347
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, call_type);
348
+
349
+ VALUE output = Qnil;
350
+ struct String_vector strings;
351
+ struct Stat stat;
352
+
353
+ int rc = 0;
354
+ switch (call_type) {
355
+
356
+ #ifdef THREADED
357
+ case SYNC:
358
+ rc = zkrb_call_zoo_get_children2(
359
+ zk->zh, RSTRING_PTR(path), 0, &strings, &stat);
360
+ break;
361
+
362
+ case SYNC_WATCH:
363
+ rc = zkrb_call_zoo_wget_children2(
364
+ zk->zh, RSTRING_PTR(path), zkrb_state_callback, CTX_ALLOC(zk, reqid), &strings, &stat);
365
+ break;
366
+ #endif
367
+
368
+ case ASYNC:
369
+ rc = zkrb_call_zoo_aget_children2(
370
+ zk->zh, RSTRING_PTR(path), 0, zkrb_strings_stat_callback, CTX_ALLOC(zk, reqid));
371
+ break;
372
+
373
+ case ASYNC_WATCH:
374
+ rc = zkrb_call_zoo_awget_children2(
375
+ zk->zh, RSTRING_PTR(path), zkrb_state_callback, CTX_ALLOC(zk, reqid), zkrb_strings_stat_callback, CTX_ALLOC(zk, reqid));
376
+ break;
377
+
378
+ default:
379
+ raise_invalid_call_type_err(call_type);
380
+ break;
381
+ }
382
+
383
+ output = rb_ary_new();
384
+ rb_ary_push(output, INT2FIX(rc));
385
+ if (IS_SYNC(call_type) && rc == ZOK) {
386
+ rb_ary_push(output, zkrb_string_vector_to_ruby(&strings));
387
+ rb_ary_push(output, zkrb_stat_to_rarray(&stat));
388
+ }
389
+ return output;
390
+ }
391
+
392
+ static VALUE method_exists(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
393
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, call_type);
394
+
395
+ VALUE output = Qnil;
396
+ struct Stat stat;
397
+
398
+ int rc = 0;
399
+ switch (call_type) {
400
+
401
+ #ifdef THREADED
402
+ case SYNC:
403
+ rc = zkrb_call_zoo_exists(zk->zh, RSTRING_PTR(path), 0, &stat);
404
+ break;
405
+
406
+ case SYNC_WATCH:
407
+ rc = zkrb_call_zoo_wexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, CTX_ALLOC(zk, reqid), &stat);
408
+ break;
409
+ #endif
410
+
411
+ case ASYNC:
412
+ rc = zkrb_call_zoo_aexists(zk->zh, RSTRING_PTR(path), 0, zkrb_stat_callback, CTX_ALLOC(zk, reqid));
413
+ break;
414
+
415
+ case ASYNC_WATCH:
416
+ rc = zkrb_call_zoo_awexists(zk->zh, RSTRING_PTR(path), zkrb_state_callback, CTX_ALLOC(zk, reqid), zkrb_stat_callback, CTX_ALLOC(zk, reqid));
417
+ break;
418
+
419
+ default:
420
+ raise_invalid_call_type_err(call_type);
421
+ break;
422
+ }
423
+
424
+ output = rb_ary_new();
425
+ rb_ary_push(output, INT2FIX(rc));
426
+ if (IS_SYNC(call_type) && rc == ZOK) {
427
+ rb_ary_push(output, zkrb_stat_to_rarray(&stat));
428
+ }
429
+ return output;
430
+ }
431
+
432
+ // this method is *only* called asynchronously
433
+ static VALUE method_sync(VALUE self, VALUE reqid, VALUE path) {
434
+ int rc = ZOK;
435
+
436
+ // don't use STANDARD_PREAMBLE here b/c we don't need to determine call_type
437
+ assert_valid_params(reqid, path);
438
+ FETCH_DATA_PTR(self, zk);
439
+
440
+ rc = zkrb_call_zoo_async(zk->zh, RSTRING_PTR(path), zkrb_string_callback, CTX_ALLOC(zk, reqid));
441
+
442
+ return INT2FIX(rc);
443
+ }
444
+
445
+ static VALUE method_add_auth(VALUE self, VALUE reqid, VALUE scheme, VALUE cert) {
446
+ int rc = ZOK;
447
+
448
+ Check_Type(scheme, T_STRING);
449
+ Check_Type(cert, T_STRING);
450
+
451
+ FETCH_DATA_PTR(self, zk);
452
+
453
+ rc = zkrb_call_zoo_add_auth(zk->zh, RSTRING_PTR(scheme), RSTRING_PTR(cert), RSTRING_LEN(cert), zkrb_void_callback, CTX_ALLOC(zk, reqid));
454
+
455
+ return INT2FIX(rc);
456
+ }
457
+
458
+
459
+ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE async, VALUE acls, VALUE flags) {
460
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, Qfalse, call_type);
461
+ VALUE output = Qnil;
462
+
463
+ if (data != Qnil) Check_Type(data, T_STRING);
464
+ Check_Type(flags, T_FIXNUM);
465
+ const char *data_ptr = (data == Qnil) ? NULL : RSTRING_PTR(data);
466
+ ssize_t data_len = (data == Qnil) ? -1 : RSTRING_LEN(data);
467
+
468
+ struct ACL_vector *aclptr = NULL;
469
+ if (acls != Qnil) { aclptr = zkrb_ruby_to_aclvector(acls); }
470
+ char realpath[16384];
471
+
472
+ int invalid_call_type=0;
473
+
474
+ int rc = 0;
475
+ switch (call_type) {
476
+
477
+ #ifdef THREADED
478
+ case SYNC:
479
+ // casting data_len to int is OK as you can only store 1MB in zookeeper
480
+ rc = zkrb_call_zoo_create(zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, aclptr, FIX2INT(flags), realpath, sizeof(realpath));
481
+ break;
482
+ #endif
483
+
484
+ case ASYNC:
485
+ rc = zkrb_call_zoo_acreate(zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, aclptr, FIX2INT(flags), zkrb_string_callback, CTX_ALLOC(zk, reqid));
486
+ break;
487
+
488
+ default:
489
+ invalid_call_type=1;
490
+ break;
491
+ }
492
+
493
+ if (aclptr) {
494
+ deallocate_ACL_vector(aclptr);
495
+ free(aclptr);
496
+ }
497
+
498
+ if (invalid_call_type) raise_invalid_call_type_err(call_type);
499
+
500
+ output = rb_ary_new();
501
+ rb_ary_push(output, INT2FIX(rc));
502
+ if (IS_SYNC(call_type) && rc == ZOK) {
503
+ return rb_ary_push(output, rb_str_new2(realpath));
504
+ }
505
+ return output;
506
+ }
507
+
508
+ static VALUE method_delete(VALUE self, VALUE reqid, VALUE path, VALUE version, VALUE async) {
509
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, Qfalse, call_type);
510
+ Check_Type(version, T_FIXNUM);
511
+
512
+ int rc = 0;
513
+ switch (call_type) {
514
+
515
+ #ifdef THREADED
516
+ case SYNC:
517
+ rc = zkrb_call_zoo_delete(zk->zh, RSTRING_PTR(path), FIX2INT(version));
518
+ break;
519
+ #endif
520
+
521
+ case ASYNC:
522
+ rc = zkrb_call_zoo_adelete(zk->zh, RSTRING_PTR(path), FIX2INT(version), zkrb_void_callback, CTX_ALLOC(zk, reqid));
523
+ break;
524
+
525
+ default:
526
+ raise_invalid_call_type_err(call_type);
527
+ break;
528
+ }
529
+
530
+ return INT2FIX(rc);
531
+ }
532
+
533
+ #define MAX_ZNODE_SIZE 1048576
534
+
535
+ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
536
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, call_type);
537
+
538
+ VALUE output = Qnil;
539
+
540
+ int data_len = MAX_ZNODE_SIZE;
541
+ struct Stat stat;
542
+
543
+ char * data = NULL;
544
+ if (IS_SYNC(call_type)) {
545
+ data = malloc(MAX_ZNODE_SIZE); /* ugh */
546
+ memset(data, 0, MAX_ZNODE_SIZE);
547
+ }
548
+
549
+ int rc, invalid_call_type=0;
550
+
551
+ switch (call_type) {
552
+
553
+ #ifdef THREADED
554
+ case SYNC:
555
+ rc = zkrb_call_zoo_get(zk->zh, RSTRING_PTR(path), 0, data, &data_len, &stat);
556
+ break;
557
+
558
+ case SYNC_WATCH:
559
+ rc = zkrb_call_zoo_wget(
560
+ zk->zh, RSTRING_PTR(path), zkrb_state_callback, CTX_ALLOC(zk, reqid), data, &data_len, &stat);
561
+ break;
562
+ #endif
563
+
564
+ case ASYNC:
565
+ rc = zkrb_call_zoo_aget(zk->zh, RSTRING_PTR(path), 0, zkrb_data_callback, CTX_ALLOC(zk, reqid));
566
+ break;
567
+
568
+ case ASYNC_WATCH:
569
+ // first ctx is a watch, second is the async callback
570
+ rc = zkrb_call_zoo_awget(
571
+ zk->zh, RSTRING_PTR(path), zkrb_state_callback, CTX_ALLOC(zk, reqid), zkrb_data_callback, CTX_ALLOC(zk, reqid));
572
+ break;
573
+
574
+ default:
575
+ invalid_call_type=1;
576
+ goto cleanup;
577
+ break;
578
+ }
579
+
580
+ output = rb_ary_new();
581
+ rb_ary_push(output, INT2FIX(rc));
582
+ if (IS_SYNC(call_type) && rc == ZOK) {
583
+ if (data_len == -1)
584
+ rb_ary_push(output, Qnil); /* No data associated with path */
585
+ else
586
+ rb_ary_push(output, rb_str_new(data, data_len));
587
+ rb_ary_push(output, zkrb_stat_to_rarray(&stat));
588
+ }
589
+
590
+ cleanup:
591
+ free(data);
592
+ if (invalid_call_type) raise_invalid_call_type_err(call_type);
593
+ return output;
594
+ }
595
+
596
+ static VALUE method_set(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE async, VALUE version) {
597
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, Qfalse, call_type);
598
+
599
+ VALUE output = Qnil;
600
+ struct Stat stat;
601
+
602
+ if (data != Qnil) Check_Type(data, T_STRING);
603
+
604
+ const char *data_ptr = (data == Qnil) ? NULL : RSTRING_PTR(data);
605
+ ssize_t data_len = (data == Qnil) ? -1 : RSTRING_LEN(data);
606
+
607
+ int rc=ZOK;
608
+ switch (call_type) {
609
+
610
+ #ifdef THREADED
611
+ case SYNC:
612
+ rc = zkrb_call_zoo_set2(zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, FIX2INT(version), &stat);
613
+ break;
614
+ #endif
615
+
616
+ case ASYNC:
617
+ rc = zkrb_call_zoo_aset(
618
+ zk->zh, RSTRING_PTR(path), data_ptr, (int)data_len, FIX2INT(version), zkrb_stat_callback, CTX_ALLOC(zk, reqid));
619
+ break;
620
+
621
+ default:
622
+ raise_invalid_call_type_err(call_type);
623
+ break;
624
+ }
625
+
626
+ output = rb_ary_new();
627
+ rb_ary_push(output, INT2FIX(rc));
628
+ if (IS_SYNC(call_type) && rc == ZOK) {
629
+ rb_ary_push(output, zkrb_stat_to_rarray(&stat));
630
+ }
631
+ return output;
632
+ }
633
+
634
+ static VALUE method_set_acl(VALUE self, VALUE reqid, VALUE path, VALUE acls, VALUE async, VALUE version) {
635
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, Qfalse, call_type);
636
+
637
+ struct ACL_vector * aclptr = zkrb_ruby_to_aclvector(acls);
638
+
639
+ int rc=ZOK, invalid_call_type=0;
640
+ switch (call_type) {
641
+
642
+ #ifdef THREADED
643
+ case SYNC:
644
+ rc = zkrb_call_zoo_set_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr);
645
+ break;
646
+ #endif
647
+
648
+ case ASYNC:
649
+ rc = zkrb_call_zoo_aset_acl(zk->zh, RSTRING_PTR(path), FIX2INT(version), aclptr, zkrb_void_callback, CTX_ALLOC(zk, reqid));
650
+ break;
651
+
652
+ default:
653
+ invalid_call_type=1;
654
+ break;
655
+ }
656
+
657
+ deallocate_ACL_vector(aclptr);
658
+ free(aclptr);
659
+
660
+ if (invalid_call_type) raise_invalid_call_type_err(call_type);
661
+
662
+ return INT2FIX(rc);
663
+ }
664
+
665
+ static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
666
+ STANDARD_PREAMBLE(self, zk, reqid, path, async, Qfalse, call_type);
667
+
668
+ VALUE output = Qnil;
669
+ struct ACL_vector acls;
670
+ struct Stat stat;
671
+
672
+ int rc=ZOK;
673
+ switch (call_type) {
674
+
675
+ #ifdef THREADED
676
+ case SYNC:
677
+ rc = zkrb_call_zoo_get_acl(zk->zh, RSTRING_PTR(path), &acls, &stat);
678
+ break;
679
+ #endif
680
+
681
+ case ASYNC:
682
+ rc = zkrb_call_zoo_aget_acl(zk->zh, RSTRING_PTR(path), zkrb_acl_callback, CTX_ALLOC(zk, reqid));
683
+ break;
684
+
685
+ default:
686
+ raise_invalid_call_type_err(call_type);
687
+ break;
688
+ }
689
+
690
+ output = rb_ary_new();
691
+ rb_ary_push(output, INT2FIX(rc));
692
+ if (IS_SYNC(call_type) && rc == ZOK) {
693
+ rb_ary_push(output, zkrb_acl_vector_to_ruby(&acls));
694
+ rb_ary_push(output, zkrb_stat_to_rarray(&stat));
695
+ deallocate_ACL_vector(&acls);
696
+ }
697
+ return output;
698
+ }
699
+
700
+ #define is_running(self) RTEST(rb_iv_get(self, "@_running"))
701
+ #define is_closed(self) RTEST(rb_iv_get(self, "@_closed"))
702
+ #define is_shutting_down(self) RTEST(rb_iv_get(self, "@_shutting_down"))
703
+
704
+ static VALUE method_zkrb_get_next_event(VALUE self, VALUE blocking) {
705
+ // dbg.h
706
+ check_debug(!is_closed(self), "we are closed, not trying to get event");
707
+
708
+ char buf[64];
709
+ FETCH_DATA_PTR(self, zk);
710
+
711
+ for (;;) {
712
+ check_debug(!is_closed(self), "we're closed in the middle of method_zkrb_get_next_event, bailing");
713
+
714
+ zkrb_event_t *event = zkrb_dequeue(zk->queue, 1);
715
+
716
+ if (event == NULL) {
717
+ if (NIL_P(blocking) || (blocking == Qfalse)) {
718
+ goto error;
719
+ }
720
+ else {
721
+ // if we're shutting down, don't enter this section, we don't want to block
722
+ check_debug(!is_shutting_down(self), "method_zkrb_get_next_event, we're shutting down, don't enter blocking section");
723
+
724
+ int fd = zk->queue->pipe_read;
725
+ ssize_t bytes_read = 0;
726
+
727
+ // wait for an fd to become readable, opposite of rb_thread_fd_writable
728
+ rb_thread_wait_fd(fd);
729
+
730
+ // clear all bytes here, we'll catch all the events on subsequent calls
731
+ // (until we run out of events)
732
+ bytes_read = read(fd, buf, sizeof(buf));
733
+
734
+ if (bytes_read == -1) {
735
+ rb_raise(rb_eRuntimeError, "read failed: %d", errno);
736
+ }
737
+
738
+ zkrb_debug_inst(self, "read %zd bytes from the queue (%p)'s pipe", bytes_read, zk->queue);
739
+
740
+ continue;
741
+ }
742
+ }
743
+
744
+ VALUE hash = zkrb_event_to_ruby(event);
745
+ zkrb_event_free(event);
746
+ return hash;
747
+ }
748
+
749
+ error:
750
+ return Qnil;
751
+ }
752
+
753
+ // the single threaded version of this call. will go away when we do direct
754
+ // event delivery (soon)
755
+ static VALUE method_zkrb_get_next_event_st(VALUE self) {
756
+ volatile VALUE rval = Qnil;
757
+
758
+ if (is_closed(self)) {
759
+ zkrb_debug("we are closed, not gonna try to get an event");
760
+ return Qnil;
761
+ }
762
+
763
+ FETCH_DATA_PTR(self, zk);
764
+
765
+ zkrb_event_t *event = zkrb_dequeue(zk->queue, 0);
766
+
767
+ if (event != NULL) {
768
+ rval = zkrb_event_to_ruby(event);
769
+ zkrb_event_free(event);
770
+
771
+ #if THREADED
772
+ int fd = zk->queue->pipe_read;
773
+
774
+ // we don't care in this case. this is just until i can remove the self
775
+ // pipe from the queue
776
+ char b[128];
777
+ while(read(fd, b, sizeof(b)) == sizeof(b)){}
778
+ #endif
779
+ }
780
+
781
+ return rval;
782
+ }
783
+
784
+ inline static int get_self_pipe_read_fd(VALUE self) {
785
+ rb_io_t *fptr;
786
+ VALUE pipe_read = rb_iv_get(self, "@pipe_read");
787
+
788
+ if (NIL_P(pipe_read))
789
+ rb_raise(rb_eRuntimeError, "@pipe_read was nil!");
790
+
791
+ GetOpenFile(pipe_read, fptr);
792
+
793
+ rb_io_check_readable(fptr);
794
+
795
+ #ifdef ZKRB_RUBY_187
796
+ return fileno(fptr->f);
797
+ #else
798
+ return fptr->fd;
799
+ #endif
800
+ }
801
+
802
+ static VALUE method_zkrb_iterate_event_loop(VALUE self) {
803
+ FETCH_DATA_PTR(self, zk);
804
+
805
+ rb_fdset_t rfds, wfds, efds;
806
+ rb_fd_init(&rfds); rb_fd_init(&wfds); rb_fd_init(&efds);
807
+
808
+ int fd = 0, interest = 0, events = 0, rc = 0, maxfd = 0, irc = 0, prc = 0;
809
+ struct timeval tv;
810
+
811
+ irc = zookeeper_interest(zk->zh, &fd, &interest, &tv);
812
+
813
+ if (fd != -1) {
814
+ if (interest & ZOOKEEPER_READ) {
815
+ rb_fd_set(fd, &rfds);
816
+ } else {
817
+ rb_fd_clr(fd, &rfds);
818
+ }
819
+ if (interest & ZOOKEEPER_WRITE) {
820
+ rb_fd_set(fd, &wfds);
821
+ } else {
822
+ rb_fd_clr(fd, &wfds);
823
+ }
824
+ } else {
825
+ fd = 0;
826
+ }
827
+
828
+ // add our self-pipe to the read set, allow us to wake up in case our attention is needed
829
+ int pipe_r_fd = get_self_pipe_read_fd(self);
830
+
831
+ rb_fd_set(pipe_r_fd, &rfds);
832
+
833
+ maxfd = (pipe_r_fd > fd) ? pipe_r_fd : fd;
834
+
835
+ rc = rb_thread_fd_select(maxfd+1, &rfds, &wfds, &efds, &tv);
836
+
837
+ if (rc > 0) {
838
+ if (rb_fd_isset(fd, &rfds)) {
839
+ events |= ZOOKEEPER_READ;
840
+ }
841
+ if (rb_fd_isset(fd, &wfds)) {
842
+ events |= ZOOKEEPER_WRITE;
843
+ }
844
+
845
+ // we got woken up by the self-pipe
846
+ if (rb_fd_isset(pipe_r_fd, &rfds)) {
847
+ // one event has awoken us, so we clear one event from the pipe
848
+ char b[1];
849
+
850
+ if (read(pipe_r_fd, b, 1) < 0) {
851
+ rb_raise(rb_eRuntimeError, "read from pipe failed: %s", clean_errno());
852
+ }
853
+ }
854
+ }
855
+ else if (rc == 0) {
856
+ // zkrb_debug("timed out waiting for descriptor to be ready. interest=%d fd=%d pipe_r_fd=%d maxfd=%d irc=%d timeout=%f",
857
+ // interest, fd, pipe_r_fd, maxfd, irc, tv.tv_sec + (tv.tv_usec/ 1000.0 / 1000.0));
858
+ }
859
+ else {
860
+ log_err("select returned an error: rc=%d interest=%d fd=%d pipe_r_fd=%d maxfd=%d irc=%d timeout=%f",
861
+ rc, interest, fd, pipe_r_fd, maxfd, irc, tv.tv_sec + (tv.tv_usec/ 1000.0 / 1000.0));
862
+ }
863
+
864
+ prc = zookeeper_process(zk->zh, events);
865
+
866
+ if (rc == 0) {
867
+ zkrb_debug("timed out waiting for descriptor to be ready. prc=%d interest=%d fd=%d pipe_r_fd=%d maxfd=%d irc=%d timeout=%f",
868
+ prc, interest, fd, pipe_r_fd, maxfd, irc, tv.tv_sec + (tv.tv_usec/ 1000.0 / 1000.0));
869
+ }
870
+
871
+ rb_fd_term(&rfds);
872
+ rb_fd_term(&wfds);
873
+ rb_fd_term(&efds);
874
+ return INT2FIX(prc);
875
+ }
876
+
877
+ static VALUE method_has_events(VALUE self) {
878
+ VALUE rb_event;
879
+ FETCH_DATA_PTR(self, zk);
880
+
881
+ rb_event = zkrb_peek(zk->queue) != NULL ? Qtrue : Qfalse;
882
+ return rb_event;
883
+ }
884
+
885
+ static VALUE method_zoo_set_log_level(VALUE self, VALUE level) {
886
+ Check_Type(level, T_FIXNUM);
887
+ zoo_set_debug_level(FIX2INT(level));
888
+ return Qnil;
889
+ }
890
+
891
+ static VALUE method_close_handle(VALUE self) {
892
+ FETCH_DATA_PTR(self, zk);
893
+
894
+ if (ZKRBDebugging) {
895
+ zkrb_debug_inst(self, "CLOSING_ZK_INSTANCE");
896
+ print_zkrb_instance_data(zk);
897
+ }
898
+
899
+ // this is a value on the ruby side we can check to see if destroy_zkrb_instance
900
+ // has been called
901
+ rb_iv_set(self, "@_closed", Qtrue);
902
+
903
+ /* Note that after zookeeper_close() returns, ZK handle is invalid */
904
+ int rc = destroy_zkrb_instance(zk);
905
+
906
+ zkrb_debug("destroy_zkrb_instance returned: %d", rc);
907
+
908
+ return INT2FIX(rc);
909
+ }
910
+
911
+ static VALUE method_deterministic_conn_order(VALUE self, VALUE yn) {
912
+ zoo_deterministic_conn_order(yn == Qtrue);
913
+ return Qnil;
914
+ }
915
+
916
+ static VALUE method_is_unrecoverable(VALUE self) {
917
+ FETCH_DATA_PTR(self, zk);
918
+ return is_unrecoverable(zk->zh) == ZINVALIDSTATE ? Qtrue : Qfalse;
919
+ }
920
+
921
+ static VALUE method_zkrb_state(VALUE self) {
922
+ FETCH_DATA_PTR(self, zk);
923
+ return INT2NUM(zoo_state(zk->zh));
924
+ }
925
+
926
+ static VALUE method_recv_timeout(VALUE self) {
927
+ FETCH_DATA_PTR(self, zk);
928
+ return INT2NUM(zoo_recv_timeout(zk->zh));
929
+ }
930
+
931
+ // returns a CZookeeper::ClientId object with the values set for session_id and passwd
932
+ static VALUE method_client_id(VALUE self) {
933
+ FETCH_DATA_PTR(self, zk);
934
+ const clientid_t *cid = zoo_client_id(zk->zh);
935
+
936
+ VALUE session_id = LL2NUM(cid->client_id);
937
+ VALUE passwd = rb_str_new(cid->passwd, 16);
938
+
939
+ VALUE client_id_obj = rb_class_new_instance(0, RARRAY_PTR(rb_ary_new()), ZookeeperClientId);
940
+
941
+ rb_funcall(client_id_obj, rb_intern("session_id="), 1, session_id);
942
+ rb_funcall(client_id_obj, rb_intern("passwd="), 1, passwd);
943
+
944
+ return client_id_obj;
945
+ }
946
+
947
+ static VALUE klass_method_zkrb_set_debug_level(VALUE klass, VALUE level) {
948
+ Check_Type(level, T_FIXNUM);
949
+ ZKRBDebugging = (FIX2INT(level) == ZOO_LOG_LEVEL_DEBUG);
950
+ zoo_set_debug_level(FIX2INT(level));
951
+ return Qnil;
952
+ }
953
+
954
+ static VALUE method_zerror(VALUE self, VALUE errc) {
955
+ return rb_str_new2(zerror(FIX2INT(errc)));
956
+ }
957
+
958
+ static VALUE method_connected_host(VALUE self) {
959
+ FETCH_DATA_PTR(self, zk);
960
+
961
+ struct sockaddr addr;
962
+ socklen_t addr_len = sizeof(addr);
963
+
964
+ if (zookeeper_get_connected_host(zk->zh, &addr, &addr_len) != NULL) {
965
+ char buf[255];
966
+ char addrstr[128];
967
+ void *inaddr;
968
+ int port;
969
+
970
+ #if defined(AF_INET6)
971
+ if(addr.sa_family==AF_INET6){
972
+ inaddr = &((struct sockaddr_in6 *) &addr)->sin6_addr;
973
+ port = ((struct sockaddr_in6 *) &addr)->sin6_port;
974
+ } else {
975
+ #endif
976
+ inaddr = &((struct sockaddr_in *) &addr)->sin_addr;
977
+ port = ((struct sockaddr_in *) &addr)->sin_port;
978
+ #if defined(AF_INET6)
979
+ }
980
+ #endif
981
+
982
+ inet_ntop(addr.sa_family, inaddr, addrstr, sizeof(addrstr)-1);
983
+ snprintf(buf, sizeof(buf), "%s:%d", addrstr, ntohs(port));
984
+ return rb_str_new2(buf);
985
+ }
986
+
987
+ return Qnil;
988
+ }
989
+
990
+ static void zkrb_define_methods(void) {
991
+ #define DEFINE_METHOD(M, ARGS) { \
992
+ rb_define_method(CZookeeper, #M, method_ ## M, ARGS); }
993
+
994
+ #define DEFINE_CLASS_METHOD(M, ARGS) { \
995
+ rb_define_singleton_method(CZookeeper, #M, method_ ## M, ARGS); }
996
+
997
+ // defines a method with a zkrb_ prefix, the actual C method does not have this prefix
998
+ #define DEFINE_ZKRB_METHOD(M, ARGS) { \
999
+ rb_define_method(CZookeeper, zkrb_ ## M, method_ ## M, ARGS); }
1000
+
1001
+ // the number after the method name should be actual arity of C function - 1
1002
+ DEFINE_METHOD(zkrb_init, -1);
1003
+
1004
+ rb_define_method(CZookeeper, "zkrb_get_children", method_get_children, 4);
1005
+ rb_define_method(CZookeeper, "zkrb_exists", method_exists, 4);
1006
+ rb_define_method(CZookeeper, "zkrb_create", method_create, 6);
1007
+ rb_define_method(CZookeeper, "zkrb_delete", method_delete, 4);
1008
+ rb_define_method(CZookeeper, "zkrb_get", method_get, 4);
1009
+ rb_define_method(CZookeeper, "zkrb_set", method_set, 5);
1010
+ rb_define_method(CZookeeper, "zkrb_set_acl", method_set_acl, 5);
1011
+ rb_define_method(CZookeeper, "zkrb_get_acl", method_get_acl, 3);
1012
+ rb_define_method(CZookeeper, "zkrb_add_auth", method_add_auth, 3);
1013
+
1014
+ rb_define_singleton_method(CZookeeper, "zoo_set_log_level", method_zoo_set_log_level, 1);
1015
+
1016
+ DEFINE_METHOD(client_id, 0);
1017
+ DEFINE_METHOD(close_handle, 0);
1018
+ DEFINE_METHOD(deterministic_conn_order, 1);
1019
+ DEFINE_METHOD(is_unrecoverable, 0);
1020
+ DEFINE_METHOD(recv_timeout, 0);
1021
+ DEFINE_METHOD(zkrb_state, 0);
1022
+ DEFINE_METHOD(sync, 2);
1023
+ DEFINE_METHOD(zkrb_iterate_event_loop, 0);
1024
+ DEFINE_METHOD(zkrb_get_next_event_st, 0);
1025
+ DEFINE_METHOD(connected_host, 0);
1026
+
1027
+ // methods for the ruby-side event manager
1028
+ DEFINE_METHOD(zkrb_get_next_event, 1);
1029
+ DEFINE_METHOD(zkrb_get_next_event_st, 0);
1030
+ DEFINE_METHOD(has_events, 0);
1031
+
1032
+ // Make these class methods?
1033
+ DEFINE_METHOD(zerror, 1);
1034
+
1035
+ rb_define_singleton_method(CZookeeper, "set_zkrb_debug_level", klass_method_zkrb_set_debug_level, 1);
1036
+
1037
+ rb_attr(CZookeeper, rb_intern("selectable_io"), 1, 0, Qtrue);
1038
+
1039
+ }
1040
+
1041
+ // class CZookeeper::ClientId
1042
+ // attr_accessor :session_id, :passwd
1043
+ //
1044
+ // def initialize(session_id, passwd)
1045
+ // @session_id = session_id
1046
+ // @passwd = passwd
1047
+ // end
1048
+ // end
1049
+
1050
+ static VALUE zkrb_client_id_method_initialize(VALUE self) {
1051
+ rb_iv_set(self, "@session_id", Qnil);
1052
+ rb_iv_set(self, "@passwd", Qnil);
1053
+ return Qnil;
1054
+ }
1055
+
1056
+
1057
+ void Init_zookeeper_c() {
1058
+ // Don't debug by default
1059
+ ZKRBDebugging = 0;
1060
+ zoo_set_debug_level(0);
1061
+
1062
+ mZookeeper = rb_define_module("Zookeeper");
1063
+ mZookeeperExceptions = rb_define_module_under(mZookeeper, "Exceptions");
1064
+
1065
+ // this will likely fail if the load order is screwed up
1066
+ eHandleClosedException = rb_const_get(mZookeeperExceptions, rb_intern("HandleClosedException"));
1067
+
1068
+ /* initialize CZookeeper class */
1069
+ CZookeeper = rb_define_class_under(mZookeeper, "CZookeeper", rb_cObject);
1070
+ rb_define_alloc_func(CZookeeper, alloc_zkrb_instance);
1071
+ zkrb_define_methods();
1072
+
1073
+ ZookeeperClientId = rb_define_class_under(CZookeeper, "ClientId", rb_cObject);
1074
+ rb_define_method(ZookeeperClientId, "initialize", zkrb_client_id_method_initialize, 0);
1075
+ rb_define_attr(ZookeeperClientId, "session_id", 1, 1);
1076
+ rb_define_attr(ZookeeperClientId, "passwd", 1, 1);
1077
+
1078
+ }
1079
+
1080
+ // vim:ts=2:sw=2:sts=2:et