zookeeper 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,89 @@
1
+ module ZookeeperCallbacks
2
+ class Callback
3
+ attr_reader :proc, :completed, :context
4
+
5
+ def initialize
6
+ @completed = false
7
+ @proc = Proc.new do |hash|
8
+ initialize_context(hash)
9
+ yield if block_given?
10
+ @completed = true
11
+ end
12
+ end
13
+
14
+ def call(*args)
15
+ puts "call passed #{args.inspect}"
16
+ @proc.call(*args)
17
+ end
18
+
19
+ def completed?
20
+ @completed
21
+ end
22
+
23
+ def initialize_context(hash)
24
+ @context = nil
25
+ end
26
+ end
27
+
28
+ class WatcherCallback < Callback
29
+ ## wexists, awexists, wget, awget, wget_children, awget_children
30
+ attr_reader :type, :state, :path
31
+
32
+ def initialize_context(hash)
33
+ @type, @state, @path, @context = hash[:type], hash[:state], hash[:path], hash[:context]
34
+ end
35
+ end
36
+
37
+ class DataCallback < Callback
38
+ ## aget, awget
39
+ attr_reader :return_code, :data, :stat
40
+
41
+ def initialize_context(hash)
42
+ @return_code, @data, @stat, @context = hash[:rc], hash[:data], hash[:stat], hash[:context]
43
+ end
44
+ end
45
+
46
+ class StringCallback < Callback
47
+ ## acreate, async
48
+ attr_reader :return_code, :path
49
+
50
+ def initialize_context(hash)
51
+ @return_code, @path, @context = hash[:rc], hash[:path], hash[:context]
52
+ end
53
+ end
54
+
55
+ class StringsCallback < Callback
56
+ ## aget_children, awget_children
57
+ attr_reader :return_code, :children, :stat
58
+
59
+ def initialize_context(hash)
60
+ @return_code, @children, @stat, @context = hash[:rc], hash[:children], hash[:stat], hash[:context]
61
+ end
62
+ end
63
+
64
+ class StatCallback < Callback
65
+ ## aset, aexists, awexists
66
+ attr_reader :return_code, :stat
67
+
68
+ def initialize_context(hash)
69
+ @return_code, @stat, @context = hash[:rc], hash[:stat], hash[:context]
70
+ end
71
+ end
72
+
73
+ class VoidCallback < Callback
74
+ ## adelete, aset_acl, add_auth
75
+ attr_reader :return_code
76
+
77
+ def initialize_context(hash)
78
+ @return_code, @context = hash[:rc], hash[:context]
79
+ end
80
+ end
81
+
82
+ class ACLCallback < Callback
83
+ ## aget_acl
84
+ attr_reader :return_code, :acl, :stat
85
+ def initialize_context(hash)
86
+ @return_code, @acl, @stat, @context = hash[:rc], hash[:acl], hash[:stat], hash[:context]
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,54 @@
1
+ module ZookeeperConstants
2
+ # file type masks
3
+ ZOO_EPHEMERAL = 1
4
+ ZOO_SEQUENCE = 2
5
+
6
+ # session state
7
+ ZOO_EXPIRED_SESSION_STATE = -112
8
+ ZOO_AUTH_FAILED_STATE = -113
9
+ ZOO_CONNECTING_STATE = 1
10
+ ZOO_ASSOCIATING_STATE = 2
11
+ ZOO_CONNECTED_STATE = 3
12
+
13
+ # watch types
14
+ ZOO_CREATED_EVENT = 1
15
+ ZOO_DELETED_EVENT = 2
16
+ ZOO_CHANGED_EVENT = 3
17
+ ZOO_CHILD_EVENT = 4
18
+ ZOO_SESSION_EVENT = -1
19
+ ZOO_NOTWATCHING_EVENT = -2
20
+
21
+ def print_events
22
+ puts "ZK events:"
23
+ ZookeeperConstants::constants.each do |c|
24
+ puts "\t #{c}" if c =~ /^ZOO..*EVENT$/
25
+ end
26
+ end
27
+
28
+ def print_states
29
+ puts "ZK states:"
30
+ ZookeeperConstants::constants.each do |c|
31
+ puts "\t #{c}" if c =~ /^ZOO..*STATE$/
32
+ end
33
+ end
34
+
35
+ def event_by_value(v)
36
+ return unless v
37
+ ZookeeperConstants::constants.each do |c|
38
+ next unless c =~ /^ZOO..*EVENT$/
39
+ if eval("ZookeeperConstants::#{c}") == v
40
+ return c
41
+ end
42
+ end
43
+ end
44
+
45
+ def state_by_value(v)
46
+ return unless v
47
+ ZookeeperConstants::constants.each do |c|
48
+ next unless c =~ /^ZOO..*STATE$/
49
+ if eval("ZookeeperConstants::#{c}") == v
50
+ return c
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,91 @@
1
+ module ZookeeperExceptions
2
+ # exceptions/errors
3
+ ZOK = 0
4
+ ZSYSTEMERROR = -1
5
+ ZRUNTIMEINCONSISTENCY = -2
6
+ ZDATAINCONSISTENCY = -3
7
+ ZCONNECTIONLOSS = -4
8
+ ZMARSHALLINGERROR = -5
9
+ ZUNIMPLEMENTED = -6
10
+ ZOPERATIONTIMEOUT = -7
11
+ ZBADARGUMENTS = -8
12
+ ZINVALIDSTATE = -9
13
+
14
+ # api errors
15
+ ZAPIERROR = -100
16
+ ZNONODE = -101
17
+ ZNOAUTH = -102
18
+ ZBADVERSION = -103
19
+ ZNOCHILDRENFOREPHEMERALS = -108
20
+ ZNODEEXISTS = -110
21
+ ZNOTEMPTY = -111
22
+ ZSESSIONEXPIRED = -112
23
+ ZINVALIDCALLBACK = -113
24
+ ZINVALIDACL = -114
25
+ ZAUTHFAILED = -115
26
+ ZCLOSING = -116
27
+ ZNOTHING = -117
28
+ ZSESSIONMOVED = -118
29
+
30
+ class ZookeeperException < Exception
31
+ class EverythingOk < ZookeeperException; end
32
+ class SystemError < ZookeeperException; end
33
+ class RunTimeInconsistency < ZookeeperException; end
34
+ class DataInconsistency < ZookeeperException; end
35
+ class ConnectionLoss < ZookeeperException; end
36
+ class MarshallingError < ZookeeperException; end
37
+ class Unimplemented < ZookeeperException; end
38
+ class OperationTimeOut < ZookeeperException; end
39
+ class BadArguments < ZookeeperException; end
40
+ class InvalidState < ZookeeperException; end
41
+ class ApiError < ZookeeperException; end
42
+ class NoNode < ZookeeperException; end
43
+ class NoAuth < ZookeeperException; end
44
+ class BadVersion < ZookeeperException; end
45
+ class NoChildrenForEphemerals < ZookeeperException; end
46
+ class NodeExists < ZookeeperException; end
47
+ class NotEmpty < ZookeeperException; end
48
+ class SessionExpired < ZookeeperException; end
49
+ class InvalidCallback < ZookeeperException; end
50
+ class InvalidACL < ZookeeperException; end
51
+ class AuthFailed < ZookeeperException; end
52
+ class Closing < ZookeeperException; end
53
+ class Nothing < ZookeeperException; end
54
+ class SessionMoved < ZookeeperException; end
55
+
56
+ def self.by_code(code)
57
+ case code
58
+ when ZOK then EverythingOk
59
+ when ZSYSTEMERROR then SystemError
60
+ when ZRUNTIMEINCONSISTENCY then RunTimeInconsistency
61
+ when ZDATAINCONSISTENCY then DataInconsistency
62
+ when ZCONNECTIONLOSS then ConnectionLoss
63
+ when ZMARSHALLINGERROR then MarshallingError
64
+ when ZUNIMPLEMENTED then Unimplemented
65
+ when ZOPERATIONTIMEOUT then OperationTimeOut
66
+ when ZBADARGUMENTS then BadArguments
67
+ when ZINVALIDSTATE then InvalidState
68
+ when ZAPIERROR then ApiError
69
+ when ZNONODE then NoNode
70
+ when ZNOAUTH then NoAuth
71
+ when ZBADVERSION then BadVersion
72
+ when ZNOCHILDRENFOREPHEMERALS then NoChildrenForEphemerals
73
+ when ZNODEEXISTS then NodeExists
74
+ when ZNOTEMPTY then NotEmpty
75
+ when ZSESSIONEXPIRED then SessionExpired
76
+ when ZINVALIDCALLBACK then InvalidCallback
77
+ when ZINVALIDACL then InvalidACL
78
+ when ZAUTHFAILED then AuthFailed
79
+ when ZCLOSING then Closing
80
+ when ZNOTHING then Nothing
81
+ when ZSESSIONMOVED then SessionMoved
82
+ else Exception.new("no exception defined for code #{code}")
83
+ end
84
+ end
85
+
86
+ def self.raise_on_error(code)
87
+ exc = self.by_code(code)
88
+ raise exc unless exc == EverythingOk
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,12 @@
1
+ module ZookeeperStat
2
+ class Stat
3
+ attr_reader :version, :exists
4
+ def initialize(val)
5
+ @exists = !!val
6
+ @czxid, @mzxid, @ctime, @mtime, @version, @cversion, @aversion,
7
+ @ephemeralOwner, @dataLength, @numChildren, @pzxid = val if val.is_a?(Array)
8
+ val.each { |k,v| instance_variable_set "@#{k}", v } if val.is_a?(Hash)
9
+ raise ArgumentError unless (val.is_a?(Hash) or val.is_a?(Array) or val == nil)
10
+ end
11
+ end
12
+ end
data/lib/zookeeper.rb CHANGED
@@ -1,78 +1,234 @@
1
1
  # Ruby wrapper for the Zookeeper C API
2
- # Phillip Pearson <pp@myelin.co.nz>
3
2
 
4
3
  require 'zookeeper_c'
5
-
6
- class ZkStat
7
- attr_reader :version
8
- def initialize(ary)
9
- @czxid, @mzxid, @ctime, @mtime, @version, @cversion, @aversion, @ephemeralOwner = ary
10
- end
11
- end
4
+ require 'thread'
5
+ require 'zookeeper/callbacks'
6
+ require 'zookeeper/constants'
7
+ require 'zookeeper/exceptions'
8
+ require 'zookeeper/stat'
9
+ require 'zookeeper/acls'
12
10
 
13
11
  class Zookeeper < CZookeeper
14
- def initialize(host)
12
+ include ZookeeperCallbacks
13
+ include ZookeeperConstants
14
+ include ZookeeperExceptions
15
+ include ZookeeperACLs
16
+ include ZookeeperStat
17
+
18
+ ZKRB_GLOBAL_CB_REQ = -1
19
+
20
+ # debug levels
21
+ ZOO_LOG_LEVEL_ERROR = 1
22
+ ZOO_LOG_LEVEL_WARN = 2
23
+ ZOO_LOG_LEVEL_INFO = 3
24
+ ZOO_LOG_LEVEL_DEBUG = 4
25
+
26
+ def initialize(host, timeout = 10)
27
+ @watcher_reqs = { ZKRB_GLOBAL_CB_REQ => { :watcher => get_default_global_watcher } }
28
+ @completion_reqs = {}
29
+ @req_mutex = Mutex.new
30
+ @current_req_id = 1
15
31
  super(host)
16
- @watchers = {} # path => [ block, block, ... ]
32
+
33
+ if timeout > 0
34
+ time_to_stop = Time.now + timeout
35
+ until state == Zookeeper::ZOO_CONNECTED_STATE
36
+ break if Time.now > time_to_stop
37
+ sleep 0.1
38
+ end
39
+
40
+ return nil if state != Zookeeper::ZOO_CONNECTED_STATE
41
+ end
42
+
43
+ setup_dispatch_thread!
17
44
  end
45
+
46
+ public
47
+ def get(options = {})
48
+ assert_supported_keys(options, [:path, :watcher, :watcher_context, :callback, :callback_context])
49
+ assert_required_keys(options, [:path])
50
+
51
+ req_id = setup_call(options)
52
+ rc, value, stat = super(req_id, options[:path], options[:callback], options[:watcher])
18
53
 
19
- def exists(path, &blk)
20
- (@watchers[path] ||= []) << blk if blk
21
- ZkStat.new(super(path, !!blk))
54
+ rv = { :req_id => req_id, :rc => rc }
55
+ options[:callback] ? rv : rv.merge(:data => value, :stat => Stat.new(stat))
22
56
  end
57
+
58
+ def set(options = {})
59
+ assert_supported_keys(options, [:path, :data, :version, :callback, :callback_context])
60
+ assert_required_keys(options, [:path])
61
+ options[:version] ||= -1
23
62
 
24
- def stat(path, &blk)
25
- exists(path, &blk)
26
- rescue Zookeeper::NoNodeError
27
- nil
63
+ req_id = setup_call(options)
64
+ rc, stat = super(req_id, options[:path], options[:data], options[:callback], options[:version])
65
+
66
+ rv = { :req_id => req_id, :rc => rc }
67
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
28
68
  end
69
+
70
+ def get_children(options = {})
71
+ assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
72
+ assert_required_keys(options, [:path])
73
+
74
+ req_id = setup_call(options)
75
+ rc, children, stat = super(req_id, options[:path], options[:callback], options[:watcher])
29
76
 
30
- def get(path)
31
- value, stat = super
32
- [value, ZkStat.new(stat)]
77
+ rv = { :req_id => req_id, :rc => rc }
78
+ options[:callback] ? rv : rv.merge(:children => children, :stat => Stat.new(stat))
33
79
  end
34
80
 
35
- def try_acquire(path, value)
36
- # create the parent node if it doesn't exist already
37
- create(path, "lock node", 0) unless stat(path)
81
+ def stat(options = {})
82
+ assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
83
+ assert_required_keys(options, [:path])
84
+
85
+ req_id = setup_call(options)
86
+ rc, stat = exists(req_id, options[:path], options[:callback], options[:watcher])
87
+
88
+ rv = { :req_id => req_id, :rc => rc }
89
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
90
+ end
91
+
92
+ def create(options = {})
93
+ assert_supported_keys(options, [:path, :data, :acl, :ephemeral, :sequence, :callback, :callback_context])
94
+ assert_required_keys(options, [:path])
95
+
96
+ flags = 0
97
+ flags |= ZOO_EPHEMERAL if options[:ephemeral]
98
+ flags |= ZOO_SEQUENCE if options[:sequence]
38
99
 
39
- # attempt to obtain the lock
40
- realpath = create("#{path}/lock-", value, Zookeeper::ZOO_EPHEMERAL | Zookeeper::ZOO_SEQUENCE)
41
- #puts "created lock node #{realpath}"
100
+ options[:acl] ||= ZOO_OPEN_ACL_UNSAFE
101
+
102
+ req_id = setup_call(options)
103
+ rc, newpath = super(req_id, options[:path], options[:data], options[:callback], options[:acl], flags)
104
+
105
+ rv = { :req_id => req_id, :rc => rc }
106
+ options[:callback] ? rv : rv.merge(:path => newpath)
107
+ end
108
+
109
+ def delete(options = {})
110
+ assert_supported_keys(options, [:path, :version, :callback, :callback_context])
111
+ assert_required_keys(options, [:path])
112
+ options[:version] ||= -1
113
+
114
+ req_id = setup_call(options)
115
+ rc = super(req_id, options[:path], options[:version], options[:callback])
116
+
117
+ { :req_id => req_id, :rc => rc }
118
+ end
42
119
 
43
- # see if we got it
44
- serial = /lock-(\d+)$/.match(realpath).captures[0].to_i
45
- have_lock = true
46
- ls(path).each do |child|
47
- if m = /lock-(\d+)$/.match(child)
48
- if m.captures[0].to_i < serial
49
- have_lock = false
50
- break
51
- end
120
+ def set_acl(options = {})
121
+ assert_supported_keys(options, [:path, :acl, :version, :callback, :callback_context])
122
+ assert_required_keys(options, [:path, :acl])
123
+ options[:version] ||= -1
124
+
125
+ req_id = setup_call(options)
126
+ rc = super(req_id, options[:path], options[:acl], options[:callback], options[:version])
127
+
128
+ { :req_id => req_id, :rc => rc }
129
+ end
130
+
131
+ def get_acl(options = {})
132
+ assert_supported_keys(options, [:path, :callback, :callback_context])
133
+ assert_required_keys(options, [:path])
134
+
135
+ req_id = setup_call(options)
136
+ rc, acls, stat = super(req_id, options[:path], options[:callback])
137
+
138
+ rv = { :req_id => req_id, :rc => rc }
139
+ options[:callback] ? rv : rv.merge(:acl => acls, :stat => Stat.new(stat))
140
+ end
141
+
142
+ private
143
+ def setup_dispatch_thread!
144
+ @dispatcher = Thread.new {
145
+ while true do
146
+ dispatch_next_callback
147
+ sleep 0.1
52
148
  end
53
- end
149
+ }
150
+ end
54
151
 
55
- # call block
56
- yield(have_lock)
152
+ def dispatch_next_callback
153
+ hash = get_next_event
154
+ return nil unless hash
155
+
156
+ is_completion = hash.has_key?(:rc)
157
+
158
+ hash[:stat] = Stat.new(hash[:stat]) if hash.has_key?(:stat)
159
+ hash[:acl] = hash[:acl].map { |acl| ACL.new(acl) } if hash[:acl]
160
+
161
+ callback_context = is_completion ? get_completion(hash[:req_id]) : get_watcher(hash[:req_id])
162
+ callback = is_completion ? callback_context[:callback] : callback_context[:watcher]
163
+ hash[:context] = callback_context[:context]
164
+
165
+ # TODO: Eventually enforce derivation from Zookeeper::Callback
166
+ if callback.respond_to?(:call)
167
+ callback.call(hash)
168
+ else
169
+ puts "dispatch_next_callback found non-callback => #{callback.inspect}"
170
+ end
171
+ end
172
+
173
+ def setup_call(opts)
174
+ req_id = nil
175
+ @req_mutex.synchronize {
176
+ req_id = @current_req_id
177
+ @current_req_id += 1
178
+ setup_completion(req_id, opts) if opts[:callback]
179
+ setup_watcher(req_id, opts) if opts[:watcher]
180
+ }
181
+ req_id
182
+ end
183
+
184
+ def setup_watcher(req_id, call_opts)
185
+ @watcher_reqs[req_id] = { :watcher => call_opts[:watcher],
186
+ :context => call_opts[:watcher_context] }
187
+ end
57
188
 
58
- # release the lock
59
- #puts "deleting #{realpath}"
60
- delete(realpath, stat(realpath).version)
189
+ def setup_completion(req_id, call_opts)
190
+ @completion_reqs[req_id] = { :callback => call_opts[:callback],
191
+ :context => call_opts[:callback_context] }
192
+ end
193
+
194
+ def get_watcher(req_id)
195
+ @req_mutex.synchronize {
196
+ req_id != ZKRB_GLOBAL_CB_REQ ? @watcher_reqs.delete(req_id) : @watcher_reqs[req_id]
197
+ }
198
+ end
199
+
200
+ def get_completion(req_id)
201
+ @req_mutex.synchronize { @completion_reqs.delete(req_id) }
61
202
  end
62
203
 
63
- def watcher(type, state, path)
64
- raise Exception("watchers don't work in ruby yet") # ... until I figure out how to synchronize access to the Ruby interpreter
204
+ public
205
+ # TODO: Sanitize user mistakes by unregistering watchers from ops that
206
+ # don't return ZOK (except wexists)? Make users clean up after themselves for now.
207
+ def unregister_watcher(req_id)
208
+ @req_mutex.synchronize {
209
+ @watcher_reqs.delete(req_id)
210
+ }
211
+ end
65
212
 
66
- return unless type == ZOO_SESSION_EVENT
213
+ private
214
+ def get_default_global_watcher
215
+ Proc.new { |args|
216
+ puts "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}"
217
+ }
218
+ end
67
219
 
68
- case state
69
- when ZOO_CONNECTED_STATE
70
- puts "ruby watcher; got an event for #{path}"
220
+ def assert_supported_keys(args, supported)
221
+ unless (args.keys - supported).empty?
222
+ raise ZookeeperException::BadArguments,
223
+ "Supported arguments are: #{supported.inspect}, but arguments #{args.keys.inspect} were supplied instead"
224
+ end
225
+ end
71
226
 
72
- when ZOO_AUTH_FAILED_STATE
73
- raise Exception, "auth failure"
74
- when ZOO_EXPIRED_SESSION_STATE
75
- raise Exception, "session expired"
227
+ def assert_required_keys(args, required)
228
+ unless (required - args.keys).empty?
229
+ raise ZookeeperException::BadArguments,
230
+ "Required arguments are: #{required.inspect}, but only the arguments #{args.keys.inspect} were supplied."
76
231
  end
77
232
  end
78
233
  end
234
+
data/test/test_basic.rb CHANGED
@@ -1,63 +1,40 @@
1
+ require 'rubygems'
2
+
1
3
  HERE = File.expand_path(File.dirname(__FILE__))
2
4
 
3
5
  require "#{HERE}/../lib/zookeeper"
4
6
 
5
7
  z = Zookeeper.new("localhost:2181")
6
8
 
7
- puts "root: #{z.get_children("/").inspect}"
9
+ puts "root: #{z.get_children(:path => "/").inspect}"
8
10
 
9
11
  path = "/testing_node"
10
12
 
11
13
  puts "working with path #{path}"
12
14
 
13
- stat = z.stat(path)
15
+ h = z.stat(:path => path)
16
+ stat = h[:stat]
14
17
  puts "exists? #{stat.inspect}"
15
18
 
16
- unless stat.nil?
17
- z.get_children(path).each do |o|
19
+ if stat.exists
20
+ z.get_children(:path => path)[:children].each do |o|
18
21
  puts " child object: #{o}"
19
22
  end
20
- puts "delete: #{z.delete(path, stat.version).inspect}"
23
+ puts "delete: #{z.delete(:path => path, :version => stat.version).inspect}"
21
24
  end
22
25
 
23
- puts "create: #{z.create(path, "initial value", 0).inspect}"
26
+ puts "create: #{z.create(:path => path, :data => 'initial value').inspect}"
24
27
 
25
- value, stat = z.get(path)
28
+ v = z.get(:path => path)
29
+ value, stat = v[:data], v[:stat]
26
30
  puts "current value #{value}, stat #{stat.inspect}"
27
31
 
28
- puts "set: #{z.set(path, "this is a test", stat.version).inspect}"
32
+ puts "set: #{z.set(:path => path, :data => 'this is a test', :version => stat.version).inspect}"
29
33
 
30
- value, stat = z.get(path)
34
+ v = z.get(:path => path)
35
+ value, stat = v[:data], v[:stat]
31
36
  puts "new value: #{value.inspect} #{stat.inspect}"
32
37
 
33
- puts "delete: #{z.delete(path, stat.version).inspect}"
34
-
35
- begin
36
- puts "exists? #{z.exists(path)}"
37
- raise Exception, "it shouldn't exist"
38
- rescue Zookeeper::NoNodeError
39
- puts "doesn't exist - good, because we just deleted it!"
40
- end
41
-
42
- puts "trying a watcher"
43
- puts z
44
- if s = z.stat("/test"); z.delete("/test", s.version); end
45
- z.create("/test", "foo", 0)
46
- z.exists("/test") do
47
- puts "callback!!!"
48
- end
49
- puts "now changing it"
50
- z.set("/test", "bar", 0)
51
- sleep 1
52
- puts "did the watcher say something?"
53
-
54
- puts "let's try using a lock"
55
- z.try_acquire("/test_lock", "this is the content of the lock file") do |have_lock|
56
- puts have_lock ? "we have the lock!" : "failed to obtain lock :("
57
- if have_lock
58
- puts "sleeping"
59
- sleep 5
60
- end
61
- end
62
- puts "done with locking..."
38
+ puts "delete: #{z.delete(:path => path, :version => stat.version).inspect}"
63
39
 
40
+ puts "exists? #{z.stat(:path => path)[:stat].exists}"
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'zookeeper'
3
+
4
+ def wait_until(timeout=10, &block)
5
+ time_to_stop = Time.now + timeout
6
+ until yield do
7
+ break if Time.now > time_to_stop
8
+ sleep 0.1
9
+ end
10
+ end
11
+
12
+ puts 'Initializing Zookeeper'
13
+
14
+ zk = Zookeeper.new('localhost:2181')
15
+
16
+ if zk.state != Zookeeper::ZOO_CONNECTED_STATE
17
+ puts 'Unable to connect to Zookeeper!'
18
+ Kernel.exit
19
+ end
20
+
21
+ def callback(args)
22
+ puts "CALLBACK EXECUTED, args = #{args.inspect}"
23
+ puts args.return_code == Zookeeper::ZOK ? "TEST PASSED IN CALLBACK" : "TEST FAILED IN CALLBACK"
24
+ end
25
+
26
+ ccb = Zookeeper::VoidCallback.new do
27
+ callback(ccb)
28
+ end
29
+
30
+ resp = zk.create(:path => '/test', :data => "new data", :sequence => true, :callback => ccb)
31
+ puts "#{resp.inspect}"
32
+ puts "TEST FAILED [create]" unless resp[:rc] == Zookeeper::ZOK
33
+
34
+ wait_until { ccb.completed? }
35
+
36
+ puts ccb.completed? ? "TEST PASSED" : "TEST FAILED"
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'zookeeper'
3
+ zk = Zookeeper.new('localhost:2181')
4
+
5
+ puts "get acl #{zk.get_acl(:path => '/').inspect}"
6
+ puts "zerror #{zk.zerror(Zookeeper::ZBADVERSION)}"
7
+