blob: d895138bf238821f2428c3c01316fb29edab0b07 [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
Yuta HIGUCHIb6cf5832014-03-26 17:57:58 -070016/*
17 * Future TODO memo.
18 * - Throwing exception is a bit expensive in Java. (Construct backtrace, etc.)
19 * Those native methods should be modified to notify conditional failure as
20 * part of return value object instead of exception to eliminate overhead.
21 * - Inner classes in JRamCloud.java should be moved out to be a separate
22 * stand alone class, to eliminate workaround 00024 signature in
23 * C methods.
24 *
25 */
26
yoshi28bac132014-01-22 11:00:17 -080027#include <RamCloud.h>
28#include <TableEnumerator.h>
29#include <Object.h>
30#include "edu_stanford_ramcloud_JRamCloud.h"
yoshi28bac132014-01-22 11:00:17 -080031
32using namespace RAMCloud;
33
34/// Our JRamCloud java library is packaged under "edu.stanford.ramcloud".
35/// We will need this when using FindClass, etc.
36#define PACKAGE_PATH "edu/stanford/ramcloud/"
37
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080038// Java RejectRules flags bit index
39const static int DoesntExist = 1;
40const static int Exists = 1 << 1;
41const static int VersionLeGiven = 1 << 2;
42const static int VersionNeGiven = 1 << 3;
43
yoshi28bac132014-01-22 11:00:17 -080044#define check_null(var, msg) \
45 if (var == NULL) { \
46 throw Exception(HERE, "JRamCloud: NULL returned: " msg "\n"); \
47 }
48
49/**
50 * This class provides a simple means of extracting C-style strings
51 * from a jstring and cleans up when the destructor is called. This
52 * avoids having to manually do the annoying GetStringUTFChars /
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080053 * ReleaseStringUTFChars dance.
yoshi28bac132014-01-22 11:00:17 -080054 */
55class JStringGetter {
56 public:
57 JStringGetter(JNIEnv* env, jstring jString)
58 : env(env)
59 , jString(jString)
60 , string(env->GetStringUTFChars(jString, 0))
61 {
62 check_null(string, "GetStringUTFChars failed");
63 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080064
yoshi28bac132014-01-22 11:00:17 -080065 ~JStringGetter()
66 {
67 if (string != NULL)
68 env->ReleaseStringUTFChars(jString, string);
69 }
70
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080071 private:
yoshi28bac132014-01-22 11:00:17 -080072 JNIEnv* env;
73 jstring jString;
74
75 public:
76 const char* const string;
77};
78
79/**
80 * This class provides a simple means of accessing jbyteArrays as
81 * C-style void* buffers and cleans up when the destructor is called.
82 * This avoids having to manually do the annoying GetByteArrayElements /
83 * ReleaseByteArrayElements dance.
84 */
85class JByteArrayGetter {
86 public:
87 JByteArrayGetter(JNIEnv* env, jbyteArray jByteArray)
88 : env(env)
89 , jByteArray(jByteArray)
90 , pointer(static_cast<void*>(env->GetByteArrayElements(jByteArray, 0)))
91 , length(env->GetArrayLength(jByteArray))
92 {
93 check_null(pointer, "GetByteArrayElements failed");
94 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -080095
yoshi28bac132014-01-22 11:00:17 -080096 ~JByteArrayGetter()
97 {
98 if (pointer != NULL) {
99 env->ReleaseByteArrayElements(jByteArray,
100 reinterpret_cast<jbyte*>(pointer),
101 0);
102 }
103 }
104
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800105 private:
yoshi28bac132014-01-22 11:00:17 -0800106 JNIEnv* env;
107 jbyteArray jByteArray;
108
109 public:
110 void* const pointer;
111 const jsize length;
112};
113
114class JByteArrayReference {
115 public:
116 JByteArrayReference(JNIEnv* env, jbyteArray jByteArray)
117 : env(env)
118 , jByteArray(jByteArray)
119 , pointer(static_cast<const void*>(env->GetByteArrayElements(jByteArray, 0)))
120 , length(env->GetArrayLength(jByteArray))
121 {
122 check_null(pointer, "GetByteArrayElements failed");
123 }
124
125 ~JByteArrayReference()
126 {
127 if (pointer != NULL) {
128 env->ReleaseByteArrayElements(jByteArray,
129 (jbyte*)pointer,
130 JNI_ABORT);
131 }
132 }
133
134 private:
135 JNIEnv* env;
136 jbyteArray jByteArray;
137
138 public:
139 const void* const pointer;
140 const jsize length;
141};
142
143static RamCloud*
144getRamCloud(JNIEnv* env, jobject jRamCloud)
145{
146 const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud"));
147 const static jfieldID fieldId = env->GetFieldID(cls, "ramcloudObjectPointer", "J");
148 return reinterpret_cast<RamCloud*>(env->GetLongField(jRamCloud, fieldId));
149}
150
151static TableEnumerator*
152getTableEnumerator(JNIEnv* env, jobject jTableEnumerator)
153{
154 const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$TableEnumerator"));
155 const static jfieldID fieldId = env->GetFieldID(cls, "tableEnumeratorObjectPointer", "J");
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800156 return reinterpret_cast<TableEnumerator*>(env->GetLongField(jTableEnumerator, fieldId));
yoshi28bac132014-01-22 11:00:17 -0800157}
158
159static void
160createException(JNIEnv* env, jobject jRamCloud, const char* name)
161{
162 // Need to specify the full class name, including the package. To make it
163 // slightly more complicated, our exceptions are nested under the JRamCloud
164 // class.
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800165 string fullName(PACKAGE_PATH "JRamCloud$");
yoshi28bac132014-01-22 11:00:17 -0800166 fullName += name;
167
yoshi28bac132014-01-22 11:00:17 -0800168 jclass cls = env->FindClass(fullName.c_str());
169 check_null(cls, "FindClass failed");
170
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800171 env->ThrowNew(cls, "");
172}
yoshi28bac132014-01-22 11:00:17 -0800173
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800174static void
175setRejectRules(JNIEnv* env, jobject jRejectRules, RejectRules& rules)
176{
177 const static jclass jc_RejectRules = (jclass) env->NewGlobalRef(
178 env->FindClass(PACKAGE_PATH "JRamCloud$RejectRules"));
179 static const jfieldID jf_flags = env->GetFieldID(jc_RejectRules, "flags", "I");
180 check_null(jf_flags, "flags field ID is null");
181 static const jfieldID jf_givenVersion = env->GetFieldID(jc_RejectRules,
182 "givenVersion", "J");
183 check_null(jf_givenVersion, "givenVersion field ID is null");
yoshi28bac132014-01-22 11:00:17 -0800184
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800185 const jint rejectFlag = env->GetIntField(jRejectRules, jf_flags);
186 rules.doesntExist = (rejectFlag & DoesntExist) != 0;
187 rules.exists = (rejectFlag & Exists) != 0;
188 rules.versionLeGiven = (rejectFlag & VersionLeGiven) != 0;
189 rules.versionNeGiven = (rejectFlag & VersionNeGiven) != 0;
190 if (rules.versionLeGiven || rules.versionNeGiven) {
191 rules.givenVersion = env->GetLongField(jRejectRules, jf_givenVersion);
192 }
yoshi28bac132014-01-22 11:00:17 -0800193}
194
195/**
196 * This macro is used to catch C++ exceptions and convert them into Java
197 * exceptions. Be sure to wrap the individual RamCloud:: calls in try blocks,
198 * rather than the entire methods, since doing so with functions that return
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800199 * non-void is a bad idea with undefined(?) behaviour.
yoshi28bac132014-01-22 11:00:17 -0800200 *
201 * _returnValue is the value that should be returned from the JNI function
202 * when an exception is caught and generated in Java. As far as I can tell,
203 * the exception fires immediately upon returning from the JNI method. I
204 * don't think anything else would make sense, but the JNI docs kind of
205 * suck.
206 */
207#define EXCEPTION_CATCHER(_returnValue) \
208 catch (TableDoesntExistException& e) { \
209 createException(env, jRamCloud, "TableDoesntExistException"); \
210 return _returnValue; \
211 } catch (ObjectDoesntExistException& e) { \
212 createException(env, jRamCloud, "ObjectDoesntExistException"); \
213 return _returnValue; \
214 } catch (ObjectExistsException& e) { \
215 createException(env, jRamCloud, "ObjectExistsException"); \
216 return _returnValue; \
217 } catch (WrongVersionException& e) { \
218 createException(env, jRamCloud, "WrongVersionException"); \
219 return _returnValue; \
220 } catch (RejectRulesException& e) { \
221 createException(env, jRamCloud, "RejectRulesException"); \
222 return _returnValue; \
223 } catch (InvalidObjectException& e) { \
224 createException(env, jRamCloud, "InvalidObjectException"); \
225 return _returnValue; \
226 }
227
228/*
229 * Class: edu_stanford_ramcloud_JRamCloud
230 * Method: connect
231 * Signature: (Ljava/lang/String;)J
232 */
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800233JNIEXPORT jlong
yoshi28bac132014-01-22 11:00:17 -0800234JNICALL Java_edu_stanford_ramcloud_JRamCloud_connect(JNIEnv *env,
235 jclass jRamCloud,
236 jstring coordinatorLocator)
237{
238 JStringGetter locator(env, coordinatorLocator);
239 RamCloud* ramcloud = NULL;
240 try {
241 ramcloud = new RamCloud(locator.string);
Yuta HIGUCHI52617722014-03-14 13:36:10 -0700242 } EXCEPTION_CATCHER((jlong)(NULL));
yoshi28bac132014-01-22 11:00:17 -0800243 return reinterpret_cast<jlong>(ramcloud);
244}
245
246/*
247 * Class: edu_stanford_ramcloud_JRamCloud
248 * Method: disconnect
249 * Signature: (J)V
250 */
251JNIEXPORT void
252JNICALL Java_edu_stanford_ramcloud_JRamCloud_disconnect(JNIEnv *env,
253 jclass jRamCloud,
254 jlong ramcloudObjectPointer)
255{
256 delete reinterpret_cast<RamCloud*>(ramcloudObjectPointer);
257}
258
259/*
260 * Class: edu_stanford_ramcloud_JRamCloud
261 * Method: createTable
262 * Signature: (Ljava/lang/String;)I
263 */
264JNIEXPORT jlong
265JNICALL Java_edu_stanford_ramcloud_JRamCloud_createTable__Ljava_lang_String_2(JNIEnv *env,
266 jobject jRamCloud,
267 jstring jTableName)
268{
269 return Java_edu_stanford_ramcloud_JRamCloud_createTable__Ljava_lang_String_2I(env,
270 jRamCloud,
271 jTableName,
272 1);
273}
274
275/*
276 * Class: edu_stanford_ramcloud_JRamCloud
277 * Method: createTable
278 * Signature: (Ljava/lang/String;I)I
279 */
280JNIEXPORT jlong
281JNICALL Java_edu_stanford_ramcloud_JRamCloud_createTable__Ljava_lang_String_2I(JNIEnv *env,
282 jobject jRamCloud,
283 jstring jTableName,
284 jint jServerSpan)
285{
286 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
287 JStringGetter tableName(env, jTableName);
288 uint64_t tableId;
289 try {
290 tableId = ramcloud->createTable(tableName.string, jServerSpan);
291 } EXCEPTION_CATCHER(-1);
292 return static_cast<jlong>(tableId);
293}
294
295/*
296 * Class: edu_stanford_ramcloud_JRamCloud
297 * Method: dropTable
298 * Signature: (Ljava/lang/String;)I
299 */
300JNIEXPORT void
301JNICALL Java_edu_stanford_ramcloud_JRamCloud_dropTable(JNIEnv *env,
302 jobject jRamCloud,
303 jstring jTableName)
304{
305 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
306 JStringGetter tableName(env, jTableName);
307 try {
308 ramcloud->dropTable(tableName.string);
309 } EXCEPTION_CATCHER();
310}
311
312/*
313 * Class: edu_stanford_ramcloud_JRamCloud
314 * Method: getTableId
315 * Signature: (Ljava/lang/String;)J
316 */
317JNIEXPORT jlong
318JNICALL Java_edu_stanford_ramcloud_JRamCloud_getTableId(JNIEnv *env,
319 jobject jRamCloud,
320 jstring jTableName)
321{
322 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
323 JStringGetter tableName(env, jTableName);
324 uint64_t tableId;
325 try {
326 tableId = ramcloud->getTableId(tableName.string);
327 } EXCEPTION_CATCHER(-1);
328 return tableId;
329}
330
331/*
332 * Class: edu_stanford_ramcloud_JRamCloud
333 * Method: read
334 * Signature: (J[B)LJRamCloud/Object;
335 */
336JNIEXPORT jobject
337JNICALL Java_edu_stanford_ramcloud_JRamCloud_read__J_3B(JNIEnv *env,
338 jobject jRamCloud,
339 jlong jTableId,
340 jbyteArray jKey)
341{
342 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
343 JByteArrayReference key(env, jKey);
344
345 Buffer buffer;
346 uint64_t version;
347 try {
348 ramcloud->read(jTableId, key.pointer, key.length, &buffer, NULL, &version);
349 } EXCEPTION_CATCHER(NULL);
350
351 jbyteArray jValue = env->NewByteArray(buffer.getTotalLength());
352 check_null(jValue, "NewByteArray failed");
353 JByteArrayGetter value(env, jValue);
354 buffer.copy(0, buffer.getTotalLength(), value.pointer);
355
356 // Note that using 'javap -s' on the class file will print out the method
357 // signatures (the third argument to GetMethodID).
358 const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
359 check_null(cls, "FindClass failed");
360
361 const static jmethodID methodId = env->GetMethodID(cls,
362 "<init>",
Yoshi Muroie7693b12014-02-19 19:41:17 -0800363 "([B[BJ)V");
yoshi28bac132014-01-22 11:00:17 -0800364 check_null(methodId, "GetMethodID failed");
365
366 return env->NewObject(cls,
367 methodId,
yoshi28bac132014-01-22 11:00:17 -0800368 jKey,
369 jValue,
370 static_cast<jlong>(version));
371}
372
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800373// Workaround for javah generating incorrect signature for inner class
374// 00024 is an escaped signature for $ character
375#ifdef __cplusplus
376extern "C" {
377#endif
378JNIEXPORT jobject JNICALL Java_edu_stanford_ramcloud_JRamCloud_read__J_3BLedu_stanford_ramcloud_JRamCloud_00024RejectRules_2
379 (JNIEnv *, jobject, jlong, jbyteArray, jobject);
380#ifdef __cplusplus
381}
382#endif
383
yoshi28bac132014-01-22 11:00:17 -0800384/*
385 * Class: edu_stanford_ramcloud_JRamCloud
386 * Method: read
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800387 * Signature: (J[BLedu/stanford/ramcloud/JRamCloud/RejectRules;)Ledu/stanford/ramcloud/JRamCloud/Object;
yoshi28bac132014-01-22 11:00:17 -0800388 */
389JNIEXPORT jobject
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800390JNICALL Java_edu_stanford_ramcloud_JRamCloud_read__J_3BLedu_stanford_ramcloud_JRamCloud_00024RejectRules_2(JNIEnv *env,
yoshi28bac132014-01-22 11:00:17 -0800391 jobject jRamCloud,
392 jlong jTableId,
393 jbyteArray jKey,
394 jobject jRejectRules)
395{
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800396 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
397 JByteArrayReference key(env, jKey);
398
399 Buffer buffer;
400 uint64_t version;
401 RejectRules rules = {};
402 setRejectRules(env, jRejectRules, rules);
403
404 try {
405 ramcloud->read(jTableId, key.pointer, key.length, &buffer, &rules, &version);
406 } EXCEPTION_CATCHER(NULL);
407
408 jbyteArray jValue = env->NewByteArray(buffer.getTotalLength());
409 check_null(jValue, "NewByteArray failed");
410 JByteArrayGetter value(env, jValue);
411 buffer.copy(0, buffer.getTotalLength(), value.pointer);
412
413 // Note that using 'javap -s' on the class file will print out the method
414 // signatures (the third argument to GetMethodID).
415 const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
416 check_null(cls, "FindClass failed");
417
418 const static jmethodID methodId = env->GetMethodID(cls,
419 "<init>",
420 "([B[BJ)V");
421 check_null(methodId, "GetMethodID failed");
422
423 return env->NewObject(cls,
424 methodId,
425 jKey,
426 jValue,
427 static_cast<jlong>(version));
yoshi28bac132014-01-22 11:00:17 -0800428}
429
430/*
431 * Class: edu_stanford_ramcloud_JRamCloud
432 * Method: multiRead
433 * Signature: ([Ledu/stanford/ramcloud/JRamCloud$multiReadObject;I)[Ledu/stanford/ramcloud/JRamCloud$Object;
434 */
435JNIEXPORT jobjectArray
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800436JNICALL Java_edu_stanford_ramcloud_JRamCloud_multiRead(JNIEnv *env,
yoshi28bac132014-01-22 11:00:17 -0800437 jobject jRamCloud,
Yoshi Muroi2c170602014-02-15 08:31:28 -0800438 jlongArray jTableId,
439 jobjectArray jKeyData,
Yoshi Muroie7693b12014-02-19 19:41:17 -0800440 jshortArray jKeyLength,
Yoshi Muroi2c170602014-02-15 08:31:28 -0800441 jint jrequestNum){
yoshi28bac132014-01-22 11:00:17 -0800442
443 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
Yoshi Muroi2c170602014-02-15 08:31:28 -0800444 MultiReadObject objects[jrequestNum];
445 Tub<Buffer> values[jrequestNum];
446 jbyteArray jKey[jrequestNum];
447 MultiReadObject* requests[jrequestNum];
yoshi28bac132014-01-22 11:00:17 -0800448
Yoshi Muroie7693b12014-02-19 19:41:17 -0800449 jlong tableId;
450 jshort keyLength;
451 jbyte* keyData[jrequestNum];
yoshi28bac132014-01-22 11:00:17 -0800452
Yoshi Muroi2c170602014-02-15 08:31:28 -0800453 for (int i = 0 ; i < jrequestNum ; i++){
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800454 jKey[i] = (jbyteArray)env->GetObjectArrayElement(jKeyData, i);
yoshi28bac132014-01-22 11:00:17 -0800455
Yoshi Muroie7693b12014-02-19 19:41:17 -0800456 env->GetShortArrayRegion(jKeyLength, i, 1, &keyLength);
yoshi28bac132014-01-22 11:00:17 -0800457
Yoshi Muroie7693b12014-02-19 19:41:17 -0800458 keyData[i] = (jbyte *) malloc(keyLength);
459 env->GetByteArrayRegion(jKey[i], 0, keyLength, keyData[i]);
yoshi28bac132014-01-22 11:00:17 -0800460
Yoshi Muroie7693b12014-02-19 19:41:17 -0800461 env->GetLongArrayRegion(jTableId, i, 1, &tableId);
462 objects[i].tableId = tableId;
463 objects[i].key = keyData[i];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800464 objects[i].keyLength = keyLength;
yoshi28bac132014-01-22 11:00:17 -0800465 objects[i].value = &values[i];
466 requests[i] = &objects[i];
467 }
468
469 try {
Yoshi Muroi2c170602014-02-15 08:31:28 -0800470 ramcloud->multiRead(requests, jrequestNum);
yoshi28bac132014-01-22 11:00:17 -0800471 } EXCEPTION_CATCHER(NULL);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800472
yoshi28bac132014-01-22 11:00:17 -0800473 const static jclass jc_RcObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
474 check_null(jc_RcObject, "FindClass failed");
475 const static jmethodID jm_init = env->GetMethodID(jc_RcObject,
476 "<init>",
Yoshi Muroie7693b12014-02-19 19:41:17 -0800477 "([B[BJ)V");
yoshi28bac132014-01-22 11:00:17 -0800478
Yoshi Muroi2c170602014-02-15 08:31:28 -0800479 jobjectArray outJNIArray = env->NewObjectArray(jrequestNum, jc_RcObject , NULL);
yoshi28bac132014-01-22 11:00:17 -0800480 check_null(outJNIArray, "NewObjectArray failed");
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800481
Yoshi Muroi2c170602014-02-15 08:31:28 -0800482 for (int i = 0 ; i < jrequestNum ; i++) {
yoshi28bac132014-01-22 11:00:17 -0800483 if (objects[i].status == 0) {
484 jbyteArray jValue = env->NewByteArray(values[i].get()->getTotalLength());
485 check_null(jValue, "NewByteArray failed");
486 JByteArrayGetter value(env, jValue);
487 values[i].get()->copy(0, values[i].get()->getTotalLength(), value.pointer);
Yuta HIGUCHI52617722014-03-14 13:36:10 -0700488 jobject obj = env->NewObject(jc_RcObject, jm_init, jKey[i], jValue, (jlong)objects[i].version);
yoshi28bac132014-01-22 11:00:17 -0800489 check_null(obj, "NewObject failed");
490 env->SetObjectArrayElement(outJNIArray, i, obj);
491 }
Yoshi Muroie7693b12014-02-19 19:41:17 -0800492 free(keyData[i]);
yoshi28bac132014-01-22 11:00:17 -0800493 }
494 return outJNIArray;
495}
496
497
498/*
499 * Class: edu_stanford_ramcloud_JRamCloud
500 * Method: remove
501 * Signature: (J[B)J
502 */
503JNIEXPORT jlong
504JNICALL Java_edu_stanford_ramcloud_JRamCloud_remove__J_3B(JNIEnv *env,
505 jobject jRamCloud,
506 jlong jTableId,
507 jbyteArray jKey)
508{
509 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
510 JByteArrayReference key(env, jKey);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700511 uint64_t version = VERSION_NONEXISTENT;
yoshi28bac132014-01-22 11:00:17 -0800512 try {
513 ramcloud->remove(jTableId, key.pointer, key.length, NULL, &version);
514 } EXCEPTION_CATCHER(-1);
515 return static_cast<jlong>(version);
516}
517
Yuta HIGUCHI9402dab2014-01-30 19:54:31 -0800518
519// Workaround for javah generating incorrect signature for inner class
520// 00024 is an escaped signature for $ character
521#ifdef __cplusplus
522extern "C" {
523#endif
524JNIEXPORT jlong JNICALL Java_edu_stanford_ramcloud_JRamCloud_remove__J_3BLedu_stanford_ramcloud_JRamCloud_00024RejectRules_2
525 (JNIEnv *, jobject, jlong, jbyteArray, jobject);
526#ifdef __cplusplus
527}
528#endif
529
yoshi28bac132014-01-22 11:00:17 -0800530/*
531 * Class: edu_stanford_ramcloud_JRamCloud
532 * Method: remove
Yuta HIGUCHI9402dab2014-01-30 19:54:31 -0800533 * Signature: (J[BLedu/stanford/ramcloud/JRamCloud/$RejectRules;)J
yoshi28bac132014-01-22 11:00:17 -0800534 */
535JNIEXPORT jlong
Yuta HIGUCHI9402dab2014-01-30 19:54:31 -0800536JNICALL Java_edu_stanford_ramcloud_JRamCloud_remove__J_3BLedu_stanford_ramcloud_JRamCloud_00024RejectRules_2(JNIEnv *env,
yoshi28bac132014-01-22 11:00:17 -0800537 jobject jRamCloud,
538 jlong jTableId,
539 jbyteArray jKey,
540 jobject jRejectRules)
541{
yoshi28bac132014-01-22 11:00:17 -0800542 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
543 JByteArrayReference key(env, jKey);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800544 RejectRules rules = {};
545 setRejectRules(env, jRejectRules, rules);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700546 uint64_t version = VERSION_NONEXISTENT;
yoshi28bac132014-01-22 11:00:17 -0800547 try {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800548 ramcloud->remove(jTableId, key.pointer, key.length, &rules, &version);
yoshi28bac132014-01-22 11:00:17 -0800549 } EXCEPTION_CATCHER(-1);
550 return static_cast<jlong>(version);
551}
552
553/*
554 * Class: edu_stanford_ramcloud_JRamCloud
555 * Method: write
556 * Signature: (J[B[B)J
557 */
558JNIEXPORT jlong
559JNICALL Java_edu_stanford_ramcloud_JRamCloud_write__J_3B_3B(JNIEnv *env,
560 jobject jRamCloud,
561 jlong jTableId,
562 jbyteArray jKey,
563 jbyteArray jValue)
564{
565 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
566 JByteArrayReference key(env, jKey);
567 JByteArrayGetter value(env, jValue);
568 uint64_t version;
569 try {
570 ramcloud->write(jTableId,
571 key.pointer, key.length,
572 value.pointer, value.length,
573 NULL,
574 &version);
575 } EXCEPTION_CATCHER(-1);
576 return static_cast<jlong>(version);
577}
578
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800579// Workaround for javah generating incorrect signature for inner class
580// 00024 is an escaped signature for $ character
581#ifdef __cplusplus
582extern "C" {
583#endif
584JNIEXPORT jlong JNICALL Java_edu_stanford_ramcloud_JRamCloud_write__J_3B_3BLedu_stanford_ramcloud_JRamCloud_00024RejectRules_2
585 (JNIEnv *, jobject, jlong, jbyteArray, jbyteArray, jobject);
586#ifdef __cplusplus
587}
588#endif
589
yoshi28bac132014-01-22 11:00:17 -0800590/*
591 * Class: edu_stanford_ramcloud_JRamCloud
592 * Method: write
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800593 * Signature: (J[B[BLedu/stanford/ramcloud/JRamCloud/RejectRules;)J
yoshi28bac132014-01-22 11:00:17 -0800594 */
595JNIEXPORT jlong
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800596JNICALL Java_edu_stanford_ramcloud_JRamCloud_write__J_3B_3BLedu_stanford_ramcloud_JRamCloud_00024RejectRules_2(JNIEnv *env,
yoshi28bac132014-01-22 11:00:17 -0800597 jobject jRamCloud,
598 jlong jTableId,
599 jbyteArray jKey,
600 jbyteArray jValue,
601 jobject jRejectRules)
602{
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800603 return Java_edu_stanford_ramcloud_JRamCloud_writeRule(env, jRamCloud, jTableId, jKey, jValue, jRejectRules);
yoshi28bac132014-01-22 11:00:17 -0800604}
605
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800606/*
607 * Class: edu_stanford_ramcloud_JRamCloud
608 * Method: writeRule
609 * Signature: (J[B[BLedu/stanford/ramcloud/JRamCloud/RejectRules;)J
610 */
yoshi28bac132014-01-22 11:00:17 -0800611JNIEXPORT jlong
612JNICALL Java_edu_stanford_ramcloud_JRamCloud_writeRule(JNIEnv *env,
613 jobject jRamCloud,
614 jlong jTableId,
615 jbyteArray jKey,
616 jbyteArray jValue,
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800617 jobject jRejectRules)
618{
yoshi28bac132014-01-22 11:00:17 -0800619 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
620 JByteArrayReference key(env, jKey);
621 JByteArrayGetter value(env, jValue);
yoshi28bac132014-01-22 11:00:17 -0800622 RejectRules rules = {};
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800623 setRejectRules(env, jRejectRules, rules);
624 uint64_t version;
yoshi28bac132014-01-22 11:00:17 -0800625 try {
626 ramcloud->write(jTableId,
627 key.pointer, key.length,
628 value.pointer, value.length,
629 &rules,
630 &version);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800631 } EXCEPTION_CATCHER(-1);
yoshi28bac132014-01-22 11:00:17 -0800632 return static_cast<jlong> (version);
633}
634
635/*
636 * Class: edu_stanford_ramcloud_JRamCloud_TableEnumerator
637 * Method: init
638 * Signature: (J)V
639 */
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800640JNIEXPORT jlong JNICALL Java_edu_stanford_ramcloud_JRamCloud_00024TableEnumerator_init(JNIEnv *env,
641 jobject jTableEnumerator,
yoshi28bac132014-01-22 11:00:17 -0800642 jlong jTableId)
643{
644 const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$TableEnumerator"));
645 const static jfieldID fieldId = env->GetFieldID(cls, "ramCloudObjectPointer", "J");
646 RamCloud* ramcloud = reinterpret_cast<RamCloud*>(env->GetLongField(jTableEnumerator, fieldId));
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800647
Yuta HIGUCHIa7ec0732014-03-10 16:01:06 -0700648 return reinterpret_cast<jlong>(new TableEnumerator(*ramcloud, jTableId, false));
yoshi28bac132014-01-22 11:00:17 -0800649}
650
651/*
652 * Class: edu_stanford_ramcloud_JRamCloud_TableEnumerator
653 * Method: hasNext
654 * Signature: ()Z
655 */
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800656JNIEXPORT jboolean JNICALL Java_edu_stanford_ramcloud_JRamCloud_00024TableEnumerator_hasNext( JNIEnv *env,
yoshi28bac132014-01-22 11:00:17 -0800657 jobject jTableEnumerator)
658{
659 TableEnumerator* tableEnum = getTableEnumerator(env, jTableEnumerator);
660 return static_cast<jboolean>(tableEnum->hasNext());
661}
662
663/*
664 * Class: edu_stanford_ramcloud_JRamCloud_TableEnumerator
665 * Method: next
666 * Signature: ()Ledu/stanford/ramcloud/JRamCloud/Object;
667 */
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800668JNIEXPORT jobject JNICALL Java_edu_stanford_ramcloud_JRamCloud_00024TableEnumerator_next( JNIEnv *env,
yoshi28bac132014-01-22 11:00:17 -0800669 jobject jTableEnumerator)
670{
671 TableEnumerator* tableEnum = getTableEnumerator(env, jTableEnumerator);
672
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800673 if (tableEnum->hasNext()) {
yoshi28bac132014-01-22 11:00:17 -0800674 uint32_t size = 0;
675 const void* buffer = 0;
676 uint64_t version = 0;
677
678 tableEnum->next(&size, &buffer);
679 Object object(buffer, size);
680
681 jbyteArray jKey = env->NewByteArray(object.getKeyLength());
682 jbyteArray jValue = env->NewByteArray(object.getDataLength());
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800683
yoshi28bac132014-01-22 11:00:17 -0800684 JByteArrayGetter key(env, jKey);
685 JByteArrayGetter value(env, jValue);
686
687 memcpy(key.pointer, object.getKey(), object.getKeyLength());
688 memcpy(value.pointer, object.getData(), object.getDataLength());
689
690 version = object.getVersion();
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800691
yoshi28bac132014-01-22 11:00:17 -0800692 const static jclass cls = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
693 check_null(cls, "FindClass failed");
694 const static jmethodID methodId = env->GetMethodID(cls,
695 "<init>",
Yoshi Muroie7693b12014-02-19 19:41:17 -0800696 "([B[BJ)V");
yoshi28bac132014-01-22 11:00:17 -0800697 check_null(methodId, "GetMethodID failed");
698 return env->NewObject(cls,
699 methodId,
yoshi28bac132014-01-22 11:00:17 -0800700 jKey,
701 jValue,
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800702 static_cast<jlong>(version));
703 } else {
yoshi28bac132014-01-22 11:00:17 -0800704 return NULL;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800705 }
yoshi28bac132014-01-22 11:00:17 -0800706}
707
708/*
709 * Class: edu_stanford_ramcloud_JRamCloud
Yoshi Muroie7693b12014-02-19 19:41:17 -0800710 * Method: getTableObjects
711 * Signature: (JJ)Ledu/stanford/ramcloud/JRamCloud/TableEnumeratorObject;
712 */
713JNIEXPORT jobject JNICALL Java_edu_stanford_ramcloud_JRamCloud_getTableObjects(JNIEnv *env,
714 jobject jRamCloud,
715 jlong jTableId,
716 jlong jTabletNextHash){
717
718 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
719
Yoshi Muroie7693b12014-02-19 19:41:17 -0800720 const static jclass jc_RcObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$Object"));
721 check_null(jc_RcObject, "FindClass failed");
722 const static jmethodID jm_init = env->GetMethodID(jc_RcObject,
723 "<init>",
724 "([B[BJ)V");
725 check_null(jm_init, "GetMethodID failed");
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800726
Yoshi Muroie7693b12014-02-19 19:41:17 -0800727 const static jclass jc_RcTableObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$TableEnumeratorObject"));
728 check_null(jc_RcTableObject, "FindClass failed");
729 const static jmethodID jm_TableEnumeratorObject_init = env->GetMethodID(jc_RcTableObject,
730 "<init>",
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800731 "([L" PACKAGE_PATH "JRamCloud$Object;J)V");
Yoshi Muroie7693b12014-02-19 19:41:17 -0800732 check_null(jm_TableEnumeratorObject_init, "GetMethodID failed");
733
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800734
735 Buffer state;
736 Buffer objects;
737 bool done = false;
738
Yoshi Muroie7693b12014-02-19 19:41:17 -0800739 while (true) {
Yuta HIGUCHIa7ec0732014-03-10 16:01:06 -0700740 jTabletNextHash = ramcloud->enumerateTable(jTableId, false, jTabletNextHash, state, objects);
Yoshi Muroie7693b12014-02-19 19:41:17 -0800741 if (objects.getTotalLength() > 0) {
742 break;
743 }
744 if (objects.getTotalLength() == 0 && jTabletNextHash == 0) {
745 done = true;
746 break;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800747 }
Yoshi Muroie7693b12014-02-19 19:41:17 -0800748 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800749
Yoshi Muroie7693b12014-02-19 19:41:17 -0800750 if (done) {
751 return env->NewObject(jc_RcTableObject, jm_TableEnumeratorObject_init, env->NewObjectArray(0, jc_RcObject , NULL), 0);
752 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800753
754 int numOfObjects = 0;
755 uint32_t nextOffset = 0;
756 for (numOfObjects = 0; nextOffset < objects.getTotalLength() ; numOfObjects++) {
Yoshi Muroie7693b12014-02-19 19:41:17 -0800757 uint32_t objectSize = *objects.getOffset<uint32_t>(nextOffset);
758 nextOffset += downCast<uint32_t>(sizeof(uint32_t));
759 nextOffset += objectSize;
760 }
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800761
762 jobjectArray outJNIArray = env->NewObjectArray(numOfObjects, jc_RcObject , NULL);
Yoshi Muroie7693b12014-02-19 19:41:17 -0800763 check_null(outJNIArray, "NewObjectArray failed");
764
765 nextOffset = 0;
766 for (int i = 0; nextOffset < objects.getTotalLength() ;i++) {
767 uint32_t objectSize = *objects.getOffset<uint32_t>(nextOffset);
768 nextOffset += downCast<uint32_t>(sizeof(uint32_t));
769
770 const void* blob = objects.getRange(nextOffset, objectSize);
771 nextOffset += objectSize;
772
773 Object object(blob, objectSize);
774
775 jbyteArray jKey = env->NewByteArray(object.getKeyLength());
776 jbyteArray jValue = env->NewByteArray(object.getDataLength());
777
778 JByteArrayGetter key(env, jKey);
779 JByteArrayGetter value(env, jValue);
780
781 memcpy(key.pointer, object.getKey(), object.getKeyLength());
782 memcpy(value.pointer, object.getData(), object.getDataLength());
783
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800784 uint64_t version = object.getVersion();
Yoshi Muroie7693b12014-02-19 19:41:17 -0800785
786 jobject obj = env->NewObject(jc_RcObject, jm_init, jKey, jValue, static_cast<jlong>(version));
787 check_null(obj, "NewObject failed");
788
789 env->SetObjectArrayElement(outJNIArray, i, obj);
790 }
791
792 return env->NewObject(jc_RcTableObject, jm_TableEnumeratorObject_init, outJNIArray, jTabletNextHash);
Yoshi Muroie7693b12014-02-19 19:41:17 -0800793}
794
795/*
796 * Class: edu_stanford_ramcloud_JRamCloud
yoshi28bac132014-01-22 11:00:17 -0800797 * Method: multiWrite
798 * Signature: ([Ledu/stanford/ramcloud/JRamCloud/MultiWriteObject;)[Ledu/stanford/ramcloud/JRamCloud/MultiWriteRspObject;
799 */
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800800JNIEXPORT jobjectArray JNICALL Java_edu_stanford_ramcloud_JRamCloud_multiWrite(JNIEnv *env,
Yoshi Muroie7693b12014-02-19 19:41:17 -0800801 jobject jRamCloud,
802 jlongArray jTableId,
803 jobjectArray jKeyData,
804 jshortArray jKeyLength,
805 jobjectArray jValueData,
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800806 jintArray jValueLength,
Yoshi Muroie7693b12014-02-19 19:41:17 -0800807 jint jrequestNum,
808 jobjectArray jRules ) {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800809
Yoshi Muroie7693b12014-02-19 19:41:17 -0800810 RamCloud* ramcloud = getRamCloud(env, jRamCloud);
811 Tub<MultiWriteObject> objects[jrequestNum];
812 MultiWriteObject *requests[jrequestNum];
813 RejectRules rules[jrequestNum];
814 jbyteArray jKey[jrequestNum];
815 jbyteArray jValue[jrequestNum];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800816
Yoshi Muroie7693b12014-02-19 19:41:17 -0800817 jlong tableId;
818 jshort keyLength;
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800819 jint valueLength;
Yoshi Muroie7693b12014-02-19 19:41:17 -0800820 jbyte* keyData[jrequestNum];
821 jbyte* valueData[jrequestNum];
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800822
yoshi28bac132014-01-22 11:00:17 -0800823 const static jclass jc_RejectRules = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$RejectRules"));
yoshi28bac132014-01-22 11:00:17 -0800824
yoshi28bac132014-01-22 11:00:17 -0800825 const static jfieldID jf_givenVersion = env->GetFieldID(jc_RejectRules, "givenVersion", "J");
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800826 check_null(jf_givenVersion, "givenVersion field ID is null");
827
828 const static jfieldID jf_flags = env->GetFieldID(jc_RejectRules, "flags", "I");
829 check_null(jf_flags, "flags field ID is null");
yoshi28bac132014-01-22 11:00:17 -0800830
Yoshi Muroie7693b12014-02-19 19:41:17 -0800831 for (int i = 0; i < jrequestNum; i++) {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800832 env->GetLongArrayRegion(jTableId, i, 1, &tableId);
yoshi28bac132014-01-22 11:00:17 -0800833
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800834 env->GetShortArrayRegion(jKeyLength, i, 1, &keyLength);
835 jKey[i] = (jbyteArray)env->GetObjectArrayElement(jKeyData, i);
836 keyData[i] = (jbyte *) malloc(keyLength);
837 env->GetByteArrayRegion(jKey[i], 0, keyLength, keyData[i]);
838
839 env->GetIntArrayRegion(jValueLength, i, 1, &valueLength);
Yoshi Muroie7693b12014-02-19 19:41:17 -0800840 jValue[i] = (jbyteArray)env->GetObjectArrayElement(jValueData, i);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800841 valueData[i] = (jbyte *) malloc(valueLength);
842 env->GetByteArrayRegion(jValue[i], 0, valueLength, valueData[i]);
843
844 jobject jRejectRules = (jbyteArray)env->GetObjectArrayElement(jRules, i);
yoshi28bac132014-01-22 11:00:17 -0800845 rules[i] = {};
846
847 if (jRejectRules != NULL) {
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800848 const jint flags = env->GetIntField(jRejectRules, jf_flags);
yoshi28bac132014-01-22 11:00:17 -0800849
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800850 rules[i].doesntExist = (flags & DoesntExist) != 0;
yoshi28bac132014-01-22 11:00:17 -0800851
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800852 rules[i].exists = (flags & Exists) != 0;
yoshi28bac132014-01-22 11:00:17 -0800853
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800854 rules[i].versionLeGiven = (flags & VersionLeGiven) != 0;
yoshi28bac132014-01-22 11:00:17 -0800855
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800856 rules[i].versionNeGiven = (flags & VersionNeGiven) != 0;
yoshi28bac132014-01-22 11:00:17 -0800857
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800858 if (rules[i].versionLeGiven || rules[i].versionNeGiven) {
859 rules[i].givenVersion = env->GetLongField(jRejectRules, jf_givenVersion);
860 }
yoshi28bac132014-01-22 11:00:17 -0800861 }
Yoshi Muroie7693b12014-02-19 19:41:17 -0800862 objects[i].construct(tableId, keyData[i], keyLength, valueData[i], valueLength, &rules[i]);
yoshi28bac132014-01-22 11:00:17 -0800863 requests[i] = objects[i].get();
864 }
865 try {
Yoshi Muroie7693b12014-02-19 19:41:17 -0800866 ramcloud->multiWrite(requests, jrequestNum);
yoshi28bac132014-01-22 11:00:17 -0800867 } EXCEPTION_CATCHER(NULL);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800868
yoshi28bac132014-01-22 11:00:17 -0800869 const static jclass jc_RcObject = (jclass)env->NewGlobalRef(env->FindClass(PACKAGE_PATH "JRamCloud$MultiWriteRspObject"));
870 check_null(jc_RcObject, "FindClass failed");
871 const static jmethodID jm_init = env->GetMethodID(jc_RcObject,
872 "<init>",
Yoshi Muroie7693b12014-02-19 19:41:17 -0800873 "(IJ)V");
yoshi28bac132014-01-22 11:00:17 -0800874
Yoshi Muroie7693b12014-02-19 19:41:17 -0800875 jobjectArray outJNIArray = env->NewObjectArray(jrequestNum, jc_RcObject , NULL);
yoshi28bac132014-01-22 11:00:17 -0800876 check_null(outJNIArray, "NewObjectArray failed");
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800877
Yoshi Muroie7693b12014-02-19 19:41:17 -0800878 for (int i = 0 ; i < jrequestNum ; i++) {
879 jobject obj = env->NewObject(jc_RcObject, jm_init, objects[i]->status, objects[i]->version);
yoshi28bac132014-01-22 11:00:17 -0800880 check_null(obj, "NewObject failed");
881 env->SetObjectArrayElement(outJNIArray, i, obj);
Yuta HIGUCHI1d6a22a2014-02-21 19:17:42 -0800882 free(keyData[i]);
883 free(valueData[i]);
yoshi28bac132014-01-22 11:00:17 -0800884 objects[i].destroy();
885 }
886 return outJNIArray;
887}