zk 0.8.6 → 0.8.7
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/.dotfiles/rvmrc +1 -1
- data/Gemfile +2 -8
- data/Rakefile +24 -9
- data/lib/z_k/locker.rb +4 -5
- data/lib/z_k/version.rb +1 -1
- data/spec/z_k/locker_spec.rb +262 -223
- data/zk.gemspec +5 -5
- metadata +29 -27
data/.dotfiles/rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm jruby-1.6.
|
1
|
+
rvm jruby-1.6.7@zk --create
|
data/Gemfile
CHANGED
@@ -1,15 +1,9 @@
|
|
1
|
+
# this is here for doing internal builds in our environment
|
2
|
+
source ENV['MBOX_BUNDLER_SOURCE'] if ENV['MBOX_BUNDLER_SOURCE']
|
1
3
|
source "http://rubygems.org"
|
2
|
-
source "http://rubygems"
|
3
|
-
source "http://localhost:50000"
|
4
4
|
|
5
5
|
# Specify your gem's dependencies in zk.gemspec
|
6
6
|
gemspec
|
7
7
|
|
8
|
-
gem 'ruby-debug', :platforms => [:mri_18, :jruby]
|
9
|
-
|
10
|
-
if RUBY_VERSION < '1.9.3'
|
11
|
-
gem 'ruby-debug19', :platforms => :mri_19
|
12
|
-
end
|
13
|
-
|
14
8
|
|
15
9
|
# vim:ft=ruby
|
data/Rakefile
CHANGED
@@ -1,13 +1,28 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
# require 'rubygems'
|
2
|
+
# gem 'rdoc', '~> 2.5'
|
3
|
+
# require 'rdoc/task'
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
# RDoc::Task.new do |rd|
|
6
|
+
# rd.title = 'ZK Documentation'
|
7
|
+
# rd.rdoc_files.include("lib/**/*.rb")
|
8
|
+
# end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
gemset_name = 'zk'
|
11
|
+
|
12
|
+
%w[1.9.3 jruby].each do |rvm_ruby|
|
13
|
+
ruby_with_gemset = "#{rvm_ruby}@#{gemset_name}"
|
14
|
+
bundle_task_name = "mb:#{rvm_ruby}:bundle_install"
|
15
|
+
rspec_task_name = "mb:#{rvm_ruby}:run_rspec"
|
16
|
+
|
17
|
+
task bundle_task_name do
|
18
|
+
rm_f 'Gemfile.lock'
|
19
|
+
sh "rvm #{ruby_with_gemset} do bundle install"
|
20
|
+
end
|
12
21
|
|
22
|
+
task rspec_task_name => bundle_task_name do
|
23
|
+
sh "rvm #{ruby_with_gemset} do bundle exec rspec spec --fail-fast"
|
24
|
+
end
|
25
|
+
|
26
|
+
task "mb:test_all_rubies" => rspec_task_name
|
27
|
+
end
|
13
28
|
|
data/lib/z_k/locker.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
module ZK
|
2
|
-
# Implements locking primitives
|
2
|
+
# Implements locking primitives [described here](http://hadoop.apache.org/zookeeper/docs/current/recipes.html#sc_recipes_Locks)
|
3
3
|
#
|
4
4
|
# There are both shared and exclusive lock implementations.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# synchronize operations.
|
6
|
+
# NOTE: These lock instances are _not_ safe for use across threads. If you
|
7
|
+
# want to use the same Locker instance between threads, it is your
|
8
|
+
# responsibility to synchronize operations.
|
10
9
|
#
|
11
10
|
module Locker
|
12
11
|
SHARED_LOCK_PREFIX = 'sh'.freeze
|
data/lib/z_k/version.rb
CHANGED
data/spec/z_k/locker_spec.rb
CHANGED
@@ -74,313 +74,352 @@ describe 'ZK::Client#locker' do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
|
77
|
+
shared_examples_for 'SharedLocker' do
|
78
78
|
before do
|
79
|
-
@
|
80
|
-
@
|
81
|
-
@zk3 = ZK.new("localhost:#{ZK_TEST_PORT}")
|
82
|
-
@connections = [@zk, @zk2, @zk3]
|
83
|
-
|
84
|
-
wait_until{ @connections.all? {|c| c.connected?} }
|
85
|
-
|
86
|
-
@path = "shlock"
|
87
|
-
@root_lock_path = "/_zklocking/#{@path}"
|
79
|
+
@shared_locker = ZK::Locker.shared_locker(zk, path)
|
80
|
+
@shared_locker2 = ZK::Locker.shared_locker(zk2, path)
|
88
81
|
end
|
89
82
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
83
|
+
describe :lock! do
|
84
|
+
describe 'non-blocking success' do
|
85
|
+
before do
|
86
|
+
@rval = @shared_locker.lock!
|
87
|
+
@rval2 = @shared_locker2.lock!
|
88
|
+
end
|
94
89
|
|
90
|
+
it %[should acquire the first lock] do
|
91
|
+
@rval.should be_true
|
92
|
+
@shared_locker.should be_locked
|
93
|
+
end
|
95
94
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
95
|
+
it %[should acquire the second lock] do
|
96
|
+
@rval2.should be_true
|
97
|
+
@shared_locker2.should be_locked
|
98
|
+
end
|
100
99
|
end
|
101
100
|
|
102
|
-
describe
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
101
|
+
describe 'non-blocking failure' do
|
102
|
+
before do
|
103
|
+
zk.mkdir_p(root_lock_path)
|
104
|
+
@write_lock_path = zk.create("#{root_lock_path}/#{ZK::Locker::EXCLUSIVE_LOCK_PREFIX}", '', :mode => :ephemeral_sequential)
|
105
|
+
@rval = @shared_locker.lock!
|
106
|
+
end
|
108
107
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
108
|
+
after do
|
109
|
+
zk.rm_rf('/_zklocking')
|
110
|
+
end
|
113
111
|
|
114
|
-
|
115
|
-
|
116
|
-
@shared_locker2.should be_locked
|
117
|
-
end
|
112
|
+
it %[should return false] do
|
113
|
+
@rval.should be_false
|
118
114
|
end
|
119
115
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
@rval = @shared_locker.lock!
|
125
|
-
end
|
116
|
+
it %[should not be locked] do
|
117
|
+
@shared_locker.should_not be_locked
|
118
|
+
end
|
119
|
+
end
|
126
120
|
|
127
|
-
|
128
|
-
|
129
|
-
|
121
|
+
describe 'blocking success' do
|
122
|
+
before do
|
123
|
+
zk.mkdir_p(root_lock_path)
|
124
|
+
@write_lock_path = zk.create("#{root_lock_path}/#{ZK::Locker::EXCLUSIVE_LOCK_PREFIX}", '', :mode => :ephemeral_sequential)
|
125
|
+
$stderr.sync = true
|
126
|
+
end
|
130
127
|
|
131
|
-
|
132
|
-
|
133
|
-
end
|
128
|
+
it %[should acquire the lock after the write lock is released] do
|
129
|
+
ary = []
|
134
130
|
|
135
|
-
|
136
|
-
@shared_locker.should_not be_locked
|
137
|
-
end
|
138
|
-
end
|
131
|
+
@shared_locker.lock!.should be_false
|
139
132
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
@write_lock_path = @zk.create("#{@root_lock_path}/#{ZK::Locker::EXCLUSIVE_LOCK_PREFIX}", '', :mode => :ephemeral_sequential)
|
144
|
-
$stderr.sync = true
|
133
|
+
th = Thread.new do
|
134
|
+
@shared_locker.lock!(true)
|
135
|
+
ary << :locked
|
145
136
|
end
|
146
137
|
|
147
|
-
|
148
|
-
|
138
|
+
ary.should be_empty
|
139
|
+
@shared_locker.should_not be_locked
|
149
140
|
|
150
|
-
|
141
|
+
zk.delete(@write_lock_path)
|
151
142
|
|
152
|
-
|
153
|
-
@shared_locker.lock!(true)
|
154
|
-
ary << :locked
|
155
|
-
end
|
143
|
+
th.join(2)
|
156
144
|
|
157
|
-
|
158
|
-
|
145
|
+
wait_until(2) { !ary.empty? }
|
146
|
+
ary.length.should == 1
|
159
147
|
|
160
|
-
|
148
|
+
@shared_locker.should be_locked
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end # SharedLocker
|
161
153
|
|
162
|
-
|
154
|
+
shared_examples_for 'ExclusiveLocker' do
|
155
|
+
before do
|
156
|
+
@ex_locker = ZK::Locker.exclusive_locker(zk, path)
|
157
|
+
@ex_locker2 = ZK::Locker.exclusive_locker(zk2, path)
|
158
|
+
end
|
163
159
|
|
164
|
-
|
165
|
-
|
160
|
+
describe :lock! do
|
161
|
+
describe 'non-blocking' do
|
162
|
+
before do
|
163
|
+
@rval = @ex_locker.lock!
|
164
|
+
@rval2 = @ex_locker2.lock!
|
165
|
+
end
|
166
166
|
|
167
|
-
|
168
|
-
|
167
|
+
it %[should acquire the first lock] do
|
168
|
+
@rval.should be_true
|
169
169
|
end
|
170
|
-
end
|
171
|
-
end # SharedLocker
|
172
170
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
171
|
+
it %[should not acquire the second lock] do
|
172
|
+
@rval2.should be_false
|
173
|
+
end
|
174
|
+
|
175
|
+
it %[should acquire the second lock after the first lock is released] do
|
176
|
+
@ex_locker.unlock!.should be_true
|
177
|
+
@ex_locker2.lock!.should be_true
|
178
|
+
end
|
177
179
|
end
|
178
180
|
|
179
|
-
describe
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
end
|
181
|
+
describe 'blocking' do
|
182
|
+
before do
|
183
|
+
zk.mkdir_p(root_lock_path)
|
184
|
+
@read_lock_path = zk.create('/_zklocking/shlock/read', '', :mode => :ephemeral_sequential)
|
185
|
+
end
|
185
186
|
|
186
|
-
|
187
|
-
|
188
|
-
|
187
|
+
it %[should block waiting for the lock] do
|
188
|
+
ary = []
|
189
|
+
|
190
|
+
@ex_locker.lock!.should be_false
|
189
191
|
|
190
|
-
|
191
|
-
@
|
192
|
+
th = Thread.new do
|
193
|
+
@ex_locker.lock!(true)
|
194
|
+
ary << :locked
|
192
195
|
end
|
193
196
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
+
th.run
|
198
|
+
|
199
|
+
ary.should be_empty
|
200
|
+
@ex_locker.should_not be_locked
|
201
|
+
|
202
|
+
zk.delete(@read_lock_path)
|
203
|
+
|
204
|
+
th.join(2)
|
205
|
+
|
206
|
+
ary.length.should == 1
|
207
|
+
@ex_locker.should be_locked
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end # ExclusiveLocker
|
212
|
+
|
213
|
+
shared_examples_for 'shared-exclusive interaction' do
|
214
|
+
before do
|
215
|
+
@sh_lock = ZK::Locker.shared_locker(zk, path)
|
216
|
+
@ex_lock = ZK::Locker.exclusive_locker(zk2, path)
|
217
|
+
end
|
218
|
+
|
219
|
+
describe 'shared lock acquired first' do
|
220
|
+
it %[should block exclusive locks from acquiring until released] do
|
221
|
+
q1 = Queue.new
|
222
|
+
q2 = Queue.new
|
223
|
+
|
224
|
+
th1 = Thread.new do
|
225
|
+
@sh_lock.with_lock do
|
226
|
+
q1.enq(:got_lock)
|
227
|
+
Thread.current[:got_lock] = true
|
228
|
+
q2.pop
|
197
229
|
end
|
198
230
|
end
|
199
231
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
232
|
+
th2 = Thread.new do
|
233
|
+
q1.pop # wait for th1 to get the shared lock
|
234
|
+
|
235
|
+
Thread.current[:acquiring_lock] = true
|
236
|
+
|
237
|
+
@ex_lock.with_lock do
|
238
|
+
Thread.current[:got_lock] = true
|
204
239
|
end
|
240
|
+
end
|
205
241
|
|
206
|
-
|
207
|
-
|
242
|
+
th1.join_until { th1[:got_lock] }
|
243
|
+
th1[:got_lock].should be_true
|
208
244
|
|
209
|
-
|
245
|
+
th2.join_until { th2[:acquiring_lock] }
|
246
|
+
th2[:acquiring_lock].should be_true
|
210
247
|
|
211
|
-
|
212
|
-
|
213
|
-
ary << :locked
|
214
|
-
end
|
248
|
+
q2.num_waiting.should > 0
|
249
|
+
q2.enq(:release)
|
215
250
|
|
216
|
-
|
217
|
-
|
218
|
-
ary.should be_empty
|
219
|
-
@ex_locker.should_not be_locked
|
251
|
+
th1.join_until { q2.size == 0 }
|
252
|
+
q2.size.should == 0
|
220
253
|
|
221
|
-
|
254
|
+
th1.join(2).should == th1
|
222
255
|
|
223
|
-
|
256
|
+
th2.join_until { th2[:got_lock] }
|
257
|
+
th2[:got_lock].should be_true
|
224
258
|
|
225
|
-
|
226
|
-
@ex_locker.should be_locked
|
227
|
-
end
|
228
|
-
end
|
259
|
+
th2.join(2).should == th2
|
229
260
|
end
|
230
|
-
end
|
261
|
+
end
|
231
262
|
|
232
|
-
describe '
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
263
|
+
describe 'exclusive lock acquired first' do
|
264
|
+
it %[should block shared lock from acquiring until released] do
|
265
|
+
# same test as above but with the thread's locks switched,
|
266
|
+
# th1 is the exclusive locker
|
267
|
+
|
268
|
+
q1 = Queue.new
|
269
|
+
q2 = Queue.new
|
237
270
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
th1 = Thread.new do
|
244
|
-
@sh_lock.with_lock do
|
245
|
-
q1.enq(:got_lock)
|
246
|
-
Thread.current[:got_lock] = true
|
247
|
-
q2.pop
|
248
|
-
end
|
271
|
+
th1 = Thread.new do
|
272
|
+
@ex_lock.with_lock do
|
273
|
+
q1.enq(:got_lock)
|
274
|
+
Thread.current[:got_lock] = true
|
275
|
+
q2.pop
|
249
276
|
end
|
277
|
+
end
|
250
278
|
|
251
|
-
|
252
|
-
|
279
|
+
th2 = Thread.new do
|
280
|
+
q1.pop # wait for th1 to get the shared lock
|
253
281
|
|
254
|
-
|
282
|
+
Thread.current[:acquiring_lock] = true
|
255
283
|
|
256
|
-
|
257
|
-
|
258
|
-
end
|
284
|
+
@sh_lock.with_lock do
|
285
|
+
Thread.current[:got_lock] = true
|
259
286
|
end
|
287
|
+
end
|
260
288
|
|
261
|
-
|
262
|
-
|
289
|
+
th1.join_until { th1[:got_lock] }
|
290
|
+
th1[:got_lock].should be_true
|
263
291
|
|
264
|
-
|
265
|
-
|
292
|
+
th2.join_until { th2[:acquiring_lock] }
|
293
|
+
th2[:acquiring_lock].should be_true
|
266
294
|
|
267
|
-
|
268
|
-
|
295
|
+
q2.num_waiting.should > 0
|
296
|
+
q2.enq(:release)
|
269
297
|
|
270
|
-
|
271
|
-
|
298
|
+
th1.join_until { q2.size == 0 }
|
299
|
+
q2.size.should == 0
|
272
300
|
|
273
|
-
|
301
|
+
th1.join(2).should == th1
|
274
302
|
|
275
|
-
|
276
|
-
|
303
|
+
th2.join_until { th2[:got_lock] }
|
304
|
+
th2[:got_lock].should be_true
|
277
305
|
|
278
|
-
|
279
|
-
|
306
|
+
th2.join(2).should == th2
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
describe 'shared-exclusive-shared' do
|
311
|
+
before do
|
312
|
+
zk3.should_not be_nil
|
313
|
+
@sh_lock2 = ZK::Locker.shared_locker(zk3, path)
|
280
314
|
end
|
281
315
|
|
282
|
-
|
283
|
-
|
284
|
-
# same test as above but with the thread's locks switched,
|
285
|
-
# th1 is the exclusive locker
|
316
|
+
it %[should act something like a queue] do
|
317
|
+
@array = []
|
286
318
|
|
287
|
-
|
288
|
-
|
319
|
+
@sh_lock.lock!.should be_true
|
320
|
+
@sh_lock.should be_locked
|
289
321
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
322
|
+
ex_th = Thread.new do
|
323
|
+
begin
|
324
|
+
@ex_lock.lock!(true) # blocking lock
|
325
|
+
Thread.current[:got_lock] = true
|
326
|
+
@array << :ex_lock
|
327
|
+
ensure
|
328
|
+
@ex_lock.unlock!
|
296
329
|
end
|
330
|
+
end
|
297
331
|
|
298
|
-
|
299
|
-
|
332
|
+
ex_th.join_until { @ex_lock.waiting? }
|
333
|
+
@ex_lock.should be_waiting
|
334
|
+
@ex_lock.should_not be_locked
|
335
|
+
|
336
|
+
# this is the important one, does the second shared lock get blocked by
|
337
|
+
# the exclusive lock
|
338
|
+
@sh_lock2.lock!.should_not be_true
|
339
|
+
|
340
|
+
sh2_th = Thread.new do
|
341
|
+
begin
|
342
|
+
@sh_lock2.lock!(true)
|
343
|
+
Thread.current[:got_lock] = true
|
344
|
+
@array << :sh_lock2
|
345
|
+
ensure
|
346
|
+
@sh_lock2.unlock!
|
347
|
+
end
|
348
|
+
end
|
300
349
|
|
301
|
-
|
350
|
+
sh2_th.join_until { @sh_lock2.waiting? }
|
351
|
+
@sh_lock2.should be_waiting
|
302
352
|
|
303
|
-
|
304
|
-
Thread.current[:got_lock] = true
|
305
|
-
end
|
306
|
-
end
|
353
|
+
@sh_lock.unlock!.should be_true
|
307
354
|
|
308
|
-
|
309
|
-
|
355
|
+
ex_th.join_until { ex_th[:got_lock] }
|
356
|
+
ex_th[:got_lock].should be_true
|
310
357
|
|
311
|
-
|
312
|
-
|
358
|
+
sh2_th.join_until { sh2_th[:got_lock] }
|
359
|
+
sh2_th[:got_lock].should be_true
|
313
360
|
|
314
|
-
|
315
|
-
|
361
|
+
@array.length.should == 2
|
362
|
+
@array.should == [:ex_lock, :sh_lock2]
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end # shared-exclusive interaction
|
316
366
|
|
317
|
-
th1.join_until { q2.size == 0 }
|
318
|
-
q2.size.should == 0
|
319
367
|
|
320
|
-
|
368
|
+
describe ZK::Locker do
|
369
|
+
let(:zk) { ZK.new("localhost:#{ZK_TEST_PORT}", :watcher => :default) }
|
370
|
+
let(:zk2) { ZK.new("localhost:#{ZK_TEST_PORT}", :watcher => :default) }
|
371
|
+
let(:zk3) { ZK.new("localhost:#{ZK_TEST_PORT}") }
|
321
372
|
|
322
|
-
|
323
|
-
th2[:got_lock].should be_true
|
373
|
+
let(:connections) { [zk, zk2, zk3] }
|
324
374
|
|
325
|
-
|
326
|
-
|
327
|
-
end
|
375
|
+
let(:path) { "shlock" }
|
376
|
+
let(:root_lock_path) { "/_zklocking/#{path}" }
|
328
377
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
378
|
+
before do
|
379
|
+
wait_until{ connections.all?(&:connected?) }
|
380
|
+
end
|
381
|
+
|
382
|
+
after do
|
383
|
+
connections.each { |c| c.close! }
|
384
|
+
wait_until { !connections.any?(&:connected?) }
|
385
|
+
end
|
334
386
|
|
335
|
-
|
336
|
-
|
387
|
+
it_should_behave_like 'SharedLocker'
|
388
|
+
it_should_behave_like 'ExclusiveLocker'
|
389
|
+
it_should_behave_like 'shared-exclusive interaction'
|
390
|
+
end # ZK::Locker
|
337
391
|
|
338
|
-
|
339
|
-
|
392
|
+
describe "ZK::Locker chrooted" do
|
393
|
+
let(:chroot_path) { '/_zk_chroot_' }
|
340
394
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
Thread.current[:got_lock] = true
|
345
|
-
@array << :ex_lock
|
346
|
-
ensure
|
347
|
-
@ex_lock.unlock!
|
348
|
-
end
|
349
|
-
end
|
395
|
+
let(:zk) { ZK.new("localhost:#{ZK_TEST_PORT}#{chroot_path}") }
|
396
|
+
let(:zk2) { ZK.new("localhost:#{ZK_TEST_PORT}#{chroot_path}") }
|
397
|
+
let(:zk3) { ZK.new("localhost:#{ZK_TEST_PORT}#{chroot_path}") }
|
350
398
|
|
351
|
-
|
352
|
-
@ex_lock.should be_waiting
|
353
|
-
@ex_lock.should_not be_locked
|
354
|
-
|
355
|
-
# this is the important one, does the second shared lock get blocked by
|
356
|
-
# the exclusive lock
|
357
|
-
@sh_lock2.lock!.should_not be_true
|
358
|
-
|
359
|
-
sh2_th = Thread.new do
|
360
|
-
begin
|
361
|
-
@sh_lock2.lock!(true)
|
362
|
-
Thread.current[:got_lock] = true
|
363
|
-
@array << :sh_lock2
|
364
|
-
ensure
|
365
|
-
@sh_lock2.unlock!
|
366
|
-
end
|
367
|
-
end
|
399
|
+
let(:connections) { [zk, zk2, zk3] }
|
368
400
|
|
369
|
-
|
370
|
-
|
401
|
+
let(:path) { "shlock" }
|
402
|
+
let(:root_lock_path) { "/_zklocking/#{path}" }
|
371
403
|
|
372
|
-
|
404
|
+
before do
|
405
|
+
ZK.open("localhost:#{ZK_TEST_PORT}") do |zk|
|
406
|
+
zk.mkdir_p(chroot_path)
|
407
|
+
end
|
373
408
|
|
374
|
-
|
375
|
-
|
409
|
+
wait_until{ connections.all?(&:connected?) }
|
410
|
+
end
|
376
411
|
|
377
|
-
|
378
|
-
|
412
|
+
after do
|
413
|
+
connections.each { |c| c.close! }
|
414
|
+
wait_until { !connections.any?(&:connected?) }
|
379
415
|
|
380
|
-
|
381
|
-
|
382
|
-
end
|
416
|
+
ZK.open("localhost:#{ZK_TEST_PORT}") do |zk|
|
417
|
+
zk.rm_rf(chroot_path)
|
383
418
|
end
|
384
419
|
end
|
420
|
+
|
421
|
+
it_should_behave_like 'SharedLocker'
|
422
|
+
it_should_behave_like 'ExclusiveLocker'
|
423
|
+
it_should_behave_like 'shared-exclusive interaction'
|
385
424
|
end
|
386
425
|
|
data/zk.gemspec
CHANGED
@@ -8,16 +8,16 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Jonathan D. Simms", "Topper Bowers"]
|
10
10
|
s.email = ["simms@hp.com", "tobowers@hp.com"]
|
11
|
-
s.homepage = ""
|
11
|
+
s.homepage = "https://github.com/slyphon/zk"
|
12
12
|
s.summary = %q{A high-level wrapper around the zookeeper driver}
|
13
|
-
s.description = s.summary
|
13
|
+
s.description = s.summary + "\n"
|
14
14
|
|
15
|
-
s.add_runtime_dependency 'slyphon-zookeeper', '~> 0.
|
15
|
+
s.add_runtime_dependency 'slyphon-zookeeper', '~> 0.3.0'
|
16
16
|
|
17
|
-
s.add_development_dependency 'rspec', '~> 2.
|
18
|
-
s.add_development_dependency 'wirble'
|
17
|
+
s.add_development_dependency 'rspec', '~> 2.8.0'
|
19
18
|
s.add_development_dependency 'flexmock', '~> 0.8.10'
|
20
19
|
s.add_development_dependency 'ZenTest', '~> 4.5.0'
|
20
|
+
s.add_development_dependency 'pry'
|
21
21
|
|
22
22
|
s.files = `git ls-files`.split("\n")
|
23
23
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 49
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 8
|
9
|
-
-
|
10
|
-
version: 0.8.
|
9
|
+
- 7
|
10
|
+
version: 0.8.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jonathan D. Simms
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-04-11 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: slyphon-zookeeper
|
@@ -26,12 +26,12 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 19
|
30
30
|
segments:
|
31
31
|
- 0
|
32
|
-
-
|
33
|
-
-
|
34
|
-
version: 0.
|
32
|
+
- 3
|
33
|
+
- 0
|
34
|
+
version: 0.3.0
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
37
|
- !ruby/object:Gem::Dependency
|
@@ -42,30 +42,32 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
45
|
+
hash: 47
|
46
46
|
segments:
|
47
47
|
- 2
|
48
|
-
-
|
48
|
+
- 8
|
49
49
|
- 0
|
50
|
-
version: 2.
|
50
|
+
version: 2.8.0
|
51
51
|
type: :development
|
52
52
|
version_requirements: *id002
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
54
|
+
name: flexmock
|
55
55
|
prerelease: false
|
56
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
hash:
|
61
|
+
hash: 43
|
62
62
|
segments:
|
63
63
|
- 0
|
64
|
-
|
64
|
+
- 8
|
65
|
+
- 10
|
66
|
+
version: 0.8.10
|
65
67
|
type: :development
|
66
68
|
version_requirements: *id003
|
67
69
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
70
|
+
name: ZenTest
|
69
71
|
prerelease: false
|
70
72
|
requirement: &id004 !ruby/object:Gem::Requirement
|
71
73
|
none: false
|
@@ -74,29 +76,29 @@ dependencies:
|
|
74
76
|
- !ruby/object:Gem::Version
|
75
77
|
hash: 43
|
76
78
|
segments:
|
79
|
+
- 4
|
80
|
+
- 5
|
77
81
|
- 0
|
78
|
-
|
79
|
-
- 10
|
80
|
-
version: 0.8.10
|
82
|
+
version: 4.5.0
|
81
83
|
type: :development
|
82
84
|
version_requirements: *id004
|
83
85
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
86
|
+
name: pry
|
85
87
|
prerelease: false
|
86
88
|
requirement: &id005 !ruby/object:Gem::Requirement
|
87
89
|
none: false
|
88
90
|
requirements:
|
89
|
-
- -
|
91
|
+
- - ">="
|
90
92
|
- !ruby/object:Gem::Version
|
91
|
-
hash:
|
93
|
+
hash: 3
|
92
94
|
segments:
|
93
|
-
- 4
|
94
|
-
- 5
|
95
95
|
- 0
|
96
|
-
version:
|
96
|
+
version: "0"
|
97
97
|
type: :development
|
98
98
|
version_requirements: *id005
|
99
|
-
description:
|
99
|
+
description: |
|
100
|
+
A high-level wrapper around the zookeeper driver
|
101
|
+
|
100
102
|
email:
|
101
103
|
- simms@hp.com
|
102
104
|
- tobowers@hp.com
|
@@ -153,7 +155,7 @@ files:
|
|
153
155
|
- spec/z_k/threadpool_spec.rb
|
154
156
|
- spec/zookeeper_spec.rb
|
155
157
|
- zk.gemspec
|
156
|
-
homepage:
|
158
|
+
homepage: https://github.com/slyphon/zk
|
157
159
|
licenses: []
|
158
160
|
|
159
161
|
post_install_message:
|