zookeeper 0.9.3 → 0.9.4

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,10 @@
1
+ v0.9.4 Fix shutdown timing bug
2
+
3
+ * Because we now release the GIL, ruby may call close while there's still
4
+ a pending synchronous call (since we give up the interpreter during that
5
+ time). Protect calls with a mutex so that close can only be called when
6
+ there isn't an in-flight call.
7
+
1
8
  v0.9.3 Event thread shutdown fix, Windows compatibility fix
2
9
 
3
10
  * Use a 'shutdown thread' to coordinate cleanup if close is called from the
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source :rubygems
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'rake', '~> 0.9.0'
6
+
5
7
  group :test do
6
8
  gem "rspec", "~> 2.8.0"
7
9
  gem 'flexmock', '~> 0.8.11'
@@ -10,7 +12,6 @@ group :test do
10
12
  end
11
13
 
12
14
  group :development do
13
- gem 'rake', '~> 0.9.0'
14
15
  gem 'pry'
15
16
  end
16
17
 
data/Rakefile CHANGED
@@ -2,17 +2,24 @@
2
2
  # ENV.fetch('GEM_HOME').split('@').last
3
3
  # end
4
4
 
5
- GEM_FILES = FileList['slyphon-zookeeper-*.gem']
5
+ GEM_FILES = FileList['*zookeeper-*.gem']
6
+
7
+ # need to releaase under both names until ZK is updated to use just 'zookeeper'
8
+ GEM_NAMES = %w[zookeeper slyphon-zookeeper]
6
9
 
7
10
  namespace :mb do
8
11
  namespace :gems do
9
12
  task :build do
10
- sh "rvm 1.8.7 do gem build zookeeper.gemspec"
11
- ENV['JAVA_GEM'] = '1'
12
- sh "rvm 1.8.7 do gem build zookeeper.gemspec"
13
+ GEM_NAMES.each do |gem_name|
14
+ ENV['JAVA_GEM'] = nil
15
+ sh "rvm 1.8.7 do env ZOOKEEPER_GEM_NAME='#{gem_name}' gem build zookeeper.gemspec"
16
+ sh "rvm 1.8.7 do env JAVA_GEM=1 ZOOKEEPER_GEM_NAME='#{gem_name}' gem build zookeeper.gemspec"
17
+ end
13
18
  end
14
19
 
15
- task :push do
20
+ task :push => :build do
21
+ raise "No gemfiles to push!" if GEM_FILES.empty?
22
+
16
23
  GEM_FILES.each do |gem|
17
24
  sh "gem push #{gem}"
18
25
  end
@@ -61,7 +68,7 @@ gemset_name = 'zookeeper'
61
68
  task clobber_task_name do
62
69
  unless rvm_ruby == 'jruby'
63
70
  cd 'ext' do
64
- sh "rake clobber"
71
+ sh "rvm #{ruby_with_gemset} do bundle exec rake clobber"
65
72
  end
66
73
  end
67
74
  end
@@ -69,7 +76,7 @@ gemset_name = 'zookeeper'
69
76
  task clean_task_name do
70
77
  unless rvm_ruby == 'jruby'
71
78
  cd 'ext' do
72
- sh "rake clean"
79
+ sh "rvm #{ruby_with_gemset} do bundle exec rake clean"
73
80
  end
74
81
  end
75
82
  end
@@ -77,7 +84,7 @@ gemset_name = 'zookeeper'
77
84
  task build_task_name => [create_gemset_name, clean_task_name] do
78
85
  unless rvm_ruby == 'jruby'
79
86
  cd 'ext' do
80
- sh "rvm #{ruby_with_gemset} do rake build"
87
+ sh "rvm #{ruby_with_gemset} do bundle exec rake build"
81
88
  end
82
89
  end
83
90
  end
@@ -104,8 +111,6 @@ task "mb:test_all" do
104
111
  $stderr.puts "Test run took: #{t} s"
105
112
  end
106
113
 
107
- task :default => 'mb:1.9.3'
108
-
109
114
  task :clobber do
110
115
  rm_rf 'tmp'
111
116
  end
@@ -137,3 +142,23 @@ task :build do
137
142
  end
138
143
  end
139
144
 
145
+ namespace :spec do
146
+ task :define do
147
+ require 'rubygems'
148
+ require 'bundler/setup'
149
+ require 'rspec/core/rake_task'
150
+
151
+ RSpec::Core::RakeTask.new('spec:runner') do |t|
152
+ t.rspec_opts = '-f d' if ENV['TRAVIS']
153
+ end
154
+
155
+ task 'spec:runner' => :build
156
+ end
157
+
158
+ task :run => :define do
159
+ Rake::Task['spec:runner'].invoke
160
+ end
161
+ end
162
+
163
+ task :default => 'spec:run'
164
+
@@ -26,8 +26,29 @@ class ZookeeperBase
26
26
  ZOO_LOG_LEVEL_INFO = 3
27
27
  ZOO_LOG_LEVEL_DEBUG = 4
28
28
 
29
- def_delegators :czk,
30
- :get_children, :exists, :delete, :get, :set, :set_acl, :get_acl, :client_id, :sync, :selectable_io
29
+
30
+ # this is unfortunately necessary to prevent a really horrendous race in
31
+ # shutdown, where some other thread calls close in the middle of a
32
+ # synchronous operation (thanks to the GIL-releasing wrappers, we now
33
+ # have this problem). so we need to make sure only one thread can be calling
34
+ # a synchronous operation at a time.
35
+ #
36
+ # this might be solved by waiting for a condition where there are no "in flight"
37
+ # operations (thereby allowing multiple threads to make requests simultaneously),
38
+ # but this would represent quite a bit of added complexity, and questionable
39
+ # performance gains.
40
+ #
41
+ def self.synchronized_delegation(provider, *syms)
42
+ syms.each do |sym|
43
+ class_eval(<<-EOM, __FILE__, __LINE__+1)
44
+ def #{sym}(*a, &b)
45
+ @mutex.synchronize { #{provider}.#{sym}(*a, &b) }
46
+ end
47
+ EOM
48
+ end
49
+ end
50
+
51
+ synchronized_delegation :@czk, :get_children, :exists, :delete, :get, :set, :set_acl, :get_acl, :client_id, :sync
31
52
 
32
53
  # some state methods need to be more paranoid about locking to ensure the correct
33
54
  # state is returned
@@ -90,17 +111,13 @@ class ZookeeperBase
90
111
 
91
112
  reopen(timeout)
92
113
  end
93
-
94
- # synchronized accessor to the @czk instance
95
- # @private
96
- def czk
97
- @mutex.synchronize { @czk }
98
- end
99
-
114
+
100
115
  # if either of these happen, the user will need to renegotiate a connection via reopen
101
116
  def assert_open
102
- raise ZookeeperException::SessionExpired if state == ZOO_EXPIRED_SESSION_STATE
103
- raise ZookeeperException::NotConnected unless connected?
117
+ @mutex.synchronize do
118
+ raise ZookeeperException::SessionExpired if state == ZOO_EXPIRED_SESSION_STATE
119
+ raise ZookeeperException::NotConnected unless connected?
120
+ end
104
121
  end
105
122
 
106
123
  def close
@@ -118,7 +135,7 @@ class ZookeeperBase
118
135
  # is pretty damn annoying. this is used to clean things up.
119
136
  def create(*args)
120
137
  # since we don't care about the inputs, just glob args
121
- rc, new_path = czk.create(*args)
138
+ rc, new_path = @mutex.synchronize { @czk.create(*args) }
122
139
  [rc, strip_chroot_from(new_path)]
123
140
  end
124
141
 
@@ -139,15 +156,19 @@ class ZookeeperBase
139
156
 
140
157
  def state
141
158
  return ZOO_CLOSED_STATE if closed?
142
- czk.state
159
+ @mutex.synchronize { @czk.state }
143
160
  end
144
161
 
145
162
  def session_id
146
- cid = client_id and cid.session_id
163
+ @mutex.synchronize do
164
+ cid = client_id and cid.session_id
165
+ end
147
166
  end
148
167
 
149
168
  def session_passwd
150
- cid = client_id and cid.passwd
169
+ @mutex.synchronize do
170
+ cid = client_id and cid.passwd
171
+ end
151
172
  end
152
173
 
153
174
  # we are closed if there is no @czk instance or @czk.closed?
@@ -1,6 +1,6 @@
1
1
  # this "namespacing" is retarded. fix this in 1.0
2
2
  # @private
3
3
  module ZookeeperVersion
4
- VERSION = '0.9.3'
4
+ VERSION = '0.9.4'
5
5
  DRIVER_VERSION = '3.3.5'
6
6
  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: 61
4
+ hash: 51
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 3
10
- version: 0.9.3
9
+ - 4
10
+ version: 0.9.4
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-03 00:00:00 Z
23
+ date: 2012-05-07 00:00:00 Z
24
24
  dependencies: []
25
25
 
26
26
  description: |+