zookeeper 0.9.4 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
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