zookeeper-ng 1.5

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.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.ctags_paths +1 -0
  3. data/.dotfiles/ruby-gemset +1 -0
  4. data/.dotfiles/ruby-version +1 -0
  5. data/.dotfiles/rvmrc +2 -0
  6. data/.gitignore +19 -0
  7. data/.gitmodules +3 -0
  8. data/.travis.yml +25 -0
  9. data/CHANGELOG +395 -0
  10. data/Gemfile +30 -0
  11. data/Guardfile +8 -0
  12. data/LICENSE +23 -0
  13. data/Manifest +29 -0
  14. data/README.markdown +85 -0
  15. data/Rakefile +121 -0
  16. data/cause-abort.rb +117 -0
  17. data/ext/.gitignore +6 -0
  18. data/ext/Rakefile +41 -0
  19. data/ext/c_zookeeper.rb +398 -0
  20. data/ext/common.h +17 -0
  21. data/ext/dbg.h +53 -0
  22. data/ext/depend +5 -0
  23. data/ext/event_lib.c +740 -0
  24. data/ext/event_lib.h +175 -0
  25. data/ext/extconf.rb +103 -0
  26. data/ext/generate_gvl_code.rb +321 -0
  27. data/ext/patches/zkc-3.3.5-network.patch +24 -0
  28. data/ext/patches/zkc-3.4.5-fetch-and-add.patch +16 -0
  29. data/ext/patches/zkc-3.4.5-logging.patch +41 -0
  30. data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
  31. data/ext/patches/zkc-3.4.5-overflow.patch +11 -0
  32. data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
  33. data/ext/zkc-3.4.5.tar.gz +0 -0
  34. data/ext/zkrb.c +1075 -0
  35. data/ext/zkrb_wrapper.c +775 -0
  36. data/ext/zkrb_wrapper.h +350 -0
  37. data/ext/zkrb_wrapper_compat.c +15 -0
  38. data/ext/zkrb_wrapper_compat.h +11 -0
  39. data/ext/zookeeper_base.rb +256 -0
  40. data/java/java_base.rb +503 -0
  41. data/lib/zookeeper.rb +115 -0
  42. data/lib/zookeeper/acls.rb +44 -0
  43. data/lib/zookeeper/callbacks.rb +108 -0
  44. data/lib/zookeeper/client.rb +30 -0
  45. data/lib/zookeeper/client_methods.rb +282 -0
  46. data/lib/zookeeper/common.rb +122 -0
  47. data/lib/zookeeper/common/queue_with_pipe.rb +110 -0
  48. data/lib/zookeeper/compatibility.rb +138 -0
  49. data/lib/zookeeper/constants.rb +97 -0
  50. data/lib/zookeeper/continuation.rb +223 -0
  51. data/lib/zookeeper/core_ext.rb +58 -0
  52. data/lib/zookeeper/em_client.rb +55 -0
  53. data/lib/zookeeper/exceptions.rb +135 -0
  54. data/lib/zookeeper/forked.rb +19 -0
  55. data/lib/zookeeper/latch.rb +34 -0
  56. data/lib/zookeeper/logger.rb +39 -0
  57. data/lib/zookeeper/logger/forwarding_logger.rb +84 -0
  58. data/lib/zookeeper/monitor.rb +19 -0
  59. data/lib/zookeeper/rake_tasks.rb +165 -0
  60. data/lib/zookeeper/request_registry.rb +153 -0
  61. data/lib/zookeeper/stat.rb +21 -0
  62. data/lib/zookeeper/version.rb +4 -0
  63. data/notes.txt +14 -0
  64. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  65. data/spec/c_zookeeper_spec.rb +51 -0
  66. data/spec/chrooted_connection_spec.rb +83 -0
  67. data/spec/compatibilty_spec.rb +8 -0
  68. data/spec/default_watcher_spec.rb +41 -0
  69. data/spec/em_spec.rb +51 -0
  70. data/spec/ext/zookeeper_base_spec.rb +19 -0
  71. data/spec/forked_connection_spec.rb +124 -0
  72. data/spec/latch_spec.rb +24 -0
  73. data/spec/log4j.properties +17 -0
  74. data/spec/shared/all_success_return_values.rb +10 -0
  75. data/spec/shared/connection_examples.rb +1077 -0
  76. data/spec/spec_helper.rb +61 -0
  77. data/spec/support/00_logging.rb +38 -0
  78. data/spec/support/10_spawn_zookeeper.rb +24 -0
  79. data/spec/support/progress_formatter.rb +15 -0
  80. data/spec/support/zookeeper_spec_helpers.rb +96 -0
  81. data/spec/zookeeper_spec.rb +24 -0
  82. data/zookeeper.gemspec +38 -0
  83. data/zoomonkey/duplicates +3 -0
  84. data/zoomonkey/zoomonkey.rb +194 -0
  85. metadata +157 -0
data/java/java_base.rb ADDED
@@ -0,0 +1,503 @@
1
+ require 'java'
2
+ require 'thread'
3
+
4
+ # require 'rubygems'
5
+ # gem 'slyphon-log4j', '= 1.2.15'
6
+ # gem 'zk-ruby-zookeeper_jar', "= #{Zookeeper::DRIVER_VERSION}"
7
+
8
+ require 'log4j'
9
+ require 'zookeeper_jar'
10
+
11
+
12
+ # XXX: reindent this WHOLE FILE later
13
+ module Zookeeper
14
+
15
+ # The low-level wrapper-specific methods for the Java lib,
16
+ # subclassed by the top-level Zookeeper class
17
+ class JavaBase
18
+ include Java
19
+ include Common
20
+ include Constants
21
+ include Callbacks
22
+ include Exceptions
23
+ include ACLs
24
+ include Logger
25
+
26
+ JZK = org.apache.zookeeper
27
+ JZKD = org.apache.zookeeper.data
28
+ Code = JZK::KeeperException::Code
29
+
30
+ ANY_VERSION = -1
31
+ DEFAULT_SESSION_TIMEOUT = 10_000
32
+
33
+ JZKD::Stat.class_eval do
34
+ MEMBERS = [:version, :czxid, :mzxid, :ctime, :mtime, :cversion, :aversion, :ephemeralOwner, :dataLength, :numChildren, :pzxid]
35
+ def to_hash
36
+ MEMBERS.inject({}) { |h,k| h[k] = __send__(k); h }
37
+ end
38
+ end
39
+
40
+ JZKD::Id.class_eval do
41
+ def to_hash
42
+ { :scheme => getScheme, :id => getId }
43
+ end
44
+ end
45
+
46
+ JZKD::ACL.class_eval do
47
+ def self.from_ruby_acl(acl)
48
+ raise TypeError, "acl must be a Zookeeper::ACLs::ACL not #{acl.inspect}" unless acl.kind_of?(Zookeeper::ACLs::ACL)
49
+ id = org.apache.zookeeper.data.Id.new(acl.id.scheme.to_s, acl.id.id.to_s)
50
+ new(acl.perms.to_i, id)
51
+ end
52
+
53
+ def to_hash
54
+ { :perms => getPerms, :id => getId.to_hash }
55
+ end
56
+ end
57
+
58
+ JZK::WatchedEvent.class_eval do
59
+ def to_hash
60
+ { :type => getType.getIntValue, :state => getState.getIntValue, :path => getPath }
61
+ end
62
+ end
63
+
64
+ # used for internal dispatching
65
+ # @private
66
+ module JavaCB
67
+ class Callback
68
+ include Logger
69
+
70
+ attr_reader :req_id
71
+
72
+ def initialize(req_id)
73
+ @req_id = req_id
74
+ end
75
+ end
76
+
77
+ class DataCallback < Callback
78
+ include JZK::AsyncCallback::DataCallback
79
+
80
+ def processResult(rc, path, queue, data, stat)
81
+ logger.debug { "#{self.class.name}#processResult rc: #{rc}, req_id: #{req_id}, path: #{path}, queue: #{queue.inspect}, data: #{data.inspect}, stat: #{stat.inspect}" }
82
+
83
+ hash = {
84
+ :rc => rc,
85
+ :req_id => req_id,
86
+ :path => path,
87
+ :data => (data && String.from_java_bytes(data)),
88
+ :stat => (stat && stat.to_hash),
89
+ }
90
+
91
+ # if rc == Zookeeper::ZOK
92
+ # hash.merge!({
93
+ # :data => String.from_java_bytes(data),
94
+ # :stat => stat.to_hash,
95
+ # })
96
+ # end
97
+
98
+ queue.push(hash)
99
+ end
100
+ end
101
+
102
+ class StringCallback < Callback
103
+ include JZK::AsyncCallback::StringCallback
104
+
105
+ def processResult(rc, path, queue, str)
106
+ logger.debug { "#{self.class.name}#processResult rc: #{rc}, req_id: #{req_id}, path: #{path}, queue: #{queue.inspect}, str: #{str.inspect}" }
107
+ queue.push(:rc => rc, :req_id => req_id, :path => path, :string => str)
108
+ end
109
+ end
110
+
111
+ class StatCallback < Callback
112
+ include JZK::AsyncCallback::StatCallback
113
+
114
+ def processResult(rc, path, queue, stat)
115
+ logger.debug { "#{self.class.name}#processResult rc: #{rc.inspect}, req_id: #{req_id}, path: #{path.inspect}, queue: #{queue.inspect}, stat: #{stat.inspect}" }
116
+ queue.push(:rc => rc, :req_id => req_id, :stat => (stat and stat.to_hash), :path => path)
117
+ end
118
+ end
119
+
120
+ class Children2Callback < Callback
121
+ include JZK::AsyncCallback::Children2Callback
122
+
123
+ def processResult(rc, path, queue, children, stat)
124
+ logger.debug { "#{self.class.name}#processResult rc: #{rc}, req_id: #{req_id}, path: #{path}, queue: #{queue.inspect}, children: #{children.inspect}, stat: #{stat.inspect}" }
125
+ hash = {
126
+ :rc => rc,
127
+ :req_id => req_id,
128
+ :path => path,
129
+ :strings => (children && children.to_a),
130
+ :stat => (stat and stat.to_hash),
131
+ }
132
+
133
+ queue.push(hash)
134
+ end
135
+ end
136
+
137
+ class ACLCallback < Callback
138
+ include JZK::AsyncCallback::ACLCallback
139
+
140
+ def processResult(rc, path, queue, acl, stat)
141
+ logger.debug { "ACLCallback#processResult rc: #{rc.inspect}, req_id: #{req_id}, path: #{path.inspect}, queue: #{queue.inspect}, acl: #{acl.inspect}, stat: #{stat.inspect}" }
142
+ a = Array(acl).map { |a| a.to_hash }
143
+ queue.push(:rc => rc, :req_id => req_id, :path => path, :acl => a, :stat => (stat && stat.to_hash))
144
+ end
145
+ end
146
+
147
+ class VoidCallback < Callback
148
+ include JZK::AsyncCallback::VoidCallback
149
+
150
+ def processResult(rc, path, queue)
151
+ logger.debug { "#{self.class.name}#processResult rc: #{rc}, req_id: #{req_id}, queue: #{queue.inspect}" }
152
+ queue.push(:rc => rc, :req_id => req_id, :path => path)
153
+ end
154
+ end
155
+
156
+ class WatcherCallback < Callback
157
+ include JZK::Watcher
158
+ include Zookeeper::Constants
159
+
160
+ attr_reader :client
161
+
162
+ def initialize(event_queue, opts={})
163
+ @event_queue = event_queue
164
+ @client = opts[:client]
165
+ super(ZKRB_GLOBAL_CB_REQ)
166
+ end
167
+
168
+ def process(event)
169
+ hash = event.to_hash
170
+ logger.debug { "WatcherCallback got event: #{hash.inspect}" }
171
+
172
+ if client && (hash[:type] == ZOO_SESSION_EVENT) && (hash[:state] == ZOO_CONNECTED_STATE)
173
+ logger.debug { "#{self.class}##{__method__} notifying client of connected state!" }
174
+ client.notify_connected!
175
+ end
176
+
177
+ hash = event.to_hash.merge(:req_id => req_id)
178
+ @event_queue.push(hash)
179
+ end
180
+ end
181
+ end
182
+
183
+ attr_reader :event_queue
184
+
185
+ def reopen(timeout=10, watcher=nil, opts = {})
186
+ # watcher ||= @default_watcher
187
+
188
+ @mutex.synchronize do
189
+ @req_registry.clear_watchers!
190
+
191
+ replace_jzk!(opts)
192
+ wait_until_connected
193
+ end
194
+
195
+ state
196
+ end
197
+
198
+ def wait_until_connected(timeout=10)
199
+ @connected_latch.await(timeout) unless connected?
200
+ connected?
201
+ end
202
+
203
+ def initialize(host, timeout=10, watcher=nil, options={})
204
+ @host = host
205
+ @event_queue = QueueWithPipe.new
206
+
207
+ watcher ||= get_default_global_watcher()
208
+
209
+ @req_registry = RequestRegistry.new(watcher)
210
+
211
+ @mutex = Monitor.new
212
+ @dispatch_shutdown_cond = @mutex.new_cond
213
+ @connected_latch = Latch.new
214
+
215
+ @_running = nil
216
+ @_closed = false
217
+ @options = {}
218
+
219
+
220
+ # allows connected-state handlers to be registered before
221
+ yield self if block_given?
222
+
223
+ reopen(timeout, nil, options)
224
+ return nil unless connected?
225
+ @_running = true
226
+ setup_dispatch_thread!
227
+ end
228
+
229
+ def close
230
+ shutdown_thread = Thread.new do
231
+ @mutex.synchronize do
232
+ unless @_closed
233
+ @_closed = true # these are probably unnecessary
234
+ @_running = false
235
+
236
+ stop_dispatch_thread!
237
+ @jzk.close if @jzk
238
+ end
239
+ end
240
+ end
241
+
242
+ shutdown_thread.join unless event_dispatch_thread?
243
+ end
244
+
245
+ def state
246
+ @mutex.synchronize { @jzk.state }
247
+ end
248
+
249
+ def connected?
250
+ state == JZK::ZooKeeper::States::CONNECTED
251
+ end
252
+
253
+ def connecting?
254
+ state == JZK::ZooKeeper::States::CONNECTING
255
+ end
256
+
257
+ def associating?
258
+ state == JZK::ZooKeeper::States::ASSOCIATING
259
+ end
260
+
261
+ def running?
262
+ @_running
263
+ end
264
+
265
+ def closed?
266
+ @_closed
267
+ end
268
+
269
+ def self.set_debug_level(*a)
270
+ # IGNORED IN JRUBY
271
+ end
272
+
273
+ def set_debug_level(*a)
274
+ # IGNORED IN JRUBY
275
+ end
276
+
277
+ def get(req_id, path, callback, watcher)
278
+ handle_keeper_exception do
279
+ watch_cb = watcher ? create_watcher(req_id, path) : false
280
+
281
+ if callback
282
+ jzk.getData(path, watch_cb, JavaCB::DataCallback.new(req_id), event_queue)
283
+ [Code::Ok, nil, nil] # the 'nil, nil' isn't strictly necessary here
284
+ else # sync
285
+ stat = JZKD::Stat.new
286
+
287
+ value = jzk.getData(path, watch_cb, stat)
288
+ data = String.from_java_bytes(value) unless value.nil?
289
+ [Code::Ok, data, stat.to_hash]
290
+ end
291
+ end
292
+ end
293
+
294
+ def set(req_id, path, data, callback, version)
295
+ handle_keeper_exception do
296
+ version ||= ANY_VERSION
297
+
298
+ if callback
299
+ jzk.setData(path, data.to_java_bytes, version, JavaCB::StatCallback.new(req_id), event_queue)
300
+ [Code::Ok, nil]
301
+ else
302
+ stat = jzk.setData(path, data.to_java_bytes, version).to_hash
303
+ [Code::Ok, stat]
304
+ end
305
+ end
306
+ end
307
+
308
+ def get_children(req_id, path, callback, watcher)
309
+ handle_keeper_exception do
310
+ watch_cb = watcher ? create_watcher(req_id, path) : false
311
+
312
+ if callback
313
+ jzk.getChildren(path, watch_cb, JavaCB::Children2Callback.new(req_id), event_queue)
314
+ [Code::Ok, nil, nil]
315
+ else
316
+ stat = JZKD::Stat.new
317
+ children = jzk.getChildren(path, watch_cb, stat)
318
+ [Code::Ok, children.to_a, stat.to_hash]
319
+ end
320
+ end
321
+ end
322
+
323
+ def add_auth(req_id, scheme, cert)
324
+ handle_keeper_exception do
325
+ jzk.addAuthInfo(scheme, cert.to_java_bytes)
326
+ Code::Ok
327
+ end
328
+ end
329
+
330
+ def create(req_id, path, data, callback, acl, flags)
331
+ handle_keeper_exception do
332
+ acl = Array(acl).map{ |a| JZKD::ACL.from_ruby_acl(a) }
333
+ mode = JZK::CreateMode.fromFlag(flags)
334
+
335
+ data ||= ''
336
+
337
+ if callback
338
+ jzk.create(path, data.to_java_bytes, acl, mode, JavaCB::StringCallback.new(req_id), event_queue)
339
+ [Code::Ok, nil]
340
+ else
341
+ new_path = jzk.create(path, data.to_java_bytes, acl, mode)
342
+ [Code::Ok, new_path]
343
+ end
344
+ end
345
+ end
346
+
347
+ def sync(req_id, path)
348
+ handle_keeper_exception do
349
+ jzk.sync(path, JavaCB::VoidCallback.new(req_id), event_queue)
350
+ Code::Ok
351
+ end
352
+ end
353
+
354
+ def delete(req_id, path, version, callback)
355
+ handle_keeper_exception do
356
+ if callback
357
+ jzk.delete(path, version, JavaCB::VoidCallback.new(req_id), event_queue)
358
+ else
359
+ jzk.delete(path, version)
360
+ end
361
+
362
+ Code::Ok
363
+ end
364
+ end
365
+
366
+ def set_acl(req_id, path, acl, callback, version)
367
+ handle_keeper_exception do
368
+ logger.debug { "set_acl: acl #{acl.inspect}" }
369
+ acl = Array(acl).flatten.map { |a| JZKD::ACL.from_ruby_acl(a) }
370
+ logger.debug { "set_acl: converted #{acl.inspect}" }
371
+
372
+ if callback
373
+ jzk.setACL(path, acl, version, JavaCB::ACLCallback.new(req_id), event_queue)
374
+ else
375
+ jzk.setACL(path, acl, version)
376
+ end
377
+
378
+ Code::Ok
379
+ end
380
+ end
381
+
382
+ def exists(req_id, path, callback, watcher)
383
+ handle_keeper_exception do
384
+ watch_cb = watcher ? create_watcher(req_id, path) : false
385
+
386
+ if callback
387
+ jzk.exists(path, watch_cb, JavaCB::StatCallback.new(req_id), event_queue)
388
+ [Code::Ok, nil, nil]
389
+ else
390
+ stat = jzk.exists(path, watch_cb)
391
+ [Code::Ok, (stat and stat.to_hash)]
392
+ end
393
+ end
394
+ end
395
+
396
+ def get_acl(req_id, path, callback)
397
+ handle_keeper_exception do
398
+ stat = JZKD::Stat.new
399
+
400
+ if callback
401
+ logger.debug { "calling getACL, path: #{path.inspect}, stat: #{stat.inspect}" }
402
+ jzk.getACL(path, stat, JavaCB::ACLCallback.new(req_id), event_queue)
403
+ [Code::Ok, nil, nil]
404
+ else
405
+ acls = jzk.getACL(path, stat).map { |a| a.to_hash }
406
+
407
+ [Code::Ok, Array(acls).map{|m| m.to_hash}, stat.to_hash]
408
+ end
409
+ end
410
+ end
411
+
412
+ def assert_open
413
+ # XXX don't know how to check for valid session state!
414
+ raise NotConnected unless connected?
415
+ end
416
+
417
+ def session_id
418
+ jzk.session_id
419
+ end
420
+
421
+ def session_passwd
422
+ jzk.session_passwd.to_s
423
+ end
424
+
425
+ # called from watcher when we are connected
426
+ # @private
427
+ def notify_connected!
428
+ @connected_latch.release
429
+ end
430
+
431
+ def pause_before_fork_in_parent
432
+ # this is a no-op in java-land
433
+ end
434
+
435
+ def resume_after_fork_in_parent
436
+ # this is a no-op in java-land
437
+ end
438
+
439
+ private
440
+ def jzk
441
+ @mutex.synchronize { @jzk }
442
+ end
443
+
444
+ # java exceptions are not wrapped anymore in JRuby 1.7+
445
+ if JRUBY_VERSION >= '1.7.0'
446
+ def handle_keeper_exception
447
+ yield
448
+ rescue JZK::KeeperException => e
449
+ # code is an enum and always set -> we don't need any additional checks here
450
+ e.code.intValue
451
+ end
452
+ else
453
+ def handle_keeper_exception
454
+ yield
455
+ rescue JZK::KeeperException => e
456
+ if e.respond_to?(:cause) and e.cause and e.cause.respond_to?(:code) and e.cause.code and e.cause.code.respond_to?(:intValue)
457
+ e.cause.code.intValue
458
+ else
459
+ raise e # dunno what happened, just raise it
460
+ end
461
+ end
462
+ end
463
+
464
+ def call_type(callback, watcher)
465
+ if callback
466
+ watcher ? :async_watch : :async
467
+ else
468
+ watcher ? :sync_watch : :sync
469
+ end
470
+ end
471
+
472
+ def create_watcher(req_id, path)
473
+ logger.debug { "creating watcher for req_id: #{req_id} path: #{path}" }
474
+ lambda do |event|
475
+ ev_type, ev_state = event.type.int_value, event.state.int_value
476
+
477
+ logger.debug { "watcher for req_id #{req_id}, path: #{path} called back" }
478
+
479
+ h = { :req_id => req_id, :type => ev_type, :state => ev_state, :path => path }
480
+ event_queue.push(h)
481
+ end
482
+ end
483
+
484
+ def get_default_global_watcher
485
+ Proc.new { |args|
486
+ logger.debug { "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}" }
487
+ true
488
+ }
489
+ end
490
+
491
+ def replace_jzk!(opts = {})
492
+ orig_jzk = @jzk
493
+ if opts.has_key?(:session_id) && opts.has_key(:session_passwd)
494
+ @jzk = JZK::ZooKeeper.new(@host, DEFAULT_SESSION_TIMEOUT, JavaCB::WatcherCallback.new(event_queue, :client => self), opts.fetch(:session_id), opts.fetch(:session_passwd).to_java_bytes)
495
+ else
496
+ @jzk = JZK::ZooKeeper.new(@host, DEFAULT_SESSION_TIMEOUT, JavaCB::WatcherCallback.new(event_queue, :client => self))
497
+ end
498
+ ensure
499
+ orig_jzk.close if orig_jzk
500
+ end
501
+ end
502
+ end
503
+