zkruby 3.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/History.txt +18 -0
- data/Manifest.txt +39 -0
- data/README.rdoc +119 -0
- data/Rakefile +39 -0
- data/jute/jute.citrus +105 -0
- data/jute/lib/hoe/jute.rb +56 -0
- data/jute/lib/jute.rb +120 -0
- data/lib/em_zkruby.rb +4 -0
- data/lib/jute/zookeeper.rb +203 -0
- data/lib/zkruby.rb +4 -0
- data/lib/zkruby/bindata.rb +45 -0
- data/lib/zkruby/client.rb +608 -0
- data/lib/zkruby/enum.rb +108 -0
- data/lib/zkruby/eventmachine.rb +186 -0
- data/lib/zkruby/multi.rb +47 -0
- data/lib/zkruby/protocol.rb +182 -0
- data/lib/zkruby/rubyio.rb +310 -0
- data/lib/zkruby/session.rb +445 -0
- data/lib/zkruby/util.rb +141 -0
- data/lib/zkruby/zkruby.rb +27 -0
- data/spec/bindata_spec.rb +51 -0
- data/spec/enum_spec.rb +84 -0
- data/spec/eventmachine_spec.rb +50 -0
- data/spec/multi_spec.rb +93 -0
- data/spec/protocol_spec.rb +72 -0
- data/spec/recipe_helper.rb +68 -0
- data/spec/rubyio_spec.rb +8 -0
- data/spec/sequences_spec.rb +19 -0
- data/spec/server_helper.rb +45 -0
- data/spec/shared/auth.rb +40 -0
- data/spec/shared/basic.rb +180 -0
- data/spec/shared/binding.rb +33 -0
- data/spec/shared/chroot.rb +61 -0
- data/spec/shared/multi.rb +38 -0
- data/spec/shared/util.rb +56 -0
- data/spec/shared/watch.rb +49 -0
- data/spec/spec_helper.rb +12 -0
- data/src/jute/zookeeper.jute +288 -0
- data/yard_ext/enum_handler.rb +16 -0
- metadata +243 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
shared_examples_for "chrooted connection" do
|
2
|
+
describe "chrooted connection" do
|
3
|
+
|
4
|
+
around(:each) do |example|
|
5
|
+
@zk = connect(:binding => binding)
|
6
|
+
@ch_zk = connect(:binding => binding, :chroot => "/zkruby")
|
7
|
+
|
8
|
+
example.run
|
9
|
+
|
10
|
+
safe_close(@zk)
|
11
|
+
safe_close(@ch_zk)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should perform all the ZooKeeper CRUD chrooted" do
|
15
|
+
path = @ch_zk.create("/spec-chroot","someData",ZK::ACL_OPEN_UNSAFE,:ephemeral)
|
16
|
+
path.should == "/spec-chroot"
|
17
|
+
real_path = "/zkruby#{path}"
|
18
|
+
stat,data = @ch_zk.get(path)
|
19
|
+
stat.should be_a ZooKeeper::Data::Stat
|
20
|
+
data.should == "someData"
|
21
|
+
|
22
|
+
stat,data = @zk.get(real_path)
|
23
|
+
data.should == "someData"
|
24
|
+
|
25
|
+
new_stat = @ch_zk.set(path,"different data",stat.version)
|
26
|
+
new_stat.should be_a ZooKeeper::Data::Stat
|
27
|
+
|
28
|
+
stat,data = @ch_zk.get(path)
|
29
|
+
data.should == "different data"
|
30
|
+
|
31
|
+
stat,data = @zk.get(real_path)
|
32
|
+
data.should == "different data"
|
33
|
+
|
34
|
+
@ch_zk.delete(path,stat.version)
|
35
|
+
@ch_zk.exists?(path).should be_false
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return a client path for sync" do
|
39
|
+
path = @ch_zk.sync("/aPath")
|
40
|
+
path.should == "/aPath"
|
41
|
+
end
|
42
|
+
|
43
|
+
context "util recipes" do
|
44
|
+
|
45
|
+
it "Client#mkpath should work with chroot" do
|
46
|
+
@zk.rmpath("/zkruby/spec-util")
|
47
|
+
@ch_zk.mkpath("/spec-util/test/mkpath")
|
48
|
+
stat,data = @zk.get("/zkruby/spec-util/test")
|
49
|
+
data.should == ""
|
50
|
+
end
|
51
|
+
|
52
|
+
it "Client#rmpath should work with chroot" do
|
53
|
+
@zk.mkpath("/zkruby/spec-util/test")
|
54
|
+
@zk.mkpath("/zkruby/spec-util/test/two/three/four")
|
55
|
+
@ch_zk.rmpath("/spec-util")
|
56
|
+
@zk.exists?("/zkruby/spec-util").should be_false
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
shared_examples_for "multi" do
|
2
|
+
|
3
|
+
context "only in 3.4 and up", :multi => true do
|
4
|
+
it "should do a create in a multi-op" do
|
5
|
+
delete_path = @zk.create("/zkruby/multi","hello multi",ZK::ACL_OPEN_UNSAFE,:ephemeral,:sequential)
|
6
|
+
|
7
|
+
new_path = nil
|
8
|
+
stat,data = @zk.get("/zkruby")
|
9
|
+
@zk.transaction() do |txn|
|
10
|
+
txn.create("/zkruby/multi","hello world", ZK::ACL_OPEN_UNSAFE,:ephemeral,:sequential) { |path| logger.debug{ "New path #{path}"} ; new_path = path }
|
11
|
+
txn.check("/zkruby",stat.version)
|
12
|
+
txn.set("/zkruby","new multi data",-1)
|
13
|
+
txn.delete(delete_path,-1)
|
14
|
+
end
|
15
|
+
|
16
|
+
new_path.should_not be_nil
|
17
|
+
|
18
|
+
stat, data = @zk.get(new_path)
|
19
|
+
data.should == "hello world"
|
20
|
+
|
21
|
+
stat, data = @zk.get("/zkruby")
|
22
|
+
data.should == "new multi data"
|
23
|
+
|
24
|
+
@zk.exists?(delete_path).should be_nil
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should raise exceptions if the multi op fails" do
|
29
|
+
lambda { @zk.transaction() do |txn|
|
30
|
+
txn.create("/multi","hello world", ZK::ACL_OPEN_UNSAFE,:ephemeral,:sequential) { |path| puts path }
|
31
|
+
txn.create("/multi/something/","hello world", ZK::ACL_OPEN_UNSAFE,:ephemeral,:sequential) { |path| puts path }
|
32
|
+
txn.create("/multi","hello world 2", ZK::ACL_OPEN_UNSAFE,:ephemeral,:sequential) { |path| puts path }
|
33
|
+
end }.should raise_error(ZooKeeper::Error)
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/spec/shared/util.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
shared_examples_for "util recipes" do
|
2
|
+
context "util recipes" do
|
3
|
+
context "Client#mkpath" do
|
4
|
+
#you'll note that these tests rely on each other!
|
5
|
+
before(:each) do
|
6
|
+
@zk.rmpath("/zkruby/spec-util")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should create empty nodes at all the intermediate paths" do
|
10
|
+
@zk.mkpath("/zkruby/spec-util/test/mkpath")
|
11
|
+
stat,data = @zk.get("/zkruby/spec-util/test")
|
12
|
+
data.should == ""
|
13
|
+
stat,data = @zk.get("/zkruby/spec-util/test/mkpath")
|
14
|
+
data.should == ""
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should not raise errors when path already exists" do
|
18
|
+
@zk.mkpath("/zkruby")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should only create the final path if all parents exist" do
|
22
|
+
@zk.create("/zkruby/spec-util","node that exists",ZK::ACL_OPEN_UNSAFE)
|
23
|
+
@zk.mkpath("/zkruby/spec-util/mkpath")
|
24
|
+
stat, data = @zk.get("/zkruby/spec-util")
|
25
|
+
data.should == "node that exists"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not raise error if something else creates an intermediate path"
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context "Client#rmpath" do
|
34
|
+
before(:each) do
|
35
|
+
@zk.mkpath("/zkruby/spec_util/one")
|
36
|
+
@zk.mkpath("/zkruby/spec_util/two/twopointtwo")
|
37
|
+
@zk.mkpath("/zkruby/spec_util/two/three/four/five")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should delete a tree of paths" do
|
41
|
+
@zk.rmpath("/zkruby/spec_util")
|
42
|
+
@zk.exists?("/zkruby/spec_util").should be_false
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not raise errors if the path is already deleted"
|
46
|
+
it "should delete leaf nodes just like delete does" do
|
47
|
+
@zk.rmpath("/zkruby/spec_util/one")
|
48
|
+
@zk.exists?("/zkruby/spec_util/one").should be_false
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
it "should not raise errors if some nodes are deleted by something else during processing"
|
53
|
+
it "should fight to the death if something else is creating subnodes"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
shared_examples_for "watches" do
|
2
|
+
describe "watches" do
|
3
|
+
around(:each) do |example|
|
4
|
+
@zk = connect(:binding => binding)
|
5
|
+
@zk2 = connect(:binding => binding)
|
6
|
+
|
7
|
+
example.run
|
8
|
+
|
9
|
+
safe_close(@zk)
|
10
|
+
safe_close(@zk2)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should handle data watches" do
|
14
|
+
path = @zk.create("/zkruby/rspec_watch","somedata",ZK::ACL_OPEN_UNSAFE,:ephemeral,:sequential)
|
15
|
+
watch_results = []
|
16
|
+
watch = lambda { |state,path,event| watch_results << [ state,path,event ] }
|
17
|
+
|
18
|
+
stat,data = @zk.get(path,watch)
|
19
|
+
# set the data on the 2nd session
|
20
|
+
@zk2.set(path,"newdata",stat.version)
|
21
|
+
sleep(5)
|
22
|
+
watch_results.size().should == 1
|
23
|
+
watch_results[0][1].should == path
|
24
|
+
watch_results[0][2].should === :node_data_changed
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should handle exists watches"
|
28
|
+
it "should handle child watches" do
|
29
|
+
watch_results = []
|
30
|
+
watch = lambda { |state,path,event| watch_results << [ state,path,event ] }
|
31
|
+
|
32
|
+
stat,children = @zk.children("/zkruby",watch)
|
33
|
+
path = @zk2.create("/zkruby/rspec_watch","somedata",ZK::ACL_OPEN_UNSAFE,:ephemeral,:sequential)
|
34
|
+
sleep(5)
|
35
|
+
watch_results.size().should == 1
|
36
|
+
watch_results[0][1].should == "/zkruby"
|
37
|
+
watch_results[0][2].should === :node_children_changed
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should reset watches over socket disconnects"
|
42
|
+
it "should not send :connection_lost to watches on disconnect if so configured"
|
43
|
+
|
44
|
+
describe :close do
|
45
|
+
it "should send :session_expired to the default watcher on close"
|
46
|
+
it "should send :Session_expired to all watchers on close"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'slf4r/logging_logger'
|
2
|
+
require 'zkruby/zkruby'
|
3
|
+
|
4
|
+
Logging.logger.root.level = :error
|
5
|
+
Logging.logger.root.appenders = Logging.appenders.stdout(:layout => Logging.layouts.pattern(:pattern => '%c [%T] %-5l: %m\n'))
|
6
|
+
#Logging.logger[ZooKeeper::RubyIO::Connection].level = :error
|
7
|
+
#Logging.logger[ZooKeeper::RubyIO::Binding].level = :error
|
8
|
+
#Logging.logger[ZooKeeper::Session].level = :debug
|
9
|
+
#Logging.logger["ZooKeeper::EventMachine::ClientConn"].level = :debug
|
10
|
+
#Logging.logger["ZooKeeper::Session::Ping"].level = :error
|
11
|
+
|
12
|
+
Thread.current[:name] = "Rspec::Main"
|
@@ -0,0 +1,288 @@
|
|
1
|
+
/**
|
2
|
+
* Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
4
|
+
* distributed with this work for additional information
|
5
|
+
* regarding copyright ownership. The ASF licenses this file
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
7
|
+
* "License"); you may not use this file except in compliance
|
8
|
+
* with the License. You may obtain a copy of the License at
|
9
|
+
*
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
*
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
* See the License for the specific language governing permissions and
|
16
|
+
* limitations under the License.
|
17
|
+
*/
|
18
|
+
|
19
|
+
module org.apache.zookeeper.data {
|
20
|
+
class Id {
|
21
|
+
ustring scheme;
|
22
|
+
ustring id;
|
23
|
+
}
|
24
|
+
class ACL {
|
25
|
+
int perms;
|
26
|
+
Id id;
|
27
|
+
}
|
28
|
+
// information shared with the client
|
29
|
+
class Stat {
|
30
|
+
long czxid; // created zxid
|
31
|
+
long mzxid; // last modified zxid
|
32
|
+
long ctime; // created
|
33
|
+
long mtime; // last modified
|
34
|
+
int version; // version
|
35
|
+
int cversion; // child version
|
36
|
+
int aversion; // acl version
|
37
|
+
long ephemeralOwner; // owner id if ephemeral, 0 otw
|
38
|
+
int dataLength; //length of the data in the node
|
39
|
+
int numChildren; //number of children of this node
|
40
|
+
long pzxid; // last modified children
|
41
|
+
}
|
42
|
+
// information explicitly stored by the server persistently
|
43
|
+
class StatPersisted {
|
44
|
+
long czxid; // created zxid
|
45
|
+
long mzxid; // last modified zxid
|
46
|
+
long ctime; // created
|
47
|
+
long mtime; // last modified
|
48
|
+
int version; // version
|
49
|
+
int cversion; // child version
|
50
|
+
int aversion; // acl version
|
51
|
+
long ephemeralOwner; // owner id if ephemeral, 0 otw
|
52
|
+
long pzxid; // last modified children
|
53
|
+
}
|
54
|
+
|
55
|
+
// information explicitly stored by the version 1 database of servers
|
56
|
+
class StatPersistedV1 {
|
57
|
+
long czxid; //created zxid
|
58
|
+
long mzxid; //last modified zxid
|
59
|
+
long ctime; //created
|
60
|
+
long mtime; //last modified
|
61
|
+
int version; //version
|
62
|
+
int cversion; //child version
|
63
|
+
int aversion; //acl version
|
64
|
+
long ephemeralOwner; //owner id if ephemeral. 0 otw
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
module org.apache.zookeeper.proto {
|
69
|
+
class ConnectRequest {
|
70
|
+
int protocolVersion;
|
71
|
+
long lastZxidSeen;
|
72
|
+
int timeOut;
|
73
|
+
long sessionId;
|
74
|
+
buffer passwd;
|
75
|
+
}
|
76
|
+
class ConnectResponse {
|
77
|
+
int protocolVersion;
|
78
|
+
int timeOut;
|
79
|
+
long sessionId;
|
80
|
+
buffer passwd;
|
81
|
+
}
|
82
|
+
class SetWatches {
|
83
|
+
long relativeZxid;
|
84
|
+
vector<ustring>dataWatches;
|
85
|
+
vector<ustring>existWatches;
|
86
|
+
vector<ustring>childWatches;
|
87
|
+
}
|
88
|
+
class RequestHeader {
|
89
|
+
int xid;
|
90
|
+
int type;
|
91
|
+
}
|
92
|
+
class MultiHeader {
|
93
|
+
int type;
|
94
|
+
boolean done;
|
95
|
+
int err;
|
96
|
+
}
|
97
|
+
class AuthPacket {
|
98
|
+
int type;
|
99
|
+
ustring scheme;
|
100
|
+
buffer auth;
|
101
|
+
}
|
102
|
+
class ReplyHeader {
|
103
|
+
int xid;
|
104
|
+
long zxid;
|
105
|
+
int err;
|
106
|
+
}
|
107
|
+
class GetDataRequest {
|
108
|
+
ustring path;
|
109
|
+
boolean watch;
|
110
|
+
}
|
111
|
+
class SetDataRequest {
|
112
|
+
ustring path;
|
113
|
+
buffer data;
|
114
|
+
int version;
|
115
|
+
}
|
116
|
+
class SetDataResponse {
|
117
|
+
org.apache.zookeeper.data.Stat stat;
|
118
|
+
}
|
119
|
+
class GetSASLRequest {
|
120
|
+
buffer token;
|
121
|
+
}
|
122
|
+
class SetSASLRequest {
|
123
|
+
buffer token;
|
124
|
+
}
|
125
|
+
class SetSASLResponse {
|
126
|
+
buffer token;
|
127
|
+
}
|
128
|
+
class CreateRequest {
|
129
|
+
ustring path;
|
130
|
+
buffer data;
|
131
|
+
vector<org.apache.zookeeper.data.ACL> acl;
|
132
|
+
int flags;
|
133
|
+
}
|
134
|
+
class DeleteRequest {
|
135
|
+
ustring path;
|
136
|
+
int version;
|
137
|
+
}
|
138
|
+
class GetChildrenRequest {
|
139
|
+
ustring path;
|
140
|
+
boolean watch;
|
141
|
+
}
|
142
|
+
class GetChildren2Request {
|
143
|
+
ustring path;
|
144
|
+
boolean watch;
|
145
|
+
}
|
146
|
+
class CheckVersionRequest {
|
147
|
+
ustring path;
|
148
|
+
int version;
|
149
|
+
}
|
150
|
+
class GetMaxChildrenRequest {
|
151
|
+
ustring path;
|
152
|
+
}
|
153
|
+
class GetMaxChildrenResponse {
|
154
|
+
int max;
|
155
|
+
}
|
156
|
+
class SetMaxChildrenRequest {
|
157
|
+
ustring path;
|
158
|
+
int max;
|
159
|
+
}
|
160
|
+
class SyncRequest {
|
161
|
+
ustring path;
|
162
|
+
}
|
163
|
+
class SyncResponse {
|
164
|
+
ustring path;
|
165
|
+
}
|
166
|
+
class GetACLRequest {
|
167
|
+
ustring path;
|
168
|
+
}
|
169
|
+
class SetACLRequest {
|
170
|
+
ustring path;
|
171
|
+
vector<org.apache.zookeeper.data.ACL> acl;
|
172
|
+
int version;
|
173
|
+
}
|
174
|
+
class SetACLResponse {
|
175
|
+
org.apache.zookeeper.data.Stat stat;
|
176
|
+
}
|
177
|
+
class WatcherEvent {
|
178
|
+
int type; // event type
|
179
|
+
int state; // state of the Keeper client runtime
|
180
|
+
ustring path;
|
181
|
+
}
|
182
|
+
class ErrorResponse {
|
183
|
+
int err;
|
184
|
+
}
|
185
|
+
class CreateResponse {
|
186
|
+
ustring path;
|
187
|
+
}
|
188
|
+
class ExistsRequest {
|
189
|
+
ustring path;
|
190
|
+
boolean watch;
|
191
|
+
}
|
192
|
+
class ExistsResponse {
|
193
|
+
org.apache.zookeeper.data.Stat stat;
|
194
|
+
}
|
195
|
+
class GetDataResponse {
|
196
|
+
buffer data;
|
197
|
+
org.apache.zookeeper.data.Stat stat;
|
198
|
+
}
|
199
|
+
class GetChildrenResponse {
|
200
|
+
vector<ustring> children;
|
201
|
+
}
|
202
|
+
class GetChildren2Response {
|
203
|
+
vector<ustring> children;
|
204
|
+
org.apache.zookeeper.data.Stat stat;
|
205
|
+
}
|
206
|
+
class GetACLResponse {
|
207
|
+
vector<org.apache.zookeeper.data.ACL> acl;
|
208
|
+
org.apache.zookeeper.data.Stat stat;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
module org.apache.zookeeper.server.quorum {
|
213
|
+
class LearnerInfo {
|
214
|
+
long serverid;
|
215
|
+
int protocolVersion;
|
216
|
+
}
|
217
|
+
class QuorumPacket {
|
218
|
+
int type; // Request, Ack, Commit, Ping
|
219
|
+
long zxid;
|
220
|
+
buffer data; // Only significant when type is request
|
221
|
+
vector<org.apache.zookeeper.data.Id> authinfo;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
module org.apache.zookeeper.server.persistence {
|
226
|
+
class FileHeader {
|
227
|
+
int magic;
|
228
|
+
int version;
|
229
|
+
long dbid;
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
module org.apache.zookeeper.txn {
|
234
|
+
class TxnHeader {
|
235
|
+
long clientId;
|
236
|
+
int cxid;
|
237
|
+
long zxid;
|
238
|
+
long time;
|
239
|
+
int type;
|
240
|
+
}
|
241
|
+
class CreateTxnV0 {
|
242
|
+
ustring path;
|
243
|
+
buffer data;
|
244
|
+
vector<org.apache.zookeeper.data.ACL> acl;
|
245
|
+
boolean ephemeral;
|
246
|
+
}
|
247
|
+
class CreateTxn {
|
248
|
+
ustring path;
|
249
|
+
buffer data;
|
250
|
+
vector<org.apache.zookeeper.data.ACL> acl;
|
251
|
+
boolean ephemeral;
|
252
|
+
int parentCVersion;
|
253
|
+
}
|
254
|
+
class DeleteTxn {
|
255
|
+
ustring path;
|
256
|
+
}
|
257
|
+
class SetDataTxn {
|
258
|
+
ustring path;
|
259
|
+
buffer data;
|
260
|
+
int version;
|
261
|
+
}
|
262
|
+
class CheckVersionTxn {
|
263
|
+
ustring path;
|
264
|
+
int version;
|
265
|
+
}
|
266
|
+
class SetACLTxn {
|
267
|
+
ustring path;
|
268
|
+
vector<org.apache.zookeeper.data.ACL> acl;
|
269
|
+
int version;
|
270
|
+
}
|
271
|
+
class SetMaxChildrenTxn {
|
272
|
+
ustring path;
|
273
|
+
int max;
|
274
|
+
}
|
275
|
+
class CreateSessionTxn {
|
276
|
+
int timeOut;
|
277
|
+
}
|
278
|
+
class ErrorTxn {
|
279
|
+
int err;
|
280
|
+
}
|
281
|
+
class Txn {
|
282
|
+
int type;
|
283
|
+
buffer data;
|
284
|
+
}
|
285
|
+
class MultiTxn {
|
286
|
+
vector<org.apache.zookeeper.txn.Txn> txns;
|
287
|
+
}
|
288
|
+
}
|