neerfri-zookeeper_client 0.0.5
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/ext/zookeeper_c/extconf.rb +9 -0
 - data/ext/zookeeper_c/zookeeper_ruby.c +203 -0
 - data/lib/zookeeper_client.rb +78 -0
 - data/test/test_basic.rb +62 -0
 - metadata +56 -0
 
| 
         @@ -0,0 +1,203 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /* Ruby wrapper for the ZooKeeper C API
         
     | 
| 
      
 2 
     | 
    
         
            +
             * Phillip Pearson <pp@myelin.co.nz>
         
     | 
| 
      
 3 
     | 
    
         
            +
             */
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            #define THREADED
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            #include "ruby.h"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            #include "c-client-src/zookeeper.h"
         
     | 
| 
      
 10 
     | 
    
         
            +
            #include <errno.h>
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 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* context) {
         
     | 
| 
      
 24 
     | 
    
         
            +
              VALUE self, watcher_id;
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 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 
     | 
    
         
            +
            static void check_errors(int rc) {
         
     | 
| 
      
 36 
     | 
    
         
            +
              switch (rc) {
         
     | 
| 
      
 37 
     | 
    
         
            +
              case ZOK: /* all good! */ break;
         
     | 
| 
      
 38 
     | 
    
         
            +
              case ZBADARGUMENTS: rb_raise(rb_eRuntimeError, "invalid input parameters");
         
     | 
| 
      
 39 
     | 
    
         
            +
              case ZMARSHALLINGERROR: rb_raise(rb_eRuntimeError, "failed to marshall a request; possibly out of memory");
         
     | 
| 
      
 40 
     | 
    
         
            +
              case ZOPERATIONTIMEOUT: rb_raise(rb_eRuntimeError, "failed to flush the buffers within the specified timeout");
         
     | 
| 
      
 41 
     | 
    
         
            +
              case ZCONNECTIONLOSS: rb_raise(rb_eRuntimeError, "a network error occured while attempting to send request to server");
         
     | 
| 
      
 42 
     | 
    
         
            +
              case ZSYSTEMERROR: rb_raise(rb_eRuntimeError, "a system (OS) error occured; it's worth checking errno to get details");
         
     | 
| 
      
 43 
     | 
    
         
            +
              case ZNONODE: rb_raise(eNoNode, "the node does not exist");
         
     | 
| 
      
 44 
     | 
    
         
            +
              case ZNOAUTH: rb_raise(rb_eRuntimeError, "the client does not have permission");
         
     | 
| 
      
 45 
     | 
    
         
            +
              case ZBADVERSION: rb_raise(eBadVersion, "expected version does not match actual version");
         
     | 
| 
      
 46 
     | 
    
         
            +
              case ZINVALIDSTATE: rb_raise(rb_eRuntimeError, "zhandle state is either SESSION_EXPIRED_STATE or AUTH_FAILED_STATE");
         
     | 
| 
      
 47 
     | 
    
         
            +
              case ZNODEEXISTS: rb_raise(rb_eRuntimeError, "the node already exists");
         
     | 
| 
      
 48 
     | 
    
         
            +
              case ZNOCHILDRENFOREPHEMERALS: rb_raise(rb_eRuntimeError, "cannot create children of ephemeral nodes");
         
     | 
| 
      
 49 
     | 
    
         
            +
              case ZINVALIDACL: rb_raise(rb_eRuntimeError, "invalid ACL specified");
         
     | 
| 
      
 50 
     | 
    
         
            +
              default: rb_raise(rb_eRuntimeError, "unknown error returned from zookeeper: %d", rc);
         
     | 
| 
      
 51 
     | 
    
         
            +
              }
         
     | 
| 
      
 52 
     | 
    
         
            +
            }
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            static void free_zk_rb_data(struct zk_rb_data* ptr) {
         
     | 
| 
      
 55 
     | 
    
         
            +
              /*fprintf(stderr, "free zk_rb_data at %p\n", ptr);*/
         
     | 
| 
      
 56 
     | 
    
         
            +
              zookeeper_close(ptr->zh);
         
     | 
| 
      
 57 
     | 
    
         
            +
            }
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            static VALUE array_from_stat(const struct Stat* stat) {
         
     | 
| 
      
 60 
     | 
    
         
            +
              return rb_ary_new3(8,
         
     | 
| 
      
 61 
     | 
    
         
            +
            		     LL2NUM(stat->czxid),
         
     | 
| 
      
 62 
     | 
    
         
            +
            		     LL2NUM(stat->mzxid),
         
     | 
| 
      
 63 
     | 
    
         
            +
            		     LL2NUM(stat->ctime),
         
     | 
| 
      
 64 
     | 
    
         
            +
            		     LL2NUM(stat->mtime),
         
     | 
| 
      
 65 
     | 
    
         
            +
            		     INT2NUM(stat->version),
         
     | 
| 
      
 66 
     | 
    
         
            +
            		     INT2NUM(stat->cversion),
         
     | 
| 
      
 67 
     | 
    
         
            +
            		     INT2NUM(stat->aversion),
         
     | 
| 
      
 68 
     | 
    
         
            +
            		     LL2NUM(stat->ephemeralOwner));
         
     | 
| 
      
 69 
     | 
    
         
            +
            }
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            static VALUE method_initialize(VALUE self, VALUE hostPort, VALUE logLevel) {
         
     | 
| 
      
 72 
     | 
    
         
            +
              VALUE data;
         
     | 
| 
      
 73 
     | 
    
         
            +
              struct zk_rb_data* zk = NULL;
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
              Check_Type(hostPort, T_STRING);
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              data = Data_Make_Struct(ZooKeeper, struct zk_rb_data, 0, free_zk_rb_data, zk);
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              zoo_set_debug_level(FIX2INT(logLevel));
         
     | 
| 
      
 80 
     | 
    
         
            +
              zoo_deterministic_conn_order(0);
         
     | 
| 
      
 81 
     | 
    
         
            +
              zk->zh = zookeeper_init(RSTRING(hostPort)->ptr, watcher, 10000, &zk->myid, (void*)self, 0);
         
     | 
| 
      
 82 
     | 
    
         
            +
              if (!zk->zh) {
         
     | 
| 
      
 83 
     | 
    
         
            +
                rb_raise(rb_eRuntimeError, "error connecting to zookeeper: %d", errno);
         
     | 
| 
      
 84 
     | 
    
         
            +
              }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              rb_iv_set(self, "@data", data);
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 89 
     | 
    
         
            +
            }
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            static VALUE method_ls(VALUE self, VALUE path) {
         
     | 
| 
      
 92 
     | 
    
         
            +
              struct zk_rb_data* zk;
         
     | 
| 
      
 93 
     | 
    
         
            +
              struct String_vector strings;
         
     | 
| 
      
 94 
     | 
    
         
            +
              int i;
         
     | 
| 
      
 95 
     | 
    
         
            +
              VALUE output;
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              Check_Type(path, T_STRING);
         
     | 
| 
      
 98 
     | 
    
         
            +
              Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              check_errors(zoo_get_children(zk->zh, RSTRING(path)->ptr, 0, &strings));
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              output = rb_ary_new();
         
     | 
| 
      
 103 
     | 
    
         
            +
              for (i = 0; i < strings.count; ++i) {
         
     | 
| 
      
 104 
     | 
    
         
            +
                rb_ary_push(output, rb_str_new2(strings.data[i]));
         
     | 
| 
      
 105 
     | 
    
         
            +
              }
         
     | 
| 
      
 106 
     | 
    
         
            +
              return output;
         
     | 
| 
      
 107 
     | 
    
         
            +
            }
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            static VALUE method_exists(VALUE self, VALUE path, VALUE watch) {
         
     | 
| 
      
 110 
     | 
    
         
            +
              struct zk_rb_data* zk;
         
     | 
| 
      
 111 
     | 
    
         
            +
              struct Stat stat;
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              Check_Type(path, T_STRING);
         
     | 
| 
      
 114 
     | 
    
         
            +
              Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, 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 
     | 
    
         
            +
              struct zk_rb_data* zk;
         
     | 
| 
      
 123 
     | 
    
         
            +
              char realpath[10240];
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
              Check_Type(path, T_STRING);
         
     | 
| 
      
 126 
     | 
    
         
            +
              Check_Type(value, T_STRING);
         
     | 
| 
      
 127 
     | 
    
         
            +
              Check_Type(flags, T_FIXNUM);
         
     | 
| 
      
 128 
     | 
    
         
            +
              Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
              check_errors(zoo_create(zk->zh, RSTRING(path)->ptr, RSTRING(value)->ptr, RSTRING(value)->len,
         
     | 
| 
      
 131 
     | 
    
         
            +
            			  &ZOO_OPEN_ACL_UNSAFE, FIX2INT(flags), realpath, 10240));
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
              return rb_str_new2(realpath);
         
     | 
| 
      
 134 
     | 
    
         
            +
            }
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            static VALUE method_delete(VALUE self, VALUE path, VALUE version) {
         
     | 
| 
      
 137 
     | 
    
         
            +
              struct zk_rb_data* zk;
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
              Check_Type(path, T_STRING);
         
     | 
| 
      
 140 
     | 
    
         
            +
              Check_Type(version, T_FIXNUM);
         
     | 
| 
      
 141 
     | 
    
         
            +
              Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
              check_errors(zoo_delete(zk->zh, RSTRING(path)->ptr, FIX2INT(version)));
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 146 
     | 
    
         
            +
            }
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            static VALUE method_get(VALUE self, VALUE path) {
         
     | 
| 
      
 149 
     | 
    
         
            +
              struct zk_rb_data* zk;
         
     | 
| 
      
 150 
     | 
    
         
            +
              char data[1024];
         
     | 
| 
      
 151 
     | 
    
         
            +
              int data_len = 1024;
         
     | 
| 
      
 152 
     | 
    
         
            +
              struct Stat stat;
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
              Check_Type(path, T_STRING);
         
     | 
| 
      
 155 
     | 
    
         
            +
              Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
         
     | 
| 
      
 156 
     | 
    
         
            +
              
         
     | 
| 
      
 157 
     | 
    
         
            +
              check_errors(zoo_get(zk->zh, RSTRING(path)->ptr, 0, data, &data_len, &stat));
         
     | 
| 
      
 158 
     | 
    
         
            +
              /*printf("got some data; version=%d\n", stat.version);*/
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
              return rb_ary_new3(2,
         
     | 
| 
      
 161 
     | 
    
         
            +
            		     rb_str_new(data, data_len),
         
     | 
| 
      
 162 
     | 
    
         
            +
            		     array_from_stat(&stat));
         
     | 
| 
      
 163 
     | 
    
         
            +
            }
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
            static VALUE method_set(VALUE self, VALUE path, VALUE data, VALUE version) {
         
     | 
| 
      
 166 
     | 
    
         
            +
              struct zk_rb_data* zk;
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
              Check_Type(path, T_STRING);
         
     | 
| 
      
 169 
     | 
    
         
            +
              Check_Type(data, T_STRING);
         
     | 
| 
      
 170 
     | 
    
         
            +
              Check_Type(version, T_FIXNUM);
         
     | 
| 
      
 171 
     | 
    
         
            +
              Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
         
     | 
| 
      
 172 
     | 
    
         
            +
              
         
     | 
| 
      
 173 
     | 
    
         
            +
              check_errors(zoo_set(zk->zh, RSTRING(path)->ptr, RSTRING(data)->ptr, RSTRING(data)->len, FIX2INT(version)));
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 176 
     | 
    
         
            +
            }
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
            void Init_zookeeper_c() {
         
     | 
| 
      
 179 
     | 
    
         
            +
              ZooKeeper = rb_define_class("CZooKeeper", rb_cObject);
         
     | 
| 
      
 180 
     | 
    
         
            +
              rb_define_method(ZooKeeper, "initialize", method_initialize, 1);
         
     | 
| 
      
 181 
     | 
    
         
            +
              rb_define_method(ZooKeeper, "ls", method_ls, 1);
         
     | 
| 
      
 182 
     | 
    
         
            +
              rb_define_method(ZooKeeper, "exists", method_exists, 2);
         
     | 
| 
      
 183 
     | 
    
         
            +
              rb_define_method(ZooKeeper, "create", method_create, 3);
         
     | 
| 
      
 184 
     | 
    
         
            +
              rb_define_method(ZooKeeper, "delete", method_delete, 2);
         
     | 
| 
      
 185 
     | 
    
         
            +
              rb_define_method(ZooKeeper, "get", method_get, 1);
         
     | 
| 
      
 186 
     | 
    
         
            +
              rb_define_method(ZooKeeper, "set", method_set, 3);
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
              eNoNode = rb_define_class_under(ZooKeeper, "NoNodeError", rb_eRuntimeError);
         
     | 
| 
      
 189 
     | 
    
         
            +
              eBadVersion = rb_define_class_under(ZooKeeper, "BadVersionError", rb_eRuntimeError);
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "EPHEMERAL", INT2FIX(ZOO_EPHEMERAL));
         
     | 
| 
      
 192 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "SEQUENCE", INT2FIX(ZOO_SEQUENCE));
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "SESSION_EVENT", INT2FIX(ZOO_SESSION_EVENT));
         
     | 
| 
      
 195 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "CONNECTED_STATE", INT2FIX(ZOO_CONNECTED_STATE));
         
     | 
| 
      
 196 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "AUTH_FAILED_STATE", INT2FIX(ZOO_AUTH_FAILED_STATE));
         
     | 
| 
      
 197 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "EXPIRED_SESSION_STATE", INT2FIX(ZOO_EXPIRED_SESSION_STATE));
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "LOG_LEVEL_ERROR", INT2FIX(ZOO_LOG_LEVEL_ERROR));
         
     | 
| 
      
 200 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "LOG_LEVEL_WARN", INT2FIX(ZOO_LOG_LEVEL_WARN));
         
     | 
| 
      
 201 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "LOG_LEVEL_INFO", INT2FIX(ZOO_LOG_LEVEL_INFO));
         
     | 
| 
      
 202 
     | 
    
         
            +
              rb_define_const(ZooKeeper, "LOG_LEVEL_DEBUG", INT2FIX(ZOO_LOG_LEVEL_DEBUG));
         
     | 
| 
      
 203 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -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, log_level = LOG_LEVEL_INFO)
         
     | 
| 
      
 15 
     | 
    
         
            +
                super(host, log_level)
         
     | 
| 
      
 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::EPHEMERAL | ZooKeeper::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 == SESSION_EVENT
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                case state
         
     | 
| 
      
 69 
     | 
    
         
            +
                when CONNECTED_STATE
         
     | 
| 
      
 70 
     | 
    
         
            +
                  puts "ruby watcher; got an event for #{path}"
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                when AUTH_FAILED_STATE
         
     | 
| 
      
 73 
     | 
    
         
            +
                  raise Exception, "auth failure"
         
     | 
| 
      
 74 
     | 
    
         
            +
                when EXPIRED_SESSION_STATE
         
     | 
| 
      
 75 
     | 
    
         
            +
                  raise Exception, "session expired"
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
    
        data/test/test_basic.rb
    ADDED
    
    | 
         @@ -0,0 +1,62 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'zookeeper_client'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            z = ZooKeeper.new("localhost:2181")
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            puts "root: #{z.ls("/").inspect}"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            path = "/testing_node"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            puts "working with path #{path}"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            stat = z.stat(path)
         
     | 
| 
      
 13 
     | 
    
         
            +
            puts "exists? #{stat.inspect}"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            unless stat.nil?
         
     | 
| 
      
 16 
     | 
    
         
            +
              z.ls(path).each do |o|
         
     | 
| 
      
 17 
     | 
    
         
            +
                puts "  child object: #{o}"
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
              puts "delete: #{z.delete(path, stat.version).inspect}"
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            puts "create: #{z.create(path, "initial value", 0).inspect}"
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            value, stat = z.get(path)
         
     | 
| 
      
 25 
     | 
    
         
            +
            puts "current value #{value}, stat #{stat.inspect}"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            puts "set: #{z.set(path, "this is a test", stat.version).inspect}"
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            value, stat = z.get(path)
         
     | 
| 
      
 30 
     | 
    
         
            +
            puts "new value: #{value.inspect} #{stat.inspect}"
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            puts "delete: #{z.delete(path, stat.version).inspect}"
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            begin
         
     | 
| 
      
 35 
     | 
    
         
            +
              puts "exists? #{z.exists(path)}"
         
     | 
| 
      
 36 
     | 
    
         
            +
              raise Exception, "it shouldn't exist"
         
     | 
| 
      
 37 
     | 
    
         
            +
            rescue ZooKeeper::NoNodeError
         
     | 
| 
      
 38 
     | 
    
         
            +
              puts "doesn't exist - good, because we just deleted it!"
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            puts "trying a watcher"
         
     | 
| 
      
 42 
     | 
    
         
            +
            puts z
         
     | 
| 
      
 43 
     | 
    
         
            +
            if s = z.stat("/test"); z.delete("/test", s.version); end
         
     | 
| 
      
 44 
     | 
    
         
            +
            z.create("/test", "foo", 0)
         
     | 
| 
      
 45 
     | 
    
         
            +
            z.exists("/test") do
         
     | 
| 
      
 46 
     | 
    
         
            +
              puts "callback!!!"
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
      
 48 
     | 
    
         
            +
            puts "now changing it"
         
     | 
| 
      
 49 
     | 
    
         
            +
            z.set("/test", "bar", 0)
         
     | 
| 
      
 50 
     | 
    
         
            +
            sleep 1
         
     | 
| 
      
 51 
     | 
    
         
            +
            puts "did the watcher say something?"
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            puts "let's try using a lock"
         
     | 
| 
      
 54 
     | 
    
         
            +
            z.try_acquire("/test_lock", "this is the content of the lock file") do |have_lock|
         
     | 
| 
      
 55 
     | 
    
         
            +
              puts have_lock ? "we have the lock!" : "failed to obtain lock :("
         
     | 
| 
      
 56 
     | 
    
         
            +
              if have_lock
         
     | 
| 
      
 57 
     | 
    
         
            +
                puts "sleeping"
         
     | 
| 
      
 58 
     | 
    
         
            +
                sleep 5
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     | 
| 
      
 61 
     | 
    
         
            +
            puts "done with locking..."
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification 
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: neerfri-zookeeper_client
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.5
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors: 
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Phillip Pearson
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Justin Shaffer
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            date: 2008-07-20 00:00:00 -07:00
         
     | 
| 
      
 14 
     | 
    
         
            +
            default_executable: 
         
     | 
| 
      
 15 
     | 
    
         
            +
            dependencies: []
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            description: zookeeper_client is a Ruby library to interface with the ZooKeeper replicated object store / lock server.
         
     | 
| 
      
 18 
     | 
    
         
            +
            email: justin@hotpotato.com
         
     | 
| 
      
 19 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            extensions: 
         
     | 
| 
      
 22 
     | 
    
         
            +
            - ext/zookeeper_c/extconf.rb
         
     | 
| 
      
 23 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            files: 
         
     | 
| 
      
 26 
     | 
    
         
            +
            - lib/zookeeper_client.rb
         
     | 
| 
      
 27 
     | 
    
         
            +
            - ext/zookeeper_c/zookeeper_ruby.c
         
     | 
| 
      
 28 
     | 
    
         
            +
            has_rdoc: false
         
     | 
| 
      
 29 
     | 
    
         
            +
            homepage: http://github.com/shafferj/zookeeper_client
         
     | 
| 
      
 30 
     | 
    
         
            +
            licenses: 
         
     | 
| 
      
 31 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 32 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 35 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 36 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 37 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 38 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 39 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 40 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 41 
     | 
    
         
            +
              version: 
         
     | 
| 
      
 42 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 44 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 45 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 46 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 47 
     | 
    
         
            +
              version: 
         
     | 
| 
      
 48 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 51 
     | 
    
         
            +
            rubygems_version: 1.3.5
         
     | 
| 
      
 52 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 53 
     | 
    
         
            +
            specification_version: 2
         
     | 
| 
      
 54 
     | 
    
         
            +
            summary: Ruby wrapper for the ZooKeeper C client library
         
     | 
| 
      
 55 
     | 
    
         
            +
            test_files: 
         
     | 
| 
      
 56 
     | 
    
         
            +
            - test/test_basic.rb
         
     |