zookeeper 0.9.4 → 1.0.0.beta.1

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.
Files changed (44) hide show
  1. data/.dotfiles/rvmrc +1 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +22 -0
  5. data/CHANGELOG +38 -5
  6. data/Gemfile +18 -1
  7. data/README.markdown +2 -0
  8. data/Rakefile +47 -109
  9. data/ext/c_zookeeper.rb +10 -6
  10. data/ext/zookeeper_base.rb +23 -11
  11. data/ext/zookeeper_c.c +14 -10
  12. data/java/{zookeeper_base.rb → java_base.rb} +13 -12
  13. data/lib/zookeeper.rb +32 -244
  14. data/lib/zookeeper/acls.rb +17 -13
  15. data/lib/zookeeper/callbacks.rb +28 -11
  16. data/lib/zookeeper/client.rb +30 -0
  17. data/lib/zookeeper/client_methods.rb +241 -0
  18. data/lib/zookeeper/common.rb +13 -12
  19. data/lib/zookeeper/common/queue_with_pipe.rb +3 -7
  20. data/lib/zookeeper/compatibility.rb +135 -0
  21. data/lib/zookeeper/constants.rb +35 -1
  22. data/lib/zookeeper/em_client.rb +1 -1
  23. data/lib/zookeeper/exceptions.rb +117 -93
  24. data/lib/zookeeper/rake_tasks.rb +165 -0
  25. data/lib/zookeeper/stat.rb +16 -16
  26. data/lib/zookeeper/version.rb +2 -4
  27. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  28. data/spec/c_zookeeper_spec.rb +10 -9
  29. data/spec/chrooted_connection_spec.rb +2 -2
  30. data/spec/default_watcher_spec.rb +4 -4
  31. data/spec/em_spec.rb +1 -1
  32. data/spec/shared/connection_examples.rb +52 -37
  33. data/spec/spec_helper.rb +22 -84
  34. data/spec/support/00_spawn_zookeeper.rb +20 -0
  35. data/spec/support/zookeeper_spec_helpers.rb +84 -0
  36. data/spec/zookeeper_spec.rb +1 -1
  37. metadata +47 -34
  38. data/examples/cloud_config.rb +0 -125
  39. data/test/test_basic.rb +0 -37
  40. data/test/test_callback1.rb +0 -36
  41. data/test/test_close.rb +0 -16
  42. data/test/test_esoteric.rb +0 -7
  43. data/test/test_watcher1.rb +0 -56
  44. data/test/test_watcher2.rb +0 -52
@@ -8,16 +8,19 @@ gem 'slyphon-zookeeper_jar', '= 3.3.5'
8
8
  require 'log4j'
9
9
  require 'zookeeper_jar'
10
10
 
11
+
12
+ # XXX: reindent this WHOLE FILE later
13
+ module Zookeeper
14
+
11
15
  # The low-level wrapper-specific methods for the Java lib,
12
16
  # subclassed by the top-level Zookeeper class
13
- class ZookeeperBase
17
+ class JavaBase
14
18
  include Java
15
- include ZookeeperCommon
16
- include ZookeeperConstants
17
- include ZookeeperCallbacks
18
- include ZookeeperExceptions
19
- include ZookeeperACLs
20
- include ZookeeperStat
19
+ include Zookeeper::Common
20
+ include Zookeeper::Constants
21
+ include Zookeeper::Callbacks
22
+ include Zookeeper::Exceptions
23
+ include Zookeeper::ACLs
21
24
 
22
25
  JZK = org.apache.zookeeper
23
26
  JZKD = org.apache.zookeeper.data
@@ -26,8 +29,6 @@ class ZookeeperBase
26
29
  ANY_VERSION = -1
27
30
  DEFAULT_SESSION_TIMEOUT = 10_000
28
31
 
29
- ZKRB_GLOBAL_CB_REQ = -1 unless defined?(ZKRB_GLOBAL_CB_REQ)
30
-
31
32
  JZKD::Stat.class_eval do
32
33
  MEMBERS = [:version, :czxid, :mzxid, :ctime, :mtime, :cversion, :aversion, :ephemeralOwner, :dataLength, :numChildren, :pzxid]
33
34
  def to_hash
@@ -43,7 +44,7 @@ class ZookeeperBase
43
44
 
44
45
  JZKD::ACL.class_eval do
45
46
  def self.from_ruby_acl(acl)
46
- raise TypeError, "acl must be a ZookeeperACLs::ACL not #{acl.inspect}" unless acl.kind_of?(ZookeeperACLs::ACL)
47
+ raise TypeError, "acl must be a Zookeeper::ACLs::ACL not #{acl.inspect}" unless acl.kind_of?(Zookeeper::ACLs::ACL)
47
48
  id = org.apache.zookeeper.data.Id.new(acl.id.scheme.to_s, acl.id.id.to_s)
48
49
  new(acl.perms.to_i, id)
49
50
  end
@@ -158,7 +159,7 @@ class ZookeeperBase
158
159
 
159
160
  def initialize(event_queue)
160
161
  @event_queue = event_queue
161
- super(ZookeeperBase::ZKRB_GLOBAL_CB_REQ)
162
+ super(Zookeeper::Constants::ZKRB_GLOBAL_CB_REQ)
162
163
  end
163
164
 
164
165
  def process(event)
@@ -473,5 +474,5 @@ class ZookeeperBase
473
474
  orig_jzk.close if orig_jzk
474
475
  end
475
476
  end
476
-
477
+ end
477
478
 
@@ -5,23 +5,27 @@ require 'monitor'
5
5
  require 'forwardable'
6
6
  require 'logger'
7
7
 
8
- require 'zookeeper/common'
9
- require 'zookeeper/constants'
10
- require 'zookeeper/callbacks'
11
- require 'zookeeper/exceptions'
12
- require 'zookeeper/stat'
13
- require 'zookeeper/acls'
8
+ require 'backports'
14
9
 
15
-
16
- if defined?(::JRUBY_VERSION)
17
- $LOAD_PATH.unshift(File.expand_path('../java', File.dirname(__FILE__))).uniq!
18
- else
19
- $LOAD_PATH.unshift(File.expand_path('../ext', File.dirname(__FILE__))).uniq!
10
+ module Zookeeper
11
+ # establishes the namespace
20
12
  end
21
13
 
22
- require 'zookeeper_base'
14
+ require_relative 'zookeeper/acls'
15
+ require_relative 'zookeeper/constants'
16
+ require_relative 'zookeeper/exceptions'
17
+ require_relative 'zookeeper/common'
18
+ require_relative 'zookeeper/callbacks'
19
+ require_relative 'zookeeper/stat'
20
+ require_relative 'zookeeper/client_methods'
21
+
22
+ # ok, now we construct the client
23
+
24
+ require_relative 'zookeeper/client'
25
+
26
+ module Zookeeper
27
+ include Constants
23
28
 
24
- class Zookeeper < ZookeeperBase
25
29
  unless defined?(@@logger)
26
30
  @@logger = Logger.new($stderr).tap { |l| l.level = Logger::ERROR }
27
31
  end
@@ -34,167 +38,20 @@ class Zookeeper < ZookeeperBase
34
38
  @@logger = logger
35
39
  end
36
40
 
37
- def reopen(timeout=10, watcher=nil)
38
- warn "WARN: ZookeeperBase#reopen watcher argument is now ignored" if watcher
39
- super
40
- end
41
-
42
- def initialize(host, timeout=10, watcher=nil)
43
- super
44
- end
45
-
46
- def get(options = {})
47
- assert_open
48
- assert_supported_keys(options, [:path, :watcher, :watcher_context, :callback, :callback_context])
49
- assert_required_keys(options, [:path])
50
-
51
- req_id = setup_call(:get, options)
52
- rc, value, stat = super(req_id, options[:path], options[:callback], options[:watcher])
53
-
54
- rv = { :req_id => req_id, :rc => rc }
55
- options[:callback] ? rv : rv.merge(:data => value, :stat => Stat.new(stat))
56
- end
57
-
58
- def set(options = {})
59
- assert_open
60
- assert_supported_keys(options, [:path, :data, :version, :callback, :callback_context])
61
- assert_required_keys(options, [:path])
62
- assert_valid_data_size!(options[:data])
63
- options[:version] ||= -1
64
-
65
- req_id = setup_call(:set, options)
66
- rc, stat = super(req_id, options[:path], options[:data], options[:callback], options[:version])
67
-
68
- rv = { :req_id => req_id, :rc => rc }
69
- options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
70
- end
71
-
72
- def get_children(options = {})
73
- assert_open
74
- assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
75
- assert_required_keys(options, [:path])
76
-
77
- req_id = setup_call(:get_children, options)
78
- rc, children, stat = super(req_id, options[:path], options[:callback], options[:watcher])
79
-
80
- rv = { :req_id => req_id, :rc => rc }
81
- options[:callback] ? rv : rv.merge(:children => children, :stat => Stat.new(stat))
82
- end
83
-
84
- def stat(options = {})
85
- assert_open
86
- assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
87
- assert_required_keys(options, [:path])
88
-
89
- req_id = setup_call(:stat, options)
90
- rc, stat = exists(req_id, options[:path], options[:callback], options[:watcher])
91
-
92
- rv = { :req_id => req_id, :rc => rc }
93
- options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
94
- end
95
-
96
- def create(options = {})
97
- assert_open
98
- assert_supported_keys(options, [:path, :data, :acl, :ephemeral, :sequence, :callback, :callback_context])
99
- assert_required_keys(options, [:path])
100
- assert_valid_data_size!(options[:data])
101
-
102
- flags = 0
103
- flags |= ZOO_EPHEMERAL if options[:ephemeral]
104
- flags |= ZOO_SEQUENCE if options[:sequence]
105
-
106
- options[:acl] ||= ZOO_OPEN_ACL_UNSAFE
107
-
108
- req_id = setup_call(:create, options)
109
- rc, newpath = super(req_id, options[:path], options[:data], options[:callback], options[:acl], flags)
110
-
111
- rv = { :req_id => req_id, :rc => rc }
112
- options[:callback] ? rv : rv.merge(:path => newpath)
113
- end
114
-
115
- def delete(options = {})
116
- assert_open
117
- assert_supported_keys(options, [:path, :version, :callback, :callback_context])
118
- assert_required_keys(options, [:path])
119
- options[:version] ||= -1
120
-
121
- req_id = setup_call(:delete, options)
122
- rc = super(req_id, options[:path], options[:version], options[:callback])
123
-
124
- { :req_id => req_id, :rc => rc }
125
- end
126
-
127
- # this method is *only* asynchronous
128
- #
129
- # @note There is a discrepancy between the zkc and java versions. zkc takes
130
- # a string_callback_t, java takes a VoidCallback. You should most likely use
131
- # the ZookeeperCallbacks::VoidCallback and not rely on the string value.
132
- #
133
- def sync(options = {})
134
- assert_open
135
- assert_supported_keys(options, [:path, :callback, :callback_context])
136
- assert_required_keys(options, [:path, :callback])
137
-
138
- req_id = setup_call(:sync, options)
139
-
140
- rc = super(req_id, options[:path]) # we don't pass options[:callback] here as this method is *always* async
141
-
142
- { :req_id => req_id, :rc => rc }
143
- end
144
-
145
- def set_acl(options = {})
146
- assert_open
147
- assert_supported_keys(options, [:path, :acl, :version, :callback, :callback_context])
148
- assert_required_keys(options, [:path, :acl])
149
- options[:version] ||= -1
150
-
151
- req_id = setup_call(:set_acl, options)
152
- rc = super(req_id, options[:path], options[:acl], options[:callback], options[:version])
153
-
154
- { :req_id => req_id, :rc => rc }
155
- end
156
-
157
- def get_acl(options = {})
158
- assert_open
159
- assert_supported_keys(options, [:path, :callback, :callback_context])
160
- assert_required_keys(options, [:path])
161
-
162
- req_id = setup_call(:get_acl, options)
163
- rc, acls, stat = super(req_id, options[:path], options[:callback])
164
-
165
- rv = { :req_id => req_id, :rc => rc }
166
- options[:callback] ? rv : rv.merge(:acl => acls, :stat => Stat.new(stat))
167
- end
168
-
169
- # close this client and any underyling connections
170
- def close
171
- super
172
- end
173
-
174
- def state
175
- super
176
- end
177
-
178
- def connected?
179
- super
41
+ # @private
42
+ def self.deprecation_warnings?
43
+ @deprecation_warnings = true if @deprecation_warnings.nil?
180
44
  end
181
45
 
182
- def connecting?
183
- super
46
+ # set this to false to mute Zookeeper related deprecation warnings...
47
+ # __AT YOUR PERIL__
48
+ def self.deprecation_warnings=(v)
49
+ @deprecation_warnings = v
184
50
  end
185
51
 
186
- def associating?
187
- super
188
- end
189
-
190
- # There are some operations that are dangerous in the context of the event
191
- # dispatch thread (because they would block further event delivery). This
192
- # method allows clients to know if they're currently executing in the context of an
193
- # event.
194
- #
195
- # @returns [true,false] true if the current thread is the event dispatch thread
196
- def event_dispatch_thread?
197
- super
52
+ # @private
53
+ def self.deprecation_warning(warning)
54
+ Kernel.warn(warning) if deprecation_warnings?
198
55
  end
199
56
 
200
57
  # for expert use only. set the underlying debug level for the C layer, has no
@@ -202,14 +59,14 @@ class Zookeeper < ZookeeperBase
202
59
  #
203
60
  # @private
204
61
  def self.set_debug_level(val)
205
- if defined?(::CZookeeper)
62
+ if defined?(CZookeeper)
206
63
  CZookeeper.set_debug_level(val.to_i)
207
64
  end
208
65
  end
209
66
 
210
67
  # @private
211
68
  def self.get_debug_level
212
- if defined?(::CZookeeper)
69
+ if defined?(CZookeeper)
213
70
  CZookeeper.get_debug_level
214
71
  end
215
72
  end
@@ -221,77 +78,8 @@ class Zookeeper < ZookeeperBase
221
78
  # @private
222
79
  alias :debug_level :get_debug_level
223
80
  end
224
-
225
- # DEPRECATED: use the class-level method instead
226
- def set_debug_level(val)
227
- super
228
- end
229
-
230
- # has the underlying connection been closed?
231
- def closed?
232
- super
233
- end
234
-
235
- # is the event delivery system running?
236
- def running?
237
- super
238
- end
239
-
240
- # return the session id of the current connection as an Fixnum
241
- def session_id
242
- super
243
- end
244
-
245
- # Return the passwd portion of this connection's credentials as a String
246
- def session_passwd
247
- super
248
- end
249
-
250
- protected
251
- # used during shutdown, awaken the event delivery thread if it's blocked
252
- # waiting for the next event
253
- def wake_event_loop!
254
- super
255
- end
256
-
257
- # starts the event delivery subsystem going. after calling this method, running? will be true
258
- def setup_dispatch_thread!
259
- super
260
- end
261
-
262
- # TODO: describe what this does
263
- def get_default_global_watcher
264
- super
265
- end
266
-
267
- def logger
268
- Zookeeper.logger
269
- end
270
-
271
- def assert_valid_data_size!(data)
272
- return if data.nil?
273
-
274
- data = data.to_s
275
- if data.length >= 1048576 # one megabyte
276
- raise ZookeeperException::DataTooLargeException, "data must be smaller than 1 MiB, your data starts with: #{data[0..32].inspect}"
277
- end
278
- nil
279
- end
280
-
281
- private
282
- # TODO: Sanitize user mistakes by unregistering watchers from ops that
283
- # don't return ZOK (except wexists)? Make users clean up after themselves for now.
284
- #
285
- # XXX: is this dead code?
286
- def unregister_watcher(req_id)
287
- @mutex.synchronize {
288
- @watcher_reqs.delete(req_id)
289
- }
290
- end
291
-
292
- # must be supplied by parent class impl.
293
- def assert_open
294
- super
295
- end
296
81
  end
297
82
 
83
+ # just for first test, get rid of this soon
84
+ require_relative 'zookeeper/compatibility'
85
+
@@ -1,4 +1,5 @@
1
- module ZookeeperACLs
1
+ module Zookeeper
2
+ module ACLs
2
3
  class Id
3
4
  attr_reader :scheme, :id
4
5
  def initialize(hash)
@@ -24,17 +25,20 @@ module ZookeeperACLs
24
25
  end
25
26
  end
26
27
 
27
- ZOO_PERM_READ = 0
28
- ZOO_PERM_WRITE = 1
29
- ZOO_PERM_CREATE = 2
30
- ZOO_PERM_DELETE = 4
31
- ZOO_PERM_ADMIN = 8
32
- ZOO_PERM_ALL = ZOO_PERM_READ | ZOO_PERM_WRITE | ZOO_PERM_CREATE | ZOO_PERM_DELETE | ZOO_PERM_ADMIN
33
-
34
- ZOO_ANYONE_ID_UNSAFE = Id.new(:scheme => "world", :id => "anyone")
35
- ZOO_AUTH_IDS = Id.new(:scheme => "auth", :id => "")
28
+ module Constants
29
+ ZOO_PERM_READ = 0
30
+ ZOO_PERM_WRITE = 1
31
+ ZOO_PERM_CREATE = 2
32
+ ZOO_PERM_DELETE = 4
33
+ ZOO_PERM_ADMIN = 8
34
+ ZOO_PERM_ALL = ZOO_PERM_READ | ZOO_PERM_WRITE | ZOO_PERM_CREATE | ZOO_PERM_DELETE | ZOO_PERM_ADMIN
35
+
36
+ ZOO_ANYONE_ID_UNSAFE = Id.new(:scheme => "world", :id => "anyone")
37
+ ZOO_AUTH_IDS = Id.new(:scheme => "auth", :id => "")
36
38
 
37
- ZOO_OPEN_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_ANYONE_ID_UNSAFE)]
38
- ZOO_READ_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_READ, :id => ZOO_ANYONE_ID_UNSAFE)]
39
- ZOO_CREATOR_ALL_ACL = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_AUTH_IDS)]
39
+ ZOO_OPEN_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_ANYONE_ID_UNSAFE)]
40
+ ZOO_READ_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_READ, :id => ZOO_ANYONE_ID_UNSAFE)]
41
+ ZOO_CREATOR_ALL_ACL = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_AUTH_IDS)]
42
+ end
43
+ end
40
44
  end
@@ -1,7 +1,24 @@
1
- module ZookeeperCallbacks
2
- class Callback
1
+ module Zookeeper
2
+ module Callbacks
3
+ class Base
3
4
  attr_reader :proc, :completed, :context
4
5
 
6
+ # allows for easier construction of a user callback block that will be
7
+ # called with the callback object itself as an argument.
8
+ #
9
+ # @example
10
+ #
11
+ # Base.create do |cb|
12
+ # puts "watcher callback called with argument: #{cb.inspect}"
13
+ # end
14
+ #
15
+ # "watcher callback called with argument: #<Zookeeper::Callbacks::Base:0x1018a3958 @state=3, @type=1, ...>"
16
+ #
17
+ #
18
+ def self.create
19
+ cb_inst = new { yield cb_inst }
20
+ end
21
+
5
22
  def initialize
6
23
  @completed = false
7
24
  @proc = Proc.new do |hash|
@@ -12,7 +29,6 @@ module ZookeeperCallbacks
12
29
  end
13
30
 
14
31
  def call(*args)
15
- # puts "call passed #{args.inspect}"
16
32
  @proc.call(*args)
17
33
  end
18
34
 
@@ -24,8 +40,8 @@ module ZookeeperCallbacks
24
40
  @context = nil
25
41
  end
26
42
  end
27
-
28
- class WatcherCallback < Callback
43
+
44
+ class WatcherCallback < Base
29
45
  ## wexists, awexists, wget, awget, wget_children, awget_children
30
46
  attr_reader :type, :state, :path
31
47
 
@@ -34,7 +50,7 @@ module ZookeeperCallbacks
34
50
  end
35
51
  end
36
52
 
37
- class DataCallback < Callback
53
+ class DataCallback < Base
38
54
  ## aget, awget
39
55
  attr_reader :return_code, :data, :stat
40
56
 
@@ -43,7 +59,7 @@ module ZookeeperCallbacks
43
59
  end
44
60
  end
45
61
 
46
- class StringCallback < Callback
62
+ class StringCallback < Base
47
63
  ## acreate, async
48
64
  attr_reader :return_code, :string, :context
49
65
 
@@ -54,7 +70,7 @@ module ZookeeperCallbacks
54
70
  end
55
71
  end
56
72
 
57
- class StringsCallback < Callback
73
+ class StringsCallback < Base
58
74
  ## aget_children, awget_children
59
75
  attr_reader :return_code, :children, :stat
60
76
 
@@ -63,7 +79,7 @@ module ZookeeperCallbacks
63
79
  end
64
80
  end
65
81
 
66
- class StatCallback < Callback
82
+ class StatCallback < Base
67
83
  ## aset, aexists, awexists
68
84
  attr_reader :return_code, :stat
69
85
 
@@ -72,7 +88,7 @@ module ZookeeperCallbacks
72
88
  end
73
89
  end
74
90
 
75
- class VoidCallback < Callback
91
+ class VoidCallback < Base
76
92
  ## adelete, aset_acl, add_auth
77
93
  attr_reader :return_code
78
94
 
@@ -81,7 +97,7 @@ module ZookeeperCallbacks
81
97
  end
82
98
  end
83
99
 
84
- class ACLCallback < Callback
100
+ class ACLCallback < Base
85
101
  ## aget_acl
86
102
  attr_reader :return_code, :acl, :stat
87
103
  def initialize_context(hash)
@@ -89,3 +105,4 @@ module ZookeeperCallbacks
89
105
  end
90
106
  end
91
107
  end
108
+ end