zookeeper-ng 1.5
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.
- checksums.yaml +7 -0
- data/.ctags_paths +1 -0
- data/.dotfiles/ruby-gemset +1 -0
- data/.dotfiles/ruby-version +1 -0
- data/.dotfiles/rvmrc +2 -0
- data/.gitignore +19 -0
- data/.gitmodules +3 -0
- data/.travis.yml +25 -0
- data/CHANGELOG +395 -0
- data/Gemfile +30 -0
- data/Guardfile +8 -0
- data/LICENSE +23 -0
- data/Manifest +29 -0
- data/README.markdown +85 -0
- data/Rakefile +121 -0
- data/cause-abort.rb +117 -0
- data/ext/.gitignore +6 -0
- data/ext/Rakefile +41 -0
- data/ext/c_zookeeper.rb +398 -0
- data/ext/common.h +17 -0
- data/ext/dbg.h +53 -0
- data/ext/depend +5 -0
- data/ext/event_lib.c +740 -0
- data/ext/event_lib.h +175 -0
- data/ext/extconf.rb +103 -0
- data/ext/generate_gvl_code.rb +321 -0
- data/ext/patches/zkc-3.3.5-network.patch +24 -0
- data/ext/patches/zkc-3.4.5-fetch-and-add.patch +16 -0
- data/ext/patches/zkc-3.4.5-logging.patch +41 -0
- data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
- data/ext/patches/zkc-3.4.5-overflow.patch +11 -0
- data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
- data/ext/zkc-3.4.5.tar.gz +0 -0
- data/ext/zkrb.c +1075 -0
- data/ext/zkrb_wrapper.c +775 -0
- data/ext/zkrb_wrapper.h +350 -0
- data/ext/zkrb_wrapper_compat.c +15 -0
- data/ext/zkrb_wrapper_compat.h +11 -0
- data/ext/zookeeper_base.rb +256 -0
- data/java/java_base.rb +503 -0
- data/lib/zookeeper.rb +115 -0
- data/lib/zookeeper/acls.rb +44 -0
- data/lib/zookeeper/callbacks.rb +108 -0
- data/lib/zookeeper/client.rb +30 -0
- data/lib/zookeeper/client_methods.rb +282 -0
- data/lib/zookeeper/common.rb +122 -0
- data/lib/zookeeper/common/queue_with_pipe.rb +110 -0
- data/lib/zookeeper/compatibility.rb +138 -0
- data/lib/zookeeper/constants.rb +97 -0
- data/lib/zookeeper/continuation.rb +223 -0
- data/lib/zookeeper/core_ext.rb +58 -0
- data/lib/zookeeper/em_client.rb +55 -0
- data/lib/zookeeper/exceptions.rb +135 -0
- data/lib/zookeeper/forked.rb +19 -0
- data/lib/zookeeper/latch.rb +34 -0
- data/lib/zookeeper/logger.rb +39 -0
- data/lib/zookeeper/logger/forwarding_logger.rb +84 -0
- data/lib/zookeeper/monitor.rb +19 -0
- data/lib/zookeeper/rake_tasks.rb +165 -0
- data/lib/zookeeper/request_registry.rb +153 -0
- data/lib/zookeeper/stat.rb +21 -0
- data/lib/zookeeper/version.rb +4 -0
- data/notes.txt +14 -0
- data/scripts/upgrade-1.0-sed-alike.rb +46 -0
- data/spec/c_zookeeper_spec.rb +51 -0
- data/spec/chrooted_connection_spec.rb +83 -0
- data/spec/compatibilty_spec.rb +8 -0
- data/spec/default_watcher_spec.rb +41 -0
- data/spec/em_spec.rb +51 -0
- data/spec/ext/zookeeper_base_spec.rb +19 -0
- data/spec/forked_connection_spec.rb +124 -0
- data/spec/latch_spec.rb +24 -0
- data/spec/log4j.properties +17 -0
- data/spec/shared/all_success_return_values.rb +10 -0
- data/spec/shared/connection_examples.rb +1077 -0
- data/spec/spec_helper.rb +61 -0
- data/spec/support/00_logging.rb +38 -0
- data/spec/support/10_spawn_zookeeper.rb +24 -0
- data/spec/support/progress_formatter.rb +15 -0
- data/spec/support/zookeeper_spec_helpers.rb +96 -0
- data/spec/zookeeper_spec.rb +24 -0
- data/zookeeper.gemspec +38 -0
- data/zoomonkey/duplicates +3 -0
- data/zoomonkey/zoomonkey.rb +194 -0
- metadata +157 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
module Zookeeper
|
2
|
+
module Forked
|
3
|
+
# the includer provides an 'original_pid' method, which is set
|
4
|
+
# when the original 'owning' process creates the object.
|
5
|
+
#
|
6
|
+
# @return [true] if the current PID differs from the original_pid value
|
7
|
+
# @return [false] if the current PID matches the original_pid value
|
8
|
+
#
|
9
|
+
def forked?
|
10
|
+
Process.pid != original_pid
|
11
|
+
end
|
12
|
+
|
13
|
+
# sets the `original_pid` to the current value
|
14
|
+
def update_pid!
|
15
|
+
self.original_pid = Process.pid
|
16
|
+
end
|
17
|
+
end # Forked
|
18
|
+
end # Zookeeper
|
19
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Zookeeper
|
2
|
+
# a cross-thread gate of sorts.
|
3
|
+
class Latch
|
4
|
+
def initialize(count = 1)
|
5
|
+
@count = count
|
6
|
+
@mutex = Monitor.new
|
7
|
+
@cond = @mutex.new_cond
|
8
|
+
end
|
9
|
+
|
10
|
+
def release
|
11
|
+
@mutex.synchronize {
|
12
|
+
@count -= 1 if @count > 0
|
13
|
+
@cond.broadcast if @count.zero?
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def await(timeout=nil)
|
18
|
+
@mutex.synchronize do
|
19
|
+
if timeout
|
20
|
+
time_to_stop = Time.now + timeout
|
21
|
+
|
22
|
+
while @count > 0
|
23
|
+
@cond.wait(timeout)
|
24
|
+
|
25
|
+
break if (Time.now > time_to_stop)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
@cond.wait_while { @count > 0 }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Zookeeper
|
2
|
+
module Logger
|
3
|
+
def self.wrapped_logger
|
4
|
+
if defined?(@@wrapped_logger)
|
5
|
+
@@wrapped_logger
|
6
|
+
else
|
7
|
+
@@wrapped_logger = ::Logger.new(STDERR).tap { |l| l.level = ::Logger::FATAL }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.wrapped_logger=(log)
|
12
|
+
@@wrapped_logger = log
|
13
|
+
end
|
14
|
+
|
15
|
+
# @private
|
16
|
+
module ClassMethods
|
17
|
+
def logger
|
18
|
+
::Zookeeper.logger || ForwardingLogger.for(::Zookeeper::Logger.wrapped_logger, _zk_logger_name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.included(base)
|
23
|
+
# return false if base < self # avoid infinite recursion
|
24
|
+
base.extend(ClassMethods)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def log_realtime(what)
|
29
|
+
logger.debug do
|
30
|
+
t = Benchmark.realtime { yield }
|
31
|
+
"#{what} took #{t} sec"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def logger
|
36
|
+
@logger ||= (::Zookeeper.logger || self.class.logger)
|
37
|
+
end
|
38
|
+
end # Logger
|
39
|
+
end # Zookeeper
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Zookeeper
|
2
|
+
module Logger
|
3
|
+
# h/t _eric and Papertrail
|
4
|
+
# @private
|
5
|
+
class ForwardingLogger
|
6
|
+
attr_accessor :level, :formatter
|
7
|
+
|
8
|
+
@@mutex = Monitor.new unless defined?(@@mutex)
|
9
|
+
@@loggers = {} unless defined?(@@loggers)
|
10
|
+
|
11
|
+
def self.for(logger, name)
|
12
|
+
@@mutex.synchronize do
|
13
|
+
@@loggers.fetch(name) do |k|
|
14
|
+
@@loggers[k] = new(logger, :formatter => lambda { |m| "%25.25s: %s" % [k, m] })
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(logger, options = {})
|
20
|
+
@level = ::Logger::DEBUG
|
21
|
+
@logger = logger
|
22
|
+
@formatter = options[:formatter]
|
23
|
+
end
|
24
|
+
|
25
|
+
def add(severity, message = nil, progname = nil, &block)
|
26
|
+
severity ||= ::Logger::UNKNOWN
|
27
|
+
if !@logger || severity < @level
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
|
31
|
+
message = (message || (block && block.call) || progname).to_s
|
32
|
+
|
33
|
+
if @formatter && @formatter.respond_to?(:call)
|
34
|
+
message = @formatter.call(message)
|
35
|
+
end
|
36
|
+
|
37
|
+
# If a newline is necessary then create a new message ending with a newline.
|
38
|
+
# Ensures that the original message is not mutated.
|
39
|
+
# message = "#{message}\n" unless message[-1] == ?\n
|
40
|
+
|
41
|
+
@logger.add(severity, message)
|
42
|
+
end
|
43
|
+
|
44
|
+
def <<(msg); @logger << msg; end
|
45
|
+
def write(msg); @logger.write(msg); end
|
46
|
+
|
47
|
+
def debug(progname = nil, &block)
|
48
|
+
add(::Logger::DEBUG, nil, progname, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def info(progname = nil, &block)
|
52
|
+
add(::Logger::INFO, nil, progname, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
def warn(progname = nil, &block)
|
56
|
+
add(::Logger::WARN, nil, progname, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def error(progname = nil, &block)
|
60
|
+
add(::Logger::ERROR, nil, progname, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def fatal(progname = nil, &block)
|
64
|
+
add(::Logger::FATAL, nil, progname, &block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def unknown(progname = nil, &block)
|
68
|
+
add(::Logger::UNKNOWN, nil, progname, &block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def debug?; @level <= DEBUG; end
|
72
|
+
|
73
|
+
def info?; @level <= INFO; end
|
74
|
+
|
75
|
+
def warn?; @level <= WARN; end
|
76
|
+
|
77
|
+
def error?; @level <= ERROR; end
|
78
|
+
|
79
|
+
def fatal?; @level <= FATAL; end
|
80
|
+
end # ForwardingLogger
|
81
|
+
end # Logger
|
82
|
+
end # Zookeeper
|
83
|
+
|
84
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Zookeeper
|
2
|
+
# just like stdlib Monitor but provides the SAME API AS MUTEX, FFS!
|
3
|
+
class Monitor
|
4
|
+
include MonitorMixin
|
5
|
+
|
6
|
+
alias try_enter try_mon_enter
|
7
|
+
alias enter mon_enter
|
8
|
+
alias exit mon_exit
|
9
|
+
|
10
|
+
# here, HERE!
|
11
|
+
# *here* are the methods that are the same
|
12
|
+
# god *dammit*
|
13
|
+
|
14
|
+
alias lock mon_enter
|
15
|
+
alias unlock mon_exit
|
16
|
+
alias try_lock try_mon_enter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
|
4
|
+
module Zookeeper
|
5
|
+
# @private
|
6
|
+
module RakeTasks
|
7
|
+
def self.define_test_tasks_for(*rubies)
|
8
|
+
rubies.each do |r|
|
9
|
+
|
10
|
+
TestOneRuby.new(:name => r) do |tor|
|
11
|
+
yield tor if block_given?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestOneRuby < ::Rake::TaskLib
|
17
|
+
include ::Rake::DSL if defined?(::Rake::DSL)
|
18
|
+
|
19
|
+
DEFAULT_RVM_RUBY_NAME = '1.9.3'
|
20
|
+
|
21
|
+
# defaults to 'zk', test tasks will be built under this
|
22
|
+
attr_accessor :namespace
|
23
|
+
|
24
|
+
# the name of the task
|
25
|
+
# (tasks will be 'zk:1.9.3:run_rspec')
|
26
|
+
#
|
27
|
+
# this is mainly here so that the rvm ruby name rbx-2.0.testing
|
28
|
+
# will have its tasks defined as 'zk:rbx'
|
29
|
+
attr_accessor :name
|
30
|
+
|
31
|
+
# what is the rvm name we should use for testing? (i.e. could be an alias)
|
32
|
+
# defaults to {#name}
|
33
|
+
attr_accessor :rvm_ruby_name
|
34
|
+
|
35
|
+
# any extra environment variables?
|
36
|
+
attr_accessor :env
|
37
|
+
|
38
|
+
# gemset name to use, deafults to the name of the gemspec in the top of the
|
39
|
+
# project directory (minus the .gempsec)
|
40
|
+
attr_accessor :gemset_name
|
41
|
+
|
42
|
+
# @private
|
43
|
+
attr_reader :ruby_with_gemset,
|
44
|
+
:create_gemset_name,
|
45
|
+
:clobber_task_name,
|
46
|
+
:clean_task_name,
|
47
|
+
:build_task_name,
|
48
|
+
:bundle_task_name,
|
49
|
+
:rspec_task_name,
|
50
|
+
:phony_gemfile_link_name,
|
51
|
+
:phony_gemfile_lock_name
|
52
|
+
|
53
|
+
|
54
|
+
def self.default_gemset_name
|
55
|
+
ary = Dir['*.gemspec']
|
56
|
+
raise 'No gemspec found' if ary.empty?
|
57
|
+
ary.first[/(.+)\.gemspec\Z/, 1]
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize(opts={})
|
61
|
+
@namespace = 'zk'
|
62
|
+
@name = nil
|
63
|
+
@env = {}
|
64
|
+
@rvm_ruby_name = nil
|
65
|
+
@gemset_name = nil
|
66
|
+
|
67
|
+
opts.each { |k,v| __send__(:"#{k}=", v) }
|
68
|
+
|
69
|
+
yield self if block_given?
|
70
|
+
|
71
|
+
@gemset_name ||= self.class.default_gemset_name
|
72
|
+
|
73
|
+
# XXX: add an exception just for me in here (yes, i know this is naughty)
|
74
|
+
# or else i'd have to do this in every zk variant i want to test
|
75
|
+
# (like i have to now)
|
76
|
+
|
77
|
+
unless @rvm_ruby_name
|
78
|
+
@rvm_ruby_name = 'rbx-2.0.testing' if @name == 'rbx'
|
79
|
+
end
|
80
|
+
|
81
|
+
@rvm_ruby_name ||= name
|
82
|
+
|
83
|
+
@ruby_with_gemset = "#{@rvm_ruby_name}@#{@gemset_name}"
|
84
|
+
@create_gemset_name = "#{namespace}:#{name}:create_gemset"
|
85
|
+
@clobber_task_name = "#{namespace}:#{name}:clobber"
|
86
|
+
@clean_task_name = "#{namespace}:#{name}:clean"
|
87
|
+
@build_task_name = "#{namespace}:#{name}:build"
|
88
|
+
@bundle_task_name = "#{namespace}:#{name}:bundle_install"
|
89
|
+
@rspec_task_name = "#{namespace}:#{name}:run_rspec"
|
90
|
+
@phony_gemfile_link_name = "Gemfile.#{name}"
|
91
|
+
@phony_gemfile_lock_name = "#{phony_gemfile_link_name}.lock"
|
92
|
+
|
93
|
+
define_tasks
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def need_ext_build?
|
98
|
+
name != 'jruby' && File.directory?('./ext')
|
99
|
+
end
|
100
|
+
|
101
|
+
def define_tasks
|
102
|
+
file phony_gemfile_link_name do
|
103
|
+
# apparently, rake doesn't deal with symlinks intelligently :P
|
104
|
+
ln_s('Gemfile', phony_gemfile_link_name) unless File.symlink?(phony_gemfile_link_name)
|
105
|
+
end
|
106
|
+
|
107
|
+
task :clean do
|
108
|
+
rm_rf [phony_gemfile_lock_name, phony_gemfile_lock_name]
|
109
|
+
end
|
110
|
+
|
111
|
+
task create_gemset_name do
|
112
|
+
sh "rvm #{rvm_ruby_name} do rvm gemset create #{gemset_name}"
|
113
|
+
end
|
114
|
+
|
115
|
+
task clobber_task_name do
|
116
|
+
if need_ext_build?
|
117
|
+
cd 'ext' do
|
118
|
+
sh "rake clobber"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
task clean_task_name do
|
124
|
+
if need_ext_build?
|
125
|
+
cd 'ext' do
|
126
|
+
sh "rake clean"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
task build_task_name => [create_gemset_name, clean_task_name] do
|
132
|
+
if need_ext_build?
|
133
|
+
cd 'ext' do
|
134
|
+
sh "rvm #{ruby_with_gemset} do rake build"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
task bundle_task_name => [phony_gemfile_link_name, build_task_name] do
|
140
|
+
sh "rvm #{ruby_with_gemset} do bundle install --gemfile #{phony_gemfile_link_name}"
|
141
|
+
end
|
142
|
+
|
143
|
+
task rspec_task_name => bundle_task_name do
|
144
|
+
sh "rvm #{ruby_with_gemset} do env BUNDLE_GEMFILE=#{phony_gemfile_link_name} bundle exec rspec spec --fail-fast"
|
145
|
+
end
|
146
|
+
|
147
|
+
task "#{namespace}:#{name}" => rspec_task_name
|
148
|
+
|
149
|
+
task "#{namespace}:test_all_rubies" => rspec_task_name
|
150
|
+
|
151
|
+
unless Rake::Task.task_defined?("#{namespace}:test_all")
|
152
|
+
task "#{namespace}:test_all" do
|
153
|
+
require 'benchmark'
|
154
|
+
t = Benchmark.realtime do
|
155
|
+
Rake::Task["#{namespace}:test_all_rubies"].invoke
|
156
|
+
end
|
157
|
+
|
158
|
+
$stderr.puts "Test run took: #{t} s"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Zookeeper
|
2
|
+
class RequestRegistry
|
3
|
+
include Constants
|
4
|
+
include Logger
|
5
|
+
|
6
|
+
# @param [Hash] opts
|
7
|
+
# @option opts [String] :chroot_path (nil) if given, will be used to
|
8
|
+
# correct a discrepancy between the C and Java clients when using a
|
9
|
+
# chrooted connection. If given, the chroot path will be stripped from
|
10
|
+
# the string returned by a `create`. It should be an absolute path.
|
11
|
+
#
|
12
|
+
def initialize(watcher, opts={})
|
13
|
+
@mutex = Monitor.new
|
14
|
+
|
15
|
+
@default_watcher = watcher
|
16
|
+
|
17
|
+
@current_req_id = 0
|
18
|
+
@watcher_reqs = {}
|
19
|
+
@completion_reqs = {}
|
20
|
+
|
21
|
+
@chroot_path = opts[:chroot_path]
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_watcher
|
25
|
+
@mutex.synchronize { @default_watcher }
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_watcher=(blk)
|
29
|
+
@mutex.synchronize { @default_watcher = blk }
|
30
|
+
end
|
31
|
+
|
32
|
+
def setup_call(meth_name, opts)
|
33
|
+
req_id = nil
|
34
|
+
@mutex.synchronize {
|
35
|
+
req_id = @current_req_id
|
36
|
+
@current_req_id += 1
|
37
|
+
setup_completion(req_id, meth_name, opts) if opts[:callback]
|
38
|
+
setup_watcher(req_id, opts) if opts[:watcher]
|
39
|
+
}
|
40
|
+
req_id
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_context_for(hash)
|
44
|
+
return nil unless hash
|
45
|
+
|
46
|
+
is_session_event = (hash[:type] == ZOO_SESSION_EVENT)
|
47
|
+
|
48
|
+
req_id = hash.fetch(:req_id)
|
49
|
+
|
50
|
+
if hash.has_key?(:rc)
|
51
|
+
get_completion(req_id, :keep => is_session_event)
|
52
|
+
else
|
53
|
+
get_watcher(req_id, :keep => is_session_event)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def clear_watchers!
|
58
|
+
@mutex.synchronize { @watcher_reqs.clear }
|
59
|
+
end
|
60
|
+
|
61
|
+
# if we're chrooted, this method will strip the chroot prefix from +path+
|
62
|
+
def strip_chroot_from(path)
|
63
|
+
return path unless (chrooted? and path and path.start_with?(@chroot_path))
|
64
|
+
path[@chroot_path.length..-1]
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def get_completion(req_id, opts={})
|
69
|
+
@mutex.synchronize do
|
70
|
+
if opts[:keep]
|
71
|
+
@completion_reqs[req_id]
|
72
|
+
else
|
73
|
+
@completion_reqs.delete(req_id)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return the watcher hash associated with the req_id. If the req_id
|
79
|
+
# is the ZKRB_GLOBAL_CB_REQ, then does not clear the req from the internal
|
80
|
+
# store, otherwise the req_id is removed.
|
81
|
+
#
|
82
|
+
def get_watcher(req_id, opts={})
|
83
|
+
@mutex.synchronize do
|
84
|
+
if Constants::ZKRB_GLOBAL_CB_REQ == req_id
|
85
|
+
{ :watcher => @default_watcher, :watcher_context => nil }
|
86
|
+
elsif opts[:keep]
|
87
|
+
@watcher_reqs[req_id]
|
88
|
+
else
|
89
|
+
@watcher_reqs.delete(req_id)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def setup_watcher(req_id, call_opts)
|
96
|
+
@mutex.synchronize do
|
97
|
+
@watcher_reqs[req_id] = {
|
98
|
+
:watcher => call_opts[:watcher],
|
99
|
+
:context => call_opts[:watcher_context]
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# as a hack, to provide consistency between the java implementation and the C
|
105
|
+
# implementation when dealing w/ chrooted connections, we override this in
|
106
|
+
# ext/zookeeper_base.rb to wrap the callback in a chroot-path-stripping block.
|
107
|
+
#
|
108
|
+
# we don't use meth_name here, but we need it in the C implementation
|
109
|
+
#
|
110
|
+
def setup_completion(req_id, meth_name, call_opts)
|
111
|
+
@mutex.synchronize do
|
112
|
+
@completion_reqs[req_id] = {
|
113
|
+
:callback => maybe_wrap_callback(meth_name, call_opts[:callback]),
|
114
|
+
:context => call_opts[:callback_context]
|
115
|
+
}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# this is a hack: to provide consistency between the C and Java drivers when
|
120
|
+
# using a chrooted connection, we wrap the callback in a block that will
|
121
|
+
# strip the chroot path from the returned path (important in an async create
|
122
|
+
# sequential call). This is the only place where we can hook *just* the C
|
123
|
+
# version. The non-async manipulation is handled in ZookeeperBase#create.
|
124
|
+
#
|
125
|
+
# TODO: need to move the continuation setup into here, so that it can get
|
126
|
+
# added to the callback hash
|
127
|
+
#
|
128
|
+
def maybe_wrap_callback(meth_name, cb)
|
129
|
+
return cb unless cb and chrooted? and (meth_name == :create)
|
130
|
+
|
131
|
+
lambda do |hash|
|
132
|
+
# in this case the string will be the absolute zookeeper path (i.e.
|
133
|
+
# with the chroot still prepended to the path). Here's where we strip it off
|
134
|
+
hash[:string] = strip_chroot_from(hash[:string])
|
135
|
+
|
136
|
+
# call the original callback
|
137
|
+
cb.call(hash)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def chrooted?
|
142
|
+
@chroot_path && !@chroot_path.empty?
|
143
|
+
end
|
144
|
+
|
145
|
+
def default_watcher_proc
|
146
|
+
Proc.new { |args|
|
147
|
+
logger.debug { "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}" }
|
148
|
+
true
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|