blob: 9787fe51bbe0c092e7ef809dd9bd6f0a498f638b [file] [log] [blame]
yoshi28bac132014-01-22 11:00:17 -08001/* Copyright (c) 2013 Stanford University
2 *
3 * Permission to use, copy, modify, and distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16package edu.stanford.ramcloud;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080017import java.nio.charset.StandardCharsets;
Yoshi Muroi2c170602014-02-15 08:31:28 -080018import java.util.Arrays;
Yoshi Muroie7693b12014-02-19 19:41:17 -080019import java.util.LinkedList;
yoshi28bac132014-01-22 11:00:17 -080020
Yuta HIGUCHIceb99bd2014-04-19 11:55:12 -070021import org.slf4j.Logger;
22import org.slf4j.LoggerFactory;
23
yoshi28bac132014-01-22 11:00:17 -080024/*
25 * This class provides Java bindings for RAMCloud. Right now it is a rather
26 * simple subset of what RamCloud.h defines.
27 *
28 * Running ``javah'' on this file will generate a C header file with the
29 * appropriate JNI function definitions. The glue interfacing to the C++
30 * RAMCloud library can be found in JRamCloud.cc.
31 *
32 * For JNI information, the IBM tutorials and Android developer docs are much
33 * better than Sun's at giving an overall intro:
34 * http://www.ibm.com/developerworks/java/tutorials/j-jni/section4.html
35 * http://developer.android.com/training/articles/perf-jni.html
36 */
37public class JRamCloud {
Yuta HIGUCHIceb99bd2014-04-19 11:55:12 -070038 private static final Logger log = LoggerFactory.getLogger(JRamCloud.class);
39
yoshi28bac132014-01-22 11:00:17 -080040 static {
Yuta HIGUCHIceb99bd2014-04-19 11:55:12 -070041 try {
42 System.loadLibrary("edu_stanford_ramcloud_JRamCloud");
43 } catch (UnsatisfiedLinkError e) {
44 System.err.println("Unable to load JNI binding. Please build RAMCloud Java bindings.");
45 log.error("Unable to load JNI binding. Please build RAMCloud Java bindings.", e);
46 System.exit(-1);
47 }
yoshi28bac132014-01-22 11:00:17 -080048 }
49
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080050 public static final long VERSION_NONEXISTENT = 0L;
51
yoshi28bac132014-01-22 11:00:17 -080052 /// Pointer to the underlying C++ RAMCloud object associated with this
53 /// object.
54 private long ramcloudObjectPointer = 0;
55
56 /**
57 * See src/RejectRules.h.
58 */
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080059 public static class RejectRules {
60 // these needs to be in sync with JNI code;
61 public static final int DoesntExist = 1;
62 public static final int Exists = 1 << 1;
63 public static final int VersionLeGiven = 1 << 2;
64 public static final int VersionNeGiven = 1 << 3;
65
66 protected long givenVersion;
67 protected int flags;
yoshi28bac132014-01-22 11:00:17 -080068
69 public RejectRules() {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080070 clear();
yoshi28bac132014-01-22 11:00:17 -080071 }
72
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080073 public void clear() {
74 this.givenVersion = VERSION_NONEXISTENT;
75 this.flags = 0x0;
76 }
77
78 public RejectRules set(int flags, long version) {
79 this.flags = flags;
80 this.givenVersion = version;
81 return this;
82 }
83
84 public RejectRules set(int flags) {
85 return set(flags,VERSION_NONEXISTENT);
86 }
87
88 public RejectRules rejectIfLeVersion(long version) {
yoshi28bac132014-01-22 11:00:17 -080089 setVersion(version);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080090 this.flags |= VersionLeGiven;
91 return this;
yoshi28bac132014-01-22 11:00:17 -080092 }
93
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080094 public RejectRules rejectIfExists() {
95 this.flags |= Exists;
96 return this;
yoshi28bac132014-01-22 11:00:17 -080097 }
98
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080099 public RejectRules rejectIfDoesntExists() {
100 this.flags |= DoesntExist;
101 return this;
yoshi28bac132014-01-22 11:00:17 -0800102 }
103
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800104 public RejectRules rejectIfNeVersion(long version) {
yoshi28bac132014-01-22 11:00:17 -0800105 setVersion(version);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800106 this.flags |= VersionNeGiven;
107 return this;
yoshi28bac132014-01-22 11:00:17 -0800108 }
109
110 private void setVersion(long version) {
111 this.givenVersion = version;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800112 }
yoshi28bac132014-01-22 11:00:17 -0800113 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800114
Yoshi Muroie7693b12014-02-19 19:41:17 -0800115 public static class MultiReadObject {
116 public long[] tableId;
117 public byte[] key[];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800118 public short[] keyLength;
119
Yoshi Muroie7693b12014-02-19 19:41:17 -0800120 public MultiReadObject(int size){
121 this.tableId = new long[size];
122 this.key = new byte[size][];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800123 this.keyLength = new short[size];
yoshi28bac132014-01-22 11:00:17 -0800124 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800125
Ray Milkey269ffb92014-04-03 14:43:30 -0700126 public void setObject(int num, long tableId, byte key[]){
Yoshi Muroie7693b12014-02-19 19:41:17 -0800127 this.tableId[num] = tableId;
128 this.key[num] = key;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800129 this.keyLength[num] = (short) this.key[num].length;
Ray Milkey269ffb92014-04-03 14:43:30 -0700130 }
yoshi28bac132014-01-22 11:00:17 -0800131 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800132
yoshi28bac132014-01-22 11:00:17 -0800133 public static class MultiWriteObject {
Yoshi Muroie7693b12014-02-19 19:41:17 -0800134 public long[] tableId;
135 public byte[] key[];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800136 public short[] keyLength;
Yoshi Muroie7693b12014-02-19 19:41:17 -0800137 public byte[] value[];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800138 public int[] valueLength;
Yoshi Muroie7693b12014-02-19 19:41:17 -0800139 public RejectRules[] rules;
yoshi28bac132014-01-22 11:00:17 -0800140
Yoshi Muroie7693b12014-02-19 19:41:17 -0800141 public MultiWriteObject(int size) {
142 this.tableId = new long[size];
143 this.key = new byte[size][];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800144 this.keyLength = new short[size];
Yoshi Muroie7693b12014-02-19 19:41:17 -0800145 this.value = new byte[size][];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800146 this.valueLength = new int[size];
Yoshi Muroie7693b12014-02-19 19:41:17 -0800147 this.rules = new RejectRules[size];
yoshi28bac132014-01-22 11:00:17 -0800148 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800149
Ray Milkey269ffb92014-04-03 14:43:30 -0700150 public void setObject(int num, long tableId, byte key[], byte value[], RejectRules rules){
151 this.tableId[num] = tableId;
152 this.key[num] = key;
153 this.keyLength[num] = (short) key.length;
154 this.value[num] = value;
155 this.valueLength[num] = value.length;
156 this.rules[num] = rules;
157 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800158
yoshi28bac132014-01-22 11:00:17 -0800159 }
160
Yoshi Muroie7693b12014-02-19 19:41:17 -0800161 public static class MultiWriteRspObject {
yoshi28bac132014-01-22 11:00:17 -0800162 private int status;
163 private long version;
164
165 public MultiWriteRspObject(int status, long version) {
166 this.status = status;
167 this.version = version;
168 }
169 public int getStatus() {
170 return status;
171 }
172
173 public long getVersion() {
174 return version;
175 }
176 }
177
178 /**
179 * This class is returned by Read operations. It encapsulates the entire
180 * object, including the key, value, and version.
181 *
182 * It mostly exists because Java doesn't support primitive out parameters
183 * or multiple return values, and we don't know the object's size ahead of
184 * time, so passing in a fixed-length array would be problematic.
185 */
Yoshi Muroie7693b12014-02-19 19:41:17 -0800186 public static class Object {
yoshi28bac132014-01-22 11:00:17 -0800187 Object(byte[] _key, byte[] _value, long _version)
188 {
189 key = _key;
190 value = _value;
191 version = _version;
192 }
193
194 public String
195 getKey()
196 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800197 return new String(key,StandardCharsets.UTF_8);
yoshi28bac132014-01-22 11:00:17 -0800198 }
199
200 public String
201 getValue()
202 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800203 return new String(value,StandardCharsets.UTF_8);
yoshi28bac132014-01-22 11:00:17 -0800204 }
205
206 final public byte[] key;
207 final public byte[] value;
208 final public long version;
209 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800210
Yoshi Muroie7693b12014-02-19 19:41:17 -0800211 public static class TableEnumeratorObject {
Ray Milkey269ffb92014-04-03 14:43:30 -0700212 TableEnumeratorObject(Object[] _object, long _nextHash)
213 {
214 object = _object;
215 nextHash = _nextHash;
216 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800217
Ray Milkey269ffb92014-04-03 14:43:30 -0700218 final public Object[] object;
219 final public long nextHash;
Yoshi Muroie7693b12014-02-19 19:41:17 -0800220 }
yoshi28bac132014-01-22 11:00:17 -0800221
Yuta HIGUCHIe316d5c2014-04-19 13:37:38 -0700222 @Deprecated
yoshi28bac132014-01-22 11:00:17 -0800223 public class TableEnumerator {
224 private long tableEnumeratorObjectPointer = 0;
225 private long ramCloudObjectPointer = 0;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800226
yoshi28bac132014-01-22 11:00:17 -0800227 public TableEnumerator(long tableId)
228 {
229 ramCloudObjectPointer = ramcloudObjectPointer;
230 tableEnumeratorObjectPointer = init(tableId);
231 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800232
yoshi28bac132014-01-22 11:00:17 -0800233 private native long init(long tableId);
234 public native boolean hasNext();
235 public native Object next();
236 }
237
Yoshi Muroie7693b12014-02-19 19:41:17 -0800238 public class TableEnumerator2 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800239
Ray Milkey269ffb92014-04-03 14:43:30 -0700240 protected long tableId;
241 protected LinkedList<JRamCloud.Object> rcobjs = null;
242 protected long nextHash = 0;
243 protected boolean done = false;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800244
Yoshi Muroie7693b12014-02-19 19:41:17 -0800245 public TableEnumerator2(long tableId)
246 {
Ray Milkey269ffb92014-04-03 14:43:30 -0700247 this.tableId = tableId;
248 rcobjs = new LinkedList<>();
Yoshi Muroie7693b12014-02-19 19:41:17 -0800249 }
250 public boolean hasNext() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700251 if (rcobjs.isEmpty())
252 {
253 if (done) {
254 return false;
255 }
256 JRamCloud.TableEnumeratorObject o = getTableObjects(this.tableId, this.nextHash);
257 if (o.nextHash == 0L) {
258 done = true;
259 }
260 this.nextHash = o.nextHash;
261 rcobjs.addAll(Arrays.asList(o.object));
262 if (rcobjs.isEmpty()) {
263 return false;
264 }
265 }
266 return true;
267 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800268
Ray Milkey269ffb92014-04-03 14:43:30 -0700269 public Object next()
270 {
271 return rcobjs.pop();
272 }
Yoshi Muroie7693b12014-02-19 19:41:17 -0800273 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800274
yoshi28bac132014-01-22 11:00:17 -0800275 /**
276 * Connect to the RAMCloud cluster specified by the given coordinator's
277 * service locator string. This causes the JNI code to instantiate the
278 * underlying RamCloud C++ object.
279 */
280 public
Yuta HIGUCHId150ece2014-04-29 16:25:36 -0700281 JRamCloud(String coordinatorLocator, String clusterName)
282 {
283 ramcloudObjectPointer = connect(coordinatorLocator, clusterName);
284 }
285
286 public
yoshi28bac132014-01-22 11:00:17 -0800287 JRamCloud(String coordinatorLocator)
288 {
Yuta HIGUCHId150ece2014-04-29 16:25:36 -0700289 this(coordinatorLocator, "main");
yoshi28bac132014-01-22 11:00:17 -0800290 }
291
292 /**
293 * Disconnect from the RAMCloud cluster. This causes the JNI code to
294 * destroy the underlying RamCloud C++ object.
295 */
296 public void
297 disconnect()
298 {
299 if (ramcloudObjectPointer != 0) {
300 disconnect(ramcloudObjectPointer);
301 ramcloudObjectPointer = 0;
302 }
303 }
304
305 /**
306 * This method is called by the garbage collector before destroying the
307 * object. The user really should have called disconnect, but in case
308 * they did not, be sure to clean up after them.
309 */
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800310 @Override
311 protected void
yoshi28bac132014-01-22 11:00:17 -0800312 finalize()
313 {
314 System.err.println("warning: JRamCloud::disconnect() was not called " +
315 "prior to the finalizer. You should disconnect " +
316 "your JRamCloud object when you're done with it.");
317 disconnect();
318 }
319
320 /**
321 * Convenience read() wrapper that take a String key argument.
322 */
323 public Object
324 read(long tableId, String key)
325 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800326 return read(tableId, key.getBytes(StandardCharsets.UTF_8));
yoshi28bac132014-01-22 11:00:17 -0800327 }
328
329 /**
330 * Convenience read() wrapper that take a String key argument.
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800331 * @throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800332 */
333 public Object
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800334 read(long tableId, String key, RejectRules rules) throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800335 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800336 return read(tableId, key.getBytes(StandardCharsets.UTF_8), rules);
yoshi28bac132014-01-22 11:00:17 -0800337 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800338
yoshi28bac132014-01-22 11:00:17 -0800339 /**
340 * Convenience remove() wrapper that take a String key argument.
341 */
342 public long
343 remove(long tableId, String key)
344 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800345 return remove(tableId, key.getBytes(StandardCharsets.UTF_8));
yoshi28bac132014-01-22 11:00:17 -0800346 }
347
348 /**
349 * Convenience remove() wrapper that take a String key argument.
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800350 * @throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800351 */
352 public long
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800353 remove(long tableId, String key, RejectRules rules) throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800354 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800355 return remove(tableId, key.getBytes(StandardCharsets.UTF_8), rules);
yoshi28bac132014-01-22 11:00:17 -0800356 }
357
358 /**
359 * Convenience write() wrapper that take String key and value arguments.
360 */
361 public long
362 write(long tableId, String key, String value)
363 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800364 return write(tableId, key.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8));
yoshi28bac132014-01-22 11:00:17 -0800365 }
366
367 /**
368 * Convenience write() wrapper that take String key and value arguments.
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800369 * @throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800370 */
371 public long
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800372 write(long tableId, String key, String value, RejectRules rules) throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800373 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800374 return write(tableId, key.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8), rules);
yoshi28bac132014-01-22 11:00:17 -0800375 }
376
377 /**
378 * Convenience write() wrapper that takes a String key and a byte[] value
379 * argument.
380 */
381 public long
382 write(long tableId, String key, byte[] value)
383 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800384 return write(tableId, key.getBytes(StandardCharsets.UTF_8), value);
yoshi28bac132014-01-22 11:00:17 -0800385 }
386
387 /**
388 * Convenience write() wrapper that takes a String key and a byte[] value
389 * argument.
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800390 * @throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800391 */
392 public long
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800393 write(long tableId, String key, byte[] value, RejectRules rules) throws RejectRulesException
yoshi28bac132014-01-22 11:00:17 -0800394 {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800395 return write(tableId, key.getBytes(StandardCharsets.UTF_8), value, rules);
yoshi28bac132014-01-22 11:00:17 -0800396 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800397
Yuta HIGUCHId150ece2014-04-29 16:25:36 -0700398 private static native long connect(String coordinatorLocator, String clusterName);
yoshi28bac132014-01-22 11:00:17 -0800399 private static native void disconnect(long ramcloudObjectPointer);
400
401 public native long createTable(String name);
402 public native long createTable(String name, int serverSpan);
403 public native void dropTable(String name);
404 public native long getTableId(String name);
405 public native Object read(long tableId, byte[] key);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800406 public native Object read(long tableId, byte[] key, RejectRules rules) throws RejectRulesException;
Yoshi Muroi2c170602014-02-15 08:31:28 -0800407 public native Object[] multiRead(long[] tableId, byte[] keydata[], short[] keyDataSize, int requestNum);
yoshi28bac132014-01-22 11:00:17 -0800408 public native long remove(long tableId, byte[] key);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800409 public native long remove(long tableId, byte[] key, RejectRules rules) throws RejectRulesException;
yoshi28bac132014-01-22 11:00:17 -0800410 public native long write(long tableId, byte[] key, byte[] value);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800411 public native long write(long tableId, byte[] key, byte[] value, RejectRules rules) throws RejectRulesException;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800412 public native MultiWriteRspObject[] multiWrite(long[] tableId, byte[] key[], short[] keyDataSize, byte[] value[], int[] valueDataSize, int requestNum, RejectRules[] rules);
Yoshi Muroie7693b12014-02-19 19:41:17 -0800413 public native TableEnumeratorObject getTableObjects(long tableId, long nextHash);
Yuta HIGUCHId47eac32014-04-07 13:44:47 -0700414 public native long increment(long tableId, byte[] key, long incrementValue) throws ObjectDoesntExistException;
yoshi28bac132014-01-22 11:00:17 -0800415
416 /*
417 * The following exceptions may be thrown by the JNI functions:
418 */
419
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800420 public static class TableDoesntExistException extends RuntimeException {
yoshi28bac132014-01-22 11:00:17 -0800421 public TableDoesntExistException(String message)
422 {
423 super(message);
424 }
425 }
426
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800427 public static class ObjectDoesntExistException extends RejectRulesException {
yoshi28bac132014-01-22 11:00:17 -0800428 public ObjectDoesntExistException(String message)
429 {
430 super(message);
431 }
432 }
433
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800434 public static class ObjectExistsException extends RejectRulesException {
yoshi28bac132014-01-22 11:00:17 -0800435 public ObjectExistsException(String message)
436 {
437 super(message);
438 }
439 }
440
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800441 public static class WrongVersionException extends RejectRulesException {
yoshi28bac132014-01-22 11:00:17 -0800442 public WrongVersionException(String message)
443 {
444 super(message);
445 }
446 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800447
448 public static class InvalidObjectException extends RuntimeException {
yoshi28bac132014-01-22 11:00:17 -0800449 public InvalidObjectException(String message) {
450 super(message);
451 }
452 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800453
454 public static class RejectRulesException extends Exception {
yoshi28bac132014-01-22 11:00:17 -0800455 public RejectRulesException(String message) {
456 super(message);
457 }
458 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800459
Yuta HIGUCHId150ece2014-04-29 16:25:36 -0700460 // TODO Define and support some of ClientException sub-classes.
461 public static class ClientException extends Exception {
462 public ClientException(String message) {
463 super(message);
464 }
465 }
466
Yoshi Muroie7693b12014-02-19 19:41:17 -0800467 public static void tableEnumeratorTest(JRamCloud ramcloud) {
468 long startTime = 0;
469 for (int x = 0 ; x < 2 ; x ++){
470 for(int N = 1000; N < 10000; N += 1000) {
471 long EnumerateTesttable = ramcloud.createTable("EnumerateTest");
472 for(int i = 0 ; i < N ; ++i) {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800473 String key = String.valueOf(i);
474 ramcloud.write(EnumerateTesttable, key.getBytes(StandardCharsets.UTF_8), "Hello, World!".getBytes(StandardCharsets.UTF_8));
Yoshi Muroie7693b12014-02-19 19:41:17 -0800475 }
yoshi28bac132014-01-22 11:00:17 -0800476
Yoshi Muroie7693b12014-02-19 19:41:17 -0800477 long tableIdList[] = new long[N];
478 byte[] keydata[] = new byte[N][];
479 short keydataSize[] = new short[N];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800480 startTime = System.nanoTime();
Yoshi Muroie7693b12014-02-19 19:41:17 -0800481 for (int j = 0 ; j < N ; ++j) {
482 tableIdList[j] = EnumerateTesttable;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800483 String key = String.valueOf(j);
484 keydata[j] = key.getBytes(StandardCharsets.UTF_8);
Yoshi Muroie7693b12014-02-19 19:41:17 -0800485 keydataSize[j] = (short) keydata[j].length;
486 }
487 JRamCloud.Object out[] = ramcloud.multiRead(tableIdList, keydata, keydataSize, N);
488 for (int i = 0; i < N; ++i) {
489 if(out[i].version == 0) {
490 System.out.println("Verify fail " + out[i].getKey() + " V:" + out[i].getValue());
491 }
492 }
493
494 System.out.println("multiRead : " + N + " Time : " + (System.nanoTime()-startTime));
495
496 startTime = System.nanoTime();
497 JRamCloud.TableEnumerator tableEnum = ramcloud.new TableEnumerator(EnumerateTesttable);
498 while (tableEnum.hasNext()) {
499 Object tableEntry = tableEnum.next();
500 if (tableEntry != null) {
501 System.out.println("tableEnumerator object: key = [" + tableEntry.getKey() + "], value = [" + tableEntry.getValue() + "]");
502 }
503 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800504 System.out.println("old TableEnumerator : " + N + " Time : " + (System.nanoTime()-startTime));
Yoshi Muroie7693b12014-02-19 19:41:17 -0800505
506 startTime = System.nanoTime();
507 JRamCloud.TableEnumerator2 tableEnum2 = ramcloud.new TableEnumerator2(EnumerateTesttable);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800508 while (tableEnum2.hasNext()) {
509 Object tableEntry2 = tableEnum2.next();
510 if (tableEntry2 != null) {
Yoshi Muroie7693b12014-02-19 19:41:17 -0800511 System.out.println("tableEnumerator2 object: key = [" + tableEntry2.getKey() + "], value = [" + tableEntry2.getValue() + "]");
512 }
513 }
514 System.out.println("new TableEnumerator : " + N + " Time : " + (System.nanoTime()-startTime));
515 ramcloud.dropTable("EnumerateTest");
516 }
517 }
518 }
yoshi28bac132014-01-22 11:00:17 -0800519 /**
520 * A simple end-to-end test of the java bindings.
521 */
522 public static void
523 main(String argv[])
524 {
525 JRamCloud ramcloud = new JRamCloud(argv[0]);
526 long tableId = ramcloud.createTable("hi");
527 System.out.println("created table, id = " + tableId);
528 long tableId2 = ramcloud.getTableId("hi");
529 System.out.println("getTableId says tableId = " + tableId2);
530
531 System.out.println("wrote obj version = " +
532 ramcloud.write(tableId, "thisIsTheKey", "thisIsTheValue"));
533
534 JRamCloud.Object o = ramcloud.read(tableId, "thisIsTheKey");
535 System.out.println("read object: key = [" + o.getKey() + "], value = ["
536 + o.getValue() + "], version = " + o.version);
537
538 ramcloud.remove(tableId, "thisIsTheKey");
539
540 try {
541 ramcloud.read(tableId, "thisIsTheKey");
542 System.out.println("Error: shouldn't have read successfully!");
543 } catch (Exception e) {
544 // OK
545 }
546
547 ramcloud.write(tableId, "thisIsTheKey", "thisIsTheValue");
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800548
yoshi28bac132014-01-22 11:00:17 -0800549 long before = System.nanoTime();
550 for (int i = 0; i < 1000; i++) {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800551 @SuppressWarnings("unused")
yoshi28bac132014-01-22 11:00:17 -0800552 JRamCloud.Object unused = ramcloud.read(tableId, "thisIsTheKey");
553 }
554 long after = System.nanoTime();
555 System.out.println("Avg read latency: " +
556 ((double)(after - before) / 1000 / 1000) + " usec");
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800557
yoshi28bac132014-01-22 11:00:17 -0800558 // multiRead test
559 long tableId4 = ramcloud.createTable("table4");
560 System.out.println("table4 id " + tableId4);
561 ramcloud.write(tableId4, "object1-1", "value:1-1");
562 ramcloud.write(tableId4, "object1-2", "value:1-2");
563 ramcloud.write(tableId4, "object1-3", "value:1-3");
564 long tableId5 = ramcloud.createTable("table5");
565 System.out.println("table5 id " + tableId5);
566 ramcloud.write(tableId5, "object2-1", "value:2-1");
567 long tableId6 = ramcloud.createTable("table6");
568 ramcloud.write(tableId6, "object3-1", "value:3-1");
569 ramcloud.write(tableId6, "object3-2", "value:3-2");
570
Ray Milkey269ffb92014-04-03 14:43:30 -0700571 MultiReadObject mr = new MultiReadObject(2);
572 MultiWriteObject mw = new MultiWriteObject(2);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800573
Ray Milkey269ffb92014-04-03 14:43:30 -0700574 mr.setObject(0, tableId4, "object1-1".getBytes(StandardCharsets.UTF_8));
575 mr.setObject(1, tableId5, "object2-1".getBytes(StandardCharsets.UTF_8));
Yoshi Muroi2c170602014-02-15 08:31:28 -0800576
Yoshi Muroie7693b12014-02-19 19:41:17 -0800577 JRamCloud.Object out[] = ramcloud.multiRead(mr.tableId, mr.key, mr.keyLength, 2);
yoshi28bac132014-01-22 11:00:17 -0800578 for (int i = 0 ; i < 2 ; i++){
579 System.out.println("multi read object: key = [" + out[i].getKey() + "], value = ["
580 + out[i].getValue() + "]");
yoshi28bac132014-01-22 11:00:17 -0800581 }
Yoshi Muroi2c170602014-02-15 08:31:28 -0800582
yoshi28bac132014-01-22 11:00:17 -0800583 for (int i = 0; i < 1000; i++) {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800584 String key1 = "key1" + String.valueOf(i);
585 String key2 = "key2" + String.valueOf(i);
586
587 mw.setObject(0, tableId4, key1.getBytes(StandardCharsets.UTF_8), "v0-value".getBytes(StandardCharsets.UTF_8), null);
588 mw.setObject(1, tableId5, key2.getBytes(StandardCharsets.UTF_8), "v1".getBytes(StandardCharsets.UTF_8), null);
589
Yoshi Muroie7693b12014-02-19 19:41:17 -0800590 MultiWriteRspObject[] rsp = ramcloud.multiWrite(mw.tableId, mw.key, mw.keyLength, mw.value, mw.valueLength, 2, mw.rules);
yoshi28bac132014-01-22 11:00:17 -0800591 if (rsp != null) {
592 for (int j = 0; j < rsp.length; j++) {
593 System.out.println("multi write rsp(" + j + ") status:version " + rsp[j].getStatus() + ":" + rsp[j].getVersion());
594 }
595 }
596 }
597 for (int i = 0; i < 1000; i++) {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800598 String key1 = "key1" + String.valueOf(i);
599 String key2 = "key2" + String.valueOf(i);
Yoshi Muroi2c170602014-02-15 08:31:28 -0800600
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800601 mr.setObject(0, tableId4, key1.getBytes(StandardCharsets.UTF_8));
602 mr.setObject(1, tableId5, key2.getBytes(StandardCharsets.UTF_8));
603
Yoshi Muroie7693b12014-02-19 19:41:17 -0800604 out = ramcloud.multiRead(mr.tableId, mr.key, mr.keyLength, 2);
yoshi28bac132014-01-22 11:00:17 -0800605 for (int j = 0; j < 2; j++) {
606 System.out.println("multi read object: key = [" + out[j].getKey() + "], value = [" + out[j].getValue() + "]");
607 }
608 }
Yoshi Muroi2c170602014-02-15 08:31:28 -0800609
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800610 tableEnumeratorTest(ramcloud);
611
yoshi28bac132014-01-22 11:00:17 -0800612 ramcloud.dropTable("table4");
613 ramcloud.dropTable("table5");
614 ramcloud.dropTable("table6");
615 ramcloud.disconnect();
616 }
617}