zookeeper-ng 1.5.2.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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/.github/workflows/build.yml +57 -0
- data/.gitignore +19 -0
- data/.gitmodules +3 -0
- data/CHANGELOG +408 -0
- data/Gemfile +30 -0
- data/Guardfile +8 -0
- data/LICENSE +23 -0
- data/Manifest +29 -0
- data/README.markdown +62 -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-buffer-overflow.patch +11 -0
- data/ext/patches/zkc-3.4.5-config.patch +5454 -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-yosemite-htonl-fix.patch +102 -0
- data/ext/zkc-3.4.5.tar.gz +0 -0
- data/ext/zkrb.c +1080 -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 +501 -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/queue_with_pipe.rb +110 -0
- data/lib/zookeeper/common.rb +122 -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/forwarding_logger.rb +84 -0
- data/lib/zookeeper/logger.rb +39 -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/lib/zookeeper.rb +115 -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 +122 -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 +1081 -0
- data/spec/spec_helper.rb +61 -0
- data/spec/support/00_logging.rb +38 -0
- data/spec/support/10_spawn_zookeeper.rb +20 -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 +46 -0
- data/zoomonkey/duplicates +3 -0
- data/zoomonkey/zoomonkey.rb +194 -0
- metadata +185 -0
@@ -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,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
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Zookeeper
|
2
|
+
class Stat
|
3
|
+
attr_reader :version, :exists, :czxid, :mzxid, :ctime, :mtime, :cversion, :aversion, :ephemeralOwner, :dataLength, :numChildren, :pzxid
|
4
|
+
|
5
|
+
alias :ephemeral_owner :ephemeralOwner
|
6
|
+
alias :num_children :numChildren
|
7
|
+
alias :data_length :dataLength
|
8
|
+
|
9
|
+
def initialize(val)
|
10
|
+
@exists = !!val
|
11
|
+
@czxid, @mzxid, @ctime, @mtime, @version, @cversion, @aversion,
|
12
|
+
@ephemeralOwner, @dataLength, @numChildren, @pzxid = val if val.is_a?(Array)
|
13
|
+
val.each { |k,v| instance_variable_set "@#{k}", v } if val.is_a?(Hash)
|
14
|
+
raise ArgumentError unless (val.is_a?(Hash) or val.is_a?(Array) or val.nil?)
|
15
|
+
end
|
16
|
+
|
17
|
+
def exists?
|
18
|
+
@exists
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/zookeeper.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# Ruby wrapper for the Zookeeper C API
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
require 'monitor'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'logger'
|
7
|
+
require 'benchmark'
|
8
|
+
|
9
|
+
module Zookeeper
|
10
|
+
ZOOKEEPER_ROOT = File.expand_path('../..', __FILE__)
|
11
|
+
|
12
|
+
# require a path relative to the lib directory
|
13
|
+
# this is to avoid monkeying explicitly with $LOAD_PATH
|
14
|
+
#
|
15
|
+
# @private
|
16
|
+
def self.require_lib(*relpaths)
|
17
|
+
relpaths.each do |relpath|
|
18
|
+
require File.join(ZOOKEEPER_ROOT, 'lib', relpath)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# require a path that's relative to ZOOKEEPER_ROOT
|
23
|
+
# @private
|
24
|
+
def self.require_root(*relpaths)
|
25
|
+
relpaths.each do |relpath|
|
26
|
+
require File.join(ZOOKEEPER_ROOT, relpath)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Zookeeper.require_lib(
|
32
|
+
'zookeeper/core_ext',
|
33
|
+
'zookeeper/monitor',
|
34
|
+
'zookeeper/logger',
|
35
|
+
'zookeeper/logger/forwarding_logger',
|
36
|
+
'zookeeper/forked',
|
37
|
+
'zookeeper/latch',
|
38
|
+
'zookeeper/acls',
|
39
|
+
'zookeeper/constants',
|
40
|
+
'zookeeper/exceptions',
|
41
|
+
'zookeeper/continuation',
|
42
|
+
'zookeeper/common',
|
43
|
+
'zookeeper/request_registry',
|
44
|
+
'zookeeper/callbacks',
|
45
|
+
'zookeeper/stat',
|
46
|
+
'zookeeper/client_methods'
|
47
|
+
)
|
48
|
+
|
49
|
+
# ok, now we construct the client
|
50
|
+
Zookeeper.require_lib 'zookeeper/client'
|
51
|
+
|
52
|
+
module Zookeeper
|
53
|
+
include Constants
|
54
|
+
#::Logger.new($stderr).tap { |l| l.level = ENV['ZOOKEEPER_DEBUG'] ? ::Logger::DEBUG : ::Logger::ERROR }
|
55
|
+
#
|
56
|
+
|
57
|
+
@@logger = nil unless defined?(@@logger)
|
58
|
+
|
59
|
+
def self.logger
|
60
|
+
@@logger
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.logger=(logger)
|
64
|
+
@@logger = logger
|
65
|
+
end
|
66
|
+
|
67
|
+
# @private
|
68
|
+
def self.deprecation_warnings?
|
69
|
+
@deprecation_warnings = true if @deprecation_warnings.nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
# set this to false to mute Zookeeper related deprecation warnings...
|
73
|
+
# __AT YOUR PERIL__
|
74
|
+
def self.deprecation_warnings=(v)
|
75
|
+
@deprecation_warnings = v
|
76
|
+
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
def self.deprecation_warning(warning)
|
80
|
+
Kernel.warn(warning) if deprecation_warnings?
|
81
|
+
end
|
82
|
+
|
83
|
+
# for expert use only. set the underlying debug level for the C layer, has no
|
84
|
+
# effect in java
|
85
|
+
#
|
86
|
+
# @private
|
87
|
+
def self.set_debug_level(val)
|
88
|
+
if defined?(CZookeeper)
|
89
|
+
CZookeeper.set_debug_level(val.to_i)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @private
|
94
|
+
def self.get_debug_level
|
95
|
+
if defined?(CZookeeper)
|
96
|
+
CZookeeper.get_debug_level
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class << self
|
101
|
+
# @private
|
102
|
+
alias :debug_level= :set_debug_level
|
103
|
+
|
104
|
+
# @private
|
105
|
+
alias :debug_level :get_debug_level
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# just for first test, get rid of this soon
|
110
|
+
Zookeeper.require_lib 'zookeeper/compatibility'
|
111
|
+
|
112
|
+
if ENV['ZKRB_DEBUG']
|
113
|
+
Zookeeper.debug_level = Zookeeper::Constants::ZOO_LOG_LEVEL_DEBUG
|
114
|
+
end
|
115
|
+
|
data/notes.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Notes on this fork of http://github.com/twitter/zookeeper
|
2
|
+
|
3
|
+
The main purpose of this fork is to provide JRuby compatibility with the MRI driver of the original. We have been using an early fork with an incomplete binding to the C client, and had recently bumped up against a fairly serious bug with handling events. The twitter/zookeeper driver solved this problem but was lacking JRuby support (which is a core piece of our environment).
|
4
|
+
|
5
|
+
I've packaged the Java client (and its dependency on log4j) as gems that are installed separately from this codebase to cut down on the size of the zookeeper gem. If this poses a problem (for instance, if the original goal was to have an all-in-one install with no external dependencies), it would be trivial to package those jars along with this code.
|
6
|
+
|
7
|
+
In the course of writing the wrapper for JRuby, I've written nearly-complete specs for all of the public API methods: get, set, get_children, stat, create, delete, get_acl, and set_acl. The reason I say they're "nearly" complete is that I have no use for set_acl, and quite honestly, couldn't figure out how to make it work.
|
8
|
+
|
9
|
+
I'm planning on writing a companion gem, 'ZK', that would take some of the higher-level constructs that we'd written around the lower-level driver to implement features like locking and queues, and also to provide a more ruby-like interface.
|
10
|
+
|
11
|
+
I'd like to reorganize this codebase in a number of ways, most of all to move all of the various classes and modules under a common "Zookeeper" namespace, however I thought that would be a radical enough change where I'd want to discuss/coordinate with you on how exactly to do it.
|
12
|
+
|
13
|
+
|
14
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if ARGV.empty?
|
4
|
+
$stderr.puts <<-EOS
|
5
|
+
Usage: #{File.basename(__FILE__)} file1 file2 file3
|
6
|
+
|
7
|
+
Fix references to Zookeeper classes and modules.
|
8
|
+
|
9
|
+
This script acts like sed and edits files in place (not saving backups,
|
10
|
+
as you *are* using source control and aren't a complete tool).
|
11
|
+
|
12
|
+
if you have any doubts, *read the script*:
|
13
|
+
----------------------------------------------------------------------
|
14
|
+
|
15
|
+
#{File.read(__FILE__)}
|
16
|
+
|
17
|
+
EOS
|
18
|
+
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
require 'tempfile'
|
24
|
+
require 'fileutils'
|
25
|
+
|
26
|
+
ARGV.each do |path|
|
27
|
+
Tempfile.open(File.basename(path)) do |tmp|
|
28
|
+
File.open(path) do |input|
|
29
|
+
while line = input.gets
|
30
|
+
tmp.puts line.gsub(/\bZookeeperStat::Stat\b/, 'Zookeeper::Stat').
|
31
|
+
gsub(/\bZookeeper::(\w+)Callback\b/, 'Zookeeper::Callbacks::\1Callback').
|
32
|
+
gsub(/\bZookeeperACLs::(ZOO_\w+)\b/, 'Zookeeper::Constants::\1').
|
33
|
+
gsub(/\bZookeeperExceptions::ZookeeperException::(\w+)\b/, 'Zookeeper::Exceptions::\1').
|
34
|
+
gsub(/\bZookeeper(Constants|Exceptions|Common|ACLs|Callbacks)\b/, 'Zookeeper::\1').
|
35
|
+
gsub(/\bZookeeperException::(\w+)\b/, 'Exceptions::\1')
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
tmp.fsync
|
41
|
+
tmp.close
|
42
|
+
|
43
|
+
FileUtils.mv(tmp.path, path)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# tests the CZookeeper, obviously only available when running under MRI
|
2
|
+
|
3
|
+
unless defined?(::JRUBY_VERSION)
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
describe Zookeeper::CZookeeper do
|
7
|
+
def pop_all_events
|
8
|
+
[].tap do |rv|
|
9
|
+
begin
|
10
|
+
rv << @event_queue.pop(non_blocking=true)
|
11
|
+
rescue ThreadError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def wait_until_connected(timeout=10)
|
17
|
+
wait_until(timeout) { @czk.state == Zookeeper::Constants::ZOO_CONNECTED_STATE }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe do
|
21
|
+
before do
|
22
|
+
@event_queue = Zookeeper::Common::QueueWithPipe.new
|
23
|
+
@czk = Zookeeper::CZookeeper.new(Zookeeper.default_cnx_str, @event_queue)
|
24
|
+
end
|
25
|
+
|
26
|
+
after do
|
27
|
+
@czk.close rescue Exception
|
28
|
+
@event_queue.close rescue Exception
|
29
|
+
end
|
30
|
+
|
31
|
+
it %[should be in connected state within a reasonable amount of time] do
|
32
|
+
wait_until_connected.should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
describe :after_connected do
|
36
|
+
before do
|
37
|
+
wait_until_connected.should be_true
|
38
|
+
end
|
39
|
+
|
40
|
+
it %[should have a connection event after being connected] do
|
41
|
+
event = wait_until(10) { @event_queue.pop }
|
42
|
+
event.should be
|
43
|
+
event[:req_id].should == Zookeeper::Constants::ZKRB_GLOBAL_CB_REQ
|
44
|
+
event[:type].should == Zookeeper::Constants::ZOO_SESSION_EVENT
|
45
|
+
event[:state].should == Zookeeper::Constants::ZOO_CONNECTED_STATE
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|