zk 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
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