zookeeper 1.0.3-java → 1.0.4-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/ext/c_zookeeper.rb +7 -0
- data/ext/dbg.h +1 -1
- data/ext/zookeeper_base.rb +6 -8
- data/ext/zookeeper_lib.c +35 -15
- data/ext/zookeeper_lib.h +0 -1
- data/lib/zookeeper.rb +6 -2
- data/lib/zookeeper/core_ext.rb +30 -0
- data/lib/zookeeper/forked.rb +2 -2
- data/lib/zookeeper/version.rb +1 -1
- data/spec/fork_hook_specs.rb +53 -0
- data/spec/forked_connection_spec.rb +30 -5
- metadata +7 -4
data/ext/c_zookeeper.rb
CHANGED
@@ -53,6 +53,13 @@ class CZookeeper
|
|
53
53
|
|
54
54
|
@_session_timeout_msec = DEFAULT_SESSION_TIMEOUT_MSEC
|
55
55
|
|
56
|
+
if cid = opts[:client_id]
|
57
|
+
raise ArgumentError, "opts[:client_id] must be a CZookeeper::ClientId" unless cid.kind_of?(ClientId)
|
58
|
+
raise ArgumentError, "session_id must not be nil" if cid.session_id.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
@_client_id = opts[:client_id]
|
62
|
+
|
56
63
|
@start_stop_mutex = Monitor.new
|
57
64
|
|
58
65
|
# used to signal that we're running
|
data/ext/dbg.h
CHANGED
@@ -45,7 +45,7 @@
|
|
45
45
|
// like check_debug_goto, but the label is implicitly 'error'
|
46
46
|
#define check_debug(A, M, ...) check_debug_goto(A, error, M, ##__VA_ARGS__)
|
47
47
|
|
48
|
-
#define zkrb_debug(M, ...) if (ZKRBDebugging) fprintf(stderr, "DEBUG %p:%s:%d: " M "\n", pthread_self(), __FILE__, __LINE__, ##__VA_ARGS__)
|
48
|
+
#define zkrb_debug(M, ...) if (ZKRBDebugging) fprintf(stderr, "DEBUG %p:%s:%d: " M "\n", (void *)pthread_self(), __FILE__, __LINE__, ##__VA_ARGS__)
|
49
49
|
#define zkrb_debug_inst(O, M, ...) zkrb_debug("obj_id: %lx, " M, FIX2LONG(rb_obj_id(O)), ##__VA_ARGS__)
|
50
50
|
|
51
51
|
// __dbg_h__
|
data/ext/zookeeper_base.rb
CHANGED
@@ -88,7 +88,8 @@ class ZookeeperBase
|
|
88
88
|
update_pid! # from Forked
|
89
89
|
end
|
90
90
|
private :reopen_after_fork!
|
91
|
-
|
91
|
+
|
92
|
+
|
92
93
|
def reopen(timeout = 10, watcher=nil)
|
93
94
|
if watcher and (watcher != @default_watcher)
|
94
95
|
raise "You cannot set the watcher to a different value this way anymore!"
|
@@ -97,11 +98,7 @@ class ZookeeperBase
|
|
97
98
|
reopen_after_fork! if forked?
|
98
99
|
|
99
100
|
@mutex.synchronize do
|
100
|
-
if @czk
|
101
|
-
@czk.close
|
102
|
-
@czk = nil
|
103
|
-
end
|
104
|
-
|
101
|
+
@czk.close if @czk
|
105
102
|
@czk = CZookeeper.new(@host, @event_queue)
|
106
103
|
|
107
104
|
# flushes all outstanding watcher reqs.
|
@@ -123,13 +120,14 @@ class ZookeeperBase
|
|
123
120
|
|
124
121
|
@dispatcher = @czk = nil
|
125
122
|
|
123
|
+
update_pid!
|
126
124
|
reopen_after_fork!
|
127
125
|
|
128
126
|
# approximate the java behavior of raising java.lang.IllegalArgumentException if the host
|
129
127
|
# argument ends with '/'
|
130
128
|
raise ArgumentError, "Host argument #{host.inspect} may not end with /" if host.end_with?('/')
|
131
129
|
|
132
|
-
@host = host
|
130
|
+
@host = host.dup
|
133
131
|
|
134
132
|
@default_watcher = (watcher or get_default_global_watcher)
|
135
133
|
|
@@ -165,7 +163,7 @@ class ZookeeperBase
|
|
165
163
|
shutdown_thread = Thread.new do
|
166
164
|
@mutex.synchronize do
|
167
165
|
stop_dispatch_thread!
|
168
|
-
|
166
|
+
close!
|
169
167
|
end
|
170
168
|
end
|
171
169
|
|
data/ext/zookeeper_lib.c
CHANGED
@@ -37,10 +37,34 @@ int ZKRBDebugging;
|
|
37
37
|
// XXX(slyphon): need to check these for error, but what to do if they fail?
|
38
38
|
pthread_mutex_t zkrb_q_mutex = PTHREAD_MUTEX_INITIALIZER;
|
39
39
|
|
40
|
-
|
40
|
+
inline static int global_mutex_lock() {
|
41
|
+
int rv = pthread_mutex_lock(&zkrb_q_mutex);
|
42
|
+
if (rv != 0) log_err("global_mutex_lock error");
|
43
|
+
return rv;
|
44
|
+
}
|
41
45
|
|
42
|
-
|
43
|
-
|
46
|
+
inline static int global_mutex_unlock() {
|
47
|
+
int rv = pthread_mutex_unlock(&zkrb_q_mutex);
|
48
|
+
if (rv != 0) log_err("global_mutex_unlock error");
|
49
|
+
return rv;
|
50
|
+
}
|
51
|
+
|
52
|
+
void atfork_prepare() {
|
53
|
+
global_mutex_lock();
|
54
|
+
}
|
55
|
+
|
56
|
+
void atfork_parent() {
|
57
|
+
global_mutex_unlock();
|
58
|
+
}
|
59
|
+
|
60
|
+
void atfork_child() {
|
61
|
+
global_mutex_unlock();
|
62
|
+
}
|
63
|
+
|
64
|
+
// set up handlers to make sure the thread being forked holds the lock at the
|
65
|
+
// time the process is copied, then immediately unlock the mutex in both parent
|
66
|
+
// and children
|
67
|
+
pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
|
44
68
|
|
45
69
|
|
46
70
|
void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
|
@@ -54,7 +78,7 @@ void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
|
|
54
78
|
return;
|
55
79
|
}
|
56
80
|
|
57
|
-
|
81
|
+
global_mutex_lock();
|
58
82
|
|
59
83
|
q->tail->event = elt;
|
60
84
|
q->tail->next = (zkrb_event_ll_t *) malloc(sizeof(zkrb_event_ll_t));
|
@@ -64,7 +88,7 @@ void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
|
|
64
88
|
|
65
89
|
ssize_t ret = write(q->pipe_write, "0", 1); /* Wake up Ruby listener */
|
66
90
|
|
67
|
-
|
91
|
+
global_mutex_unlock();
|
68
92
|
|
69
93
|
if (ret < 0) {
|
70
94
|
log_err("write to queue (%p) pipe failed!\n", q);
|
@@ -81,13 +105,13 @@ zkrb_event_t * zkrb_peek(zkrb_queue_t *q) {
|
|
81
105
|
|
82
106
|
if (!q) return NULL;
|
83
107
|
|
84
|
-
|
108
|
+
global_mutex_lock();
|
85
109
|
|
86
110
|
if (q != NULL && q->head != NULL && q->head->event != NULL) {
|
87
111
|
event = q->head->event;
|
88
112
|
}
|
89
113
|
|
90
|
-
|
114
|
+
global_mutex_unlock();
|
91
115
|
|
92
116
|
return event;
|
93
117
|
}
|
@@ -99,7 +123,7 @@ zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q, int need_lock) {
|
|
99
123
|
zkrb_event_ll_t *old_root = NULL;
|
100
124
|
|
101
125
|
if (need_lock)
|
102
|
-
|
126
|
+
global_mutex_lock();
|
103
127
|
|
104
128
|
if (!ZKRB_QUEUE_EMPTY(q)) {
|
105
129
|
old_root = q->head;
|
@@ -108,7 +132,7 @@ zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q, int need_lock) {
|
|
108
132
|
}
|
109
133
|
|
110
134
|
if (need_lock)
|
111
|
-
|
135
|
+
global_mutex_unlock();
|
112
136
|
|
113
137
|
free(old_root);
|
114
138
|
return rv;
|
@@ -117,12 +141,12 @@ zkrb_event_t* zkrb_dequeue(zkrb_queue_t *q, int need_lock) {
|
|
117
141
|
void zkrb_signal(zkrb_queue_t *q) {
|
118
142
|
if (!q) return;
|
119
143
|
|
120
|
-
|
144
|
+
global_mutex_lock();
|
121
145
|
|
122
146
|
if (!write(q->pipe_write, "0", 1)) /* Wake up Ruby listener */
|
123
147
|
log_err("zkrb_signal: write to pipe failed, could not wake");
|
124
148
|
|
125
|
-
|
149
|
+
global_mutex_unlock();
|
126
150
|
}
|
127
151
|
|
128
152
|
zkrb_event_ll_t *zkrb_event_ll_t_alloc(void) {
|
@@ -147,8 +171,6 @@ zkrb_queue_t *zkrb_queue_alloc(void) {
|
|
147
171
|
|
148
172
|
rq->orig_pid = getpid();
|
149
173
|
|
150
|
-
check(pthread_mutex_init(&rq->mutex, NULL) == 0, "pthread_mutex_init failed");
|
151
|
-
|
152
174
|
rq->head = zkrb_event_ll_t_alloc();
|
153
175
|
check_mem(rq->head);
|
154
176
|
|
@@ -175,8 +197,6 @@ void zkrb_queue_free(zkrb_queue_t *queue) {
|
|
175
197
|
close(queue->pipe_read);
|
176
198
|
close(queue->pipe_write);
|
177
199
|
|
178
|
-
pthread_mutex_destroy(&queue->mutex);
|
179
|
-
|
180
200
|
free(queue);
|
181
201
|
}
|
182
202
|
|
data/ext/zookeeper_lib.h
CHANGED
data/lib/zookeeper.rb
CHANGED
@@ -5,12 +5,16 @@ require 'monitor'
|
|
5
5
|
require 'forwardable'
|
6
6
|
require 'logger'
|
7
7
|
|
8
|
-
require 'backports'
|
9
|
-
|
10
8
|
module Zookeeper
|
11
9
|
# establishes the namespace
|
12
10
|
end
|
13
11
|
|
12
|
+
require File.expand_path('../zookeeper/core_ext', __FILE__)
|
13
|
+
|
14
|
+
silence_warnings do
|
15
|
+
require 'backports'
|
16
|
+
end
|
17
|
+
|
14
18
|
require_relative 'zookeeper/forked'
|
15
19
|
require_relative 'zookeeper/latch'
|
16
20
|
require_relative 'zookeeper/acls'
|
@@ -0,0 +1,30 @@
|
|
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
|
+
|
data/lib/zookeeper/forked.rb
CHANGED
data/lib/zookeeper/version.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'fork hooks' do
|
4
|
+
def safe_kill_process(signal, pid)
|
5
|
+
Process.kill(signal, pid)
|
6
|
+
rescue Errno::ESRCH
|
7
|
+
nil
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
Zookeeper::Forked.clear!
|
12
|
+
|
13
|
+
if @pid
|
14
|
+
safe_kill_process('KILL', @pid)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'fork with a block' do
|
19
|
+
it %[should call the after_fork_in_child hooks in the child] do
|
20
|
+
child_hook_called = false
|
21
|
+
|
22
|
+
hook_order = []
|
23
|
+
|
24
|
+
Zookeeper.prepare_for_fork { hook_order << :prepare }
|
25
|
+
Zookeeper.after_fork_in_parent { hook_order << :parent }
|
26
|
+
Zookeeper.after_fork_in_child { hook_order << :child }
|
27
|
+
|
28
|
+
@pid = fork do
|
29
|
+
unless hook_order.first == :prepare
|
30
|
+
$stderr.puts "hook order wrong! #{hook_order.inspect}"
|
31
|
+
exit! 2
|
32
|
+
end
|
33
|
+
|
34
|
+
unless hook_order.last == :child
|
35
|
+
$stderr.puts "hook order wrong! #{hook_order.inspect}"
|
36
|
+
exit! 3
|
37
|
+
end
|
38
|
+
|
39
|
+
exit! 0
|
40
|
+
end
|
41
|
+
|
42
|
+
hook_order.first.should == :prepare
|
43
|
+
hook_order.last.should == :parent
|
44
|
+
|
45
|
+
_, st = Process.wait2(@pid)
|
46
|
+
st.exitstatus.should == 0
|
47
|
+
|
48
|
+
st.should be_exited
|
49
|
+
st.should be_success
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -27,14 +27,31 @@ unless defined?(::JRUBY_VERSION)
|
|
27
27
|
|
28
28
|
after do
|
29
29
|
if @pid and process_alive?(@pid)
|
30
|
-
|
31
|
-
|
30
|
+
begin
|
31
|
+
Process.kill('KILL', @pid)
|
32
|
+
p Process.wait2(@pid)
|
33
|
+
rescue Errno::ESRCH
|
34
|
+
end
|
32
35
|
end
|
33
36
|
|
34
37
|
@zk.close if @zk and !@zk.closed?
|
35
38
|
with_open_zk(connection_string) { |z| rm_rf(z, path) }
|
36
39
|
end
|
37
40
|
|
41
|
+
def wait_for_child_safely(pid, timeout=5)
|
42
|
+
time_to_stop = Time.now + timeout
|
43
|
+
|
44
|
+
until Time.now > time_to_stop
|
45
|
+
if a = Process.wait2(@pid, Process::WNOHANG)
|
46
|
+
return a.last
|
47
|
+
else
|
48
|
+
sleep(0.01)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
38
55
|
it %[should do the right thing and not fail] do
|
39
56
|
@zk.wait_until_connected
|
40
57
|
|
@@ -68,13 +85,21 @@ unless defined?(::JRUBY_VERSION)
|
|
68
85
|
exit!(0)
|
69
86
|
end
|
70
87
|
|
71
|
-
|
88
|
+
event_waiter_th = Thread.new do
|
89
|
+
@latch.await(10) unless @event
|
90
|
+
@event
|
91
|
+
end
|
72
92
|
|
73
|
-
|
93
|
+
logger.debug { "waiting on child #{@pid}" }
|
74
94
|
|
75
|
-
|
95
|
+
status = wait_for_child_safely(@pid)
|
96
|
+
raise "Child process did not exit, likely hung" unless status
|
76
97
|
|
98
|
+
status.should_not be_signaled
|
77
99
|
status.should be_success
|
100
|
+
|
101
|
+
event_waiter_th.join(5).should == event_waiter_th
|
102
|
+
@event.should_not be nil
|
78
103
|
end
|
79
104
|
end
|
80
105
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zookeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 4
|
10
|
+
version: 1.0.4
|
11
11
|
platform: java
|
12
12
|
authors:
|
13
13
|
- Phillip Pearson
|
@@ -20,7 +20,7 @@ autorequire:
|
|
20
20
|
bindir: bin
|
21
21
|
cert_chain: []
|
22
22
|
|
23
|
-
date: 2012-05-
|
23
|
+
date: 2012-05-10 00:00:00 Z
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: backports
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- lib/zookeeper/common/queue_with_pipe.rb
|
123
123
|
- lib/zookeeper/compatibility.rb
|
124
124
|
- lib/zookeeper/constants.rb
|
125
|
+
- lib/zookeeper/core_ext.rb
|
125
126
|
- lib/zookeeper/em_client.rb
|
126
127
|
- lib/zookeeper/exceptions.rb
|
127
128
|
- lib/zookeeper/forked.rb
|
@@ -136,6 +137,7 @@ files:
|
|
136
137
|
- spec/compatibilty_spec.rb
|
137
138
|
- spec/default_watcher_spec.rb
|
138
139
|
- spec/em_spec.rb
|
140
|
+
- spec/fork_hook_specs.rb
|
139
141
|
- spec/forked_connection_spec.rb
|
140
142
|
- spec/latch_spec.rb
|
141
143
|
- spec/log4j.properties
|
@@ -187,6 +189,7 @@ test_files:
|
|
187
189
|
- spec/compatibilty_spec.rb
|
188
190
|
- spec/default_watcher_spec.rb
|
189
191
|
- spec/em_spec.rb
|
192
|
+
- spec/fork_hook_specs.rb
|
190
193
|
- spec/forked_connection_spec.rb
|
191
194
|
- spec/latch_spec.rb
|
192
195
|
- spec/log4j.properties
|