From 036e323f7a30d3353cfac78b02479d3a241e49c4 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Tue, 13 May 2014 22:20:58 -0700 Subject: [PATCH] Add RestoreBackupableDB and RestoreOptions --- java/org/rocksdb/RestoreBackupableDB.java | 85 ++++++++++++ java/org/rocksdb/RestoreOptions.java | 38 ++++++ java/rocksjni/restorejni.cc | 149 ++++++++++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 java/org/rocksdb/RestoreBackupableDB.java create mode 100644 java/org/rocksdb/RestoreOptions.java create mode 100644 java/rocksjni/restorejni.cc diff --git a/java/org/rocksdb/RestoreBackupableDB.java b/java/org/rocksdb/RestoreBackupableDB.java new file mode 100644 index 000000000..117881f33 --- /dev/null +++ b/java/org/rocksdb/RestoreBackupableDB.java @@ -0,0 +1,85 @@ +// 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; + +/** + * This class is used to access information about backups and restore from them. + * + * Note that dispose() must be called before this instance become out-of-scope + * to release the allocated memory in c++. + * + * @param options Instance of BackupableDBOptions. + */ +public class RestoreBackupableDB extends RocksObject { + public RestoreBackupableDB(BackupableDBOptions options) { + super(); + newRestoreBackupableDB(options.nativeHandle_); + } + + /** + * Restore from backup with backup_id + * IMPORTANT -- if options_.share_table_files == true and you restore DB + * from some backup that is not the latest, and you start creating new + * backups from the new DB, they will probably fail. + * + * Example: Let's say you have backups 1, 2, 3, 4, 5 and you restore 3. + * If you add new data to the DB and try creating a new backup now, the + * database will diverge from backups 4 and 5 and the new backup will fail. + * If you want to create new backup, you will first have to delete backups 4 + * and 5. + */ + public void restoreDBFromBackup(long backupId, String dbDir, String walDir, + RestoreOptions restoreOptions) throws RocksDBException { + restoreDBFromBackup0(nativeHandle_, backupId, dbDir, walDir, + restoreOptions.nativeHandle_); + } + + /** + * Restore from the latest backup. + */ + public void restoreDBFromLatestBackup(String dbDir, String walDir, + RestoreOptions restoreOptions) throws RocksDBException { + restoreDBFromLatestBackup0(nativeHandle_, dbDir, walDir, + restoreOptions.nativeHandle_); + } + + /** + * Deletes old backups, keeping latest numBackupsToKeep alive. + * + * @param Number of latest backups to keep + */ + public void purgeOldBackups(int numBackupsToKeep) throws RocksDBException { + purgeOldBackups0(nativeHandle_, numBackupsToKeep); + } + + /** + * Deletes a specific backup. + * + * @param ID of backup to delete. + */ + public void deleteBackup(long backupId) throws RocksDBException { + deleteBackup0(nativeHandle_, backupId); + } + + /** + * Release the memory allocated for the current instance + * in the c++ side. + */ + @Override public synchronized void dispose() { + if (isInitialized()) { + dispose(nativeHandle_); + } + } + + private native void newRestoreBackupableDB(long options); + private native void restoreDBFromBackup0(long nativeHandle, long backupId, + String dbDir, String walDir, long restoreOptions) throws RocksDBException; + private native void restoreDBFromLatestBackup0(long nativeHandle, + String dbDir, String walDir, long restoreOptions) throws RocksDBException; + private native void purgeOldBackups0(long nativeHandle, int numBackupsToKeep); + private native void deleteBackup0(long nativeHandle, long backupId); + private native void dispose(long nativeHandle); +} \ No newline at end of file diff --git a/java/org/rocksdb/RestoreOptions.java b/java/org/rocksdb/RestoreOptions.java new file mode 100644 index 000000000..a451bd2dd --- /dev/null +++ b/java/org/rocksdb/RestoreOptions.java @@ -0,0 +1,38 @@ +// 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; + +/** + * RestoreOptions to control the behavior of restore. + * + * Note that dispose() must be called before this instance become out-of-scope + * to release the allocated memory in c++. + * + * @param If true, restore won't overwrite the existing log files in wal_dir. It + * will also move all log files from archive directory to wal_dir. Use this + * option in combination with BackupableDBOptions::backup_log_files = false + * for persisting in-memory databases. + * Default: false + */ +public class RestoreOptions extends RocksObject { + public RestoreOptions(boolean keepLogFiles) { + super(); + newRestoreOptions(keepLogFiles); + } + + /** + * Release the memory allocated for the current instance + * in the c++ side. + */ + @Override public synchronized void dispose() { + if (isInitialized()) { + dispose(nativeHandle_); + } + } + + private native void newRestoreOptions(boolean keepLogFiles); + private native void dispose(long handle); +} \ No newline at end of file diff --git a/java/rocksjni/restorejni.cc b/java/rocksjni/restorejni.cc new file mode 100644 index 000000000..185b780a5 --- /dev/null +++ b/java/rocksjni/restorejni.cc @@ -0,0 +1,149 @@ +// 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++ and enables +// calling c++ rocksdb::RestoreBackupableDB and rocksdb::RestoreOptions methods +// from Java side. + +#include +#include +#include +#include +#include + +#include "include/org_rocksdb_RestoreOptions.h" +#include "include/org_rocksdb_RestoreBackupableDB.h" +#include "rocksjni/portal.h" +#include "utilities/backupable_db.h" +/* + * Class: org_rocksdb_RestoreOptions + * Method: newRestoreOptions + * Signature: (Z)V + */ +void Java_org_rocksdb_RestoreOptions_newRestoreOptions(JNIEnv* env, + jobject jobj, jboolean keep_log_files) { + auto ropt = new rocksdb::RestoreOptions(keep_log_files); + rocksdb::RestoreOptionsJni::setHandle(env, jobj, ropt); +} + +/* + * Class: org_rocksdb_RestoreOptions + * Method: dispose + * Signature: (J)V + */ +void Java_org_rocksdb_RestoreOptions_dispose(JNIEnv* env, jobject jobj, + jlong jhandle) { + auto ropt = reinterpret_cast(jhandle); + assert(ropt); + delete ropt; + + rocksdb::RestoreOptionsJni::setHandle(env, jobj, nullptr); +} + +/* + * Class: org_rocksdb_RestoreBackupableDB + * Method: newRestoreBackupableDB + * Signature: (J)V + */ +void Java_org_rocksdb_RestoreBackupableDB_newRestoreBackupableDB(JNIEnv* env, + jobject jobj, jlong jopt_handle) { + auto opt = reinterpret_cast(jopt_handle); + auto rdb = new rocksdb::RestoreBackupableDB(rocksdb::Env::Default(), *opt); + rocksdb::RestoreBackupableDBJni::setHandle(env, jobj, rdb); +} + +/* + * Class: org_rocksdb_RestoreBackupableDB + * Method: restoreDBFromBackup0 + * Signature: (JJLjava/lang/String;Ljava/lang/String;J)V + */ +void Java_org_rocksdb_RestoreBackupableDB_restoreDBFromBackup0(JNIEnv* env, + jobject jobj, jlong jhandle, jlong jbackup_id, jstring jdb_dir, + jstring jwal_dir, jlong jopt_handle) { + auto opt = reinterpret_cast(jopt_handle); + + const char* cdb_dir = env->GetStringUTFChars(jdb_dir, 0); + const char* cwal_dir = env->GetStringUTFChars(jwal_dir, 0); + + auto rdb = reinterpret_cast(jhandle); + rocksdb::Status s = + rdb->RestoreDBFromBackup(jbackup_id, cdb_dir, cwal_dir, *opt); + + env->ReleaseStringUTFChars(jdb_dir, cdb_dir); + env->ReleaseStringUTFChars(jwal_dir, cwal_dir); + + if(!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RestoreBackupableDB + * Method: restoreDBFromLatestBackup0 + * Signature: (JLjava/lang/String;Ljava/lang/String;J)V + */ +void Java_org_rocksdb_RestoreBackupableDB_restoreDBFromLatestBackup0( + JNIEnv* env, jobject jobj, jlong jhandle, jstring jdb_dir, jstring jwal_dir, + jlong jopt_handle) { + auto opt = reinterpret_cast(jopt_handle); + + const char* cdb_dir = env->GetStringUTFChars(jdb_dir, 0); + const char* cwal_dir = env->GetStringUTFChars(jwal_dir, 0); + + auto rdb = reinterpret_cast(jhandle); + rocksdb::Status s = + rdb->RestoreDBFromLatestBackup(cdb_dir, cwal_dir, *opt); + + env->ReleaseStringUTFChars(jdb_dir, cdb_dir); + env->ReleaseStringUTFChars(jwal_dir, cwal_dir); + + if(!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RestoreBackupableDB + * Method: purgeOldBackups0 + * Signature: (JI)V + */ +void Java_org_rocksdb_RestoreBackupableDB_purgeOldBackups0(JNIEnv* env, + jobject jobj, jlong jhandle, jint jnum_backups_to_keep) { + auto rdb = reinterpret_cast(jhandle); + rocksdb::Status s = rdb->PurgeOldBackups(jnum_backups_to_keep); + + if(!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RestoreBackupableDB + * Method: deleteBackup0 + * Signature: (JJ)V + */ +void Java_org_rocksdb_RestoreBackupableDB_deleteBackup0(JNIEnv* env, + jobject jobj, jlong jhandle, jlong jbackup_id) { + auto rdb = reinterpret_cast(jhandle); + rocksdb::Status s = rdb->DeleteBackup(jbackup_id); + + if(!s.ok()) { + rocksdb::RocksDBExceptionJni::ThrowNew(env, s); + } +} + +/* + * Class: org_rocksdb_RestoreBackupableDB + * Method: dispose + * Signature: (J)V + */ +void Java_org_rocksdb_RestoreBackupableDB_dispose(JNIEnv* env, jobject jobj, + jlong jhandle) { + auto ropt = reinterpret_cast(jhandle); + assert(ropt); + delete ropt; + + rocksdb::RestoreBackupableDBJni::setHandle(env, jobj, nullptr); +} \ No newline at end of file