[RocksJava] - BackupInfos & Restore-/BackupableDB enhancements
Summary: - BackupableDB deleteBackup method - BackupableDB purgeOldBackups bugfix - BackupInfos now available in Restorable-/BackupableDB - Extended BackupableDBTest to cover more of the currently implemented functionality. Test Plan: make rocksdbjava make jtest Differential Revision: https://reviews.facebook.net/D27027
This commit is contained in:
parent
eb357af58c
commit
7e12ae5a21
67
java/org/rocksdb/BackupInfo.java
Normal file
67
java/org/rocksdb/BackupInfo.java
Normal file
@ -0,0 +1,67 @@
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Instances of this class describe a Backup made by
|
||||
* {@link org.rocksdb.BackupableDB}.
|
||||
*/
|
||||
public class BackupInfo {
|
||||
|
||||
/**
|
||||
* Package private constructor used to create instances
|
||||
* of BackupInfo by {@link org.rocksdb.BackupableDB} and
|
||||
* {@link org.rocksdb.RestoreBackupableDB}.
|
||||
*
|
||||
* @param backupId id of backup
|
||||
* @param timestamp timestamp of backup
|
||||
* @param size size of backup
|
||||
* @param numberFiles number of files related to this backup.
|
||||
*/
|
||||
BackupInfo(int backupId, long timestamp, long size,
|
||||
int numberFiles) {
|
||||
backupId_ = backupId;
|
||||
timestamp_ = timestamp;
|
||||
size_ = size;
|
||||
numberFiles_ = numberFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the backup id.
|
||||
*/
|
||||
public int backupId() {
|
||||
return backupId_;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the timestamp of the backup.
|
||||
*/
|
||||
public long timestamp() {
|
||||
return timestamp_;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the size of the backup
|
||||
*/
|
||||
public long size() {
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the number of files of this backup.
|
||||
*/
|
||||
public int numberFiles() {
|
||||
return numberFiles_;
|
||||
}
|
||||
|
||||
private int backupId_;
|
||||
private long timestamp_;
|
||||
private long size_;
|
||||
private int numberFiles_;
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
|
||||
package org.rocksdb;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A subclass of RocksDB which supports backup-related operations.
|
||||
*
|
||||
@ -43,8 +45,10 @@ public class BackupableDB extends RocksDB {
|
||||
*
|
||||
* @param flushBeforeBackup if true, then all data will be flushed
|
||||
* before creating backup.
|
||||
* @throws org.rocksdb.RocksDBException
|
||||
*/
|
||||
public void createNewBackup(boolean flushBeforeBackup) {
|
||||
public void createNewBackup(boolean flushBeforeBackup)
|
||||
throws RocksDBException {
|
||||
createNewBackup(nativeHandle_, flushBeforeBackup);
|
||||
}
|
||||
|
||||
@ -52,11 +56,32 @@ public class BackupableDB extends RocksDB {
|
||||
* Deletes old backups, keeping latest numBackupsToKeep alive.
|
||||
*
|
||||
* @param numBackupsToKeep Number of latest backups to keep.
|
||||
* @throws org.rocksdb.RocksDBException
|
||||
*/
|
||||
public void purgeOldBackups(int numBackupsToKeep) {
|
||||
public void purgeOldBackups(int numBackupsToKeep)
|
||||
throws RocksDBException {
|
||||
purgeOldBackups(nativeHandle_, numBackupsToKeep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a specific backup.
|
||||
*
|
||||
* @param backupId of backup to delete.
|
||||
* @throws org.rocksdb.RocksDBException
|
||||
*/
|
||||
public void deleteBackup(long backupId) throws RocksDBException {
|
||||
deleteBackup0(nativeHandle_, backupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of {@link BackupInfo} instances, which describe
|
||||
* already made backups.
|
||||
*
|
||||
* @return List of {@link BackupInfo} instances.
|
||||
*/
|
||||
public List<BackupInfo> getBackupInfos() {
|
||||
return getBackupInfo(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the BackupableDB instance and release resource.
|
||||
@ -85,6 +110,11 @@ public class BackupableDB extends RocksDB {
|
||||
}
|
||||
|
||||
protected native void open(long rocksDBHandle, long backupDBOptionsHandle);
|
||||
protected native void createNewBackup(long handle, boolean flag);
|
||||
protected native void purgeOldBackups(long handle, int numBackupsToKeep);
|
||||
protected native void createNewBackup(long handle, boolean flag)
|
||||
throws RocksDBException;
|
||||
protected native void purgeOldBackups(long handle, int numBackupsToKeep)
|
||||
throws RocksDBException;
|
||||
private native void deleteBackup0(long nativeHandle, long backupId)
|
||||
throws RocksDBException;
|
||||
protected native List<BackupInfo> getBackupInfo(long handle);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
package org.rocksdb;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used to access information about backups and restore from them.
|
||||
*
|
||||
@ -65,6 +67,7 @@ public class RestoreBackupableDB extends RocksObject {
|
||||
* Deletes old backups, keeping latest numBackupsToKeep alive.
|
||||
*
|
||||
* @param numBackupsToKeep of latest backups to keep
|
||||
* @throws org.rocksdb.RocksDBException
|
||||
*/
|
||||
public void purgeOldBackups(int numBackupsToKeep) throws RocksDBException {
|
||||
purgeOldBackups0(nativeHandle_, numBackupsToKeep);
|
||||
@ -74,11 +77,22 @@ public class RestoreBackupableDB extends RocksObject {
|
||||
* Deletes a specific backup.
|
||||
*
|
||||
* @param backupId of backup to delete.
|
||||
* @throws org.rocksdb.RocksDBException
|
||||
*/
|
||||
public void deleteBackup(long backupId) throws RocksDBException {
|
||||
deleteBackup0(nativeHandle_, backupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of {@link BackupInfo} instances, which describe
|
||||
* already made backups.
|
||||
*
|
||||
* @return List of {@link BackupInfo} instances.
|
||||
*/
|
||||
public List<BackupInfo> getBackupInfos() {
|
||||
return getBackupInfo(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the memory allocated for the current instance
|
||||
* in the c++ side.
|
||||
@ -90,10 +104,15 @@ public class RestoreBackupableDB extends RocksObject {
|
||||
|
||||
private native long newRestoreBackupableDB(long options);
|
||||
private native void restoreDBFromBackup0(long nativeHandle, long backupId,
|
||||
String dbDir, String walDir, long restoreOptions) throws RocksDBException;
|
||||
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);
|
||||
String dbDir, String walDir, long restoreOptions)
|
||||
throws RocksDBException;
|
||||
private native void purgeOldBackups0(long nativeHandle, int numBackupsToKeep)
|
||||
throws RocksDBException;
|
||||
private native void deleteBackup0(long nativeHandle, long backupId)
|
||||
throws RocksDBException;
|
||||
protected native List<BackupInfo> getBackupInfo(long handle);
|
||||
private native void dispose(long nativeHandle);
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ package org.rocksdb.test;
|
||||
|
||||
import org.rocksdb.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BackupableDBTest {
|
||||
static final String db_path = "/tmp/rocksdbjni_backupable_db_test";
|
||||
static final String backup_path = "/tmp/rocksdbjni_backupable_db_backup_test";
|
||||
@ -21,14 +23,34 @@ public class BackupableDBTest {
|
||||
BackupableDBOptions bopt = new BackupableDBOptions(backup_path, false,
|
||||
true, false, true, 0, 0);
|
||||
BackupableDB bdb = null;
|
||||
|
||||
List<BackupInfo> backupInfos;
|
||||
List<BackupInfo> restoreInfos;
|
||||
try {
|
||||
bdb = BackupableDB.open(opt, bopt, db_path);
|
||||
|
||||
bdb.put("abc".getBytes(), "def".getBytes());
|
||||
bdb.put("ghi".getBytes(), "jkl".getBytes());
|
||||
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assert(backupInfos.size() == 0);
|
||||
|
||||
bdb.createNewBackup(true);
|
||||
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assert(backupInfos.size() == 1);
|
||||
|
||||
// Retrieving backup infos twice shall not
|
||||
// lead to different results
|
||||
List<BackupInfo> tmpBackupInfo = bdb.getBackupInfos();
|
||||
assert(tmpBackupInfo.get(0).backupId() ==
|
||||
backupInfos.get(0).backupId());
|
||||
assert(tmpBackupInfo.get(0).timestamp() ==
|
||||
backupInfos.get(0).timestamp());
|
||||
assert(tmpBackupInfo.get(0).size() ==
|
||||
backupInfos.get(0).size());
|
||||
assert(tmpBackupInfo.get(0).numberFiles() ==
|
||||
backupInfos.get(0).numberFiles());
|
||||
|
||||
// delete record after backup
|
||||
bdb.remove("abc".getBytes());
|
||||
byte[] value = bdb.get("abc".getBytes());
|
||||
@ -38,8 +60,26 @@ public class BackupableDBTest {
|
||||
// restore from backup
|
||||
RestoreOptions ropt = new RestoreOptions(false);
|
||||
RestoreBackupableDB rdb = new RestoreBackupableDB(bopt);
|
||||
|
||||
// getting backup infos from restorable db should
|
||||
// lead to the same infos as from backupable db
|
||||
restoreInfos = rdb.getBackupInfos();
|
||||
assert(restoreInfos.size() == backupInfos.size());
|
||||
assert(restoreInfos.get(0).backupId() ==
|
||||
backupInfos.get(0).backupId());
|
||||
assert(restoreInfos.get(0).timestamp() ==
|
||||
backupInfos.get(0).timestamp());
|
||||
assert(restoreInfos.get(0).size() ==
|
||||
backupInfos.get(0).size());
|
||||
assert(restoreInfos.get(0).numberFiles() ==
|
||||
backupInfos.get(0).numberFiles());
|
||||
|
||||
rdb.restoreDBFromLatestBackup(db_path, db_path,
|
||||
ropt);
|
||||
// do nothing because there is only one backup
|
||||
rdb.purgeOldBackups(1);
|
||||
restoreInfos = rdb.getBackupInfos();
|
||||
assert(restoreInfos.size() == 1);
|
||||
rdb.dispose();
|
||||
ropt.dispose();
|
||||
|
||||
@ -48,6 +88,28 @@ public class BackupableDBTest {
|
||||
value = bdb.get("abc".getBytes());
|
||||
assert(new String(value).equals("def"));
|
||||
|
||||
bdb.createNewBackup(false);
|
||||
// after new backup there must be two backup infos
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assert(backupInfos.size() == 2);
|
||||
// deleting the backup must be possible using the
|
||||
// id provided by backup infos
|
||||
bdb.deleteBackup(backupInfos.get(1).backupId());
|
||||
// after deletion there should only be one info
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assert(backupInfos.size() == 1);
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(false);
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assert(backupInfos.size() == 4);
|
||||
// purge everything and keep two
|
||||
bdb.purgeOldBackups(2);
|
||||
// backup infos need to be two
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assert(backupInfos.size() == 2);
|
||||
assert(backupInfos.get(0).backupId() == 4);
|
||||
assert(backupInfos.get(1).backupId() == 5);
|
||||
System.out.println("Backup and restore test passed");
|
||||
} catch (RocksDBException e) {
|
||||
System.err.format("[ERROR]: %s%n", e);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/org_rocksdb_BackupableDB.h"
|
||||
#include "include/org_rocksdb_BackupableDBOptions.h"
|
||||
@ -53,7 +54,7 @@ void Java_org_rocksdb_BackupableDB_createNewBackup(
|
||||
* Signature: (JI)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDB_purgeOldBackups(
|
||||
JNIEnv* env, jobject jbdb, jlong jhandle, jboolean jnumBackupsToKeep) {
|
||||
JNIEnv* env, jobject jbdb, jlong jhandle, jint jnumBackupsToKeep) {
|
||||
rocksdb::Status s =
|
||||
reinterpret_cast<rocksdb::BackupableDB*>(jhandle)->
|
||||
PurgeOldBackups(jnumBackupsToKeep);
|
||||
@ -62,6 +63,35 @@ void Java_org_rocksdb_BackupableDB_purgeOldBackups(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDB
|
||||
* Method: deleteBackup0
|
||||
* Signature: (JJ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDB_deleteBackup0(JNIEnv* env,
|
||||
jobject jobj, jlong jhandle, jlong jbackup_id) {
|
||||
auto rdb = reinterpret_cast<rocksdb::BackupableDB*>(jhandle);
|
||||
rocksdb::Status s = rdb->DeleteBackup(jbackup_id);
|
||||
|
||||
if (!s.ok()) {
|
||||
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDB
|
||||
* Method: getBackupInfo
|
||||
* Signature: (J)Ljava/util/List;
|
||||
*/
|
||||
jobject Java_org_rocksdb_BackupableDB_getBackupInfo(
|
||||
JNIEnv* env, jobject jbdb, jlong jhandle) {
|
||||
std::vector<rocksdb::BackupInfo> backup_infos;
|
||||
reinterpret_cast<rocksdb::BackupableDB*>(jhandle)->
|
||||
GetBackupInfo(&backup_infos);
|
||||
return rocksdb::BackupInfoListJni::getBackupInfo(env,
|
||||
backup_infos);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// BackupDBOptions
|
||||
|
||||
|
@ -15,7 +15,6 @@ BaseComparatorJniCallback::BaseComparatorJniCallback(
|
||||
const ComparatorJniCallbackOptions* copt)
|
||||
: mtx_compare(new port::Mutex(copt->use_adaptive_mutex)),
|
||||
mtx_findShortestSeparator(new port::Mutex(copt->use_adaptive_mutex)) {
|
||||
|
||||
// Note: Comparator methods may be accessed by multiple threads,
|
||||
// so we ref the jvm not the env
|
||||
const jint rs = env->GetJavaVM(&m_jvm);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <jni.h>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/filter_policy.h"
|
||||
@ -591,6 +592,50 @@ class ListJni {
|
||||
}
|
||||
};
|
||||
|
||||
class BackupInfoJni {
|
||||
public:
|
||||
// Get the java class id of org.rocksdb.BackupInfo.
|
||||
static jclass getJClass(JNIEnv* env) {
|
||||
jclass jclazz = env->FindClass("org/rocksdb/BackupInfo");
|
||||
assert(jclazz != nullptr);
|
||||
return jclazz;
|
||||
}
|
||||
|
||||
static jobject construct0(JNIEnv* env, uint32_t backup_id, int64_t timestamp,
|
||||
uint64_t size, uint32_t number_files) {
|
||||
static jmethodID mid = env->GetMethodID(getJClass(env), "<init>",
|
||||
"(IJJI)V");
|
||||
assert(mid != nullptr);
|
||||
return env->NewObject(getJClass(env), mid,
|
||||
backup_id, timestamp, size, number_files);
|
||||
}
|
||||
};
|
||||
|
||||
class BackupInfoListJni {
|
||||
public:
|
||||
static jobject getBackupInfo(JNIEnv* env,
|
||||
std::vector<BackupInfo> backup_infos) {
|
||||
jclass jclazz = env->FindClass("java/util/ArrayList");
|
||||
jmethodID mid = rocksdb::ListJni::getArrayListConstructorMethodId(
|
||||
env, jclazz);
|
||||
jobject jbackup_info_handle_list = env->NewObject(jclazz, mid,
|
||||
backup_infos.size());
|
||||
// insert in java list
|
||||
for (std::vector<rocksdb::BackupInfo>::size_type i = 0;
|
||||
i != backup_infos.size(); i++) {
|
||||
rocksdb::BackupInfo backup_info = backup_infos[i];
|
||||
jobject obj = rocksdb::BackupInfoJni::construct0(env,
|
||||
backup_info.backup_id,
|
||||
backup_info.timestamp,
|
||||
backup_info.size,
|
||||
backup_info.number_files);
|
||||
env->CallBooleanMethod(jbackup_info_handle_list,
|
||||
rocksdb::ListJni::getListAddMethodId(env), obj);
|
||||
}
|
||||
return jbackup_info_handle_list;
|
||||
}
|
||||
};
|
||||
|
||||
class JniUtil {
|
||||
public:
|
||||
/**
|
||||
|
@ -131,6 +131,20 @@ void Java_org_rocksdb_RestoreBackupableDB_deleteBackup0(JNIEnv* env,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_RestoreBackupableDB
|
||||
* Method: getBackupInfo
|
||||
* Signature: (J)Ljava/util/List;
|
||||
*/
|
||||
jobject Java_org_rocksdb_RestoreBackupableDB_getBackupInfo(
|
||||
JNIEnv* env, jobject jbdb, jlong jhandle) {
|
||||
std::vector<rocksdb::BackupInfo> backup_infos;
|
||||
reinterpret_cast<rocksdb::RestoreBackupableDB*>(jhandle)->
|
||||
GetBackupInfo(&backup_infos);
|
||||
return rocksdb::BackupInfoListJni::getBackupInfo(env,
|
||||
backup_infos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_RestoreBackupableDB
|
||||
* Method: dispose
|
||||
|
Loading…
Reference in New Issue
Block a user