zookeeper 0.1

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig ADDED
@@ -0,0 +1 @@
1
+ ��0i�4E�X��� ������I�>���Ya�0����� >��s���xSʷ����(9��?�#�2i2�#j����P��?E9Q!��T��Q)}v�HL��k�i�al)��(�U鱗kZ�r�?��->��������V��?s���s�CQ�^aL�N����R�đn��7�V�a��0/�_T c���1s��ͦJ��Р;�LC�ͅA-��{��I��",��@���Gs&h���6���D]إi�g�����6���
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+
2
+ v0.1. First release.
data/Manifest ADDED
@@ -0,0 +1,8 @@
1
+ CHANGELOG
2
+ README
3
+ Rakefile
4
+ ext/zookeeper_c/extconf.rb
5
+ ext/zookeeper_c/zookeeper_ruby.c
6
+ lib/zookeeper_client.rb
7
+ test/test_basic.rb
8
+ Manifest
data/README ADDED
@@ -0,0 +1,98 @@
1
+ zookeeper_client
2
+ by Phillip Pearson
3
+ http://github.com/myelin/zookeeper_client
4
+
5
+ == DESCRIPTION:
6
+
7
+ zookeeper_client is a Ruby library to interface with the ZooKeeper
8
+ replicated object store / lock server.
9
+
10
+ Project maturity: early alpha. Working, although very chatty and
11
+ there may be bugs to do with threading. Expect to get your hands
12
+ dirty.
13
+
14
+ == REQUIREMENTS:
15
+
16
+ * ZooKeeper C client library (http://zookeeper.sourceforge.net/)
17
+
18
+ See installation instructions in c/README, in the ZooKeeper source
19
+ distribution. zookeeper_client expects the headers to live in
20
+ /usr/include/c-client-src/, which doesn't feel right but is where
21
+ they go on my system when I run 'make install'.
22
+
23
+ == INSTALL:
24
+
25
+ $ gem sources -a http://gems.github.com/
26
+ $ gem install myelin-zookeeper_client
27
+
28
+ == USAGE:
29
+
30
+ = Connect to a server
31
+
32
+ require 'rubygems'
33
+ require 'myelin-zookeeper_client'
34
+ z = ZooKeeper.new("localhost:2181")
35
+
36
+ = Create, set and read nodes
37
+
38
+ z.create("/bacon", "text to be stored in the new node", 0)
39
+ # => "/bacon"
40
+
41
+ data, stat = z.get("/bacon")
42
+ # => ["text to be stored in the new node", #<ZkStat:0xb771be54 @ephemeralOwner=0, @ctime=1216196667669, @aversion=0, @mzxid=1008, @cversion=0, @version=0, @czxid=1008, @mtime=1216196667669>]
43
+
44
+ z.set("/bacon", "an entirely different line of text", stat.version)
45
+ # => nil
46
+
47
+ z.set("/bacon", "this won't work", stat.version)
48
+ # CZooKeeper::BadVersionError: expected version does not match actual version
49
+
50
+ data, stat = z.get("/bacon")
51
+ # => ["an entirely different line of text", #<ZkStat:0xb77125d4 @ephemeralOwner=0, @ctime=1216196667669, @aversion=0, @mzxid=1009, @cversion=0, @version=1, @czxid=1008, @mtime=1216196704709>]
52
+
53
+ z.delete("/bacon", stat.version)
54
+ # => nil
55
+
56
+ = Create ephemeral and sequence nodes
57
+
58
+ z.create("/parent", "parent node", 0)
59
+ # => "/parent"
60
+
61
+ z.create("/parent/test-", "an ordered node that will disappear when the connection goes down", ZooKeeper::EPHEMERAL | ZooKeeper::SEQUENCE)
62
+ # => "/parent/test-0"
63
+
64
+ z.create("/parent/test-", "an ordered node that will disappear when the connection goes down", ZooKeeper::EPHEMERAL | ZooKeeper::SEQUENCE)
65
+ # => "/parent/test-1"
66
+
67
+ = Acquire locks
68
+
69
+ z.try_acquire "/parent/lock-", "content for the lock file" do |have_lock|
70
+ puts have_lock ? "we have the lock" : "we don't have the lock"
71
+ end
72
+ # we have the lock
73
+ # => nil
74
+
75
+ == LICENSE:
76
+
77
+ (The MIT License)
78
+
79
+ Copyright (C) 2008 Phillip Pearson
80
+
81
+ Permission is hereby granted, free of charge, to any person obtaining
82
+ a copy of this software and associated documentation files (the
83
+ 'Software'), to deal in the Software without restriction, including
84
+ without limitation the rights to use, copy, modify, merge, publish,
85
+ distribute, sublicense, and/or sell copies of the Software, and to
86
+ permit persons to whom the Software is furnished to do so, subject to
87
+ the following conditions:
88
+
89
+ The above copyright notice and this permission notice shall be
90
+ included in all copies or substantial portions of the Software.
91
+
92
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
93
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
94
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
95
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
96
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
97
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
98
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'echoe'
2
+
3
+ Echoe.new("zookeeper") do |p|
4
+ p.author = "Phillip Pearson, Eric Maland, Evan Weaver"
5
+ p.project = "fauna"
6
+ p.summary = "A Ruby wrapper for the ZooKeeper C client library."
7
+ p.url = "http://blog.evanweaver.com/files/doc/fauna/zookeeper/"
8
+ p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
9
+ end
@@ -0,0 +1,14 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("zookeeper")
4
+
5
+ have_header "sys/errno.h"
6
+ have_header "stdio.h"
7
+ find_header("zookeeper/zookeeper.h") or
8
+ raise "zookeeper.h not found."
9
+ find_library("zookeeper_mt", "zoo_set_debug_level") or
10
+ raise "libzookeeper_mt not found."
11
+
12
+ dir_config('zookeeper_c')
13
+ create_makefile( 'zookeeper_c')
14
+
@@ -0,0 +1,518 @@
1
+ /* Ruby wrapper for the ZooKeeper C API
2
+ * Phillip Pearson <pp@myelin.co.nz>
3
+ * Eric Maland <eric@twitter.com>
4
+ */
5
+
6
+ #define THREADED
7
+
8
+ #include "ruby.h"
9
+
10
+ #include "zookeeper/zookeeper.h"
11
+ #include <errno.h>
12
+ #include <stdio.h>
13
+
14
+ static VALUE ZooKeeper = Qnil;
15
+ static VALUE eNoNode = Qnil;
16
+ static VALUE eBadVersion = Qnil;
17
+
18
+ struct zk_rb_data {
19
+ zhandle_t *zh;
20
+ clientid_t myid;
21
+ };
22
+
23
+ static void watcher(zhandle_t *zh, int type, int state, const char *path, void *ctx) {
24
+ VALUE self, watcher_id;
25
+ (void)ctx;
26
+ return; // watchers don't work in ruby yet
27
+
28
+ self = (VALUE)zoo_get_context(zh);;
29
+ watcher_id = rb_intern("watcher");
30
+
31
+ fprintf(stderr,"C watcher %d state = %d for %s.\n", type, state, (path ? path: "null"));
32
+ rb_funcall(self, watcher_id, 3, INT2FIX(type), INT2FIX(state), rb_str_new2(path));
33
+ }
34
+
35
+ #warning [emaland] incomplete - but easier to read!
36
+ static void check_errors(int rc) {
37
+ switch (rc) {
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));
49
+ }
50
+ }
51
+
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
+ static VALUE method_initialize(VALUE self, VALUE hostPort) {
69
+ VALUE data;
70
+ struct zk_rb_data* zk = NULL;
71
+
72
+ Check_Type(hostPort, T_STRING);
73
+
74
+ data = Data_Make_Struct(ZooKeeper, struct zk_rb_data, 0, free_zk_rb_data, zk);
75
+
76
+ zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
77
+ zoo_deterministic_conn_order(0);
78
+
79
+ zk->zh = zookeeper_init(RSTRING(hostPort)->ptr, watcher, 10000, &zk->myid, (void*)self, 0);
80
+ if (!zk->zh) {
81
+ rb_raise(rb_eRuntimeError, "error connecting to zookeeper: %d", errno);
82
+ }
83
+
84
+ rb_iv_set(self, "@data", data);
85
+
86
+ return Qnil;
87
+ }
88
+
89
+ #define FETCH_DATA_PTR(x, y) \
90
+ struct zk_rb_data * y; \
91
+ Data_Get_Struct(rb_iv_get(x, "@data"), struct zk_rb_data, y)
92
+
93
+ static VALUE method_get_children(VALUE self, VALUE path) {
94
+ struct String_vector strings;
95
+ int i;
96
+ VALUE output;
97
+
98
+ Check_Type(path, T_STRING);
99
+ FETCH_DATA_PTR(self, zk);
100
+
101
+ check_errors(zoo_get_children(zk->zh, RSTRING(path)->ptr, 0, &strings));
102
+
103
+ output = rb_ary_new();
104
+ for (i = 0; i < strings.count; ++i) {
105
+ rb_ary_push(output, rb_str_new2(strings.data[i]));
106
+ }
107
+ return output;
108
+ }
109
+
110
+ static VALUE method_exists(VALUE self, VALUE path, VALUE watch) {
111
+ struct Stat stat;
112
+
113
+ Check_Type(path, T_STRING);
114
+ FETCH_DATA_PTR(self, zk);
115
+
116
+ check_errors(zoo_exists(zk->zh, RSTRING(path)->ptr, (watch != Qfalse && watch != Qnil), &stat));
117
+
118
+ return array_from_stat(&stat);
119
+ }
120
+
121
+ static VALUE method_create(VALUE self, VALUE path, VALUE value, VALUE flags) {
122
+ char realpath[10240];
123
+
124
+ Check_Type(path, T_STRING);
125
+ Check_Type(value, T_STRING);
126
+ Check_Type(flags, T_FIXNUM);
127
+
128
+ FETCH_DATA_PTR(self, zk);
129
+
130
+ check_errors(zoo_create(zk->zh, RSTRING(path)->ptr,
131
+ RSTRING(value)->ptr, RSTRING(value)->len,
132
+ &ZOO_OPEN_ACL_UNSAFE, FIX2INT(flags),
133
+ realpath, sizeof(realpath)));
134
+
135
+ return rb_str_new2(realpath);
136
+ }
137
+
138
+ static VALUE method_delete(VALUE self, VALUE path, VALUE version) {
139
+ Check_Type(path, T_STRING);
140
+ 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
+
159
+ check_errors(zoo_get(zk->zh, RSTRING(path)->ptr, 0, data, &data_len, &stat));
160
+
161
+ return rb_ary_new3(2,
162
+ rb_str_new(data, data_len),
163
+ array_from_stat(&stat));
164
+ }
165
+
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
+
179
+ if(!NIL_P(v_version))
180
+ real_version = FIX2INT(v_version);
181
+
182
+ check_errors(zoo_set(zk->zh,
183
+ RSTRING(v_path)->ptr,
184
+ RSTRING(v_data)->ptr, RSTRING(v_data)->len,
185
+ FIX2INT(v_version)));
186
+
187
+ return Qtrue;
188
+ }
189
+
190
+ static void void_completion_callback(int rc, const void *data) {
191
+
192
+ }
193
+
194
+ static void string_completion_callback(int rc, const char *value, const void *data) {
195
+
196
+ }
197
+
198
+ #warning [emaland] to be implemented
199
+ static VALUE method_set2(int argc, VALUE *argv, VALUE self) {
200
+ // ZOOAPI int zoo_set2(zhandle_t *zh, const char *path, const char *buffer,
201
+ // int buflen, int version, struct Stat *stat);
202
+ return Qnil;
203
+
204
+ }
205
+
206
+ static VALUE method_set_acl(int argc, VALUE* argv, VALUE self) {
207
+ /* STUB */
208
+ /* VALUE v_path, v_data, v_version; */
209
+ /* struct zk_rb_data* zk; */
210
+ /* int real_version = -1; */
211
+
212
+ /* rb_scan_args(argc, argv, "21", &v_path, &v_data, &v_version); */
213
+
214
+ /* Check_Type(v_path, T_STRING); */
215
+ /* Check_Type(v_data, T_STRING); */
216
+ /* Check_Type(v_version, T_FIXNUM); */
217
+
218
+ /* if(!NIL_P(v_version)) */
219
+ /* real_version = FIX2INT(v_version); */
220
+
221
+ /* Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk); */
222
+
223
+ /* check_errors(zoo_set(zk->zh, RSTRING(v_path)->ptr, */
224
+ /* RSTRING(v_data)->ptr, RSTRING(v_data)->len, */
225
+ /* FIX2INT(v_version))); */
226
+
227
+ return Qnil;
228
+ }
229
+
230
+ /*
231
+ PARAMETERS:
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); // ???
259
+
260
+ check_errors(zoo_add_auth(zk->zh, RSTRING(scheme)->ptr,
261
+ RSTRING(cert)->ptr, RSTRING(cert)->len,
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);
270
+
271
+ Check_Type(path, T_STRING);
272
+ // Check_Type(completion, T_OBJECT); // ???
273
+
274
+ check_errors(zoo_async(zk->zh, RSTRING(path)->ptr,
275
+ string_completion_callback, DATA_PTR(completion_data)));
276
+
277
+ return Qtrue;
278
+ }
279
+
280
+ static VALUE method_client_id(VALUE self) {
281
+ FETCH_DATA_PTR(self, zk);
282
+ const clientid_t *id = zoo_client_id(zk->zh);
283
+ return UINT2NUM(id->client_id);
284
+ }
285
+
286
+ static VALUE method_close(VALUE self) {
287
+ FETCH_DATA_PTR(self, zk);
288
+ check_errors(zookeeper_close(zk->zh));
289
+ return Qtrue;
290
+ }
291
+
292
+ static VALUE method_deterministic_conn_order(VALUE self, VALUE yn) {
293
+ zoo_deterministic_conn_order(yn == Qtrue);
294
+ return Qnil;
295
+ }
296
+
297
+ static VALUE id_to_ruby(struct Id *id) {
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) {
353
+ FETCH_DATA_PTR(self, zk);
354
+ Check_Type(path, T_STRING);
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;
366
+ }
367
+
368
+ static VALUE method_is_unrecoverable(VALUE self) {
369
+ FETCH_DATA_PTR(self, zk);
370
+ if(is_unrecoverable(zk->zh) == ZINVALIDSTATE)
371
+ return Qtrue;
372
+
373
+ return Qfalse;
374
+ }
375
+
376
+ static VALUE method_recv_timeout(VALUE self) {
377
+ FETCH_DATA_PTR(self, zk);
378
+ return INT2NUM(zoo_recv_timeout(zk->zh));
379
+ }
380
+
381
+ #warning [emaland] make this a class method or global
382
+ static VALUE method_set_debug_level(VALUE self, VALUE level) {
383
+ FETCH_DATA_PTR(self, zk);
384
+ Check_Type(level, T_FIXNUM);
385
+ zoo_set_debug_level(FIX2INT(level));
386
+ return Qnil;
387
+ }
388
+
389
+ #warning [emaland] make this a class method or global
390
+ static VALUE method_zerror(VALUE self, VALUE errc) {
391
+ return rb_str_new2(zerror(FIX2INT(errc)));
392
+ }
393
+
394
+ static VALUE method_state(VALUE self) {
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
+
418
+ #define DEFINE_METHOD(method, args) { \
419
+ rb_define_method(ZooKeeper, #method, method_ ## method, args); }
420
+
421
+ DEFINE_METHOD(initialize, 1);
422
+ DEFINE_METHOD(get_children, 1);
423
+ DEFINE_METHOD(exists, 2);
424
+ DEFINE_METHOD(create, 3);
425
+ DEFINE_METHOD(delete, 2);
426
+ DEFINE_METHOD(get, 1);
427
+ DEFINE_METHOD(set, -1);
428
+
429
+ /* TODO */
430
+ DEFINE_METHOD(add_auth, 3);
431
+ DEFINE_METHOD(set_acl, -1);
432
+ DEFINE_METHOD(async, 1);
433
+ DEFINE_METHOD(client_id, 0);
434
+ DEFINE_METHOD(close, 0);
435
+ DEFINE_METHOD(deterministic_conn_order, 1);
436
+ DEFINE_METHOD(get_acl, 2);
437
+ DEFINE_METHOD(is_unrecoverable, 0);
438
+ 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
+ DEFINE_METHOD(state, 0);
444
+ DEFINE_METHOD(zerror, 1);
445
+
446
+ eNoNode = rb_define_class_under(ZooKeeper, "NoNodeError", rb_eRuntimeError);
447
+ eBadVersion = rb_define_class_under(ZooKeeper, "BadVersionError", rb_eRuntimeError);
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
+
518
+ }
@@ -0,0 +1,78 @@
1
+ # Ruby wrapper for the ZooKeeper C API
2
+ # Phillip Pearson <pp@myelin.co.nz>
3
+
4
+ require 'zookeeper_c'
5
+
6
+ class ZkStat
7
+ attr_reader :version
8
+ def initialize(ary)
9
+ @czxid, @mzxid, @ctime, @mtime, @version, @cversion, @aversion, @ephemeralOwner = ary
10
+ end
11
+ end
12
+
13
+ class ZooKeeper < CZooKeeper
14
+ def initialize(host)
15
+ super(host)
16
+ @watchers = {} # path => [ block, block, ... ]
17
+ end
18
+
19
+ def exists(path, &blk)
20
+ (@watchers[path] ||= []) << blk if blk
21
+ ZkStat.new(super(path, !!blk))
22
+ end
23
+
24
+ def stat(path, &blk)
25
+ exists(path, &blk)
26
+ rescue ZooKeeper::NoNodeError
27
+ nil
28
+ end
29
+
30
+ def get(path)
31
+ value, stat = super
32
+ [value, ZkStat.new(stat)]
33
+ end
34
+
35
+ def try_acquire(path, value)
36
+ # create the parent node if it doesn't exist already
37
+ create(path, "lock node", 0) unless stat(path)
38
+
39
+ # attempt to obtain the lock
40
+ realpath = create("#{path}/lock-", value, ZooKeeper::ZOO_EPHEMERAL | ZooKeeper::ZOO_SEQUENCE)
41
+ #puts "created lock node #{realpath}"
42
+
43
+ # see if we got it
44
+ serial = /lock-(\d+)$/.match(realpath).captures[0].to_i
45
+ have_lock = true
46
+ ls(path).each do |child|
47
+ if m = /lock-(\d+)$/.match(child)
48
+ if m.captures[0].to_i < serial
49
+ have_lock = false
50
+ break
51
+ end
52
+ end
53
+ end
54
+
55
+ # call block
56
+ yield(have_lock)
57
+
58
+ # release the lock
59
+ #puts "deleting #{realpath}"
60
+ delete(realpath, stat(realpath).version)
61
+ end
62
+
63
+ def watcher(type, state, path)
64
+ raise Exception("watchers don't work in ruby yet") # ... until I figure out how to synchronize access to the Ruby interpreter
65
+
66
+ return unless type == ZOO_SESSION_EVENT
67
+
68
+ case state
69
+ when ZOO_CONNECTED_STATE
70
+ puts "ruby watcher; got an event for #{path}"
71
+
72
+ when ZOO_AUTH_FAILED_STATE
73
+ raise Exception, "auth failure"
74
+ when ZOO_EXPIRED_SESSION_STATE
75
+ raise Exception, "session expired"
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,63 @@
1
+ $LOAD_PATH << '/home/eric/zk-clients/lib'
2
+ require 'rubygems'
3
+ require 'zookeeper_client'
4
+
5
+ z = ZooKeeper.new("localhost:2181")
6
+
7
+ puts "root: #{z.get_children("/").inspect}"
8
+
9
+ path = "/testing_node"
10
+
11
+ puts "working with path #{path}"
12
+
13
+ stat = z.stat(path)
14
+ puts "exists? #{stat.inspect}"
15
+
16
+ unless stat.nil?
17
+ z.get_children(path).each do |o|
18
+ puts " child object: #{o}"
19
+ end
20
+ puts "delete: #{z.delete(path, stat.version).inspect}"
21
+ end
22
+
23
+ puts "create: #{z.create(path, "initial value", 0).inspect}"
24
+
25
+ value, stat = z.get(path)
26
+ puts "current value #{value}, stat #{stat.inspect}"
27
+
28
+ puts "set: #{z.set(path, "this is a test", stat.version).inspect}"
29
+
30
+ value, stat = z.get(path)
31
+ puts "new value: #{value.inspect} #{stat.inspect}"
32
+
33
+ puts "delete: #{z.delete(path, stat.version).inspect}"
34
+
35
+ begin
36
+ puts "exists? #{z.exists(path)}"
37
+ raise Exception, "it shouldn't exist"
38
+ rescue ZooKeeper::NoNodeError
39
+ puts "doesn't exist - good, because we just deleted it!"
40
+ end
41
+
42
+ puts "trying a watcher"
43
+ puts z
44
+ if s = z.stat("/test"); z.delete("/test", s.version); end
45
+ z.create("/test", "foo", 0)
46
+ z.exists("/test") do
47
+ puts "callback!!!"
48
+ end
49
+ puts "now changing it"
50
+ z.set("/test", "bar", 0)
51
+ sleep 1
52
+ puts "did the watcher say something?"
53
+
54
+ puts "let's try using a lock"
55
+ z.try_acquire("/test_lock", "this is the content of the lock file") do |have_lock|
56
+ puts have_lock ? "we have the lock!" : "failed to obtain lock :("
57
+ if have_lock
58
+ puts "sleeping"
59
+ sleep 5
60
+ end
61
+ end
62
+ puts "done with locking..."
63
+
data/zookeeper.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{zookeeper}
5
+ s.version = "0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Phillip Pearson, Eric Maland, Evan Weaver"]
9
+ s.cert_chain = ["/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-public_cert.pem"]
10
+ s.date = %q{2010-02-09}
11
+ s.description = %q{A Ruby wrapper for the ZooKeeper C client library.}
12
+ s.email = %q{}
13
+ s.extensions = ["ext/zookeeper_c/extconf.rb"]
14
+ s.extra_rdoc_files = ["CHANGELOG", "README", "ext/zookeeper_c/extconf.rb", "ext/zookeeper_c/zookeeper_ruby.c", "lib/zookeeper_client.rb"]
15
+ s.files = ["CHANGELOG", "README", "Rakefile", "ext/zookeeper_c/extconf.rb", "ext/zookeeper_c/zookeeper_ruby.c", "lib/zookeeper_client.rb", "test/test_basic.rb", "Manifest", "zookeeper.gemspec"]
16
+ s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/zookeeper/}
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Zookeeper", "--main", "README"]
18
+ s.require_paths = ["lib", "ext"]
19
+ s.rubyforge_project = %q{fauna}
20
+ s.rubygems_version = %q{1.3.5}
21
+ s.signing_key = %q{/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-private_key.pem}
22
+ s.summary = %q{A Ruby wrapper for the ZooKeeper C client library.}
23
+ s.test_files = ["test/test_basic.rb"]
24
+
25
+ if s.respond_to? :specification_version then
26
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
27
+ s.specification_version = 3
28
+
29
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
30
+ else
31
+ end
32
+ else
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zookeeper
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Phillip Pearson, Eric Maland, Evan Weaver
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQUFADA9MQ0wCwYDVQQDDARldmFu
14
+ MRgwFgYKCZImiZPyLGQBGRYIY2xvdWRidXIxEjAQBgoJkiaJk/IsZAEZFgJzdDAe
15
+ Fw0wNzA5MTYxMDMzMDBaFw0wODA5MTUxMDMzMDBaMD0xDTALBgNVBAMMBGV2YW4x
16
+ GDAWBgoJkiaJk/IsZAEZFghjbG91ZGJ1cjESMBAGCgmSJomT8ixkARkWAnN0MIIB
17
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5C0Io89nyApnr+PvbNFge9Vs
18
+ yRWAlGBUEMahpXp28VrrfXZT0rAW7JBo4PlCE3jl4nE4dzE6gAdItSycjTosrw7A
19
+ Ir5+xoyl4Vb35adv56TIQQXvNz+BzlqnkAY5JN0CSBRTQb6mxS3hFyD/h4qgDosj
20
+ R2RFVzHqSxCS8xq4Ny8uzOwOi+Xyu4w67fI5JvnPvMxqrlR1eaIQHmxnf76RzC46
21
+ QO5QhufjAYGGXd960XzbQsQyTDUYJzrvT7AdOfiyZzKQykKt8dEpDn+QPjFTnGnT
22
+ QmgJBX5WJN0lHF2l1sbv3gh4Kn1tZu+kTUqeXY6ShAoDTyvZRiFqQdwh8w2lTQID
23
+ AQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU+WqJz3xQ
24
+ XSea1hRvvHWcIMgeeC4wDQYJKoZIhvcNAQEFBQADggEBAGLZ75jfOEW8Nsl26CTt
25
+ JFrWxQTcQT/UljeefVE3xYr7lc9oQjbqO3FOyued3qW7TaNEtZfSHoYeUSMYbpw1
26
+ XAwocIPuSRFDGM4B+hgQGVDx8PMGiJKom4qLXjO40UZsR7QyN/u869Vj45LURm6h
27
+ MBcPeqCASI+WNprj9+uZa2kmHiitrFqqfMBNlm5IFbn9XeYSta9AHVvs5QQqV2m5
28
+ hIPfLqCyxsn/YgOGvo6iwyQTWyTswamaAC3HRWZxIS1sfn/Ssqa7E7oQMkv5FAXr
29
+ x5rKePfXINf8XTJczkl9OBEYdE9aNdJsJpXD0asLgGVwBICS5Bjohp6mizJcDC1+
30
+ yZ0=
31
+ -----END CERTIFICATE-----
32
+
33
+ date: 2010-02-09 00:00:00 -08:00
34
+ default_executable:
35
+ dependencies: []
36
+
37
+ description: A Ruby wrapper for the ZooKeeper C client library.
38
+ email: ""
39
+ executables: []
40
+
41
+ extensions:
42
+ - ext/zookeeper_c/extconf.rb
43
+ extra_rdoc_files:
44
+ - CHANGELOG
45
+ - README
46
+ - ext/zookeeper_c/extconf.rb
47
+ - ext/zookeeper_c/zookeeper_ruby.c
48
+ - lib/zookeeper_client.rb
49
+ files:
50
+ - CHANGELOG
51
+ - README
52
+ - Rakefile
53
+ - ext/zookeeper_c/extconf.rb
54
+ - ext/zookeeper_c/zookeeper_ruby.c
55
+ - lib/zookeeper_client.rb
56
+ - test/test_basic.rb
57
+ - Manifest
58
+ - zookeeper.gemspec
59
+ has_rdoc: true
60
+ homepage: http://blog.evanweaver.com/files/doc/fauna/zookeeper/
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options:
65
+ - --line-numbers
66
+ - --inline-source
67
+ - --title
68
+ - Zookeeper
69
+ - --main
70
+ - README
71
+ require_paths:
72
+ - lib
73
+ - ext
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "1.2"
85
+ version:
86
+ requirements: []
87
+
88
+ rubyforge_project: fauna
89
+ rubygems_version: 1.3.5
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: A Ruby wrapper for the ZooKeeper C client library.
93
+ test_files:
94
+ - test/test_basic.rb
metadata.gz.sig ADDED
Binary file