zookeeper 0.9.4-java → 1.0.0.beta.1-java

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 (45) 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/acls.rb +17 -13
  14. data/lib/zookeeper/callbacks.rb +28 -11
  15. data/lib/zookeeper/client.rb +30 -0
  16. data/lib/zookeeper/client_methods.rb +241 -0
  17. data/lib/zookeeper/common/queue_with_pipe.rb +3 -7
  18. data/lib/zookeeper/common.rb +13 -12
  19. data/lib/zookeeper/compatibility.rb +135 -0
  20. data/lib/zookeeper/constants.rb +35 -1
  21. data/lib/zookeeper/em_client.rb +1 -1
  22. data/lib/zookeeper/exceptions.rb +117 -93
  23. data/lib/zookeeper/rake_tasks.rb +165 -0
  24. data/lib/zookeeper/stat.rb +16 -16
  25. data/lib/zookeeper/version.rb +2 -4
  26. data/lib/zookeeper.rb +32 -244
  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. data/zookeeper.gemspec +9 -12
  38. metadata +50 -36
  39. data/examples/cloud_config.rb +0 -125
  40. data/test/test_basic.rb +0 -37
  41. data/test/test_callback1.rb +0 -36
  42. data/test/test_close.rb +0 -16
  43. data/test/test_esoteric.rb +0 -7
  44. data/test/test_watcher1.rb +0 -56
  45. data/test/test_watcher2.rb +0 -52
@@ -0,0 +1,30 @@
1
+ # figure out what platform we're on
2
+ # this way there's no ambiguity about which file to include
3
+ # or which class we're subclassing.
4
+
5
+ if defined?(::JRUBY_VERSION)
6
+ require_relative('../../java/java_base')
7
+ else
8
+ require_relative('../../ext/zookeeper_base')
9
+ end
10
+
11
+
12
+ module Zookeeper
13
+ if defined?(::JRUBY_VERSION)
14
+ class Client < Zookeeper::JavaBase
15
+ end
16
+ else
17
+ class Client < Zookeeper::ZookeeperBase
18
+ end
19
+ end
20
+
21
+ def self.new(*a, &b)
22
+ Zookeeper::Client.new(*a, &b)
23
+ end
24
+ end
25
+
26
+
27
+ Zookeeper::Client.class_eval do
28
+ include Zookeeper::ClientMethods
29
+ end
30
+
@@ -0,0 +1,241 @@
1
+ module Zookeeper
2
+ module ClientMethods
3
+ include Constants
4
+ include ACLs
5
+
6
+ def reopen(timeout=10, watcher=nil)
7
+ warn "WARN: ZookeeperBase#reopen watcher argument is now ignored" if watcher
8
+ super
9
+ end
10
+
11
+ def initialize(host, timeout=10, watcher=nil)
12
+ super
13
+ end
14
+
15
+ def get(options = {})
16
+ assert_open
17
+ assert_supported_keys(options, [:path, :watcher, :watcher_context, :callback, :callback_context])
18
+ assert_required_keys(options, [:path])
19
+
20
+ req_id = setup_call(:get, options)
21
+ rc, value, stat = super(req_id, options[:path], options[:callback], options[:watcher])
22
+
23
+ rv = { :req_id => req_id, :rc => rc }
24
+ options[:callback] ? rv : rv.merge(:data => value, :stat => Stat.new(stat))
25
+ end
26
+
27
+ def set(options = {})
28
+ assert_open
29
+ assert_supported_keys(options, [:path, :data, :version, :callback, :callback_context])
30
+ assert_required_keys(options, [:path])
31
+ assert_valid_data_size!(options[:data])
32
+ options[:version] ||= -1
33
+
34
+ req_id = setup_call(:set, options)
35
+ rc, stat = super(req_id, options[:path], options[:data], options[:callback], options[:version])
36
+
37
+ rv = { :req_id => req_id, :rc => rc }
38
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
39
+ end
40
+
41
+ def get_children(options = {})
42
+ assert_open
43
+ assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
44
+ assert_required_keys(options, [:path])
45
+
46
+ req_id = setup_call(:get_children, options)
47
+ rc, children, stat = super(req_id, options[:path], options[:callback], options[:watcher])
48
+
49
+ rv = { :req_id => req_id, :rc => rc }
50
+ options[:callback] ? rv : rv.merge(:children => children, :stat => Stat.new(stat))
51
+ end
52
+
53
+ def stat(options = {})
54
+ assert_open
55
+ assert_supported_keys(options, [:path, :callback, :callback_context, :watcher, :watcher_context])
56
+ assert_required_keys(options, [:path])
57
+
58
+ req_id = setup_call(:stat, options)
59
+ rc, stat = exists(req_id, options[:path], options[:callback], options[:watcher])
60
+
61
+ rv = { :req_id => req_id, :rc => rc }
62
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
63
+ end
64
+
65
+ def create(options = {})
66
+ assert_open
67
+ assert_supported_keys(options, [:path, :data, :acl, :ephemeral, :sequence, :callback, :callback_context])
68
+ assert_required_keys(options, [:path])
69
+ assert_valid_data_size!(options[:data])
70
+
71
+ flags = 0
72
+ flags |= ZOO_EPHEMERAL if options[:ephemeral]
73
+ flags |= ZOO_SEQUENCE if options[:sequence]
74
+
75
+ options[:acl] ||= ZOO_OPEN_ACL_UNSAFE
76
+
77
+ req_id = setup_call(:create, options)
78
+ rc, newpath = super(req_id, options[:path], options[:data], options[:callback], options[:acl], flags)
79
+
80
+ rv = { :req_id => req_id, :rc => rc }
81
+ options[:callback] ? rv : rv.merge(:path => newpath)
82
+ end
83
+
84
+ def delete(options = {})
85
+ assert_open
86
+ assert_supported_keys(options, [:path, :version, :callback, :callback_context])
87
+ assert_required_keys(options, [:path])
88
+ options[:version] ||= -1
89
+
90
+ req_id = setup_call(:delete, options)
91
+ rc = super(req_id, options[:path], options[:version], options[:callback])
92
+
93
+ { :req_id => req_id, :rc => rc }
94
+ end
95
+
96
+ # this method is *only* asynchronous
97
+ #
98
+ # @note There is a discrepancy between the zkc and java versions. zkc takes
99
+ # a string_callback_t, java takes a VoidCallback. You should most likely use
100
+ # the ZookeeperCallbacks::VoidCallback and not rely on the string value.
101
+ #
102
+ def sync(options = {})
103
+ assert_open
104
+ assert_supported_keys(options, [:path, :callback, :callback_context])
105
+ assert_required_keys(options, [:path, :callback])
106
+
107
+ req_id = setup_call(:sync, options)
108
+
109
+ rc = super(req_id, options[:path]) # we don't pass options[:callback] here as this method is *always* async
110
+
111
+ { :req_id => req_id, :rc => rc }
112
+ end
113
+
114
+ def set_acl(options = {})
115
+ assert_open
116
+ assert_supported_keys(options, [:path, :acl, :version, :callback, :callback_context])
117
+ assert_required_keys(options, [:path, :acl])
118
+ options[:version] ||= -1
119
+
120
+ req_id = setup_call(:set_acl, options)
121
+ rc = super(req_id, options[:path], options[:acl], options[:callback], options[:version])
122
+
123
+ { :req_id => req_id, :rc => rc }
124
+ end
125
+
126
+ def get_acl(options = {})
127
+ assert_open
128
+ assert_supported_keys(options, [:path, :callback, :callback_context])
129
+ assert_required_keys(options, [:path])
130
+
131
+ req_id = setup_call(:get_acl, options)
132
+ rc, acls, stat = super(req_id, options[:path], options[:callback])
133
+
134
+ rv = { :req_id => req_id, :rc => rc }
135
+ options[:callback] ? rv : rv.merge(:acl => acls, :stat => Stat.new(stat))
136
+ end
137
+
138
+ # close this client and any underyling connections
139
+ def close
140
+ super
141
+ end
142
+
143
+ def state
144
+ super
145
+ end
146
+
147
+ def connected?
148
+ super
149
+ end
150
+
151
+ def connecting?
152
+ super
153
+ end
154
+
155
+ def associating?
156
+ super
157
+ end
158
+
159
+ # There are some operations that are dangerous in the context of the event
160
+ # dispatch thread (because they would block further event delivery). This
161
+ # method allows clients to know if they're currently executing in the context of an
162
+ # event.
163
+ #
164
+ # @returns [true,false] true if the current thread is the event dispatch thread
165
+ def event_dispatch_thread?
166
+ super
167
+ end
168
+
169
+ # DEPRECATED: use the class-level method instead
170
+ def set_debug_level(val)
171
+ super
172
+ end
173
+
174
+ # has the underlying connection been closed?
175
+ def closed?
176
+ super
177
+ end
178
+
179
+ # is the event delivery system running?
180
+ def running?
181
+ super
182
+ end
183
+
184
+ # return the session id of the current connection as an Fixnum
185
+ def session_id
186
+ super
187
+ end
188
+
189
+ # Return the passwd portion of this connection's credentials as a String
190
+ def session_passwd
191
+ super
192
+ end
193
+
194
+ protected
195
+ # used during shutdown, awaken the event delivery thread if it's blocked
196
+ # waiting for the next event
197
+ def wake_event_loop!
198
+ super
199
+ end
200
+
201
+ # starts the event delivery subsystem going. after calling this method, running? will be true
202
+ def setup_dispatch_thread!
203
+ super
204
+ end
205
+
206
+ # TODO: describe what this does
207
+ def get_default_global_watcher
208
+ super
209
+ end
210
+
211
+ def logger
212
+ Zookeeper.logger
213
+ end
214
+
215
+ def assert_valid_data_size!(data)
216
+ return if data.nil?
217
+
218
+ data = data.to_s
219
+ if data.length >= 1048576 # one megabyte
220
+ raise Zookeeper::Exceptions::DataTooLargeException, "data must be smaller than 1 MiB, your data starts with: #{data[0..32].inspect}"
221
+ end
222
+ nil
223
+ end
224
+
225
+ private
226
+ # TODO: Sanitize user mistakes by unregistering watchers from ops that
227
+ # don't return ZOK (except wexists)? Make users clean up after themselves for now.
228
+ #
229
+ # XXX: is this dead code?
230
+ def unregister_watcher(req_id)
231
+ @mutex.synchronize {
232
+ @watcher_reqs.delete(req_id)
233
+ }
234
+ end
235
+
236
+ # must be supplied by parent class impl.
237
+ def assert_open
238
+ super
239
+ end
240
+ end # ClientMethods
241
+ end # Zookeeper
@@ -1,4 +1,5 @@
1
- module ZookeeperCommon
1
+ module Zookeeper
2
+ module Common
2
3
  # Ceci n'est pas une pipe
3
4
  class QueueWithPipe
4
5
  extend Forwardable
@@ -13,14 +14,8 @@ module ZookeeperCommon
13
14
  KILL_TOKEN = Object.new unless defined?(KILL_TOKEN)
14
15
 
15
16
  def initialize
16
- # r, w = IO.pipe
17
- # @pipe = { :read => r, :write => w }
18
17
  @queue = Queue.new
19
18
 
20
- # with the EventMachine client, we want to let EM handle clearing the
21
- # event pipe, so we set this to false
22
- # @clear_reads_on_pop = true
23
-
24
19
  @mutex = Mutex.new
25
20
  @closed = false
26
21
  @graceful = false
@@ -76,3 +71,4 @@ module ZookeeperCommon
76
71
  end
77
72
  end
78
73
  end
74
+ end
@@ -1,6 +1,8 @@
1
1
  require 'zookeeper/exceptions'
2
+ require 'zookeeper/common/queue_with_pipe'
2
3
 
3
- module ZookeeperCommon
4
+ module Zookeeper
5
+ module Common
4
6
  # sigh, i guess define this here?
5
7
  ZKRB_GLOBAL_CB_REQ = -1
6
8
 
@@ -27,7 +29,7 @@ protected
27
29
  }
28
30
  req_id
29
31
  end
30
-
32
+
31
33
  def setup_watcher(req_id, call_opts)
32
34
  @watcher_reqs[req_id] = { :watcher => call_opts[:watcher],
33
35
  :context => call_opts[:watcher_context] }
@@ -41,7 +43,7 @@ protected
41
43
  #
42
44
  def setup_completion(req_id, meth_name, call_opts)
43
45
  @completion_reqs[req_id] = { :callback => call_opts[:callback],
44
- :context => call_opts[:callback_context] }
46
+ :context => call_opts[:callback_context] }
45
47
  end
46
48
 
47
49
  def get_watcher(req_id)
@@ -118,15 +120,15 @@ protected
118
120
 
119
121
  is_completion = hash.has_key?(:rc)
120
122
 
121
- hash[:stat] = ZookeeperStat::Stat.new(hash[:stat]) if hash.has_key?(:stat)
122
- hash[:acl] = hash[:acl].map { |acl| ZookeeperACLs::ACL.new(acl) } if hash[:acl]
123
+ hash[:stat] = Zookeeper::Stat.new(hash[:stat]) if hash.has_key?(:stat)
124
+ hash[:acl] = hash[:acl].map { |acl| Zookeeper::ACLs::ACL.new(acl) } if hash[:acl]
123
125
 
124
126
  callback_context = is_completion ? get_completion(hash[:req_id]) : get_watcher(hash[:req_id])
125
127
 
126
128
  # When connectivity to the server has been lost (as indicated by SESSION_EVENT)
127
129
  # we want to rerun the callback at a later time when we eventually do have
128
130
  # a valid response.
129
- if hash[:type] == ZookeeperConstants::ZOO_SESSION_EVENT
131
+ if hash[:type] == Zookeeper::Constants::ZOO_SESSION_EVENT
130
132
  is_completion ? setup_completion(hash[:req_id], callback_context) : setup_watcher(hash[:req_id], callback_context)
131
133
  end
132
134
  if callback_context
@@ -148,14 +150,14 @@ protected
148
150
 
149
151
  def assert_supported_keys(args, supported)
150
152
  unless (args.keys - supported).empty?
151
- raise ZookeeperExceptions::ZookeeperException::BadArguments, # this heirarchy is kind of retarded
153
+ raise Zookeeper::Exceptions::BadArguments, # this heirarchy is kind of retarded
152
154
  "Supported arguments are: #{supported.inspect}, but arguments #{args.keys.inspect} were supplied instead"
153
155
  end
154
156
  end
155
157
 
156
158
  def assert_required_keys(args, required)
157
159
  unless (required - args.keys).empty?
158
- raise ZookeeperExceptions::ZookeeperException::BadArguments,
160
+ raise Zookeeper::Exceptions::BadArguments,
159
161
  "Required arguments are: #{required.inspect}, but only the arguments #{args.keys.inspect} were supplied."
160
162
  end
161
163
  end
@@ -164,11 +166,10 @@ private
164
166
  def prettify_event(hash)
165
167
  hash.dup.tap do |h|
166
168
  # pretty up the event display
167
- h[:type] = ZookeeperConstants::EVENT_TYPE_NAMES.fetch(h[:type]) if h[:type]
168
- h[:state] = ZookeeperConstants::STATE_NAMES.fetch(h[:state]) if h[:state]
169
+ h[:type] = Zookeeper::Constants::EVENT_TYPE_NAMES.fetch(h[:type]) if h[:type]
170
+ h[:state] = Zookeeper::Constants::STATE_NAMES.fetch(h[:state]) if h[:state]
169
171
  h[:req_id] = :global_session if h[:req_id] == -1
170
172
  end
171
173
  end
172
174
  end
173
-
174
- require 'zookeeper/common/queue_with_pipe'
175
+ end
@@ -0,0 +1,135 @@
1
+ module Zookeeper
2
+ # @private
3
+ def self.warn_about_compatability_once!
4
+ return if @warned_about_compatibility
5
+ @warned_about_compatibility = true
6
+
7
+ warn <<-EOS
8
+
9
+ -----------------------------------------------------------------------------
10
+
11
+ NOTICE: ZOOKEEPER BACKWARDS COMPATIBILTY EANBLED!!
12
+
13
+ THIS WILL NOT BE AUTOMATIC IN 1.1 !!
14
+
15
+ There was a major change to the organization of the Zookeeper gem between
16
+ 0.9 and 1.0, breaking backwards compatibility. To ease the transition,
17
+
18
+ #{__FILE__}
19
+
20
+ is automatically required. This will *not* be the case in 1.1.
21
+
22
+ -----------------------------------------------------------------------------
23
+ EOS
24
+ end
25
+
26
+ def self.warned_about_compatability?
27
+ !!@warned_about_compatability
28
+ end
29
+ end
30
+
31
+ Zookeeper.warn_about_compatability_once!
32
+
33
+ module Zookeeper
34
+ module Compatibility
35
+ def clean_backtrace
36
+ caller[0..-2].reject {|n| n =~ %r%/rspec/|\(eval\)|const_missing% }.map { |n| "\t#{n}" }.join("\n")
37
+ end
38
+ end
39
+ end
40
+
41
+ module ZookeeperConstants
42
+ include Zookeeper::Constants
43
+ end
44
+
45
+ module ZookeeperCallbacks
46
+ include Zookeeper::Callbacks
47
+ Callback = Base
48
+ end
49
+
50
+ module ZookeeperExceptions
51
+ include Zookeeper::Exceptions
52
+ end
53
+
54
+ module ZookeeperStat
55
+ extend Zookeeper::Compatibility
56
+ def self.const_missing(sym)
57
+ if sym == :Stat
58
+ warn "\nZookeeperStat::Stat is now Zookeeper::Stat, please update your code!\n#{clean_backtrace}"
59
+ # self.const_set(sym, Zookeeper::Stat)
60
+ Zookeeper::Stat
61
+ else
62
+ super
63
+ end
64
+ end
65
+ end
66
+
67
+ module ZookeeperACLs
68
+ extend Zookeeper::Compatibility
69
+ def self.const_missing(sym)
70
+ candidates = [Zookeeper::ACLs, Zookeeper::Constants, Zookeeper::ACLs::Constants]
71
+
72
+ candidates.each do |candidate|
73
+ if candidate.const_defined?(sym)
74
+ warn "\n#{self.name}::#{sym} is now located in #{candidate}::#{sym}, please update your code!\n#{clean_backtrace}"
75
+
76
+ c = candidate.const_get(sym)
77
+ # self.const_set(sym, c)
78
+ return c
79
+ end
80
+ end
81
+
82
+ super
83
+ end
84
+ end
85
+
86
+ module ZookeeperCommon
87
+ include Zookeeper::Common
88
+ extend Zookeeper::Compatibility
89
+
90
+ def self.const_missing(sym)
91
+ candidate = Zookeeper::Common
92
+
93
+ if candidate.const_defined?(sym)
94
+ warn "\n#{self.name}::#{sym} is now located in #{candidate}::#{sym}, please update your code!\n#{clean_backtrace}"
95
+
96
+ candidate.const_get(sym).tap do |c|
97
+ # self.const_set(sym, c)
98
+ end
99
+ else
100
+ super
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ # module Zookeeper
107
+ # include ZookeeperConstants
108
+ # include ZookeeperCallbacks
109
+ # include ZookeeperExceptions
110
+ # include ZookeeperCommon
111
+ # include ZookeeperStat
112
+ # include ZookeeperACLs
113
+ # end
114
+
115
+ module Zookeeper
116
+ extend Zookeeper::Compatibility
117
+ def self.const_missing(sym)
118
+ candidate =
119
+ case sym.to_s
120
+ when /Callback/
121
+ Zookeeper::Callbacks
122
+ end
123
+
124
+ if candidate.const_defined?(sym)
125
+ warn "\n#{self.name}::#{sym} is now located in #{candidate}::#{sym}, please update your code!\n#{clean_backtrace}"
126
+
127
+ candidate.const_get(sym).tap do |c|
128
+ # self.const_set(sym, c)
129
+ end
130
+ else
131
+ super
132
+ end
133
+ end
134
+ end
135
+
@@ -1,4 +1,7 @@
1
- module ZookeeperConstants
1
+ module Zookeeper
2
+ module Constants
3
+ include ACLs::Constants
4
+
2
5
  # file type masks
3
6
  ZOO_EPHEMERAL = 1
4
7
  ZOO_SEQUENCE = 2
@@ -25,6 +28,36 @@ module ZookeeperConstants
25
28
  ZOO_LOG_LEVEL_INFO = 3
26
29
  ZOO_LOG_LEVEL_DEBUG = 4
27
30
 
31
+ # exceptions/errors
32
+ ZOK = 0
33
+ ZSYSTEMERROR = -1
34
+ ZRUNTIMEINCONSISTENCY = -2
35
+ ZDATAINCONSISTENCY = -3
36
+ ZCONNECTIONLOSS = -4
37
+ ZMARSHALLINGERROR = -5
38
+ ZUNIMPLEMENTED = -6
39
+ ZOPERATIONTIMEOUT = -7
40
+ ZBADARGUMENTS = -8
41
+ ZINVALIDSTATE = -9
42
+
43
+ # api errors
44
+ ZAPIERROR = -100
45
+ ZNONODE = -101
46
+ ZNOAUTH = -102
47
+ ZBADVERSION = -103
48
+ ZNOCHILDRENFOREPHEMERALS = -108
49
+ ZNODEEXISTS = -110
50
+ ZNOTEMPTY = -111
51
+ ZSESSIONEXPIRED = -112
52
+ ZINVALIDCALLBACK = -113
53
+ ZINVALIDACL = -114
54
+ ZAUTHFAILED = -115
55
+ ZCLOSING = -116
56
+ ZNOTHING = -117
57
+ ZSESSIONMOVED = -118
58
+
59
+ ZKRB_GLOBAL_CB_REQ = -1
60
+
28
61
  # used to find the name for a numeric event
29
62
  # @private
30
63
  EVENT_TYPE_NAMES = {
@@ -55,3 +88,4 @@ module ZookeeperConstants
55
88
  (name = STATE_NAMES[v]) ? "ZOO_#{name.upcase}_STATE" : ''
56
89
  end
57
90
  end
91
+ end
@@ -2,7 +2,7 @@ require 'zookeeper'
2
2
  require 'eventmachine'
3
3
 
4
4
  module ZookeeperEM
5
- class Client < Zookeeper
5
+ class Client < Zookeeper::Client
6
6
  # @private
7
7
  # the EM Connection instance we receive once we call EM.watch on our selectable_io
8
8
  attr_reader :em_connection