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/lib/zookeeper.rb ADDED
@@ -0,0 +1,115 @@
1
+ # Ruby wrapper for the Zookeeper C API
2
+
3
+ require 'thread'
4
+ require 'monitor'
5
+ require 'forwardable'
6
+ require 'logger'
7
+ require 'benchmark'
8
+
9
+ module Zookeeper
10
+ ZOOKEEPER_ROOT = File.expand_path('../..', __FILE__)
11
+
12
+ # require a path relative to the lib directory
13
+ # this is to avoid monkeying explicitly with $LOAD_PATH
14
+ #
15
+ # @private
16
+ def self.require_lib(*relpaths)
17
+ relpaths.each do |relpath|
18
+ require File.join(ZOOKEEPER_ROOT, 'lib', relpath)
19
+ end
20
+ end
21
+
22
+ # require a path that's relative to ZOOKEEPER_ROOT
23
+ # @private
24
+ def self.require_root(*relpaths)
25
+ relpaths.each do |relpath|
26
+ require File.join(ZOOKEEPER_ROOT, relpath)
27
+ end
28
+ end
29
+ end
30
+
31
+ Zookeeper.require_lib(
32
+ 'zookeeper/core_ext',
33
+ 'zookeeper/monitor',
34
+ 'zookeeper/logger',
35
+ 'zookeeper/logger/forwarding_logger',
36
+ 'zookeeper/forked',
37
+ 'zookeeper/latch',
38
+ 'zookeeper/acls',
39
+ 'zookeeper/constants',
40
+ 'zookeeper/exceptions',
41
+ 'zookeeper/continuation',
42
+ 'zookeeper/common',
43
+ 'zookeeper/request_registry',
44
+ 'zookeeper/callbacks',
45
+ 'zookeeper/stat',
46
+ 'zookeeper/client_methods'
47
+ )
48
+
49
+ # ok, now we construct the client
50
+ Zookeeper.require_lib 'zookeeper/client'
51
+
52
+ module Zookeeper
53
+ include Constants
54
+ #::Logger.new($stderr).tap { |l| l.level = ENV['ZOOKEEPER_DEBUG'] ? ::Logger::DEBUG : ::Logger::ERROR }
55
+ #
56
+
57
+ @@logger = nil unless defined?(@@logger)
58
+
59
+ def self.logger
60
+ @@logger
61
+ end
62
+
63
+ def self.logger=(logger)
64
+ @@logger = logger
65
+ end
66
+
67
+ # @private
68
+ def self.deprecation_warnings?
69
+ @deprecation_warnings = true if @deprecation_warnings.nil?
70
+ end
71
+
72
+ # set this to false to mute Zookeeper related deprecation warnings...
73
+ # __AT YOUR PERIL__
74
+ def self.deprecation_warnings=(v)
75
+ @deprecation_warnings = v
76
+ end
77
+
78
+ # @private
79
+ def self.deprecation_warning(warning)
80
+ Kernel.warn(warning) if deprecation_warnings?
81
+ end
82
+
83
+ # for expert use only. set the underlying debug level for the C layer, has no
84
+ # effect in java
85
+ #
86
+ # @private
87
+ def self.set_debug_level(val)
88
+ if defined?(CZookeeper)
89
+ CZookeeper.set_debug_level(val.to_i)
90
+ end
91
+ end
92
+
93
+ # @private
94
+ def self.get_debug_level
95
+ if defined?(CZookeeper)
96
+ CZookeeper.get_debug_level
97
+ end
98
+ end
99
+
100
+ class << self
101
+ # @private
102
+ alias :debug_level= :set_debug_level
103
+
104
+ # @private
105
+ alias :debug_level :get_debug_level
106
+ end
107
+ end
108
+
109
+ # just for first test, get rid of this soon
110
+ Zookeeper.require_lib 'zookeeper/compatibility'
111
+
112
+ if ENV['ZKRB_DEBUG']
113
+ Zookeeper.debug_level = Zookeeper::Constants::ZOO_LOG_LEVEL_DEBUG
114
+ end
115
+
@@ -0,0 +1,44 @@
1
+ module Zookeeper
2
+ module ACLs
3
+ class Id
4
+ attr_reader :scheme, :id
5
+ def initialize(hash)
6
+ @scheme = hash[:scheme]
7
+ @id = hash[:id]
8
+ end
9
+
10
+ def to_hash
11
+ { :id => id, :scheme => scheme }
12
+ end
13
+ end
14
+
15
+ class ACL
16
+ attr_reader :perms, :id
17
+ def initialize(hash)
18
+ @perms = hash[:perms]
19
+ v = hash[:id]
20
+ @id = v.kind_of?(Hash) ? Id.new(v) : v
21
+ end
22
+
23
+ def to_hash
24
+ { :perms => perms, :id => id.to_hash }
25
+ end
26
+ end
27
+
28
+ module Constants
29
+ ZOO_PERM_READ = 1 << 0
30
+ ZOO_PERM_WRITE = 1 << 1
31
+ ZOO_PERM_CREATE = 1 << 2
32
+ ZOO_PERM_DELETE = 1 << 3
33
+ ZOO_PERM_ADMIN = 1 << 4
34
+ ZOO_PERM_ALL = ZOO_PERM_READ | ZOO_PERM_WRITE | ZOO_PERM_CREATE | ZOO_PERM_DELETE | ZOO_PERM_ADMIN
35
+
36
+ ZOO_ANYONE_ID_UNSAFE = Id.new(:scheme => "world", :id => "anyone")
37
+ ZOO_AUTH_IDS = Id.new(:scheme => "auth", :id => "")
38
+
39
+ ZOO_OPEN_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_ANYONE_ID_UNSAFE)]
40
+ ZOO_READ_ACL_UNSAFE = [ACL.new(:perms => ZOO_PERM_READ, :id => ZOO_ANYONE_ID_UNSAFE)]
41
+ ZOO_CREATOR_ALL_ACL = [ACL.new(:perms => ZOO_PERM_ALL, :id => ZOO_AUTH_IDS)]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,108 @@
1
+ module Zookeeper
2
+ module Callbacks
3
+ class Base
4
+ attr_reader :proc, :completed, :context
5
+
6
+ # allows for easier construction of a user callback block that will be
7
+ # called with the callback object itself as an argument.
8
+ #
9
+ # @example
10
+ #
11
+ # Base.create do |cb|
12
+ # puts "watcher callback called with argument: #{cb.inspect}"
13
+ # end
14
+ #
15
+ # "watcher callback called with argument: #<Zookeeper::Callbacks::Base:0x1018a3958 @state=3, @type=1, ...>"
16
+ #
17
+ #
18
+ def self.create
19
+ cb_inst = new { yield cb_inst }
20
+ end
21
+
22
+ def initialize
23
+ @completed = false
24
+ @proc = Proc.new do |hash|
25
+ initialize_context(hash)
26
+ yield if block_given?
27
+ @completed = true
28
+ end
29
+ end
30
+
31
+ def call(*args)
32
+ @proc.call(*args)
33
+ end
34
+
35
+ def completed?
36
+ @completed
37
+ end
38
+
39
+ def initialize_context(hash)
40
+ @context = nil
41
+ end
42
+ end
43
+
44
+ class WatcherCallback < Base
45
+ ## wexists, awexists, wget, awget, wget_children, awget_children
46
+ attr_reader :type, :state, :path
47
+
48
+ def initialize_context(hash)
49
+ @type, @state, @path, @context = hash[:type], hash[:state], hash[:path], hash[:context]
50
+ end
51
+ end
52
+
53
+ class DataCallback < Base
54
+ ## aget, awget
55
+ attr_reader :return_code, :data, :stat
56
+
57
+ def initialize_context(hash)
58
+ @return_code, @data, @stat, @context = hash[:rc], hash[:data], hash[:stat], hash[:context]
59
+ end
60
+ end
61
+
62
+ class StringCallback < Base
63
+ ## acreate, async
64
+ attr_reader :return_code, :string, :context
65
+
66
+ alias path string
67
+
68
+ def initialize_context(hash)
69
+ @return_code, @string, @context = hash[:rc], hash[:string], hash[:context]
70
+ end
71
+ end
72
+
73
+ class StringsCallback < Base
74
+ ## aget_children, awget_children
75
+ attr_reader :return_code, :children, :stat
76
+
77
+ def initialize_context(hash)
78
+ @return_code, @children, @stat, @context = hash[:rc], hash[:strings], hash[:stat], hash[:context]
79
+ end
80
+ end
81
+
82
+ class StatCallback < Base
83
+ ## aset, aexists, awexists
84
+ attr_reader :return_code, :stat
85
+
86
+ def initialize_context(hash)
87
+ @return_code, @stat, @context = hash[:rc], hash[:stat], hash[:context]
88
+ end
89
+ end
90
+
91
+ class VoidCallback < Base
92
+ ## adelete, aset_acl, add_auth
93
+ attr_reader :return_code
94
+
95
+ def initialize_context(hash)
96
+ @return_code, @context = hash[:rc], hash[:context]
97
+ end
98
+ end
99
+
100
+ class ACLCallback < Base
101
+ ## aget_acl
102
+ attr_reader :return_code, :acl, :stat
103
+ def initialize_context(hash)
104
+ @return_code, @acl, @stat, @context = hash[:rc], hash[:acl], hash[:stat], hash[:context]
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,30 @@
1
+ # figure out what platform we're on
2
+ # this way there's no ambiguity about which file to include
3
+ # or which class we're subclassing.
4
+
5
+ if defined?(::JRUBY_VERSION)
6
+ Zookeeper.require_root('java/java_base')
7
+ else
8
+ Zookeeper.require_root('ext/zookeeper_base')
9
+ end
10
+
11
+
12
+ module Zookeeper
13
+ if defined?(::JRUBY_VERSION)
14
+ class Client < Zookeeper::JavaBase
15
+ end
16
+ else
17
+ class Client < Zookeeper::ZookeeperBase
18
+ end
19
+ end
20
+
21
+ def self.new(*a, &b)
22
+ Zookeeper::Client.new(*a, &b)
23
+ end
24
+ end
25
+
26
+
27
+ Zookeeper::Client.class_eval do
28
+ include Zookeeper::ClientMethods
29
+ end
30
+
@@ -0,0 +1,282 @@
1
+ module Zookeeper
2
+ module ClientMethods
3
+ extend Forwardable
4
+ include Constants
5
+ include ACLs
6
+ include Logger
7
+
8
+ # @req_registry is set up in the platform-specific base classes
9
+ def_delegators :@req_registry, :setup_call
10
+ private :setup_call
11
+
12
+ def reopen(timeout=10, watcher=nil, opts = {})
13
+ warn "WARN: ZookeeperBase#reopen watcher argument is now ignored" if watcher
14
+ super
15
+ end
16
+
17
+ def initialize(host, timeout=10, watcher=nil, opts = {})
18
+ super
19
+ end
20
+
21
+ def add_auth(options = {})
22
+ assert_open
23
+ assert_keys(options,
24
+ :supported => [:scheme, :cert],
25
+ :required => [:scheme, :cert])
26
+
27
+ req_id = setup_call(:add_auth, options)
28
+ rc = super(req_id, options[:scheme], options[:cert])
29
+
30
+ { :req_id => req_id, :rc => rc }
31
+ end
32
+
33
+ def get(options = {})
34
+ assert_open
35
+ assert_keys(options,
36
+ :supported => [:path, :watcher, :watcher_context, :callback, :callback_context],
37
+ :required => [:path])
38
+
39
+ req_id = setup_call(:get, options)
40
+ rc, value, stat = super(req_id, options[:path], options[:callback], options[:watcher])
41
+
42
+ rv = { :req_id => req_id, :rc => rc }
43
+ options[:callback] ? rv : rv.merge(:data => value, :stat => Stat.new(stat))
44
+ end
45
+
46
+ def set(options = {})
47
+ assert_open
48
+ assert_keys(options,
49
+ :supported => [:path, :data, :version, :callback, :callback_context],
50
+ :required => [:path])
51
+
52
+ assert_valid_data_size!(options[:data])
53
+ options[:version] ||= -1
54
+
55
+ req_id = setup_call(:set, options)
56
+ rc, stat = super(req_id, options[:path], options[:data], options[:callback], options[:version])
57
+
58
+ rv = { :req_id => req_id, :rc => rc }
59
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
60
+ end
61
+
62
+ def get_children(options = {})
63
+ assert_open
64
+ assert_keys(options,
65
+ :supported => [:path, :callback, :callback_context, :watcher, :watcher_context],
66
+ :required => [:path])
67
+
68
+ req_id = setup_call(:get_children, options)
69
+ rc, children, stat = super(req_id, options[:path], options[:callback], options[:watcher])
70
+
71
+ rv = { :req_id => req_id, :rc => rc }
72
+ options[:callback] ? rv : rv.merge(:children => children, :stat => Stat.new(stat))
73
+ end
74
+
75
+ def stat(options = {})
76
+ assert_open
77
+ assert_keys(options,
78
+ :supported => [:path, :callback, :callback_context, :watcher, :watcher_context],
79
+ :required => [:path])
80
+
81
+ req_id = setup_call(:stat, options)
82
+ rc, stat = exists(req_id, options[:path], options[:callback], options[:watcher])
83
+
84
+ rv = { :req_id => req_id, :rc => rc }
85
+ options[:callback] ? rv : rv.merge(:stat => Stat.new(stat))
86
+ end
87
+
88
+ def create(options = {})
89
+ assert_open
90
+ assert_keys(options,
91
+ :supported => [:path, :data, :acl, :ephemeral, :sequence, :callback, :callback_context],
92
+ :required => [:path])
93
+
94
+ assert_valid_data_size!(options[:data])
95
+
96
+ flags = 0
97
+ flags |= ZOO_EPHEMERAL if options[:ephemeral]
98
+ flags |= ZOO_SEQUENCE if options[:sequence]
99
+
100
+ options[:acl] ||= ZOO_OPEN_ACL_UNSAFE
101
+
102
+ req_id = setup_call(:create, options)
103
+ rc, newpath = super(req_id, options[:path], options[:data], options[:callback], options[:acl], flags)
104
+
105
+ rv = { :req_id => req_id, :rc => rc }
106
+ options[:callback] ? rv : rv.merge(:path => newpath)
107
+ end
108
+
109
+ def delete(options = {})
110
+ assert_open
111
+ assert_keys(options,
112
+ :supported => [:path, :version, :callback, :callback_context],
113
+ :required => [:path])
114
+
115
+ options[:version] ||= -1
116
+
117
+ req_id = setup_call(:delete, options)
118
+ rc = super(req_id, options[:path], options[:version], options[:callback])
119
+
120
+ { :req_id => req_id, :rc => rc }
121
+ end
122
+
123
+ # this method is *only* asynchronous
124
+ #
125
+ # @note There is a discrepancy between the zkc and java versions. zkc takes
126
+ # a string_callback_t, java takes a VoidCallback. You should most likely use
127
+ # the Zookeeper::Callbacks::VoidCallback and not rely on the string value.
128
+ #
129
+ def sync(options = {})
130
+ assert_open
131
+ assert_keys(options,
132
+ :supported => [:path, :callback, :callback_context],
133
+ :required => [:path, :callback])
134
+
135
+ req_id = setup_call(:sync, options)
136
+
137
+ rc = super(req_id, options[:path]) # we don't pass options[:callback] here as this method is *always* async
138
+
139
+ { :req_id => req_id, :rc => rc }
140
+ end
141
+
142
+ def set_acl(options = {})
143
+ assert_open
144
+ assert_keys(options,
145
+ :supported => [:path, :acl, :version, :callback, :callback_context],
146
+ :required => [:path, :acl])
147
+ options[:version] ||= -1
148
+
149
+ req_id = setup_call(:set_acl, options)
150
+ rc = super(req_id, options[:path], options[:acl], options[:callback], options[:version])
151
+
152
+ { :req_id => req_id, :rc => rc }
153
+ end
154
+
155
+ def get_acl(options = {})
156
+ assert_open
157
+ assert_keys(options,
158
+ :supported => [:path, :callback, :callback_context],
159
+ :required => [:path])
160
+
161
+ req_id = setup_call(:get_acl, options)
162
+ rc, acls, stat = super(req_id, options[:path], options[:callback])
163
+
164
+ rv = { :req_id => req_id, :rc => rc }
165
+ options[:callback] ? rv : rv.merge(:acl => acls, :stat => Stat.new(stat))
166
+ end
167
+
168
+ # close this client and any underlying connections
169
+ def close
170
+ super
171
+ end
172
+
173
+ def state
174
+ super
175
+ end
176
+
177
+ def connected?
178
+ super
179
+ end
180
+
181
+ def connecting?
182
+ super
183
+ end
184
+
185
+ def associating?
186
+ super
187
+ end
188
+
189
+ # There are some operations that are dangerous in the context of the event
190
+ # dispatch thread (because they would block further event delivery). This
191
+ # method allows clients to know if they're currently executing in the context of an
192
+ # event.
193
+ #
194
+ # @returns [true,false] true if the current thread is the event dispatch thread
195
+ def event_dispatch_thread?
196
+ super
197
+ end
198
+
199
+ # DEPRECATED: use the class-level method instead
200
+ def set_debug_level(val)
201
+ super
202
+ end
203
+
204
+ # has the underlying connection been closed?
205
+ def closed?
206
+ super
207
+ end
208
+
209
+ # is the event delivery system running?
210
+ def running?
211
+ super
212
+ end
213
+
214
+ # return the session id of the current connection as an Fixnum
215
+ def session_id
216
+ super
217
+ end
218
+
219
+ # Return the passwd portion of this connection's credentials as a String
220
+ def session_passwd
221
+ super
222
+ end
223
+
224
+ # stop all underlying threads in preparation for a fork()
225
+ def pause_before_fork_in_parent
226
+ super
227
+ end
228
+
229
+ # re-start all underlying threads after performing a fork()
230
+ def resume_after_fork_in_parent
231
+ super
232
+ end
233
+
234
+ protected
235
+ # used during shutdown, awaken the event delivery thread if it's blocked
236
+ # waiting for the next event
237
+ def wake_event_loop!
238
+ super
239
+ end
240
+
241
+ # starts the event delivery subsystem going. after calling this method, running? will be true
242
+ def setup_dispatch_thread!
243
+ super
244
+ end
245
+
246
+ # TODO: describe what this does
247
+ def get_default_global_watcher
248
+ super
249
+ end
250
+
251
+ def assert_valid_data_size!(data)
252
+ return if data.nil?
253
+
254
+ data = data.to_s
255
+ if data.length >= 1048576 # one megabyte
256
+ raise Zookeeper::Exceptions::DataTooLargeException, "data must be smaller than 1 MiB, your data starts with: #{data[0..32].inspect}"
257
+ end
258
+ nil
259
+ end
260
+
261
+ private
262
+ def assert_keys(args, opts={})
263
+ supported = opts[:supported] || []
264
+ required = opts[:required] || []
265
+
266
+ unless (args.keys - supported).empty?
267
+ raise Zookeeper::Exceptions::BadArguments,
268
+ "Supported arguments are: #{supported.inspect}, but arguments #{args.keys.inspect} were supplied instead"
269
+ end
270
+
271
+ unless (required - args.keys).empty?
272
+ raise Zookeeper::Exceptions::BadArguments,
273
+ "Required arguments are: #{required.inspect}, but only the arguments #{args.keys.inspect} were supplied."
274
+ end
275
+ end
276
+
277
+ # must be supplied by parent class impl.
278
+ def assert_open
279
+ super
280
+ end
281
+ end # ClientMethods
282
+ end # Zookeeper