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.
- data/CHANGELOG +3 -0
- data/Manifest +13 -1
- data/README +30 -0
- data/Rakefile +1 -1
- data/examples/cloud_config.rb +125 -0
- data/ext/zkc-3.3.1.tar.gz +0 -0
- data/ext/zookeeper_c.c +338 -393
- data/ext/zookeeper_lib.c +527 -0
- data/ext/zookeeper_lib.h +151 -0
- data/lib/zookeeper/acls.rb +31 -0
- data/lib/zookeeper/callbacks.rb +89 -0
- data/lib/zookeeper/constants.rb +54 -0
- data/lib/zookeeper/exceptions.rb +91 -0
- data/lib/zookeeper/stat.rb +12 -0
- data/lib/zookeeper.rb +207 -51
- data/test/test_basic.rb +16 -39
- data/test/test_callback1.rb +36 -0
- data/test/test_esoteric.rb +7 -0
- data/test/test_watcher1.rb +56 -0
- data/test/test_watcher2.rb +52 -0
- data/zookeeper.gemspec +6 -6
- data.tar.gz.sig +0 -0
- metadata +31 -7
- metadata.gz.sig +0 -0
- data/ext/zkc-3.2.2.tar.gz +0 -0
data/ext/zookeeper_c.c
CHANGED
@@ -1,83 +1,79 @@
|
|
1
1
|
/* Ruby wrapper for the Zookeeper C API
|
2
2
|
* Phillip Pearson <pp@myelin.co.nz>
|
3
3
|
* Eric Maland <eric@twitter.com>
|
4
|
+
* Brian Wickman <wickman@twitter.com>
|
5
|
+
*
|
6
|
+
* This fork is a 90% rewrite of the original. It takes a more evented
|
7
|
+
* approach to isolate the ZK state machine from the ruby interpreter via an
|
8
|
+
* event queue. It's similar to the ZookeeperFFI version except that it
|
9
|
+
* actually works on MRI 1.8.
|
4
10
|
*/
|
5
11
|
|
6
12
|
#define THREADED
|
7
13
|
|
8
14
|
#include "ruby.h"
|
9
|
-
|
10
15
|
#include "c-client-src/zookeeper.h"
|
11
16
|
#include <errno.h>
|
12
17
|
#include <stdio.h>
|
18
|
+
#include <stdlib.h>
|
19
|
+
|
20
|
+
#include "zookeeper_lib.h"
|
13
21
|
|
14
22
|
static VALUE Zookeeper = Qnil;
|
15
|
-
static VALUE eNoNode = Qnil;
|
16
|
-
static VALUE eBadVersion = Qnil;
|
17
23
|
|
18
|
-
struct
|
19
|
-
zhandle_t
|
20
|
-
clientid_t
|
24
|
+
struct zkrb_instance_data {
|
25
|
+
zhandle_t *zh;
|
26
|
+
clientid_t myid;
|
27
|
+
zkrb_queue_t *queue;
|
21
28
|
};
|
22
29
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
#warning [
|
36
|
-
|
37
|
-
|
38
|
-
case ZOK:
|
39
|
-
/* all good! */
|
40
|
-
break;
|
41
|
-
case ZNONODE:
|
42
|
-
rb_raise(eNoNode, "the node does not exist");
|
43
|
-
break;
|
44
|
-
case ZBADVERSION:
|
45
|
-
rb_raise(eBadVersion, "expected version does not match actual version");
|
46
|
-
break;
|
47
|
-
default:
|
48
|
-
rb_raise(rb_eRuntimeError, "unknown error returned from zookeeper: %d (%s)", rc, zerror(rc));
|
30
|
+
typedef enum {
|
31
|
+
SYNC = 0,
|
32
|
+
ASYNC = 1,
|
33
|
+
SYNC_WATCH = 2,
|
34
|
+
ASYNC_WATCH = 3
|
35
|
+
} zkrb_call_type;
|
36
|
+
|
37
|
+
#define IS_SYNC(zkrbcall) ((zkrbcall)==SYNC || (zkrbcall)==SYNC_WATCH)
|
38
|
+
#define IS_ASYNC(zkrbcall) ((zkrbcall)==ASYNC || (zkrbcall)==ASYNC_WATCH)
|
39
|
+
|
40
|
+
static void free_zkrb_instance_data(struct zkrb_instance_data* ptr) {
|
41
|
+
#warning [wickman] TODO: free queue
|
42
|
+
#warning [wickman] TODO: fire off warning if queue is not empty
|
43
|
+
if (ptr->zh && zoo_state(ptr->zh) == ZOO_CONNECTED_STATE) {
|
44
|
+
zookeeper_close(ptr->zh);
|
49
45
|
}
|
50
46
|
}
|
51
47
|
|
52
|
-
static void free_zk_rb_data(struct zk_rb_data* ptr) {
|
53
|
-
zookeeper_close(ptr->zh);
|
54
|
-
}
|
55
|
-
|
56
|
-
static VALUE array_from_stat(const struct Stat* stat) {
|
57
|
-
return rb_ary_new3(8,
|
58
|
-
LL2NUM(stat->czxid),
|
59
|
-
LL2NUM(stat->mzxid),
|
60
|
-
LL2NUM(stat->ctime),
|
61
|
-
LL2NUM(stat->mtime),
|
62
|
-
INT2NUM(stat->version),
|
63
|
-
INT2NUM(stat->cversion),
|
64
|
-
INT2NUM(stat->aversion),
|
65
|
-
LL2NUM(stat->ephemeralOwner));
|
66
|
-
}
|
67
|
-
|
68
48
|
static VALUE method_initialize(VALUE self, VALUE hostPort) {
|
69
|
-
VALUE data;
|
70
|
-
struct zk_rb_data* zk = NULL;
|
71
|
-
|
72
49
|
Check_Type(hostPort, T_STRING);
|
73
50
|
|
74
|
-
data
|
75
|
-
|
51
|
+
VALUE data;
|
52
|
+
struct zkrb_instance_data *zk_local_ctx = NULL;
|
53
|
+
data = Data_Make_Struct(Zookeeper,
|
54
|
+
struct zkrb_instance_data,
|
55
|
+
0,
|
56
|
+
free_zkrb_instance_data,
|
57
|
+
zk_local_ctx);
|
58
|
+
zk_local_ctx->queue = zkrb_queue_alloc();
|
59
|
+
|
76
60
|
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
|
77
61
|
zoo_deterministic_conn_order(0);
|
78
|
-
|
79
|
-
|
80
|
-
|
62
|
+
|
63
|
+
zkrb_calling_context *ctx =
|
64
|
+
zkrb_calling_context_alloc(ZKRB_GLOBAL_REQ, zk_local_ctx->queue);
|
65
|
+
|
66
|
+
zk_local_ctx->zh =
|
67
|
+
zookeeper_init(
|
68
|
+
RSTRING(hostPort)->ptr,
|
69
|
+
zkrb_state_callback,
|
70
|
+
10000,
|
71
|
+
&zk_local_ctx->myid,
|
72
|
+
ctx,
|
73
|
+
0);
|
74
|
+
|
75
|
+
#warning [wickman] TODO handle this properly on the Ruby side rather than C side
|
76
|
+
if (!zk_local_ctx->zh) {
|
81
77
|
rb_raise(rb_eRuntimeError, "error connecting to zookeeper: %d", errno);
|
82
78
|
}
|
83
79
|
|
@@ -87,194 +83,298 @@ static VALUE method_initialize(VALUE self, VALUE hostPort) {
|
|
87
83
|
}
|
88
84
|
|
89
85
|
#define FETCH_DATA_PTR(x, y) \
|
90
|
-
struct
|
91
|
-
Data_Get_Struct(rb_iv_get(x, "@data"), struct
|
92
|
-
|
93
|
-
|
86
|
+
struct zkrb_instance_data * y; \
|
87
|
+
Data_Get_Struct(rb_iv_get(x, "@data"), struct zkrb_instance_data, y)
|
88
|
+
|
89
|
+
#define STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, cb_ctx, w_ctx, call_type) \
|
90
|
+
if (TYPE(reqid) != T_FIXNUM && TYPE(reqid) != T_BIGNUM) { \
|
91
|
+
rb_raise(rb_eTypeError, "reqid must be Fixnum/Bignum"); \
|
92
|
+
return Qnil; \
|
93
|
+
} \
|
94
|
+
Check_Type(path, T_STRING); \
|
95
|
+
struct zkrb_instance_data * zk; \
|
96
|
+
Data_Get_Struct(rb_iv_get(self, "@data"), struct zkrb_instance_data, zk); \
|
97
|
+
zkrb_calling_context* cb_ctx = \
|
98
|
+
(async != Qfalse && async != Qnil) ? \
|
99
|
+
zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
|
100
|
+
NULL; \
|
101
|
+
zkrb_calling_context* w_ctx = \
|
102
|
+
(watch != Qfalse && watch != Qnil) ? \
|
103
|
+
zkrb_calling_context_alloc(NUM2LL(reqid), zk->queue) : \
|
104
|
+
NULL; \
|
105
|
+
int a = (async != Qfalse && async != Qnil); \
|
106
|
+
int w = (watch != Qfalse && watch != Qnil); \
|
107
|
+
zkrb_call_type call_type; \
|
108
|
+
if (a) { if (w) { call_type = ASYNC_WATCH; } else { call_type = ASYNC; } } \
|
109
|
+
else { if (w) { call_type = SYNC_WATCH; } else { call_type = SYNC; } }
|
110
|
+
|
111
|
+
static VALUE method_get_children(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
|
112
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
113
|
+
|
94
114
|
struct String_vector strings;
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
115
|
+
struct Stat stat;
|
116
|
+
|
117
|
+
int rc;
|
118
|
+
switch (call_type) {
|
119
|
+
case SYNC:
|
120
|
+
rc = zoo_get_children2(zk->zh, RSTRING(path)->ptr, 0, &strings, &stat);
|
121
|
+
break;
|
122
|
+
|
123
|
+
case SYNC_WATCH:
|
124
|
+
rc = zoo_wget_children2(zk->zh, RSTRING(path)->ptr, zkrb_state_callback, watch_ctx, &strings, &stat);
|
125
|
+
break;
|
126
|
+
|
127
|
+
case ASYNC:
|
128
|
+
rc = zoo_aget_children2(zk->zh, RSTRING(path)->ptr, 0, zkrb_strings_stat_callback, data_ctx);
|
129
|
+
break;
|
130
|
+
|
131
|
+
case ASYNC_WATCH:
|
132
|
+
rc = zoo_awget_children2(zk->zh, RSTRING(path)->ptr, zkrb_state_callback, watch_ctx, zkrb_strings_stat_callback, data_ctx);
|
133
|
+
break;
|
134
|
+
}
|
102
135
|
|
103
|
-
output = rb_ary_new();
|
104
|
-
|
105
|
-
|
136
|
+
VALUE output = rb_ary_new();
|
137
|
+
rb_ary_push(output, INT2FIX(rc));
|
138
|
+
if (IS_SYNC(call_type) && rc == ZOK) {
|
139
|
+
rb_ary_push(output, zkrb_string_vector_to_ruby(&strings));
|
140
|
+
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
106
141
|
}
|
107
142
|
return output;
|
108
143
|
}
|
109
144
|
|
110
|
-
static VALUE method_exists(VALUE self, VALUE path, VALUE watch) {
|
145
|
+
static VALUE method_exists(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
|
146
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
147
|
+
|
111
148
|
struct Stat stat;
|
112
149
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
150
|
+
int rc;
|
151
|
+
switch (call_type) {
|
152
|
+
case SYNC:
|
153
|
+
rc = zoo_exists(zk->zh, RSTRING(path)->ptr, 0, &stat);
|
154
|
+
break;
|
155
|
+
|
156
|
+
case SYNC_WATCH:
|
157
|
+
rc = zoo_wexists(zk->zh, RSTRING(path)->ptr, zkrb_state_callback, watch_ctx, &stat);
|
158
|
+
break;
|
159
|
+
|
160
|
+
case ASYNC:
|
161
|
+
rc = zoo_aexists(zk->zh, RSTRING(path)->ptr, 0, zkrb_stat_callback, data_ctx);
|
162
|
+
break;
|
163
|
+
|
164
|
+
case ASYNC_WATCH:
|
165
|
+
rc = zoo_awexists(zk->zh, RSTRING(path)->ptr, zkrb_state_callback, watch_ctx, zkrb_stat_callback, data_ctx);
|
166
|
+
break;
|
167
|
+
}
|
117
168
|
|
118
|
-
|
169
|
+
VALUE output = rb_ary_new();
|
170
|
+
rb_ary_push(output, INT2FIX(rc));
|
171
|
+
if (IS_SYNC(call_type) && rc == ZOK) {
|
172
|
+
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
173
|
+
}
|
174
|
+
return output;
|
119
175
|
}
|
120
176
|
|
121
|
-
static VALUE method_create(VALUE self, VALUE path, VALUE
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
177
|
+
static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE async, VALUE acls, VALUE flags) {
|
178
|
+
VALUE watch = Qfalse;
|
179
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
180
|
+
|
181
|
+
struct Stat stat;
|
182
|
+
if (data != Qnil) Check_Type(data, T_STRING);
|
126
183
|
Check_Type(flags, T_FIXNUM);
|
184
|
+
const char *data_ptr = (data == Qnil) ? NULL : RSTRING(data)->ptr;
|
185
|
+
size_t data_len = (data == Qnil) ? -1 : RSTRING(data)->len;
|
186
|
+
|
187
|
+
struct ACL_vector *aclptr = NULL;
|
188
|
+
if (acls != Qnil) { aclptr = zkrb_ruby_to_aclvector(acls); }
|
189
|
+
char realpath[16384];
|
190
|
+
|
191
|
+
int rc;
|
192
|
+
switch (call_type) {
|
193
|
+
case SYNC:
|
194
|
+
rc = zoo_create(zk->zh, RSTRING(path)->ptr, data_ptr, data_len, aclptr, FIX2INT(flags), realpath, sizeof(realpath));
|
195
|
+
if (aclptr != NULL) deallocate_ACL_vector(aclptr);
|
196
|
+
break;
|
197
|
+
case ASYNC:
|
198
|
+
rc = zoo_acreate(zk->zh, RSTRING(path)->ptr, data_ptr, data_len, aclptr, FIX2INT(flags), zkrb_string_callback, data_ctx);
|
199
|
+
if (aclptr != NULL) deallocate_ACL_vector(aclptr);
|
200
|
+
break;
|
201
|
+
default:
|
202
|
+
/* TODO(wickman) raise proper argument error */
|
203
|
+
return Qnil;
|
204
|
+
break;
|
205
|
+
}
|
127
206
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
return rb_str_new2(realpath);
|
207
|
+
VALUE output = rb_ary_new();
|
208
|
+
rb_ary_push(output, INT2FIX(rc));
|
209
|
+
if (IS_SYNC(call_type) && rc == ZOK) {
|
210
|
+
return rb_ary_push(output, rb_str_new2(realpath));
|
211
|
+
}
|
212
|
+
return output;
|
136
213
|
}
|
137
214
|
|
138
|
-
static VALUE method_delete(VALUE self, VALUE path, VALUE version) {
|
139
|
-
|
215
|
+
static VALUE method_delete(VALUE self, VALUE reqid, VALUE path, VALUE version, VALUE async) {
|
216
|
+
VALUE watch = Qfalse;
|
217
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
140
218
|
Check_Type(version, T_FIXNUM);
|
141
|
-
|
142
|
-
FETCH_DATA_PTR(self, zk);
|
143
|
-
|
144
|
-
check_errors(zoo_delete(zk->zh, RSTRING(path)->ptr, FIX2INT(version)));
|
145
|
-
|
146
|
-
return Qtrue;
|
147
|
-
}
|
148
|
-
|
149
|
-
static VALUE method_get(VALUE self, VALUE path) {
|
150
|
-
char data[1024];
|
151
|
-
int data_len = sizeof(data);
|
152
|
-
|
153
|
-
struct Stat stat;
|
154
|
-
memset(data, 0, sizeof(data));
|
155
|
-
|
156
|
-
Check_Type(path, T_STRING);
|
157
|
-
FETCH_DATA_PTR(self, zk);
|
158
219
|
|
159
|
-
|
220
|
+
int rc = 0;
|
221
|
+
switch (call_type) {
|
222
|
+
case SYNC:
|
223
|
+
rc = zoo_delete(zk->zh, RSTRING(path)->ptr, FIX2INT(version));
|
224
|
+
break;
|
225
|
+
case ASYNC:
|
226
|
+
rc = zoo_adelete(zk->zh, RSTRING(path)->ptr, FIX2INT(version), zkrb_void_callback, data_ctx);
|
227
|
+
break;
|
228
|
+
default:
|
229
|
+
/* TODO(wickman) raise proper argument error */
|
230
|
+
return Qnil;
|
231
|
+
break;
|
232
|
+
}
|
160
233
|
|
161
|
-
return
|
162
|
-
rb_str_new(data, data_len),
|
163
|
-
array_from_stat(&stat));
|
234
|
+
return INT2FIX(rc);
|
164
235
|
}
|
165
236
|
|
166
|
-
static VALUE method_set(int argc, VALUE* argv, VALUE self)
|
167
|
-
{
|
168
|
-
VALUE v_path, v_data, v_version;
|
169
|
-
int real_version = -1;
|
170
|
-
|
171
|
-
FETCH_DATA_PTR(self, zk);
|
172
|
-
|
173
|
-
rb_scan_args(argc, argv, "21", &v_path, &v_data, &v_version);
|
174
|
-
|
175
|
-
Check_Type(v_path, T_STRING);
|
176
|
-
Check_Type(v_data, T_STRING);
|
177
|
-
Check_Type(v_version, T_FIXNUM);
|
178
237
|
|
179
|
-
|
180
|
-
real_version = FIX2INT(v_version);
|
238
|
+
#define MAX_ZNODE_SIZE 1048576
|
181
239
|
|
182
|
-
|
183
|
-
|
184
|
-
RSTRING(v_data)->ptr, RSTRING(v_data)->len,
|
185
|
-
FIX2INT(v_version)));
|
240
|
+
static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE watch) {
|
241
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
186
242
|
|
187
|
-
|
188
|
-
|
243
|
+
/* ugh */
|
244
|
+
char * data = malloc(MAX_ZNODE_SIZE);
|
245
|
+
int data_len = MAX_ZNODE_SIZE;
|
246
|
+
struct Stat stat;
|
189
247
|
|
190
|
-
|
248
|
+
int rc;
|
249
|
+
switch (call_type) {
|
250
|
+
case SYNC:
|
251
|
+
rc = zoo_get(zk->zh, RSTRING(path)->ptr, 0, data, &data_len, &stat);
|
252
|
+
break;
|
253
|
+
|
254
|
+
case SYNC_WATCH:
|
255
|
+
rc = zoo_wget(zk->zh, RSTRING(path)->ptr, zkrb_state_callback, watch_ctx, data, &data_len, &stat);
|
256
|
+
break;
|
257
|
+
|
258
|
+
case ASYNC:
|
259
|
+
rc = zoo_aget(zk->zh, RSTRING(path)->ptr, 0, zkrb_data_callback, data_ctx);
|
260
|
+
break;
|
261
|
+
|
262
|
+
case ASYNC_WATCH:
|
263
|
+
rc = zoo_awget(zk->zh, RSTRING(path)->ptr, zkrb_state_callback, watch_ctx, zkrb_data_callback, data_ctx);
|
264
|
+
break;
|
265
|
+
}
|
191
266
|
|
267
|
+
VALUE output = rb_ary_new();
|
268
|
+
rb_ary_push(output, INT2FIX(rc));
|
269
|
+
if (IS_SYNC(call_type) && rc == ZOK) {
|
270
|
+
rb_ary_push(output, rb_str_new(data, data_len));
|
271
|
+
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
272
|
+
}
|
273
|
+
free(data);
|
274
|
+
return output;
|
192
275
|
}
|
193
276
|
|
194
|
-
static
|
277
|
+
static VALUE method_set(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE async, VALUE version) {
|
278
|
+
VALUE watch = Qfalse;
|
279
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
195
280
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
281
|
+
struct Stat stat;
|
282
|
+
if (data != Qnil) Check_Type(data, T_STRING);
|
283
|
+
const char *data_ptr = (data == Qnil) ? NULL : RSTRING(data)->ptr;
|
284
|
+
size_t data_len = (data == Qnil) ? -1 : RSTRING(data)->len;
|
285
|
+
|
286
|
+
int rc;
|
287
|
+
switch (call_type) {
|
288
|
+
case SYNC:
|
289
|
+
rc = zoo_set2(zk->zh, RSTRING(path)->ptr, data_ptr, data_len, FIX2INT(version), &stat);
|
290
|
+
break;
|
291
|
+
case ASYNC:
|
292
|
+
rc = zoo_aset(zk->zh, RSTRING(path)->ptr, data_ptr, data_len, FIX2INT(version),
|
293
|
+
zkrb_stat_callback, data_ctx);
|
294
|
+
break;
|
295
|
+
default:
|
296
|
+
/* TODO(wickman) raise proper argument error */
|
297
|
+
return Qnil;
|
298
|
+
break;
|
299
|
+
}
|
203
300
|
|
301
|
+
VALUE output = rb_ary_new();
|
302
|
+
rb_ary_push(output, INT2FIX(rc));
|
303
|
+
if (IS_SYNC(call_type) && rc == ZOK) {
|
304
|
+
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
305
|
+
}
|
306
|
+
return output;
|
204
307
|
}
|
205
308
|
|
206
|
-
static VALUE method_set_acl(
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
309
|
+
static VALUE method_set_acl(VALUE self, VALUE reqid, VALUE path, VALUE acls, VALUE async, VALUE version) {
|
310
|
+
VALUE watch = Qfalse;
|
311
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
312
|
+
struct ACL_vector * aclptr = zkrb_ruby_to_aclvector(acls);
|
313
|
+
|
314
|
+
int rc;
|
315
|
+
switch (call_type) {
|
316
|
+
case SYNC:
|
317
|
+
rc = zoo_set_acl(zk->zh, RSTRING(path)->ptr, FIX2INT(version), aclptr);
|
318
|
+
deallocate_ACL_vector(aclptr);
|
319
|
+
break;
|
320
|
+
case ASYNC:
|
321
|
+
rc = zoo_aset_acl(zk->zh, RSTRING(path)->ptr, FIX2INT(version), aclptr, zkrb_void_callback, data_ctx);
|
322
|
+
deallocate_ACL_vector(aclptr);
|
323
|
+
break;
|
324
|
+
default:
|
325
|
+
/* TODO(wickman) raise proper argument error */
|
326
|
+
return Qnil;
|
327
|
+
break;
|
328
|
+
}
|
211
329
|
|
212
|
-
|
213
|
-
|
214
|
-
/* Check_Type(v_path, T_STRING); */
|
215
|
-
/* Check_Type(v_data, T_STRING); */
|
216
|
-
/* Check_Type(v_version, T_FIXNUM); */
|
330
|
+
return INT2FIX(rc);
|
331
|
+
}
|
217
332
|
|
218
|
-
|
219
|
-
|
333
|
+
static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
|
334
|
+
VALUE watch = Qfalse;
|
335
|
+
STANDARD_PREAMBLE(self, zk, reqid, path, async, watch, data_ctx, watch_ctx, call_type);
|
220
336
|
|
221
|
-
|
337
|
+
struct ACL_vector acls;
|
338
|
+
struct Stat stat;
|
222
339
|
|
223
|
-
|
224
|
-
|
225
|
-
|
340
|
+
int rc;
|
341
|
+
switch (call_type) {
|
342
|
+
case SYNC:
|
343
|
+
rc = zoo_get_acl(zk->zh, RSTRING(path)->ptr, &acls, &stat);
|
344
|
+
break;
|
345
|
+
case ASYNC:
|
346
|
+
rc = zoo_aget_acl(zk->zh, RSTRING(path)->ptr, zkrb_acl_callback, data_ctx);
|
347
|
+
break;
|
348
|
+
default:
|
349
|
+
/* TODO(wickman) raise proper argument error */
|
350
|
+
return Qnil;
|
351
|
+
break;
|
352
|
+
}
|
226
353
|
|
227
|
-
|
354
|
+
// do we need to deallocate the strings in the acl vector????
|
355
|
+
VALUE output = rb_ary_new();
|
356
|
+
rb_ary_push(output, INT2FIX(rc));
|
357
|
+
if (IS_SYNC(call_type) && rc == ZOK) {
|
358
|
+
rb_ary_push(output, zkrb_acl_vector_to_ruby(&acls));
|
359
|
+
rb_ary_push(output, zkrb_stat_to_rarray(&stat));
|
360
|
+
}
|
361
|
+
return output;
|
228
362
|
}
|
229
363
|
|
230
|
-
|
231
|
-
|
232
|
-
zh: the zookeeper handle obtained by a call to zookeeper.init
|
233
|
-
scheme: the id of authentication scheme. Natively supported:
|
234
|
-
'digest' password-based authentication
|
235
|
-
cert: application credentials. The actual value depends on the scheme.
|
236
|
-
completion: the routine to invoke when the request completes. One of
|
237
|
-
the following result codes may be passed into the completion callback:
|
238
|
-
OK operation completed successfully
|
239
|
-
AUTHFAILED authentication failed
|
240
|
-
|
241
|
-
RETURNS:
|
242
|
-
OK on success or one of the following errcodes on failure:
|
243
|
-
BADARGUMENTS - invalid input parameters
|
244
|
-
INVALIDSTATE - zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAI
|
245
|
-
LED_STATE
|
246
|
-
MARSHALLINGERROR - failed to marshall a request; possibly, out of memory
|
247
|
-
SYSTEMERROR - a system error occured
|
248
|
-
*/
|
249
|
-
#warning [emaland] make these magically synchronous for now?
|
250
|
-
static VALUE method_add_auth(VALUE self, VALUE scheme,
|
251
|
-
VALUE cert, VALUE completion,
|
252
|
-
VALUE completion_data) {
|
253
|
-
struct zk_rb_data* zk;
|
254
|
-
Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
|
255
|
-
|
256
|
-
Check_Type(scheme, T_STRING);
|
257
|
-
Check_Type(cert, T_STRING);
|
258
|
-
// Check_Type(completion, T_OBJECT); // ???
|
364
|
+
static VALUE method_get_next_event(VALUE self) {
|
365
|
+
FETCH_DATA_PTR(self, zk);
|
259
366
|
|
260
|
-
|
261
|
-
|
262
|
-
void_completion_callback, DATA_PTR(completion_data)));
|
263
|
-
return Qtrue;
|
264
|
-
}
|
265
|
-
|
266
|
-
static VALUE method_async(VALUE self, VALUE path,
|
267
|
-
VALUE completion, VALUE completion_data) {
|
268
|
-
struct zk_rb_data* zk;
|
269
|
-
Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
|
367
|
+
zkrb_event_t *event = zkrb_dequeue(zk->queue);
|
368
|
+
if (event == NULL) return Qnil;
|
270
369
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
string_completion_callback, DATA_PTR(completion_data)));
|
370
|
+
VALUE hash = zkrb_event_to_ruby(event);
|
371
|
+
zkrb_event_free(event);
|
372
|
+
return hash;
|
373
|
+
}
|
276
374
|
|
277
|
-
|
375
|
+
static VALUE method_has_events(VALUE self) {
|
376
|
+
FETCH_DATA_PTR(self, zk);
|
377
|
+
return zkrb_peek(zk->queue) != NULL ? Qtrue : Qfalse;
|
278
378
|
}
|
279
379
|
|
280
380
|
static VALUE method_client_id(VALUE self) {
|
@@ -285,8 +385,8 @@ static VALUE method_client_id(VALUE self) {
|
|
285
385
|
|
286
386
|
static VALUE method_close(VALUE self) {
|
287
387
|
FETCH_DATA_PTR(self, zk);
|
288
|
-
|
289
|
-
return
|
388
|
+
int rc = zookeeper_close(zk->zh);
|
389
|
+
return INT2FIX(rc);
|
290
390
|
}
|
291
391
|
|
292
392
|
static VALUE method_deterministic_conn_order(VALUE self, VALUE yn) {
|
@@ -294,83 +394,14 @@ static VALUE method_deterministic_conn_order(VALUE self, VALUE yn) {
|
|
294
394
|
return Qnil;
|
295
395
|
}
|
296
396
|
|
297
|
-
static VALUE
|
298
|
-
VALUE hash = rb_hash_new();
|
299
|
-
rb_hash_aset(hash, rb_str_new2("scheme"), rb_str_new2(id->scheme));
|
300
|
-
rb_hash_aset(hash, rb_str_new2("id"), rb_str_new2(id->id));
|
301
|
-
return hash;
|
302
|
-
}
|
303
|
-
|
304
|
-
static VALUE acl_to_ruby(struct ACL *acl) {
|
305
|
-
VALUE hash = rb_hash_new();
|
306
|
-
rb_hash_aset(hash, rb_str_new2("perms"), INT2NUM(acl->perms));
|
307
|
-
rb_hash_aset(hash, rb_str_new2("id"), id_to_ruby(&(acl->id)));
|
308
|
-
return hash;
|
309
|
-
}
|
310
|
-
|
311
|
-
static VALUE acl_vector_to_ruby(struct ACL_vector *acl_vector) {
|
312
|
-
int i = 0;
|
313
|
-
VALUE ary = rb_ary_new();
|
314
|
-
for(i = 0; i < acl_vector->count; i++) {
|
315
|
-
rb_ary_push(ary, acl_to_ruby(acl_vector->data+i));
|
316
|
-
}
|
317
|
-
return ary;
|
318
|
-
}
|
319
|
-
|
320
|
-
/*
|
321
|
-
struct Stat {
|
322
|
-
int64_t czxid;
|
323
|
-
int64_t mzxid;
|
324
|
-
int64_t ctime;
|
325
|
-
int64_t mtime;
|
326
|
-
int32_t version;
|
327
|
-
int32_t cversion;
|
328
|
-
int32_t aversion;
|
329
|
-
int64_t ephemeralOwner;
|
330
|
-
int32_t dataLength;
|
331
|
-
int32_t numChildren;
|
332
|
-
int64_t pzxid;
|
333
|
-
}
|
334
|
-
}
|
335
|
-
*/
|
336
|
-
static VALUE stat_to_ruby(struct Stat *stat) {
|
337
|
-
VALUE hash = rb_hash_new();
|
338
|
-
rb_hash_aset(hash, rb_str_new2("czxid"), UINT2NUM(stat->czxid));
|
339
|
-
rb_hash_aset(hash, rb_str_new2("mzxid"), UINT2NUM(stat->mzxid));
|
340
|
-
rb_hash_aset(hash, rb_str_new2("ctime"), UINT2NUM(stat->ctime));
|
341
|
-
rb_hash_aset(hash, rb_str_new2("mtime"), UINT2NUM(stat->mtime));
|
342
|
-
rb_hash_aset(hash, rb_str_new2("version"), INT2NUM(stat->version));
|
343
|
-
rb_hash_aset(hash, rb_str_new2("cversion"), INT2NUM(stat->cversion));
|
344
|
-
rb_hash_aset(hash, rb_str_new2("aversion"), INT2NUM(stat->aversion));
|
345
|
-
rb_hash_aset(hash, rb_str_new2("ephemeralOwner"), UINT2NUM(stat->ephemeralOwner));
|
346
|
-
rb_hash_aset(hash, rb_str_new2("dataLength"), INT2NUM(stat->dataLength));
|
347
|
-
rb_hash_aset(hash, rb_str_new2("numChildren"), INT2NUM(stat->numChildren));
|
348
|
-
rb_hash_aset(hash, rb_str_new2("pzxid"), UINT2NUM(stat->pzxid));
|
349
|
-
return hash;
|
350
|
-
}
|
351
|
-
|
352
|
-
static VALUE method_get_acl(VALUE self, VALUE path) {
|
397
|
+
static VALUE method_is_unrecoverable(VALUE self) {
|
353
398
|
FETCH_DATA_PTR(self, zk);
|
354
|
-
|
355
|
-
|
356
|
-
// ZOOAPI int zoo_get_acl(zhandle_t *zh, const char *path, struct ACL_vector *acl,
|
357
|
-
// struct Stat *stat);
|
358
|
-
struct ACL_vector acl;
|
359
|
-
struct Stat stat;
|
360
|
-
check_errors(zoo_get_acl(zk->zh, RSTRING(path)->ptr, &acl, &stat));
|
361
|
-
|
362
|
-
VALUE result = rb_ary_new();
|
363
|
-
rb_ary_push(result, acl_vector_to_ruby(&acl));
|
364
|
-
rb_ary_push(result, stat_to_ruby(&stat));
|
365
|
-
return result;
|
399
|
+
return is_unrecoverable(zk->zh) == ZINVALIDSTATE ? Qtrue : Qfalse;
|
366
400
|
}
|
367
401
|
|
368
|
-
static VALUE
|
402
|
+
static VALUE method_state(VALUE self) {
|
369
403
|
FETCH_DATA_PTR(self, zk);
|
370
|
-
|
371
|
-
return Qtrue;
|
372
|
-
|
373
|
-
return Qfalse;
|
404
|
+
return INT2NUM(zoo_state(zk->zh));
|
374
405
|
}
|
375
406
|
|
376
407
|
static VALUE method_recv_timeout(VALUE self) {
|
@@ -378,141 +409,55 @@ static VALUE method_recv_timeout(VALUE self) {
|
|
378
409
|
return INT2NUM(zoo_recv_timeout(zk->zh));
|
379
410
|
}
|
380
411
|
|
381
|
-
|
412
|
+
// how do you make a class method??
|
382
413
|
static VALUE method_set_debug_level(VALUE self, VALUE level) {
|
383
|
-
FETCH_DATA_PTR(self, zk);
|
384
414
|
Check_Type(level, T_FIXNUM);
|
415
|
+
ZKRBDebugging = (FIX2INT(level) == ZOO_LOG_LEVEL_DEBUG);
|
385
416
|
zoo_set_debug_level(FIX2INT(level));
|
386
417
|
return Qnil;
|
387
418
|
}
|
388
419
|
|
389
|
-
#warning [emaland] make this a class method or global
|
390
420
|
static VALUE method_zerror(VALUE self, VALUE errc) {
|
391
421
|
return rb_str_new2(zerror(FIX2INT(errc)));
|
392
422
|
}
|
393
423
|
|
394
|
-
static
|
395
|
-
FETCH_DATA_PTR(self, zk);
|
396
|
-
return INT2NUM(zoo_state(zk->zh));
|
397
|
-
}
|
398
|
-
|
399
|
-
#warning [emaland] make this a class method or global
|
400
|
-
static VALUE method_set_log_stream(VALUE self, VALUE stream) {
|
401
|
-
// convert stream to FILE*
|
402
|
-
FILE *fp_stream = (FILE*)stream;
|
403
|
-
zoo_set_log_stream(fp_stream);
|
404
|
-
return Qnil;
|
405
|
-
}
|
406
|
-
|
407
|
-
static VALUE method_set_watcher(VALUE self, VALUE new_watcher) {
|
408
|
-
FETCH_DATA_PTR(self, zk);
|
409
|
-
#warning [emaland] needs to be tested/implemented
|
410
|
-
return Qnil;
|
411
|
-
// watcher_fn old_watcher = zoo_set_watcher(zk->zh, new_watcher);
|
412
|
-
// return old_watcher;
|
413
|
-
}
|
414
|
-
|
415
|
-
void Init_zookeeper_c() {
|
416
|
-
Zookeeper = rb_define_class("CZookeeper", rb_cObject);
|
417
|
-
|
424
|
+
static void zkrb_define_methods(void) {
|
418
425
|
#define DEFINE_METHOD(method, args) { \
|
419
426
|
rb_define_method(Zookeeper, #method, method_ ## method, args); }
|
427
|
+
#define DEFINE_CLASS_METHOD(method, args) { \
|
428
|
+
rb_define_singleton_method(Zookeeper, #method, method_ ## method, args); }
|
420
429
|
|
421
430
|
DEFINE_METHOD(initialize, 1);
|
422
|
-
DEFINE_METHOD(get_children,
|
423
|
-
DEFINE_METHOD(exists,
|
424
|
-
DEFINE_METHOD(create,
|
425
|
-
DEFINE_METHOD(delete,
|
426
|
-
DEFINE_METHOD(get,
|
427
|
-
DEFINE_METHOD(set,
|
428
|
-
|
429
|
-
|
430
|
-
DEFINE_METHOD(add_auth, 3);
|
431
|
-
DEFINE_METHOD(set_acl, -1);
|
432
|
-
DEFINE_METHOD(async, 1);
|
431
|
+
DEFINE_METHOD(get_children, 4);
|
432
|
+
DEFINE_METHOD(exists, 4);
|
433
|
+
DEFINE_METHOD(create, 6);
|
434
|
+
DEFINE_METHOD(delete, 4);
|
435
|
+
DEFINE_METHOD(get, 4);
|
436
|
+
DEFINE_METHOD(set, 5);
|
437
|
+
DEFINE_METHOD(set_acl, 5);
|
438
|
+
DEFINE_METHOD(get_acl, 3);
|
433
439
|
DEFINE_METHOD(client_id, 0);
|
434
440
|
DEFINE_METHOD(close, 0);
|
435
441
|
DEFINE_METHOD(deterministic_conn_order, 1);
|
436
|
-
DEFINE_METHOD(get_acl, 2);
|
437
442
|
DEFINE_METHOD(is_unrecoverable, 0);
|
438
443
|
DEFINE_METHOD(recv_timeout, 1);
|
439
|
-
DEFINE_METHOD(set2, -1);
|
440
|
-
DEFINE_METHOD(set_debug_level, 1);
|
441
|
-
DEFINE_METHOD(set_log_stream, 1);
|
442
|
-
DEFINE_METHOD(set_watcher, 2);
|
443
444
|
DEFINE_METHOD(state, 0);
|
445
|
+
// TODO
|
446
|
+
// DEFINE_METHOD(add_auth, 3);
|
447
|
+
// DEFINE_METHOD(async, 1);
|
448
|
+
|
449
|
+
// methods for the ruby-side event manager
|
450
|
+
DEFINE_METHOD(get_next_event, 0);
|
451
|
+
DEFINE_METHOD(has_events, 0);
|
452
|
+
|
453
|
+
// Make these class methods?
|
454
|
+
DEFINE_METHOD(set_debug_level, 1);
|
444
455
|
DEFINE_METHOD(zerror, 1);
|
456
|
+
}
|
457
|
+
void Init_zookeeper_c() {
|
458
|
+
ZKRBDebugging = 0;
|
445
459
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
#define EXPORT_CONST(x) { rb_define_const(Zookeeper, #x, INT2FIX(x)); }
|
450
|
-
|
451
|
-
/* create flags */
|
452
|
-
EXPORT_CONST(ZOO_EPHEMERAL);
|
453
|
-
EXPORT_CONST(ZOO_SEQUENCE);
|
454
|
-
|
455
|
-
/*
|
456
|
-
session state
|
457
|
-
*/
|
458
|
-
EXPORT_CONST(ZOO_EXPIRED_SESSION_STATE);
|
459
|
-
EXPORT_CONST(ZOO_AUTH_FAILED_STATE);
|
460
|
-
EXPORT_CONST(ZOO_CONNECTING_STATE);
|
461
|
-
EXPORT_CONST(ZOO_ASSOCIATING_STATE);
|
462
|
-
EXPORT_CONST(ZOO_CONNECTED_STATE);
|
463
|
-
|
464
|
-
/* notifications */
|
465
|
-
EXPORT_CONST(ZOOKEEPER_WRITE);
|
466
|
-
EXPORT_CONST(ZOOKEEPER_READ);
|
467
|
-
|
468
|
-
/* errors */
|
469
|
-
EXPORT_CONST(ZOK);
|
470
|
-
EXPORT_CONST(ZSYSTEMERROR);
|
471
|
-
EXPORT_CONST(ZRUNTIMEINCONSISTENCY);
|
472
|
-
EXPORT_CONST(ZDATAINCONSISTENCY);
|
473
|
-
EXPORT_CONST(ZCONNECTIONLOSS);
|
474
|
-
EXPORT_CONST(ZMARSHALLINGERROR);
|
475
|
-
EXPORT_CONST(ZUNIMPLEMENTED);
|
476
|
-
EXPORT_CONST(ZOPERATIONTIMEOUT);
|
477
|
-
EXPORT_CONST(ZBADARGUMENTS);
|
478
|
-
EXPORT_CONST(ZINVALIDSTATE);
|
479
|
-
|
480
|
-
/** API errors. */
|
481
|
-
EXPORT_CONST(ZAPIERROR);
|
482
|
-
EXPORT_CONST(ZNONODE);
|
483
|
-
EXPORT_CONST(ZNOAUTH);
|
484
|
-
EXPORT_CONST(ZBADVERSION);
|
485
|
-
EXPORT_CONST(ZNOCHILDRENFOREPHEMERALS);
|
486
|
-
EXPORT_CONST(ZNODEEXISTS);
|
487
|
-
EXPORT_CONST(ZNOTEMPTY);
|
488
|
-
EXPORT_CONST(ZSESSIONEXPIRED);
|
489
|
-
EXPORT_CONST(ZINVALIDCALLBACK);
|
490
|
-
EXPORT_CONST(ZINVALIDACL);
|
491
|
-
EXPORT_CONST(ZAUTHFAILED);
|
492
|
-
EXPORT_CONST(ZCLOSING);
|
493
|
-
EXPORT_CONST(ZNOTHING);
|
494
|
-
EXPORT_CONST(ZSESSIONMOVED);
|
495
|
-
|
496
|
-
/* debug levels */
|
497
|
-
EXPORT_CONST(ZOO_LOG_LEVEL_ERROR);
|
498
|
-
EXPORT_CONST(ZOO_LOG_LEVEL_WARN);
|
499
|
-
EXPORT_CONST(ZOO_LOG_LEVEL_INFO);
|
500
|
-
EXPORT_CONST(ZOO_LOG_LEVEL_DEBUG);
|
501
|
-
|
502
|
-
/* ACL constants */
|
503
|
-
EXPORT_CONST(ZOO_PERM_READ);
|
504
|
-
EXPORT_CONST(ZOO_PERM_WRITE);
|
505
|
-
EXPORT_CONST(ZOO_PERM_CREATE);
|
506
|
-
EXPORT_CONST(ZOO_PERM_DELETE);
|
507
|
-
EXPORT_CONST(ZOO_PERM_ADMIN);
|
508
|
-
EXPORT_CONST(ZOO_PERM_ALL);
|
509
|
-
|
510
|
-
/* Watch types */
|
511
|
-
EXPORT_CONST(ZOO_CREATED_EVENT);
|
512
|
-
EXPORT_CONST(ZOO_DELETED_EVENT);
|
513
|
-
EXPORT_CONST(ZOO_CHANGED_EVENT);
|
514
|
-
EXPORT_CONST(ZOO_CHILD_EVENT);
|
515
|
-
EXPORT_CONST(ZOO_SESSION_EVENT);
|
516
|
-
EXPORT_CONST(ZOO_NOTWATCHING_EVENT);
|
517
|
-
|
460
|
+
/* initialize Zookeeper class */
|
461
|
+
Zookeeper = rb_define_class("CZookeeper", rb_cObject);
|
462
|
+
zkrb_define_methods();
|
518
463
|
}
|