zookeeper 0.4.4 → 0.9.3
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.
- data/.gitignore +10 -0
- data/CHANGELOG +95 -0
- data/Gemfile +17 -0
- data/Manifest +8 -2
- data/README.markdown +59 -0
- data/Rakefile +137 -7
- data/ext/.gitignore +6 -0
- data/ext/Rakefile +51 -0
- data/ext/c_zookeeper.rb +212 -0
- data/ext/dbg.h +53 -0
- data/ext/depend +5 -0
- data/ext/extconf.rb +44 -15
- data/ext/generate_gvl_code.rb +316 -0
- data/ext/zkc-3.3.5.tar.gz +0 -0
- data/ext/zkrb_wrapper.c +731 -0
- data/ext/zkrb_wrapper.h +330 -0
- data/ext/zkrb_wrapper_compat.c +15 -0
- data/ext/zkrb_wrapper_compat.h +11 -0
- data/ext/zookeeper_base.rb +211 -0
- data/ext/zookeeper_c.c +268 -97
- data/ext/zookeeper_lib.c +157 -92
- data/ext/zookeeper_lib.h +12 -6
- data/java/zookeeper_base.rb +477 -0
- data/lib/zookeeper/acls.rb +10 -1
- data/lib/zookeeper/callbacks.rb +5 -3
- data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
- data/lib/zookeeper/common.rb +174 -0
- data/lib/zookeeper/constants.rb +31 -28
- data/lib/zookeeper/em_client.rb +55 -0
- data/lib/zookeeper/exceptions.rb +10 -2
- data/lib/zookeeper/stat.rb +11 -2
- data/lib/zookeeper/version.rb +6 -0
- data/lib/zookeeper.rb +155 -122
- data/notes.txt +14 -0
- data/spec/c_zookeeper_spec.rb +50 -0
- data/spec/chrooted_connection_spec.rb +81 -0
- data/spec/default_watcher_spec.rb +41 -0
- data/spec/em_spec.rb +51 -0
- data/spec/log4j.properties +17 -0
- data/spec/shared/all_success_return_values.rb +10 -0
- data/spec/shared/connection_examples.rb +1018 -0
- data/spec/spec_helper.rb +119 -0
- data/spec/support/progress_formatter.rb +15 -0
- data/spec/zookeeper_spec.rb +24 -0
- data/zookeeper.gemspec +37 -25
- metadata +78 -34
- data/README +0 -42
- data/ext/zkc-3.3.2.tar.gz +0 -0
data/.gitignore
ADDED
data/CHANGELOG
CHANGED
@@ -1,3 +1,97 @@
|
|
1
|
+
v0.9.3 Event thread shutdown fix, Windows compatibility fix
|
2
|
+
|
3
|
+
* Use a 'shutdown thread' to coordinate cleanup if close is called from the
|
4
|
+
event thread (prevents deadlock)
|
5
|
+
|
6
|
+
* Default Logger now uses $stderr instead of opening /dev/null [#16]
|
7
|
+
|
8
|
+
* Gemfile/gemspec/Rakefile refactoring.
|
9
|
+
|
10
|
+
v0.9.2 More efficient and simpler wrappers for GIL release
|
11
|
+
|
12
|
+
* After a code review by Andrew Wason (rectalogic), use a much simpler
|
13
|
+
technique for creating the arg structs and passing them to the
|
14
|
+
zkrb_gvl_* functions. No malloc(), no free(), no problem.
|
15
|
+
|
16
|
+
v0.9.1 see v0.8.4 notes, same patch
|
17
|
+
|
18
|
+
v0.9.0 RELEASE THE KRAK..er, GIL!!
|
19
|
+
|
20
|
+
* In >= 1.9.2 the ruby interpreter allows you to release the GIL when
|
21
|
+
calling into native code, sounds like a good idea.
|
22
|
+
|
23
|
+
This release makes use of that code by parsing the zookeeper.h header file
|
24
|
+
and extracting the method signatures of all relevant zoo_* functions, then
|
25
|
+
generating boilerplate that allows us to call those functions via the
|
26
|
+
rb_thread_blocking_region function.
|
27
|
+
|
28
|
+
1.8.7 compatibility is maintained by stubbing out that functionality if built
|
29
|
+
under 1.8.7.
|
30
|
+
|
31
|
+
* 1.8.7 is deprecated! I will continue to support 1.8.7 for the near future
|
32
|
+
but sometime soon, you're gonna have to upgrade.
|
33
|
+
|
34
|
+
v0.8.4 fix NameError, require 'forwardable'
|
35
|
+
|
36
|
+
* Really not sure why this didn't come up in tests
|
37
|
+
|
38
|
+
* issue here https://github.com/slyphon/zk/issues/22
|
39
|
+
|
40
|
+
v0.8.3 fix NonLocalJump exception in event delivery thread shutdown code
|
41
|
+
|
42
|
+
* hit a corner case where we're waiting for the zkc handle setup
|
43
|
+
and the user decides to shutdown, but before we've had a chance
|
44
|
+
to enter the delivery loop.
|
45
|
+
|
46
|
+
* Cleaned up some nasty code in ZookeeperConstants
|
47
|
+
|
48
|
+
* removed ZookeeperConstants#print_events and ZookeeperConstants#print_states
|
49
|
+
|
50
|
+
* changed EVENT_TYPE_NAMES and EVENT_STATE_NAMES in ZookeeperConstants
|
51
|
+
to use string values instead of symbols
|
52
|
+
|
53
|
+
v0.8.2 fix close after a fork()
|
54
|
+
|
55
|
+
* The dispatch thread will be dead in this situation, so we need to
|
56
|
+
check to see if it's already dead before waiting on it to exit.
|
57
|
+
|
58
|
+
v0.8.1 Java client fix, silence warnings
|
59
|
+
|
60
|
+
v0.8.0 Refactor C implementaion, EventMachine client
|
61
|
+
|
62
|
+
* separated CZookeeper and ZookeeperBase implementation
|
63
|
+
|
64
|
+
This solves issues with reopen not working properly, makes for a much
|
65
|
+
cleaner event delivery implementation. ZookeeperBase controls the lifecycle
|
66
|
+
of the event dispatch thread now, rather than it being tied to CZookeeper.
|
67
|
+
|
68
|
+
* added support for the 'sync' API call
|
69
|
+
|
70
|
+
* Refactored zookeeper_c.c and zookeeper_lib.c
|
71
|
+
|
72
|
+
More error checking in zookeeper_lib.c and restructure some things to make
|
73
|
+
logic easier to follow
|
74
|
+
|
75
|
+
Fix bug in method_get_next_event that made the shutdown case so complicated
|
76
|
+
|
77
|
+
* Massively simplified EMClient implementation
|
78
|
+
|
79
|
+
Rather than trying to hook the IO used by zookeeper_lib to notify zookeeper_c
|
80
|
+
about event availabiltiy directly into EventMachine, use the same event delivery
|
81
|
+
thread, but wrap the dispatch call in EM.schedule.
|
82
|
+
|
83
|
+
* Improve implementation of spin-lock-esque code that waits for the connection to be
|
84
|
+
established before returning.
|
85
|
+
|
86
|
+
This cut the test runtime down from 1m 20s to 2s.
|
87
|
+
|
88
|
+
* Java client refactoring, similar correctness changes
|
89
|
+
|
90
|
+
* Change ZookeeperException base class to StandardError instead of Exception
|
91
|
+
|
92
|
+
|
93
|
+
v0.4.5 Upgrade to ZooKeeper 3.3.3
|
94
|
+
|
1
95
|
v0.4.4 Fix race condition on close, possible data corruption on async get.
|
2
96
|
|
3
97
|
v0.4.3 Fix a handful of memory-related bugs, fix SIGSEGV on master change, reduce latency of event handling, fix compilation on OSX.
|
@@ -22,3 +116,4 @@ v0.2. Bundle C dependencies, like memcached.gem.
|
|
22
116
|
|
23
117
|
v0.1. First release.
|
24
118
|
|
119
|
+
# vim:ft=text:ts=2:sw=2:et
|
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :test do
|
6
|
+
gem "rspec", "~> 2.8.0"
|
7
|
+
gem 'flexmock', '~> 0.8.11'
|
8
|
+
gem 'eventmachine', '1.0.0.beta.4'
|
9
|
+
gem 'evented-spec', '~> 0.9.0'
|
10
|
+
end
|
11
|
+
|
12
|
+
group :development do
|
13
|
+
gem 'rake', '~> 0.9.0'
|
14
|
+
gem 'pry'
|
15
|
+
end
|
16
|
+
|
17
|
+
# vim:ft=ruby
|
data/Manifest
CHANGED
@@ -1,23 +1,29 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
LICENSE
|
3
|
+
Manifest
|
3
4
|
README
|
4
5
|
Rakefile
|
5
6
|
examples/cloud_config.rb
|
6
7
|
ext/extconf.rb
|
7
|
-
ext/zkc-3.3.
|
8
|
+
ext/zkc-3.3.4.tar.gz
|
9
|
+
ext/zookeeper_base.rb
|
8
10
|
ext/zookeeper_c.c
|
9
11
|
ext/zookeeper_lib.c
|
10
12
|
ext/zookeeper_lib.h
|
13
|
+
java/zookeeper_base.rb
|
11
14
|
lib/zookeeper.rb
|
12
15
|
lib/zookeeper/acls.rb
|
13
16
|
lib/zookeeper/callbacks.rb
|
17
|
+
lib/zookeeper/common.rb
|
14
18
|
lib/zookeeper/constants.rb
|
15
19
|
lib/zookeeper/exceptions.rb
|
16
20
|
lib/zookeeper/stat.rb
|
21
|
+
spec/log4j.properties
|
22
|
+
spec/spec_helper.rb
|
23
|
+
spec/zookeeper_spec.rb
|
17
24
|
test/test_basic.rb
|
18
25
|
test/test_callback1.rb
|
19
26
|
test/test_close.rb
|
20
27
|
test/test_esoteric.rb
|
21
28
|
test/test_watcher1.rb
|
22
29
|
test/test_watcher2.rb
|
23
|
-
Manifest
|
data/README.markdown
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# zookeeper #
|
2
|
+
|
3
|
+
An interface to the Zookeeper cluster coordination server.
|
4
|
+
|
5
|
+
For a higher-level interface with a more convenient API and features such as locks, have a look at [ZK](https://github.com/slyphon/zk) (also available is [ZK-EventMachine](https://github.com/slyphon/zk-eventmachine) for those who prefer async).
|
6
|
+
|
7
|
+
## Big Plans for 1.0 ##
|
8
|
+
|
9
|
+
The 1.0 release will feature a reorganization of the heirarchy. There will be a single top-level `Zookeeper` namespace (as opposed to the current layout, with 5-6 different top-level constants), and for the next several releases, there will be a backwards compatible require for users that still need to use the old names.
|
10
|
+
|
11
|
+
## License
|
12
|
+
|
13
|
+
Copyright 2008 Phillip Pearson, and 2010 Twitter, Inc.
|
14
|
+
Licensed under the MIT License. See the included LICENSE file.
|
15
|
+
|
16
|
+
Portions copyright 2008-2010 the Apache Software Foundation, licensed under the
|
17
|
+
Apache 2 license, and used with permission.
|
18
|
+
|
19
|
+
Portions contributed to the open source community by HPDC, L.P.
|
20
|
+
|
21
|
+
## Install
|
22
|
+
|
23
|
+
sudo gem install zookeeper
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Connect to a server:
|
28
|
+
|
29
|
+
require 'rubygems'
|
30
|
+
require 'zookeeper'
|
31
|
+
z = Zookeeper.new("localhost:2181")
|
32
|
+
z.get_children(:path => "/")
|
33
|
+
|
34
|
+
## Idioms
|
35
|
+
|
36
|
+
The following methods are initially supported:
|
37
|
+
* get
|
38
|
+
* set
|
39
|
+
* get\_children
|
40
|
+
* stat
|
41
|
+
* create
|
42
|
+
* delete
|
43
|
+
* get\_acl
|
44
|
+
* set\_acl
|
45
|
+
|
46
|
+
All support async callbacks. get, get\_children and stat support both watchers and callbacks.
|
47
|
+
|
48
|
+
Calls take a dictionary of parameters. With the exception of set\_acl, the only required parameter is :path. Each call returns a dictionary with at minimum two keys :req\_id and :rc.
|
49
|
+
|
50
|
+
### A Bit about this repository ###
|
51
|
+
|
52
|
+
Twitter's open source office was kind enough to transfer this repository to facilitate development and administration of this repository. The `zookeeper` gem's last three releases were recorded in branches `v0.4.2`, `v0.4.3` and `v0.4.4`. Releases of the `slyphon-zookeeper` gem were cut off of the fork, and unfortunately (due to an oversight on my part) were tagged with unrelated versions. Those were tagged with names `release/0.9.2`.
|
53
|
+
|
54
|
+
The plan is to keep the `slyphon-zookeeper` tags, and to tag the `zookeeper` releases `twitter/release/0.4.x`.
|
55
|
+
|
56
|
+
Further work will be carried out on this repository. The `0.9.3` release of the zookeeper gem will be released under the 'zookeeper' name, and will bring the two divergent (conceptual) branches of development together.
|
57
|
+
|
58
|
+
|
59
|
+
|
data/Rakefile
CHANGED
@@ -1,9 +1,139 @@
|
|
1
|
-
|
1
|
+
# def gemset_name
|
2
|
+
# ENV.fetch('GEM_HOME').split('@').last
|
3
|
+
# end
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
GEM_FILES = FileList['slyphon-zookeeper-*.gem']
|
6
|
+
|
7
|
+
namespace :mb do
|
8
|
+
namespace :gems do
|
9
|
+
task :build do
|
10
|
+
sh "rvm 1.8.7 do gem build zookeeper.gemspec"
|
11
|
+
ENV['JAVA_GEM'] = '1'
|
12
|
+
sh "rvm 1.8.7 do gem build zookeeper.gemspec"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :push do
|
16
|
+
GEM_FILES.each do |gem|
|
17
|
+
sh "gem push #{gem}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
task :clean do
|
22
|
+
rm_rf GEM_FILES
|
23
|
+
end
|
24
|
+
|
25
|
+
task :all => [:build, :push, :clean]
|
26
|
+
end
|
9
27
|
end
|
28
|
+
|
29
|
+
gemset_name = 'zookeeper'
|
30
|
+
|
31
|
+
# this nonsense w/ tmp and the Gemfile is a bundler optimization
|
32
|
+
|
33
|
+
%w[1.8.7 1.9.2 jruby rbx 1.9.3].each do |ns_name|
|
34
|
+
rvm_ruby = (ns_name == 'rbx') ? "rbx-2.0.testing" : ns_name
|
35
|
+
|
36
|
+
ruby_with_gemset = "#{rvm_ruby}@#{gemset_name}"
|
37
|
+
|
38
|
+
create_gemset_name = "mb:#{ns_name}:create_gemset"
|
39
|
+
clobber_task_name = "mb:#{ns_name}:clobber"
|
40
|
+
clean_task_name = "mb:#{ns_name}:clean"
|
41
|
+
build_task_name = "mb:#{ns_name}:build"
|
42
|
+
bundle_task_name = "mb:#{ns_name}:bundle_install"
|
43
|
+
rspec_task_name = "mb:#{ns_name}:run_rspec"
|
44
|
+
|
45
|
+
phony_gemfile_link_name = "Gemfile.#{ns_name}"
|
46
|
+
phony_gemfile_lock_name = "#{phony_gemfile_link_name}.lock"
|
47
|
+
|
48
|
+
file phony_gemfile_link_name do
|
49
|
+
# apparently, rake doesn't deal with symlinks intelligently :P
|
50
|
+
ln_s('Gemfile', phony_gemfile_link_name) unless File.symlink?(phony_gemfile_link_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
task :clean do
|
54
|
+
rm_rf [phony_gemfile_lock_name, phony_gemfile_lock_name]
|
55
|
+
end
|
56
|
+
|
57
|
+
task create_gemset_name do
|
58
|
+
sh "rvm #{rvm_ruby} do rvm gemset create #{gemset_name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
task clobber_task_name do
|
62
|
+
unless rvm_ruby == 'jruby'
|
63
|
+
cd 'ext' do
|
64
|
+
sh "rake clobber"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
task clean_task_name do
|
70
|
+
unless rvm_ruby == 'jruby'
|
71
|
+
cd 'ext' do
|
72
|
+
sh "rake clean"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
task build_task_name => [create_gemset_name, clean_task_name] do
|
78
|
+
unless rvm_ruby == 'jruby'
|
79
|
+
cd 'ext' do
|
80
|
+
sh "rvm #{ruby_with_gemset} do rake build"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
task bundle_task_name => [phony_gemfile_link_name, build_task_name] do
|
86
|
+
sh "rvm #{ruby_with_gemset} do bundle install --gemfile #{phony_gemfile_link_name}"
|
87
|
+
end
|
88
|
+
|
89
|
+
task rspec_task_name => bundle_task_name do
|
90
|
+
sh "rvm #{ruby_with_gemset} do env BUNDLE_GEMFILE=#{phony_gemfile_link_name} bundle exec rspec spec --fail-fast"
|
91
|
+
end
|
92
|
+
|
93
|
+
task "mb:#{ns_name}" => rspec_task_name
|
94
|
+
|
95
|
+
task "mb:test_all_rubies" => rspec_task_name
|
96
|
+
end
|
97
|
+
|
98
|
+
task "mb:test_all" do
|
99
|
+
require 'benchmark'
|
100
|
+
t = Benchmark.realtime do
|
101
|
+
Rake::Task['mb:test_all_rubies'].invoke
|
102
|
+
end
|
103
|
+
|
104
|
+
$stderr.puts "Test run took: #{t} s"
|
105
|
+
end
|
106
|
+
|
107
|
+
task :default => 'mb:1.9.3'
|
108
|
+
|
109
|
+
task :clobber do
|
110
|
+
rm_rf 'tmp'
|
111
|
+
end
|
112
|
+
|
113
|
+
# cargo culted from http://blog.flavorjon.es/2009/06/easily-valgrind-gdb-your-ruby-c.html
|
114
|
+
VALGRIND_BASIC_OPTS = '--num-callers=50 --error-limit=no --partial-loads-ok=yes --undef-value-errors=no'
|
115
|
+
|
116
|
+
task 'valgrind' do
|
117
|
+
cd 'ext' do
|
118
|
+
sh "rake clean build"
|
119
|
+
end
|
120
|
+
|
121
|
+
sh "valgrind #{VALGRIND_BASIC_OPTS} bundle exec rspec spec"
|
122
|
+
end
|
123
|
+
|
124
|
+
namespace :build do
|
125
|
+
task :clean do
|
126
|
+
cd 'ext' do
|
127
|
+
sh 'rake clean'
|
128
|
+
end
|
129
|
+
|
130
|
+
Rake::Task['build'].invoke
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
task :build do
|
135
|
+
cd 'ext' do
|
136
|
+
sh "rake"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
data/ext/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
task :clean do
|
3
|
+
if File.exists?('Makefile')
|
4
|
+
sh 'make clean'
|
5
|
+
else
|
6
|
+
$stderr.puts "nothing to clean, no Makefile"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
GENERATE_GVL_CODE_RB = 'generate_gvl_code.rb'
|
11
|
+
|
12
|
+
file 'c' do
|
13
|
+
if tarball = Dir['zkc-*.tar.gz'].first
|
14
|
+
sh "tar -zxf #{tarball}"
|
15
|
+
else
|
16
|
+
raise "couldn't find the tarball! wtf?!"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
file GENERATE_GVL_CODE_RB => 'c'
|
21
|
+
|
22
|
+
file 'zkrb_wrapper.c' => GENERATE_GVL_CODE_RB do
|
23
|
+
sh "ruby generate_gvl_code.rb code"
|
24
|
+
end
|
25
|
+
|
26
|
+
file 'zkrb_wrapper.h' => GENERATE_GVL_CODE_RB do
|
27
|
+
sh "ruby generate_gvl_code.rb headers"
|
28
|
+
end
|
29
|
+
|
30
|
+
ZKRB_WRAPPER = %w[zkrb_wrapper.c zkrb_wrapper.h]
|
31
|
+
|
32
|
+
|
33
|
+
task :wrappers => ZKRB_WRAPPER
|
34
|
+
|
35
|
+
|
36
|
+
task :clobber => :clean do
|
37
|
+
rm_rf %w[Makefile c lib bin include]
|
38
|
+
end
|
39
|
+
|
40
|
+
task :build_zkc do
|
41
|
+
sh 'ruby extconf.rb'
|
42
|
+
end
|
43
|
+
|
44
|
+
file 'Makefile' => :build_zkc
|
45
|
+
|
46
|
+
task :build => [ZKRB_WRAPPER, 'Makefile'].flatten do
|
47
|
+
sh 'make'
|
48
|
+
end
|
49
|
+
|
50
|
+
task :default => :build
|
51
|
+
|
data/ext/c_zookeeper.rb
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'zookeeper/constants'
|
2
|
+
require File.expand_path('../zookeeper_c', __FILE__)
|
3
|
+
|
4
|
+
# TODO: see if we can get the destructor to handle thread/event queue teardown
|
5
|
+
# when we're garbage collected
|
6
|
+
class CZookeeper
|
7
|
+
include ZookeeperCommon
|
8
|
+
include ZookeeperConstants
|
9
|
+
include ZookeeperExceptions
|
10
|
+
|
11
|
+
DEFAULT_SESSION_TIMEOUT_MSEC = 10000
|
12
|
+
|
13
|
+
class GotNilEventException < StandardError; end
|
14
|
+
|
15
|
+
# assume we're at debug level
|
16
|
+
def self.get_debug_level
|
17
|
+
@debug_level ||= ZOO_LOG_LEVEL_INFO
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.set_debug_level(value)
|
21
|
+
@debug_level = value
|
22
|
+
set_zkrb_debug_level(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(host, event_queue, opts={})
|
26
|
+
@host = host
|
27
|
+
@event_queue = event_queue
|
28
|
+
|
29
|
+
# used by the C layer. CZookeeper sets this to true when the init method
|
30
|
+
# has completed. once this is set to true, it stays true.
|
31
|
+
#
|
32
|
+
# you should grab the @start_stop_mutex before messing with this flag
|
33
|
+
@_running = nil
|
34
|
+
|
35
|
+
# This is set to true after destroy_zkrb_instance has been called and all
|
36
|
+
# CZookeeper state has been cleaned up
|
37
|
+
@_closed = false # also used by the C layer
|
38
|
+
|
39
|
+
# set by the ruby side to indicate we are in shutdown mode used by method_get_next_event
|
40
|
+
@_shutting_down = false
|
41
|
+
|
42
|
+
# the actual C data is stashed in this ivar. never *ever* touch this
|
43
|
+
@_data = nil
|
44
|
+
|
45
|
+
@_session_timeout_msec = DEFAULT_SESSION_TIMEOUT_MSEC
|
46
|
+
|
47
|
+
@start_stop_mutex = Monitor.new
|
48
|
+
|
49
|
+
# used to signal that we're running
|
50
|
+
@running_cond = @start_stop_mutex.new_cond
|
51
|
+
|
52
|
+
@event_thread = nil
|
53
|
+
|
54
|
+
setup_event_thread!
|
55
|
+
|
56
|
+
zkrb_init(@host)
|
57
|
+
|
58
|
+
logger.debug { "init returned!" }
|
59
|
+
end
|
60
|
+
|
61
|
+
def closed?
|
62
|
+
@start_stop_mutex.synchronize { !!@_closed }
|
63
|
+
end
|
64
|
+
|
65
|
+
def running?
|
66
|
+
@start_stop_mutex.synchronize { !!@_running }
|
67
|
+
end
|
68
|
+
|
69
|
+
def shutting_down?
|
70
|
+
@start_stop_mutex.synchronize { !!@_shutting_down }
|
71
|
+
end
|
72
|
+
|
73
|
+
def connected?
|
74
|
+
state == ZOO_CONNECTED_STATE
|
75
|
+
end
|
76
|
+
|
77
|
+
def connecting?
|
78
|
+
state == ZOO_CONNECTING_STATE
|
79
|
+
end
|
80
|
+
|
81
|
+
def associating?
|
82
|
+
state == ZOO_ASSOCIATING_STATE
|
83
|
+
end
|
84
|
+
|
85
|
+
def close
|
86
|
+
return if closed?
|
87
|
+
|
88
|
+
shut_down!
|
89
|
+
stop_event_thread!
|
90
|
+
|
91
|
+
@start_stop_mutex.synchronize do
|
92
|
+
if !@_closed and @_data
|
93
|
+
close_handle
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def state
|
101
|
+
return ZOO_CLOSED_STATE if closed?
|
102
|
+
zkrb_state
|
103
|
+
end
|
104
|
+
|
105
|
+
# this implementation is gross, but i don't really see another way of doing it
|
106
|
+
# without more grossness
|
107
|
+
#
|
108
|
+
# returns true if we're connected, false if we're not
|
109
|
+
#
|
110
|
+
# if timeout is nil, we never time out, and wait forever for CONNECTED state
|
111
|
+
#
|
112
|
+
def wait_until_connected(timeout=10)
|
113
|
+
return false unless wait_until_running(timeout)
|
114
|
+
|
115
|
+
time_to_stop = timeout ? (Time.now + timeout) : nil
|
116
|
+
|
117
|
+
until connected? or (time_to_stop and Time.now > time_to_stop)
|
118
|
+
Thread.pass
|
119
|
+
end
|
120
|
+
|
121
|
+
connected?
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
# will wait until the client has entered the running? state
|
126
|
+
# or until timeout seconds have passed.
|
127
|
+
#
|
128
|
+
# returns true if we're running, false if we timed out
|
129
|
+
def wait_until_running(timeout=5)
|
130
|
+
@start_stop_mutex.synchronize do
|
131
|
+
return true if @_running
|
132
|
+
@running_cond.wait(timeout)
|
133
|
+
!!@_running
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def setup_event_thread!
|
138
|
+
@event_thread ||= Thread.new(&method(:_event_thread_body))
|
139
|
+
end
|
140
|
+
|
141
|
+
def _event_thread_body
|
142
|
+
logger.debug { "event_thread waiting until running: #{@_running}" }
|
143
|
+
|
144
|
+
@start_stop_mutex.synchronize do
|
145
|
+
@running_cond.wait_until { @_running }
|
146
|
+
|
147
|
+
if @_shutting_down
|
148
|
+
logger.error { "event thread saw @_shutting_down, bailing without entering loop" }
|
149
|
+
return
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
logger.debug { "event_thread running: #{@_running}" }
|
154
|
+
|
155
|
+
while true
|
156
|
+
begin
|
157
|
+
_iterate_event_delivery
|
158
|
+
rescue GotNilEventException
|
159
|
+
logger.debug { "#{self.class}##{__method__}: event delivery thread is exiting" }
|
160
|
+
break
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def _iterate_event_delivery
|
166
|
+
get_next_event(true).tap do |hash|
|
167
|
+
raise GotNilEventException if hash.nil?
|
168
|
+
@event_queue.push(hash)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# use this method to set the @_shutting_down flag to true
|
173
|
+
def shut_down!
|
174
|
+
logger.debug { "#{self.class}##{__method__}" }
|
175
|
+
|
176
|
+
@start_stop_mutex.synchronize do
|
177
|
+
@_shutting_down = true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# this method is part of the reopen/close code, and is responsible for
|
182
|
+
# shutting down the dispatch thread.
|
183
|
+
#
|
184
|
+
# @dispatch will be nil when this method exits
|
185
|
+
#
|
186
|
+
def stop_event_thread!
|
187
|
+
logger.debug { "#{self.class}##{__method__}" }
|
188
|
+
|
189
|
+
if @event_thread
|
190
|
+
unless @_closed
|
191
|
+
wake_event_loop! # this is a C method
|
192
|
+
end
|
193
|
+
@event_thread.join
|
194
|
+
@event_thread = nil
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def logger
|
199
|
+
Zookeeper.logger
|
200
|
+
end
|
201
|
+
|
202
|
+
# called by underlying C code to signal we're running
|
203
|
+
def zkc_set_running_and_notify!
|
204
|
+
logger.debug { "#{self.class}##{__method__}" }
|
205
|
+
|
206
|
+
@start_stop_mutex.synchronize do
|
207
|
+
@_running = true
|
208
|
+
@running_cond.broadcast
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
data/ext/dbg.h
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#ifndef __dbg_h__
|
2
|
+
#define __dbg_h__
|
3
|
+
|
4
|
+
// ALL GLORY TO THE Zed A. Shaw
|
5
|
+
// http://c.learncodethehardway.org/book/learn-c-the-hard-waych21.html#x26-10500021
|
6
|
+
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <errno.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
#ifdef NDEBUG
|
12
|
+
#define debug(M, ...)
|
13
|
+
#else
|
14
|
+
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
18
|
+
|
19
|
+
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
20
|
+
|
21
|
+
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
22
|
+
|
23
|
+
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
24
|
+
|
25
|
+
// acts to assert that A is true
|
26
|
+
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
27
|
+
|
28
|
+
// like check, but provide an explicit goto label name
|
29
|
+
#define check_goto(A, L, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto L; }
|
30
|
+
|
31
|
+
// like check, but implicit jump to 'unlock' label
|
32
|
+
#define check_unlock(A, M, ...) check_goto(A, unlock, M, ##__VA_ARGS__)
|
33
|
+
|
34
|
+
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
35
|
+
|
36
|
+
#define check_mem(A) check((A), "Out of memory.")
|
37
|
+
|
38
|
+
// checks the condition A, if not true, logs the message M given using zkrb_debug
|
39
|
+
// then does a goto to the label L
|
40
|
+
#define check_debug_goto(A, L, M, ...) if(!(A)) { zkrb_debug(M, ##__VA_ARGS__); errno=0; goto L; }
|
41
|
+
|
42
|
+
// check_debug_goto with implicit 'unlock' label
|
43
|
+
#define check_debug_unlock(A, M, ...) check_debug_goto(A, unlock, M, ##__VA_ARGS__)
|
44
|
+
|
45
|
+
// like check_debug_goto, but the label is implicitly 'error'
|
46
|
+
#define check_debug(A, M, ...) check_debug_goto(A, error, M, ##__VA_ARGS__)
|
47
|
+
|
48
|
+
#define zkrb_debug(M, ...) if (ZKRBDebugging) fprintf(stderr, "DEBUG %p:%s:%d: " M "\n", pthread_self(), __FILE__, __LINE__, ##__VA_ARGS__)
|
49
|
+
#define zkrb_debug_inst(O, M, ...) zkrb_debug("obj_id: %lx, " M, FIX2LONG(rb_obj_id(O)), ##__VA_ARGS__)
|
50
|
+
|
51
|
+
// __dbg_h__
|
52
|
+
#endif
|
53
|
+
|