zookeeper 0.9.3-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG +119 -0
  3. data/Gemfile +17 -0
  4. data/LICENSE +23 -0
  5. data/Manifest +29 -0
  6. data/README.markdown +59 -0
  7. data/Rakefile +139 -0
  8. data/examples/cloud_config.rb +125 -0
  9. data/ext/.gitignore +6 -0
  10. data/ext/Rakefile +51 -0
  11. data/ext/c_zookeeper.rb +212 -0
  12. data/ext/dbg.h +53 -0
  13. data/ext/depend +5 -0
  14. data/ext/extconf.rb +85 -0
  15. data/ext/generate_gvl_code.rb +316 -0
  16. data/ext/zkc-3.3.5.tar.gz +0 -0
  17. data/ext/zkrb_wrapper.c +731 -0
  18. data/ext/zkrb_wrapper.h +330 -0
  19. data/ext/zkrb_wrapper_compat.c +15 -0
  20. data/ext/zkrb_wrapper_compat.h +11 -0
  21. data/ext/zookeeper_base.rb +211 -0
  22. data/ext/zookeeper_c.c +725 -0
  23. data/ext/zookeeper_lib.c +677 -0
  24. data/ext/zookeeper_lib.h +172 -0
  25. data/java/zookeeper_base.rb +477 -0
  26. data/lib/zookeeper.rb +297 -0
  27. data/lib/zookeeper/acls.rb +40 -0
  28. data/lib/zookeeper/callbacks.rb +91 -0
  29. data/lib/zookeeper/common.rb +174 -0
  30. data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
  31. data/lib/zookeeper/constants.rb +57 -0
  32. data/lib/zookeeper/em_client.rb +55 -0
  33. data/lib/zookeeper/exceptions.rb +100 -0
  34. data/lib/zookeeper/stat.rb +21 -0
  35. data/lib/zookeeper/version.rb +6 -0
  36. data/notes.txt +14 -0
  37. data/spec/c_zookeeper_spec.rb +50 -0
  38. data/spec/chrooted_connection_spec.rb +81 -0
  39. data/spec/default_watcher_spec.rb +41 -0
  40. data/spec/em_spec.rb +51 -0
  41. data/spec/log4j.properties +17 -0
  42. data/spec/shared/all_success_return_values.rb +10 -0
  43. data/spec/shared/connection_examples.rb +1018 -0
  44. data/spec/spec_helper.rb +119 -0
  45. data/spec/support/progress_formatter.rb +15 -0
  46. data/spec/zookeeper_spec.rb +24 -0
  47. data/test/test_basic.rb +37 -0
  48. data/test/test_callback1.rb +36 -0
  49. data/test/test_close.rb +16 -0
  50. data/test/test_esoteric.rb +7 -0
  51. data/test/test_watcher1.rb +56 -0
  52. data/test/test_watcher2.rb +52 -0
  53. metadata +181 -0
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Zookeeper do
4
+ describe :initialize, 'with watcher block' do
5
+ before do
6
+ @events = []
7
+ @watch_block = lambda do |hash|
8
+ $stderr.puts "watch_block: #{hash.inspect}"
9
+ @events << hash
10
+ end
11
+
12
+ @zk = Zookeeper.new('localhost:2181', 10, @watch_block)
13
+
14
+ wait_until(2) { @zk.connected? }
15
+ @zk.should be_connected
16
+ $stderr.puts "connected!"
17
+
18
+ wait_until(2) { !@events.empty? }
19
+ $stderr.puts "got events!"
20
+ end
21
+
22
+ after do
23
+ @zk.close if @zk.connected?
24
+ end
25
+
26
+ it %[should receive initial connection state events] do
27
+ @events.should_not be_empty
28
+ @events.length.should == 1
29
+ @events.first[:state].should == Zookeeper::ZOO_CONNECTED_STATE
30
+ end
31
+
32
+ it %[should receive disconnection events] do
33
+ pending "the C driver doesn't appear to deliver disconnection events (?)"
34
+ @events.clear
35
+ @zk.close
36
+ wait_until(2) { !@events.empty? }
37
+ @events.should_not be_empty
38
+ end
39
+ end
40
+ end
41
+
data/spec/em_spec.rb ADDED
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ require 'zookeeper/em_client'
3
+
4
+ gem 'evented-spec', '~> 0.9.0'
5
+ require 'evented-spec'
6
+
7
+
8
+ describe 'ZookeeperEM' do
9
+ describe 'Client' do
10
+ include EventedSpec::SpecHelper
11
+ default_timeout 3.0
12
+
13
+ def setup_zk
14
+ @zk = ZookeeperEM::Client.new('localhost:2181')
15
+ em do
16
+ @zk.on_attached do
17
+ yield
18
+ end
19
+ end
20
+ end
21
+
22
+ def teardown_and_done
23
+ @zk.close do
24
+ logger.debug { "TEST: about to call done" }
25
+ EM.next_tick do
26
+ done
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'callbacks' do
32
+ it %[should be called on the reactor thread] do
33
+ cb = lambda do |h|
34
+ EM.reactor_thread?.should be_true
35
+ logger.debug { "called back on the reactor thread? #{EM.reactor_thread?}" }
36
+ teardown_and_done
37
+ end
38
+
39
+ setup_zk do
40
+ @zk.on_attached do |*|
41
+ logger.debug { "on_attached called" }
42
+ rv = @zk.get(:path => '/', :callback => cb)
43
+ logger.debug { "rv from @zk.get: #{rv.inspect}" }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,17 @@
1
+ log4j.rootLogger = DEBUG,S
2
+
3
+ log4j.appender.S = org.apache.log4j.FileAppender
4
+ log4j.appender.S.File = /tmp/zk-test.log
5
+
6
+ log4j.appender.S.layout = org.apache.log4j.PatternLayout
7
+ log4j.appender.S.layout.ConversionPattern = %5p [%t] (%c:%F:%L) - %m%n
8
+
9
+ log4j.appender.C = org.apache.log4j.FileAppender
10
+ log4j.appender.C.File = /tmp/zk-test-client.log
11
+
12
+ log4j.appender.C.layout = org.apache.log4j.PatternLayout
13
+ log4j.appender.C.layout.ConversionPattern = %5p [%t] (%c:%F:%L) - %m%n
14
+
15
+ log4j.org.apache.zookeeper.ZooKeeper = DEBUG,C
16
+ log4j.org.apache.zookeeper.server = DEBUG,S
17
+
@@ -0,0 +1,10 @@
1
+ shared_examples_for "all success return values" do
2
+ it %[should have a return code of Zookeeper::ZOK] do
3
+ @rv[:rc].should == Zookeeper::ZOK
4
+ end
5
+
6
+ it %[should have a req_id integer] do
7
+ @rv[:req_id].should be_kind_of(Integer)
8
+ end
9
+ end
10
+
@@ -0,0 +1,1018 @@
1
+ require 'shared/all_success_return_values'
2
+
3
+ shared_examples_for "connection" do
4
+
5
+ before :each do
6
+ ensure_node(zk, path, data)
7
+ end
8
+
9
+ after :each do
10
+ ensure_node(zk, path, data)
11
+ end
12
+
13
+ after :all do
14
+ Zookeeper.logger.warn "running shared examples after :all"
15
+
16
+ with_open_zk(connection_string) do |z|
17
+ rm_rf(z, path)
18
+ end
19
+ end
20
+
21
+ # unfortunately, we can't test w/o exercising other parts of the driver, so
22
+ # if "set" is broken, this test will fail as well (but whaddyagonnado?)
23
+ describe :get do
24
+ describe :sync do
25
+ it_should_behave_like "all success return values"
26
+
27
+ before do
28
+ @rv = zk.get(:path => path)
29
+ end
30
+
31
+ it %[should return the data] do
32
+ @rv[:data].should == data
33
+ end
34
+
35
+ it %[should return a stat] do
36
+ @rv[:stat].should_not be_nil
37
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
38
+ end
39
+ end
40
+
41
+ describe :sync_watch do
42
+ it_should_behave_like "all success return values"
43
+
44
+ before do
45
+ @event = nil
46
+ @watcher = Zookeeper::WatcherCallback.new
47
+
48
+ @rv = zk.get(:path => path, :watcher => @watcher, :watcher_context => path)
49
+ end
50
+
51
+ it %[should return the data] do
52
+ @rv[:data].should == data
53
+ end
54
+
55
+ it %[should set a watcher on the node] do
56
+ # test the watcher by changing node data
57
+ zk.set(:path => path, :data => 'blah')[:rc].should be_zero
58
+
59
+ wait_until(1.0) { @watcher.completed? }
60
+
61
+ @watcher.path.should == path
62
+ @watcher.context.should == path
63
+ @watcher.should be_completed
64
+ @watcher.type.should == Zookeeper::ZOO_CHANGED_EVENT
65
+ end
66
+ end
67
+
68
+ describe :async do
69
+ before do
70
+ @cb = Zookeeper::DataCallback.new
71
+
72
+ @rv = zk.get(:path => path, :callback => @cb, :callback_context => path)
73
+ wait_until(1.0) { @cb.completed? }
74
+ @cb.should be_completed
75
+ end
76
+
77
+ it_should_behave_like "all success return values"
78
+
79
+ it %[should have a return code of ZOK] do
80
+ @cb.return_code.should == Zookeeper::ZOK
81
+ end
82
+
83
+ it %[should have the stat object in the callback] do
84
+ @cb.stat.should_not be_nil
85
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
86
+ end
87
+
88
+ it %[should have the data] do
89
+ @cb.data.should == data
90
+ end
91
+ end
92
+
93
+ describe :async_watch do
94
+ it_should_behave_like "all success return values"
95
+
96
+ before do
97
+ @cb = Zookeeper::DataCallback.new
98
+ @watcher = Zookeeper::WatcherCallback.new
99
+
100
+ @rv = zk.get(:path => path, :callback => @cb, :callback_context => path, :watcher => @watcher, :watcher_context => path)
101
+ wait_until(1.0) { @cb.completed? }
102
+ @cb.should be_completed
103
+ end
104
+
105
+ it %[should have the stat object in the callback] do
106
+ @cb.stat.should_not be_nil
107
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
108
+ end
109
+
110
+ it %[should have the data] do
111
+ @cb.data.should == data
112
+ end
113
+
114
+ it %[should have a return code of ZOK] do
115
+ @cb.return_code.should == Zookeeper::ZOK
116
+ end
117
+
118
+ it %[should set a watcher on the node] do
119
+ zk.set(:path => path, :data => 'blah')[:rc].should be_zero
120
+
121
+ wait_until(2) { @watcher.completed? }
122
+
123
+ @watcher.should be_completed
124
+
125
+ @watcher.path.should == path
126
+ @watcher.context.should == path
127
+ end
128
+ end
129
+
130
+ describe 'bad arguments' do
131
+ it %[should barf with a BadArguments error] do
132
+ lambda { zk.get(:bad_arg => 'what!?') }.should raise_error(ZookeeperExceptions::ZookeeperException::BadArguments)
133
+ end
134
+ end
135
+ end # get
136
+
137
+ describe :set do
138
+ before do
139
+ @new_data = "Four score and \007 years ago"
140
+ @stat = zk.stat(:path => path)[:stat]
141
+ end
142
+
143
+ describe :sync do
144
+ describe 'without version' do
145
+ it_should_behave_like "all success return values"
146
+
147
+ before do
148
+ @rv = zk.set(:path => path, :data => @new_data)
149
+ end
150
+
151
+ it %[should return the new stat] do
152
+ @rv[:stat].should_not be_nil
153
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
154
+ @rv[:stat].version.should > @stat.version
155
+ end
156
+ end
157
+
158
+ describe 'with current version' do
159
+ it_should_behave_like "all success return values"
160
+
161
+ before do
162
+ @rv = zk.set(:path => path, :data => @new_data, :version => @stat.version)
163
+ end
164
+
165
+ it %[should return the new stat] do
166
+ @rv[:stat].should_not be_nil
167
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
168
+ @rv[:stat].version.should > @stat.version
169
+ end
170
+ end
171
+
172
+ describe 'with outdated version' do
173
+ before do
174
+ # need to do a couple of sets to ramp up the version
175
+ 3.times { |n| @stat = zk.set(:path => path, :data => "#{@new_data}#{n}")[:stat] }
176
+
177
+ @rv = zk.set(:path => path, :data => @new_data, :version => 0)
178
+ end
179
+
180
+ it %[should have a return code of ZBADVERSION] do
181
+ @rv[:rc].should == Zookeeper::ZBADVERSION
182
+ end
183
+
184
+ it %[should return a stat with !exists] do
185
+ @rv[:stat].exists.should be_false
186
+ end
187
+ end
188
+
189
+ describe 'error' do
190
+ it %[should barf if the data size is too large], :input_size => true do
191
+ large_data = '0' * (1024 ** 2)
192
+
193
+ lambda { zk.set(:path => path, :data => large_data) }.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
194
+ end
195
+ end
196
+ end # sync
197
+
198
+ describe :async do
199
+ before do
200
+ @cb = Zookeeper::StatCallback.new
201
+ end
202
+
203
+ describe 'without version' do
204
+ it_should_behave_like "all success return values"
205
+
206
+ before do
207
+ @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path)
208
+
209
+ wait_until(2) { @cb.completed? }
210
+ @cb.should be_completed
211
+ end
212
+
213
+ it %[should have the stat in the callback] do
214
+ @cb.stat.should_not be_nil
215
+ @cb.stat.version.should > @stat.version
216
+ end
217
+
218
+ it %[should have a return code of ZOK] do
219
+ @cb.return_code.should == Zookeeper::ZOK
220
+ end
221
+ end
222
+
223
+ describe 'with current version' do
224
+ it_should_behave_like "all success return values"
225
+
226
+ before do
227
+ @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path, :version => @stat.version)
228
+
229
+ wait_until(2) { @cb.completed? }
230
+ @cb.should be_completed
231
+ end
232
+
233
+ it %[should have the stat in the callback] do
234
+ @cb.stat.should_not be_nil
235
+ @cb.stat.version.should > @stat.version
236
+ end
237
+
238
+ it %[should have a return code of ZOK] do
239
+ @cb.return_code.should == Zookeeper::ZOK
240
+ end
241
+ end
242
+
243
+ describe 'with outdated version' do
244
+ before do
245
+ # need to do a couple of sets to ramp up the version
246
+ 3.times { |n| @stat = zk.set(:path => path, :data => "#{@new_data}#{n}")[:stat] }
247
+
248
+ @rv = zk.set(:path => path, :data => @new_data, :callback => @cb, :callback_context => path, :version => 0)
249
+
250
+ wait_until(2) { @cb.completed? }
251
+ @cb.should be_completed
252
+ end
253
+
254
+ it %[should have a return code of ZBADVERSION] do
255
+ @cb.return_code.should == Zookeeper::ZBADVERSION
256
+ end
257
+
258
+ it %[should return a stat with !exists] do
259
+ @cb.stat.exists.should be_false
260
+ end
261
+ end
262
+
263
+ describe 'error' do
264
+ it %[should barf if the data size is too large], :input_size => true do
265
+ large_data = '0' * (1024 ** 2)
266
+
267
+ lambda { zk.set(:path => path, :data => large_data, :callback => @cb, :callback_context => path) }.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
268
+ end
269
+ end
270
+
271
+ end # async
272
+ end # set
273
+
274
+ describe :get_children do
275
+ before do
276
+ @children = %w[child0 child1 child2]
277
+
278
+ @children.each do |name|
279
+ zk.create(:path => "#{path}/#{name}", :data => name)
280
+ end
281
+ end
282
+
283
+ after do
284
+ @children.each do |name|
285
+ zk.delete(:path => "#{path}/#{name}")
286
+ end
287
+ end
288
+
289
+ describe :sync do
290
+ it_should_behave_like "all success return values"
291
+
292
+ before do
293
+ @rv = zk.get_children(:path => path)
294
+ end
295
+
296
+ it %[should have an array of names of the children] do
297
+ @rv[:children].should be_kind_of(Array)
298
+ @rv[:children].length.should == 3
299
+ @rv[:children].sort.should == @children.sort
300
+ end
301
+
302
+ # "Three shall be the number of the counting, and the number of the counting shall be 3"
303
+
304
+ it %[should have a stat object whose num_children is 3] do
305
+ @rv[:stat].should_not be_nil
306
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
307
+ @rv[:stat].num_children.should == 3
308
+ end
309
+ end
310
+
311
+ describe :sync_watch do
312
+ it_should_behave_like "all success return values"
313
+
314
+ before do
315
+ @addtl_child = 'child3'
316
+
317
+ @watcher = Zookeeper::WatcherCallback.new
318
+
319
+ @rv = zk.get_children(:path => path, :watcher => @watcher, :watcher_context => path)
320
+ end
321
+
322
+ after do
323
+ zk.delete(:path => "#{path}/#{@addtl_child}")
324
+ end
325
+
326
+ it %[should have an array of names of the children] do
327
+ @rv[:children].should be_kind_of(Array)
328
+ @rv[:children].length.should == 3
329
+ @rv[:children].sort.should == @children.sort
330
+ end
331
+
332
+ it %[should have a stat object whose num_children is 3] do
333
+ @rv[:stat].should_not be_nil
334
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
335
+ @rv[:stat].num_children.should == 3
336
+ end
337
+
338
+ it %[should set a watcher for children on the node] do
339
+ @watcher.should_not be_completed
340
+
341
+ zk.create(:path => "#{path}/#{@addtl_child}", :data => '')[:rc].should == Zookeeper::ZOK
342
+
343
+ wait_until { @watcher.completed? }
344
+ @watcher.should be_completed
345
+
346
+ @watcher.path.should == path
347
+ @watcher.context.should == path
348
+ @watcher.type.should == Zookeeper::ZOO_CHILD_EVENT
349
+ end
350
+ end
351
+
352
+ describe :async do
353
+ it_should_behave_like "all success return values"
354
+
355
+ before do
356
+ @cb = ZookeeperCallbacks::StringsCallback.new
357
+ @rv = zk.get_children(:path => path, :callback => @cb, :callback_context => path)
358
+
359
+ wait_until { @cb.completed? }
360
+ @cb.should be_completed
361
+ end
362
+
363
+ it %[should succeed] do
364
+ @cb.return_code.should == Zookeeper::ZOK
365
+ end
366
+
367
+ it %[should return an array of children] do
368
+ @cb.children.should be_kind_of(Array)
369
+ @cb.children.length.should == 3
370
+ @cb.children.sort.should == @children.sort
371
+ end
372
+
373
+ it %[should have a stat object whose num_children is 3] do
374
+ @cb.stat.should_not be_nil
375
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
376
+ @cb.stat.num_children.should == 3
377
+ end
378
+ end
379
+
380
+ describe :async_watch do
381
+ it_should_behave_like "all success return values"
382
+
383
+ before do
384
+ @addtl_child = 'child3'
385
+
386
+ @watcher = Zookeeper::WatcherCallback.new
387
+ @cb = ZookeeperCallbacks::StringsCallback.new
388
+
389
+ @rv = zk.get_children(:path => path, :watcher => @watcher, :watcher_context => path, :callback => @cb, :callback_context => path)
390
+ wait_until { @cb.completed? }
391
+ @cb.should be_completed
392
+ end
393
+
394
+ after do
395
+ zk.delete(:path => "#{path}/#{@addtl_child}")
396
+ end
397
+
398
+ it %[should succeed] do
399
+ @cb.return_code.should == Zookeeper::ZOK
400
+ end
401
+
402
+ it %[should return an array of children] do
403
+ @cb.children.should be_kind_of(Array)
404
+ @cb.children.length.should == 3
405
+ @cb.children.sort.should == @children.sort
406
+ end
407
+
408
+ it %[should have a stat object whose num_children is 3] do
409
+ @cb.stat.should_not be_nil
410
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
411
+ @cb.stat.num_children.should == 3
412
+ end
413
+
414
+ it %[should set a watcher for children on the node] do
415
+ @watcher.should_not be_completed
416
+
417
+ zk.create(:path => "#{path}/#{@addtl_child}", :data => '')[:rc].should == Zookeeper::ZOK
418
+
419
+ wait_until { @watcher.completed? }
420
+ @watcher.should be_completed
421
+
422
+ @watcher.path.should == path
423
+ @watcher.context.should == path
424
+ @watcher.type.should == Zookeeper::ZOO_CHILD_EVENT
425
+ end
426
+ end
427
+ end
428
+
429
+ # NOTE: the jruby version of stat on non-existent node will have a
430
+ # return_code of 0, but the C version will have a return_code of -101
431
+ describe :stat do
432
+ describe :sync do
433
+ it_should_behave_like "all success return values"
434
+
435
+ before do
436
+ @rv = zk.stat(:path => path)
437
+ end
438
+
439
+ it %[should have a stat object] do
440
+ @rv[:stat].should be_kind_of(Zookeeper::Stat)
441
+ end
442
+ end
443
+
444
+ describe :sync_watch do
445
+ it_should_behave_like "all success return values"
446
+
447
+ before do
448
+ @watcher = Zookeeper::WatcherCallback.new
449
+
450
+ @rv = zk.stat(:path => path, :watcher => @watcher, :watcher_context => path)
451
+ end
452
+
453
+ it %[should have a stat object] do
454
+ @rv[:stat].should be_kind_of(Zookeeper::Stat)
455
+ end
456
+
457
+ it %[should set a watcher for data changes on the node] do
458
+ @watcher.should_not be_completed
459
+
460
+ zk.set(:path => path, :data => 'skunk')[:rc].should == Zookeeper::ZOK
461
+
462
+ wait_until { @watcher.completed? }
463
+ @watcher.should be_completed
464
+
465
+ @watcher.path.should == path
466
+ @watcher.context.should == path
467
+ @watcher.type.should == Zookeeper::ZOO_CHANGED_EVENT
468
+ end
469
+ end
470
+
471
+ describe :async do
472
+ it_should_behave_like "all success return values"
473
+
474
+ before do
475
+ @cb = ZookeeperCallbacks::StatCallback.new
476
+ @rv = zk.stat(:path => path, :callback => @cb, :callback_context => path)
477
+
478
+ wait_until { @cb.completed? }
479
+ @cb.should be_completed
480
+ end
481
+
482
+ it %[should succeed] do
483
+ @cb.return_code.should == Zookeeper::ZOK
484
+ end
485
+
486
+ it %[should have a stat object] do
487
+ @cb.stat.should be_kind_of(Zookeeper::Stat)
488
+ end
489
+ end
490
+
491
+ describe :async_watch do
492
+ it_should_behave_like "all success return values"
493
+
494
+ before do
495
+ @addtl_child = 'child3'
496
+
497
+ @watcher = Zookeeper::WatcherCallback.new
498
+
499
+ @cb = ZookeeperCallbacks::StatCallback.new
500
+ @rv = zk.stat(:path => path, :callback => @cb, :callback_context => path, :watcher => @watcher, :watcher_context => path)
501
+
502
+ wait_until { @cb.completed? }
503
+ @cb.should be_completed
504
+ end
505
+
506
+ after do
507
+ zk.delete(:path => "#{path}/#{@addtl_child}")
508
+ end
509
+
510
+ it %[should succeed] do
511
+ @cb.return_code.should == Zookeeper::ZOK
512
+ end
513
+
514
+ it %[should have a stat object] do
515
+ @cb.stat.should be_kind_of(Zookeeper::Stat)
516
+ end
517
+
518
+ it %[should set a watcher for data changes on the node] do
519
+ @watcher.should_not be_completed
520
+
521
+ zk.set(:path => path, :data => 'skunk')[:rc].should == Zookeeper::ZOK
522
+
523
+ wait_until { @watcher.completed? }
524
+ @watcher.should be_completed
525
+
526
+ @watcher.path.should == path
527
+ @watcher.context.should == path
528
+ @watcher.type.should == Zookeeper::ZOO_CHANGED_EVENT
529
+ end
530
+ end
531
+ end # stat
532
+
533
+ describe :create do
534
+ before do
535
+ # remove the path set up by the global 'before' block
536
+ zk.delete(:path => path)
537
+ end
538
+
539
+ describe :sync do
540
+ describe 'error' do
541
+ it %[should barf if the data size is too large], :input_size => true do
542
+ large_data = '0' * (1024 ** 2)
543
+
544
+ lambda { zk.create(:path => path, :data => large_data) }.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
545
+ end
546
+ end
547
+
548
+ describe :default_flags do
549
+ it_should_behave_like "all success return values"
550
+
551
+ before do
552
+ @rv = zk.create(:path => path)
553
+ end
554
+
555
+ it %[should return the path that was set] do
556
+ @rv[:path].should == path
557
+ end
558
+
559
+ it %[should have created a permanent node] do
560
+ st = zk.stat(:path => path)
561
+ st[:rc].should == Zookeeper::ZOK
562
+
563
+ st[:stat].ephemeral_owner.should == 0
564
+ end
565
+ end
566
+
567
+ describe :ephemeral do
568
+ it_should_behave_like "all success return values"
569
+
570
+ before do
571
+ @rv = zk.create(:path => path, :ephemeral => true)
572
+ end
573
+
574
+ it %[should return the path that was set] do
575
+ @rv[:path].should == path
576
+ end
577
+
578
+ it %[should have created a ephemeral node] do
579
+ st = zk.stat(:path => path)
580
+ st[:rc].should == Zookeeper::ZOK
581
+
582
+ st[:stat].ephemeral_owner.should_not be_zero
583
+ end
584
+ end
585
+
586
+ describe :sequence do
587
+ it_should_behave_like "all success return values"
588
+
589
+ before do
590
+ @orig_path = path
591
+ @rv = zk.create(:path => path, :sequence => true)
592
+ @s_path = @rv[:path] # make sure this gets cleaned up
593
+ end
594
+
595
+ after do
596
+ zk.delete(:path => @s_path)
597
+ end
598
+
599
+ it %[should return the path that was set] do
600
+ @rv[:path].should_not == @orig_path
601
+ end
602
+
603
+ it %[should have created a permanent node] do
604
+ st = zk.stat(:path => @s_path)
605
+ st[:rc].should == Zookeeper::ZOK
606
+
607
+ st[:stat].ephemeral_owner.should be_zero
608
+ end
609
+ end
610
+
611
+ describe :ephemeral_sequence do
612
+ it_should_behave_like "all success return values"
613
+
614
+ before do
615
+ @orig_path = path
616
+ @rv = zk.create(:path => path, :sequence => true, :ephemeral => true)
617
+ @s_path = @rv[:path] # make sure this gets cleaned up
618
+ end
619
+
620
+ after do
621
+ zk.delete(:path => @s_path)
622
+ end
623
+
624
+ it %[should return the path that was set] do
625
+ @rv[:path].should_not == @orig_path
626
+ end
627
+
628
+ it %[should have created an ephemeral node] do
629
+ st = zk.stat(:path => @s_path)
630
+ st[:rc].should == Zookeeper::ZOK
631
+
632
+ st[:stat].ephemeral_owner.should_not be_zero
633
+ end
634
+ end
635
+
636
+ describe :acl do
637
+ it %[should work] do
638
+ pending "need to write acl tests"
639
+ end
640
+ end
641
+ end
642
+
643
+ describe :async do
644
+ before do
645
+ @cb = ZookeeperCallbacks::StringCallback.new
646
+ end
647
+
648
+ describe :default_flags do
649
+ it_should_behave_like "all success return values"
650
+
651
+ before do
652
+ @rv = zk.create(:path => path, :callback => @cb, :callback_context => path)
653
+ wait_until(2) { @cb.completed? }
654
+ @cb.should be_completed
655
+ end
656
+
657
+ it %[should have a path] do
658
+ @cb.path.should_not be_nil
659
+ end
660
+
661
+ it %[should return the path that was set] do
662
+ @cb.path.should == path
663
+ end
664
+
665
+ it %[should have created a permanent node] do
666
+ st = zk.stat(:path => path)
667
+ st[:rc].should == Zookeeper::ZOK
668
+
669
+ st[:stat].ephemeral_owner.should == 0
670
+ end
671
+ end
672
+
673
+ describe 'error' do
674
+ it %[should barf if the data size is too large], :input_size => true do
675
+ large_data = '0' * (1024 ** 2)
676
+
677
+ lambda do
678
+ zk.create(:path => path, :data => large_data, :callback => @cb, :callback_context => path)
679
+ end.should raise_error(ZookeeperExceptions::ZookeeperException::DataTooLargeException)
680
+ end
681
+ end
682
+
683
+
684
+ describe :ephemeral do
685
+ it_should_behave_like "all success return values"
686
+
687
+ before do
688
+ @rv = zk.create(:path => path, :ephemeral => true, :callback => @cb, :callback_context => path)
689
+ wait_until(2) { @cb.completed? }
690
+ @cb.should be_completed
691
+ end
692
+
693
+ it %[should have a path] do
694
+ @cb.path.should_not be_nil
695
+ end
696
+
697
+ it %[should return the path that was set] do
698
+ @cb.path.should == path
699
+ end
700
+
701
+ it %[should have created a ephemeral node] do
702
+ st = zk.stat(:path => path)
703
+ st[:rc].should == Zookeeper::ZOK
704
+
705
+ st[:stat].ephemeral_owner.should_not be_zero
706
+ end
707
+ end
708
+
709
+ describe :sequence do
710
+ it_should_behave_like "all success return values"
711
+
712
+ before do
713
+ @orig_path = path
714
+ @rv = zk.create(:path => path, :sequence => true, :callback => @cb, :callback_context => path)
715
+
716
+ wait_until(2) { @cb.completed? }
717
+ @cb.should be_completed
718
+
719
+ @s_path = @cb.path
720
+ end
721
+
722
+ after do
723
+ zk.delete(:path => @s_path)
724
+ end
725
+
726
+ it %[should have a path] do
727
+ @cb.path.should_not be_nil
728
+ end
729
+
730
+ it %[should return the path that was set] do
731
+ @cb.path.should_not == @orig_path
732
+ end
733
+
734
+ it %[should have created a permanent node] do
735
+ st = zk.stat(:path => @s_path)
736
+ st[:rc].should == Zookeeper::ZOK
737
+
738
+ st[:stat].ephemeral_owner.should be_zero
739
+ end
740
+ end
741
+
742
+ describe :ephemeral_sequence do
743
+ it_should_behave_like "all success return values"
744
+
745
+ before do
746
+ @orig_path = path
747
+ @rv = zk.create(:path => path, :sequence => true, :ephemeral => true, :callback => @cb, :callback_context => path)
748
+ path = @rv[:path] # make sure this gets cleaned up
749
+
750
+ wait_until(2) { @cb.completed? }
751
+ @cb.should be_completed
752
+ @s_path = @cb.path
753
+ end
754
+
755
+ after do
756
+ zk.delete(:path => @s_path)
757
+ end
758
+
759
+ it %[should have a path] do
760
+ @cb.path.should_not be_nil
761
+ end
762
+
763
+ it %[should return the path that was set] do
764
+ @s_path.should_not == @orig_path
765
+ end
766
+
767
+ it %[should have created an ephemeral node] do
768
+ st = zk.stat(:path => @s_path)
769
+ st[:rc].should == Zookeeper::ZOK
770
+
771
+ st[:stat].ephemeral_owner.should_not be_zero
772
+ end
773
+ end # ephemeral_sequence
774
+ end # async
775
+ end # create
776
+
777
+ describe :delete do
778
+ describe :sync do
779
+ describe 'without version' do
780
+ it_should_behave_like "all success return values"
781
+
782
+ before do
783
+ zk.create(:path => path)
784
+ @rv = zk.delete(:path => path)
785
+ end
786
+
787
+ it %[should have deleted the node] do
788
+ zk.stat(:path => path)[:stat].exists.should be_false
789
+ end
790
+ end
791
+
792
+ describe 'with current version' do
793
+ it_should_behave_like "all success return values"
794
+
795
+ before do
796
+ zk.create(:path => path)
797
+
798
+ @stat = zk.stat(:path => path)[:stat]
799
+ @stat.exists.should be_true
800
+
801
+ @rv = zk.delete(:path => path, :version => @stat.version)
802
+ end
803
+
804
+ it %[should have deleted the node] do
805
+ zk.stat(:path => path)[:stat].exists.should be_false
806
+ end
807
+ end
808
+
809
+ describe 'with old version' do
810
+ before do
811
+ 3.times { |n| @stat = zk.set(:path => path, :data => n.to_s)[:stat] }
812
+
813
+ @rv = zk.delete(:path => path, :version => 0)
814
+ end
815
+
816
+ it %[should have a return code of ZBADVERSION] do
817
+ @rv[:rc].should == Zookeeper::ZBADVERSION
818
+ end
819
+ end
820
+ end # sync
821
+
822
+ describe :async do
823
+ before do
824
+ @cb = ZookeeperCallbacks::VoidCallback.new
825
+ end
826
+
827
+ describe 'without version' do
828
+ it_should_behave_like "all success return values"
829
+
830
+ before do
831
+ @rv = zk.delete(:path => path, :callback => @cb, :callback_context => path)
832
+ wait_until { @cb.completed? }
833
+ @cb.should be_completed
834
+ end
835
+
836
+ it %[should have a success return_code] do
837
+ @cb.return_code.should == Zookeeper::ZOK
838
+ end
839
+
840
+ it %[should have deleted the node] do
841
+ zk.stat(:path => path)[:stat].exists.should be_false
842
+ end
843
+ end
844
+
845
+ describe 'with current version' do
846
+ it_should_behave_like "all success return values"
847
+
848
+ before do
849
+ @stat = zk.stat(:path => path)[:stat]
850
+ @rv = zk.delete(:path => path, :version => @stat.version, :callback => @cb, :callback_context => path)
851
+ wait_until { @cb.completed? }
852
+ @cb.should be_completed
853
+ end
854
+
855
+ it %[should have a success return_code] do
856
+ @cb.return_code.should == Zookeeper::ZOK
857
+ end
858
+
859
+ it %[should have deleted the node] do
860
+ zk.stat(:path => path)[:stat].exists.should be_false
861
+ end
862
+ end
863
+
864
+ describe 'with old version' do
865
+ before do
866
+ 3.times { |n| @stat = zk.set(:path => path, :data => n.to_s)[:stat] }
867
+
868
+ @rv = zk.delete(:path => path, :version => 0, :callback => @cb, :callback_context => path)
869
+ wait_until { @cb.completed? }
870
+ @cb.should be_completed
871
+ end
872
+
873
+ it %[should have a return code of ZBADVERSION] do
874
+ @cb.return_code.should == Zookeeper::ZBADVERSION
875
+ end
876
+ end
877
+ end # async
878
+ end # delete
879
+
880
+ describe :get_acl do
881
+ describe :sync do
882
+ it_should_behave_like "all success return values"
883
+
884
+ before do
885
+ @rv = zk.get_acl(:path => path)
886
+ end
887
+
888
+ it %[should return a stat for the path] do
889
+ @rv[:stat].should be_kind_of(ZookeeperStat::Stat)
890
+ end
891
+
892
+ it %[should return the acls] do
893
+ acls = @rv[:acl]
894
+ acls.should be_kind_of(Array)
895
+ h = acls.first
896
+
897
+ h.should be_kind_of(Hash)
898
+
899
+ h[:perms].should == Zookeeper::ZOO_PERM_ALL
900
+ h[:id][:scheme].should == 'world'
901
+ h[:id][:id].should == 'anyone'
902
+ end
903
+ end
904
+
905
+ describe :async do
906
+ it_should_behave_like "all success return values"
907
+
908
+ before do
909
+ @cb = Zookeeper::ACLCallback.new
910
+ @rv = zk.get_acl(:path => path, :callback => @cb, :callback_context => path)
911
+
912
+ wait_until(2) { @cb.completed? }
913
+ @cb.should be_completed
914
+ end
915
+
916
+ it %[should return a stat for the path] do
917
+ @cb.stat.should be_kind_of(ZookeeperStat::Stat)
918
+ end
919
+
920
+ it %[should return the acls] do
921
+ acls = @cb.acl
922
+ acls.should be_kind_of(Array)
923
+
924
+ acl = acls.first
925
+ acl.should be_kind_of(ZookeeperACLs::ACL)
926
+
927
+ acl.perms.should == Zookeeper::ZOO_PERM_ALL
928
+
929
+ acl.id.scheme.should == 'world'
930
+ acl.id.id.should == 'anyone'
931
+ end
932
+ end
933
+ end
934
+
935
+ describe :set_acl do
936
+ before do
937
+ @perms = 5
938
+ @new_acl = [ZookeeperACLs::ACL.new(:perms => @perms, :id => ZookeeperACLs::ZOO_ANYONE_ID_UNSAFE)]
939
+ pending("No idea how to set ACLs")
940
+ end
941
+
942
+ describe :sync do
943
+ it_should_behave_like "all success return values"
944
+
945
+ before do
946
+ @rv = zk.set_acl(:path => path, :acl => @new_acl)
947
+ end
948
+ end
949
+ end
950
+
951
+ describe :session_id do
952
+ it %[should return the session_id as a Fixnum] do
953
+ zk.session_id.should be_kind_of(Fixnum)
954
+ end
955
+ end
956
+
957
+ describe :session_passwd do
958
+ it %[should return the session passwd as a String] do
959
+ zk.session_passwd.should be_kind_of(String)
960
+ end
961
+ end
962
+
963
+ describe :sync do
964
+ describe :success do
965
+ it_should_behave_like "all success return values"
966
+
967
+ before do
968
+ @cb = Zookeeper::StringCallback.new
969
+ @rv = zk.sync(:path => path, :callback => @cb)
970
+
971
+ wait_until(2) { @cb.completed }
972
+ @cb.should be_completed
973
+ end
974
+ end
975
+
976
+ describe :errors do
977
+ it %[should barf with BadArguments if :callback is not given] do
978
+ lambda { zk.sync(:path => path) }.should raise_error(ZookeeperExceptions::ZookeeperException::BadArguments)
979
+ end
980
+ end
981
+ end
982
+
983
+ describe :event_dispatch_thread? do
984
+ it %[should return true when called on the event dispatching thread] do
985
+ @result = nil
986
+
987
+ cb = lambda do |hash|
988
+ @result = zk.event_dispatch_thread?
989
+ end
990
+
991
+ @rv = zk.sync(:path => path, :callback => cb)
992
+
993
+ wait_until(2) { @result == true }.should be_true
994
+ end
995
+
996
+ it %[should return false when not on the event dispatching thread] do
997
+ zk.event_dispatch_thread?.should_not be_true
998
+ end
999
+ end
1000
+
1001
+ describe :close do
1002
+ describe 'from the event dispatch thread' do
1003
+ it %[should not deadlock] do
1004
+
1005
+ evil_cb = lambda do |*|
1006
+ logger.debug { "calling close event_dispatch_thread? #{zk.event_dispatch_thread?}" }
1007
+ zk.close
1008
+ end
1009
+
1010
+ zk.stat(:path => path, :callback => evil_cb)
1011
+
1012
+ wait_until { zk.closed? }
1013
+ zk.should be_closed
1014
+ end
1015
+ end
1016
+ end
1017
+ end
1018
+