zookeeper 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|