zookeeper 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ v1.2.3 ensure that all threads are woken up on shutdown
2
+
3
+ * There was an edge case where a call would be queued up and its thread
4
+ sleeping waiting for a response, but that response would never come because
5
+ the connection was shut down. This version includes a patch for that case
6
+ to ensure that if a call is in 'pending' state, and shutdown time arrives
7
+ that all pending threads will receive a Zookeeper::Exceptions::NotConnected
8
+ exception.
9
+
1
10
  v1.2.2 avoid race while waiting for connection
2
11
 
3
12
  * There was a possible race in CZookeeper#wait_until_connected where if we
data/ext/c_zookeeper.rb CHANGED
@@ -143,13 +143,13 @@ class CZookeeper
143
143
  # requests may still be added during this time, but they will not be
144
144
  # processed until you call resume
145
145
  def pause_before_fork_in_parent
146
- logger.debug { "#{self.class}##{__method__}" }
146
+ logger.debug { "##{__method__}" }
147
147
  @mutex.synchronize { stop_event_thread }
148
148
  end
149
149
 
150
150
  # call this if 'pause' was previously called to start the event loop again
151
151
  def resume_after_fork_in_parent
152
- logger.debug { "#{self.class}##{__method__}" }
152
+ logger.debug { "##{__method__}" }
153
153
 
154
154
  @mutex.synchronize do
155
155
  @_shutting_down = nil
@@ -184,6 +184,10 @@ class CZookeeper
184
184
  # submits a job for processing
185
185
  # blocks the caller until result has returned
186
186
  def submit_and_block(meth, *args)
187
+ @mutex.synchronize do
188
+ raise Exceptions::NotConnected if @_shutting_down
189
+ end
190
+
187
191
  cnt = Continuation.new(meth, *args)
188
192
  @reg.lock
189
193
  begin
@@ -206,7 +210,7 @@ class CZookeeper
206
210
  #
207
211
  def stop_event_thread
208
212
  if @event_thread
209
- logger.debug { "#{self.class}##{__method__}" }
213
+ logger.debug { "##{__method__}" }
210
214
  shut_down!
211
215
  wake_event_loop!
212
216
  @event_thread.join
@@ -235,7 +239,7 @@ class CZookeeper
235
239
 
236
240
  def event_thread_body
237
241
  Thread.current.abort_on_exception = true
238
- logger.debug { "#{self.class}##{__method__} starting event thread" }
242
+ logger.debug { "##{__method__} starting event thread" }
239
243
 
240
244
  event_thread_await_running
241
245
 
@@ -249,21 +253,34 @@ class CZookeeper
249
253
  # ok, if we're exiting the event loop, and we still have a valid connection
250
254
  # and there's still completions we're waiting to hear about, then we
251
255
  # should pump the handle before leaving this loop
252
- if @_shutting_down and not (@_closed or is_unrecoverable or @reg.in_flight.empty?)
253
- logger.debug { "we're in shutting down state, ensuring we have no in-flight completions" }
256
+ if @_shutting_down and not (@_closed or is_unrecoverable)
257
+ logger.debug { "we're in shutting down state, there are #{@reg.in_flight.length} in_flight completions" }
254
258
 
255
- until @reg.in_flight.empty?
259
+ until @reg.in_flight.empty? or is_unrecoverable or @_closed
256
260
  zkrb_iterate_event_loop
257
261
  iterate_event_delivery
262
+ logger.debug { "there are #{@reg.in_flight} in_flight completions left" }
258
263
  end
259
264
 
260
265
  logger.debug { "finished completions" }
261
266
  end
262
267
 
268
+ if @_shutting_down # in shutting down state, no more can be added to @reg
269
+ # anything left over after all that gets the finger
270
+ remaining = @reg.next_batch + @reg.in_flight.values
271
+
272
+ logger.debug { "there are #{remaining.length} completions to awaken" }
273
+
274
+ @reg.in_flight.clear
275
+
276
+ while cb = remaining.shift
277
+ cb.shutdown!
278
+ end
279
+ end
263
280
  rescue ShuttingDownException
264
281
  logger.error { "event thread saw @_shutting_down, bailing without entering loop" }
265
282
  ensure
266
- logger.debug { "#{self.class}##{__method__} exiting" }
283
+ logger.debug { "##{__method__} exiting" }
267
284
  end
268
285
 
269
286
  def submit_pending_calls
@@ -285,7 +302,7 @@ class CZookeeper
285
302
 
286
303
  def iterate_event_delivery
287
304
  while hash = zkrb_get_next_event_st()
288
- logger.debug { "#{self.class}##{__method__} got #{hash.inspect} " }
305
+ logger.debug { "##{__method__} got #{hash.inspect} " }
289
306
 
290
307
  if (hash[:req_id] == ZKRB_GLOBAL_CB_REQ) && (hash[:type] == -1)
291
308
  ev_state = hash[:state]
@@ -324,14 +341,14 @@ class CZookeeper
324
341
 
325
342
  # use this method to set the @_shutting_down flag to true
326
343
  def shut_down!
327
- logger.debug { "#{self.class}##{__method__}" }
344
+ logger.debug { "##{__method__}" }
328
345
 
329
346
  @mutex.synchronize { @_shutting_down = true }
330
347
  end
331
348
 
332
349
  # called by underlying C code to signal we're running
333
350
  def zkc_set_running_and_notify!
334
- logger.debug { "#{self.class}##{__method__}" }
351
+ logger.debug { "##{__method__}" }
335
352
 
336
353
  @mutex.synchronize do
337
354
  @_running = true
data/lib/zookeeper.rb CHANGED
@@ -40,7 +40,7 @@ module Zookeeper
40
40
  @@logger = nil unless defined?(@@logger)
41
41
 
42
42
  def self.logger
43
- @@logger || ::Logging.logger['Zookeeper']
43
+ @@logger
44
44
  end
45
45
 
46
46
  def self.logger=(logger)
@@ -130,7 +130,7 @@ protected
130
130
  def dispatch_next_callback(hash)
131
131
  return nil unless hash
132
132
 
133
- Zookeeper.logger.debug { "get_next_event returned: #{prettify_event(hash).inspect}" }
133
+ logger.debug { "get_next_event returned: #{prettify_event(hash).inspect}" }
134
134
 
135
135
  is_completion = hash.has_key?(:rc)
136
136
 
@@ -22,7 +22,7 @@ module Zookeeper
22
22
  @mutex = Mutex.new
23
23
  end
24
24
 
25
- def synchronized
25
+ def synchronize
26
26
  @mutex.lock
27
27
  begin
28
28
  yield self
@@ -85,10 +85,6 @@ module Zookeeper
85
85
 
86
86
  # make this error reporting more robust if necessary, right now, just set to state
87
87
  @error = nil
88
-
89
- # set to true when an event occurs that would cause the caller to
90
- # otherwise block forever
91
- @interrupt = false
92
88
  end
93
89
 
94
90
  # the caller calls this method and receives the response from the async loop
@@ -99,6 +95,8 @@ module Zookeeper
99
95
  case @error
100
96
  when nil
101
97
  # ok, nothing to see here, carry on
98
+ when :shutdown
99
+ raise Exceptions::NotConnected, "the connection is shutting down"
102
100
  when ZOO_EXPIRED_SESSION_STATE
103
101
  raise Exceptions::SessionExpired, "connection has expired"
104
102
  else
@@ -162,6 +160,15 @@ module Zookeeper
162
160
  @meth == :state
163
161
  end
164
162
 
163
+ # interrupt the sleeping thread with a NotConnected error
164
+ def shutdown!
165
+ @mutex.synchronize do
166
+ return if @rval or @error
167
+ @error = :shutdown
168
+ @cond.broadcast
169
+ end
170
+ end
171
+
165
172
  protected
166
173
 
167
174
  # an args array with the only difference being that if there's a user
@@ -1,4 +1,4 @@
1
1
  module Zookeeper
2
- VERSION = '1.2.2'
2
+ VERSION = '1.2.3'
3
3
  DRIVER_VERSION = '3.3.5'
4
4
  end
@@ -61,7 +61,7 @@ describe 'Zookeeper chrooted' do
61
61
 
62
62
  describe do
63
63
  before :all do
64
- Zookeeper.logger.warn "running before :all"
64
+ logger.warn "running before :all"
65
65
 
66
66
  with_open_zk do |z|
67
67
  z.create(:path => chroot_path, :data => '')
@@ -11,7 +11,7 @@ shared_examples_for "connection" do
11
11
  end
12
12
 
13
13
  after :all do
14
- Zookeeper.logger.warn "running shared examples after :all"
14
+ logger.warn "running shared examples after :all"
15
15
 
16
16
  with_open_zk(connection_string) do |z|
17
17
  rm_rf(z, path)
@@ -3,12 +3,14 @@ module Zookeeper
3
3
  end
4
4
 
5
5
  layout = Logging.layouts.pattern(
6
- :pattern => '%.1l, [%d #%p]: %m\n',
6
+ :pattern => '%.1l, [%d #%p] %25.25c{2}: %m\n',
7
7
  :date_pattern => '%Y-%m-%d %H:%M:%S.%6N'
8
8
  )
9
9
 
10
10
  appender = (ENV['ZOOKEEPER_DEBUG'] || ENV['ZKRB_DEBUG']) ? Logging.appenders.stderr : Logging.appenders.file(Zookeeper::TEST_LOG_PATH)
11
11
  appender.layout = layout
12
+ appender.auto_flushing = 25
13
+ appender.flush_period = 5
12
14
 
13
15
  %w[spec Zookeeper].each do |name|
14
16
  ::Logging.logger[name].tap do |log|
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zookeeper
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 2
10
- version: 1.2.2
9
+ - 3
10
+ version: 1.2.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Phillip Pearson
@@ -20,7 +20,7 @@ autorequire:
20
20
  bindir: bin
21
21
  cert_chain: []
22
22
 
23
- date: 2012-05-21 00:00:00 Z
23
+ date: 2012-05-23 00:00:00 Z
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: backports
@@ -193,3 +193,4 @@ test_files:
193
193
  - spec/support/progress_formatter.rb
194
194
  - spec/support/zookeeper_spec_helpers.rb
195
195
  - spec/zookeeper_spec.rb
196
+ has_rdoc: