zookeeper-ng 1.5.2.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.ctags_paths +1 -0
  3. data/.dotfiles/ruby-gemset +1 -0
  4. data/.dotfiles/ruby-version +1 -0
  5. data/.dotfiles/rvmrc +2 -0
  6. data/.github/workflows/build.yml +57 -0
  7. data/.gitignore +19 -0
  8. data/.gitmodules +3 -0
  9. data/CHANGELOG +408 -0
  10. data/Gemfile +30 -0
  11. data/Guardfile +8 -0
  12. data/LICENSE +23 -0
  13. data/Manifest +29 -0
  14. data/README.markdown +62 -0
  15. data/Rakefile +121 -0
  16. data/cause-abort.rb +117 -0
  17. data/ext/.gitignore +6 -0
  18. data/ext/Rakefile +41 -0
  19. data/ext/c_zookeeper.rb +398 -0
  20. data/ext/common.h +17 -0
  21. data/ext/dbg.h +53 -0
  22. data/ext/depend +5 -0
  23. data/ext/event_lib.c +740 -0
  24. data/ext/event_lib.h +175 -0
  25. data/ext/extconf.rb +103 -0
  26. data/ext/generate_gvl_code.rb +321 -0
  27. data/ext/patches/zkc-3.3.5-network.patch +24 -0
  28. data/ext/patches/zkc-3.4.5-buffer-overflow.patch +11 -0
  29. data/ext/patches/zkc-3.4.5-config.patch +5454 -0
  30. data/ext/patches/zkc-3.4.5-fetch-and-add.patch +16 -0
  31. data/ext/patches/zkc-3.4.5-logging.patch +41 -0
  32. data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
  33. data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
  34. data/ext/zkc-3.4.5.tar.gz +0 -0
  35. data/ext/zkrb.c +1080 -0
  36. data/ext/zkrb_wrapper.c +775 -0
  37. data/ext/zkrb_wrapper.h +350 -0
  38. data/ext/zkrb_wrapper_compat.c +15 -0
  39. data/ext/zkrb_wrapper_compat.h +11 -0
  40. data/ext/zookeeper_base.rb +256 -0
  41. data/java/java_base.rb +501 -0
  42. data/lib/zookeeper/acls.rb +44 -0
  43. data/lib/zookeeper/callbacks.rb +108 -0
  44. data/lib/zookeeper/client.rb +30 -0
  45. data/lib/zookeeper/client_methods.rb +282 -0
  46. data/lib/zookeeper/common/queue_with_pipe.rb +110 -0
  47. data/lib/zookeeper/common.rb +122 -0
  48. data/lib/zookeeper/compatibility.rb +138 -0
  49. data/lib/zookeeper/constants.rb +97 -0
  50. data/lib/zookeeper/continuation.rb +223 -0
  51. data/lib/zookeeper/core_ext.rb +58 -0
  52. data/lib/zookeeper/em_client.rb +55 -0
  53. data/lib/zookeeper/exceptions.rb +135 -0
  54. data/lib/zookeeper/forked.rb +19 -0
  55. data/lib/zookeeper/latch.rb +34 -0
  56. data/lib/zookeeper/logger/forwarding_logger.rb +84 -0
  57. data/lib/zookeeper/logger.rb +39 -0
  58. data/lib/zookeeper/monitor.rb +19 -0
  59. data/lib/zookeeper/rake_tasks.rb +165 -0
  60. data/lib/zookeeper/request_registry.rb +153 -0
  61. data/lib/zookeeper/stat.rb +21 -0
  62. data/lib/zookeeper/version.rb +4 -0
  63. data/lib/zookeeper.rb +115 -0
  64. data/notes.txt +14 -0
  65. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  66. data/spec/c_zookeeper_spec.rb +51 -0
  67. data/spec/chrooted_connection_spec.rb +83 -0
  68. data/spec/compatibilty_spec.rb +8 -0
  69. data/spec/default_watcher_spec.rb +41 -0
  70. data/spec/em_spec.rb +51 -0
  71. data/spec/ext/zookeeper_base_spec.rb +19 -0
  72. data/spec/forked_connection_spec.rb +122 -0
  73. data/spec/latch_spec.rb +24 -0
  74. data/spec/log4j.properties +17 -0
  75. data/spec/shared/all_success_return_values.rb +10 -0
  76. data/spec/shared/connection_examples.rb +1081 -0
  77. data/spec/spec_helper.rb +61 -0
  78. data/spec/support/00_logging.rb +38 -0
  79. data/spec/support/10_spawn_zookeeper.rb +20 -0
  80. data/spec/support/progress_formatter.rb +15 -0
  81. data/spec/support/zookeeper_spec_helpers.rb +96 -0
  82. data/spec/zookeeper_spec.rb +24 -0
  83. data/zookeeper.gemspec +46 -0
  84. data/zoomonkey/duplicates +3 -0
  85. data/zoomonkey/zoomonkey.rb +194 -0
  86. metadata +185 -0
@@ -0,0 +1,282 @@
1
+ module Zookeeper
2
+ module ClientMethods
3
+ extend Forwardable
4
+ include Constants
5
+ include ACLs
6
+ include Logger
7
+
8
+ # @req_registry is set up in the platform-specific base classes
9
+ def_delegators :@req_registry, :setup_call
10
+ private :setup_call
11
+
12
+ def reopen(timeout=10, watcher=nil, opts = {})
13
+ warn "WARN: ZookeeperBase#reopen watcher argument is now ignored" if watcher
14
+ super
15
+ end
16
+
17
+ def initialize(host, timeout=10, watcher=nil, opts = {})
18
+ super
19
+ end
20
+
21
+ def add_auth(options = {})
22
+ assert_open
23
+ assert_keys(options,
24
+ :supported => [:scheme, :cert],
25
+ :required => [:scheme, :cert])
26
+
27
+ req_id = setup_call(:add_auth, options)
28
+ rc = super(req_id, options[:scheme], options[:cert])
29
+
30
+ { :req_id => req_id, :rc => rc }
31
+ end
32
+
33
+ def get(options = {})
34
+ assert_open
35
+ assert_keys(options,
36
+ :supported => [:path, :watcher, :watcher_context, :callback, :callback_context],
37
+ :required => [:path])
38
+
39
+ req_id = setup_call(:get, options)
40
+ rc, value, stat = super(req_id, options[:path], options[:callback], options[:watcher])
41
+
42
+ rv = { :req_id => req_id, :rc => rc }
43
+ options[:callback] ? rv : rv.merge(:data => value, :stat => Stat.new(stat))
44
+ end
45
+
46
+ def set(options = {})
47
+ assert_open
48
+ assert_keys(options,
49
+ :supported => [:path, :data, :version, :callback, :callback_context],
50
+ :required => [:path])
51
+
52
+ assert_valid_data_size!(options[:data])
53
+ options[:version] ||= -1
54
+
55
+ req_id = setup_call(:set, options)
56
+ rc, stat = super(req_id, options[:path], options[:data], options[:callback], options[:version])
57
+
58
+ rv = { :req_id => req_id, :rc => rc }
59
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
60
+ end
61
+
62
+ def get_children(options = {})
63
+ assert_open
64
+ assert_keys(options,
65
+ :supported => [:path, :callback, :callback_context, :watcher, :watcher_context],
66
+ :required => [:path])
67
+
68
+ req_id = setup_call(:get_children, options)
69
+ rc, children, stat = super(req_id, options[:path], options[:callback], options[:watcher])
70
+
71
+ rv = { :req_id => req_id, :rc => rc }
72
+ options[:callback] ? rv : rv.merge(:children => children, :stat => Stat.new(stat))
73
+ end
74
+
75
+ def stat(options = {})
76
+ assert_open
77
+ assert_keys(options,
78
+ :supported => [:path, :callback, :callback_context, :watcher, :watcher_context],
79
+ :required => [:path])
80
+
81
+ req_id = setup_call(:stat, options)
82
+ rc, stat = exists(req_id, options[:path], options[:callback], options[:watcher])
83
+
84
+ rv = { :req_id => req_id, :rc => rc }
85
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
86
+ end
87
+
88
+ def create(options = {})
89
+ assert_open
90
+ assert_keys(options,
91
+ :supported => [:path, :data, :acl, :ephemeral, :sequence, :callback, :callback_context],
92
+ :required => [:path])
93
+
94
+ assert_valid_data_size!(options[:data])
95
+
96
+ flags = 0
97
+ flags |= ZOO_EPHEMERAL if options[:ephemeral]
98
+ flags |= ZOO_SEQUENCE if options[:sequence]
99
+
100
+ options[:acl] ||= ZOO_OPEN_ACL_UNSAFE
101
+
102
+ req_id = setup_call(:create, 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_open
111
+ assert_keys(options,
112
+ :supported => [:path, :version, :callback, :callback_context],
113
+ :required => [:path])
114
+
115
+ options[:version] ||= -1
116
+
117
+ req_id = setup_call(:delete, options)
118
+ rc = super(req_id, options[:path], options[:version], options[:callback])
119
+
120
+ { :req_id => req_id, :rc => rc }
121
+ end
122
+
123
+ # this method is *only* asynchronous
124
+ #
125
+ # @note There is a discrepancy between the zkc and java versions. zkc takes
126
+ # a string_callback_t, java takes a VoidCallback. You should most likely use
127
+ # the Zookeeper::Callbacks::VoidCallback and not rely on the string value.
128
+ #
129
+ def sync(options = {})
130
+ assert_open
131
+ assert_keys(options,
132
+ :supported => [:path, :callback, :callback_context],
133
+ :required => [:path, :callback])
134
+
135
+ req_id = setup_call(:sync, options)
136
+
137
+ rc = super(req_id, options[:path]) # we don't pass options[:callback] here as this method is *always* async
138
+
139
+ { :req_id => req_id, :rc => rc }
140
+ end
141
+
142
+ def set_acl(options = {})
143
+ assert_open
144
+ assert_keys(options,
145
+ :supported => [:path, :acl, :version, :callback, :callback_context],
146
+ :required => [:path, :acl])
147
+ options[:version] ||= -1
148
+
149
+ req_id = setup_call(:set_acl, options)
150
+ rc = super(req_id, options[:path], options[:acl], options[:callback], options[:version])
151
+
152
+ { :req_id => req_id, :rc => rc }
153
+ end
154
+
155
+ def get_acl(options = {})
156
+ assert_open
157
+ assert_keys(options,
158
+ :supported => [:path, :callback, :callback_context],
159
+ :required => [:path])
160
+
161
+ req_id = setup_call(:get_acl, options)
162
+ rc, acls, stat = super(req_id, options[:path], options[:callback])
163
+
164
+ rv = { :req_id => req_id, :rc => rc }
165
+ options[:callback] ? rv : rv.merge(:acl => acls, :stat => Stat.new(stat))
166
+ end
167
+
168
+ # close this client and any underlying connections
169
+ def close
170
+ super
171
+ end
172
+
173
+ def state
174
+ super
175
+ end
176
+
177
+ def connected?
178
+ super
179
+ end
180
+
181
+ def connecting?
182
+ super
183
+ end
184
+
185
+ def associating?
186
+ super
187
+ end
188
+
189
+ # There are some operations that are dangerous in the context of the event
190
+ # dispatch thread (because they would block further event delivery). This
191
+ # method allows clients to know if they're currently executing in the context of an
192
+ # event.
193
+ #
194
+ # @returns [true,false] true if the current thread is the event dispatch thread
195
+ def event_dispatch_thread?
196
+ super
197
+ end
198
+
199
+ # DEPRECATED: use the class-level method instead
200
+ def set_debug_level(val)
201
+ super
202
+ end
203
+
204
+ # has the underlying connection been closed?
205
+ def closed?
206
+ super
207
+ end
208
+
209
+ # is the event delivery system running?
210
+ def running?
211
+ super
212
+ end
213
+
214
+ # return the session id of the current connection as an Fixnum
215
+ def session_id
216
+ super
217
+ end
218
+
219
+ # Return the passwd portion of this connection's credentials as a String
220
+ def session_passwd
221
+ super
222
+ end
223
+
224
+ # stop all underlying threads in preparation for a fork()
225
+ def pause_before_fork_in_parent
226
+ super
227
+ end
228
+
229
+ # re-start all underlying threads after performing a fork()
230
+ def resume_after_fork_in_parent
231
+ super
232
+ end
233
+
234
+ protected
235
+ # used during shutdown, awaken the event delivery thread if it's blocked
236
+ # waiting for the next event
237
+ def wake_event_loop!
238
+ super
239
+ end
240
+
241
+ # starts the event delivery subsystem going. after calling this method, running? will be true
242
+ def setup_dispatch_thread!
243
+ super
244
+ end
245
+
246
+ # TODO: describe what this does
247
+ def get_default_global_watcher
248
+ super
249
+ end
250
+
251
+ def assert_valid_data_size!(data)
252
+ return if data.nil?
253
+
254
+ data = data.to_s
255
+ if data.length >= 1048576 # one megabyte
256
+ raise Zookeeper::Exceptions::DataTooLargeException, "data must be smaller than 1 MiB, your data starts with: #{data[0..32].inspect}"
257
+ end
258
+ nil
259
+ end
260
+
261
+ private
262
+ def assert_keys(args, opts={})
263
+ supported = opts[:supported] || []
264
+ required = opts[:required] || []
265
+
266
+ unless (args.keys - supported).empty?
267
+ raise Zookeeper::Exceptions::BadArguments,
268
+ "Supported arguments are: #{supported.inspect}, but arguments #{args.keys.inspect} were supplied instead"
269
+ end
270
+
271
+ unless (required - args.keys).empty?
272
+ raise Zookeeper::Exceptions::BadArguments,
273
+ "Required arguments are: #{required.inspect}, but only the arguments #{args.keys.inspect} were supplied."
274
+ end
275
+ end
276
+
277
+ # must be supplied by parent class impl.
278
+ def assert_open
279
+ super
280
+ end
281
+ end # ClientMethods
282
+ end # Zookeeper
@@ -0,0 +1,110 @@
1
+ module Zookeeper
2
+ module Common
3
+ # Ceci n'est pas une pipe
4
+ class QueueWithPipe
5
+ extend Forwardable
6
+ include Logger
7
+
8
+ # raised when close has been called, and pop() is performed
9
+ #
10
+ class ShutdownException < StandardError; end
11
+
12
+ # @private
13
+ KILL_TOKEN = Object.new unless defined?(KILL_TOKEN)
14
+
15
+ def initialize
16
+ @array = []
17
+
18
+ @mutex = Mutex.new
19
+ @cond = ConditionVariable.new
20
+ @closed = false
21
+ @graceful = false
22
+ end
23
+
24
+ def clear
25
+ @mutex.lock
26
+ begin
27
+ @array.clear
28
+ ensure
29
+ @mutex.unlock rescue nil
30
+ end
31
+ end
32
+
33
+ def push(obj)
34
+ @mutex.lock
35
+ begin
36
+ # raise ShutdownException if (@closed or @graceful)
37
+ @array << obj
38
+ @cond.signal
39
+ ensure
40
+ @mutex.unlock rescue nil
41
+ end
42
+ end
43
+
44
+ def pop(non_blocking=false)
45
+ rval = nil
46
+
47
+ @mutex.lock
48
+ begin
49
+
50
+ begin
51
+ raise ShutdownException if @closed # this may get us in trouble
52
+
53
+ rval = @array.shift
54
+
55
+ unless rval
56
+ raise ThreadError if non_blocking # sigh, ruby's stupid behavior
57
+ raise ShutdownException if @graceful # we've processed all the remaining mesages
58
+
59
+ @cond.wait(@mutex) until (@closed or @graceful or (@array.length > 0))
60
+ end
61
+ end until rval
62
+
63
+ return rval
64
+
65
+ ensure
66
+ @mutex.unlock rescue nil
67
+ end
68
+ end
69
+
70
+ # close the queue and causes ShutdownException to be raised on waiting threads
71
+ def graceful_close!
72
+ @mutex.lock
73
+ begin
74
+ return if @graceful or @closed
75
+ logger.debug { "#{self.class}##{__method__} gracefully closing" }
76
+ @graceful = true
77
+ @cond.broadcast
78
+ ensure
79
+ @mutex.unlock rescue nil
80
+ end
81
+ nil
82
+ end
83
+
84
+ def open
85
+ @mutex.lock
86
+ begin
87
+ @closed = @graceful = false
88
+ @cond.broadcast
89
+ ensure
90
+ @mutex.unlock rescue nil
91
+ end
92
+ end
93
+
94
+ def close
95
+ @mutex.lock
96
+ begin
97
+ return if @closed
98
+ @closed = true
99
+ @cond.broadcast
100
+ ensure
101
+ @mutex.unlock rescue nil
102
+ end
103
+ end
104
+
105
+ def closed?
106
+ @mutex.synchronize { !!@closed }
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,122 @@
1
+ require 'zookeeper/exceptions'
2
+ require 'zookeeper/common/queue_with_pipe'
3
+
4
+ module Zookeeper
5
+ module Common
6
+ def event_dispatch_thread?
7
+ @dispatcher && (@dispatcher == Thread.current)
8
+ end
9
+
10
+ private
11
+ def setup_dispatch_thread!
12
+ @mutex.synchronize do
13
+ if @dispatcher
14
+ logger.debug { "dispatcher already running" }
15
+ return
16
+ end
17
+
18
+ logger.debug { "starting dispatch thread" }
19
+
20
+ @dispatcher = Thread.new(&method(:dispatch_thread_body))
21
+ end
22
+ end
23
+
24
+ # this method is part of the reopen/close code, and is responsible for
25
+ # shutting down the dispatch thread.
26
+ #
27
+ # @dispatcher will be nil when this method exits
28
+ #
29
+ def stop_dispatch_thread!(timeout=2)
30
+ logger.debug { "#{self.class}##{__method__}" }
31
+
32
+ if @dispatcher
33
+ if @dispatcher.join(0)
34
+ @dispatcher = nil
35
+ return
36
+ end
37
+
38
+ @mutex.synchronize do
39
+ event_queue.graceful_close!
40
+
41
+ # we now release the mutex so that dispatch_next_callback can grab it
42
+ # to do what it needs to do while delivering events
43
+ #
44
+ @dispatch_shutdown_cond.wait
45
+
46
+ # wait for another timeout sec for the thread to join
47
+ until @dispatcher.join(timeout)
48
+ logger.error { "Dispatch thread did not join cleanly, waiting" }
49
+ end
50
+ @dispatcher = nil
51
+ end
52
+ end
53
+ end
54
+
55
+ def get_next_event(blocking=true)
56
+ @event_queue.pop(!blocking).tap do |event|
57
+ logger.debug { "#{self.class}##{__method__} delivering event #{event.inspect}" }
58
+ end
59
+ rescue ThreadError
60
+ nil
61
+ end
62
+
63
+ def dispatch_next_callback(hash)
64
+ return nil unless hash
65
+
66
+ logger.debug { "get_next_event returned: #{prettify_event(hash).inspect}" }
67
+
68
+ is_completion = hash.has_key?(:rc)
69
+
70
+ hash[:stat] = Zookeeper::Stat.new(hash[:stat]) if hash.has_key?(:stat)
71
+ hash[:acl] = hash[:acl].map { |acl| Zookeeper::ACLs::ACL.new(acl) } if hash[:acl]
72
+
73
+ callback_context = @req_registry.get_context_for(hash)
74
+
75
+ if callback_context
76
+ callback = is_completion ? callback_context[:callback] : callback_context[:watcher]
77
+
78
+ hash[:context] = callback_context[:context]
79
+
80
+ if callback.respond_to?(:call)
81
+ callback.call(hash)
82
+ else
83
+ # puts "dispatch_next_callback found non-callback => #{callback.inspect}"
84
+ end
85
+ else
86
+ logger.warn { "Duplicate event received (no handler for req_id #{hash[:req_id]}, event: #{hash.inspect}" }
87
+ end
88
+ true
89
+ end
90
+
91
+ def dispatch_thread_body
92
+ while true
93
+ begin
94
+ dispatch_next_callback(get_next_event(true))
95
+ rescue QueueWithPipe::ShutdownException
96
+ logger.info { "dispatch thread exiting, got shutdown exception" }
97
+ return
98
+ rescue Exception => e
99
+ $stderr.puts ["#{e.class}: #{e.message}", e.backtrace.map { |n| "\t#{n}" }.join("\n")].join("\n")
100
+ end
101
+ end
102
+ ensure
103
+ signal_dispatch_thread_exit!
104
+ end
105
+
106
+ def signal_dispatch_thread_exit!
107
+ @mutex.synchronize do
108
+ logger.debug { "dispatch thread exiting!" }
109
+ @dispatch_shutdown_cond.broadcast
110
+ end
111
+ end
112
+
113
+ def prettify_event(hash)
114
+ hash.dup.tap do |h|
115
+ # pretty up the event display
116
+ h[:type] = Zookeeper::Constants::EVENT_TYPE_NAMES.fetch(h[:type]) if h[:type]
117
+ h[:state] = Zookeeper::Constants::STATE_NAMES.fetch(h[:state]) if h[:state]
118
+ h[:req_id] = :global_session if h[:req_id] == -1
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,138 @@
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
+ # at request of @eric
32
+ #Zookeeper.warn_about_compatability_once!
33
+
34
+ module Zookeeper
35
+ module Compatibility
36
+ def clean_backtrace
37
+ caller[0..-2].reject {|n| n =~ %r%/rspec/|\(eval\)|const_missing% }.map { |n| "\t#{n}" }.join("\n")
38
+ end
39
+ end
40
+ end
41
+
42
+ module ZookeeperConstants
43
+ include Zookeeper::Constants
44
+ end
45
+
46
+ module ZookeeperCallbacks
47
+ include Zookeeper::Callbacks
48
+ Callback = Base
49
+ end
50
+
51
+ module ZookeeperExceptions
52
+ include Zookeeper::Exceptions
53
+ end
54
+
55
+ module ZookeeperStat
56
+ extend Zookeeper::Compatibility
57
+ def self.const_missing(sym)
58
+ if sym == :Stat
59
+ warn "\nZookeeperStat::Stat is now Zookeeper::Stat, please update your code!\n#{clean_backtrace}"
60
+ # self.const_set(sym, Zookeeper::Stat)
61
+ Zookeeper::Stat
62
+ else
63
+ super
64
+ end
65
+ end
66
+ end
67
+
68
+ module ZookeeperACLs
69
+ extend Zookeeper::Compatibility
70
+ def self.const_missing(sym)
71
+ candidates = [Zookeeper::ACLs, Zookeeper::Constants, Zookeeper::ACLs::Constants]
72
+
73
+ candidates.each do |candidate|
74
+ if candidate.const_defined?(sym)
75
+ warn "\n#{self.name}::#{sym} is now located in #{candidate}::#{sym}, please update your code!\n#{clean_backtrace}"
76
+
77
+ c = candidate.const_get(sym)
78
+ # self.const_set(sym, c)
79
+ return c
80
+ end
81
+ end
82
+
83
+ super
84
+ end
85
+ end
86
+
87
+ module ZookeeperCommon
88
+ include Zookeeper::Common
89
+ extend Zookeeper::Compatibility
90
+
91
+ def self.const_missing(sym)
92
+ candidate = Zookeeper::Common
93
+
94
+ if candidate.const_defined?(sym)
95
+ warn "\n#{self.name}::#{sym} is now located in #{candidate}::#{sym}, please update your code!\n#{clean_backtrace}"
96
+
97
+ candidate.const_get(sym).tap do |c|
98
+ # self.const_set(sym, c)
99
+ end
100
+ else
101
+ super
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ # module Zookeeper
108
+ # include ZookeeperConstants
109
+ # include ZookeeperCallbacks
110
+ # include ZookeeperExceptions
111
+ # include ZookeeperCommon
112
+ # include ZookeeperStat
113
+ # include ZookeeperACLs
114
+ # end
115
+
116
+ module Zookeeper
117
+ extend Zookeeper::Compatibility
118
+ def self.const_missing(sym)
119
+ candidate =
120
+ case sym.to_s
121
+ when /Callback/
122
+ Zookeeper::Callbacks
123
+ end
124
+
125
+ super unless candidate
126
+
127
+ if candidate.const_defined?(sym)
128
+ warn "\n#{self.name}::#{sym} is now located in #{candidate}::#{sym}, please update your code!\n#{clean_backtrace}"
129
+
130
+ candidate.const_get(sym).tap do |c|
131
+ # self.const_set(sym, c)
132
+ end
133
+ else
134
+ super
135
+ end
136
+ end
137
+ end
138
+