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,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
@@ -0,0 +1,4 @@
1
+ module Zookeeper
2
+ VERSION = '1.5.2.1'
3
+ DRIVER_VERSION = '3.4.5'
4
+ 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
+