slyphon-zookeeper 0.3.0-java → 0.8.0-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.
- data/CHANGELOG +34 -0
- data/Rakefile +25 -5
- data/ext/c_zookeeper.rb +214 -0
- data/ext/dbg.h +18 -2
- data/ext/depend +1 -2
- data/ext/zookeeper_base.rb +73 -99
- data/ext/zookeeper_c.c +52 -41
- data/ext/zookeeper_lib.c +90 -78
- data/ext/zookeeper_lib.h +0 -1
- data/java/zookeeper_base.rb +72 -154
- data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
- data/lib/zookeeper/common.rb +73 -9
- data/lib/zookeeper/constants.rb +28 -0
- data/lib/zookeeper/em_client.rb +13 -138
- data/lib/zookeeper/exceptions.rb +4 -1
- data/lib/zookeeper.rb +51 -15
- data/slyphon-zookeeper.gemspec +1 -1
- data/spec/c_zookeeper_spec.rb +50 -0
- data/spec/chrooted_connection_spec.rb +121 -0
- data/spec/em_spec.rb +0 -61
- data/spec/shared/all_success_return_values.rb +10 -0
- data/spec/shared/connection_examples.rb +1007 -0
- data/spec/spec_helper.rb +42 -19
- data/spec/zookeeper_spec.rb +8 -1033
- metadata +16 -6
data/CHANGELOG
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
v0.8.0 Refactor C implementaion, EventMachine client
|
2
|
+
|
3
|
+
* separated CZookeeper and ZookeeperBase implementation
|
4
|
+
|
5
|
+
This solves issues with reopen not working properly, makes for a much
|
6
|
+
cleaner event delivery implementation. ZookeeperBase controls the lifecycle
|
7
|
+
of the event dispatch thread now, rather than it being tied to CZookeeper.
|
8
|
+
|
9
|
+
* added support for the 'sync' API call
|
10
|
+
|
11
|
+
* Refactored zookeeper_c.c and zookeeper_lib.c
|
12
|
+
|
13
|
+
More error checking in zookeeper_lib.c and restructure some things to make
|
14
|
+
logic easier to follow
|
15
|
+
|
16
|
+
Fix bug in method_get_next_event that made the shutdown case so complicated
|
17
|
+
|
18
|
+
* Massively simplified EMClient implementation
|
19
|
+
|
20
|
+
Rather than trying to hook the IO used by zookeeper_lib to notify zookeeper_c
|
21
|
+
about event availabiltiy directly into EventMachine, use the same event delivery
|
22
|
+
thread, but wrap the dispatch call in EM.schedule.
|
23
|
+
|
24
|
+
* Improve implementation of spin-lock-esque code that waits for the connection to be
|
25
|
+
established before returning.
|
26
|
+
|
27
|
+
This cut the test runtime down from 1m 20s to 2s.
|
28
|
+
|
29
|
+
* Java client refactoring, similar correctness changes
|
30
|
+
|
31
|
+
* Change ZookeeperException base class to StandardError instead of Exception
|
32
|
+
|
33
|
+
|
1
34
|
v0.4.5 Upgrade to ZooKeeper 3.3.3
|
2
35
|
|
3
36
|
v0.4.4 Fix race condition on close, possible data corruption on async get.
|
@@ -24,3 +57,4 @@ v0.2. Bundle C dependencies, like memcached.gem.
|
|
24
57
|
|
25
58
|
v0.1. First release.
|
26
59
|
|
60
|
+
# vim:ft=text:ts=2:sw=2:et
|
data/Rakefile
CHANGED
@@ -15,10 +15,15 @@ gemset_name = 'zookeeper'
|
|
15
15
|
%w[1.8.7 1.9.2 1.9.3 jruby].each do |rvm_ruby|
|
16
16
|
ruby_with_gemset = "#{rvm_ruby}@#{gemset_name}"
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
create_gemset_name = "mb:#{rvm_ruby}:create_gemset"
|
19
|
+
clobber_task_name = "mb:#{rvm_ruby}:clobber"
|
20
|
+
build_task_name = "mb:#{rvm_ruby}:build"
|
21
|
+
bundle_task_name = "mb:#{rvm_ruby}:bundle_install"
|
22
|
+
rspec_task_name = "mb:#{rvm_ruby}:run_rspec"
|
23
|
+
|
24
|
+
task create_gemset_name do
|
25
|
+
sh "rvm #{rvm_ruby} do rvm gemset create #{gemset_name}"
|
26
|
+
end
|
22
27
|
|
23
28
|
task clobber_task_name do
|
24
29
|
unless rvm_ruby == 'jruby'
|
@@ -28,7 +33,7 @@ gemset_name = 'zookeeper'
|
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
31
|
-
task build_task_name => clobber_task_name do
|
36
|
+
task build_task_name => [create_gemset_name, clobber_task_name] do
|
32
37
|
unless rvm_ruby == 'jruby'
|
33
38
|
cd 'ext' do
|
34
39
|
sh "rvm #{ruby_with_gemset} do rake build"
|
@@ -48,4 +53,19 @@ gemset_name = 'zookeeper'
|
|
48
53
|
task "mb:test_all_rubies" => rspec_task_name
|
49
54
|
end
|
50
55
|
|
56
|
+
namespace :build do
|
57
|
+
task :clean do
|
58
|
+
cd 'ext' do
|
59
|
+
sh 'rake clean'
|
60
|
+
end
|
61
|
+
|
62
|
+
Rake::Task['build'].invoke
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
task :build do
|
67
|
+
cd 'ext' do
|
68
|
+
sh "rake"
|
69
|
+
end
|
70
|
+
end
|
51
71
|
|
data/ext/c_zookeeper.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'zookeeper/constants'
|
2
|
+
require File.expand_path('../zookeeper_c', __FILE__)
|
3
|
+
|
4
|
+
# TODO: see if we can get the destructor to handle thread/event queue teardown
|
5
|
+
# when we're garbage collected
|
6
|
+
class CZookeeper
|
7
|
+
include ZookeeperCommon
|
8
|
+
include ZookeeperConstants
|
9
|
+
include ZookeeperExceptions
|
10
|
+
|
11
|
+
DEFAULT_SESSION_TIMEOUT_MSEC = 10000
|
12
|
+
|
13
|
+
class GotNilEventException < StandardError; end
|
14
|
+
|
15
|
+
# assume we're at debug level
|
16
|
+
def self.get_debug_level
|
17
|
+
@debug_level ||= ZOO_LOG_LEVEL_INFO
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.set_debug_level(value)
|
21
|
+
@debug_level = value
|
22
|
+
set_zkrb_debug_level(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(host, event_queue, opts={})
|
26
|
+
@host = host
|
27
|
+
@event_queue = event_queue
|
28
|
+
|
29
|
+
# used by the C layer. CZookeeper sets this to true when the init method
|
30
|
+
# has completed. once this is set to true, it stays true.
|
31
|
+
#
|
32
|
+
# you should grab the @start_stop_mutex before messing with this flag
|
33
|
+
@_running = nil
|
34
|
+
|
35
|
+
# This is set to true after destroy_zkrb_instance has been called and all
|
36
|
+
# CZookeeper state has been cleaned up
|
37
|
+
@_closed = false # also used by the C layer
|
38
|
+
|
39
|
+
# set by the ruby side to indicate we are in shutdown mode used by method_get_next_event
|
40
|
+
@_shutting_down = false
|
41
|
+
|
42
|
+
# the actual C data is stashed in this ivar. never *ever* touch this
|
43
|
+
@_data = nil
|
44
|
+
|
45
|
+
@_session_timeout_msec = DEFAULT_SESSION_TIMEOUT_MSEC
|
46
|
+
|
47
|
+
@start_stop_mutex = Monitor.new
|
48
|
+
|
49
|
+
# used to signal that we're running
|
50
|
+
@running_cond = @start_stop_mutex.new_cond
|
51
|
+
|
52
|
+
@event_thread = nil
|
53
|
+
|
54
|
+
setup_event_thread!
|
55
|
+
|
56
|
+
zkrb_init(@host)
|
57
|
+
|
58
|
+
logger.debug { "init returned!" }
|
59
|
+
end
|
60
|
+
|
61
|
+
def closed?
|
62
|
+
@start_stop_mutex.synchronize { !!@_closed }
|
63
|
+
end
|
64
|
+
|
65
|
+
def running?
|
66
|
+
@start_stop_mutex.synchronize { !!@_running }
|
67
|
+
end
|
68
|
+
|
69
|
+
def shutting_down?
|
70
|
+
@start_stop_mutex.synchronize { !!@_shutting_down }
|
71
|
+
end
|
72
|
+
|
73
|
+
def connected?
|
74
|
+
state == ZOO_CONNECTED_STATE
|
75
|
+
end
|
76
|
+
|
77
|
+
def connecting?
|
78
|
+
state == ZOO_CONNECTING_STATE
|
79
|
+
end
|
80
|
+
|
81
|
+
def associating?
|
82
|
+
state == ZOO_ASSOCIATING_STATE
|
83
|
+
end
|
84
|
+
|
85
|
+
def close
|
86
|
+
return if closed?
|
87
|
+
|
88
|
+
shut_down!
|
89
|
+
stop_event_thread!
|
90
|
+
|
91
|
+
@start_stop_mutex.synchronize do
|
92
|
+
if !@_closed and @_data
|
93
|
+
close_handle
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def state
|
101
|
+
return ZOO_CLOSED_STATE if closed?
|
102
|
+
zkrb_state
|
103
|
+
end
|
104
|
+
|
105
|
+
# this implementation is gross, but i don't really see another way of doing it
|
106
|
+
# without more grossness
|
107
|
+
#
|
108
|
+
# returns true if we're connected, false if we're not
|
109
|
+
#
|
110
|
+
# if timeout is nil, we never time out, and wait forever for CONNECTED state
|
111
|
+
#
|
112
|
+
def wait_until_connected(timeout=10)
|
113
|
+
return false unless wait_until_running(timeout)
|
114
|
+
|
115
|
+
time_to_stop = timeout ? (Time.now + timeout) : nil
|
116
|
+
|
117
|
+
until connected? or (time_to_stop and Time.now > time_to_stop)
|
118
|
+
Thread.pass
|
119
|
+
end
|
120
|
+
|
121
|
+
connected?
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
# will wait until the client has entered the running? state
|
126
|
+
# or until timeout seconds have passed.
|
127
|
+
#
|
128
|
+
# returns true if we're running, false if we timed out
|
129
|
+
def wait_until_running(timeout=5)
|
130
|
+
@start_stop_mutex.synchronize do
|
131
|
+
return true if @_running
|
132
|
+
@running_cond.wait(timeout)
|
133
|
+
!!@_running
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def setup_event_thread!
|
138
|
+
@event_thread ||= Thread.new do
|
139
|
+
Thread.current.abort_on_exception = true # remove this once this is confirmed to work
|
140
|
+
|
141
|
+
logger.debug { "event_thread waiting until running: #{@_running}" }
|
142
|
+
|
143
|
+
@start_stop_mutex.synchronize do
|
144
|
+
@running_cond.wait_until { @_running }
|
145
|
+
|
146
|
+
if @_shutting_down
|
147
|
+
logger.error { "event thread saw @_shutting_down, bailing without entering loop" }
|
148
|
+
return
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
logger.debug { "event_thread running: #{@_running}" }
|
153
|
+
|
154
|
+
while true
|
155
|
+
begin
|
156
|
+
_iterate_event_delivery
|
157
|
+
rescue GotNilEventException
|
158
|
+
logger.debug { "#{self.class}##{__method__}: event delivery thread is exiting" }
|
159
|
+
break
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# TODO: should we try iterating events after this point? to see if any are left?
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def _iterate_event_delivery
|
168
|
+
get_next_event(true).tap do |hash|
|
169
|
+
raise GotNilEventException if hash.nil?
|
170
|
+
@event_queue.push(hash)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# use this method to set the @_shutting_down flag to true
|
175
|
+
def shut_down!
|
176
|
+
logger.debug { "#{self.class}##{__method__}" }
|
177
|
+
|
178
|
+
@start_stop_mutex.synchronize do
|
179
|
+
@_shutting_down = true
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# this method is part of the reopen/close code, and is responsible for
|
184
|
+
# shutting down the dispatch thread.
|
185
|
+
#
|
186
|
+
# @dispatch will be nil when this method exits
|
187
|
+
#
|
188
|
+
def stop_event_thread!
|
189
|
+
logger.debug { "#{self.class}##{__method__}" }
|
190
|
+
|
191
|
+
if @event_thread
|
192
|
+
unless @_closed
|
193
|
+
wake_event_loop! # this is a C method
|
194
|
+
end
|
195
|
+
@event_thread.join
|
196
|
+
@event_thread = nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def logger
|
201
|
+
Zookeeper.logger
|
202
|
+
end
|
203
|
+
|
204
|
+
# called by underlying C code to signal we're running
|
205
|
+
def zkc_set_running_and_notify!
|
206
|
+
logger.debug { "#{self.class}##{__method__}" }
|
207
|
+
|
208
|
+
@start_stop_mutex.synchronize do
|
209
|
+
@_running = true
|
210
|
+
@running_cond.broadcast
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
data/ext/dbg.h
CHANGED
@@ -22,16 +22,32 @@
|
|
22
22
|
|
23
23
|
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
24
24
|
|
25
|
+
// acts to assert that A is true
|
25
26
|
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
26
27
|
|
28
|
+
// like check, but provide an explicit goto label name
|
29
|
+
#define check_goto(A, L, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto L; }
|
30
|
+
|
31
|
+
// like check, but implicit jump to 'unlock' label
|
32
|
+
#define check_unlock(A, M, ...) check_goto(A, unlock, M, ##__VA_ARGS__)
|
33
|
+
|
27
34
|
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
28
35
|
|
29
36
|
#define check_mem(A) check((A), "Out of memory.")
|
30
37
|
|
31
|
-
|
38
|
+
// checks the condition A, if not true, logs the message M given using zkrb_debug
|
39
|
+
// then does a goto to the label L
|
40
|
+
#define check_debug_goto(A, L, M, ...) if(!(A)) { zkrb_debug(M, ##__VA_ARGS__); errno=0; goto L; }
|
41
|
+
|
42
|
+
// check_debug_goto with implicit 'unlock' label
|
43
|
+
#define check_debug_unlock(A, M, ...) check_debug_goto(A, unlock, M, ##__VA_ARGS__)
|
44
|
+
|
45
|
+
// like check_debug_goto, but the label is implicitly 'error'
|
46
|
+
#define check_debug(A, M, ...) check_debug_goto(A, error, M, ##__VA_ARGS__)
|
32
47
|
|
33
|
-
#define zkrb_debug(M, ...) if (ZKRBDebugging) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
48
|
+
#define zkrb_debug(M, ...) if (ZKRBDebugging) fprintf(stderr, "DEBUG %p:%s:%d: " M "\n", pthread_self(), __FILE__, __LINE__, ##__VA_ARGS__)
|
34
49
|
#define zkrb_debug_inst(O, M, ...) zkrb_debug("obj_id: %lx, " M, FIX2LONG(rb_obj_id(O)), ##__VA_ARGS__)
|
35
50
|
|
51
|
+
// __dbg_h__
|
36
52
|
#endif
|
37
53
|
|
data/ext/depend
CHANGED
data/ext/zookeeper_base.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
require File.expand_path('../c_zookeeper', __FILE__)
|
2
|
+
require 'forwardable'
|
3
|
+
|
1
4
|
# The low-level wrapper-specific methods for the C lib
|
2
5
|
# subclassed by the top-level Zookeeper class
|
3
|
-
class ZookeeperBase
|
6
|
+
class ZookeeperBase
|
7
|
+
extend Forwardable
|
4
8
|
include ZookeeperCommon
|
5
9
|
include ZookeeperCallbacks
|
6
10
|
include ZookeeperConstants
|
@@ -8,6 +12,11 @@ class ZookeeperBase < CZookeeper
|
|
8
12
|
include ZookeeperACLs
|
9
13
|
include ZookeeperStat
|
10
14
|
|
15
|
+
# @private
|
16
|
+
class ClientShutdownException < StandardError; end
|
17
|
+
|
18
|
+
# @private
|
19
|
+
KILL_TOKEN = Object.new unless defined?(KILL_TOKEN)
|
11
20
|
|
12
21
|
ZKRB_GLOBAL_CB_REQ = -1
|
13
22
|
|
@@ -17,38 +26,57 @@ class ZookeeperBase < CZookeeper
|
|
17
26
|
ZOO_LOG_LEVEL_INFO = 3
|
18
27
|
ZOO_LOG_LEVEL_DEBUG = 4
|
19
28
|
|
29
|
+
def_delegators :czk,
|
30
|
+
:get_children, :exists, :delete, :get, :set, :set_acl, :get_acl, :client_id, :sync, :selectable_io
|
31
|
+
|
32
|
+
# some state methods need to be more paranoid about locking to ensure the correct
|
33
|
+
# state is returned
|
34
|
+
#
|
35
|
+
def self.threadsafe_inquisitor(*syms)
|
36
|
+
syms.each do |sym|
|
37
|
+
class_eval(<<-EOM, __FILE__, __LINE__+1)
|
38
|
+
def #{sym}
|
39
|
+
false|@mutex.synchronize { @czk and @czk.#{sym} }
|
40
|
+
end
|
41
|
+
EOM
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
threadsafe_inquisitor :connected?, :connecting?, :associating?, :running?
|
46
|
+
|
47
|
+
attr_reader :event_queue
|
20
48
|
|
21
49
|
def reopen(timeout = 10, watcher=nil)
|
22
|
-
watcher
|
23
|
-
|
24
|
-
@req_mutex.synchronize do
|
25
|
-
# flushes all outstanding watcher reqs.
|
26
|
-
@watcher_req = {}
|
27
|
-
set_default_global_watcher(&watcher)
|
50
|
+
if watcher and (watcher != @default_watcher)
|
51
|
+
raise "You cannot set the watcher to a different value this way anymore!"
|
28
52
|
end
|
53
|
+
|
54
|
+
@mutex.synchronize do
|
55
|
+
# flushes all outstanding watcher reqs.
|
56
|
+
@watcher_reqs.clear
|
57
|
+
set_default_global_watcher
|
29
58
|
|
30
|
-
|
31
|
-
# $stderr.puts "%s: calling init, self.obj_id: %x" % [self.class, object_id]
|
32
|
-
init(@host)
|
59
|
+
orig_czk, @czk = @czk, CZookeeper.new(@host, @event_queue)
|
33
60
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
until state == Zookeeper::ZOO_CONNECTED_STATE
|
38
|
-
break if Time.now > time_to_stop
|
39
|
-
sleep 0.1
|
40
|
-
end
|
41
|
-
end
|
61
|
+
orig_czk.close if orig_czk
|
62
|
+
|
63
|
+
@czk.wait_until_connected(timeout)
|
42
64
|
end
|
43
65
|
|
66
|
+
setup_dispatch_thread!
|
44
67
|
state
|
45
68
|
end
|
46
69
|
|
47
70
|
def initialize(host, timeout = 10, watcher=nil)
|
48
71
|
@watcher_reqs = {}
|
49
72
|
@completion_reqs = {}
|
50
|
-
|
51
|
-
@
|
73
|
+
|
74
|
+
@mutex = Monitor.new
|
75
|
+
@dispatch_shutdown_cond = @mutex.new_cond
|
76
|
+
|
77
|
+
@current_req_id = 0
|
78
|
+
@event_queue = QueueWithPipe.new
|
79
|
+
@czk = nil
|
52
80
|
|
53
81
|
# approximate the java behavior of raising java.lang.IllegalArgumentException if the host
|
54
82
|
# argument ends with '/'
|
@@ -56,18 +84,17 @@ class ZookeeperBase < CZookeeper
|
|
56
84
|
|
57
85
|
@host = host
|
58
86
|
|
59
|
-
@
|
60
|
-
|
61
|
-
watcher ||= get_default_global_watcher
|
62
|
-
|
63
|
-
@_running = nil # used by the C layer
|
64
|
-
@_closed = false # also used by the C layer
|
87
|
+
@default_watcher = (watcher or get_default_global_watcher)
|
65
88
|
|
66
89
|
yield self if block_given?
|
67
90
|
|
68
|
-
reopen(timeout
|
69
|
-
|
70
|
-
|
91
|
+
reopen(timeout)
|
92
|
+
end
|
93
|
+
|
94
|
+
# synchronized accessor to the @czk instance
|
95
|
+
# @private
|
96
|
+
def czk
|
97
|
+
@mutex.synchronize { @czk }
|
71
98
|
end
|
72
99
|
|
73
100
|
# if either of these happen, the user will need to renegotiate a connection via reopen
|
@@ -76,41 +103,10 @@ class ZookeeperBase < CZookeeper
|
|
76
103
|
raise ZookeeperException::NotConnected unless connected?
|
77
104
|
end
|
78
105
|
|
79
|
-
def connected?
|
80
|
-
state == ZOO_CONNECTED_STATE
|
81
|
-
end
|
82
|
-
|
83
|
-
def connecting?
|
84
|
-
state == ZOO_CONNECTING_STATE
|
85
|
-
end
|
86
|
-
|
87
|
-
def associating?
|
88
|
-
state == ZOO_ASSOCIATING_STATE
|
89
|
-
end
|
90
|
-
|
91
106
|
def close
|
92
|
-
@
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
if @dispatcher
|
97
|
-
unless @_closed
|
98
|
-
wake_event_loop!
|
99
|
-
end
|
100
|
-
@dispatcher.join
|
101
|
-
end
|
102
|
-
|
103
|
-
@start_stop_mutex.synchronize do
|
104
|
-
unless @_closed
|
105
|
-
close_handle
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# this is set up in the C init method, but it's easier to
|
110
|
-
# do the teardown here
|
111
|
-
begin
|
112
|
-
@selectable_io.close if @selectable_io
|
113
|
-
rescue IOError
|
107
|
+
@mutex.synchronize do
|
108
|
+
stop_dispatch_thread!
|
109
|
+
@czk.close
|
114
110
|
end
|
115
111
|
end
|
116
112
|
|
@@ -118,7 +114,7 @@ class ZookeeperBase < CZookeeper
|
|
118
114
|
# is pretty damn annoying. this is used to clean things up.
|
119
115
|
def create(*args)
|
120
116
|
# since we don't care about the inputs, just glob args
|
121
|
-
rc, new_path =
|
117
|
+
rc, new_path = czk.create(*args)
|
122
118
|
[rc, strip_chroot_from(new_path)]
|
123
119
|
end
|
124
120
|
|
@@ -128,34 +124,33 @@ class ZookeeperBase < CZookeeper
|
|
128
124
|
end
|
129
125
|
|
130
126
|
# set the watcher object/proc that will receive all global events (such as session/state events)
|
131
|
-
def set_default_global_watcher
|
132
|
-
|
133
|
-
|
127
|
+
def set_default_global_watcher
|
128
|
+
warn "DEPRECATION WARNING: #{self.class}#set_default_global_watcher ignores block" if block_given?
|
129
|
+
|
130
|
+
@mutex.synchronize do
|
131
|
+
# @default_watcher = block # save this here for reopen() to use
|
134
132
|
@watcher_reqs[ZKRB_GLOBAL_CB_REQ] = { :watcher => @default_watcher, :watcher_context => nil }
|
135
133
|
end
|
136
134
|
end
|
137
135
|
|
138
|
-
def closed?
|
139
|
-
@start_stop_mutex.synchronize { false|@_closed }
|
140
|
-
end
|
141
|
-
|
142
|
-
def running?
|
143
|
-
@start_stop_mutex.synchronize { false|@_running }
|
144
|
-
end
|
145
|
-
|
146
136
|
def state
|
147
137
|
return ZOO_CLOSED_STATE if closed?
|
148
|
-
|
138
|
+
czk.state
|
149
139
|
end
|
150
140
|
|
151
141
|
def session_id
|
152
|
-
client_id.session_id
|
142
|
+
cid = client_id and cid.session_id
|
153
143
|
end
|
154
144
|
|
155
145
|
def session_passwd
|
156
|
-
client_id.passwd
|
146
|
+
cid = client_id and cid.passwd
|
157
147
|
end
|
158
148
|
|
149
|
+
# we are closed if there is no @czk instance or @czk.closed?
|
150
|
+
def closed?
|
151
|
+
@mutex.synchronize { !@czk or @czk.closed? }
|
152
|
+
end
|
153
|
+
|
159
154
|
protected
|
160
155
|
# this is a hack: to provide consistency between the C and Java drivers when
|
161
156
|
# using a chrooted connection, we wrap the callback in a block that will
|
@@ -164,7 +159,6 @@ protected
|
|
164
159
|
# version. The non-async manipulation is handled in ZookeeperBase#create.
|
165
160
|
#
|
166
161
|
def setup_completion(req_id, meth_name, call_opts)
|
167
|
-
|
168
162
|
if (meth_name == :create) and cb = call_opts[:callback]
|
169
163
|
call_opts[:callback] = lambda do |hash|
|
170
164
|
# in this case the string will be the absolute zookeeper path (i.e.
|
@@ -186,26 +180,6 @@ protected
|
|
186
180
|
path[chroot_path.length..-1]
|
187
181
|
end
|
188
182
|
|
189
|
-
def barf_unless_running!
|
190
|
-
@start_stop_mutex.synchronize do
|
191
|
-
raise ShuttingDownException unless (@_running and not @_closed)
|
192
|
-
yield
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def setup_dispatch_thread!
|
197
|
-
@dispatcher = Thread.new do
|
198
|
-
while running?
|
199
|
-
begin # calling user code, so protect ourselves
|
200
|
-
dispatch_next_callback
|
201
|
-
rescue Exception => e
|
202
|
-
$stderr.puts "Error in dispatch thread, #{e.class}: #{e.message}\n" << e.backtrace.map{|n| "\t#{n}"}.join("\n")
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
# TODO: Make all global puts configurable
|
209
183
|
def get_default_global_watcher
|
210
184
|
Proc.new { |args|
|
211
185
|
logger.debug { "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}" }
|