zookeeper-ng 1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) 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/.gitignore +19 -0
  7. data/.gitmodules +3 -0
  8. data/.travis.yml +25 -0
  9. data/CHANGELOG +395 -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 +85 -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-fetch-and-add.patch +16 -0
  29. data/ext/patches/zkc-3.4.5-logging.patch +41 -0
  30. data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
  31. data/ext/patches/zkc-3.4.5-overflow.patch +11 -0
  32. data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
  33. data/ext/zkc-3.4.5.tar.gz +0 -0
  34. data/ext/zkrb.c +1075 -0
  35. data/ext/zkrb_wrapper.c +775 -0
  36. data/ext/zkrb_wrapper.h +350 -0
  37. data/ext/zkrb_wrapper_compat.c +15 -0
  38. data/ext/zkrb_wrapper_compat.h +11 -0
  39. data/ext/zookeeper_base.rb +256 -0
  40. data/java/java_base.rb +503 -0
  41. data/lib/zookeeper.rb +115 -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.rb +122 -0
  47. data/lib/zookeeper/common/queue_with_pipe.rb +110 -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.rb +39 -0
  57. data/lib/zookeeper/logger/forwarding_logger.rb +84 -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/notes.txt +14 -0
  64. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  65. data/spec/c_zookeeper_spec.rb +51 -0
  66. data/spec/chrooted_connection_spec.rb +83 -0
  67. data/spec/compatibilty_spec.rb +8 -0
  68. data/spec/default_watcher_spec.rb +41 -0
  69. data/spec/em_spec.rb +51 -0
  70. data/spec/ext/zookeeper_base_spec.rb +19 -0
  71. data/spec/forked_connection_spec.rb +124 -0
  72. data/spec/latch_spec.rb +24 -0
  73. data/spec/log4j.properties +17 -0
  74. data/spec/shared/all_success_return_values.rb +10 -0
  75. data/spec/shared/connection_examples.rb +1077 -0
  76. data/spec/spec_helper.rb +61 -0
  77. data/spec/support/00_logging.rb +38 -0
  78. data/spec/support/10_spawn_zookeeper.rb +24 -0
  79. data/spec/support/progress_formatter.rb +15 -0
  80. data/spec/support/zookeeper_spec_helpers.rb +96 -0
  81. data/spec/zookeeper_spec.rb +24 -0
  82. data/zookeeper.gemspec +38 -0
  83. data/zoomonkey/duplicates +3 -0
  84. data/zoomonkey/zoomonkey.rb +194 -0
  85. metadata +157 -0
@@ -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'
3
+ DRIVER_VERSION = '3.4.5'
4
+ end
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
+
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'shared/connection_examples'
3
+
4
+ describe 'Zookeeper chrooted' do
5
+ let(:path) { "/_zkchroottest_" }
6
+ let(:data) { "underpants" }
7
+ let(:chroot_path) { '/slyphon-zookeeper-chroot' }
8
+
9
+ let(:connection_string) { "#{Zookeeper.default_cnx_str}#{chroot_path}" }
10
+
11
+ before do
12
+ @zk = Zookeeper.new(connection_string)
13
+ end
14
+
15
+ after do
16
+ @zk and @zk.close
17
+ end
18
+
19
+ def zk
20
+ @zk
21
+ end
22
+
23
+ describe 'non-existent' do
24
+ describe 'with existing parent' do
25
+ let(:chroot_path) { '/one-level' }
26
+
27
+ describe 'create' do
28
+ before do
29
+ with_open_zk { |z| rm_rf(z, chroot_path) }
30
+ end
31
+
32
+ after do
33
+ with_open_zk { |z| rm_rf(z, chroot_path) }
34
+ end
35
+
36
+ it %[should successfully create the path] do
37
+ rv = zk.create(:path => '/', :data => '')
38
+ rv[:rc].should be_zero
39
+ rv[:path].should == ''
40
+ end
41
+ end
42
+ end
43
+
44
+ describe 'with missing parent' do
45
+ let(:chroot_path) { '/deeply/nested/path' }
46
+
47
+ describe 'create' do
48
+ before do
49
+ with_open_zk do |z|
50
+ rm_rf(z, chroot_path)
51
+ end
52
+ end
53
+
54
+ it %[should return ZNONODE] do
55
+ rv = zk.create(:path => '/', :data => '')
56
+ rv[:rc].should_not be_zero
57
+ rv[:rc].should == Zookeeper::Exceptions::ZNONODE
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+
64
+ describe do
65
+ before :all do
66
+ logger.warn "running before :all"
67
+
68
+ with_open_zk do |z|
69
+ z.create(:path => chroot_path, :data => '')
70
+ end
71
+ end
72
+
73
+ after :all do
74
+ with_open_zk do |z|
75
+ rm_rf(z, chroot_path)
76
+ end
77
+ end
78
+
79
+ it_should_behave_like "connection"
80
+ end
81
+ end
82
+
83
+
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Compatibiliy layer' do
4
+ it %[should raise the correct error when a const is missing] do
5
+ lambda { Zookeeper::THISISANINVALIDCONST }.should raise_error(NameError)
6
+ end
7
+ end
8
+
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zookeeper do
4
+ describe :initialize, 'with watcher block' do
5
+ before do
6
+ @events = []
7
+ @watch_block = lambda do |hash|
8
+ logger.debug "watch_block: #{hash.inspect}"
9
+ @events << hash
10
+ end
11
+
12
+ @zk = Zookeeper.new(Zookeeper.default_cnx_str, 10, @watch_block)
13
+
14
+ wait_until(2) { @zk.connected? }
15
+ @zk.should be_connected
16
+ logger.debug "connected!"
17
+
18
+ wait_until(2) { !@events.empty? }
19
+ logger.debug "got events!"
20
+ end
21
+
22
+ after do
23
+ @zk.close if @zk.connected?
24
+ end
25
+
26
+ it %[should receive initial connection state events] do
27
+ @events.should_not be_empty
28
+ @events.length.should == 1
29
+ @events.first[:state].should == Zookeeper::ZOO_CONNECTED_STATE
30
+ end
31
+
32
+ it %[should receive disconnection events] do
33
+ pending "the C driver doesn't appear to deliver disconnection events (?)"
34
+ @events.clear
35
+ @zk.close
36
+ wait_until(2) { !@events.empty? }
37
+ @events.should_not be_empty
38
+ end
39
+ end
40
+ end
41
+
data/spec/em_spec.rb ADDED
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ require 'zookeeper/em_client'
3
+
4
+ gem 'evented-spec', '~> 0.9.0'
5
+ require 'evented-spec'
6
+
7
+
8
+ describe 'ZookeeperEM' do
9
+ describe 'Client' do
10
+ include EventedSpec::SpecHelper
11
+ default_timeout 3.0
12
+
13
+ def setup_zk
14
+ @zk = ZookeeperEM::Client.new(Zookeeper.default_cnx_str)
15
+ em do
16
+ @zk.on_attached do
17
+ yield
18
+ end
19
+ end
20
+ end
21
+
22
+ def teardown_and_done
23
+ @zk.close do
24
+ logger.debug { "TEST: about to call done" }
25
+ EM.next_tick do
26
+ done
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'callbacks' do
32
+ it %[should be called on the reactor thread] do
33
+ cb = lambda do |h|
34
+ EM.reactor_thread?.should be_true
35
+ logger.debug { "called back on the reactor thread? #{EM.reactor_thread?}" }
36
+ teardown_and_done
37
+ end
38
+
39
+ setup_zk do
40
+ @zk.on_attached do |*|
41
+ logger.debug { "on_attached called" }
42
+ rv = @zk.get(:path => '/', :callback => cb)
43
+ logger.debug { "rv from @zk.get: #{rv.inspect}" }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ unless defined?(::JRUBY_VERSION)
4
+ describe Zookeeper::ZookeeperBase do
5
+ before do
6
+ @zk = described_class.new(Zookeeper.default_cnx_str)
7
+ end
8
+
9
+ after do
10
+ @zk.close unless @zk.closed?
11
+ end
12
+
13
+ it %[should have an original_pid assigned] do
14
+ @zk.original_pid.should == Process.pid
15
+ end
16
+ end
17
+ end
18
+
19
+
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ unless defined?(::JRUBY_VERSION)
4
+ describe %[forked connection] do
5
+ let(:path) { "/_zktest_" }
6
+ let(:pids_root) { "#{path}/pids" }
7
+ let(:data) { "underpants" }
8
+ let(:connection_string) { Zookeeper.default_cnx_str }
9
+
10
+ def process_alive?(pid)
11
+ Process.kill(0, @pid)
12
+ true
13
+ rescue Errno::ESRCH
14
+ false
15
+ end
16
+
17
+ LBORDER = ('-' * 35) << '< '
18
+ RBORDER = ' >' << ('-' * 35)
19
+
20
+ def mark(thing)
21
+ logger << "\n#{LBORDER}#{thing}#{RBORDER}\n\n"
22
+ end
23
+
24
+ before do
25
+ mark "BEFORE: START"
26
+ if defined?(::Rubinius)
27
+ pending("this test is currently broken in rbx")
28
+ # elsif ENV['TRAVIS']
29
+ # pending("this test is currently hanging in travis")
30
+ else
31
+ @zk = Zookeeper.new(connection_string)
32
+ rm_rf(@zk, path)
33
+ end
34
+ mark "BEFORE: END"
35
+ end
36
+
37
+ after do
38
+ mark "AFTER: START"
39
+
40
+ if @pid and process_alive?(@pid)
41
+ begin
42
+ Process.kill('KILL', @pid)
43
+ p Process.wait2(@pid)
44
+ rescue Errno::ESRCH
45
+ end
46
+ end
47
+
48
+ @zk.close if @zk and !@zk.closed?
49
+ with_open_zk(connection_string) { |z| rm_rf(z, path) }
50
+
51
+ mark "AFTER: END"
52
+ end
53
+
54
+ def wait_for_child_safely(pid, timeout=5)
55
+ time_to_stop = Time.now + timeout
56
+
57
+ until Time.now > time_to_stop
58
+ if a = Process.wait2(@pid, Process::WNOHANG)
59
+ return a.last
60
+ else
61
+ sleep(0.01)
62
+ end
63
+ end
64
+
65
+ nil
66
+ end
67
+
68
+ it %[should do the right thing and not fail] do
69
+ mark "TEST: START"
70
+
71
+ @zk.wait_until_connected
72
+
73
+ mkdir_p(@zk, pids_root)
74
+
75
+ # the parent's pid path
76
+ @zk.create(:path => "#{pids_root}/#{$$}", :data => $$.to_s)
77
+
78
+ @latch = Zookeeper::Latch.new
79
+ @event = nil
80
+
81
+ cb = proc do |h|
82
+ logger.debug { "watcher called back: #{h.inspect}" }
83
+ @event = h
84
+ @latch.release
85
+ end
86
+
87
+ @zk.stat(:path => "#{pids_root}/child", :watcher => cb)
88
+
89
+ @zk.pause_before_fork_in_parent
90
+
91
+ mark "FORK"
92
+
93
+ @pid = fork do
94
+ logger.debug { "reopening connection in child: #{$$}" }
95
+ @zk.reopen
96
+ logger.debug { "creating path" }
97
+ rv = @zk.create(:path => "#{pids_root}/child", :data => $$.to_s)
98
+ logger.debug { "created path #{rv[:path]}" }
99
+ @zk.close
100
+
101
+ logger.debug { "close finished" }
102
+ exit!(0)
103
+ end
104
+
105
+ @zk.resume_after_fork_in_parent
106
+
107
+ event_waiter_th = Thread.new do
108
+ @latch.await(5) unless @event
109
+ @event
110
+ end
111
+
112
+ logger.debug { "waiting on child #{@pid}" }
113
+
114
+ status = wait_for_child_safely(@pid)
115
+ raise "Child process did not exit, likely hung" unless status
116
+
117
+ status.should_not be_signaled
118
+ status.should be_success
119
+
120
+ event_waiter_th.join(5).should == event_waiter_th
121
+ @event.should_not be_nil
122
+ end
123
+ end
124
+ end