zookeeper 0.9.3-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/.gitignore +10 -0
- data/CHANGELOG +119 -0
- data/Gemfile +17 -0
- data/LICENSE +23 -0
- data/Manifest +29 -0
- data/README.markdown +59 -0
- data/Rakefile +139 -0
- data/examples/cloud_config.rb +125 -0
- data/ext/.gitignore +6 -0
- data/ext/Rakefile +51 -0
- data/ext/c_zookeeper.rb +212 -0
- data/ext/dbg.h +53 -0
- data/ext/depend +5 -0
- data/ext/extconf.rb +85 -0
- data/ext/generate_gvl_code.rb +316 -0
- data/ext/zkc-3.3.5.tar.gz +0 -0
- data/ext/zkrb_wrapper.c +731 -0
- data/ext/zkrb_wrapper.h +330 -0
- data/ext/zkrb_wrapper_compat.c +15 -0
- data/ext/zkrb_wrapper_compat.h +11 -0
- data/ext/zookeeper_base.rb +211 -0
- data/ext/zookeeper_c.c +725 -0
- data/ext/zookeeper_lib.c +677 -0
- data/ext/zookeeper_lib.h +172 -0
- data/java/zookeeper_base.rb +477 -0
- data/lib/zookeeper.rb +297 -0
- data/lib/zookeeper/acls.rb +40 -0
- data/lib/zookeeper/callbacks.rb +91 -0
- data/lib/zookeeper/common.rb +174 -0
- data/lib/zookeeper/common/queue_with_pipe.rb +78 -0
- data/lib/zookeeper/constants.rb +57 -0
- data/lib/zookeeper/em_client.rb +55 -0
- data/lib/zookeeper/exceptions.rb +100 -0
- data/lib/zookeeper/stat.rb +21 -0
- data/lib/zookeeper/version.rb +6 -0
- data/notes.txt +14 -0
- data/spec/c_zookeeper_spec.rb +50 -0
- data/spec/chrooted_connection_spec.rb +81 -0
- data/spec/default_watcher_spec.rb +41 -0
- data/spec/em_spec.rb +51 -0
- data/spec/log4j.properties +17 -0
- data/spec/shared/all_success_return_values.rb +10 -0
- data/spec/shared/connection_examples.rb +1018 -0
- data/spec/spec_helper.rb +119 -0
- data/spec/support/progress_formatter.rb +15 -0
- data/spec/zookeeper_spec.rb +24 -0
- data/test/test_basic.rb +37 -0
- data/test/test_callback1.rb +36 -0
- data/test/test_close.rb +16 -0
- data/test/test_esoteric.rb +7 -0
- data/test/test_watcher1.rb +56 -0
- data/test/test_watcher2.rb +52 -0
- metadata +181 -0
data/ext/zookeeper_lib.h
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
#ifndef ZOOKEEPER_LIB_H
|
2
|
+
#define ZOOKEEPER_LIB_H
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
#include "c-client-src/zookeeper.h"
|
6
|
+
#include <errno.h>
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <stdlib.h>
|
9
|
+
|
10
|
+
#define ZK_TRUE 1
|
11
|
+
#define ZK_FALSE 0
|
12
|
+
#define ZKRB_GLOBAL_REQ -1
|
13
|
+
|
14
|
+
// (slyphon): this RC value does not conflict with any of the ZOO_ERRORS
|
15
|
+
// but need to find a better way of formalizing and defining this stuff
|
16
|
+
#define ZKRB_ERR_REQ -2
|
17
|
+
#define ZKRB_ERR_RC -15
|
18
|
+
|
19
|
+
#ifndef RSTRING_LEN
|
20
|
+
# define RSTRING_LEN(x) RSTRING(x)->len
|
21
|
+
#endif
|
22
|
+
#ifndef RSTRING_PTR
|
23
|
+
# define RSTRING_PTR(x) RSTRING(x)->ptr
|
24
|
+
#endif
|
25
|
+
#ifndef RARRAY_LEN
|
26
|
+
# define RARRAY_LEN(x) RARRAY(x)->len
|
27
|
+
#endif
|
28
|
+
|
29
|
+
extern int ZKRBDebugging;
|
30
|
+
extern pthread_mutex_t zkrb_q_mutex;
|
31
|
+
|
32
|
+
struct zkrb_data_completion {
|
33
|
+
char *data;
|
34
|
+
int data_len;
|
35
|
+
struct Stat *stat;
|
36
|
+
};
|
37
|
+
|
38
|
+
struct zkrb_stat_completion {
|
39
|
+
struct Stat *stat;
|
40
|
+
};
|
41
|
+
|
42
|
+
struct zkrb_void_completion {
|
43
|
+
};
|
44
|
+
|
45
|
+
struct zkrb_string_completion {
|
46
|
+
char *value;
|
47
|
+
};
|
48
|
+
|
49
|
+
struct zkrb_strings_completion {
|
50
|
+
struct String_vector *values;
|
51
|
+
};
|
52
|
+
|
53
|
+
struct zkrb_strings_stat_completion {
|
54
|
+
struct String_vector *values;
|
55
|
+
struct Stat *stat;
|
56
|
+
};
|
57
|
+
|
58
|
+
struct zkrb_acl_completion {
|
59
|
+
struct ACL_vector *acl;
|
60
|
+
struct Stat *stat;
|
61
|
+
};
|
62
|
+
|
63
|
+
struct zkrb_watcher_completion {
|
64
|
+
int type;
|
65
|
+
int state;
|
66
|
+
char *path;
|
67
|
+
};
|
68
|
+
|
69
|
+
typedef struct {
|
70
|
+
int64_t req_id;
|
71
|
+
int rc;
|
72
|
+
|
73
|
+
enum {
|
74
|
+
ZKRB_DATA = 0,
|
75
|
+
ZKRB_STAT = 1,
|
76
|
+
ZKRB_VOID = 2,
|
77
|
+
ZKRB_STRING = 3,
|
78
|
+
ZKRB_STRINGS = 4,
|
79
|
+
ZKRB_STRINGS_STAT = 5,
|
80
|
+
ZKRB_ACL = 6,
|
81
|
+
ZKRB_WATCHER = 7
|
82
|
+
} type;
|
83
|
+
|
84
|
+
union {
|
85
|
+
struct zkrb_data_completion *data_completion;
|
86
|
+
struct zkrb_stat_completion *stat_completion;
|
87
|
+
struct zkrb_void_completion *void_completion;
|
88
|
+
struct zkrb_string_completion *string_completion;
|
89
|
+
struct zkrb_strings_completion *strings_completion;
|
90
|
+
struct zkrb_strings_stat_completion *strings_stat_completion;
|
91
|
+
struct zkrb_acl_completion *acl_completion;
|
92
|
+
struct zkrb_watcher_completion *watcher_completion;
|
93
|
+
} completion;
|
94
|
+
} zkrb_event_t;
|
95
|
+
|
96
|
+
struct zkrb_event_ll {
|
97
|
+
zkrb_event_t *event;
|
98
|
+
struct zkrb_event_ll *next;
|
99
|
+
};
|
100
|
+
|
101
|
+
typedef struct zkrb_event_ll zkrb_event_ll_t;
|
102
|
+
|
103
|
+
typedef struct {
|
104
|
+
zkrb_event_ll_t *head;
|
105
|
+
zkrb_event_ll_t *tail;
|
106
|
+
int pipe_read;
|
107
|
+
int pipe_write;
|
108
|
+
} zkrb_queue_t;
|
109
|
+
|
110
|
+
zkrb_queue_t * zkrb_queue_alloc(void);
|
111
|
+
void zkrb_queue_free(zkrb_queue_t *queue);
|
112
|
+
zkrb_event_t * zkrb_event_alloc(void);
|
113
|
+
void zkrb_event_free(zkrb_event_t *ptr);
|
114
|
+
|
115
|
+
void zkrb_enqueue(zkrb_queue_t *queue, zkrb_event_t *elt);
|
116
|
+
zkrb_event_t * zkrb_peek(zkrb_queue_t *queue);
|
117
|
+
zkrb_event_t * zkrb_dequeue(zkrb_queue_t *queue, int need_lock);
|
118
|
+
void zkrb_signal(zkrb_queue_t *queue);
|
119
|
+
|
120
|
+
void zkrb_print_stat(const struct Stat *s);
|
121
|
+
|
122
|
+
typedef struct {
|
123
|
+
int64_t req_id;
|
124
|
+
zkrb_queue_t *queue;
|
125
|
+
} zkrb_calling_context;
|
126
|
+
|
127
|
+
void zkrb_print_calling_context(zkrb_calling_context *ctx);
|
128
|
+
zkrb_calling_context *zkrb_calling_context_alloc(int64_t req_id, zkrb_queue_t *queue);
|
129
|
+
|
130
|
+
/*
|
131
|
+
default process completions that get queued into the ruby client event queue
|
132
|
+
*/
|
133
|
+
|
134
|
+
void zkrb_state_callback(
|
135
|
+
zhandle_t *zh, int type, int state, const char *path, void *calling_ctx);
|
136
|
+
|
137
|
+
void zkrb_data_callback(
|
138
|
+
int rc, const char *value, int value_len, const struct Stat *stat, const void *calling_ctx);
|
139
|
+
|
140
|
+
void zkrb_stat_callback(
|
141
|
+
int rc, const struct Stat *stat, const void *calling_ctx);
|
142
|
+
|
143
|
+
void zkrb_string_callback(
|
144
|
+
int rc, const char *string, const void *calling_ctx);
|
145
|
+
|
146
|
+
void zkrb_strings_callback(
|
147
|
+
int rc, const struct String_vector *strings, const void *calling_ctx);
|
148
|
+
|
149
|
+
void zkrb_strings_stat_callback(
|
150
|
+
int rc, const struct String_vector *strings, const struct Stat* stat, const void *calling_ctx);
|
151
|
+
|
152
|
+
void zkrb_void_callback(
|
153
|
+
int rc, const void *calling_ctx);
|
154
|
+
|
155
|
+
void zkrb_acl_callback(
|
156
|
+
int rc, struct ACL_vector *acls, struct Stat *stat, const void *calling_ctx);
|
157
|
+
|
158
|
+
VALUE zkrb_event_to_ruby(zkrb_event_t *event);
|
159
|
+
VALUE zkrb_acl_to_ruby(struct ACL *acl);
|
160
|
+
VALUE zkrb_acl_vector_to_ruby(struct ACL_vector *acl_vector);
|
161
|
+
VALUE zkrb_id_to_ruby(struct Id *id);
|
162
|
+
VALUE zkrb_string_vector_to_ruby(struct String_vector *string_vector);
|
163
|
+
VALUE zkrb_stat_to_rarray(const struct Stat *stat);
|
164
|
+
VALUE zkrb_stat_to_rhash(const struct Stat* stat);
|
165
|
+
|
166
|
+
struct ACL_vector * zkrb_ruby_to_aclvector(VALUE acl_ary);
|
167
|
+
struct ACL_vector * zkrb_clone_acl_vector(struct ACL_vector * src);
|
168
|
+
struct String_vector * zkrb_clone_string_vector(const struct String_vector * src);
|
169
|
+
struct ACL zkrb_ruby_to_acl(VALUE rubyacl);
|
170
|
+
struct Id zkrb_ruby_to_id(VALUE rubyid);
|
171
|
+
|
172
|
+
#endif /* ZOOKEEPER_LIB_H */
|
@@ -0,0 +1,477 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'thread'
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
gem 'slyphon-log4j', '= 1.2.15'
|
6
|
+
gem 'slyphon-zookeeper_jar', '= 3.3.5'
|
7
|
+
|
8
|
+
require 'log4j'
|
9
|
+
require 'zookeeper_jar'
|
10
|
+
|
11
|
+
# The low-level wrapper-specific methods for the Java lib,
|
12
|
+
# subclassed by the top-level Zookeeper class
|
13
|
+
class ZookeeperBase
|
14
|
+
include Java
|
15
|
+
include ZookeeperCommon
|
16
|
+
include ZookeeperConstants
|
17
|
+
include ZookeeperCallbacks
|
18
|
+
include ZookeeperExceptions
|
19
|
+
include ZookeeperACLs
|
20
|
+
include ZookeeperStat
|
21
|
+
|
22
|
+
JZK = org.apache.zookeeper
|
23
|
+
JZKD = org.apache.zookeeper.data
|
24
|
+
Code = JZK::KeeperException::Code
|
25
|
+
|
26
|
+
ANY_VERSION = -1
|
27
|
+
DEFAULT_SESSION_TIMEOUT = 10_000
|
28
|
+
|
29
|
+
ZKRB_GLOBAL_CB_REQ = -1 unless defined?(ZKRB_GLOBAL_CB_REQ)
|
30
|
+
|
31
|
+
JZKD::Stat.class_eval do
|
32
|
+
MEMBERS = [:version, :czxid, :mzxid, :ctime, :mtime, :cversion, :aversion, :ephemeralOwner, :dataLength, :numChildren, :pzxid]
|
33
|
+
def to_hash
|
34
|
+
MEMBERS.inject({}) { |h,k| h[k] = __send__(k); h }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
JZKD::Id.class_eval do
|
39
|
+
def to_hash
|
40
|
+
{ :scheme => getScheme, :id => getId }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
JZKD::ACL.class_eval do
|
45
|
+
def self.from_ruby_acl(acl)
|
46
|
+
raise TypeError, "acl must be a ZookeeperACLs::ACL not #{acl.inspect}" unless acl.kind_of?(ZookeeperACLs::ACL)
|
47
|
+
id = org.apache.zookeeper.data.Id.new(acl.id.scheme.to_s, acl.id.id.to_s)
|
48
|
+
new(acl.perms.to_i, id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_hash
|
52
|
+
{ :perms => getPerms, :id => getId.to_hash }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
JZK::WatchedEvent.class_eval do
|
57
|
+
def to_hash
|
58
|
+
{ :type => getType.getIntValue, :state => getState.getIntValue, :path => getPath }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# used for internal dispatching
|
63
|
+
module JavaCB #:nodoc:
|
64
|
+
class Callback
|
65
|
+
attr_reader :req_id
|
66
|
+
|
67
|
+
def initialize(req_id)
|
68
|
+
@req_id = req_id
|
69
|
+
end
|
70
|
+
|
71
|
+
protected
|
72
|
+
def logger
|
73
|
+
Zookeeper.logger
|
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
|
+
|
159
|
+
def initialize(event_queue)
|
160
|
+
@event_queue = event_queue
|
161
|
+
super(ZookeeperBase::ZKRB_GLOBAL_CB_REQ)
|
162
|
+
end
|
163
|
+
|
164
|
+
def process(event)
|
165
|
+
logger.debug { "WatcherCallback got event: #{event.to_hash.inspect}" }
|
166
|
+
hash = event.to_hash.merge(:req_id => req_id)
|
167
|
+
@event_queue.push(hash)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
attr_reader :event_queue
|
173
|
+
|
174
|
+
def reopen(timeout=10, watcher=nil)
|
175
|
+
# watcher ||= @default_watcher
|
176
|
+
|
177
|
+
@mutex.synchronize do
|
178
|
+
# flushes all outstanding watcher reqs.
|
179
|
+
@watcher_reqs.clear
|
180
|
+
set_default_global_watcher
|
181
|
+
|
182
|
+
replace_jzk!
|
183
|
+
wait_until_connected
|
184
|
+
end
|
185
|
+
|
186
|
+
state
|
187
|
+
end
|
188
|
+
|
189
|
+
def wait_until_connected(timeout=10)
|
190
|
+
time_to_stop = timeout ? (Time.now + timeout) : nil
|
191
|
+
|
192
|
+
until connected? or (time_to_stop and Time.now > time_to_stop)
|
193
|
+
Thread.pass
|
194
|
+
end
|
195
|
+
|
196
|
+
connected?
|
197
|
+
end
|
198
|
+
|
199
|
+
def initialize(host, timeout=10, watcher=nil, options={})
|
200
|
+
@host = host
|
201
|
+
@event_queue = QueueWithPipe.new
|
202
|
+
@current_req_id = 0
|
203
|
+
|
204
|
+
@mutex = Monitor.new
|
205
|
+
@dispatch_shutdown_cond = @mutex.new_cond
|
206
|
+
|
207
|
+
@watcher_reqs = {}
|
208
|
+
@completion_reqs = {}
|
209
|
+
@_running = nil
|
210
|
+
@_closed = false
|
211
|
+
@options = {}
|
212
|
+
|
213
|
+
@default_watcher = (watcher || get_default_global_watcher)
|
214
|
+
|
215
|
+
# allows connected-state handlers to be registered before
|
216
|
+
yield self if block_given?
|
217
|
+
|
218
|
+
reopen(timeout)
|
219
|
+
return nil unless connected?
|
220
|
+
@_running = true
|
221
|
+
setup_dispatch_thread!
|
222
|
+
end
|
223
|
+
|
224
|
+
def close
|
225
|
+
shutdown_thread = Thread.new do
|
226
|
+
@mutex.synchronize do
|
227
|
+
unless @_closed
|
228
|
+
@_closed = true # these are probably unnecessary
|
229
|
+
@_running = false
|
230
|
+
|
231
|
+
stop_dispatch_thread!
|
232
|
+
@jzk.close if @jzk
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
shutdown_thread.join unless event_dispatch_thread?
|
238
|
+
end
|
239
|
+
|
240
|
+
def state
|
241
|
+
@mutex.synchronize { @jzk.state }
|
242
|
+
end
|
243
|
+
|
244
|
+
def connected?
|
245
|
+
state == JZK::ZooKeeper::States::CONNECTED
|
246
|
+
end
|
247
|
+
|
248
|
+
def connecting?
|
249
|
+
state == JZK::ZooKeeper::States::CONNECTING
|
250
|
+
end
|
251
|
+
|
252
|
+
def associating?
|
253
|
+
state == JZK::ZooKeeper::States::ASSOCIATING
|
254
|
+
end
|
255
|
+
|
256
|
+
def running?
|
257
|
+
@_running
|
258
|
+
end
|
259
|
+
|
260
|
+
def closed?
|
261
|
+
@_closed
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.set_debug_level(*a)
|
265
|
+
# IGNORED IN JRUBY
|
266
|
+
end
|
267
|
+
|
268
|
+
def set_debug_level(*a)
|
269
|
+
# IGNORED IN JRUBY
|
270
|
+
end
|
271
|
+
|
272
|
+
def get(req_id, path, callback, watcher)
|
273
|
+
handle_keeper_exception do
|
274
|
+
watch_cb = watcher ? create_watcher(req_id, path) : false
|
275
|
+
|
276
|
+
if callback
|
277
|
+
jzk.getData(path, watch_cb, JavaCB::DataCallback.new(req_id), event_queue)
|
278
|
+
[Code::Ok, nil, nil] # the 'nil, nil' isn't strictly necessary here
|
279
|
+
else # sync
|
280
|
+
stat = JZKD::Stat.new
|
281
|
+
data = String.from_java_bytes(jzk.getData(path, watch_cb, stat))
|
282
|
+
|
283
|
+
[Code::Ok, data, stat.to_hash]
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def set(req_id, path, data, callback, version)
|
289
|
+
handle_keeper_exception do
|
290
|
+
version ||= ANY_VERSION
|
291
|
+
|
292
|
+
if callback
|
293
|
+
jzk.setData(path, data.to_java_bytes, version, JavaCB::StatCallback.new(req_id), event_queue)
|
294
|
+
[Code::Ok, nil]
|
295
|
+
else
|
296
|
+
stat = jzk.setData(path, data.to_java_bytes, version).to_hash
|
297
|
+
[Code::Ok, stat]
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def get_children(req_id, path, callback, watcher)
|
303
|
+
handle_keeper_exception do
|
304
|
+
watch_cb = watcher ? create_watcher(req_id, path) : false
|
305
|
+
|
306
|
+
if callback
|
307
|
+
jzk.getChildren(path, watch_cb, JavaCB::Children2Callback.new(req_id), event_queue)
|
308
|
+
[Code::Ok, nil, nil]
|
309
|
+
else
|
310
|
+
stat = JZKD::Stat.new
|
311
|
+
children = jzk.getChildren(path, watch_cb, stat)
|
312
|
+
[Code::Ok, children.to_a, stat.to_hash]
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def create(req_id, path, data, callback, acl, flags)
|
318
|
+
handle_keeper_exception do
|
319
|
+
acl = Array(acl).map{ |a| JZKD::ACL.from_ruby_acl(a) }
|
320
|
+
mode = JZK::CreateMode.fromFlag(flags)
|
321
|
+
|
322
|
+
data ||= ''
|
323
|
+
|
324
|
+
if callback
|
325
|
+
jzk.create(path, data.to_java_bytes, acl, mode, JavaCB::StringCallback.new(req_id), event_queue)
|
326
|
+
[Code::Ok, nil]
|
327
|
+
else
|
328
|
+
new_path = jzk.create(path, data.to_java_bytes, acl, mode)
|
329
|
+
[Code::Ok, new_path]
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def sync(req_id, path)
|
335
|
+
handle_keeper_exception do
|
336
|
+
jzk.sync(path, JavaCB::VoidCallback.new(req_id), event_queue)
|
337
|
+
Code::Ok
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def delete(req_id, path, version, callback)
|
342
|
+
handle_keeper_exception do
|
343
|
+
if callback
|
344
|
+
jzk.delete(path, version, JavaCB::VoidCallback.new(req_id), event_queue)
|
345
|
+
else
|
346
|
+
jzk.delete(path, version)
|
347
|
+
end
|
348
|
+
|
349
|
+
Code::Ok
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
def set_acl(req_id, path, acl, callback, version)
|
354
|
+
handle_keeper_exception do
|
355
|
+
logger.debug { "set_acl: acl #{acl.inspect}" }
|
356
|
+
acl = Array(acl).flatten.map { |a| JZKD::ACL.from_ruby_acl(a) }
|
357
|
+
logger.debug { "set_acl: converted #{acl.inspect}" }
|
358
|
+
|
359
|
+
if callback
|
360
|
+
jzk.setACL(path, acl, version, JavaCB::ACLCallback.new(req_id), event_queue)
|
361
|
+
else
|
362
|
+
jzk.setACL(path, acl, version)
|
363
|
+
end
|
364
|
+
|
365
|
+
Code::Ok
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def exists(req_id, path, callback, watcher)
|
370
|
+
handle_keeper_exception do
|
371
|
+
watch_cb = watcher ? create_watcher(req_id, path) : false
|
372
|
+
|
373
|
+
if callback
|
374
|
+
jzk.exists(path, watch_cb, JavaCB::StatCallback.new(req_id), event_queue)
|
375
|
+
[Code::Ok, nil, nil]
|
376
|
+
else
|
377
|
+
stat = jzk.exists(path, watch_cb)
|
378
|
+
[Code::Ok, (stat and stat.to_hash)]
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def get_acl(req_id, path, callback)
|
384
|
+
handle_keeper_exception do
|
385
|
+
stat = JZKD::Stat.new
|
386
|
+
|
387
|
+
if callback
|
388
|
+
logger.debug { "calling getACL, path: #{path.inspect}, stat: #{stat.inspect}" }
|
389
|
+
jzk.getACL(path, stat, JavaCB::ACLCallback.new(req_id), event_queue)
|
390
|
+
[Code::Ok, nil, nil]
|
391
|
+
else
|
392
|
+
acls = jzk.getACL(path, stat).map { |a| a.to_hash }
|
393
|
+
|
394
|
+
[Code::Ok, Array(acls).map{|m| m.to_hash}, stat.to_hash]
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def assert_open
|
400
|
+
# XXX don't know how to check for valid session state!
|
401
|
+
raise ZookeeperException::NotConnected unless connected?
|
402
|
+
end
|
403
|
+
|
404
|
+
# set the watcher object/proc that will receive all global events (such as session/state events)
|
405
|
+
#---
|
406
|
+
# XXX: this code needs to be duplicated from ext/zookeeper_base.rb because
|
407
|
+
# it's called from the initializer, and because of the C impl. we can't have
|
408
|
+
# the two decend from a common base, and a module wouldn't work
|
409
|
+
def set_default_global_watcher
|
410
|
+
@mutex.synchronize do
|
411
|
+
@watcher_reqs[ZKRB_GLOBAL_CB_REQ] = { :watcher => @default_watcher, :watcher_context => nil }
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
def session_id
|
416
|
+
jzk.session_id
|
417
|
+
end
|
418
|
+
|
419
|
+
def session_passwd
|
420
|
+
jzk.session_passwd.to_s
|
421
|
+
end
|
422
|
+
|
423
|
+
protected
|
424
|
+
def jzk
|
425
|
+
@mutex.synchronize { @jzk }
|
426
|
+
end
|
427
|
+
|
428
|
+
def handle_keeper_exception
|
429
|
+
yield
|
430
|
+
rescue JZK::KeeperException => e
|
431
|
+
e.cause.code.intValue
|
432
|
+
end
|
433
|
+
|
434
|
+
def call_type(callback, watcher)
|
435
|
+
if callback
|
436
|
+
watcher ? :async_watch : :async
|
437
|
+
else
|
438
|
+
watcher ? :sync_watch : :sync
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
def create_watcher(req_id, path)
|
443
|
+
logger.debug { "creating watcher for req_id: #{req_id} path: #{path}" }
|
444
|
+
lambda do |event|
|
445
|
+
logger.debug { "watcher for req_id #{req_id}, path: #{path} called back" }
|
446
|
+
h = { :req_id => req_id, :type => event.type.int_value, :state => event.state.int_value, :path => path }
|
447
|
+
event_queue.push(h)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
# method to wait until block passed returns true or timeout (default is 10 seconds) is reached
|
452
|
+
def wait_until(timeout=10, &block)
|
453
|
+
time_to_stop = Time.now + timeout
|
454
|
+
until yield do
|
455
|
+
break if Time.now > time_to_stop
|
456
|
+
sleep 0.1
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
# TODO: Make all global puts configurable
|
461
|
+
def get_default_global_watcher
|
462
|
+
Proc.new { |args|
|
463
|
+
logger.debug { "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}" }
|
464
|
+
true
|
465
|
+
}
|
466
|
+
end
|
467
|
+
|
468
|
+
private
|
469
|
+
def replace_jzk!
|
470
|
+
orig_jzk = @jzk
|
471
|
+
@jzk = JZK::ZooKeeper.new(@host, DEFAULT_SESSION_TIMEOUT, JavaCB::WatcherCallback.new(event_queue))
|
472
|
+
ensure
|
473
|
+
orig_jzk.close if orig_jzk
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
|