zookeeper 1.2.0 → 1.2.1

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,17 @@
1
+ v1.2.1 simplify assert_open
2
+
3
+ * The client methods were all calling assert_open before performing an
4
+ action. This was meant as a fail-early lightweight check of the connection
5
+ state and it worked well when we were running against the mt code. Now this
6
+ requires us to use a Continuation and make our way through the event loop.
7
+ There is a possible deadlock this release should solve that was caused by
8
+ the assert_open code holding a lock while making an async call through
9
+ the event loop. This is no longer the case. The assert_open call only checks
10
+ that the current handle hasn't been closed, the connection-state checking
11
+ now occurs before submitting a request on the event iteration thread, and
12
+ the behavior should be the same as it was before. If the underlying
13
+ connection is not in the 'connected' state, an exception will be raised.
14
+
1
15
  v1.2.0 Stop the World, I Wanna fork()
2
16
 
3
17
  * changed pause/resume methods to pause_before_fork_in_parent
@@ -117,8 +117,7 @@ class ZookeeperBase
117
117
  # if either of these happen, the user will need to renegotiate a connection via reopen
118
118
  def assert_open
119
119
  @mutex.synchronize do
120
- raise Exceptions::SessionExpired if state == ZOO_EXPIRED_SESSION_STATE
121
- raise Exceptions::NotConnected unless connected?
120
+ raise Exceptions::NotConnected if closed?
122
121
  if forked?
123
122
  raise InheritedConnectionError, <<-EOS.gsub(/(?:^|\n)\s*/, ' ').strip
124
123
  You tried to use a connection inherited from another process
data/lib/zookeeper.rb CHANGED
@@ -5,6 +5,7 @@ require 'monitor'
5
5
  require 'forwardable'
6
6
  require 'logger'
7
7
  require 'benchmark'
8
+ require 'logging'
8
9
 
9
10
  module Zookeeper
10
11
  # establishes the namespace
@@ -33,13 +34,13 @@ require_relative 'zookeeper/client'
33
34
 
34
35
  module Zookeeper
35
36
  include Constants
36
-
37
- unless defined?(@@logger)
38
- @@logger = ::Logger.new($stderr).tap { |l| l.level = ENV['ZOOKEEPER_DEBUG'] ? ::Logger::DEBUG : ::Logger::ERROR }
39
- end
40
-
37
+ #::Logger.new($stderr).tap { |l| l.level = ENV['ZOOKEEPER_DEBUG'] ? ::Logger::DEBUG : ::Logger::ERROR }
38
+ #
39
+
40
+ @@logger = nil unless defined?(@@logger)
41
+
41
42
  def self.logger
42
- @@logger
43
+ @@logger || ::Logging.logger['Zookeeper']
43
44
  end
44
45
 
45
46
  def self.logger=(logger)
@@ -82,6 +82,9 @@ module Zookeeper
82
82
  @mutex = Mutex.new
83
83
  @cond = ConditionVariable.new
84
84
  @rval = nil
85
+
86
+ # make this error reporting more robust if necessary, right now, just set to state
87
+ @error = nil
85
88
 
86
89
  # set to true when an event occurs that would cause the caller to
87
90
  # otherwise block forever
@@ -90,9 +93,17 @@ module Zookeeper
90
93
 
91
94
  # the caller calls this method and receives the response from the async loop
92
95
  def value
93
- @mutex.lock
94
- begin
95
- @cond.wait(@mutex) until @rval
96
+ @mutex.synchronize do
97
+ @cond.wait(@mutex) until @rval or @error
98
+
99
+ case @error
100
+ when nil
101
+ # ok, nothing to see here, carry on
102
+ when ZOO_EXPIRED_SESSION_STATE
103
+ raise Exceptions::SessionExpired, "connection has expired"
104
+ else
105
+ raise Exceptions::NotConnected, "connection state is #{STATE_NAMES[@error]}"
106
+ end
96
107
 
97
108
  case @rval.length
98
109
  when 1
@@ -100,8 +111,6 @@ module Zookeeper
100
111
  else
101
112
  return @rval
102
113
  end
103
- ensure
104
- @mutex.unlock rescue nil
105
114
  end
106
115
  end
107
116
 
@@ -124,13 +133,24 @@ module Zookeeper
124
133
  # implementation, but it's more important to get *something* working and
125
134
  # passing specs, then refactor to make everything sane
126
135
  #
136
+ #
127
137
  def submit(czk)
138
+ state = czk.zkrb_state # check the state of the connection
139
+
140
+ if @meth == :state # if the method is a state call
141
+ @rval = [state] # we're done, no error
142
+ return deliver!
143
+
144
+ elsif state != ZOO_CONNECTED_STATE # otherwise, we must be connected
145
+ @error = state # so set the error
146
+ return deliver! # and we're out
147
+ end
148
+
128
149
  rc, *_ = czk.__send__(:"zkrb_#{@meth}", *async_args)
129
150
 
130
- # if this is an state call, async call, or we failed to submit it
131
- if (@meth == :state) or user_callback? or (rc != ZOK)
132
- @rval = [rc] # create the repsonse
133
- deliver! # wake the caller and we're out
151
+ if user_callback? or (rc != ZOK) # async call, or we failed to submit it
152
+ @rval = [rc] # create the repsonse
153
+ deliver! # wake the caller and we're out
134
154
  end
135
155
  end
136
156
 
@@ -152,9 +172,6 @@ module Zookeeper
152
172
 
153
173
  logger.debug { "async_args, meth: #{meth} ary: #{ary.inspect}, #{callback_arg_idx}" }
154
174
 
155
- # this is not already an async call
156
- # so we replace the req_id with the ZKRB_ASYNC_CONTN_ID so the
157
- # event thread knows to dispatch it itself
158
175
  ary[callback_arg_idx] ||= self
159
176
 
160
177
  ary
@@ -165,11 +182,8 @@ module Zookeeper
165
182
  end
166
183
 
167
184
  def deliver!
168
- @mutex.lock
169
- begin
185
+ @mutex.synchronize do
170
186
  @cond.signal
171
- ensure
172
- @mutex.unlock rescue nil
173
187
  end
174
188
  end
175
189
  end # Base
@@ -1,16 +1,28 @@
1
1
  module Zookeeper
2
2
  module Logger
3
3
  def self.included(mod)
4
+ return false if mod < self # avoid infinite recursion
5
+ mod.class_eval do
6
+ def self.logger
7
+ ::Zookeeper.logger || ::Logging.logger[logger_name]
8
+ end
9
+ end
4
10
  mod.extend(self)
5
11
  end
6
12
 
7
- def self.const_missing(sym)
8
- return ::Logger.const_get(sym) if ::Logger.const_defined?(sym)
9
- super
10
- end
13
+ def self.set_default
14
+ ::Logging.logger['Zookeeper'].tap do |ch_root|
15
+ ::Logging.appenders.stderr.tap do |serr|
16
+ serr.layout = ::Logging.layouts.pattern(
17
+ :pattern => '%.1l, [%d] %c30.30{2}: %m\n',
18
+ :date_pattern => '%Y-%m-%d %H:%M:%S.%6N'
19
+ )
11
20
 
12
- def self.new(*a, &b)
13
- ::Logger.new(*a, &b)
21
+ ch_root.add_appenders(serr)
22
+ end
23
+
24
+ ch_root.level = ENV['ZOOKEEPER_DEBUG'] ? :debug : :off
25
+ end
14
26
  end
15
27
 
16
28
  private
@@ -22,7 +34,7 @@ module Zookeeper
22
34
  end
23
35
 
24
36
  def logger
25
- ::Zookeeper.logger
37
+ @logger ||= (::Zookeeper.logger || ::Logging.logger[self.class.logger_name]) # logger_name defined in ::Logging::Utils
26
38
  end
27
39
  end
28
40
  end
@@ -1,4 +1,4 @@
1
1
  module Zookeeper
2
- VERSION = '1.2.0'
2
+ VERSION = '1.2.1'
3
3
  DRIVER_VERSION = '3.3.5'
4
4
  end
data/spec/spec_helper.rb CHANGED
@@ -16,30 +16,26 @@ require 'zookeeper'
16
16
  Dir[File.expand_path('../support/**/*.rb', __FILE__)].sort.each { |f| require(f) }
17
17
 
18
18
  if ENV['ZKRB_DEBUG']
19
- Zookeeper.logger = Logger.new($stderr).tap { |l| l.level = Logger::DEBUG }
20
19
  Zookeeper.set_debug_level(4)
21
- else
22
- Zookeeper.logger = Logger.new(File.expand_path('../../test.log', __FILE__)).tap do |log|
23
- log.level = Logger::DEBUG
24
- end
25
20
  end
26
21
 
27
22
  if ENV['ZKRB_NOLOG']
28
- Zookeeper.logger.level = Logger::FATAL
23
+ ::Logging.logger['Zookeeper'].level = :off
29
24
  Zookeeper.set_debug_level(0)
30
25
  end
31
26
 
32
-
33
27
  RSpec.configure do |config|
34
28
  config.mock_with :rspec
35
- config.include Zookeeper::SpecHelpers
36
- config.extend Zookeeper::SpecHelpers
29
+ [Zookeeper::SpecHelpers, SpecGlobalLogger].each do |mod|
30
+ config.include(mod)
31
+ config.extend(mod)
32
+ end
37
33
 
38
34
  if Zookeeper.spawn_zookeeper?
39
35
  require 'zk-server'
40
36
 
41
37
  config.before(:suite) do
42
- Zookeeper.logger.debug { "Starting zookeeper service" }
38
+ ::Logging.logger['spec'].debug { "Starting zookeeper service" }
43
39
  ZK::Server.run do |c|
44
40
  c.base_dir = File.expand_path('../../.zkserver', __FILE__)
45
41
  c.client_port = Zookeeper.test_port
@@ -49,7 +45,7 @@ RSpec.configure do |config|
49
45
  end
50
46
 
51
47
  config.after(:suite) do
52
- Zookeeper.logger.debug { "stopping zookeeper service" }
48
+ ::Logging.logger['spec'].debug { "stopping zookeeper service" }
53
49
  ZK::Server.shutdown
54
50
  end
55
51
  end
@@ -0,0 +1,35 @@
1
+ module Zookeeper
2
+ TEST_LOG_PATH = File.expand_path('../../../test.log', __FILE__)
3
+ end
4
+
5
+ layout = Logging.layouts.pattern(
6
+ :pattern => '%.1l, [%d #%p]: %m\n',
7
+ :date_pattern => '%Y-%m-%d %H:%M:%S.%6N'
8
+ )
9
+
10
+ appender = (ENV['ZOOKEEPER_DEBUG'] || ENV['ZKRB_DEBUG']) ? Logging.appenders.stderr : Logging.appenders.file(Zookeeper::TEST_LOG_PATH)
11
+ appender.layout = layout
12
+
13
+ %w[spec Zookeeper].each do |name|
14
+ ::Logging.logger[name].tap do |log|
15
+ log.appenders = [appender]
16
+ log.level = :debug
17
+ end
18
+ end
19
+
20
+ module SpecGlobalLogger
21
+ def logger
22
+ @spec_global_logger ||= ::Logging.logger['spec']
23
+ end
24
+
25
+ # sets the log level to FATAL for the duration of the block
26
+ def mute_logger
27
+ zk_log = Logging.logger['Zookeeper']
28
+ orig_level, zk_log.level = zk_log.level, :off
29
+ orig_zk_level, Zookeeper.debug_level = Zookeeper.debug_level, Zookeeper::Constants::ZOO_LOG_LEVEL_ERROR
30
+ yield
31
+ ensure
32
+ zk_log.level = orig_zk_level
33
+ end
34
+ end
35
+
@@ -5,7 +5,7 @@ module RSpec
5
5
  module Formatters
6
6
  class ProgressFormatter
7
7
  def example_started(example)
8
- Zookeeper.logger.info(yellow("=====<([ #{example.full_description} ])>====="))
8
+ ::Logging.logger['spec'].write(yellow("\n=====<([ #{example.full_description} ])>=====\n"))
9
9
  super(example)
10
10
  end
11
11
  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: 31
4
+ hash: 29
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 0
10
- version: 1.2.0
9
+ - 1
10
+ version: 1.2.1
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-18 00:00:00 Z
23
+ date: 2012-05-21 00:00:00 Z
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: backports
@@ -38,6 +38,22 @@ dependencies:
38
38
  version: 2.5.1
39
39
  type: :runtime
40
40
  version_requirements: *id001
41
+ - !ruby/object:Gem::Dependency
42
+ name: logging
43
+ prerelease: false
44
+ requirement: &id002 !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ hash: 15
50
+ segments:
51
+ - 1
52
+ - 7
53
+ - 2
54
+ version: 1.7.2
55
+ type: :runtime
56
+ version_requirements: *id002
41
57
  description: |+
42
58
  A low-level multi-Ruby wrapper around the ZooKeeper API bindings. For a
43
59
  friendlier interface, see http://github.com/slyphon/zk. Currently supported:
@@ -119,7 +135,8 @@ files:
119
135
  - spec/shared/all_success_return_values.rb
120
136
  - spec/shared/connection_examples.rb
121
137
  - spec/spec_helper.rb
122
- - spec/support/00_spawn_zookeeper.rb
138
+ - spec/support/00_logging.rb
139
+ - spec/support/10_spawn_zookeeper.rb
123
140
  - spec/support/progress_formatter.rb
124
141
  - spec/support/zookeeper_spec_helpers.rb
125
142
  - spec/zookeeper_spec.rb
@@ -171,7 +188,8 @@ test_files:
171
188
  - spec/shared/all_success_return_values.rb
172
189
  - spec/shared/connection_examples.rb
173
190
  - spec/spec_helper.rb
174
- - spec/support/00_spawn_zookeeper.rb
191
+ - spec/support/00_logging.rb
192
+ - spec/support/10_spawn_zookeeper.rb
175
193
  - spec/support/progress_formatter.rb
176
194
  - spec/support/zookeeper_spec_helpers.rb
177
195
  - spec/zookeeper_spec.rb