Add a java api for rocksdb::Options, currently only supports create_if_missing.

Summary:
* [java] Add a java api for rocksdb::Options, currently only supports create_if_missing.
* [java] Add a test for RocksDBException in RocksDBSample.

Test Plan: make jtest

Reviewers: haobo, sdong

Reviewed By: haobo

CC: leveldb, dhruba

Differential Revision: https://reviews.facebook.net/D17385
main
Yueh-Hsuan Chiang 11 years ago
parent e0a87c4cf1
commit 8c4a3bfa5b
  1. 2
      Makefile
  2. 8
      java/Makefile
  3. 25
      java/RocksDBSample.java
  4. 69
      java/org/rocksdb/Options.java
  5. 18
      java/org/rocksdb/RocksDB.java
  6. 57
      java/rocksjni/options.cc
  7. 32
      java/rocksjni/portal.h
  8. 38
      java/rocksjni/rocksjni.cc

@ -402,7 +402,7 @@ ldb: tools/ldb.o $(LIBOBJECTS)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Jni stuff # Jni stuff
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
JNI_NATIVE_SOURCES = ./java/rocksjni/rocksjni.cc JNI_NATIVE_SOURCES = ./java/rocksjni/rocksjni.cc ./java/rocksjni/options.cc
JAVA_INCLUDE = -I/usr/lib/jvm/java-openjdk/include/ -I/usr/lib/jvm/java-openjdk/include/linux JAVA_INCLUDE = -I/usr/lib/jvm/java-openjdk/include/ -I/usr/lib/jvm/java-openjdk/include/linux
ROCKSDBJNILIB = ./java/librocksdbjni.so ROCKSDBJNILIB = ./java/librocksdbjni.so

@ -1,4 +1,4 @@
NATIVE_JAVA_CLASSES = org.rocksdb.RocksDB NATIVE_JAVA_CLASSES = org.rocksdb.RocksDB org.rocksdb.Options
NATIVE_INCLUDE = ./include NATIVE_INCLUDE = ./include
ROCKSDB_JAR = rocksdbjni.jar ROCKSDB_JAR = rocksdbjni.jar
@ -14,4 +14,8 @@ java:
sample: sample:
javac -cp $(ROCKSDB_JAR) RocksDBSample.java javac -cp $(ROCKSDB_JAR) RocksDBSample.java
java -ea -Djava.library.path=.:../ -cp ".:./*" RocksDBSample /tmp/rocksdbjni/ @rm -rf /tmp/rocksdbjni
@rm -rf /tmp/rocksdbjni_not_found
java -ea -Djava.library.path=.:../ -cp ".:./*" RocksDBSample /tmp/rocksdbjni
@rm -rf /tmp/rocksdbjni
@rm -rf /tmp/rocksdbjni_not_found

@ -19,9 +19,34 @@ public class RocksDBSample {
return; return;
} }
String db_path = args[0]; String db_path = args[0];
String db_path_not_found = db_path + "_not_found";
System.out.println("RocksDBSample"); System.out.println("RocksDBSample");
RocksDB db = null; RocksDB db = null;
Options options = new Options();
try {
db = RocksDB.open(options, db_path_not_found);
assert(false);
} catch (RocksDBException e) {
System.out.format("caught the expceted exception -- %s\n", e);
assert(db == null);
}
options.setCreateIfMissing(true);
try {
db = RocksDB.open(options, db_path_not_found);
db.put("hello".getBytes(), "world".getBytes());
byte[] value = db.get("hello".getBytes());
assert("world".equals(new String(value)));
} catch (RocksDBException e) {
System.out.format("[ERROR] caught the unexpceted exception -- %s\n", e);
assert(db == null);
assert(false);
}
// be sure to release the c++ pointer
options.dispose();
db.close();
try { try {
db = RocksDB.open(db_path); db = RocksDB.open(db_path);

@ -0,0 +1,69 @@
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
package org.rocksdb;
/**
* Options to control the behavior of a database. It will be used
* during the creation of a RocksDB (i.e., RocksDB::Open()).
*
* Note that dispose() must be called before an Options instance
* become out-of-scope to release the allocated memory in c++.
*/
public class Options {
/**
* Construct options for opening a RocksDB.
*
* This constructor will create (by allocating a block of memory)
* an rocksdb::Options in the c++ side.
*/
public Options() {
nativeHandle_ = 0;
newOptions();
}
/**
* If this value is set to true, then the database will be created
* if it is missing during RocksDB::Open().
* Default: false
*
* @param flag a flag indicating whether to create a database the
* specified database in RocksDB::Open() operation is missing.
* @see RocksDB::Open()
*/
public void setCreateIfMissing(boolean flag) {
assert(nativeHandle_ != 0);
setCreateIfMissing(nativeHandle_, flag);
}
/**
* Return true if the create_if_missing flag is set to true.
* If true, the database will be created if it is missing.
*
* @return return true if the create_if_missing flag is set to true.
* @see setCreateIfMissing()
*/
public boolean craeteIfMissing() {
assert(nativeHandle_ != 0);
return createIfMissing(nativeHandle_);
}
/**
* Release the memory allocated for the current instance
* in the c++ side.
*/
public synchronized void dispose() {
if (nativeHandle_ != 0) {
dispose0();
}
}
private native void newOptions();
private native void dispose0();
private native void setCreateIfMissing(long handle, boolean flag);
private native boolean createIfMissing(long handle);
long nativeHandle_;
}

@ -20,12 +20,16 @@ public class RocksDB {
public static final int NOT_FOUND = -1; public static final int NOT_FOUND = -1;
/** /**
* The factory constructor of RocksDB that opens a RocksDB instance given * The factory constructor of RocksDB that opens a RocksDB instance given
* the path to the database. * the path to the database using the default options w/ createIfMissing
* set to true.
* *
* @param path the path to the rocksdb. * @param path the path to the rocksdb.
* @param status an out value indicating the status of the Open(). * @param status an out value indicating the status of the Open().
* @return a rocksdb instance on success, null if the specified rocksdb can * @return a rocksdb instance on success, null if the specified rocksdb can
* not be opened. * not be opened.
*
* @see Options.setCreateIfMissing()
* @see Options.createIfMissing()
*/ */
public static RocksDB open(String path) throws RocksDBException { public static RocksDB open(String path) throws RocksDBException {
RocksDB db = new RocksDB(); RocksDB db = new RocksDB();
@ -33,6 +37,17 @@ public class RocksDB {
return db; return db;
} }
/**
* The factory constructor of RocksDB that opens a RocksDB instance given
* the path to the database using the specified options and db path.
*/
public static RocksDB open(Options options, String path)
throws RocksDBException {
RocksDB db = new RocksDB();
db.open(options.nativeHandle_, path);
return db;
}
public synchronized void close() { public synchronized void close() {
if (nativeHandle_ != 0) { if (nativeHandle_ != 0) {
close0(); close0();
@ -93,6 +108,7 @@ public class RocksDB {
// native methods // native methods
private native void open0(String path) throws RocksDBException; private native void open0(String path) throws RocksDBException;
private native void open(long optionsHandle, String path) throws RocksDBException;
private native void put( private native void put(
byte[] key, int keyLen, byte[] key, int keyLen,
byte[] value, int valueLen) throws RocksDBException; byte[] value, int valueLen) throws RocksDBException;

@ -0,0 +1,57 @@
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// This file implements the "bridge" between Java and C++ for rocksdb::Options.
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <string>
#include "include/org_rocksdb_Options.h"
#include "rocksjni/portal.h"
#include "rocksdb/db.h"
/*
* Class: org_rocksdb_Options
* Method: newOptions
* Signature: ()V
*/
void Java_org_rocksdb_Options_newOptions(JNIEnv* env, jobject jobj) {
rocksdb::Options* op = new rocksdb::Options();
rocksdb::OptionsJni::setHandle(env, jobj, op);
}
/*
* Class: org_rocksdb_Options
* Method: dispose0
* Signature: ()V
*/
void Java_org_rocksdb_Options_dispose0(JNIEnv* env, jobject jobj) {
rocksdb::Options* op = rocksdb::OptionsJni::getHandle(env, jobj);
delete op;
rocksdb::OptionsJni::setHandle(env, jobj, op);
}
/*
* Class: org_rocksdb_Options
* Method: setCreateIfMissing
* Signature: (JZ)V
*/
void Java_org_rocksdb_Options_setCreateIfMissing(
JNIEnv* env, jobject jobj, jlong jhandle, jboolean flag) {
reinterpret_cast<rocksdb::Options*>(jhandle)->create_if_missing = flag;
}
/*
* Class: org_rocksdb_Options
* Method: createIfMissing
* Signature: (J)Z
*/
jboolean Java_org_rocksdb_Options_createIfMissing(
JNIEnv* env, jobject jobj, jlong jhandle) {
return reinterpret_cast<rocksdb::Options*>(jhandle)->create_if_missing;
}

@ -77,5 +77,37 @@ class RocksDBExceptionJni {
} }
}; };
class OptionsJni {
public:
// Get the java class id of org.rocksdb.Options.
static jclass getJClass(JNIEnv* env) {
static jclass jclazz = env->FindClass("org/rocksdb/Options");
assert(jclazz != nullptr);
return jclazz;
}
// Get the field id of the member variable of org.rocksdb.Options
// that stores the pointer to rocksdb::Options
static jfieldID getHandleFieldID(JNIEnv* env) {
static jfieldID fid = env->GetFieldID(
getJClass(env), "nativeHandle_", "J");
assert(fid != nullptr);
return fid;
}
// Get the pointer to rocksdb::Options
static rocksdb::Options* getHandle(JNIEnv* env, jobject jobj) {
return reinterpret_cast<rocksdb::Options*>(
env->GetLongField(jobj, getHandleFieldID(env)));
}
// Pass the rocksdb::Options pointer to the java side.
static void setHandle(JNIEnv* env, jobject jobj, rocksdb::Options* op) {
env->SetLongField(
jobj, getHandleFieldID(env),
reinterpret_cast<jlong>(op));
}
};
} // namespace rocksdb } // namespace rocksdb
#endif // JAVA_ROCKSJNI_PORTAL_H_ #endif // JAVA_ROCKSJNI_PORTAL_H_

@ -15,27 +15,43 @@
#include "rocksjni/portal.h" #include "rocksjni/portal.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
void rocksdb_open_helper(
JNIEnv* env, jobject java_db, jstring jdb_path, const rocksdb::Options& opt) {
rocksdb::DB* db;
const char* db_path = env->GetStringUTFChars(jdb_path, 0);
rocksdb::Status s = rocksdb::DB::Open(opt, db_path, &db);
env->ReleaseStringUTFChars(jdb_path, db_path);
if (s.ok()) {
rocksdb::RocksDBJni::setHandle(env, java_db, db);
return;
}
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
}
/* /*
* Class: org_rocksdb_RocksDB * Class: org_rocksdb_RocksDB
* Method: open0 * Method: open0
* Signature: (Ljava/lang/String;)V * Signature: (Ljava/lang/String;)V
*/ */
void Java_org_rocksdb_RocksDB_open0( void Java_org_rocksdb_RocksDB_open0(
JNIEnv* env, jobject java_db, jstring jdb_path) { JNIEnv* env, jobject jdb, jstring jdb_path) {
rocksdb::DB* db;
rocksdb::Options options; rocksdb::Options options;
options.create_if_missing = true; options.create_if_missing = true;
jboolean isCopy = false; rocksdb_open_helper(env, jdb, jdb_path, options);
const char* db_path = env->GetStringUTFChars(jdb_path, &isCopy);
rocksdb::Status s = rocksdb::DB::Open(options, db_path, &db);
env->ReleaseStringUTFChars(jdb_path, db_path);
if (s.ok()) {
rocksdb::RocksDBJni::setHandle(env, java_db, db);
return;
} }
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
/*
* Class: org_rocksdb_RocksDB
* Method: open
* Signature: (JLjava/lang/String;)V
*/
void Java_org_rocksdb_RocksDB_open(
JNIEnv* env, jobject jdb, jlong jopt_handle, jstring jdb_path) {
auto options = reinterpret_cast<rocksdb::Options*>(jopt_handle);
rocksdb_open_helper(env, jdb, jdb_path, *options);
} }
/* /*

Loading…
Cancel
Save