Skip to content

Commit e96e71b

Browse files
author
Ankit Gupta
committed
Multi-get impl and formatting
1 parent 042221b commit e96e71b

File tree

6 files changed

+216
-2
lines changed

6 files changed

+216
-2
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ ROCKSDBJNILIB = ./java/librocksdbjni.jnilib
434434
JAVA_INCLUDE = -I/System/Library/Frameworks/JavaVM.framework/Headers/
435435
endif
436436

437-
rocksdbjava: clean
437+
rocksdbjava:
438438
OPT="-fPIC -DNDEBUG -O2" $(MAKE) $(LIBRARY) -j32
439439
cd java;$(MAKE) java;
440440
rm -f $(ROCKSDBJNILIB)

java/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ sample: java
1616
javac -cp $(ROCKSDB_JAR) RocksDBSample.java
1717
@rm -rf /tmp/rocksdbjni
1818
@rm -rf /tmp/rocksdbjni_not_found
19-
java -ea -Djava.library.path=.:../ -cp ".:./*" -Xcheck:jni RocksDBSample /tmp/rocksdbjni
19+
java -ea -Djava.library.path=. -cp ".:./*" -Xcheck:jni RocksDBSample /tmp/rocksdbjni
2020
@rm -rf /tmp/rocksdbjni
2121
@rm -rf /tmp/rocksdbjni_not_found
2222

java/RocksDBSample.java

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// of patent rights can be found in the PATENTS file in the same directory.
55

66
import java.util.Arrays;
7+
import java.util.List;
8+
import java.util.ArrayList;
79
import org.rocksdb.*;
810
import org.rocksdb.util.SizeUnit;
911
import java.io.IOException;

java/org/rocksdb/RocksDB.java

+62
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
package org.rocksdb;
77

8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.HashMap;
811
import java.io.Closeable;
912
import java.io.IOException;
1013

@@ -142,6 +145,7 @@ public byte[] get(byte[] key) throws RocksDBException {
142145
* returned if the specified key is not found.
143146
*
144147
* @param key the key retrieve the value.
148+
* @param opt Read options.
145149
* @return a byte array storing the value associated with the input key if
146150
* any. null if it does not find the specified key.
147151
*
@@ -150,6 +154,60 @@ public byte[] get(byte[] key) throws RocksDBException {
150154
public byte[] get(ReadOptions opt, byte[] key) throws RocksDBException {
151155
return get(nativeHandle_, opt.nativeHandle_, key, key.length);
152156
}
157+
158+
/**
159+
* Returns a map of keys for which values were found in DB.
160+
*
161+
* @param keys List of keys for which values need to be retrieved.
162+
* @return Map where key of map is the key passed by user and value for map
163+
* entry is the corresponding value in DB.
164+
*
165+
* @see RocksDBException
166+
*/
167+
public Map<byte[], byte[]> multiGet(List<byte[]> keys)
168+
throws RocksDBException {
169+
List<byte[]> values = multiGet(
170+
nativeHandle_, keys, keys.size());
171+
172+
Map<byte[], byte[]> keyValueMap = new HashMap<byte[], byte[]>();
173+
for(int i = 0; i < values.size(); i++) {
174+
if(values.get(i) == null) {
175+
continue;
176+
}
177+
178+
keyValueMap.put(keys.get(i), values.get(i));
179+
}
180+
181+
return keyValueMap;
182+
}
183+
184+
185+
/**
186+
* Returns a map of keys for which values were found in DB.
187+
*
188+
* @param List of keys for which values need to be retrieved.
189+
* @param opt Read options.
190+
* @return Map where key of map is the key passed by user and value for map
191+
* entry is the corresponding value in DB.
192+
*
193+
* @see RocksDBException
194+
*/
195+
public Map<byte[], byte[]> multiGet(ReadOptions opt, List<byte[]> keys)
196+
throws RocksDBException {
197+
List<byte[]> values = multiGet(
198+
nativeHandle_, opt.nativeHandle_, keys, keys.size());
199+
200+
Map<byte[], byte[]> keyValueMap = new HashMap<byte[], byte[]>();
201+
for(int i = 0; i < values.size(); i++) {
202+
if(values.get(i) == null) {
203+
continue;
204+
}
205+
206+
keyValueMap.put(keys.get(i), values.get(i));
207+
}
208+
209+
return keyValueMap;
210+
}
153211

154212
/**
155213
* Remove the database entry (if any) for "key". Returns OK on
@@ -213,6 +271,10 @@ protected native int get(
213271
protected native int get(
214272
long handle, long readOptHandle, byte[] key, int keyLen,
215273
byte[] value, int valueLen) throws RocksDBException;
274+
protected native List<byte[]> multiGet(
275+
long dbHandle, List<byte[]> keys, int keysCount);
276+
protected native List<byte[]> multiGet(
277+
long dbHandle, long rOptHandle, List<byte[]> keys, int keysCount);
216278
protected native byte[] get(
217279
long handle, byte[] key, int keyLen) throws RocksDBException;
218280
protected native byte[] get(

java/rocksjni/portal.h

+64
Original file line numberDiff line numberDiff line change
@@ -315,5 +315,69 @@ class FilterJni {
315315
reinterpret_cast<jlong>(op));
316316
}
317317
};
318+
319+
class ListJni {
320+
public:
321+
// Get the java class id of java.util.List.
322+
static jclass getListClass(JNIEnv* env) {
323+
static jclass jclazz = env->FindClass("java/util/List");
324+
assert(jclazz != nullptr);
325+
return jclazz;
326+
}
327+
328+
// Get the java class id of java.util.ArrayList.
329+
static jclass getArrayListClass(JNIEnv* env) {
330+
static jclass jclazz = env->FindClass("java/util/ArrayList");
331+
assert(jclazz != nullptr);
332+
return jclazz;
333+
}
334+
335+
// Get the java class id of java.util.Iterator.
336+
static jclass getIteratorClass(JNIEnv* env) {
337+
static jclass jclazz = env->FindClass("java/util/Iterator");
338+
assert(jclazz != nullptr);
339+
return jclazz;
340+
}
341+
342+
// Get the java method id of java.util.List.iterator().
343+
static jmethodID getIteratorMethod(JNIEnv* env) {
344+
static jmethodID mid = env->GetMethodID(
345+
getListClass(env), "iterator", "()Ljava/util/Iterator;");
346+
assert(mid != nullptr);
347+
return mid;
348+
}
349+
350+
// Get the java method id of java.util.Iterator.hasNext().
351+
static jmethodID getHasNextMethod(JNIEnv* env) {
352+
static jmethodID mid = env->GetMethodID(
353+
getIteratorClass(env), "hasNext", "()Z");
354+
assert(mid != nullptr);
355+
return mid;
356+
}
357+
358+
// Get the java method id of java.util.Iterator.next().
359+
static jmethodID getNextMethod(JNIEnv* env) {
360+
static jmethodID mid = env->GetMethodID(
361+
getIteratorClass(env), "next", "()Ljava/lang/Object;");
362+
assert(mid != nullptr);
363+
return mid;
364+
}
365+
366+
// Get the java method id of arrayList constructor.
367+
static jmethodID getArrayListConstructorMethodId(JNIEnv* env, jclass jclazz) {
368+
static jmethodID mid = env->GetMethodID(
369+
jclazz, "<init>", "(I)V");
370+
assert(mid != nullptr);
371+
return mid;
372+
}
373+
374+
// Get the java method id of java.util.List.add().
375+
static jmethodID getListAddMethodId(JNIEnv* env) {
376+
static jmethodID mid = env->GetMethodID(
377+
getListClass(env), "add", "(Ljava/lang/Object;)Z");
378+
assert(mid != nullptr);
379+
return mid;
380+
}
381+
};
318382
} // namespace rocksdb
319383
#endif // JAVA_ROCKSJNI_PORTAL_H_

java/rocksjni/rocksjni.cc

+86
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stdlib.h>
1111
#include <jni.h>
1212
#include <string>
13+
#include <vector>
1314

1415
#include "include/org_rocksdb_RocksDB.h"
1516
#include "rocksjni/portal.h"
@@ -244,6 +245,91 @@ jint rocksdb_get_helper(
244245
return cvalue_len;
245246
}
246247

248+
jobject multi_get_helper(JNIEnv* env, jobject jdb, rocksdb::DB* db,
249+
const rocksdb::ReadOptions& rOpt, jobject jkey_list, jint jkeys_count) {
250+
std::vector<rocksdb::Slice> keys;
251+
std::vector<jbyte*> keys_to_free;
252+
253+
// get iterator
254+
jobject iteratorObj = env->CallObjectMethod(
255+
jkey_list, rocksdb::ListJni::getIteratorMethod(env));
256+
257+
// iterate over keys and convert java byte array to slice
258+
while(env->CallBooleanMethod(
259+
iteratorObj, rocksdb::ListJni::getHasNextMethod(env)) == JNI_TRUE) {
260+
jbyteArray jkey = (jbyteArray) env->CallObjectMethod(
261+
iteratorObj, rocksdb::ListJni::getNextMethod(env));
262+
jint key_length = env->GetArrayLength(jkey);
263+
264+
jbyte* key = new jbyte[key_length];
265+
env->GetByteArrayRegion(jkey, 0, key_length, key);
266+
// store allocated jbyte to free it after multiGet call
267+
keys_to_free.push_back(key);
268+
269+
rocksdb::Slice key_slice(
270+
reinterpret_cast<char*>(key), key_length);
271+
keys.push_back(key_slice);
272+
}
273+
274+
std::vector<std::string> values;
275+
std::vector<rocksdb::Status> s = db->MultiGet(rOpt, keys, &values);
276+
277+
// Don't reuse class pointer
278+
jclass jclazz = env->FindClass("java/util/ArrayList");
279+
jmethodID mid = rocksdb::ListJni::getArrayListConstructorMethodId(
280+
env, jclazz);
281+
jobject jvalue_list = env->NewObject(jclazz, mid, jkeys_count);
282+
283+
// insert in java list
284+
for(std::vector<rocksdb::Status>::size_type i = 0; i != s.size(); i++) {
285+
if(s[i].ok()) {
286+
jbyteArray jvalue = env->NewByteArray(values[i].size());
287+
env->SetByteArrayRegion(
288+
jvalue, 0, values[i].size(),
289+
reinterpret_cast<const jbyte*>(values[i].c_str()));
290+
env->CallBooleanMethod(
291+
jvalue_list, rocksdb::ListJni::getListAddMethodId(env), jvalue);
292+
}
293+
else {
294+
env->CallBooleanMethod(
295+
jvalue_list, rocksdb::ListJni::getListAddMethodId(env), nullptr);
296+
}
297+
}
298+
299+
// free up allocated byte arrays
300+
for(std::vector<jbyte*>::size_type i = 0; i != keys_to_free.size(); i++) {
301+
delete[] keys_to_free[i];
302+
}
303+
keys_to_free.clear();
304+
305+
return jvalue_list;
306+
}
307+
308+
/*
309+
* Class: org_rocksdb_RocksDB
310+
* Method: multiGet
311+
* Signature: (JLjava/util/List;I)Ljava/util/List;
312+
*/
313+
jobject Java_org_rocksdb_RocksDB_multiGet(
314+
JNIEnv* env, jobject jdb, jlong jdb_handle,
315+
jobject jkey_list, jint jkeys_count) {
316+
return multi_get_helper(env, jdb, reinterpret_cast<rocksdb::DB*>(jdb_handle),
317+
rocksdb::ReadOptions(), jkey_list, jkeys_count);
318+
}
319+
320+
/*
321+
* Class: org_rocksdb_RocksDB
322+
* Method: multiGet
323+
* Signature: (JJLjava/util/List;I)Ljava/util/List;
324+
*/
325+
jobject Java_org_rocksdb_RocksDB_multiGet(
326+
JNIEnv* env, jobject jdb, jlong jdb_handle,
327+
jlong jropt_handle, jobject jkey_list, jint jkeys_count) {
328+
return multi_get_helper(env, jdb, reinterpret_cast<rocksdb::DB*>(jdb_handle),
329+
*reinterpret_cast<rocksdb::ReadOptions*>(jropt_handle), jkey_list,
330+
jkeys_count);
331+
}
332+
247333
/*
248334
* Class: org_rocksdb_RocksDB
249335
* Method: get

0 commit comments

Comments
 (0)