zk 1.4.1 → 1.4.2

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/lib/zk.rb CHANGED
@@ -225,6 +225,10 @@ module ZK
225
225
  ruby_19? and not jruby? or rubinius?
226
226
  end
227
227
 
228
+ def self.mri_193?
229
+ (RUBY_VERSION == '1.9.3') and not jruby? or rubinius?
230
+ end
231
+
228
232
  def self.ruby_19?
229
233
  (RUBY_VERSION =~ /\A1\.9\.[2-9]\Z/)
230
234
  end
@@ -135,7 +135,7 @@ module ZK
135
135
  # close the underlying connection and clear all pending events.
136
136
  #
137
137
  def close!
138
- event_handler.clear!
138
+ event_handler.close
139
139
  close
140
140
  end
141
141
 
@@ -180,6 +180,7 @@ module ZK
180
180
  old_cnx.close! if old_cnx # && !old_cnx.closed?
181
181
  else
182
182
  logger.debug { "#{self.class}##{__method__} not reopening, no fork detected" }
183
+ @cnx.reopen(timeout)
183
184
  end
184
185
 
185
186
  @mutex.synchronize { @close_requested = false }
@@ -231,6 +231,14 @@ module ZK
231
231
  end
232
232
  end
233
233
 
234
+ # shut down the EventHandlerSubscriptions
235
+ def close
236
+ synchronize do
237
+ @callbacks.values.flatten.each(&:close)
238
+ clear!
239
+ end
240
+ end
241
+
234
242
  # @private
235
243
  def synchronize
236
244
  @mutex.synchronize { yield }
@@ -21,6 +21,11 @@ module ZK
21
21
  def async?
22
22
  true
23
23
  end
24
+
25
+ # calls unsubscribe and shuts down
26
+ def close
27
+ unsubscribe
28
+ end
24
29
  end
25
30
  end
26
31
  end
@@ -39,6 +39,10 @@ module ZK
39
39
  false
40
40
  end
41
41
 
42
+ # take any action to free resources associated with this subscription
43
+ def close
44
+ end
45
+
42
46
  protected
43
47
  def prep_interests(a)
44
48
  # logger.debug { "prep_interests: #{a.inspect}" }
@@ -23,8 +23,15 @@ module ZK
23
23
  reopen_after_fork!
24
24
  end
25
25
 
26
+ def unregistered?
27
+ @parent.nil?
28
+ end
29
+
30
+ # calls unregister on parent, then sets parent to nil
26
31
  def unregister
27
- parent.unregister(self)
32
+ return false unless @parent
33
+ @parent.unregister(self)
34
+ @parent = nil
28
35
  end
29
36
  alias unsubscribe unregister
30
37
 
@@ -55,7 +62,7 @@ module ZK
55
62
 
56
63
  def unsubscribe_with_threaded_callback
57
64
  synchronize do
58
- @threaded_callback.shutdown
65
+ @threaded_callback && @threaded_callback.shutdown
59
66
  unsubscribe_without_threaded_callback
60
67
  end
61
68
  end
data/lib/zk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ZK
2
- VERSION = "1.4.1"
2
+ VERSION = "1.4.2"
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -36,7 +36,7 @@ RSpec.configure do |config|
36
36
  config.filter_run_excluding :rbx => :broken
37
37
  end
38
38
 
39
- if ZK.jruby?
39
+ if ZK.jruby? or not ZK.mri_193?
40
40
  config.filter_run_excluding :fork_required => true
41
41
  end
42
42
 
@@ -0,0 +1,159 @@
1
+ class ClientForker
2
+ include ZK::Logging
3
+ attr_reader :base_path, :cnx_args, :stat
4
+
5
+ def self.run(cnx_args, base_path)
6
+ cf = new(cnx_args, base_path)
7
+ cf.run
8
+ yield cf
9
+ end
10
+
11
+ def initialize(cnx_args, base_path)
12
+ @cnx_args = cnx_args
13
+ @base_path = base_path
14
+ @pids_root = "#{@base_path}/pid"
15
+ end
16
+
17
+ def before
18
+ ZK.open(*cnx_args) do |z|
19
+ z.rm_rf(@base_path)
20
+ z.mkdir_p(@pids_root)
21
+ end
22
+ end
23
+
24
+ def tear_down
25
+ @zk.rm_rf(@base_path)
26
+ @zk.close! unless @zk.closed?
27
+ end
28
+
29
+ def kill_child!
30
+ return unless @pid
31
+ Process.kill('TERM', @pid)
32
+ pid, st = Process.wait2(@pid)
33
+ logger.debug { "child #{@pid} exited with status: #{st.inspect}" }
34
+ rescue Errno::ESRCH
35
+ end
36
+
37
+ def run
38
+ before
39
+
40
+ logger.debug { "Process.pid of parent: #{Process.pid}" }
41
+
42
+ @zk = ZK.new(*cnx_args) do |z|
43
+ z.on_connected do
44
+ logger.debug { "on_connected fired, writing pid to path #{@pids_root}/#{$$}" }
45
+ begin
46
+ z.create("#{@pids_root}/#{Process.pid}", Process.pid.to_s)
47
+ rescue ZK::Exceptions::NodeExists
48
+ end
49
+ end
50
+ end
51
+
52
+ @parent_pid = $$
53
+
54
+ @zk.create("#{@pids_root}/#{$$}", $$.to_s)
55
+
56
+ event_catcher = EventCatcher.new
57
+
58
+ @zk.register(@pids_root) do |event|
59
+ if event.node_child?
60
+ event_catcher << event
61
+ else
62
+ @zk.children(@pids_root, :watch => true)
63
+ end
64
+ end
65
+
66
+ logger.debug { "parent watching for children on #{@pids_root}" }
67
+ @zk.children(@pids_root, :watch => true) # side-effect, register watch
68
+
69
+ @pid = fork do
70
+ @zk.reopen
71
+ @zk.wait_until_connected
72
+
73
+ child_pid_path = "#{@pids_root}/#{$$}"
74
+
75
+ create_latch = Zookeeper::Latch.new
76
+
77
+ create_sub = @zk.register(child_pid_path) do |event|
78
+ if event.node_created?
79
+ logger.debug { "got created event, releasing create_latch" }
80
+ create_latch.release
81
+ else
82
+ if @zk.exists?(child_pid_path, :watch => true)
83
+ logger.debug { "created behind our backs, releasing create_latch" }
84
+ create_latch.release
85
+ end
86
+ end
87
+ end
88
+
89
+ if @zk.exists?(child_pid_path, :watch => true)
90
+ logger.debug { "woot! #{child_pid_path} exists!" }
91
+ create_sub.unregister
92
+ else
93
+ logger.debug { "awaiting the create_latch to release" }
94
+ create_latch.await
95
+ end
96
+
97
+ logger.debug { "now testing for delete event totally created in child" }
98
+
99
+ delete_latch = Zookeeper::Latch.new
100
+
101
+ delete_event = nil
102
+
103
+ delete_sub = @zk.register(child_pid_path) do |event|
104
+ if event.node_deleted?
105
+ delete_event = event
106
+ logger.debug { "child got delete event on #{child_pid_path}" }
107
+ delete_latch.release
108
+ else
109
+ unless @zk.exists?(child_pid_path, :watch => true)
110
+ logger.debug { "child: someone deleted #{child_pid_path} behind our back" }
111
+ delete_latch.release
112
+ end
113
+ end
114
+ end
115
+
116
+ @zk.exists?(child_pid_path, :watch => true)
117
+
118
+ @zk.delete(child_pid_path)
119
+
120
+ logger.debug { "awaiting deletion event notification" }
121
+ delete_latch.await unless delete_event
122
+
123
+ logger.debug { "deletion event: #{delete_event}" }
124
+
125
+ if delete_event
126
+ exit! 0
127
+ else
128
+ exit! 1
129
+ end
130
+ end # forked child
131
+
132
+ # replicates deletion watcher inside child
133
+ child_pid_path = "#{@pids_root}/#{@pid}"
134
+
135
+ delete_latch = Latch.new
136
+
137
+ delete_sub = @zk.register(child_pid_path) do |event|
138
+ if event.node_deleted?
139
+ logger.debug { "parent got delete event on #{child_pid_path}" }
140
+ delete_latch.release
141
+ else
142
+ unless @zk.exists?(child_pid_path, :watch => true)
143
+ logger.debug { "child: someone deleted #{child_pid_path} behind our back" }
144
+ delete_latch.release
145
+ end
146
+ end
147
+ end
148
+
149
+ delete_latch.await if @zk.exists?(child_pid_path, :watch => true)
150
+
151
+ _, @stat = Process.wait2(@pid)
152
+
153
+ # $stderr.puts "#{@pid} exited with status: #{stat.inspect}"
154
+ ensure
155
+ kill_child!
156
+ tear_down
157
+ end
158
+ end
159
+
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'forked client integration' do
4
+ describe :forked, :fork_required => true, :rbx => :broken do
5
+ include_context 'connection opts'
6
+
7
+ before do
8
+ @base_path = '/zktests'
9
+ @pids_root = "#{@base_path}/pid"
10
+
11
+ @cnx_args = ["#{ZK.default_host}:#{ZK.test_port}", { :thread => :single, :timeout => 5 }]
12
+
13
+ ZK.open(*@cnx_args) do |z|
14
+ z.rm_rf(@base_path)
15
+ z.mkdir_p(@pids_root)
16
+ end
17
+ end
18
+
19
+ after do
20
+ ZK.open(*connection_args) { |z| z.rm_rf(@base_path) }
21
+ end
22
+
23
+ it %[should deliver callbacks in the child] do
24
+ 10.times do
25
+ ClientForker.run(@cnx_args, @base_path) do |forker|
26
+ forker.stat.should_not be_signaled
27
+ forker.stat.should be_exited
28
+ forker.stat.should be_success
29
+ end
30
+ end
31
+ end # should deliver callbacks in the child
32
+ end # forked
33
+ end
34
+
@@ -31,154 +31,5 @@ describe ZK::Client::Threaded do
31
31
  end
32
32
  end
33
33
  end
34
-
35
- describe :forked, :fork_required => true, :rbx => :broken do
36
- include_context 'connection opts'
37
-
38
- before do
39
- @base_path = '/zktests'
40
- @pids_root = "#{@base_path}/pid"
41
-
42
- ZK.open(*connection_args) do |z|
43
- z.rm_rf(@base_path)
44
- z.mkdir_p(@pids_root)
45
- end
46
- end
47
-
48
- after do
49
- if @pid
50
- begin
51
- Process.kill('TERM', @pid)
52
- pid, st = Process.wait2(@pid)
53
- logger.debug { "child #{@pid} exited with status: #{st.inspect}" }
54
- rescue Errno::ESRCH
55
- end
56
- end
57
-
58
- @zk.close! if @zk
59
- ZK.open(*connection_args) { |z| z.rm_rf(@base_path) }
60
- end
61
-
62
- it %[should deliver callbacks in the child], :fork => true do
63
- logger.debug { "Process.pid of parent: #{Process.pid}" }
64
-
65
- @zk = ZK.new do |z|
66
- z.on_connected do
67
- logger.debug { "on_connected fired, writing pid to path #{@pids_root}/#{$$}" }
68
- begin
69
- z.create("#{@pids_root}/#{Process.pid}", Process.pid.to_s)
70
- rescue ZK::Exceptions::NodeExists
71
- end
72
- end
73
- end
74
-
75
- @parent_pid = $$
76
-
77
- @zk.create("#{@pids_root}/#{$$}", $$.to_s)
78
-
79
- event_catcher = EventCatcher.new
80
-
81
- @zk.register(@pids_root) do |event|
82
- if event.node_child?
83
- event_catcher << event
84
- else
85
- @zk.children(@pids_root, :watch => true)
86
- end
87
- end
88
-
89
- logger.debug { "parent watching for children on #{@pids_root}" }
90
- @zk.children(@pids_root, :watch => true) # side-effect, register watch
91
-
92
- @pid = fork do
93
- @zk.reopen
94
- @zk.wait_until_connected
95
-
96
- child_pid_path = "#{@pids_root}/#{$$}"
97
-
98
- create_latch = Zookeeper::Latch.new
99
-
100
- create_sub = @zk.register(child_pid_path) do |event|
101
- if event.node_created?
102
- logger.debug { "got created event, releasing create_latch" }
103
- create_latch.release
104
- else
105
- if @zk.exists?(child_pid_path, :watch => true)
106
- logger.debug { "created behind our backs, releasing create_latch" }
107
- create_latch.release
108
- end
109
- end
110
- end
111
-
112
- if @zk.exists?(child_pid_path, :watch => true)
113
- logger.debug { "woot! #{child_pid_path} exists!" }
114
- create_sub.unregister
115
- else
116
- logger.debug { "awaiting the create_latch to release" }
117
- create_latch.await
118
- end
119
-
120
- logger.debug { "now testing for delete event totally created in child" }
121
-
122
- delete_latch = Zookeeper::Latch.new
123
-
124
- delete_event = nil
125
-
126
- delete_sub = @zk.register(child_pid_path) do |event|
127
- if event.node_deleted?
128
- delete_event = event
129
- logger.debug { "child got delete event on #{child_pid_path}" }
130
- delete_latch.release
131
- else
132
- unless @zk.exists?(child_pid_path, :watch => true)
133
- logger.debug { "child: someone deleted #{child_pid_path} behind our back" }
134
- delete_latch.release
135
- end
136
- end
137
- end
138
-
139
- @zk.exists?(child_pid_path, :watch => true)
140
-
141
- @zk.delete(child_pid_path)
142
-
143
- logger.debug { "awaiting deletion event notification" }
144
- delete_latch.await unless delete_event
145
-
146
- logger.debug { "deletion event: #{delete_event}" }
147
-
148
- if delete_event
149
- exit! 0
150
- else
151
- exit! 1
152
- end
153
- end
154
-
155
- # replicates deletion watcher inside child
156
- child_pid_path = "#{@pids_root}/#{@pid}"
157
-
158
- delete_latch = Latch.new
159
-
160
- delete_sub = @zk.register(child_pid_path) do |event|
161
- if event.node_deleted?
162
- logger.debug { "parent got delete event on #{child_pid_path}" }
163
- delete_latch.release
164
- else
165
- unless @zk.exists?(child_pid_path, :watch => true)
166
- logger.debug { "child: someone deleted #{child_pid_path} behind our back" }
167
- delete_latch.release
168
- end
169
- end
170
- end
171
-
172
- delete_latch.await if @zk.exists?(child_pid_path, :watch => true)
173
-
174
- _, stat = Process.wait2(@pid)
175
-
176
- stat.should_not be_signaled
177
- stat.should be_exited
178
- stat.should be_success
179
-
180
-
181
- end # should deliver callbacks in the child
182
- end # forked
183
34
  end # ZK::Client::Threaded
184
35
 
File without changes
File without changes
data/zk.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{A high-level wrapper around the zookeeper driver}
13
13
  s.description = s.summary + "\n"
14
14
 
15
- s.add_runtime_dependency 'zookeeper', '~> 1.1.0'
15
+ s.add_runtime_dependency 'zookeeper', '~> 1.1.1'
16
16
  s.add_runtime_dependency 'backports', '~> 2.5.1'
17
17
 
18
18
  s.files = `git ls-files`.split("\n")
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zk
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 4
9
- - 1
10
- version: 1.4.1
9
+ - 2
10
+ version: 1.4.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jonathan D. Simms
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2012-05-14 00:00:00 Z
19
+ date: 2012-05-17 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: zookeeper
@@ -26,12 +26,12 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 19
29
+ hash: 17
30
30
  segments:
31
31
  - 1
32
32
  - 1
33
- - 0
34
- version: 1.1.0
33
+ - 1
34
+ version: 1.1.1
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -120,6 +120,7 @@ files:
120
120
  - spec/spec_helper.rb
121
121
  - spec/support/00_test_port_attr.rb
122
122
  - spec/support/bogus_mongoid.rb
123
+ - spec/support/client_forker.rb
123
124
  - spec/support/event_catcher.rb
124
125
  - spec/support/exist_matcher.rb
125
126
  - spec/support/latch.rb
@@ -130,7 +131,7 @@ files:
130
131
  - spec/support/special_happy_funtime_error.rb
131
132
  - spec/support/wait_watchers.rb
132
133
  - spec/test_file.txt
133
- - spec/watch_spec.rb
134
+ - spec/zk/00_forked_client_integration_spec.rb
134
135
  - spec/zk/client/locking_and_session_death_spec.rb
135
136
  - spec/zk/client_spec.rb
136
137
  - spec/zk/election_spec.rb
@@ -140,7 +141,8 @@ files:
140
141
  - spec/zk/mongoid_spec.rb
141
142
  - spec/zk/pool_spec.rb
142
143
  - spec/zk/threadpool_spec.rb
143
- - spec/zookeeper_spec.rb
144
+ - spec/zk/watch_spec.rb
145
+ - spec/zk/zookeeper_spec.rb
144
146
  - zk.gemspec
145
147
  homepage: https://github.com/slyphon/zk
146
148
  licenses: []
@@ -171,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
173
  requirements: []
172
174
 
173
175
  rubyforge_project:
174
- rubygems_version: 1.8.15
176
+ rubygems_version: 1.8.24
175
177
  signing_key:
176
178
  specification_version: 3
177
179
  summary: A high-level wrapper around the zookeeper driver
@@ -187,6 +189,7 @@ test_files:
187
189
  - spec/spec_helper.rb
188
190
  - spec/support/00_test_port_attr.rb
189
191
  - spec/support/bogus_mongoid.rb
192
+ - spec/support/client_forker.rb
190
193
  - spec/support/event_catcher.rb
191
194
  - spec/support/exist_matcher.rb
192
195
  - spec/support/latch.rb
@@ -197,7 +200,7 @@ test_files:
197
200
  - spec/support/special_happy_funtime_error.rb
198
201
  - spec/support/wait_watchers.rb
199
202
  - spec/test_file.txt
200
- - spec/watch_spec.rb
203
+ - spec/zk/00_forked_client_integration_spec.rb
201
204
  - spec/zk/client/locking_and_session_death_spec.rb
202
205
  - spec/zk/client_spec.rb
203
206
  - spec/zk/election_spec.rb
@@ -207,4 +210,5 @@ test_files:
207
210
  - spec/zk/mongoid_spec.rb
208
211
  - spec/zk/pool_spec.rb
209
212
  - spec/zk/threadpool_spec.rb
210
- - spec/zookeeper_spec.rb
213
+ - spec/zk/watch_spec.rb
214
+ - spec/zk/zookeeper_spec.rb