zookeeper 0.9.3-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG +119 -0
  3. data/Gemfile +17 -0
  4. data/LICENSE +23 -0
  5. data/Manifest +29 -0
  6. data/README.markdown +59 -0
  7. data/Rakefile +139 -0
  8. data/examples/cloud_config.rb +125 -0
  9. data/ext/.gitignore +6 -0
  10. data/ext/Rakefile +51 -0
  11. data/ext/c_zookeeper.rb +212 -0
  12. data/ext/dbg.h +53 -0
  13. data/ext/depend +5 -0
  14. data/ext/extconf.rb +85 -0
  15. data/ext/generate_gvl_code.rb +316 -0
  16. data/ext/zkc-3.3.5.tar.gz +0 -0
  17. data/ext/zkrb_wrapper.c +731 -0
  18. data/ext/zkrb_wrapper.h +330 -0
  19. data/ext/zkrb_wrapper_compat.c +15 -0
  20. data/ext/zkrb_wrapper_compat.h +11 -0
  21. data/ext/zookeeper_base.rb +211 -0
  22. data/ext/zookeeper_c.c +725 -0
  23. data/ext/zookeeper_lib.c +677 -0
  24. data/ext/zookeeper_lib.h +172 -0
  25. data/java/zookeeper_base.rb +477 -0
  26. data/lib/zookeeper.rb +297 -0
  27. data/lib/zookeeper/acls.rb +40 -0
  28. data/lib/zookeeper/callbacks.rb +91 -0
  29. data/lib/zookeeper/common.rb +174 -0
  30. data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
  31. data/lib/zookeeper/constants.rb +57 -0
  32. data/lib/zookeeper/em_client.rb +55 -0
  33. data/lib/zookeeper/exceptions.rb +100 -0
  34. data/lib/zookeeper/stat.rb +21 -0
  35. data/lib/zookeeper/version.rb +6 -0
  36. data/notes.txt +14 -0
  37. data/spec/c_zookeeper_spec.rb +50 -0
  38. data/spec/chrooted_connection_spec.rb +81 -0
  39. data/spec/default_watcher_spec.rb +41 -0
  40. data/spec/em_spec.rb +51 -0
  41. data/spec/log4j.properties +17 -0
  42. data/spec/shared/all_success_return_values.rb +10 -0
  43. data/spec/shared/connection_examples.rb +1018 -0
  44. data/spec/spec_helper.rb +119 -0
  45. data/spec/support/progress_formatter.rb +15 -0
  46. data/spec/zookeeper_spec.rb +24 -0
  47. data/test/test_basic.rb +37 -0
  48. data/test/test_callback1.rb +36 -0
  49. data/test/test_close.rb +16 -0
  50. data/test/test_esoteric.rb +7 -0
  51. data/test/test_watcher1.rb +56 -0
  52. data/test/test_watcher2.rb +52 -0
  53. metadata +181 -0
@@ -0,0 +1,677 @@
1
+ /* Ruby wrapper for the Zookeeper C API
2
+
3
+ This file contains three sets of helpers:
4
+ - the event queue that glues RB<->C together
5
+ - the completions that marshall data between RB<->C formats
6
+ - functions for translating between Ruby and C versions of ZK datatypes
7
+
8
+ wickman@twitter.com
9
+
10
+ *********************************************************************************
11
+ *
12
+ * NOTE: be *very careful* in these functions, calling *ANY* ruby interpreter
13
+ * function when you're not in an interpreter thread can hork ruby, trigger a
14
+ * [BUG], corrupt the stack, kill your dog, knock up your daughter, etc. etc.
15
+ *
16
+ *********************************************************************************
17
+
18
+ slyphon@gmail.com
19
+
20
+ */
21
+
22
+ #include "ruby.h"
23
+ #include "zookeeper_lib.h"
24
+ #include "c-client-src/zookeeper.h"
25
+ #include <errno.h>
26
+ #include <stdio.h>
27
+ #include <stdlib.h>
28
+ #include <pthread.h>
29
+ #include <unistd.h>
30
+ #include <inttypes.h>
31
+ #include "dbg.h"
32
+
33
+ #define GET_SYM(str) ID2SYM(rb_intern(str))
34
+
35
+ int ZKRBDebugging;
36
+
37
+ // XXX(slyphon): need to check these for error, but what to do if they fail?
38
+ pthread_mutex_t zkrb_q_mutex = PTHREAD_MUTEX_INITIALIZER;
39
+
40
+ #define LOG_PTHREAD_ERR(A, M, ...) if (A) { log_err(M, ##__VA_ARGS__); errno=0; }
41
+
42
+ #define GLOBAL_MUTEX_LOCK(F) LOG_PTHREAD_ERR(pthread_mutex_lock(&zkrb_q_mutex), F)
43
+ #define GLOBAL_MUTEX_UNLOCK(F) LOG_PTHREAD_ERR(pthread_mutex_unlock(&zkrb_q_mutex), F)
44
+
45
+
46
+ void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
47
+ GLOBAL_MUTEX_LOCK("zkrb_enqueue");
48
+
49
+ check_debug(q != NULL && q->tail != NULL, "zkrb_enqueue: queue ptr or tail was NULL\n");
50
+
51
+ q->tail->event = elt;
52
+ q->tail->next = (zkrb_event_ll_t *) malloc(sizeof(zkrb_event_ll_t));
53
+ q->tail = q->tail->next;
54
+ q->tail->event = NULL;
55
+ q->tail->next = NULL;
56
+ ssize_t ret = write(q->pipe_write, "0", 1); /* Wake up Ruby listener */
57
+
58
+ // XXX(slyphon): can't raise a ruby exception here as we may not be calling
59
+ // this from a ruby thread. Calling into the interpreter from a non-ruby
60
+ // thread is bad, mm'kay?
61
+
62
+ check(ret != -1, "write to queue (%p) pipe failed!\n", q);
63
+
64
+ error:
65
+ GLOBAL_MUTEX_UNLOCK("zkrb_enqueue");
66
+ }
67
+
68
+ // NOTE: the zkrb_event_t* returned *is* the same pointer that's part of the
69
+ // queue, the only place this is used is in method_has_events, and it is simply
70
+ // tested for null-ness. it's probably better to make the null-test here and
71
+ // not return the pointer
72
+ //
73
+ zkrb_event_t * zkrb_peek(zkrb_queue_t *q) {
74
+ zkrb_event_t *event = NULL;
75
+
76
+ GLOBAL_MUTEX_LOCK("zkrb_peek");
77
+
78
+ if (q != NULL && q->head != NULL && q->head->event != NULL) {
79
+ event = q->head->event;
80
+ }
81
+
82
+ GLOBAL_MUTEX_UNLOCK("zkrb_peek");
83
+ return event;
84
+ }
85
+
86
+ #define ZKRB_QUEUE_EMPTY(q) (q == NULL || q->head == NULL || q->head->event == NULL)
87
+
88
+ zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q, int need_lock) {
89
+ zkrb_event_t *rv = NULL;
90
+ zkrb_event_ll_t *old_root = NULL;
91
+
92
+ if (need_lock)
93
+ GLOBAL_MUTEX_LOCK("zkrb_dequeue");
94
+
95
+ if (!ZKRB_QUEUE_EMPTY(q)) {
96
+ old_root = q->head;
97
+ q->head = q->head->next;
98
+ rv = old_root->event;
99
+ }
100
+
101
+ if (need_lock)
102
+ GLOBAL_MUTEX_UNLOCK("zkrb_dequeue");
103
+
104
+ free(old_root);
105
+ return rv;
106
+ }
107
+
108
+ void zkrb_signal(zkrb_queue_t *q) {
109
+ GLOBAL_MUTEX_LOCK("zkrb_signal");
110
+
111
+ if (!write(q->pipe_write, "0", 1)) /* Wake up Ruby listener */
112
+ log_err("zkrb_signal: write to pipe failed, could not wake");
113
+
114
+ GLOBAL_MUTEX_UNLOCK("zkrb_signal");
115
+ }
116
+
117
+ zkrb_event_ll_t *zkrb_event_ll_t_alloc(void) {
118
+ zkrb_event_ll_t *rv = malloc(sizeof(zkrb_event_ll_t));
119
+
120
+ if (!rv) return NULL;
121
+
122
+ rv->event = NULL;
123
+ rv->next = NULL;
124
+
125
+ return rv;
126
+ }
127
+
128
+ zkrb_queue_t *zkrb_queue_alloc(void) {
129
+ // some of the locking is a little coarse, but it
130
+ // eases the logic of releasing in case of error.
131
+ GLOBAL_MUTEX_LOCK("zkrb_queue_alloc");
132
+
133
+ int pfd[2];
134
+ zkrb_queue_t *rq = NULL;
135
+
136
+ check(pipe(pfd) == 0, "creating the signal pipe failed");
137
+
138
+ rq = malloc(sizeof(zkrb_queue_t));
139
+ check_mem(rq);
140
+
141
+ rq->head = zkrb_event_ll_t_alloc();
142
+ check_mem(rq->head);
143
+
144
+ rq->tail = rq->head;
145
+ rq->pipe_read = pfd[0];
146
+ rq->pipe_write = pfd[1];
147
+
148
+ GLOBAL_MUTEX_UNLOCK("zkrb_queue_alloc");
149
+ return rq;
150
+
151
+ error:
152
+ GLOBAL_MUTEX_UNLOCK("zkrb_queue_alloc");
153
+ free(rq);
154
+ return NULL;
155
+ }
156
+
157
+ void zkrb_queue_free(zkrb_queue_t *queue) {
158
+ GLOBAL_MUTEX_LOCK("zkrb_queue_free");
159
+ check_debug(queue != NULL, "zkrb_queue_free: queue was NULL");
160
+
161
+ zkrb_event_t *elt;
162
+ while ((elt = zkrb_dequeue(queue, 0)) != NULL) {
163
+ zkrb_event_free(elt);
164
+ }
165
+ free(queue->head);
166
+ close(queue->pipe_read);
167
+ close(queue->pipe_write);
168
+ free(queue);
169
+
170
+ error:
171
+ GLOBAL_MUTEX_UNLOCK("zkrb_queue_free");
172
+ }
173
+
174
+ zkrb_event_t *zkrb_event_alloc(void) {
175
+ zkrb_event_t *rv = malloc(sizeof(zkrb_event_t));
176
+ return rv;
177
+ }
178
+
179
+ void zkrb_event_free(zkrb_event_t *event) {
180
+ switch (event->type) {
181
+ case ZKRB_DATA: {
182
+ struct zkrb_data_completion *data_ctx = event->completion.data_completion;
183
+ free(data_ctx->data);
184
+ free(data_ctx->stat);
185
+ free(data_ctx);
186
+ break;
187
+ }
188
+ case ZKRB_STAT: {
189
+ struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
190
+ free(stat_ctx->stat);
191
+ free(stat_ctx);
192
+ break;
193
+ }
194
+ case ZKRB_STRING: {
195
+ struct zkrb_string_completion *string_ctx = event->completion.string_completion;
196
+ free(string_ctx->value);
197
+ free(string_ctx);
198
+ break;
199
+ }
200
+ case ZKRB_STRINGS: {
201
+ struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
202
+ int k;
203
+ if (strings_ctx->values)
204
+ for (k = 0; k < strings_ctx->values->count; ++k) free(strings_ctx->values->data[k]);
205
+ free(strings_ctx->values);
206
+ free(strings_ctx);
207
+ break;
208
+ }
209
+ case ZKRB_STRINGS_STAT: {
210
+ struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
211
+ int k;
212
+ if (strings_stat_ctx->values)
213
+ for (k = 0; k < strings_stat_ctx->values->count; ++k) free(strings_stat_ctx->values->data[k]);
214
+ free(strings_stat_ctx->values);
215
+
216
+ if (strings_stat_ctx->stat)
217
+ free(strings_stat_ctx->stat);
218
+ free(strings_stat_ctx);
219
+ break;
220
+ }
221
+ case ZKRB_ACL: {
222
+ struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
223
+ if (acl_ctx->acl) {
224
+ deallocate_ACL_vector(acl_ctx->acl);
225
+ free(acl_ctx->acl);
226
+ }
227
+ free(acl_ctx->stat);
228
+ free(acl_ctx);
229
+ break;
230
+ }
231
+ case ZKRB_WATCHER: {
232
+ struct zkrb_watcher_completion *watcher_ctx = event->completion.watcher_completion;
233
+ free(watcher_ctx->path);
234
+ free(watcher_ctx);
235
+ break;
236
+ }
237
+ case ZKRB_VOID: {
238
+ break;
239
+ }
240
+ default:
241
+ log_err("unrecognized event in event_free!");
242
+ }
243
+
244
+ free(event);
245
+ }
246
+
247
+ /* this is called only from a method_get_latest_event, so the hash is
248
+ allocated on the proper thread stack */
249
+ VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
250
+ VALUE hash = rb_hash_new();
251
+
252
+ if (!event) {
253
+ log_err("event was NULL in zkrb_event_to_ruby");
254
+ return hash;
255
+ }
256
+
257
+ rb_hash_aset(hash, GET_SYM("req_id"), LL2NUM(event->req_id));
258
+ if (event->type != ZKRB_WATCHER)
259
+ rb_hash_aset(hash, GET_SYM("rc"), INT2FIX(event->rc));
260
+
261
+ switch (event->type) {
262
+ case ZKRB_DATA: {
263
+ struct zkrb_data_completion *data_ctx = event->completion.data_completion;
264
+ if (ZKRBDebugging) zkrb_print_stat(data_ctx->stat);
265
+ rb_hash_aset(hash, GET_SYM("data"), data_ctx->data ? rb_str_new(data_ctx->data, data_ctx->data_len) : Qnil);
266
+ rb_hash_aset(hash, GET_SYM("stat"), data_ctx->stat ? zkrb_stat_to_rarray(data_ctx->stat) : Qnil);
267
+ break;
268
+ }
269
+ case ZKRB_STAT: {
270
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STAT\n");
271
+ struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
272
+ rb_hash_aset(hash, GET_SYM("stat"), stat_ctx->stat ? zkrb_stat_to_rarray(stat_ctx->stat) : Qnil);
273
+ break;
274
+ }
275
+ case ZKRB_STRING: {
276
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STRING\n");
277
+ struct zkrb_string_completion *string_ctx = event->completion.string_completion;
278
+ rb_hash_aset(hash, GET_SYM("string"), string_ctx->value ? rb_str_new2(string_ctx->value) : Qnil);
279
+ break;
280
+ }
281
+ case ZKRB_STRINGS: {
282
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STRINGS\n");
283
+ struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
284
+ rb_hash_aset(hash, GET_SYM("strings"), strings_ctx->values ? zkrb_string_vector_to_ruby(strings_ctx->values) : Qnil);
285
+ break;
286
+ }
287
+ case ZKRB_STRINGS_STAT: {
288
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STRINGS_STAT\n");
289
+ struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
290
+ rb_hash_aset(hash, GET_SYM("strings"), strings_stat_ctx->values ? zkrb_string_vector_to_ruby(strings_stat_ctx->values) : Qnil);
291
+ rb_hash_aset(hash, GET_SYM("stat"), strings_stat_ctx->stat ? zkrb_stat_to_rarray(strings_stat_ctx->stat) : Qnil);
292
+ break;
293
+ }
294
+ case ZKRB_ACL: {
295
+ zkrb_debug("zkrb_event_to_ruby ZKRB_ACL\n");
296
+ struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
297
+ rb_hash_aset(hash, GET_SYM("acl"), acl_ctx->acl ? zkrb_acl_vector_to_ruby(acl_ctx->acl) : Qnil);
298
+ rb_hash_aset(hash, GET_SYM("stat"), acl_ctx->stat ? zkrb_stat_to_rarray(acl_ctx->stat) : Qnil);
299
+ break;
300
+ }
301
+ case ZKRB_WATCHER: {
302
+ zkrb_debug("zkrb_event_to_ruby ZKRB_WATCHER\n");
303
+ struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
304
+ struct zkrb_watcher_completion *watcher_ctx = event->completion.watcher_completion;
305
+ rb_hash_aset(hash, GET_SYM("type"), INT2FIX(watcher_ctx->type));
306
+ rb_hash_aset(hash, GET_SYM("state"), INT2FIX(watcher_ctx->state));
307
+ rb_hash_aset(hash, GET_SYM("path"), watcher_ctx->path ? rb_str_new2(watcher_ctx->path) : Qnil);
308
+ break;
309
+ }
310
+ case ZKRB_VOID:
311
+ default:
312
+ break;
313
+ }
314
+
315
+ return hash;
316
+ }
317
+
318
+ void zkrb_print_stat(const struct Stat *s) {
319
+ fprintf(stderr, "stat {\n");
320
+ if (s != NULL) {
321
+ fprintf(stderr, "\t czxid: %"PRId64"\n", s->czxid); // PRId64 defined in inttypes.h
322
+ fprintf(stderr, "\t mzxid: %"PRId64"\n", s->mzxid);
323
+ fprintf(stderr, "\t ctime: %"PRId64"\n", s->ctime);
324
+ fprintf(stderr, "\t mtime: %"PRId64"\n", s->mtime);
325
+ fprintf(stderr, "\t version: %d\n", s->version);
326
+ fprintf(stderr, "\t cversion: %d\n", s->cversion);
327
+ fprintf(stderr, "\t aversion: %d\n", s->aversion);
328
+ fprintf(stderr, "\t ephemeralOwner: %"PRId64"\n", s->ephemeralOwner);
329
+ fprintf(stderr, "\t dataLength: %d\n", s->dataLength);
330
+ fprintf(stderr, "\t numChildren: %d\n", s->numChildren);
331
+ fprintf(stderr, "\t pzxid: %"PRId64"\n", s->pzxid);
332
+ } else {
333
+ fprintf(stderr, "\tNULL\n");
334
+ }
335
+ fprintf(stderr, "}\n");
336
+ }
337
+
338
+ zkrb_calling_context *zkrb_calling_context_alloc(int64_t req_id, zkrb_queue_t *queue) {
339
+ zkrb_calling_context *ctx = malloc(sizeof(zkrb_calling_context));
340
+ if (!ctx) return NULL;
341
+
342
+ ctx->req_id = req_id;
343
+ ctx->queue = queue;
344
+
345
+ return ctx;
346
+ }
347
+
348
+ void zkrb_print_calling_context(zkrb_calling_context *ctx) {
349
+ fprintf(stderr, "calling context (%p){\n", ctx);
350
+ fprintf(stderr, "\treq_id = %"PRId64"\n", ctx->req_id);
351
+ fprintf(stderr, "\tqueue = %p\n", ctx->queue);
352
+ fprintf(stderr, "}\n");
353
+ }
354
+
355
+ /*
356
+ process completions that get queued to the watcher queue, translate events
357
+ to completions that the ruby side dispatches via callbacks.
358
+
359
+ The calling_ctx can be thought of as the outer shell that we discard in
360
+ this macro after pulling out the gooey delicious center.
361
+ */
362
+
363
+ #define ZKH_SETUP_EVENT(qptr, eptr) \
364
+ zkrb_calling_context *ctx = (zkrb_calling_context *) calling_ctx; \
365
+ zkrb_event_t *eptr = zkrb_event_alloc(); \
366
+ eptr->req_id = ctx->req_id; \
367
+ zkrb_queue_t *qptr = ctx->queue; \
368
+ if (eptr->req_id != ZKRB_GLOBAL_REQ) free(ctx)
369
+
370
+ void zkrb_state_callback(
371
+ zhandle_t *zh, int type, int state, const char *path, void *calling_ctx) {
372
+
373
+ zkrb_debug("ZOOKEEPER_C_STATE WATCHER "
374
+ "type = %d, state = %d, path = %p, value = %s\n",
375
+ type, state, (void *) path, path ? path : "NULL");
376
+
377
+ /* save callback context */
378
+ struct zkrb_watcher_completion *wc = malloc(sizeof(struct zkrb_watcher_completion));
379
+ wc->type = type;
380
+ wc->state = state;
381
+ wc->path = strdup(path);
382
+
383
+ // This is unfortunate copy-pasta from ZKH_SETUP_EVENT with one change: we
384
+ // check type instead of the req_id to see if we need to free the ctx.
385
+ zkrb_calling_context *ctx = (zkrb_calling_context *) calling_ctx;
386
+ zkrb_event_t *event = zkrb_event_alloc();
387
+ event->req_id = ctx->req_id;
388
+ zkrb_queue_t *queue = ctx->queue;
389
+ if (type != ZOO_SESSION_EVENT) {
390
+ free(ctx);
391
+ ctx = NULL;
392
+ }
393
+
394
+ event->type = ZKRB_WATCHER;
395
+ event->completion.watcher_completion = wc;
396
+
397
+ zkrb_enqueue(queue, event);
398
+ }
399
+
400
+
401
+
402
+ void zkrb_data_callback(
403
+ int rc, const char *value, int value_len, const struct Stat *stat, const void *calling_ctx) {
404
+
405
+ zkrb_debug("ZOOKEEPER_C_DATA WATCHER "
406
+ "rc = %d (%s), value = %s, len = %d\n",
407
+ rc, zerror(rc), value ? value : "NULL", value_len);
408
+
409
+ /* copy data completion */
410
+ struct zkrb_data_completion *dc = malloc(sizeof(struct zkrb_data_completion));
411
+ dc->data = NULL;
412
+ dc->stat = NULL;
413
+ dc->data_len = 0;
414
+
415
+ if (value != NULL) {
416
+ dc->data = malloc(value_len);
417
+ dc->data_len = value_len;
418
+ memcpy(dc->data, value, value_len);
419
+ }
420
+
421
+ if (stat != NULL) { dc->stat = malloc(sizeof(struct Stat)); memcpy(dc->stat, stat, sizeof(struct Stat)); }
422
+
423
+ ZKH_SETUP_EVENT(queue, event);
424
+ event->rc = rc;
425
+ event->type = ZKRB_DATA;
426
+ event->completion.data_completion = dc;
427
+
428
+ zkrb_enqueue(queue, event);
429
+ }
430
+
431
+ void zkrb_stat_callback(
432
+ int rc, const struct Stat *stat, const void *calling_ctx) {
433
+ zkrb_debug("ZOOKEEPER_C_STAT WATCHER "
434
+ "rc = %d (%s)\n", rc, zerror(rc));
435
+
436
+ struct zkrb_stat_completion *sc = malloc(sizeof(struct zkrb_stat_completion));
437
+ sc->stat = NULL;
438
+ if (stat != NULL) { sc->stat = malloc(sizeof(struct Stat)); memcpy(sc->stat, stat, sizeof(struct Stat)); }
439
+
440
+ ZKH_SETUP_EVENT(queue, event);
441
+ event->rc = rc;
442
+ event->type = ZKRB_STAT;
443
+ event->completion.stat_completion = sc;
444
+
445
+ zkrb_enqueue(queue, event);
446
+ }
447
+
448
+ void zkrb_string_callback(
449
+ int rc, const char *string, const void *calling_ctx) {
450
+
451
+ zkrb_debug("ZOOKEEPER_C_STRING WATCHER "
452
+ "rc = %d (%s)\n", rc, zerror(rc));
453
+
454
+ struct zkrb_string_completion *sc = malloc(sizeof(struct zkrb_string_completion));
455
+ sc->value = NULL;
456
+ if (string)
457
+ sc->value = strdup(string);
458
+
459
+ ZKH_SETUP_EVENT(queue, event);
460
+ event->rc = rc;
461
+ event->type = ZKRB_STRING;
462
+ event->completion.string_completion = sc;
463
+
464
+ zkrb_enqueue(queue, event);
465
+ }
466
+
467
+ void zkrb_strings_callback(
468
+ int rc, const struct String_vector *strings, const void *calling_ctx) {
469
+ zkrb_debug("ZOOKEEPER_C_STRINGS WATCHER "
470
+ "rc = %d (%s), calling_ctx = %p\n", rc, zerror(rc), calling_ctx);
471
+
472
+ /* copy string vector */
473
+ struct zkrb_strings_completion *sc = malloc(sizeof(struct zkrb_strings_completion));
474
+ sc->values = (strings != NULL) ? zkrb_clone_string_vector(strings) : NULL;
475
+
476
+ ZKH_SETUP_EVENT(queue, event);
477
+ event->rc = rc;
478
+ event->type = ZKRB_STRINGS;
479
+ event->completion.strings_completion = sc;
480
+
481
+ zkrb_enqueue(queue, event);
482
+ }
483
+
484
+ void zkrb_strings_stat_callback(
485
+ int rc, const struct String_vector *strings, const struct Stat *stat, const void *calling_ctx) {
486
+ zkrb_debug("ZOOKEEPER_C_STRINGS_STAT WATCHER "
487
+ "rc = %d (%s), calling_ctx = %p\n", rc, zerror(rc), calling_ctx);
488
+
489
+ struct zkrb_strings_stat_completion *sc = malloc(sizeof(struct zkrb_strings_stat_completion));
490
+ sc->stat = NULL;
491
+ if (stat != NULL) { sc->stat = malloc(sizeof(struct Stat)); memcpy(sc->stat, stat, sizeof(struct Stat)); }
492
+
493
+ sc->values = (strings != NULL) ? zkrb_clone_string_vector(strings) : NULL;
494
+
495
+ ZKH_SETUP_EVENT(queue, event);
496
+ event->rc = rc;
497
+ event->type = ZKRB_STRINGS_STAT;
498
+ event->completion.strings_stat_completion = sc;
499
+
500
+ zkrb_enqueue(queue, event);
501
+ }
502
+
503
+ void zkrb_void_callback(int rc, const void *calling_ctx) {
504
+ zkrb_debug("ZOOKEEPER_C_VOID WATCHER "
505
+ "rc = %d (%s)\n", rc, zerror(rc));
506
+
507
+ ZKH_SETUP_EVENT(queue, event);
508
+ event->rc = rc;
509
+ event->type = ZKRB_VOID;
510
+ event->completion.void_completion = NULL;
511
+
512
+ zkrb_enqueue(queue, event);
513
+ }
514
+
515
+ void zkrb_acl_callback(
516
+ int rc, struct ACL_vector *acls, struct Stat *stat, const void *calling_ctx) {
517
+ zkrb_debug("ZOOKEEPER_C_ACL WATCHER rc = %d (%s)\n", rc, zerror(rc));
518
+
519
+ struct zkrb_acl_completion *ac = malloc(sizeof(struct zkrb_acl_completion));
520
+ ac->acl = NULL;
521
+ ac->stat = NULL;
522
+ if (acls != NULL) { ac->acl = zkrb_clone_acl_vector(acls); }
523
+ if (stat != NULL) { ac->stat = malloc(sizeof(struct Stat)); memcpy(ac->stat, stat, sizeof(struct Stat)); }
524
+
525
+ ZKH_SETUP_EVENT(queue, event);
526
+ event->rc = rc;
527
+ event->type = ZKRB_ACL;
528
+ event->completion.acl_completion = ac;
529
+
530
+ /* should be synchronized */
531
+ zkrb_enqueue(queue, event);
532
+ }
533
+
534
+ VALUE zkrb_id_to_ruby(struct Id *id) {
535
+ VALUE hash = rb_hash_new();
536
+ rb_hash_aset(hash, GET_SYM("scheme"), rb_str_new2(id->scheme));
537
+ rb_hash_aset(hash, GET_SYM("id"), rb_str_new2(id->id));
538
+ return hash;
539
+ }
540
+
541
+ VALUE zkrb_acl_to_ruby(struct ACL *acl) {
542
+ VALUE hash = rb_hash_new();
543
+ rb_hash_aset(hash, GET_SYM("perms"), INT2NUM(acl->perms));
544
+ rb_hash_aset(hash, GET_SYM("id"), zkrb_id_to_ruby(&(acl->id)));
545
+ return hash;
546
+ }
547
+
548
+ #warning [wickman] TODO test zkrb_ruby_to_aclvector
549
+ #warning [slyphon] TODO size checking on acl_ary (cast to int)
550
+ struct ACL_vector * zkrb_ruby_to_aclvector(VALUE acl_ary) {
551
+ Check_Type(acl_ary, T_ARRAY);
552
+
553
+ struct ACL_vector *v = malloc(sizeof(struct ACL_vector));
554
+ allocate_ACL_vector(v, (int)RARRAY_LEN(acl_ary));
555
+
556
+ int k;
557
+ for (k = 0; k < v->count; ++k) {
558
+ VALUE acl_val = rb_ary_entry(acl_ary, k);
559
+ v->data[k] = zkrb_ruby_to_acl(acl_val);
560
+ }
561
+
562
+ return v;
563
+ }
564
+
565
+ #warning [wickman] TODO test zkrb_ruby_to_aclvector
566
+ struct ACL zkrb_ruby_to_acl(VALUE rubyacl) {
567
+ struct ACL acl;
568
+
569
+ VALUE perms = rb_iv_get(rubyacl, "@perms");
570
+ VALUE rubyid = rb_iv_get(rubyacl, "@id");
571
+ acl.perms = NUM2INT(perms);
572
+ acl.id = zkrb_ruby_to_id(rubyid);
573
+
574
+ return acl;
575
+ }
576
+
577
+ #warning [wickman] TODO zkrb_ruby_to_id error checking? test
578
+ struct Id zkrb_ruby_to_id(VALUE rubyid) {
579
+ struct Id id;
580
+
581
+ VALUE scheme = rb_iv_get(rubyid, "@scheme");
582
+ VALUE ident = rb_iv_get(rubyid, "@id");
583
+
584
+ if (scheme != Qnil) {
585
+ id.scheme = malloc(RSTRING_LEN(scheme) + 1);
586
+ strncpy(id.scheme, RSTRING_PTR(scheme), RSTRING_LEN(scheme));
587
+ id.scheme[RSTRING_LEN(scheme)] = '\0';
588
+ } else {
589
+ id.scheme = NULL;
590
+ }
591
+
592
+ if (ident != Qnil) {
593
+ id.id = malloc(RSTRING_LEN(ident) + 1);
594
+ strncpy(id.id, RSTRING_PTR(ident), RSTRING_LEN(ident));
595
+ id.id[RSTRING_LEN(ident)] = '\0';
596
+ } else {
597
+ id.id = NULL;
598
+ }
599
+
600
+ return id;
601
+ }
602
+
603
+ VALUE zkrb_acl_vector_to_ruby(struct ACL_vector *acl_vector) {
604
+ int i;
605
+ VALUE ary = rb_ary_new2(acl_vector->count);
606
+ for(i = 0; i < acl_vector->count; i++) {
607
+ rb_ary_push(ary, zkrb_acl_to_ruby(acl_vector->data+i));
608
+ }
609
+ return ary;
610
+ }
611
+
612
+ VALUE zkrb_string_vector_to_ruby(struct String_vector *string_vector) {
613
+ int i;
614
+ VALUE ary = rb_ary_new2(string_vector->count);
615
+ for(i = 0; i < string_vector->count; i++) {
616
+ rb_ary_push(ary, rb_str_new2(string_vector->data[i]));
617
+ }
618
+ return ary;
619
+ }
620
+
621
+ VALUE zkrb_stat_to_rarray(const struct Stat* stat) {
622
+ return rb_ary_new3(11,
623
+ LL2NUM(stat->czxid),
624
+ LL2NUM(stat->mzxid),
625
+ LL2NUM(stat->ctime),
626
+ LL2NUM(stat->mtime),
627
+ INT2NUM(stat->version),
628
+ INT2NUM(stat->cversion),
629
+ INT2NUM(stat->aversion),
630
+ LL2NUM(stat->ephemeralOwner),
631
+ INT2NUM(stat->dataLength),
632
+ INT2NUM(stat->numChildren),
633
+ LL2NUM(stat->pzxid));
634
+ }
635
+
636
+ VALUE zkrb_stat_to_rhash(const struct Stat *stat) {
637
+ VALUE ary = rb_hash_new();
638
+ rb_hash_aset(ary, GET_SYM("czxid"), LL2NUM(stat->czxid));
639
+ rb_hash_aset(ary, GET_SYM("mzxid"), LL2NUM(stat->mzxid));
640
+ rb_hash_aset(ary, GET_SYM("ctime"), LL2NUM(stat->ctime));
641
+ rb_hash_aset(ary, GET_SYM("mtime"), LL2NUM(stat->mtime));
642
+ rb_hash_aset(ary, GET_SYM("version"), INT2NUM(stat->version));
643
+ rb_hash_aset(ary, GET_SYM("cversion"), INT2NUM(stat->cversion));
644
+ rb_hash_aset(ary, GET_SYM("aversion"), INT2NUM(stat->aversion));
645
+ rb_hash_aset(ary, GET_SYM("ephemeralOwner"), LL2NUM(stat->ephemeralOwner));
646
+ rb_hash_aset(ary, GET_SYM("dataLength"), INT2NUM(stat->dataLength));
647
+ rb_hash_aset(ary, GET_SYM("numChildren"), INT2NUM(stat->numChildren));
648
+ rb_hash_aset(ary, GET_SYM("pzxid"), LL2NUM(stat->pzxid));
649
+ return ary;
650
+ }
651
+
652
+ #warning [wickman] TODO test zkrb_clone_acl_vector
653
+ struct ACL_vector * zkrb_clone_acl_vector(struct ACL_vector * src) {
654
+ struct ACL_vector * dst = malloc(sizeof(struct ACL_vector));
655
+ allocate_ACL_vector(dst, src->count);
656
+ int k;
657
+ for (k = 0; k < src->count; ++k) {
658
+ struct ACL * elt = &src->data[k];
659
+ dst->data[k].id.scheme = strdup(elt->id.scheme);
660
+ dst->data[k].id.id = strdup(elt->id.id);
661
+ dst->data[k].perms = elt->perms;
662
+ }
663
+ return dst;
664
+ }
665
+
666
+ #warning [wickman] TODO test zkrb_clone_string_vector
667
+ struct String_vector * zkrb_clone_string_vector(const struct String_vector * src) {
668
+ struct String_vector * dst = malloc(sizeof(struct String_vector));
669
+ allocate_String_vector(dst, src->count);
670
+ int k;
671
+ for (k = 0; k < src->count; ++k) {
672
+ dst->data[k] = strdup(src->data[k]);
673
+ }
674
+ return dst;
675
+ }
676
+
677
+ // vim:sts=2:sw=2:et