zkruby 3.4.3
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.tar.gz.sig +0 -0
 - data/.gemtest +0 -0
 - data/History.txt +18 -0
 - data/Manifest.txt +39 -0
 - data/README.rdoc +119 -0
 - data/Rakefile +39 -0
 - data/jute/jute.citrus +105 -0
 - data/jute/lib/hoe/jute.rb +56 -0
 - data/jute/lib/jute.rb +120 -0
 - data/lib/em_zkruby.rb +4 -0
 - data/lib/jute/zookeeper.rb +203 -0
 - data/lib/zkruby.rb +4 -0
 - data/lib/zkruby/bindata.rb +45 -0
 - data/lib/zkruby/client.rb +608 -0
 - data/lib/zkruby/enum.rb +108 -0
 - data/lib/zkruby/eventmachine.rb +186 -0
 - data/lib/zkruby/multi.rb +47 -0
 - data/lib/zkruby/protocol.rb +182 -0
 - data/lib/zkruby/rubyio.rb +310 -0
 - data/lib/zkruby/session.rb +445 -0
 - data/lib/zkruby/util.rb +141 -0
 - data/lib/zkruby/zkruby.rb +27 -0
 - data/spec/bindata_spec.rb +51 -0
 - data/spec/enum_spec.rb +84 -0
 - data/spec/eventmachine_spec.rb +50 -0
 - data/spec/multi_spec.rb +93 -0
 - data/spec/protocol_spec.rb +72 -0
 - data/spec/recipe_helper.rb +68 -0
 - data/spec/rubyio_spec.rb +8 -0
 - data/spec/sequences_spec.rb +19 -0
 - data/spec/server_helper.rb +45 -0
 - data/spec/shared/auth.rb +40 -0
 - data/spec/shared/basic.rb +180 -0
 - data/spec/shared/binding.rb +33 -0
 - data/spec/shared/chroot.rb +61 -0
 - data/spec/shared/multi.rb +38 -0
 - data/spec/shared/util.rb +56 -0
 - data/spec/shared/watch.rb +49 -0
 - data/spec/spec_helper.rb +12 -0
 - data/src/jute/zookeeper.jute +288 -0
 - data/yard_ext/enum_handler.rb +16 -0
 - metadata +243 -0
 - metadata.gz.sig +0 -0
 
    
        data/lib/em_zkruby.rb
    ADDED
    
    
| 
         @@ -0,0 +1,203 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             module ZooKeeper::Data
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Identity < BinData::Record
         
     | 
| 
      
 3 
     | 
    
         
            +
                zk_string :scheme
         
     | 
| 
      
 4 
     | 
    
         
            +
                zk_string :identity
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
      
 6 
     | 
    
         
            +
              class ACL < BinData::Record
         
     | 
| 
      
 7 
     | 
    
         
            +
                int32be :perms
         
     | 
| 
      
 8 
     | 
    
         
            +
                identity :identity
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
              class Stat < BinData::Record
         
     | 
| 
      
 11 
     | 
    
         
            +
                int64be :czxid
         
     | 
| 
      
 12 
     | 
    
         
            +
                int64be :mzxid
         
     | 
| 
      
 13 
     | 
    
         
            +
                int64be :ctime
         
     | 
| 
      
 14 
     | 
    
         
            +
                int64be :mtime
         
     | 
| 
      
 15 
     | 
    
         
            +
                int32be :version
         
     | 
| 
      
 16 
     | 
    
         
            +
                int32be :cversion
         
     | 
| 
      
 17 
     | 
    
         
            +
                int32be :aversion
         
     | 
| 
      
 18 
     | 
    
         
            +
                int64be :ephemeral_owner
         
     | 
| 
      
 19 
     | 
    
         
            +
                int32be :data_length
         
     | 
| 
      
 20 
     | 
    
         
            +
                int32be :num_children
         
     | 
| 
      
 21 
     | 
    
         
            +
                int64be :pzxid
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
              class StatPersisted < BinData::Record
         
     | 
| 
      
 24 
     | 
    
         
            +
                int64be :czxid
         
     | 
| 
      
 25 
     | 
    
         
            +
                int64be :mzxid
         
     | 
| 
      
 26 
     | 
    
         
            +
                int64be :ctime
         
     | 
| 
      
 27 
     | 
    
         
            +
                int64be :mtime
         
     | 
| 
      
 28 
     | 
    
         
            +
                int32be :version
         
     | 
| 
      
 29 
     | 
    
         
            +
                int32be :cversion
         
     | 
| 
      
 30 
     | 
    
         
            +
                int32be :aversion
         
     | 
| 
      
 31 
     | 
    
         
            +
                int64be :ephemeral_owner
         
     | 
| 
      
 32 
     | 
    
         
            +
                int64be :pzxid
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
              class StatPersistedV1 < BinData::Record
         
     | 
| 
      
 35 
     | 
    
         
            +
                int64be :czxid
         
     | 
| 
      
 36 
     | 
    
         
            +
                int64be :mzxid
         
     | 
| 
      
 37 
     | 
    
         
            +
                int64be :ctime
         
     | 
| 
      
 38 
     | 
    
         
            +
                int64be :mtime
         
     | 
| 
      
 39 
     | 
    
         
            +
                int32be :version
         
     | 
| 
      
 40 
     | 
    
         
            +
                int32be :cversion
         
     | 
| 
      
 41 
     | 
    
         
            +
                int32be :aversion
         
     | 
| 
      
 42 
     | 
    
         
            +
                int64be :ephemeral_owner
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             end
         
     | 
| 
      
 45 
     | 
    
         
            +
             module ZooKeeper::Proto
         
     | 
| 
      
 46 
     | 
    
         
            +
              class ConnectRequest < BinData::Record
         
     | 
| 
      
 47 
     | 
    
         
            +
                int32be :protocol_version
         
     | 
| 
      
 48 
     | 
    
         
            +
                int64be :last_zxid_seen
         
     | 
| 
      
 49 
     | 
    
         
            +
                int32be :time_out
         
     | 
| 
      
 50 
     | 
    
         
            +
                int64be :session_id
         
     | 
| 
      
 51 
     | 
    
         
            +
                zk_buffer :passwd
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
              class ConnectResponse < BinData::Record
         
     | 
| 
      
 54 
     | 
    
         
            +
                int32be :protocol_version
         
     | 
| 
      
 55 
     | 
    
         
            +
                int32be :time_out
         
     | 
| 
      
 56 
     | 
    
         
            +
                int64be :session_id
         
     | 
| 
      
 57 
     | 
    
         
            +
                zk_buffer :passwd
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
              class SetWatches < BinData::Record
         
     | 
| 
      
 60 
     | 
    
         
            +
                int64be :relative_zxid
         
     | 
| 
      
 61 
     | 
    
         
            +
                hide :data_watches__length
         
     | 
| 
      
 62 
     | 
    
         
            +
                int32be :data_watches__length, :value => lambda { data_watches.length }
         
     | 
| 
      
 63 
     | 
    
         
            +
                array :data_watches, :type => :zk_string, :initial_length => :data_watches__length
         
     | 
| 
      
 64 
     | 
    
         
            +
                hide :exist_watches__length
         
     | 
| 
      
 65 
     | 
    
         
            +
                int32be :exist_watches__length, :value => lambda { exist_watches.length }
         
     | 
| 
      
 66 
     | 
    
         
            +
                array :exist_watches, :type => :zk_string, :initial_length => :exist_watches__length
         
     | 
| 
      
 67 
     | 
    
         
            +
                hide :child_watches__length
         
     | 
| 
      
 68 
     | 
    
         
            +
                int32be :child_watches__length, :value => lambda { child_watches.length }
         
     | 
| 
      
 69 
     | 
    
         
            +
                array :child_watches, :type => :zk_string, :initial_length => :child_watches__length
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
              class RequestHeader < BinData::Record
         
     | 
| 
      
 72 
     | 
    
         
            +
                int32be :xid
         
     | 
| 
      
 73 
     | 
    
         
            +
                int32be :_type
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
              class MultiHeader < BinData::Record
         
     | 
| 
      
 76 
     | 
    
         
            +
                int32be :_type
         
     | 
| 
      
 77 
     | 
    
         
            +
                zk_boolean :done
         
     | 
| 
      
 78 
     | 
    
         
            +
                int32be :err
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
              class AuthPacket < BinData::Record
         
     | 
| 
      
 81 
     | 
    
         
            +
                int32be :_type
         
     | 
| 
      
 82 
     | 
    
         
            +
                zk_string :scheme
         
     | 
| 
      
 83 
     | 
    
         
            +
                zk_buffer :auth
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
              class ReplyHeader < BinData::Record
         
     | 
| 
      
 86 
     | 
    
         
            +
                int32be :xid
         
     | 
| 
      
 87 
     | 
    
         
            +
                int64be :zxid
         
     | 
| 
      
 88 
     | 
    
         
            +
                int32be :err
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
              class GetDataRequest < BinData::Record
         
     | 
| 
      
 91 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 92 
     | 
    
         
            +
                zk_boolean :watch
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
              class SetDataRequest < BinData::Record
         
     | 
| 
      
 95 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 96 
     | 
    
         
            +
                zk_buffer :data
         
     | 
| 
      
 97 
     | 
    
         
            +
                int32be :version
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
              class SetDataResponse < BinData::Record
         
     | 
| 
      
 100 
     | 
    
         
            +
                stat :stat
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
              class GetSASLRequest < BinData::Record
         
     | 
| 
      
 103 
     | 
    
         
            +
                zk_buffer :token
         
     | 
| 
      
 104 
     | 
    
         
            +
              end
         
     | 
| 
      
 105 
     | 
    
         
            +
              class SetSASLRequest < BinData::Record
         
     | 
| 
      
 106 
     | 
    
         
            +
                zk_buffer :token
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
              class SetSASLResponse < BinData::Record
         
     | 
| 
      
 109 
     | 
    
         
            +
                zk_buffer :token
         
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
              class CreateRequest < BinData::Record
         
     | 
| 
      
 112 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 113 
     | 
    
         
            +
                zk_buffer :data
         
     | 
| 
      
 114 
     | 
    
         
            +
                hide :acl__length
         
     | 
| 
      
 115 
     | 
    
         
            +
                int32be :acl__length, :value => lambda { acl.length }
         
     | 
| 
      
 116 
     | 
    
         
            +
                array :acl, :type => :acl, :initial_length => :acl__length
         
     | 
| 
      
 117 
     | 
    
         
            +
                int32be :flags
         
     | 
| 
      
 118 
     | 
    
         
            +
              end
         
     | 
| 
      
 119 
     | 
    
         
            +
              class DeleteRequest < BinData::Record
         
     | 
| 
      
 120 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 121 
     | 
    
         
            +
                int32be :version
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
              class GetChildrenRequest < BinData::Record
         
     | 
| 
      
 124 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 125 
     | 
    
         
            +
                zk_boolean :watch
         
     | 
| 
      
 126 
     | 
    
         
            +
              end
         
     | 
| 
      
 127 
     | 
    
         
            +
              class GetChildren2Request < BinData::Record
         
     | 
| 
      
 128 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 129 
     | 
    
         
            +
                zk_boolean :watch
         
     | 
| 
      
 130 
     | 
    
         
            +
              end
         
     | 
| 
      
 131 
     | 
    
         
            +
              class CheckVersionRequest < BinData::Record
         
     | 
| 
      
 132 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 133 
     | 
    
         
            +
                int32be :version
         
     | 
| 
      
 134 
     | 
    
         
            +
              end
         
     | 
| 
      
 135 
     | 
    
         
            +
              class GetMaxChildrenRequest < BinData::Record
         
     | 
| 
      
 136 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 137 
     | 
    
         
            +
              end
         
     | 
| 
      
 138 
     | 
    
         
            +
              class GetMaxChildrenResponse < BinData::Record
         
     | 
| 
      
 139 
     | 
    
         
            +
                int32be :maximum
         
     | 
| 
      
 140 
     | 
    
         
            +
              end
         
     | 
| 
      
 141 
     | 
    
         
            +
              class SetMaxChildrenRequest < BinData::Record
         
     | 
| 
      
 142 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 143 
     | 
    
         
            +
                int32be :maximum
         
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
      
 145 
     | 
    
         
            +
              class SyncRequest < BinData::Record
         
     | 
| 
      
 146 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
              class SyncResponse < BinData::Record
         
     | 
| 
      
 149 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 150 
     | 
    
         
            +
              end
         
     | 
| 
      
 151 
     | 
    
         
            +
              class GetACLRequest < BinData::Record
         
     | 
| 
      
 152 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 153 
     | 
    
         
            +
              end
         
     | 
| 
      
 154 
     | 
    
         
            +
              class SetACLRequest < BinData::Record
         
     | 
| 
      
 155 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 156 
     | 
    
         
            +
                hide :acl__length
         
     | 
| 
      
 157 
     | 
    
         
            +
                int32be :acl__length, :value => lambda { acl.length }
         
     | 
| 
      
 158 
     | 
    
         
            +
                array :acl, :type => :acl, :initial_length => :acl__length
         
     | 
| 
      
 159 
     | 
    
         
            +
                int32be :version
         
     | 
| 
      
 160 
     | 
    
         
            +
              end
         
     | 
| 
      
 161 
     | 
    
         
            +
              class SetACLResponse < BinData::Record
         
     | 
| 
      
 162 
     | 
    
         
            +
                stat :stat
         
     | 
| 
      
 163 
     | 
    
         
            +
              end
         
     | 
| 
      
 164 
     | 
    
         
            +
              class WatcherEvent < BinData::Record
         
     | 
| 
      
 165 
     | 
    
         
            +
                int32be :_type
         
     | 
| 
      
 166 
     | 
    
         
            +
                int32be :state
         
     | 
| 
      
 167 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 168 
     | 
    
         
            +
              end
         
     | 
| 
      
 169 
     | 
    
         
            +
              class ErrorResponse < BinData::Record
         
     | 
| 
      
 170 
     | 
    
         
            +
                int32be :err
         
     | 
| 
      
 171 
     | 
    
         
            +
              end
         
     | 
| 
      
 172 
     | 
    
         
            +
              class CreateResponse < BinData::Record
         
     | 
| 
      
 173 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 174 
     | 
    
         
            +
              end
         
     | 
| 
      
 175 
     | 
    
         
            +
              class ExistsRequest < BinData::Record
         
     | 
| 
      
 176 
     | 
    
         
            +
                zk_string :path
         
     | 
| 
      
 177 
     | 
    
         
            +
                zk_boolean :watch
         
     | 
| 
      
 178 
     | 
    
         
            +
              end
         
     | 
| 
      
 179 
     | 
    
         
            +
              class ExistsResponse < BinData::Record
         
     | 
| 
      
 180 
     | 
    
         
            +
                stat :stat
         
     | 
| 
      
 181 
     | 
    
         
            +
              end
         
     | 
| 
      
 182 
     | 
    
         
            +
              class GetDataResponse < BinData::Record
         
     | 
| 
      
 183 
     | 
    
         
            +
                zk_buffer :data
         
     | 
| 
      
 184 
     | 
    
         
            +
                stat :stat
         
     | 
| 
      
 185 
     | 
    
         
            +
              end
         
     | 
| 
      
 186 
     | 
    
         
            +
              class GetChildrenResponse < BinData::Record
         
     | 
| 
      
 187 
     | 
    
         
            +
                hide :children__length
         
     | 
| 
      
 188 
     | 
    
         
            +
                int32be :children__length, :value => lambda { children.length }
         
     | 
| 
      
 189 
     | 
    
         
            +
                array :children, :type => :zk_string, :initial_length => :children__length
         
     | 
| 
      
 190 
     | 
    
         
            +
              end
         
     | 
| 
      
 191 
     | 
    
         
            +
              class GetChildren2Response < BinData::Record
         
     | 
| 
      
 192 
     | 
    
         
            +
                hide :children__length
         
     | 
| 
      
 193 
     | 
    
         
            +
                int32be :children__length, :value => lambda { children.length }
         
     | 
| 
      
 194 
     | 
    
         
            +
                array :children, :type => :zk_string, :initial_length => :children__length
         
     | 
| 
      
 195 
     | 
    
         
            +
                stat :stat
         
     | 
| 
      
 196 
     | 
    
         
            +
              end
         
     | 
| 
      
 197 
     | 
    
         
            +
              class GetACLResponse < BinData::Record
         
     | 
| 
      
 198 
     | 
    
         
            +
                hide :acl__length
         
     | 
| 
      
 199 
     | 
    
         
            +
                int32be :acl__length, :value => lambda { acl.length }
         
     | 
| 
      
 200 
     | 
    
         
            +
                array :acl, :type => :acl, :initial_length => :acl__length
         
     | 
| 
      
 201 
     | 
    
         
            +
                stat :stat
         
     | 
| 
      
 202 
     | 
    
         
            +
              end
         
     | 
| 
      
 203 
     | 
    
         
            +
             end
         
     | 
    
        data/lib/zkruby.rb
    ADDED
    
    
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #TODO This belongs to jute rather than zookeeper and ideally would be a separate project/gem
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'bindata'
         
     | 
| 
      
 3 
     | 
    
         
            +
            module ZooKeeper
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                class ZKBuffer < BinData::Primitive
         
     | 
| 
      
 6 
     | 
    
         
            +
                    int32be  :len,  :value => lambda { data.nil? ? -1 : data.length }
         
     | 
| 
      
 7 
     | 
    
         
            +
                    string :data, :read_length => :len
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def get;   self.data; end
         
     | 
| 
      
 10 
     | 
    
         
            +
                    def set(v) self.data = v; end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                class ZKString < BinData::Primitive
         
     | 
| 
      
 14 
     | 
    
         
            +
                    int32be  :len,  :value => lambda { data.nil? ? -1 : data.length }
         
     | 
| 
      
 15 
     | 
    
         
            +
                    string :data, :read_length => :len
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def get;   self.data; end
         
     | 
| 
      
 18 
     | 
    
         
            +
                    def set(v) self.data = v; end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    def snapshot
         
     | 
| 
      
 20 
     | 
    
         
            +
                        super.force_encoding('UTF-8')
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                #This doesn't work as expected, because when used in a record
         
     | 
| 
      
 25 
     | 
    
         
            +
                # you get a ZKBoolean instance back which cannot be compared to "false"
         
     | 
| 
      
 26 
     | 
    
         
            +
                # you must call snapshot or compare with == false
         
     | 
| 
      
 27 
     | 
    
         
            +
                class ZKBoolean < BinData::BasePrimitive
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    def value_to_binary_string(v)
         
     | 
| 
      
 30 
     | 
    
         
            +
                        intval = v ? 1 : 0
         
     | 
| 
      
 31 
     | 
    
         
            +
                        [ intval ].pack("C")
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def read_and_return_value(io)
         
     | 
| 
      
 35 
     | 
    
         
            +
                        intval = io.readbytes(1).unpack("C").at(0)
         
     | 
| 
      
 36 
     | 
    
         
            +
                        intval != 0
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def sensible_default
         
     | 
| 
      
 40 
     | 
    
         
            +
                        false
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,608 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ZooKeeper
         
     | 
| 
      
 2 
     | 
    
         
            +
                # Represents failure mode of ZooKeeper operations
         
     | 
| 
      
 3 
     | 
    
         
            +
                # They are raised and rescued in the standard ways (much like ruby's Errno)
         
     | 
| 
      
 4 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 5 
     | 
    
         
            +
                #   begin
         
     | 
| 
      
 6 
     | 
    
         
            +
                #       zk.create(...)
         
     | 
| 
      
 7 
     | 
    
         
            +
                #   rescue ZK::Error::NODE_EXISTS
         
     | 
| 
      
 8 
     | 
    
         
            +
                #       ....
         
     | 
| 
      
 9 
     | 
    
         
            +
                #   rescue ZK::Error::CONNECTION_LOST
         
     | 
| 
      
 10 
     | 
    
         
            +
                #   end
         
     | 
| 
      
 11 
     | 
    
         
            +
                #
         
     | 
| 
      
 12 
     | 
    
         
            +
                class Error < StandardError
         
     | 
| 
      
 13 
     | 
    
         
            +
                    include Enumeration
         
     | 
| 
      
 14 
     | 
    
         
            +
                    enum :none, 0
         
     | 
| 
      
 15 
     | 
    
         
            +
                    enum :system_error,  (-1) 
         
     | 
| 
      
 16 
     | 
    
         
            +
                    enum :runtime_inconsistency, (-2)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    enum :data_inconsistency, (-3)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    enum :connection_lost, (-4)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    enum :marshalling_error, (-5)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    enum :unimplemented, (-6)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    enum :operation_timeout, (-7)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    enum :bad_arguments, (-8)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    enum :api_error, (-100)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    enum :no_node, (-101)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    enum :no_auth, (-102)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    enum :bad_version, (-103)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    enum :no_children_for_ephemerals, (-108)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    enum :node_exists, (-110)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    enum :not_empty, (-111)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    enum :session_expired, (-112)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    enum :invalid_callback, (-113)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    enum :invalid_acl, (-114)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    enum :auth_failed, (-115)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    enum :session_moved, (-118)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    enum :unknown, (-999)
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                # Permission constants
         
     | 
| 
      
 39 
     | 
    
         
            +
                class Perms
         
     | 
| 
      
 40 
     | 
    
         
            +
                    include Enumeration
         
     | 
| 
      
 41 
     | 
    
         
            +
                    enum :read, 1 << 0
         
     | 
| 
      
 42 
     | 
    
         
            +
                    enum :write, 1 << 1
         
     | 
| 
      
 43 
     | 
    
         
            +
                    enum :create, 1 << 2
         
     | 
| 
      
 44 
     | 
    
         
            +
                    enum :delete, 1 << 3
         
     | 
| 
      
 45 
     | 
    
         
            +
                    enum :admin, 1 << 4
         
     | 
| 
      
 46 
     | 
    
         
            +
                    enum :all, READ | WRITE | CREATE | DELETE | ADMIN
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Combine permissions constants
         
     | 
| 
      
 51 
     | 
    
         
            +
                # @param [Perms] perms... list of permissions to combine, can be {Perms} constants, symbols or ints 
         
     | 
| 
      
 52 
     | 
    
         
            +
                # @return [Fixnum] integer representing the combined permission
         
     | 
| 
      
 53 
     | 
    
         
            +
                def self.perms(*perms)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    perms.inject(0) { | result, perm | result = result | Perms.get(perm) }
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                # Convenience method to create a zk Identity
         
     | 
| 
      
 58 
     | 
    
         
            +
                # @param [String] scheme
         
     | 
| 
      
 59 
     | 
    
         
            +
                # @param [String] identity
         
     | 
| 
      
 60 
     | 
    
         
            +
                # @return [Data::Identity] the encapsulated identity for the given scheme
         
     | 
| 
      
 61 
     | 
    
         
            +
                def self.id(scheme,id)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    Data::Identity.new(:scheme => scheme, :identity => id)
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                # Convenience method to create a zk ACL
         
     | 
| 
      
 66 
     | 
    
         
            +
                #    ZK.acl(ZK.id("world","anyone"), ZK::Perms.DELETE, ZL::Perms.WRITE)
         
     | 
| 
      
 67 
     | 
    
         
            +
                # @param [Data::Identity] id
         
     | 
| 
      
 68 
     | 
    
         
            +
                # @param [Perms] *perms list of permissions
         
     | 
| 
      
 69 
     | 
    
         
            +
                # @return [Data::ACL] an access control list
         
     | 
| 
      
 70 
     | 
    
         
            +
                # @see #perms
         
     | 
| 
      
 71 
     | 
    
         
            +
                # 
         
     | 
| 
      
 72 
     | 
    
         
            +
                #
         
     | 
| 
      
 73 
     | 
    
         
            +
                def self.acl(id,*perms)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    Data::ACL.new( :identity => id, :perms => self.perms(*perms) )
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                #  
         
     | 
| 
      
 78 
     | 
    
         
            +
                # The Anyone ID
         
     | 
| 
      
 79 
     | 
    
         
            +
                ANYONE_ID_UNSAFE = Data::Identity.new(:scheme => "world", :identity => "anyone")
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                # Represents the set of auth ids for the current connection
         
     | 
| 
      
 82 
     | 
    
         
            +
                AUTH_IDS = Data::Identity.new(:scheme => "auth")
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                OPEN_ACL_UNSAFE = [ acl(ANYONE_ID_UNSAFE, Perms::ALL) ]
         
     | 
| 
      
 85 
     | 
    
         
            +
                CREATOR_ALL_ACL = [ acl(AUTH_IDS, Perms::ALL) ]
         
     | 
| 
      
 86 
     | 
    
         
            +
                READ_ACL_UNSAFE = [ acl(ANYONE_ID_UNSAFE, Perms::READ) ]
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                # The Anyone ID
         
     | 
| 
      
 89 
     | 
    
         
            +
                ID_ANYONE_UNSAFE = ANYONE_ID_UNSAFE
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                # Represents the set of auth ids for the current connection
         
     | 
| 
      
 92 
     | 
    
         
            +
                ID_USE_AUTHS = AUTH_IDS
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                ACL_OPEN_UNSAFE = OPEN_ACL_UNSAFE
         
     | 
| 
      
 95 
     | 
    
         
            +
                ACL_CREATOR_ALL = CREATOR_ALL_ACL
         
     | 
| 
      
 96 
     | 
    
         
            +
                ACL_READ_UNSAFE = READ_ACL_UNSAFE
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                def self.seq_to_path(path,id)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    format("%s%010d",path,id)
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                def self.path_to_seq(path)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    matches = /^(.*)(\d{10})$/.match(path)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    matches ? [matches[1],matches[2].to_i] : [path,nil]
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                CURRENT = :zookeeper_current
         
     | 
| 
      
 109 
     | 
    
         
            +
                # Main method for connecting to a client
         
     | 
| 
      
 110 
     | 
    
         
            +
                # @param addresses [Array<String>] list of host:port for the ZK cluster as Array or comma separated String
         
     | 
| 
      
 111 
     | 
    
         
            +
                # @option options [Class]  :binding binding optional implementation class
         
     | 
| 
      
 112 
     | 
    
         
            +
                #    either {EventMachine::Binding} or {RubyIO::Binding} but normally autodiscovered
         
     | 
| 
      
 113 
     | 
    
         
            +
                # @option options [String] :chroot chroot path.
         
     | 
| 
      
 114 
     | 
    
         
            +
                #    All client calls will be made relative to this path 
         
     | 
| 
      
 115 
     | 
    
         
            +
                # @option options [Watcher] :watch the default watcher
         
     | 
| 
      
 116 
     | 
    
         
            +
                # @option options [String] :scheme the authentication scheme
         
     | 
| 
      
 117 
     | 
    
         
            +
                # @option options [String] :auth   the authentication credentials
         
     | 
| 
      
 118 
     | 
    
         
            +
                # @yieldparam [Client]
         
     | 
| 
      
 119 
     | 
    
         
            +
                # @return [Client] 
         
     | 
| 
      
 120 
     | 
    
         
            +
                def self.connect(addresses,options={},&block)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    if options.has_key?(:binding)
         
     | 
| 
      
 122 
     | 
    
         
            +
                        binding_type = options[:binding]
         
     | 
| 
      
 123 
     | 
    
         
            +
                    else
         
     | 
| 
      
 124 
     | 
    
         
            +
                        binding_type = @bindings.detect { |b| b.available? }
         
     | 
| 
      
 125 
     | 
    
         
            +
                        raise ProtocolError,"No available binding" unless binding_type
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                    binding = binding_type.new()
         
     | 
| 
      
 128 
     | 
    
         
            +
                    session = Session.new(binding,addresses,options)
         
     | 
| 
      
 129 
     | 
    
         
            +
                    client = Client.new(binding)
         
     | 
| 
      
 130 
     | 
    
         
            +
                    binding.start(client,session)
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                    return client unless block_given?
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                    binding_type.context() do |storage|
         
     | 
| 
      
 135 
     | 
    
         
            +
                        @binding_storage = storage
         
     | 
| 
      
 136 
     | 
    
         
            +
                        storage.current[CURRENT] ||= []
         
     | 
| 
      
 137 
     | 
    
         
            +
                        storage.current[CURRENT].push(client)
         
     | 
| 
      
 138 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 139 
     | 
    
         
            +
                            block.call(client)
         
     | 
| 
      
 140 
     | 
    
         
            +
                        ensure
         
     | 
| 
      
 141 
     | 
    
         
            +
                            storage.current[CURRENT].pop
         
     | 
| 
      
 142 
     | 
    
         
            +
                            client.close() unless session.closed?
         
     | 
| 
      
 143 
     | 
    
         
            +
                        end
         
     | 
| 
      
 144 
     | 
    
         
            +
                    end
         
     | 
| 
      
 145 
     | 
    
         
            +
                end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                # within the block supplied to {#connect} this will return the
         
     | 
| 
      
 148 
     | 
    
         
            +
                # current ZK client
         
     | 
| 
      
 149 
     | 
    
         
            +
                def self.current
         
     | 
| 
      
 150 
     | 
    
         
            +
                    #We'd use if key? here if strand supported it
         
     | 
| 
      
 151 
     | 
    
         
            +
                    @binding_storage.current[CURRENT].last if @binding_storage.current[CURRENT]
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                class WatchEvent
         
     | 
| 
      
 155 
     | 
    
         
            +
                    attr_reader :watch_types
         
     | 
| 
      
 156 
     | 
    
         
            +
                    def initialize(watch_types)
         
     | 
| 
      
 157 
     | 
    
         
            +
                        @watch_types = watch_types
         
     | 
| 
      
 158 
     | 
    
         
            +
                    end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                    include Enumeration
         
     | 
| 
      
 161 
     | 
    
         
            +
                    enum :none,(-1),[]
         
     | 
| 
      
 162 
     | 
    
         
            +
                    enum :node_created, 1, [ :data, :exists ]
         
     | 
| 
      
 163 
     | 
    
         
            +
                    enum :node_deleted, 2, [ :data, :children ]
         
     | 
| 
      
 164 
     | 
    
         
            +
                    enum :node_data_changed, 3, [ :data, :exists ]
         
     | 
| 
      
 165 
     | 
    
         
            +
                    enum :node_children_changed, 4, [ :children ]
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                class KeeperState
         
     | 
| 
      
 169 
     | 
    
         
            +
                    include Enumeration
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                    enum :disconnected, 0
         
     | 
| 
      
 172 
     | 
    
         
            +
                    enum :connected, 3
         
     | 
| 
      
 173 
     | 
    
         
            +
                    enum :auth_failed, 4
         
     | 
| 
      
 174 
     | 
    
         
            +
                    enum :expired, (-112)
         
     | 
| 
      
 175 
     | 
    
         
            +
                end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                # @abstract.
         
     | 
| 
      
 179 
     | 
    
         
            +
                class Watcher
         
     | 
| 
      
 180 
     | 
    
         
            +
                    # @param [KeeperState] state representing the session state
         
     | 
| 
      
 181 
     | 
    
         
            +
                    #    (:connected, :disconnected, :auth_failed, :session_expired)
         
     | 
| 
      
 182 
     | 
    
         
            +
                    # @param [String] path the effected path
         
     | 
| 
      
 183 
     | 
    
         
            +
                    # @param [WatchEvent] event the event that triggered the watch 
         
     | 
| 
      
 184 
     | 
    
         
            +
                    def process_watch(state,path,event)
         
     | 
| 
      
 185 
     | 
    
         
            +
                    end
         
     | 
| 
      
 186 
     | 
    
         
            +
                end
         
     | 
| 
      
 187 
     | 
    
         
            +
                
         
     | 
| 
      
 188 
     | 
    
         
            +
                #@private
         
     | 
| 
      
 189 
     | 
    
         
            +
                module Operations
         
     | 
| 
      
 190 
     | 
    
         
            +
                    CREATE_OPTS = { :sequential => 2, :ephemeral => 1 }
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                    private
         
     | 
| 
      
 193 
     | 
    
         
            +
                    def op_create(path,data,acl,*modeopts,&callback)
         
     | 
| 
      
 194 
     | 
    
         
            +
                        return synchronous_call(:op_create,path,data,acl,*modeopts)[0] unless block_given?
         
     | 
| 
      
 195 
     | 
    
         
            +
                        flags = modeopts.inject(0) { |flags,opt|
         
     | 
| 
      
 196 
     | 
    
         
            +
                            raise ArgumentError, "Unknown create option #{ opt }" unless CREATE_OPTS.has_key?(opt)
         
     | 
| 
      
 197 
     | 
    
         
            +
                            flags | CREATE_OPTS[opt]
         
     | 
| 
      
 198 
     | 
    
         
            +
                        }
         
     | 
| 
      
 199 
     | 
    
         
            +
                        path = session.chroot(path) 
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                        req = Proto::CreateRequest.new(:path => path, :data => data, :acl => acl, :flags => flags)
         
     | 
| 
      
 202 
     | 
    
         
            +
                        queue_request(req,:create,1,Proto::CreateResponse) do | response |
         
     | 
| 
      
 203 
     | 
    
         
            +
                            callback.call(session.unchroot(response.path)) if callback
         
     | 
| 
      
 204 
     | 
    
         
            +
                        end
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
                    end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                    def op_set(path,data,version,&callback)
         
     | 
| 
      
 209 
     | 
    
         
            +
                        return synchronous_call(:op_set,path,data,version)[0] unless block_given?
         
     | 
| 
      
 210 
     | 
    
         
            +
                        path = session.chroot(path) 
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                        req = Proto::SetDataRequest.new(:path => path, :data => data, :version => version)
         
     | 
| 
      
 213 
     | 
    
         
            +
                        queue_request(req,:set_data,5,Proto::SetDataResponse) do | response |
         
     | 
| 
      
 214 
     | 
    
         
            +
                            callback.call( response.stat ) if callback
         
     | 
| 
      
 215 
     | 
    
         
            +
                        end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                    end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                    def op_delete(path,version,&callback)
         
     | 
| 
      
 220 
     | 
    
         
            +
                        return synchronous_call(:op_delete,path,version) unless block_given?
         
     | 
| 
      
 221 
     | 
    
         
            +
                        path = session.chroot(path) 
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                        req = Proto::DeleteRequest.new(:path => path, :version => version)
         
     | 
| 
      
 224 
     | 
    
         
            +
                        queue_request(req,:delete,2) do |response|
         
     | 
| 
      
 225 
     | 
    
         
            +
                            callback.call() if callback
         
     | 
| 
      
 226 
     | 
    
         
            +
                        end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                    end
         
     | 
| 
      
 229 
     | 
    
         
            +
             
     | 
| 
      
 230 
     | 
    
         
            +
                    def op_check(path,version,&callback)
         
     | 
| 
      
 231 
     | 
    
         
            +
                        return synchronous_call(:op_check,path,version) unless block_given?
         
     | 
| 
      
 232 
     | 
    
         
            +
                        path = session.chroot(path)
         
     | 
| 
      
 233 
     | 
    
         
            +
                        req = Proto::CheckVersionRequest.new(:path => path, :version => version)
         
     | 
| 
      
 234 
     | 
    
         
            +
                        queue_request(req,:check,13) do |response|
         
     | 
| 
      
 235 
     | 
    
         
            +
                            callback.call() if callback
         
     | 
| 
      
 236 
     | 
    
         
            +
                        end
         
     | 
| 
      
 237 
     | 
    
         
            +
                    end
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
                end
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
                # Client API
         
     | 
| 
      
 242 
     | 
    
         
            +
                # 
         
     | 
| 
      
 243 
     | 
    
         
            +
                # All calls operate asynchronously or synchronously based on whether a block is supplied
         
     | 
| 
      
 244 
     | 
    
         
            +
                #
         
     | 
| 
      
 245 
     | 
    
         
            +
                # Without a block, requests are executed synchronously and either return results directly or raise
         
     | 
| 
      
 246 
     | 
    
         
            +
                # a {Error}
         
     | 
| 
      
 247 
     | 
    
         
            +
                #
         
     | 
| 
      
 248 
     | 
    
         
            +
                # With a block, the request returns immediately with a {AsyncOp}. When the server responds the
         
     | 
| 
      
 249 
     | 
    
         
            +
                # block is passed the results. Errors will be sent to an error callback if registered on the {AsyncOp}
         
     | 
| 
      
 250 
     | 
    
         
            +
                #
         
     | 
| 
      
 251 
     | 
    
         
            +
                # Requests that take a watch argument can be passed either...
         
     | 
| 
      
 252 
     | 
    
         
            +
                #   * An object that quacks like a {Watcher} 
         
     | 
| 
      
 253 
     | 
    
         
            +
                #   * A Proc will be invoked with arguments state, path, event
         
     | 
| 
      
 254 
     | 
    
         
            +
                #   * The literal value "true" refers to the default watcher registered with the session
         
     | 
| 
      
 255 
     | 
    
         
            +
                #
         
     | 
| 
      
 256 
     | 
    
         
            +
                # Registered watches will be fired exactly once for a given path with either the expected event
         
     | 
| 
      
 257 
     | 
    
         
            +
                # or with state :expired and event :none when the session is finalised 
         
     | 
| 
      
 258 
     | 
    
         
            +
                class Client
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                    include Operations
         
     | 
| 
      
 261 
     | 
    
         
            +
                    # @api private
         
     | 
| 
      
 262 
     | 
    
         
            +
                    # See {::ZooKeeper.connect}
         
     | 
| 
      
 263 
     | 
    
         
            +
                    def initialize(binding)
         
     | 
| 
      
 264 
     | 
    
         
            +
                        @binding = binding
         
     | 
| 
      
 265 
     | 
    
         
            +
                    end
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
      
 267 
     | 
    
         
            +
                    # Session timeout, initially as supplied, but once connected is the negotiated
         
     | 
| 
      
 268 
     | 
    
         
            +
                    # timeout with the server. 
         
     | 
| 
      
 269 
     | 
    
         
            +
                    def timeout
         
     | 
| 
      
 270 
     | 
    
         
            +
                        @binding.session.timeout
         
     | 
| 
      
 271 
     | 
    
         
            +
                    end
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
                    # The currently registered default watcher
         
     | 
| 
      
 274 
     | 
    
         
            +
                    def watcher 
         
     | 
| 
      
 275 
     | 
    
         
            +
                        @binding.session.watcher
         
     | 
| 
      
 276 
     | 
    
         
            +
                    end
         
     | 
| 
      
 277 
     | 
    
         
            +
             
     | 
| 
      
 278 
     | 
    
         
            +
                    # Assign the watcher to the session. This watcher will receive session connect/disconnect/expired
         
     | 
| 
      
 279 
     | 
    
         
            +
                    # events as well as any path based watches registered to the API calls using the literal value "true"
         
     | 
| 
      
 280 
     | 
    
         
            +
                    # @param [Watcher|Proc] watcher
         
     | 
| 
      
 281 
     | 
    
         
            +
                    def watcher=(watcher)
         
     | 
| 
      
 282 
     | 
    
         
            +
                        @binding.session.watcher=watcher
         
     | 
| 
      
 283 
     | 
    
         
            +
                    end
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
                    # Retrieve the list of children at the given path
         
     | 
| 
      
 286 
     | 
    
         
            +
                    # @overload children(path,watch=nil)
         
     | 
| 
      
 287 
     | 
    
         
            +
                    #    @param [String] path 
         
     | 
| 
      
 288 
     | 
    
         
            +
                    #    @param [Watcher] if supplied sets a child watch on the given path
         
     | 
| 
      
 289 
     | 
    
         
            +
                    #    @return [Data::Stat,Array<String>] stat,children stat of path and the list of child nodes
         
     | 
| 
      
 290 
     | 
    
         
            +
                    #    @raise [Error] 
         
     | 
| 
      
 291 
     | 
    
         
            +
                    # @overload children(path,watch=nil)
         
     | 
| 
      
 292 
     | 
    
         
            +
                    #    @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 293 
     | 
    
         
            +
                    #    @yieldparam [Data::Stat]  stat current stat of path
         
     | 
| 
      
 294 
     | 
    
         
            +
                    #    @yieldparam [Array<String>] children the list of child nodes at path 
         
     | 
| 
      
 295 
     | 
    
         
            +
                    def children(path,watch=nil,&callback)
         
     | 
| 
      
 296 
     | 
    
         
            +
                        return synchronous_call(:children,path,watch) unless block_given?
         
     | 
| 
      
 297 
     | 
    
         
            +
                        path = chroot(path) 
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
                        req = Proto::GetChildren2Request.new(:path => path, :watch => watch)
         
     | 
| 
      
 300 
     | 
    
         
            +
                        queue_request(req,:get_children2,12,Proto::GetChildren2Response,:children,watch) do | response |
         
     | 
| 
      
 301 
     | 
    
         
            +
                            callback.call(response.stat, response.children.to_a)
         
     | 
| 
      
 302 
     | 
    
         
            +
                        end
         
     | 
| 
      
 303 
     | 
    
         
            +
                    end
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
                    # Create a node
         
     | 
| 
      
 306 
     | 
    
         
            +
                    # @overload create(path,data,acl,*modeopts)
         
     | 
| 
      
 307 
     | 
    
         
            +
                    #   Synchronous style
         
     | 
| 
      
 308 
     | 
    
         
            +
                    #   @param [String] path the base name of the path to create
         
     | 
| 
      
 309 
     | 
    
         
            +
                    #   @param [String] data the content to store at path
         
     | 
| 
      
 310 
     | 
    
         
            +
                    #   @param [Data::ACL] acl the access control list to apply to the new node
         
     | 
| 
      
 311 
     | 
    
         
            +
                    #   @param [Symbol,...] modeopts combination of :sequential, :emphemeral
         
     | 
| 
      
 312 
     | 
    
         
            +
                    #   @return [String] the created path, only different if :sequential is requested 
         
     | 
| 
      
 313 
     | 
    
         
            +
                    #   @raise [Error]     
         
     | 
| 
      
 314 
     | 
    
         
            +
                    # @overload create(path,data,acl,*modeopts)
         
     | 
| 
      
 315 
     | 
    
         
            +
                    #   @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 316 
     | 
    
         
            +
                    #   @yieldparam [String] path the created path
         
     | 
| 
      
 317 
     | 
    
         
            +
                    def create(path,data,acl,*modeopts,&callback)
         
     | 
| 
      
 318 
     | 
    
         
            +
                        op_create(path,data,acl,*modeopts,&callback)
         
     | 
| 
      
 319 
     | 
    
         
            +
                    end
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
                    # Retrieve data
         
     | 
| 
      
 322 
     | 
    
         
            +
                    # @overload get(path,watch=nil)
         
     | 
| 
      
 323 
     | 
    
         
            +
                    #   @param [String] path
         
     | 
| 
      
 324 
     | 
    
         
            +
                    #   @param [Watcher] watch optional data watch to set on this path
         
     | 
| 
      
 325 
     | 
    
         
            +
                    #   @return [Data::Stat,String] stat,data at path 
         
     | 
| 
      
 326 
     | 
    
         
            +
                    #   @raise [Error]
         
     | 
| 
      
 327 
     | 
    
         
            +
                    # @overload get(path,watch=nil)
         
     | 
| 
      
 328 
     | 
    
         
            +
                    #   @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 329 
     | 
    
         
            +
                    #   @yieldparam [Data::Stat] stat Stat of the path
         
     | 
| 
      
 330 
     | 
    
         
            +
                    #   @yieldparam [String] data Content at path
         
     | 
| 
      
 331 
     | 
    
         
            +
                    def get(path,watch=nil,&blk)
         
     | 
| 
      
 332 
     | 
    
         
            +
                        return synchronous_call(:get,path,watch) unless block_given?
         
     | 
| 
      
 333 
     | 
    
         
            +
                        path = chroot(path) 
         
     | 
| 
      
 334 
     | 
    
         
            +
             
     | 
| 
      
 335 
     | 
    
         
            +
                        req = Proto::GetDataRequest.new(:path => path, :watch => watch)
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
                        queue_request(req,:get,4,Proto::GetDataResponse,:data,watch) do | response |
         
     | 
| 
      
 338 
     | 
    
         
            +
                            blk.call( response.stat, response.data.to_s)
         
     | 
| 
      
 339 
     | 
    
         
            +
                        end
         
     | 
| 
      
 340 
     | 
    
         
            +
                    end
         
     | 
| 
      
 341 
     | 
    
         
            +
             
     | 
| 
      
 342 
     | 
    
         
            +
                    # Retrieve the {Data::Stat} of a path, or nil if the path does not exist
         
     | 
| 
      
 343 
     | 
    
         
            +
                    # @overload exists(path,watch=nil)
         
     | 
| 
      
 344 
     | 
    
         
            +
                    #   @param [String] path
         
     | 
| 
      
 345 
     | 
    
         
            +
                    #   @param [Watcher] wath optional exists watch to set on this path
         
     | 
| 
      
 346 
     | 
    
         
            +
                    #   @return [Data::Stat] Stat of the path or nil if the path does not exist
         
     | 
| 
      
 347 
     | 
    
         
            +
                    #   @raise [Error]
         
     | 
| 
      
 348 
     | 
    
         
            +
                    # @overload exists(path,watch=nil)
         
     | 
| 
      
 349 
     | 
    
         
            +
                    #   @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 350 
     | 
    
         
            +
                    #   @yieldparam [Data:Stat] stat Stat of the path or nil if the path did not exist
         
     | 
| 
      
 351 
     | 
    
         
            +
                    def exists(path,watch=nil,&blk)
         
     | 
| 
      
 352 
     | 
    
         
            +
                        return synchronous_call(:exists,path,watch)[0] unless block_given?
         
     | 
| 
      
 353 
     | 
    
         
            +
                        path = chroot(path) 
         
     | 
| 
      
 354 
     | 
    
         
            +
             
     | 
| 
      
 355 
     | 
    
         
            +
                        req = Proto::ExistsRequest.new(:path => path, :watch => watch)
         
     | 
| 
      
 356 
     | 
    
         
            +
                        queue_request(req,:exists,3,Proto::ExistsResponse,:exists,watch,ExistsPacket) do | response |
         
     | 
| 
      
 357 
     | 
    
         
            +
                            blk.call( response.nil? ? nil : response.stat )
         
     | 
| 
      
 358 
     | 
    
         
            +
                        end
         
     | 
| 
      
 359 
     | 
    
         
            +
                    end
         
     | 
| 
      
 360 
     | 
    
         
            +
                    alias :exists? :exists
         
     | 
| 
      
 361 
     | 
    
         
            +
                    alias :stat :exists
         
     | 
| 
      
 362 
     | 
    
         
            +
             
     | 
| 
      
 363 
     | 
    
         
            +
                    # Delete path
         
     | 
| 
      
 364 
     | 
    
         
            +
                    # @overload delete(path,version)
         
     | 
| 
      
 365 
     | 
    
         
            +
                    #    @param [String] path
         
     | 
| 
      
 366 
     | 
    
         
            +
                    #    @param [FixNum] version the expected version to be deleted (-1 to match any version)
         
     | 
| 
      
 367 
     | 
    
         
            +
                    #    @return 
         
     | 
| 
      
 368 
     | 
    
         
            +
                    #    @raise [Error]
         
     | 
| 
      
 369 
     | 
    
         
            +
                    # @overload delete(path,version)
         
     | 
| 
      
 370 
     | 
    
         
            +
                    #    @return [AsyncOp]
         
     | 
| 
      
 371 
     | 
    
         
            +
                    #    @yield  [] callback invoked if delete is successful
         
     | 
| 
      
 372 
     | 
    
         
            +
                    def delete(path,version,&callback)
         
     | 
| 
      
 373 
     | 
    
         
            +
                        op_delete(path,version,&callback)
         
     | 
| 
      
 374 
     | 
    
         
            +
                    end
         
     | 
| 
      
 375 
     | 
    
         
            +
             
     | 
| 
      
 376 
     | 
    
         
            +
                    # Set Data
         
     | 
| 
      
 377 
     | 
    
         
            +
                    # @overload set(path,data,version)
         
     | 
| 
      
 378 
     | 
    
         
            +
                    #    @param [String] path
         
     | 
| 
      
 379 
     | 
    
         
            +
                    #    @param [String] data content to set at path
         
     | 
| 
      
 380 
     | 
    
         
            +
                    #    @param [Fixnum] version expected current version at path
         
     | 
| 
      
 381 
     | 
    
         
            +
                    #    @return [Data::Stat] new stat of path (ie new version)
         
     | 
| 
      
 382 
     | 
    
         
            +
                    #    @raise [Error]
         
     | 
| 
      
 383 
     | 
    
         
            +
                    # @overload set(path,data,version)
         
     | 
| 
      
 384 
     | 
    
         
            +
                    #    @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 385 
     | 
    
         
            +
                    #    @yieldparam [Data::Stat] stat new stat of path
         
     | 
| 
      
 386 
     | 
    
         
            +
                    def set(path,data,version,&callback)
         
     | 
| 
      
 387 
     | 
    
         
            +
                        op_set(path,data,version,&callback)
         
     | 
| 
      
 388 
     | 
    
         
            +
                    end
         
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
      
 390 
     | 
    
         
            +
                    # Get ACl
         
     | 
| 
      
 391 
     | 
    
         
            +
                    # @overload get_acl(path)
         
     | 
| 
      
 392 
     | 
    
         
            +
                    #    @param [String] path
         
     | 
| 
      
 393 
     | 
    
         
            +
                    #    @return [Array<Data::ACL>] list of acls applying to path
         
     | 
| 
      
 394 
     | 
    
         
            +
                    #    @raise [Error]
         
     | 
| 
      
 395 
     | 
    
         
            +
                    # @overload get_acl(path)
         
     | 
| 
      
 396 
     | 
    
         
            +
                    #   @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 397 
     | 
    
         
            +
                    #   @yieldparam [Array<Data::ACL>] list of acls applying to path
         
     | 
| 
      
 398 
     | 
    
         
            +
                    def get_acl(path,&blk)
         
     | 
| 
      
 399 
     | 
    
         
            +
                        return synchronous_call(:get_acl,path)[0] unless block_given?
         
     | 
| 
      
 400 
     | 
    
         
            +
                        path = chroot(path) 
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
                        req = Proto::GetACLRequest.new(:path => path)
         
     | 
| 
      
 403 
     | 
    
         
            +
                        queue_request(req,:get_acl,6,Proto::GetACLResponse) do | response |
         
     | 
| 
      
 404 
     | 
    
         
            +
                            blk.call( response.acl )
         
     | 
| 
      
 405 
     | 
    
         
            +
                        end
         
     | 
| 
      
 406 
     | 
    
         
            +
                    end
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
                    # Set ACL
         
     | 
| 
      
 409 
     | 
    
         
            +
                    # @overload set_acl(path,acl,version)
         
     | 
| 
      
 410 
     | 
    
         
            +
                    #    @param [String] path
         
     | 
| 
      
 411 
     | 
    
         
            +
                    #    @param [Array<Data::ACL>] acl list of acls for path
         
     | 
| 
      
 412 
     | 
    
         
            +
                    #    @param [Fixnum] version expected current version
         
     | 
| 
      
 413 
     | 
    
         
            +
                    #    @return Data::Stat new stat for path if successful
         
     | 
| 
      
 414 
     | 
    
         
            +
                    #    @raise [Error]
         
     | 
| 
      
 415 
     | 
    
         
            +
                    # @overload set_acl(path,acl,version)
         
     | 
| 
      
 416 
     | 
    
         
            +
                    #    @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 417 
     | 
    
         
            +
                    #    @yieldparam [Data::Stat] new stat for path if successful
         
     | 
| 
      
 418 
     | 
    
         
            +
                    def set_acl(path,acl,version,&blk)
         
     | 
| 
      
 419 
     | 
    
         
            +
                        return synchronous_call(:set_acl,acl,version)[0] unless block_given?
         
     | 
| 
      
 420 
     | 
    
         
            +
                        path = chroot(path) 
         
     | 
| 
      
 421 
     | 
    
         
            +
             
     | 
| 
      
 422 
     | 
    
         
            +
                        req = Proto::SetACLRequest.new(:path => path, :acl => acl, :version => version)
         
     | 
| 
      
 423 
     | 
    
         
            +
                        queue_request(req,:set_acl,7,Proto::SetACLResponse) do | response |
         
     | 
| 
      
 424 
     | 
    
         
            +
                            blk.call( response.stat )
         
     | 
| 
      
 425 
     | 
    
         
            +
                        end
         
     | 
| 
      
 426 
     | 
    
         
            +
             
     | 
| 
      
 427 
     | 
    
         
            +
                    end
         
     | 
| 
      
 428 
     | 
    
         
            +
             
     | 
| 
      
 429 
     | 
    
         
            +
                    # Synchronise path between session and leader
         
     | 
| 
      
 430 
     | 
    
         
            +
                    # @overload sync(path)
         
     | 
| 
      
 431 
     | 
    
         
            +
                    #   @param [String] path
         
     | 
| 
      
 432 
     | 
    
         
            +
                    #   @return [String] path
         
     | 
| 
      
 433 
     | 
    
         
            +
                    #   @raise [Error]
         
     | 
| 
      
 434 
     | 
    
         
            +
                    # @overload sync(path)
         
     | 
| 
      
 435 
     | 
    
         
            +
                    #   @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 436 
     | 
    
         
            +
                    #   @yieldparam [String] path 
         
     | 
| 
      
 437 
     | 
    
         
            +
                    def sync(path,&blk)
         
     | 
| 
      
 438 
     | 
    
         
            +
                        return synchronous_call(:sync,path)[0] unless block_given?
         
     | 
| 
      
 439 
     | 
    
         
            +
                        path = chroot(path) 
         
     | 
| 
      
 440 
     | 
    
         
            +
                        req = Proto::SyncRequest.new(:path => path)
         
     | 
| 
      
 441 
     | 
    
         
            +
                        queue_request(req,:sync,9,Proto::SyncResponse) do | response |
         
     | 
| 
      
 442 
     | 
    
         
            +
                            blk.call(unchroot(response.path))
         
     | 
| 
      
 443 
     | 
    
         
            +
                        end
         
     | 
| 
      
 444 
     | 
    
         
            +
                    end
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
                    # Close the session
         
     | 
| 
      
 447 
     | 
    
         
            +
                    # @overload close()
         
     | 
| 
      
 448 
     | 
    
         
            +
                    #    @raise [Error]
         
     | 
| 
      
 449 
     | 
    
         
            +
                    # @overload close()
         
     | 
| 
      
 450 
     | 
    
         
            +
                    #    @return [AsyncOp] asynchronous operation
         
     | 
| 
      
 451 
     | 
    
         
            +
                    #    @yield [] callback invoked when session is closed 
         
     | 
| 
      
 452 
     | 
    
         
            +
                    def close(&blk)
         
     | 
| 
      
 453 
     | 
    
         
            +
                        return synchronous_call(:close) unless block_given?
         
     | 
| 
      
 454 
     | 
    
         
            +
                        @binding.close(&blk)
         
     | 
| 
      
 455 
     | 
    
         
            +
                    end
         
     | 
| 
      
 456 
     | 
    
         
            +
             
     | 
| 
      
 457 
     | 
    
         
            +
                    # @api private
         
     | 
| 
      
 458 
     | 
    
         
            +
                    # See {#transaction} 
         
     | 
| 
      
 459 
     | 
    
         
            +
                    def multi(ops,&callback)
         
     | 
| 
      
 460 
     | 
    
         
            +
                        return synchronous_call(:multi,ops) unless block_given?
         
     | 
| 
      
 461 
     | 
    
         
            +
             
     | 
| 
      
 462 
     | 
    
         
            +
                        req = Proto::MultiRequest.new()
         
     | 
| 
      
 463 
     | 
    
         
            +
             
     | 
| 
      
 464 
     | 
    
         
            +
                        ops.each do |op|
         
     | 
| 
      
 465 
     | 
    
         
            +
                            req.requests << { :header => { :_type => op.opcode, :done => false, :err=> 0 }, :request => op.request }
         
     | 
| 
      
 466 
     | 
    
         
            +
                        end
         
     | 
| 
      
 467 
     | 
    
         
            +
             
     | 
| 
      
 468 
     | 
    
         
            +
                        req.requests << { :header => { :_type => -1 , :done => true, :err => -1 } }
         
     | 
| 
      
 469 
     | 
    
         
            +
             
     | 
| 
      
 470 
     | 
    
         
            +
                        logger.debug("Multi #{req}")
         
     | 
| 
      
 471 
     | 
    
         
            +
                        queue_request(req,:multi,14,Proto::MultiResponse) do |response|
         
     | 
| 
      
 472 
     | 
    
         
            +
                            exception = nil  
         
     | 
| 
      
 473 
     | 
    
         
            +
                            response.responses.each_with_index() do |multi_response,index|
         
     | 
| 
      
 474 
     | 
    
         
            +
                                next if multi_response.done?
         
     | 
| 
      
 475 
     | 
    
         
            +
                                op = ops[index]
         
     | 
| 
      
 476 
     | 
    
         
            +
                                if multi_response.header._type == -1
         
     | 
| 
      
 477 
     | 
    
         
            +
                                    errcode = multi_response.header.err.to_i
         
     | 
| 
      
 478 
     | 
    
         
            +
                                    if (errcode != 0)
         
     | 
| 
      
 479 
     | 
    
         
            +
                                        exception = Error.lookup(errcode).exception("Transaction error for op ##{index} - #{op.op} (#{op.path})")
         
     | 
| 
      
 480 
     | 
    
         
            +
                                        #TODO just raises the first exception
         
     | 
| 
      
 481 
     | 
    
         
            +
                                        raise exception
         
     | 
| 
      
 482 
     | 
    
         
            +
                                    end
         
     | 
| 
      
 483 
     | 
    
         
            +
                                else
         
     | 
| 
      
 484 
     | 
    
         
            +
                                    callback_args = if multi_response.has_response? then [ multi_response.response ] else [] end
         
     | 
| 
      
 485 
     | 
    
         
            +
                                    ops[index].callback.call(*callback_args)
         
     | 
| 
      
 486 
     | 
    
         
            +
                                end
         
     | 
| 
      
 487 
     | 
    
         
            +
                            end
         
     | 
| 
      
 488 
     | 
    
         
            +
                        end
         
     | 
| 
      
 489 
     | 
    
         
            +
                    end
         
     | 
| 
      
 490 
     | 
    
         
            +
             
     | 
| 
      
 491 
     | 
    
         
            +
                    # Perform multiple operations in a transaction
         
     | 
| 
      
 492 
     | 
    
         
            +
                    # @overload transaction()
         
     | 
| 
      
 493 
     | 
    
         
            +
                    #   @return [Transaction]
         
     | 
| 
      
 494 
     | 
    
         
            +
                    # @overload transaction(&block)
         
     | 
| 
      
 495 
     | 
    
         
            +
                    #  Execute the supplied block and commit the transaction (synchronously)
         
     | 
| 
      
 496 
     | 
    
         
            +
                    #  @yieldparam [Transaction] txn
         
     | 
| 
      
 497 
     | 
    
         
            +
                    def transaction(&block)
         
     | 
| 
      
 498 
     | 
    
         
            +
                        txn = Transaction.new(self,session)
         
     | 
| 
      
 499 
     | 
    
         
            +
                        return txn unless block_given?
         
     | 
| 
      
 500 
     | 
    
         
            +
             
     | 
| 
      
 501 
     | 
    
         
            +
                        yield txn
         
     | 
| 
      
 502 
     | 
    
         
            +
                        txn.commit
         
     | 
| 
      
 503 
     | 
    
         
            +
                    end
         
     | 
| 
      
 504 
     | 
    
         
            +
                    private
         
     | 
| 
      
 505 
     | 
    
         
            +
             
     | 
| 
      
 506 
     | 
    
         
            +
                    def session
         
     | 
| 
      
 507 
     | 
    
         
            +
                        @binding.session
         
     | 
| 
      
 508 
     | 
    
         
            +
                    end
         
     | 
| 
      
 509 
     | 
    
         
            +
             
     | 
| 
      
 510 
     | 
    
         
            +
                    def synchronous_call(method,*args)
         
     | 
| 
      
 511 
     | 
    
         
            +
                        op = self.send(method,*args) do |*results|
         
     | 
| 
      
 512 
     | 
    
         
            +
                            results 
         
     | 
| 
      
 513 
     | 
    
         
            +
                        end
         
     | 
| 
      
 514 
     | 
    
         
            +
                        op.backtrace = op.backtrace[2..-1] if op.backtrace
         
     | 
| 
      
 515 
     | 
    
         
            +
             
     | 
| 
      
 516 
     | 
    
         
            +
                        op.value
         
     | 
| 
      
 517 
     | 
    
         
            +
                    end
         
     | 
| 
      
 518 
     | 
    
         
            +
             
     | 
| 
      
 519 
     | 
    
         
            +
                    def queue_request(*args,&blk)
         
     | 
| 
      
 520 
     | 
    
         
            +
                        op = @binding.queue_request(*args,&blk)
         
     | 
| 
      
 521 
     | 
    
         
            +
                        op.backtrace = caller[1..-1]
         
     | 
| 
      
 522 
     | 
    
         
            +
                        op
         
     | 
| 
      
 523 
     | 
    
         
            +
                    end
         
     | 
| 
      
 524 
     | 
    
         
            +
             
     | 
| 
      
 525 
     | 
    
         
            +
                    def chroot(path)
         
     | 
| 
      
 526 
     | 
    
         
            +
                        session.chroot(path)
         
     | 
| 
      
 527 
     | 
    
         
            +
                    end
         
     | 
| 
      
 528 
     | 
    
         
            +
             
     | 
| 
      
 529 
     | 
    
         
            +
                    def unchroot(path)
         
     | 
| 
      
 530 
     | 
    
         
            +
                        session.unchroot(path)
         
     | 
| 
      
 531 
     | 
    
         
            +
                    end
         
     | 
| 
      
 532 
     | 
    
         
            +
             
     | 
| 
      
 533 
     | 
    
         
            +
                end
         
     | 
| 
      
 534 
     | 
    
         
            +
             
     | 
| 
      
 535 
     | 
    
         
            +
                # Collects zookeeper operations to execute as a single transaction
         
     | 
| 
      
 536 
     | 
    
         
            +
                #
         
     | 
| 
      
 537 
     | 
    
         
            +
                # The builder methods {#create} {#delete} {#check} {#set} all take
         
     | 
| 
      
 538 
     | 
    
         
            +
                # an optional callback block that will be executed if the {#commit} succeeds.
         
     | 
| 
      
 539 
     | 
    
         
            +
                # 
         
     | 
| 
      
 540 
     | 
    
         
            +
                # If the transaction fails none of these callbacks will be executed.
         
     | 
| 
      
 541 
     | 
    
         
            +
                class Transaction
         
     | 
| 
      
 542 
     | 
    
         
            +
                    include Operations
         
     | 
| 
      
 543 
     | 
    
         
            +
                    #:nodoc
         
     | 
| 
      
 544 
     | 
    
         
            +
                    def initialize(client,session)
         
     | 
| 
      
 545 
     | 
    
         
            +
                        @client = client
         
     | 
| 
      
 546 
     | 
    
         
            +
                        @session = session
         
     | 
| 
      
 547 
     | 
    
         
            +
                        @ops = []
         
     | 
| 
      
 548 
     | 
    
         
            +
                    end
         
     | 
| 
      
 549 
     | 
    
         
            +
             
     | 
| 
      
 550 
     | 
    
         
            +
             
     | 
| 
      
 551 
     | 
    
         
            +
                    # Create a node
         
     | 
| 
      
 552 
     | 
    
         
            +
                    #   @param [String] path the base name of the path to create
         
     | 
| 
      
 553 
     | 
    
         
            +
                    #   @param [String] data the content to store at path
         
     | 
| 
      
 554 
     | 
    
         
            +
                    #   @param [Data::ACL] acl the access control list to apply to the new node
         
     | 
| 
      
 555 
     | 
    
         
            +
                    #   @param [Symbol,...] modeopts combination of :sequential, :emphemeral
         
     | 
| 
      
 556 
     | 
    
         
            +
                    #   @yieldparam [String] path the created path
         
     | 
| 
      
 557 
     | 
    
         
            +
                    def create(path,data,acl,*modeopts,&callback)
         
     | 
| 
      
 558 
     | 
    
         
            +
                        op_create(path,data,acl,*modeopts,&callback)
         
     | 
| 
      
 559 
     | 
    
         
            +
                    end
         
     | 
| 
      
 560 
     | 
    
         
            +
                    
         
     | 
| 
      
 561 
     | 
    
         
            +
                    # Delete path
         
     | 
| 
      
 562 
     | 
    
         
            +
                    #    @param [String] path
         
     | 
| 
      
 563 
     | 
    
         
            +
                    #    @param [FixNum] version the expected version to be deleted (-1 to match any version)
         
     | 
| 
      
 564 
     | 
    
         
            +
                    #    @yield  [] callback invoked if delete is successful
         
     | 
| 
      
 565 
     | 
    
         
            +
                    def delete(path,version,&callback)
         
     | 
| 
      
 566 
     | 
    
         
            +
                        op_delete(path,version,&callback)
         
     | 
| 
      
 567 
     | 
    
         
            +
                    end
         
     | 
| 
      
 568 
     | 
    
         
            +
             
     | 
| 
      
 569 
     | 
    
         
            +
                    # Set Data
         
     | 
| 
      
 570 
     | 
    
         
            +
                    #    @param [String] path
         
     | 
| 
      
 571 
     | 
    
         
            +
                    #    @param [String] data content to set at path
         
     | 
| 
      
 572 
     | 
    
         
            +
                    #    @param [Fixnum] version expected current version at path or -1 for any version
         
     | 
| 
      
 573 
     | 
    
         
            +
                    #    @yieldparam [Data::Stat] stat new stat of path
         
     | 
| 
      
 574 
     | 
    
         
            +
                    def set(path,data,version,&callback)
         
     | 
| 
      
 575 
     | 
    
         
            +
                        op_set(path,data,version,&callback)
         
     | 
| 
      
 576 
     | 
    
         
            +
                    end
         
     | 
| 
      
 577 
     | 
    
         
            +
             
     | 
| 
      
 578 
     | 
    
         
            +
                    # Check Version
         
     | 
| 
      
 579 
     | 
    
         
            +
                    def check(path,version,&callback)
         
     | 
| 
      
 580 
     | 
    
         
            +
                        op_check(path,version,&callback)
         
     | 
| 
      
 581 
     | 
    
         
            +
                    end
         
     | 
| 
      
 582 
     | 
    
         
            +
             
     | 
| 
      
 583 
     | 
    
         
            +
                    # Commit the transaction
         
     | 
| 
      
 584 
     | 
    
         
            +
                    # @overload commit()
         
     | 
| 
      
 585 
     | 
    
         
            +
                    #   Synchronously commit the transaction
         
     | 
| 
      
 586 
     | 
    
         
            +
                    #   @raise [Error] if the transaction failed
         
     | 
| 
      
 587 
     | 
    
         
            +
                    # @overload commit(&callback)
         
     | 
| 
      
 588 
     | 
    
         
            +
                    #   @return [AsyncOp] captures the result of the asynchronous operation
         
     | 
| 
      
 589 
     | 
    
         
            +
                    #   @yield [] callback invoked if transaction is successful
         
     | 
| 
      
 590 
     | 
    
         
            +
                    def commit(&callback)
         
     | 
| 
      
 591 
     | 
    
         
            +
                        op = client.multi(ops,&callback)
         
     | 
| 
      
 592 
     | 
    
         
            +
                    end
         
     | 
| 
      
 593 
     | 
    
         
            +
             
     | 
| 
      
 594 
     | 
    
         
            +
                    private
         
     | 
| 
      
 595 
     | 
    
         
            +
                    attr_reader :client, :session, :ops
         
     | 
| 
      
 596 
     | 
    
         
            +
                    
         
     | 
| 
      
 597 
     | 
    
         
            +
                    def queue_request(request,op,opcode,response=nil,&callback)
         
     | 
| 
      
 598 
     | 
    
         
            +
                        ops << Operation.new(op,opcode,request,response,callback)
         
     | 
| 
      
 599 
     | 
    
         
            +
                    end
         
     | 
| 
      
 600 
     | 
    
         
            +
             
     | 
| 
      
 601 
     | 
    
         
            +
                    #Just ensure we have an empty block
         
     | 
| 
      
 602 
     | 
    
         
            +
                    def synchronous_call(method,*args)
         
     | 
| 
      
 603 
     | 
    
         
            +
                        self.send(method,*args) { |*results| results  }
         
     | 
| 
      
 604 
     | 
    
         
            +
                    end
         
     | 
| 
      
 605 
     | 
    
         
            +
                end
         
     | 
| 
      
 606 
     | 
    
         
            +
             
     | 
| 
      
 607 
     | 
    
         
            +
            end
         
     | 
| 
      
 608 
     | 
    
         
            +
             
     |