zookeeper 0.2.2 → 0.3.0

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.
@@ -0,0 +1,527 @@
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
+ #include "ruby.h"
12
+ #include "zookeeper_lib.h"
13
+ #include "c-client-src/zookeeper.h"
14
+ #include <errno.h>
15
+ #include <stdio.h>
16
+ #include <stdlib.h>
17
+
18
+ #define GET_SYM(str) ID2SYM(rb_intern(str))
19
+
20
+ int ZKRBDebugging;
21
+
22
+ /* push/pop is a misnomer, this is a queue */
23
+ #warning [wickman] TODO enqueue, peek, dequeue => pthread_mutex_lock
24
+ void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
25
+ q->tail->event = elt;
26
+ q->tail->next = (struct zkrb_event_ll_t *) malloc(sizeof(struct zkrb_event_ll_t));
27
+ q->tail = q->tail->next;
28
+ q->tail->event = NULL;
29
+ q->tail->next = NULL;
30
+ }
31
+
32
+ zkrb_event_t * zkrb_peek(zkrb_queue_t *q) {
33
+ if (q->head != NULL && q->head->event != NULL)
34
+ return q->head->event;
35
+ return NULL;
36
+ }
37
+
38
+ zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q) {
39
+ if (q->head == NULL || q->head->event == NULL) {
40
+ return NULL;
41
+ } else {
42
+ struct zkrb_event_ll_t *old_root = q->head;
43
+ q->head = q->head->next;
44
+ zkrb_event_t *rv = old_root->event;
45
+ free(old_root);
46
+ return rv;
47
+ }
48
+ }
49
+
50
+ zkrb_queue_t *zkrb_queue_alloc(void) {
51
+ zkrb_queue_t *rq = malloc(sizeof(zkrb_queue_t));
52
+ rq->head = malloc(sizeof(struct zkrb_event_ll_t));
53
+ rq->head->event = NULL; rq->head->next = NULL;
54
+ rq->tail = rq->head;
55
+ return rq;
56
+ }
57
+
58
+ zkrb_event_t *zkrb_event_alloc(void) {
59
+ zkrb_event_t *rv = (zkrb_event_t *) malloc(sizeof(zkrb_event_t));
60
+ return rv;
61
+ }
62
+
63
+ void zkrb_event_free(zkrb_event_t *event) {
64
+ switch (event->type) {
65
+ case ZKRB_DATA: {
66
+ struct zkrb_data_completion *data_ctx = event->completion.data_completion;
67
+ free(data_ctx->data);
68
+ free(data_ctx->stat);
69
+ break;
70
+ }
71
+ case ZKRB_STAT: {
72
+ struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
73
+ free(stat_ctx->stat);
74
+ break;
75
+ }
76
+ case ZKRB_STRING: {
77
+ struct zkrb_string_completion *string_ctx = event->completion.string_completion;
78
+ free(string_ctx->value);
79
+ break;
80
+ }
81
+ case ZKRB_STRINGS: {
82
+ struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
83
+ int k;
84
+ for (k = 0; k < strings_ctx->values->count; ++k) free(strings_ctx->values->data[k]);
85
+ free(strings_ctx->values);
86
+ break;
87
+ }
88
+ case ZKRB_STRINGS_STAT: {
89
+ struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
90
+ int k;
91
+ for (k = 0; k < strings_stat_ctx->values->count; ++k) free(strings_stat_ctx->values->data[k]);
92
+ free(strings_stat_ctx->values);
93
+ free(strings_stat_ctx->stat);
94
+ break;
95
+ }
96
+ case ZKRB_ACL: {
97
+ struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
98
+ if (acl_ctx->acl) {
99
+ deallocate_ACL_vector(acl_ctx->acl);
100
+ free(acl_ctx->acl);
101
+ }
102
+ free(acl_ctx->stat);
103
+ break;
104
+ }
105
+ case ZKRB_WATCHER: {
106
+ struct zkrb_watcher_completion *watcher_ctx = event->completion.watcher_completion;
107
+ free(watcher_ctx->path);
108
+ break;
109
+ }
110
+ case ZKRB_VOID: {
111
+ break;
112
+ }
113
+
114
+ default:
115
+ #warning [wickman] TODO raise an exception?
116
+ fprintf(stderr, "ERROR?\n");
117
+ }
118
+ free(event);
119
+ }
120
+
121
+ /* this is called only from a method_get_latest_event, so the hash is
122
+ allocated on the proper thread stack */
123
+ VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
124
+ VALUE hash = rb_hash_new();
125
+
126
+ rb_hash_aset(hash, GET_SYM("req_id"), LL2NUM(event->req_id));
127
+ if (event->type != ZKRB_WATCHER)
128
+ rb_hash_aset(hash, GET_SYM("rc"), INT2FIX(event->rc));
129
+
130
+ switch (event->type) {
131
+ case ZKRB_DATA: {
132
+ struct zkrb_data_completion *data_ctx = event->completion.data_completion;
133
+ if (ZKRBDebugging) zkrb_print_stat(data_ctx->stat);
134
+ rb_hash_aset(hash, GET_SYM("data"), data_ctx->data ? rb_str_new2(data_ctx->data) : Qnil);
135
+ rb_hash_aset(hash, GET_SYM("stat"), data_ctx->stat ? zkrb_stat_to_rarray(data_ctx->stat) : Qnil);
136
+ break;
137
+ }
138
+ case ZKRB_STAT: {
139
+ struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
140
+ rb_hash_aset(hash, GET_SYM("stat"), stat_ctx->stat ? zkrb_stat_to_rarray(stat_ctx->stat) : Qnil);
141
+ break;
142
+ }
143
+ case ZKRB_STRING: {
144
+ struct zkrb_string_completion *string_ctx = event->completion.string_completion;
145
+ rb_hash_aset(hash, GET_SYM("string"), string_ctx->value ? rb_str_new2(string_ctx->value) : Qnil);
146
+ break;
147
+ }
148
+ case ZKRB_STRINGS: {
149
+ struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
150
+ rb_hash_aset(hash, GET_SYM("strings"), strings_ctx->values ? zkrb_string_vector_to_ruby(strings_ctx->values) : Qnil);
151
+ break;
152
+ }
153
+ case ZKRB_STRINGS_STAT: {
154
+ struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
155
+ rb_hash_aset(hash, GET_SYM("strings"), strings_stat_ctx->values ? zkrb_string_vector_to_ruby(strings_stat_ctx->values) : Qnil);
156
+ rb_hash_aset(hash, GET_SYM("stat"), strings_stat_ctx->stat ? zkrb_stat_to_rarray(strings_stat_ctx->stat) : Qnil);
157
+ break;
158
+ }
159
+ case ZKRB_ACL: {
160
+ struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
161
+ rb_hash_aset(hash, GET_SYM("acl"), acl_ctx->acl ? zkrb_acl_vector_to_ruby(acl_ctx->acl) : Qnil);
162
+ rb_hash_aset(hash, GET_SYM("stat"), acl_ctx->stat ? zkrb_stat_to_rarray(acl_ctx->stat) : Qnil);
163
+ break;
164
+ }
165
+ case ZKRB_WATCHER: {
166
+ struct zkrb_watcher_completion *watcher_ctx = event->completion.watcher_completion;
167
+ rb_hash_aset(hash, GET_SYM("type"), INT2FIX(watcher_ctx->type));
168
+ rb_hash_aset(hash, GET_SYM("state"), INT2FIX(watcher_ctx->state));
169
+ rb_hash_aset(hash, GET_SYM("path"), watcher_ctx->path ? rb_str_new2(watcher_ctx->path) : Qnil);
170
+ break;
171
+ }
172
+ case ZKRB_VOID:
173
+ default:
174
+ break;
175
+ }
176
+
177
+ return hash;
178
+ }
179
+
180
+ void zkrb_print_stat(const struct Stat *s) {
181
+ fprintf(stderr, "stat {\n");
182
+ if (s != NULL) {
183
+ fprintf(stderr, "\t czxid: %lld\n", s->czxid);
184
+ fprintf(stderr, "\t mzxid: %lld\n", s->mzxid);
185
+ fprintf(stderr, "\t ctime: %lld\n", s->ctime);
186
+ fprintf(stderr, "\t mtime: %lld\n", s->mtime);
187
+ fprintf(stderr, "\t version: %d\n" , s->version);
188
+ fprintf(stderr, "\t cversion: %d\n" , s->cversion);
189
+ fprintf(stderr, "\t aversion: %d\n" , s->aversion);
190
+ fprintf(stderr, "\t ephemeralOwner: %lld\n", s->ephemeralOwner);
191
+ fprintf(stderr, "\t dataLength: %d\n" , s->dataLength);
192
+ fprintf(stderr, "\t numChildren: %d\n" , s->numChildren);
193
+ fprintf(stderr, "\t pzxid: %lld\n", s->pzxid);
194
+ } else {
195
+ fprintf(stderr, "\tNULL\n");
196
+ }
197
+ fprintf(stderr, "}\n");
198
+ }
199
+
200
+ zkrb_calling_context *zkrb_calling_context_alloc(int64_t req_id, zkrb_queue_t *queue) {
201
+ zkrb_calling_context *ctx = malloc(sizeof(zkrb_calling_context));
202
+ ctx->req_id = req_id;
203
+ ctx->queue = queue;
204
+ return ctx;
205
+ }
206
+
207
+ void zkrb_print_calling_context(zkrb_calling_context *ctx) {
208
+ fprintf(stderr, "calling context (%#x){\n", ctx);
209
+ fprintf(stderr, "\treq_id = %lld\n", ctx->req_id);
210
+ fprintf(stderr, "\tqueue = 0x%#x\n", ctx->queue);
211
+ fprintf(stderr, "}\n");
212
+ }
213
+
214
+ /*
215
+ process completions that get queued to the watcher queue, translate events
216
+ to completions that the ruby side dispatches via callbacks.
217
+ */
218
+
219
+ #define ZKH_SETUP_EVENT(qptr, eptr) \
220
+ zkrb_calling_context *ctx = (zkrb_calling_context *) calling_ctx; \
221
+ zkrb_event_t *eptr = zkrb_event_alloc(); \
222
+ eptr->req_id = ctx->req_id; \
223
+ if (eptr->req_id != ZKRB_GLOBAL_REQ) free(ctx); \
224
+ zkrb_queue_t *qptr = ctx->queue;
225
+
226
+ void zkrb_state_callback(
227
+ zhandle_t *zh, int type, int state, const char *path, void *calling_ctx) {
228
+ /* logging */
229
+ if (ZKRBDebugging) {
230
+ fprintf(stderr, "ZOOKEEPER_C_STATE WATCHER "
231
+ "type = %d, state = %d, path = 0x%#x, value = %s\n",
232
+ type, state, (void *) path, path ? path : "NULL");
233
+ }
234
+
235
+ /* save callback context */
236
+ struct zkrb_watcher_completion *wc = malloc(sizeof(struct zkrb_watcher_completion));
237
+ wc->type = type;
238
+ wc->state = state;
239
+ wc->path = malloc(strlen(path) + 1);
240
+ strcpy(wc->path, path);
241
+
242
+ ZKH_SETUP_EVENT(queue, event);
243
+ event->type = ZKRB_WATCHER;
244
+ event->completion.watcher_completion = wc;
245
+
246
+ zkrb_enqueue(queue, event);
247
+ }
248
+
249
+
250
+
251
+ void zkrb_data_callback(
252
+ int rc, const char *value, int value_len, const struct Stat *stat, const void *calling_ctx) {
253
+ if (ZKRBDebugging) {
254
+ fprintf(stderr, "ZOOKEEPER_C_DATA WATCHER "
255
+ "rc = %d (%s), value = %s, len = %d\n",
256
+ rc, zerror(rc), value ? value : "NULL", value_len);
257
+ }
258
+
259
+ /* copy data completion */
260
+ struct zkrb_data_completion *dc = malloc(sizeof(struct zkrb_data_completion));
261
+ dc->data = dc->stat = NULL;
262
+ if (value != NULL) { dc->data = malloc(value_len); memcpy(dc->data, value, value_len); }
263
+ if (stat != NULL) { dc->stat = malloc(sizeof(struct Stat)); memcpy(dc->stat, stat, sizeof(struct Stat)); }
264
+
265
+ ZKH_SETUP_EVENT(queue, event);
266
+ event->rc = rc;
267
+ event->type = ZKRB_DATA;
268
+ event->completion.data_completion = dc;
269
+
270
+ zkrb_enqueue(queue, event);
271
+ }
272
+
273
+ void zkrb_stat_callback(
274
+ int rc, const struct Stat *stat, const void *calling_ctx) {
275
+ if (ZKRBDebugging) {
276
+ fprintf(stderr, "ZOOKEEPER_C_STAT WATCHER "
277
+ "rc = %d (%s)\n", rc, zerror(rc));
278
+ }
279
+
280
+ struct zkrb_stat_completion *sc = malloc(sizeof(struct zkrb_stat_completion));
281
+ sc->stat = NULL;
282
+ if (stat != NULL) { sc->stat = malloc(sizeof(struct Stat)); memcpy(sc->stat, stat, sizeof(struct Stat)); }
283
+
284
+ ZKH_SETUP_EVENT(queue, event);
285
+ event->rc = rc;
286
+ event->type = ZKRB_STAT;
287
+ event->completion.stat_completion = sc;
288
+
289
+ zkrb_enqueue(queue, event);
290
+ }
291
+
292
+ void zkrb_string_callback(
293
+ int rc, const char *string, const void *calling_ctx) {
294
+ if (ZKRBDebugging) {
295
+ fprintf(stderr, "ZOOKEEPER_C_STRING WATCHER "
296
+ "rc = %d (%s)\n", rc, zerror(rc));
297
+ }
298
+
299
+ struct zkrb_string_completion *sc = malloc(sizeof(struct zkrb_string_completion));
300
+ sc->value = NULL;
301
+ if (string != NULL) { sc->value = malloc(strlen(string) + 1); strcpy(sc->value, string); }
302
+
303
+ ZKH_SETUP_EVENT(queue, event);
304
+ event->rc = rc;
305
+ event->type = ZKRB_STRING;
306
+ event->completion.string_completion = sc;
307
+
308
+ zkrb_enqueue(queue, event);
309
+ }
310
+
311
+ void zkrb_strings_callback(
312
+ int rc, const struct String_vector *strings, const void *calling_ctx) {
313
+ if (ZKRBDebugging) {
314
+ fprintf(stderr, "ZOOKEEPER_C_STRINGS WATCHER "
315
+ "rc = %d (%s), calling_ctx = 0x%#x\n", rc, zerror(rc), calling_ctx);
316
+ }
317
+
318
+ /* copy string vector */
319
+ struct zkrb_strings_completion *sc = malloc(sizeof(struct zkrb_strings_completion));
320
+ sc->values = (strings != NULL) ? zkrb_clone_string_vector(strings) : NULL;
321
+
322
+ ZKH_SETUP_EVENT(queue, event);
323
+ event->rc = rc;
324
+ event->type = ZKRB_STRINGS;
325
+ event->completion.strings_completion = sc;
326
+
327
+ zkrb_enqueue(queue, event);
328
+ }
329
+
330
+ void zkrb_strings_stat_callback(
331
+ int rc, const struct String_vector *strings, const struct Stat *stat, const void *calling_ctx) {
332
+ if (ZKRBDebugging) {
333
+ fprintf(stderr, "ZOOKEEPER_C_STRINGS_STAT WATCHER "
334
+ "rc = %d (%s), calling_ctx = 0x%#x\n", rc, zerror(rc), calling_ctx);
335
+ }
336
+
337
+ struct zkrb_strings_stat_completion *sc = malloc(sizeof(struct zkrb_strings_stat_completion));
338
+ sc->stat = NULL;
339
+ if (stat != NULL) { sc->stat = malloc(sizeof(struct Stat)); memcpy(sc->stat, stat, sizeof(struct Stat)); }
340
+ sc->values = (strings != NULL) ? zkrb_clone_string_vector(strings) : NULL;
341
+
342
+ ZKH_SETUP_EVENT(queue, event);
343
+ event->rc = rc;
344
+ event->type = ZKRB_STRINGS_STAT;
345
+ event->completion.strings_completion = sc;
346
+
347
+ zkrb_enqueue(queue, event);
348
+ }
349
+
350
+ void zkrb_void_callback(
351
+ int rc, const void *calling_ctx) {
352
+ if (ZKRBDebugging) {
353
+ fprintf(stderr, "ZOOKEEPER_C_VOID WATCHER "
354
+ "rc = %d (%s)\n", rc, zerror(rc));
355
+ }
356
+
357
+ ZKH_SETUP_EVENT(queue, event);
358
+ event->rc = rc;
359
+ event->type = ZKRB_VOID;
360
+ event->completion.void_completion = NULL;
361
+
362
+ zkrb_enqueue(queue, event);
363
+ }
364
+
365
+ void zkrb_acl_callback(
366
+ int rc, struct ACL_vector *acls, struct Stat *stat, const void *calling_ctx) {
367
+ if (ZKRBDebugging) {
368
+ fprintf(stderr, "ZOOKEEPER_C_ACL WATCHER "
369
+ "rc = %d (%s)\n", rc, zerror(rc));
370
+ }
371
+
372
+ struct zkrb_acl_completion *ac = malloc(sizeof(struct zkrb_acl_completion));
373
+ ac->acl = ac->stat = NULL;
374
+ if (acls != NULL) { ac->acl = zkrb_clone_acl_vector(acls); }
375
+ if (stat != NULL) { ac->stat = malloc(sizeof(struct Stat)); memcpy(ac->stat, stat, sizeof(struct Stat)); }
376
+
377
+ ZKH_SETUP_EVENT(queue, event);
378
+ event->rc = rc;
379
+ event->type = ZKRB_ACL;
380
+ event->completion.acl_completion = ac;
381
+
382
+ /* should be synchronized */
383
+ zkrb_enqueue(queue, event);
384
+ }
385
+
386
+ VALUE zkrb_id_to_ruby(struct Id *id) {
387
+ VALUE hash = rb_hash_new();
388
+ rb_hash_aset(hash, GET_SYM("scheme"), rb_str_new2(id->scheme));
389
+ rb_hash_aset(hash, GET_SYM("id"), rb_str_new2(id->id));
390
+ return hash;
391
+ }
392
+
393
+ VALUE zkrb_acl_to_ruby(struct ACL *acl) {
394
+ VALUE hash = rb_hash_new();
395
+ rb_hash_aset(hash, GET_SYM("perms"), INT2NUM(acl->perms));
396
+ rb_hash_aset(hash, GET_SYM("id"), zkrb_id_to_ruby(&(acl->id)));
397
+ return hash;
398
+ }
399
+
400
+ #warning [wickman] TODO test zkrb_ruby_to_aclvector
401
+ struct ACL_vector * zkrb_ruby_to_aclvector(VALUE acl_ary) {
402
+ Check_Type(acl_ary, T_ARRAY);
403
+
404
+ struct ACL_vector *v = malloc(sizeof(struct ACL_vector));
405
+ allocate_ACL_vector(v, RARRAY(acl_ary)->len);
406
+
407
+ int k;
408
+ for (k = 0; k < v->count; ++k) {
409
+ VALUE acl_val = rb_ary_entry(acl_ary, k);
410
+ v->data[k] = zkrb_ruby_to_acl(acl_val);
411
+ }
412
+
413
+ return v;
414
+ }
415
+
416
+ #warning [wickman] TODO test zkrb_ruby_to_aclvector
417
+ struct ACL zkrb_ruby_to_acl(VALUE rubyacl) {
418
+ struct ACL acl;
419
+
420
+ VALUE perms = rb_iv_get(rubyacl, "@perms");
421
+ VALUE rubyid = rb_iv_get(rubyacl, "@id");
422
+ acl.perms = NUM2INT(perms);
423
+ acl.id = zkrb_ruby_to_id(rubyid);
424
+
425
+ return acl;
426
+ }
427
+
428
+ #warning [wickman] TODO zkrb_ruby_to_id error checking? test
429
+ struct Id zkrb_ruby_to_id(VALUE rubyid) {
430
+ struct Id id;
431
+
432
+ VALUE scheme = rb_iv_get(rubyid, "@scheme");
433
+ VALUE ident = rb_iv_get(rubyid, "@id");
434
+
435
+ if (scheme != Qnil) {
436
+ id.scheme = malloc(RSTRING(scheme)->len + 1);
437
+ strncpy(id.scheme, RSTRING(scheme)->ptr, RSTRING(scheme)->len);
438
+ } else {
439
+ id.scheme = NULL;
440
+ }
441
+
442
+ if (ident != Qnil) {
443
+ id.id = malloc(RSTRING(ident)->len + 1);
444
+ strncpy(id.id, RSTRING(ident)->ptr, RSTRING(ident)->len);
445
+ } else {
446
+ id.id = NULL;
447
+ }
448
+
449
+ return id;
450
+ }
451
+
452
+ VALUE zkrb_acl_vector_to_ruby(struct ACL_vector *acl_vector) {
453
+ int i = 0;
454
+ VALUE ary = rb_ary_new();
455
+ for(i = 0; i < acl_vector->count; i++) {
456
+ rb_ary_push(ary, zkrb_acl_to_ruby(acl_vector->data+i));
457
+ }
458
+ return ary;
459
+ }
460
+
461
+ VALUE zkrb_string_vector_to_ruby(struct String_vector *string_vector) {
462
+ int i = 0;
463
+ VALUE ary = rb_ary_new();
464
+ for(i = 0; i < string_vector->count; i++) {
465
+ rb_ary_push(ary, rb_str_new2(string_vector->data[i]));
466
+ }
467
+ return ary;
468
+ }
469
+
470
+ VALUE zkrb_stat_to_rarray(const struct Stat* stat) {
471
+ return rb_ary_new3(11,
472
+ LL2NUM(stat->czxid),
473
+ LL2NUM(stat->mzxid),
474
+ LL2NUM(stat->ctime),
475
+ LL2NUM(stat->mtime),
476
+ INT2NUM(stat->version),
477
+ INT2NUM(stat->cversion),
478
+ INT2NUM(stat->aversion),
479
+ LL2NUM(stat->ephemeralOwner),
480
+ INT2NUM(stat->dataLength),
481
+ INT2NUM(stat->numChildren),
482
+ LL2NUM(stat->pzxid));
483
+ }
484
+
485
+ VALUE zkrb_stat_to_rhash(const struct Stat *stat) {
486
+ VALUE ary = rb_hash_new();
487
+ rb_hash_aset(ary, GET_SYM("czxid"), LL2NUM(stat->czxid));
488
+ rb_hash_aset(ary, GET_SYM("mzxid"), LL2NUM(stat->mzxid));
489
+ rb_hash_aset(ary, GET_SYM("ctime"), LL2NUM(stat->ctime));
490
+ rb_hash_aset(ary, GET_SYM("mtime"), LL2NUM(stat->mtime));
491
+ rb_hash_aset(ary, GET_SYM("version"), INT2NUM(stat->version));
492
+ rb_hash_aset(ary, GET_SYM("cversion"), INT2NUM(stat->cversion));
493
+ rb_hash_aset(ary, GET_SYM("aversion"), INT2NUM(stat->aversion));
494
+ rb_hash_aset(ary, GET_SYM("ephemeralOwner"), LL2NUM(stat->ephemeralOwner));
495
+ rb_hash_aset(ary, GET_SYM("dataLength"), INT2NUM(stat->dataLength));
496
+ rb_hash_aset(ary, GET_SYM("numChildren"), INT2NUM(stat->numChildren));
497
+ rb_hash_aset(ary, GET_SYM("pzxid"), LL2NUM(stat->pzxid));
498
+ return ary;
499
+ }
500
+
501
+ #warning [wickman] TODO test zkrb_clone_acl_vector
502
+ struct ACL_vector * zkrb_clone_acl_vector(struct ACL_vector * src) {
503
+ struct ACL_vector * dst = malloc(sizeof(struct ACL_vector));
504
+ allocate_ACL_vector(dst, src->count);
505
+ int k;
506
+ for (k = 0; k < src->count; ++k) {
507
+ struct ACL * elt = &src->data[k];
508
+ dst->data[k].id.scheme = malloc(strlen(elt->id.scheme)+1);
509
+ dst->data[k].id.id = malloc(strlen(elt->id.id)+1);
510
+ strcpy(dst->data[k].id.scheme, elt->id.scheme);
511
+ strcpy(dst->data[k].id.id, elt->id.id);
512
+ dst->data[k].perms = elt->perms;
513
+ }
514
+ return dst;
515
+ }
516
+
517
+ #warning [wickman] TODO test zkrb_clone_string_vector
518
+ struct String_vector * zkrb_clone_string_vector(struct String_vector * src) {
519
+ struct String_vector * dst = malloc(sizeof(struct String_vector));
520
+ allocate_String_vector(dst, src->count);
521
+ int k;
522
+ for (k = 0; k < src->count; ++k) {
523
+ dst->data[k] = malloc(strlen(src->data[k]) + 1);
524
+ strcpy(dst->data[k], src->data[k]);
525
+ }
526
+ return dst;
527
+ }
@@ -0,0 +1,151 @@
1
+ #ifndef ZOOKEEPER_LIB_H
2
+ #define ZOOKEEPER_LIB_H
3
+
4
+ #include "ruby.h"
5
+ #include "c-client-src/zookeeper.h"
6
+ #include <errno.h>
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+
10
+ #define ZK_TRUE 1
11
+ #define ZK_FALSE 0
12
+ #define ZKRB_GLOBAL_REQ -1
13
+
14
+ extern int ZKRBDebugging;
15
+
16
+ struct zkrb_data_completion {
17
+ char *data;
18
+ struct Stat *stat;
19
+ };
20
+
21
+ struct zkrb_stat_completion {
22
+ struct Stat *stat;
23
+ };
24
+
25
+ struct zkrb_void_completion {
26
+ };
27
+
28
+ struct zkrb_string_completion {
29
+ char *value;
30
+ };
31
+
32
+ struct zkrb_strings_completion {
33
+ struct String_vector *values;
34
+ };
35
+
36
+ struct zkrb_strings_stat_completion {
37
+ struct String_vector *values;
38
+ struct Stat *stat;
39
+ };
40
+
41
+ struct zkrb_acl_completion {
42
+ struct ACL_vector *acl;
43
+ struct Stat *stat;
44
+ };
45
+
46
+ struct zkrb_watcher_completion {
47
+ int type;
48
+ int state;
49
+ char *path;
50
+ };
51
+
52
+ typedef struct {
53
+ int64_t req_id;
54
+ int rc;
55
+
56
+ enum {
57
+ ZKRB_DATA = 0,
58
+ ZKRB_STAT = 1,
59
+ ZKRB_VOID = 2,
60
+ ZKRB_STRING = 3,
61
+ ZKRB_STRINGS = 4,
62
+ ZKRB_STRINGS_STAT = 5,
63
+ ZKRB_ACL = 6,
64
+ ZKRB_WATCHER = 7
65
+ } type;
66
+
67
+ union {
68
+ struct zkrb_data_completion *data_completion;
69
+ struct zkrb_stat_completion *stat_completion;
70
+ struct zkrb_void_completion *void_completion;
71
+ struct zkrb_string_completion *string_completion;
72
+ struct zkrb_strings_completion *strings_completion;
73
+ struct zkrb_strings_stat_completion *strings_stat_completion;
74
+ struct zkrb_acl_completion *acl_completion;
75
+ struct zkrb_watcher_completion *watcher_completion;
76
+ } completion;
77
+ } zkrb_event_t;
78
+
79
+ struct zkrb_event_ll_t {
80
+ zkrb_event_t *event;
81
+ struct zkrb_event_ll_t *next;
82
+ };
83
+
84
+ typedef struct {
85
+ struct zkrb_event_ll_t *head;
86
+ struct zkrb_event_ll_t *tail;
87
+ } zkrb_queue_t;
88
+
89
+ zkrb_queue_t * zkrb_queue_alloc(void);
90
+ zkrb_event_t * zkrb_event_alloc(void);
91
+ void zkrb_event_free(zkrb_event_t *ptr);
92
+
93
+
94
+ /* push/pop is a misnomer, this is a queue */
95
+ void zkrb_enqueue(zkrb_queue_t *queue, zkrb_event_t *elt);
96
+ zkrb_event_t * zkrb_peek(zkrb_queue_t *queue);
97
+ zkrb_event_t * zkrb_dequeue(zkrb_queue_t *queue);
98
+
99
+ void zkrb_print_stat(const struct Stat *s);
100
+
101
+ typedef struct {
102
+ int64_t req_id;
103
+ zkrb_queue_t *queue;
104
+ } zkrb_calling_context;
105
+
106
+ void zkrb_print_calling_context(zkrb_calling_context *ctx);
107
+ zkrb_calling_context *zkrb_calling_context_alloc(int64_t req_id, zkrb_queue_t *queue);
108
+
109
+ /*
110
+ default process completions that get queued into the ruby client event queue
111
+ */
112
+
113
+ void zkrb_state_callback(
114
+ zhandle_t *zh, int type, int state, const char *path, void *calling_ctx);
115
+
116
+ void zkrb_data_callback(
117
+ int rc, const char *value, int value_len, const struct Stat *stat, const void *calling_ctx);
118
+
119
+ void zkrb_stat_callback(
120
+ int rc, const struct Stat *stat, const void *calling_ctx);
121
+
122
+ void zkrb_string_callback(
123
+ int rc, const char *string, const void *calling_ctx);
124
+
125
+ void zkrb_strings_callback(
126
+ int rc, const struct String_vector *strings, const void *calling_ctx);
127
+
128
+ void zkrb_strings_stat_callback(
129
+ int rc, const struct String_vector *strings, const struct Stat* stat, const void *calling_ctx);
130
+
131
+ void zkrb_void_callback(
132
+ int rc, const void *calling_ctx);
133
+
134
+ void zkrb_acl_callback(
135
+ int rc, struct ACL_vector *acls, struct Stat *stat, const void *calling_ctx);
136
+
137
+ VALUE zkrb_event_to_ruby(zkrb_event_t *event);
138
+ VALUE zkrb_acl_to_ruby(struct ACL *acl);
139
+ VALUE zkrb_acl_vector_to_ruby(struct ACL_vector *acl_vector);
140
+ VALUE zkrb_id_to_ruby(struct Id *id);
141
+ VALUE zkrb_string_vector_to_ruby(struct String_vector *string_vector);
142
+ VALUE zkrb_stat_to_rarray(const struct Stat *stat);
143
+ VALUE zkrb_stat_to_rhash(const struct Stat* stat);
144
+
145
+ struct ACL_vector * zkrb_ruby_to_aclvector(VALUE acl_ary);
146
+ struct ACL_vector * zkrb_clone_acl_vector(struct ACL_vector * src);
147
+ struct String_vector * zkrb_clone_string_vector(struct String_vector * src);
148
+ struct ACL zkrb_ruby_to_acl(VALUE rubyacl);
149
+ struct Id zkrb_ruby_to_id(VALUE rubyid);
150
+
151
+ #endif /* ZOOKEEPER_LIB_H */
@@ -0,0 +1,31 @@
1
+ module ZookeeperACLs
2
+ class Id
3
+ attr_reader :scheme, :id
4
+ def initialize(hash)
5
+ @scheme = hash[:scheme]
6
+ @id = hash[:id]
7
+ end
8
+ end
9
+
10
+ class ACL
11
+ attr_reader :perms, :id
12
+ def initialize(hash)
13
+ @perms = hash[:perms]
14
+ @id = hash[:id]
15
+ end
16
+ end
17
+
18
+ ZOO_PERM_READ = 0
19
+ ZOO_PERM_WRITE = 1
20
+ ZOO_PERM_CREATE = 2
21
+ ZOO_PERM_DELETE = 4
22
+ ZOO_PERM_ADMIN = 8
23
+ ZOO_PERM_ALL = ZOO_PERM_READ | ZOO_PERM_WRITE | ZOO_PERM_CREATE | ZOO_PERM_DELETE | ZOO_PERM_ADMIN
24
+
25
+ ZOO_ANYONE_ID_UNSAFE = Id.new(:scheme => "world", :id => "anyone")
26
+ ZOO_AUTH_IDS = Id.new(:scheme => "auth", :id => "")
27
+
28
+ ZOO_OPEN_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_ANYONE_ID_UNSAFE)]
29
+ ZOO_READ_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_READ, :id => ZOO_ANYONE_ID_UNSAFE)]
30
+ ZOO_CREATOR_ALL_ACL = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_AUTH_IDS)]
31
+ end