zookeeper 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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