zookeeper-ng 1.5

Sign up to get free protection for your applications and to get access to all the features.
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
+