zookeeper 1.2.2 → 1.2.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/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: