zookeeper 0.4.4 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG +95 -0
  3. data/Gemfile +17 -0
  4. data/Manifest +8 -2
  5. data/README.markdown +59 -0
  6. data/Rakefile +137 -7
  7. data/ext/.gitignore +6 -0
  8. data/ext/Rakefile +51 -0
  9. data/ext/c_zookeeper.rb +212 -0
  10. data/ext/dbg.h +53 -0
  11. data/ext/depend +5 -0
  12. data/ext/extconf.rb +44 -15
  13. data/ext/generate_gvl_code.rb +316 -0
  14. data/ext/zkc-3.3.5.tar.gz +0 -0
  15. data/ext/zkrb_wrapper.c +731 -0
  16. data/ext/zkrb_wrapper.h +330 -0
  17. data/ext/zkrb_wrapper_compat.c +15 -0
  18. data/ext/zkrb_wrapper_compat.h +11 -0
  19. data/ext/zookeeper_base.rb +211 -0
  20. data/ext/zookeeper_c.c +268 -97
  21. data/ext/zookeeper_lib.c +157 -92
  22. data/ext/zookeeper_lib.h +12 -6
  23. data/java/zookeeper_base.rb +477 -0
  24. data/lib/zookeeper/acls.rb +10 -1
  25. data/lib/zookeeper/callbacks.rb +5 -3
  26. data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
  27. data/lib/zookeeper/common.rb +174 -0
  28. data/lib/zookeeper/constants.rb +31 -28
  29. data/lib/zookeeper/em_client.rb +55 -0
  30. data/lib/zookeeper/exceptions.rb +10 -2
  31. data/lib/zookeeper/stat.rb +11 -2
  32. data/lib/zookeeper/version.rb +6 -0
  33. data/lib/zookeeper.rb +155 -122
  34. data/notes.txt +14 -0
  35. data/spec/c_zookeeper_spec.rb +50 -0
  36. data/spec/chrooted_connection_spec.rb +81 -0
  37. data/spec/default_watcher_spec.rb +41 -0
  38. data/spec/em_spec.rb +51 -0
  39. data/spec/log4j.properties +17 -0
  40. data/spec/shared/all_success_return_values.rb +10 -0
  41. data/spec/shared/connection_examples.rb +1018 -0
  42. data/spec/spec_helper.rb +119 -0
  43. data/spec/support/progress_formatter.rb +15 -0
  44. data/spec/zookeeper_spec.rb +24 -0
  45. data/zookeeper.gemspec +37 -25
  46. metadata +78 -34
  47. data/README +0 -42
  48. data/ext/zkc-3.3.2.tar.gz +0 -0
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ *.gem
2
+ *.o
3
+ *.so
4
+ *~
5
+ *.log
6
+ Makefile
7
+ pkg
8
+ zookeeper.gemspec
9
+ Gemfile.*
10
+ tmp/
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.2.tar.gz
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
- require 'echoe'
1
+ # def gemset_name
2
+ # ENV.fetch('GEM_HOME').split('@').last
3
+ # end
2
4
 
3
- Echoe.new("zookeeper") do |p|
4
- p.author = "Phillip Pearson, Eric Maland, Evan Weaver, Brian Wickman"
5
- p.project = "twitter"
6
- p.summary = "An interface to the Zookeeper distributed configuration server."
7
- p.clean_pattern += ["ext/lib", "ext/include", "ext/c", "ext/bin", "ext/conftest.dSYM"]
8
- p.rdoc_pattern = /README|TODO|LICENSE|CHANGELOG|BENCH|COMPAT|zookeeper_c.c|zookeeper.rb/
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/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ bin
2
+ include
3
+ lib
4
+ *.bundle
5
+
6
+ c
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
+
@@ -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
+
data/ext/depend ADDED
@@ -0,0 +1,5 @@
1
+ zookeeper_lib.c: zookeeper_lib.h
2
+ zkrb_wrapper_compat.c: zkrb_wrapper_compat.h
3
+ zkrb_wrapper.c: zkrb_wrapper_compat.c zkrb_wrapper.h
4
+ zookeeper_c.c: zookeeper_lib.c zookeeper_lib.h zkrb_wrapper.c zkrb_wrapper.h dbg.h
5
+