[Java] Add a basic binding and test for BackupableDB and StackableDB.

Summary:
Add a skeleton binding and test for BackupableDB which shows that BackupableDB
and RocksDB can share the same JNI calls.

Test Plan:
make rocksdbjava
make jtest

Reviewers: haobo, ankgup87, sdong, dhruba

Reviewed By: haobo

CC: leveldb

Differential Revision: https://reviews.facebook.net/D17793
This commit is contained in:
Yueh-Hsuan Chiang
2014-04-17 17:28:51 -07:00
parent 651792251a
commit bb6fd15a6e
9 changed files with 315 additions and 13 deletions

View File

@@ -0,0 +1,84 @@
// 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;
/**
* A subclass of RocksDB which supports backup-related operations.
*
* @see BackupableDBOptions
*/
public class BackupableDB extends RocksDB {
/**
* Open a BackupableDB under the specified path.
* Note that the backup path should be set properly in the
* input BackupableDBOptions.
*
* @param opt options for db.
* @param bopt backup related options.
* @param the db path for storing data. The path for storing
* backup should be specified in the BackupableDBOptions.
* @return reference to the opened BackupableDB.
*/
public static BackupableDB open(
Options opt, BackupableDBOptions bopt, String db_path)
throws RocksDBException {
// since BackupableDB c++ will handle the life cycle of
// the returned RocksDB of RocksDB.open(), here we store
// it as a BackupableDB member variable to avoid GC.
BackupableDB bdb = new BackupableDB(RocksDB.open(opt, db_path));
bdb.open(bdb.db_.nativeHandle_, bopt.nativeHandle_);
return bdb;
}
/**
* Captures the state of the database in the latest backup.
* Note that this function is not thread-safe.
*
* @param flushBeforeBackup if true, then all data will be flushed
* before creating backup.
*/
public void createNewBackup(boolean flushBeforeBackup) {
createNewBackup(nativeHandle_, flushBeforeBackup);
}
/**
* Close the BackupableDB instance and release resource.
*
* Internally, BackupableDB owns the rocksdb::DB pointer to its
* associated RocksDB. The release of that RocksDB pointer is
* handled in the destructor of the c++ rocksdb::BackupableDB and
* should be transparent to Java developers.
*/
@Override public synchronized void close() {
if (isOpened()) {
super.close0();
}
}
/**
* A protected construction that will be used in the static factory
* method BackupableDB.open().
*/
protected BackupableDB(RocksDB db) {
super();
db_ = db;
}
@Override protected void finalize() {
close();
}
private boolean isOpened() {
return nativeHandle_ != 0;
}
protected native void open(long rocksDBHandle, long backupDBOptionsHandle);
protected native void createNewBackup(long handle, boolean flag);
private final RocksDB db_;
}

View File

@@ -0,0 +1,52 @@
// 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;
/**
* BackupableDBOptions to control the behavior of a backupable database.
* It will be used during the creation of a BackupableDB.
*
* Note that dispose() must be called before an Options instance
* become out-of-scope to release the allocated memory in c++.
*/
public class BackupableDBOptions {
public BackupableDBOptions(String path) {
newBackupableDBOptions(path);
}
/**
* Returns the path to the BackupableDB directory.
*
* @return the path to the BackupableDB directory.
*/
public String backupDir() {
assert(isInitialized());
return backupDir(nativeHandle_);
}
/**
* Release the memory allocated for the current instance
* in the c++ side.
*/
public synchronized void dispose() {
if (isInitialized()) {
dispose(nativeHandle_);
}
}
@Override protected void finalize() {
dispose();
}
boolean isInitialized() {
return nativeHandle_ != 0;
}
private native void newBackupableDBOptions(String path);
private native String backupDir(long handle);
private native void dispose(long handle);
long nativeHandle_;
}

View File

@@ -228,6 +228,10 @@ public class Options {
}
}
@Override protected void finalize() {
dispose();
}
private boolean isInitialized() {
return (nativeHandle_ != 0);
}

View File

@@ -145,33 +145,33 @@ public class RocksDB {
/**
* Private constructor.
*/
private RocksDB() {
protected RocksDB() {
nativeHandle_ = 0;
}
// native methods
private native void open(
protected native void open(
long optionsHandle, long cacheSize, String path) throws RocksDBException;
private native void put(
protected native void put(
long handle, byte[] key, int keyLen,
byte[] value, int valueLen) throws RocksDBException;
private native void put(
protected native void put(
long handle, long writeOptHandle,
byte[] key, int keyLen,
byte[] value, int valueLen) throws RocksDBException;
private native void write(
protected native void write(
long writeOptHandle, long batchHandle) throws RocksDBException;
private native int get(
protected native int get(
long handle, byte[] key, int keyLen,
byte[] value, int valueLen) throws RocksDBException;
private native byte[] get(
protected native byte[] get(
long handle, byte[] key, int keyLen) throws RocksDBException;
private native void remove(
protected native void remove(
long handle, byte[] key, int keyLen) throws RocksDBException;
private native void remove(
protected native void remove(
long handle, long writeOptHandle,
byte[] key, int keyLen) throws RocksDBException;
private native void close0();
protected native void close0();
private long nativeHandle_;
protected long nativeHandle_;
}

View File

@@ -0,0 +1,41 @@
// 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.test;
import org.rocksdb.*;
public class BackupableDBTest {
static final String db_path = "/tmp/backupablejni_db";
static final String backup_path = "/tmp/backupablejni_db_backup";
static {
System.loadLibrary("rocksdbjni");
}
public static void main(String[] args) {
Options opt = new Options();
opt.setCreateIfMissing(true);
BackupableDBOptions bopt = new BackupableDBOptions(backup_path);
BackupableDB bdb = null;
try {
bdb = BackupableDB.open(opt, bopt, db_path);
bdb.put("hello".getBytes(), "BackupableDB".getBytes());
bdb.createNewBackup(true);
byte[] value = bdb.get("hello".getBytes());
assert(new String(value).equals("BackupableDB"));
} catch (RocksDBException e) {
System.err.format("[ERROR]: %s%n", e);
e.printStackTrace();
} finally {
opt.dispose();
bopt.dispose();
if (bdb != null) {
bdb.close();
}
}
}
}