zookeeper 1.2.1 → 1.2.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/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ v1.2.2 avoid race while waiting for connection
2
+
3
+ * There was a possible race in CZookeeper#wait_until_connected where if we
4
+ couldn't connect to the port specified (localhost:28271) then we wound up
5
+ burning 100% CPU and spinning. This solution fixes that by hooking into the
6
+ event delivery and keeping track of what the current state is. When there's
7
+ a change, we use a ConditionVariable to wake up threads that were waiting
8
+ until the connection was connected. Additionally, we now respect the
9
+ timeout parameter again.
10
+
1
11
  v1.2.1 simplify assert_open
2
12
 
3
13
  * The client methods were all calling assert_open before performing an
data/ext/c_zookeeper.rb CHANGED
@@ -70,7 +70,10 @@ class CZookeeper
70
70
  @running_cond = @mutex.new_cond
71
71
 
72
72
  # used to signal we've received the connected event
73
- @connected_cond = @mutex.new_cond
73
+ @state_cond = @mutex.new_cond
74
+
75
+ # the current state of the connection
76
+ @state = ZOO_CLOSED_STATE
74
77
 
75
78
  @pipe_read, @pipe_write = IO.pipe
76
79
 
@@ -167,12 +170,13 @@ class CZookeeper
167
170
  # if timeout is nil, we never time out, and wait forever for CONNECTED state
168
171
  #
169
172
  def wait_until_connected(timeout=10)
170
- # this begin/ensure/end style is recommended by tarceri
171
- # no need to create a context for every mutex grab
172
173
 
173
- wait_until_running(timeout)
174
+ return false unless wait_until_running(timeout)
175
+
176
+ @mutex.synchronize do
177
+ @state_cond.wait(timeout) unless (@state == ZOO_CONNECTED_STATE)
178
+ end
174
179
 
175
- Thread.pass until connected? or is_unrecoverable
176
180
  connected?
177
181
  end
178
182
 
@@ -222,13 +226,10 @@ class CZookeeper
222
226
  #
223
227
  # returns true if we're running, false if we timed out
224
228
  def wait_until_running(timeout=5)
225
- @mutex.lock
226
- begin
229
+ @mutex.synchronize do
227
230
  return true if @_running
228
231
  @running_cond.wait(timeout)
229
232
  !!@_running
230
- ensure
231
- @mutex.unlock rescue nil
232
233
  end
233
234
  end
234
235
 
@@ -286,11 +287,17 @@ class CZookeeper
286
287
  while hash = zkrb_get_next_event_st()
287
288
  logger.debug { "#{self.class}##{__method__} got #{hash.inspect} " }
288
289
 
289
- # notify when we get this event so we know we're connected
290
- if hash.values_at(:req_id, :type, :state) == CONNECTED_EVENT_VALUES[1..2]
291
- notify_connected!
292
- end
290
+ if (hash[:req_id] == ZKRB_GLOBAL_CB_REQ) && (hash[:type] == -1)
291
+ ev_state = hash[:state]
293
292
 
293
+ if @state != ev_state
294
+ @mutex.synchronize do
295
+ @state = ev_state
296
+ @state_cond.broadcast
297
+ end
298
+ end
299
+ end
300
+
294
301
  cntn = @reg.in_flight.delete(hash[:req_id])
295
302
 
296
303
  if cntn and not cntn.user_callback? # this is one of "our" continuations
@@ -307,14 +314,11 @@ class CZookeeper
307
314
  def event_thread_await_running
308
315
  logger.debug { "event_thread waiting until running: #{@_running}" }
309
316
 
310
- @mutex.lock
311
- begin
317
+ @mutex.synchronize do
312
318
  @running_cond.wait_until { @_running or @_shutting_down }
313
319
  logger.debug { "event_thread running: #{@_running}" }
314
320
 
315
321
  raise ShuttingDownException if @_shutting_down
316
- ensure
317
- @mutex.unlock rescue nil
318
322
  end
319
323
  end
320
324
 
@@ -329,22 +333,16 @@ class CZookeeper
329
333
  def zkc_set_running_and_notify!
330
334
  logger.debug { "#{self.class}##{__method__}" }
331
335
 
332
- @mutex.lock
333
- begin
336
+ @mutex.synchronize do
334
337
  @_running = true
335
338
  @running_cond.broadcast
336
- ensure
337
- @mutex.unlock rescue nil
338
339
  end
339
340
  end
340
341
 
341
- def notify_connected!
342
- @mutex.lock
343
- begin
344
- @connected_cond.broadcast
345
- ensure
346
- @mutex.unlock rescue nil
347
- end
348
- end
342
+ # def notify_state_change!
343
+ # @mutex.synchronize do
344
+ # @state_cond.broadcast
345
+ # end
346
+ # end
349
347
  end
350
348
  end
data/java/java_base.rb CHANGED
@@ -405,7 +405,7 @@ class JavaBase
405
405
 
406
406
  def assert_open
407
407
  # XXX don't know how to check for valid session state!
408
- raise ZookeeperException::NotConnected unless connected?
408
+ raise NotConnected unless connected?
409
409
  end
410
410
 
411
411
  # set the watcher object/proc that will receive all global events (such as session/state events)
@@ -1,4 +1,4 @@
1
1
  module Zookeeper
2
- VERSION = '1.2.1'
2
+ VERSION = '1.2.2'
3
3
  DRIVER_VERSION = '3.3.5'
4
4
  end
data/spec/spec_helper.rb CHANGED
@@ -51,3 +51,11 @@ RSpec.configure do |config|
51
51
  end
52
52
  end
53
53
 
54
+ require 'pp'
55
+
56
+ if RUBY_VERSION == '1.9.3'
57
+ trap('USR1') do
58
+ threads = Thread.list.map { |th| th.backtrace }
59
+ pp threads
60
+ end
61
+ end
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: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 1
10
- version: 1.2.1
9
+ - 2
10
+ version: 1.2.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Phillip Pearson