zookeeper-ng 1.5.2.1-java

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 (86) 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/.github/workflows/build.yml +57 -0
  7. data/.gitignore +19 -0
  8. data/.gitmodules +3 -0
  9. data/CHANGELOG +408 -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 +62 -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-buffer-overflow.patch +11 -0
  29. data/ext/patches/zkc-3.4.5-config.patch +5454 -0
  30. data/ext/patches/zkc-3.4.5-fetch-and-add.patch +16 -0
  31. data/ext/patches/zkc-3.4.5-logging.patch +41 -0
  32. data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
  33. data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
  34. data/ext/zkc-3.4.5.tar.gz +0 -0
  35. data/ext/zkrb.c +1080 -0
  36. data/ext/zkrb_wrapper.c +775 -0
  37. data/ext/zkrb_wrapper.h +350 -0
  38. data/ext/zkrb_wrapper_compat.c +15 -0
  39. data/ext/zkrb_wrapper_compat.h +11 -0
  40. data/ext/zookeeper_base.rb +256 -0
  41. data/java/java_base.rb +501 -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/queue_with_pipe.rb +110 -0
  47. data/lib/zookeeper/common.rb +122 -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/forwarding_logger.rb +84 -0
  57. data/lib/zookeeper/logger.rb +39 -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/lib/zookeeper.rb +115 -0
  64. data/notes.txt +14 -0
  65. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  66. data/spec/c_zookeeper_spec.rb +51 -0
  67. data/spec/chrooted_connection_spec.rb +83 -0
  68. data/spec/compatibilty_spec.rb +8 -0
  69. data/spec/default_watcher_spec.rb +41 -0
  70. data/spec/em_spec.rb +51 -0
  71. data/spec/ext/zookeeper_base_spec.rb +19 -0
  72. data/spec/forked_connection_spec.rb +122 -0
  73. data/spec/latch_spec.rb +24 -0
  74. data/spec/log4j.properties +17 -0
  75. data/spec/shared/all_success_return_values.rb +10 -0
  76. data/spec/shared/connection_examples.rb +1081 -0
  77. data/spec/spec_helper.rb +61 -0
  78. data/spec/support/00_logging.rb +38 -0
  79. data/spec/support/10_spawn_zookeeper.rb +20 -0
  80. data/spec/support/progress_formatter.rb +15 -0
  81. data/spec/support/zookeeper_spec_helpers.rb +96 -0
  82. data/spec/zookeeper_spec.rb +24 -0
  83. data/zookeeper.gemspec +46 -0
  84. data/zoomonkey/duplicates +3 -0
  85. data/zoomonkey/zoomonkey.rb +194 -0
  86. metadata +185 -0
@@ -0,0 +1,97 @@
1
+ module Zookeeper
2
+ module Constants
3
+ include ACLs::Constants
4
+
5
+ # file type masks
6
+ ZOO_EPHEMERAL = 1
7
+ ZOO_SEQUENCE = 2
8
+
9
+ # session state
10
+ ZOO_EXPIRED_SESSION_STATE = -112
11
+ ZOO_AUTH_FAILED_STATE = -113
12
+ ZOO_CLOSED_STATE = 0
13
+ ZOO_CONNECTING_STATE = 1
14
+ ZOO_ASSOCIATING_STATE = 2
15
+ ZOO_CONNECTED_STATE = 3
16
+
17
+ # watch types
18
+ ZOO_CREATED_EVENT = 1
19
+ ZOO_DELETED_EVENT = 2
20
+ ZOO_CHANGED_EVENT = 3
21
+ ZOO_CHILD_EVENT = 4
22
+ ZOO_SESSION_EVENT = -1
23
+ ZOO_NOTWATCHING_EVENT = -2
24
+
25
+ # only used by the C extension
26
+ ZOO_LOG_LEVEL_ERROR = 1
27
+ ZOO_LOG_LEVEL_WARN = 2
28
+ ZOO_LOG_LEVEL_INFO = 3
29
+ ZOO_LOG_LEVEL_DEBUG = 4
30
+
31
+ # exceptions/errors
32
+ ZOK = 0
33
+ ZSYSTEMERROR = -1
34
+ ZRUNTIMEINCONSISTENCY = -2
35
+ ZDATAINCONSISTENCY = -3
36
+ ZCONNECTIONLOSS = -4
37
+ ZMARSHALLINGERROR = -5
38
+ ZUNIMPLEMENTED = -6
39
+ ZOPERATIONTIMEOUT = -7
40
+ ZBADARGUMENTS = -8
41
+ ZINVALIDSTATE = -9
42
+
43
+ # api errors
44
+ ZAPIERROR = -100
45
+ ZNONODE = -101
46
+ ZNOAUTH = -102
47
+ ZBADVERSION = -103
48
+ ZNOCHILDRENFOREPHEMERALS = -108
49
+ ZNODEEXISTS = -110
50
+ ZNOTEMPTY = -111
51
+ ZSESSIONEXPIRED = -112
52
+ ZINVALIDCALLBACK = -113
53
+ ZINVALIDACL = -114
54
+ ZAUTHFAILED = -115
55
+ ZCLOSING = -116
56
+ ZNOTHING = -117
57
+ ZSESSIONMOVED = -118
58
+
59
+ ZKRB_GLOBAL_CB_REQ = -1
60
+ ZKRB_ASYNC_CONTN_ID = -2
61
+
62
+ # @private
63
+ CONNECTED_EVENT_VALUES = [Constants::ZKRB_GLOBAL_CB_REQ,
64
+ Constants::ZOO_SESSION_EVENT,
65
+ Constants::ZOO_CONNECTED_STATE].freeze
66
+
67
+ # used to find the name for a numeric event
68
+ # @private
69
+ EVENT_TYPE_NAMES = {
70
+ 1 => 'created',
71
+ 2 => 'deleted',
72
+ 3 => 'changed',
73
+ 4 => 'child',
74
+ -1 => 'session',
75
+ -2 => 'notwatching',
76
+ }
77
+
78
+ # used to pretty print the state name
79
+ # @private
80
+ STATE_NAMES = {
81
+ -112 => 'expired_session',
82
+ -113 => 'auth_failed',
83
+ 0 => 'closed',
84
+ 1 => 'connecting',
85
+ 2 => 'associating',
86
+ 3 => 'connected',
87
+ }
88
+
89
+ def event_by_value(v)
90
+ (name = EVENT_TYPE_NAMES[v]) ? "ZOO_#{name.upcase}_EVENT" : ''
91
+ end
92
+
93
+ def state_by_value(v)
94
+ (name = STATE_NAMES[v]) ? "ZOO_#{name.upcase}_STATE" : ''
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,223 @@
1
+ module Zookeeper
2
+ # @private
3
+ # sigh, slightly different than the userland callbacks, the continuation
4
+ # provides sync call semantics around an async api
5
+ class Continuation
6
+ include Constants
7
+ include Logger
8
+
9
+ OPERATION_TIMEOUT = 30 # seconds
10
+
11
+ # for keeping track of which continuations are pending, and which ones have
12
+ # been submitted and are awaiting a repsonse
13
+ #
14
+ # `state_check` are high-priority checks that query the connection about
15
+ # its current state, they always run before other continuations
16
+ #
17
+ class Registry < Struct.new(:pending, :state_check, :in_flight)
18
+ extend Forwardable
19
+
20
+ def_delegators :@mutex, :lock, :unlock
21
+
22
+ def initialize
23
+ super([], [], {})
24
+ @mutex = Mutex.new
25
+ end
26
+
27
+ def synchronize
28
+ @mutex.lock
29
+ begin
30
+ yield self
31
+ ensure
32
+ @mutex.unlock rescue nil
33
+ end
34
+ end
35
+
36
+ # does not lock the mutex, returns true if there are pending jobs
37
+ def anything_to_do?
38
+ (pending.length + state_check.length) > 0
39
+ end
40
+
41
+ # returns the pending continuations, resetting the list
42
+ # this method is synchronized
43
+ def next_batch()
44
+ @mutex.lock
45
+ begin
46
+ state_check.slice!(0, state_check.length) + pending.slice!(0,pending.length)
47
+ ensure
48
+ @mutex.unlock rescue nil
49
+ end
50
+ end
51
+ end # Registry
52
+
53
+ # *sigh* what is the index in the *args array of the 'callback' param
54
+ CALLBACK_ARG_IDX = {
55
+ :get => 2,
56
+ :set => 3,
57
+ :exists => 2,
58
+ :create => 3,
59
+ :delete => 3,
60
+ :get_acl => 2,
61
+ :set_acl => 3,
62
+ :get_children => 2,
63
+ :state => 0,
64
+ :add_auth => 2
65
+ }
66
+
67
+ # maps the method name to the async return hash keys it should use to
68
+ # deliver the results
69
+ METH_TO_ASYNC_RESULT_KEYS = {
70
+ :get => [:rc, :data, :stat],
71
+ :set => [:rc, :stat],
72
+ :exists => [:rc, :stat],
73
+ :create => [:rc, :string],
74
+ :delete => [:rc],
75
+ :get_acl => [:rc, :acl, :stat],
76
+ :set_acl => [:rc],
77
+ :get_children => [:rc, :strings, :stat],
78
+ :add_auth => [:rc]
79
+ }
80
+
81
+ attr_accessor :meth, :block, :rval
82
+
83
+ attr_reader :args
84
+
85
+ def initialize(meth, *args)
86
+ @meth = meth
87
+ @args = args.freeze
88
+ @mutex = Monitor.new
89
+ @cond = @mutex.new_cond
90
+ @rval = nil
91
+
92
+ # make this error reporting more robust if necessary, right now, just set to state
93
+ @error = nil
94
+ end
95
+
96
+ # the caller calls this method and receives the response from the async loop
97
+ # this method has a hard-coded 30 second timeout as a safety feature. No
98
+ # call should take more than 20s (as the session timeout is set to 20s)
99
+ # so if any call takes longer than that, something has gone horribly wrong.
100
+ #
101
+ # @raise [ContinuationTimeoutError] if a response is not received within 30s
102
+ #
103
+ def value
104
+ time_to_stop = Time.now + OPERATION_TIMEOUT
105
+ now = nil
106
+
107
+ @mutex.synchronize do
108
+ while true
109
+ now = Time.now
110
+ break if @rval or @error or (now > time_to_stop)
111
+
112
+ deadline = time_to_stop.to_f - now.to_f
113
+ @cond.wait(deadline)
114
+ end
115
+
116
+ if (now > time_to_stop) and !@rval and !@error
117
+ raise Exceptions::ContinuationTimeoutError, "response for meth: #{meth.inspect}, args: #{@args.inspect}, not received within #{OPERATION_TIMEOUT} seconds"
118
+ end
119
+
120
+ case @error
121
+ when nil
122
+ # ok, nothing to see here, carry on
123
+ when :shutdown
124
+ raise Exceptions::NotConnected, "the connection is shutting down"
125
+ when ZOO_EXPIRED_SESSION_STATE
126
+ raise Exceptions::SessionExpired, "connection has expired"
127
+ else
128
+ raise Exceptions::NotConnected, "connection state is #{STATE_NAMES[@error]}"
129
+ end
130
+
131
+ case @rval.length
132
+ when 1
133
+ return @rval.first
134
+ else
135
+ return @rval
136
+ end
137
+ end
138
+ end
139
+
140
+ # receive the response from the server, set @rval, notify caller
141
+ def call(hash)
142
+ logger.debug { "continuation req_id #{req_id}, got hash: #{hash.inspect}" }
143
+ @rval = hash.values_at(*METH_TO_ASYNC_RESULT_KEYS.fetch(meth))
144
+ logger.debug { "delivering result #{@rval.inspect}" }
145
+ deliver!
146
+ end
147
+
148
+ def user_callback?
149
+ !!@args.at(callback_arg_idx)
150
+ end
151
+
152
+ # this method is called by the event thread to submit the request
153
+ # passed the CZookeeper instance, makes the async call and deals with the results
154
+ #
155
+ # BTW: in case you were wondering this is a completely stupid
156
+ # implementation, but it's more important to get *something* working and
157
+ # passing specs, then refactor to make everything sane
158
+ #
159
+ #
160
+ def submit(czk)
161
+ state = czk.zkrb_state # check the state of the connection
162
+
163
+ if @meth == :state # if the method is a state call
164
+ @rval = [state] # we're done, no error
165
+ return deliver!
166
+
167
+ elsif state != ZOO_CONNECTED_STATE # otherwise, we must be connected
168
+ @error = state # so set the error
169
+ return deliver! # and we're out
170
+ end
171
+
172
+ rc, *_ = czk.__send__(:"zkrb_#{@meth}", *async_args)
173
+
174
+ if user_callback? or (rc != ZOK) # async call, or we failed to submit it
175
+ @rval = [rc] # create the repsonse
176
+ deliver! # wake the caller and we're out
177
+ end
178
+ end
179
+
180
+ def req_id
181
+ @args.first
182
+ end
183
+
184
+ def state_call?
185
+ @meth == :state
186
+ end
187
+
188
+ # interrupt the sleeping thread with a NotConnected error
189
+ def shutdown!
190
+ @mutex.synchronize do
191
+ return if @rval or @error
192
+ @error = :shutdown
193
+ @cond.broadcast
194
+ end
195
+ end
196
+
197
+ protected
198
+
199
+ # an args array with the only difference being that if there's a user
200
+ # callback provided, we don't handle delivering the end result
201
+ def async_args
202
+ return [] if @meth == :state # special-case :P
203
+ ary = @args.dup
204
+
205
+ logger.debug { "async_args, meth: #{meth} ary: #{ary.inspect}, #{callback_arg_idx}" }
206
+
207
+ ary[callback_arg_idx] ||= self
208
+
209
+ ary
210
+ end
211
+
212
+ def callback_arg_idx
213
+ CALLBACK_ARG_IDX.fetch(meth) { raise ArgumentError, "unknown method #{meth.inspect}" }
214
+ end
215
+
216
+ def deliver!
217
+ @mutex.synchronize do
218
+ @cond.signal
219
+ end
220
+ end
221
+ end # Base
222
+ end
223
+
@@ -0,0 +1,58 @@
1
+ # @private
2
+ module ::Kernel
3
+ unless method_defined?(:silence_warnings)
4
+ def silence_warnings
5
+ with_warnings(nil) { yield }
6
+ end
7
+ end
8
+
9
+ unless method_defined?(:with_warnings)
10
+ def with_warnings(flag)
11
+ old_verbose, $VERBOSE = $VERBOSE, flag
12
+ yield
13
+ ensure
14
+ $VERBOSE = old_verbose
15
+ end
16
+ end
17
+ end
18
+
19
+ # @private
20
+ class ::Exception
21
+ unless method_defined?(:to_std_format)
22
+ def to_std_format
23
+ ary = ["#{self.class}: #{message}"]
24
+ ary.concat(backtrace || [])
25
+ ary.join("\n\t")
26
+ end
27
+ end
28
+ end
29
+
30
+ # this is borrowed from the excellent Logging gem: https://github.com/TwP/logging
31
+ # @private
32
+ class ::Module
33
+ # @private
34
+ # Returns a predictable logger name for the current module or class. If
35
+ # used within an anonymous class, the first non-anonymous class name will
36
+ # be used as the logger name. If used within a meta-class, the name of the
37
+ # actual class will be used as the logger name. If used within an
38
+ # anonymous module, the string 'anonymous' will be returned.
39
+ def _zk_logger_name
40
+ return name unless name.nil? or name.empty?
41
+
42
+ # check if this is a metaclass (or eigenclass)
43
+ if ancestors.include? Class
44
+ inspect =~ %r/#<Class:([^#>]+)>/
45
+ return $1
46
+ end
47
+
48
+ # see if we have a superclass
49
+ if respond_to? :superclass
50
+ return superclass.logger_name
51
+ end
52
+
53
+ # we are an anonymous module
54
+ return 'anonymous'
55
+ end
56
+ end
57
+
58
+
@@ -0,0 +1,55 @@
1
+ require 'zookeeper'
2
+ require 'eventmachine'
3
+
4
+ module ZookeeperEM
5
+ class Client < Zookeeper::Client
6
+ # @private
7
+ # the EM Connection instance we receive once we call EM.watch on our selectable_io
8
+ attr_reader :em_connection
9
+
10
+ def initialize(*a, &b)
11
+ @on_close = EM::DefaultDeferrable.new
12
+ @on_attached = EM::DefaultDeferrable.new
13
+ @em_connection = nil
14
+ logger.debug { "ZookeeperEM::Client obj_id %x: init" % [object_id] }
15
+ super(*a, &b)
16
+ on_attached.succeed
17
+ end
18
+
19
+ # EM::DefaultDeferrable that will be called back when our em_connection has been detached
20
+ # and we've completed the close operation
21
+ def on_close(&block)
22
+ @on_close.callback(&block) if block
23
+ @on_close
24
+ end
25
+
26
+ # called after we've successfully registered our selectable_io to be
27
+ # managed by the EM reactor
28
+ def on_attached(&block)
29
+ @on_attached.callback(&block) if block
30
+ @on_attached
31
+ end
32
+
33
+ def dispatch_next_callback(hash)
34
+ EM.schedule do
35
+ if running? and not closed?
36
+ logger.debug { "#{self.class}##{__method__} dispatch_next_callback: #{hash.inspect}: reactor_thread? #{EM.reactor_thread?}, running? #{running?}, closed? #{closed?}" }
37
+ super(hash)
38
+ end
39
+ end
40
+ end
41
+
42
+ def close(&block)
43
+ on_close(&block)
44
+ super()
45
+ on_close.succeed
46
+ end
47
+
48
+ # Because eventmachine is single-threaded, and events are dispatched on the
49
+ # reactor thread we just delegate this to EM.reactor_thread?
50
+ def event_dispatch_thread?
51
+ EM.reactor_thread?
52
+ end
53
+ end # Client
54
+ end # ZookeeperEM
55
+
@@ -0,0 +1,135 @@
1
+ module Zookeeper
2
+ module Exceptions
3
+ include Constants
4
+
5
+ class ZookeeperException < StandardError
6
+
7
+ unless defined?(CONST_MISSING_WARNING)
8
+
9
+ CONST_MISSING_WARNING = <<-EOS
10
+
11
+ ------------------------------------------------------------------------------------------
12
+ WARNING! THE ZOOKEEPER NAMESPACE HAS CHANGED AS OF 1.0!
13
+
14
+ Please update your code to use the new hierarchy!
15
+
16
+ The constant that got you this was ZookeeperExceptions::ZookeeperException::%s
17
+
18
+ stacktrace:
19
+ %s
20
+
21
+ ------------------------------------------------------------------------------------------
22
+
23
+ EOS
24
+ end
25
+
26
+ # NOTE(slyphon): Since 0.4 all of the ZookeeperException subclasses were
27
+ # defined inside of ZookeeperException, which always seemed well, icky.
28
+ # if someone references one of these we'll print out a warning and
29
+ # then give them the constant
30
+ #
31
+ def self.const_missing(const)
32
+ if Zookeeper::Exceptions.const_defined?(const)
33
+
34
+ stacktrace = caller[0..-2].reject {|n| n =~ %r%/rspec/% }.map { |n| "\t#{n}" }.join("\n")
35
+
36
+ Zookeeper.deprecation_warning(CONST_MISSING_WARNING % [const.to_s, stacktrace])
37
+
38
+
39
+ Zookeeper::Exceptions.const_get(const).tap do |const_val|
40
+ self.const_set(const, const_val)
41
+ end
42
+ else
43
+ super
44
+ end
45
+ end
46
+ end
47
+
48
+
49
+ class EverythingOk < ZookeeperException; end
50
+ class SystemError < ZookeeperException; end
51
+ class RunTimeInconsistency < ZookeeperException; end
52
+ class DataInconsistency < ZookeeperException; end
53
+ class ConnectionLoss < ZookeeperException; end
54
+ class MarshallingError < ZookeeperException; end
55
+ class Unimplemented < ZookeeperException; end
56
+ class OperationTimeOut < ZookeeperException; end
57
+ class BadArguments < ZookeeperException; end
58
+ class InvalidState < ZookeeperException; end
59
+ class ApiError < ZookeeperException; end
60
+ class NoNode < ZookeeperException; end
61
+ class NoAuth < ZookeeperException; end
62
+ class BadVersion < ZookeeperException; end
63
+ class NoChildrenForEphemerals < ZookeeperException; end
64
+ class NodeExists < ZookeeperException; end
65
+ class NotEmpty < ZookeeperException; end
66
+ class SessionExpired < ZookeeperException; end
67
+ class InvalidCallback < ZookeeperException; end
68
+ class InvalidACL < ZookeeperException; end
69
+ class AuthFailed < ZookeeperException; end
70
+ class Closing < ZookeeperException; end
71
+ class Nothing < ZookeeperException; end
72
+ class SessionMoved < ZookeeperException; end
73
+
74
+ # these are Ruby client exceptions
75
+ class ConnectionClosed < ZookeeperException; end
76
+ class NotConnected < ZookeeperException; end
77
+ class ShuttingDownException < ZookeeperException; end
78
+ class DataTooLargeException < ZookeeperException; end
79
+
80
+ # raised when an operation is performed on an instance without a valid
81
+ # zookeeper handle. (C version)
82
+ class HandleClosedException < ZookeeperException; end
83
+
84
+ # maybe use this for continuation
85
+ class InterruptedException < ZookeeperException ; end
86
+
87
+ # raised when a continuation operation takes more time than is reasonable and
88
+ # the thread should be awoken. (i.e. prevents a call that never returns)
89
+ class ContinuationTimeoutError < ZookeeperException; end
90
+
91
+ # raised when the user tries to use a connection after a fork()
92
+ # without calling reopen() in the C client
93
+ #
94
+ # (h/t: @pletern http://git.io/zIsq1Q)
95
+ class InheritedConnectionError < ZookeeperException; end
96
+
97
+ # yes, make an alias, this is the way zookeeper refers to it
98
+ ExpiredSession = SessionExpired unless defined?(ExpiredSession)
99
+
100
+ def self.by_code(code)
101
+ case code
102
+ when ZOK then EverythingOk
103
+ when ZSYSTEMERROR then SystemError
104
+ when ZRUNTIMEINCONSISTENCY then RunTimeInconsistency
105
+ when ZDATAINCONSISTENCY then DataInconsistency
106
+ when ZCONNECTIONLOSS then ConnectionLoss
107
+ when ZMARSHALLINGERROR then MarshallingError
108
+ when ZUNIMPLEMENTED then Unimplemented
109
+ when ZOPERATIONTIMEOUT then OperationTimeOut
110
+ when ZBADARGUMENTS then BadArguments
111
+ when ZINVALIDSTATE then InvalidState
112
+ when ZAPIERROR then ApiError
113
+ when ZNONODE then NoNode
114
+ when ZNOAUTH then NoAuth
115
+ when ZBADVERSION then BadVersion
116
+ when ZNOCHILDRENFOREPHEMERALS then NoChildrenForEphemerals
117
+ when ZNODEEXISTS then NodeExists
118
+ when ZNOTEMPTY then NotEmpty
119
+ when ZSESSIONEXPIRED then SessionExpired
120
+ when ZINVALIDCALLBACK then InvalidCallback
121
+ when ZINVALIDACL then InvalidACL
122
+ when ZAUTHFAILED then AuthFailed
123
+ when ZCLOSING then Closing
124
+ when ZNOTHING then Nothing
125
+ when ZSESSIONMOVED then SessionMoved
126
+ else ZookeeperException.new("no exception defined for code #{code}")
127
+ end
128
+ end
129
+
130
+ def self.raise_on_error(code)
131
+ exc = self.by_code(code)
132
+ raise exc unless exc == EverythingOk
133
+ end
134
+ end # Exceptions
135
+ end # Zookeeper
@@ -0,0 +1,19 @@
1
+ module Zookeeper
2
+ module Forked
3
+ # the includer provides an 'original_pid' method, which is set
4
+ # when the original 'owning' process creates the object.
5
+ #
6
+ # @return [true] if the current PID differs from the original_pid value
7
+ # @return [false] if the current PID matches the original_pid value
8
+ #
9
+ def forked?
10
+ Process.pid != original_pid
11
+ end
12
+
13
+ # sets the `original_pid` to the current value
14
+ def update_pid!
15
+ self.original_pid = Process.pid
16
+ end
17
+ end # Forked
18
+ end # Zookeeper
19
+
@@ -0,0 +1,34 @@
1
+ module Zookeeper
2
+ # a cross-thread gate of sorts.
3
+ class Latch
4
+ def initialize(count = 1)
5
+ @count = count
6
+ @mutex = Monitor.new
7
+ @cond = @mutex.new_cond
8
+ end
9
+
10
+ def release
11
+ @mutex.synchronize {
12
+ @count -= 1 if @count > 0
13
+ @cond.broadcast if @count.zero?
14
+ }
15
+ end
16
+
17
+ def await(timeout=nil)
18
+ @mutex.synchronize do
19
+ if timeout
20
+ time_to_stop = Time.now + timeout
21
+
22
+ while @count > 0
23
+ @cond.wait(timeout)
24
+
25
+ break if (Time.now > time_to_stop)
26
+ end
27
+ else
28
+ @cond.wait_while { @count > 0 }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,84 @@
1
+ module Zookeeper
2
+ module Logger
3
+ # h/t _eric and Papertrail
4
+ # @private
5
+ class ForwardingLogger
6
+ attr_accessor :level, :formatter
7
+
8
+ @@mutex = Monitor.new unless defined?(@@mutex)
9
+ @@loggers = {} unless defined?(@@loggers)
10
+
11
+ def self.for(logger, name)
12
+ @@mutex.synchronize do
13
+ @@loggers.fetch(name) do |k|
14
+ @@loggers[k] = new(logger, :formatter => lambda { |m| "%25.25s: %s" % [k, m] })
15
+ end
16
+ end
17
+ end
18
+
19
+ def initialize(logger, options = {})
20
+ @level = ::Logger::DEBUG
21
+ @logger = logger
22
+ @formatter = options[:formatter]
23
+ end
24
+
25
+ def add(severity, message = nil, progname = nil, &block)
26
+ severity ||= ::Logger::UNKNOWN
27
+ if !@logger || severity < @level
28
+ return true
29
+ end
30
+
31
+ message = (message || (block && block.call) || progname).to_s
32
+
33
+ if @formatter && @formatter.respond_to?(:call)
34
+ message = @formatter.call(message)
35
+ end
36
+
37
+ # If a newline is necessary then create a new message ending with a newline.
38
+ # Ensures that the original message is not mutated.
39
+ # message = "#{message}\n" unless message[-1] == ?\n
40
+
41
+ @logger.add(severity, message)
42
+ end
43
+
44
+ def <<(msg); @logger << msg; end
45
+ def write(msg); @logger.write(msg); end
46
+
47
+ def debug(progname = nil, &block)
48
+ add(::Logger::DEBUG, nil, progname, &block)
49
+ end
50
+
51
+ def info(progname = nil, &block)
52
+ add(::Logger::INFO, nil, progname, &block)
53
+ end
54
+
55
+ def warn(progname = nil, &block)
56
+ add(::Logger::WARN, nil, progname, &block)
57
+ end
58
+
59
+ def error(progname = nil, &block)
60
+ add(::Logger::ERROR, nil, progname, &block)
61
+ end
62
+
63
+ def fatal(progname = nil, &block)
64
+ add(::Logger::FATAL, nil, progname, &block)
65
+ end
66
+
67
+ def unknown(progname = nil, &block)
68
+ add(::Logger::UNKNOWN, nil, progname, &block)
69
+ end
70
+
71
+ def debug?; @level <= DEBUG; end
72
+
73
+ def info?; @level <= INFO; end
74
+
75
+ def warn?; @level <= WARN; end
76
+
77
+ def error?; @level <= ERROR; end
78
+
79
+ def fatal?; @level <= FATAL; end
80
+ end # ForwardingLogger
81
+ end # Logger
82
+ end # Zookeeper
83
+
84
+