mirror of https://github.com/facebook/rocksdb.git
Merge pull request #404 from fyrz/RocksJava-Backup-Restore-3.8
[RocksJava] Update BackupableDB and RestoreBackupableDB to 3.8.0.
This commit is contained in:
commit
4f882924dd
|
@ -47,7 +47,8 @@ ifeq ($(PLATFORM), OS_MACOSX)
|
|||
ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.jar
|
||||
endif
|
||||
|
||||
JAVA_TESTS = org.rocksdb.test.BackupableDBTest\
|
||||
JAVA_TESTS = org.rocksdb.test.BackupableDBOptionsTest\
|
||||
org.rocksdb.test.BackupableDBTest\
|
||||
org.rocksdb.test.BlockBasedTableConfigTest\
|
||||
org.rocksdb.test.ColumnFamilyOptionsTest\
|
||||
org.rocksdb.test.ColumnFamilyTest\
|
||||
|
|
|
@ -8,21 +8,23 @@ package org.rocksdb;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A subclass of RocksDB which supports backup-related operations.
|
||||
* <p>A subclass of RocksDB which supports
|
||||
* backup-related operations.</p>
|
||||
*
|
||||
* @see org.rocksdb.BackupableDBOptions
|
||||
*/
|
||||
public class BackupableDB extends RocksDB {
|
||||
/**
|
||||
* Open a {@code BackupableDB} under the specified path.
|
||||
* <p>Open a {@code BackupableDB} under the specified path.
|
||||
* Note that the backup path should be set properly in the
|
||||
* input BackupableDBOptions.
|
||||
* input BackupableDBOptions.</p>
|
||||
*
|
||||
* @param opt {@link org.rocksdb.Options} to set for the database.
|
||||
* @param bopt {@link org.rocksdb.BackupableDBOptions} to use.
|
||||
* @param db_path Path to store data to. The path for storing the backup should be
|
||||
* specified in the {@link org.rocksdb.BackupableDBOptions}.
|
||||
* @return BackupableDB reference to the opened database.
|
||||
*
|
||||
* @return {@link BackupableDB} reference to the opened database.
|
||||
*
|
||||
* @throws RocksDBException thrown if error happens in underlying
|
||||
* native library.
|
||||
|
@ -43,8 +45,8 @@ public class BackupableDB extends RocksDB {
|
|||
}
|
||||
|
||||
/**
|
||||
* Captures the state of the database in the latest backup.
|
||||
* Note that this function is not thread-safe.
|
||||
* <p>Captures the state of the database in the latest backup.
|
||||
* Note that this function is not thread-safe.</p>
|
||||
*
|
||||
* @param flushBeforeBackup if true, then all data will be flushed
|
||||
* before creating backup.
|
||||
|
@ -54,11 +56,12 @@ public class BackupableDB extends RocksDB {
|
|||
*/
|
||||
public void createNewBackup(boolean flushBeforeBackup)
|
||||
throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
createNewBackup(nativeHandle_, flushBeforeBackup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes old backups, keeping latest numBackupsToKeep alive.
|
||||
* <p>Deletes old backups, keeping latest numBackupsToKeep alive.</p>
|
||||
*
|
||||
* @param numBackupsToKeep Number of latest backups to keep.
|
||||
*
|
||||
|
@ -67,11 +70,12 @@ public class BackupableDB extends RocksDB {
|
|||
*/
|
||||
public void purgeOldBackups(int numBackupsToKeep)
|
||||
throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
purgeOldBackups(nativeHandle_, numBackupsToKeep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a specific backup.
|
||||
* <p>Deletes a specific backup.</p>
|
||||
*
|
||||
* @param backupId of backup to delete.
|
||||
*
|
||||
|
@ -79,25 +83,54 @@ public class BackupableDB extends RocksDB {
|
|||
* native library.
|
||||
*/
|
||||
public void deleteBackup(int backupId) throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
deleteBackup0(nativeHandle_, backupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of {@link BackupInfo} instances, which describe
|
||||
* already made backups.
|
||||
* <p>Returns a list of {@link BackupInfo} instances, which describe
|
||||
* already made backups.</p>
|
||||
*
|
||||
* @return List of {@link BackupInfo} instances.
|
||||
*/
|
||||
public List<BackupInfo> getBackupInfos() {
|
||||
assert(isInitialized());
|
||||
return getBackupInfo(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the BackupableDB instance and release resource.
|
||||
* <p>Returns a list of corrupted backup ids. If there
|
||||
* is no corrupted backup the method will return an
|
||||
* empty list.</p>
|
||||
*
|
||||
* Internally, BackupableDB owns the {@code rocksdb::DB} pointer to its associated
|
||||
* {@link org.rocksdb.RocksDB}. The release of that RocksDB pointer is handled in the destructor
|
||||
* of the c++ {@code rocksdb::BackupableDB} and should be transparent to Java developers.
|
||||
* @return array of backup ids as int ids.
|
||||
*/
|
||||
public int[] getCorruptedBackups() {
|
||||
assert(isInitialized());
|
||||
return getCorruptedBackups(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Will delete all the files we don't need anymore. It will
|
||||
* do the full scan of the files/ directory and delete all the
|
||||
* files that are not referenced.</p>
|
||||
*
|
||||
* @throws RocksDBException thrown if error happens in underlying
|
||||
* native library.
|
||||
*/
|
||||
public void garbageCollect() throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
garbageCollect(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Close the BackupableDB instance and release resource.</p>
|
||||
*
|
||||
* <p>Internally, {@link BackupableDB} owns the {@code rocksdb::DB}
|
||||
* pointer to its associated {@link org.rocksdb.RocksDB}.
|
||||
* The release of that RocksDB pointer is handled in the destructor
|
||||
* of the c++ {@code rocksdb::BackupableDB} and should be transparent
|
||||
* to Java developers.</p>
|
||||
*/
|
||||
@Override public synchronized void close() {
|
||||
if (isInitialized()) {
|
||||
|
@ -106,8 +139,9 @@ public class BackupableDB extends RocksDB {
|
|||
}
|
||||
|
||||
/**
|
||||
* A protected construction that will be used in the static factory
|
||||
* method {@link #open(Options, BackupableDBOptions, String)}.
|
||||
* <p>A protected construction that will be used in the static
|
||||
* factory method {@link #open(Options, BackupableDBOptions, String)}.
|
||||
* </p>
|
||||
*/
|
||||
protected BackupableDB() {
|
||||
super();
|
||||
|
@ -126,4 +160,7 @@ public class BackupableDB extends RocksDB {
|
|||
private native void deleteBackup0(long nativeHandle, int backupId)
|
||||
throws RocksDBException;
|
||||
protected native List<BackupInfo> getBackupInfo(long handle);
|
||||
private native int[] getCorruptedBackups(long handle);
|
||||
private native void garbageCollect(long handle)
|
||||
throws RocksDBException;
|
||||
}
|
||||
|
|
|
@ -5,57 +5,38 @@
|
|||
|
||||
package org.rocksdb;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* BackupableDBOptions to control the behavior of a backupable database.
|
||||
* <p>BackupableDBOptions to control the behavior of a backupable database.
|
||||
* It will be used during the creation of a {@link org.rocksdb.BackupableDB}.
|
||||
*
|
||||
* Note that dispose() must be called before an Options instance
|
||||
* become out-of-scope to release the allocated memory in c++.
|
||||
* </p>
|
||||
* <p>Note that dispose() must be called before an Options instance
|
||||
* become out-of-scope to release the allocated memory in c++.</p>
|
||||
*
|
||||
* @see org.rocksdb.BackupableDB
|
||||
*/
|
||||
public class BackupableDBOptions extends RocksObject {
|
||||
|
||||
/**
|
||||
* BackupableDBOptions constructor
|
||||
* <p>BackupableDBOptions constructor.</p>
|
||||
*
|
||||
* @param path Where to keep the backup files. Has to be different than db name.
|
||||
* Best to set this to {@code db name_ + "/backups"}
|
||||
* @param shareTableFiles If {@code share_table_files == true}, backup will assume
|
||||
* that table files with same name have the same contents. This enables incremental
|
||||
* backups and avoids unnecessary data copies. If {@code share_table_files == false},
|
||||
* each backup will be on its own and will not share any data with other backups.
|
||||
* Default: true
|
||||
* @param sync If {@code sync == true}, we can guarantee you'll get consistent backup
|
||||
* even on a machine crash/reboot. Backup process is slower with sync enabled.
|
||||
* If {@code sync == false}, we don't guarantee anything on machine reboot.
|
||||
* However,chances are some of the backups are consistent.
|
||||
* Default: true
|
||||
* @param destroyOldData If true, it will delete whatever backups there are already.
|
||||
* Default: false
|
||||
* @param backupLogFiles If false, we won't backup log files. This option can be
|
||||
* useful for backing up in-memory databases where log file are persisted,but table
|
||||
* files are in memory.
|
||||
* Default: true
|
||||
* @param backupRateLimit Max bytes that can be transferred in a second during backup.
|
||||
* If 0 or negative, then go as fast as you can. Default: 0
|
||||
* @param restoreRateLimit Max bytes that can be transferred in a second during restore.
|
||||
* If 0 or negative, then go as fast as you can. Default: 0
|
||||
* Best to set this to {@code db name_ + "/backups"}
|
||||
* @throws java.lang.IllegalArgumentException if illegal path is used.
|
||||
*/
|
||||
public BackupableDBOptions(String path, boolean shareTableFiles, boolean sync,
|
||||
boolean destroyOldData, boolean backupLogFiles, long backupRateLimit,
|
||||
long restoreRateLimit) {
|
||||
public BackupableDBOptions(String path) {
|
||||
super();
|
||||
|
||||
backupRateLimit = (backupRateLimit <= 0) ? 0 : backupRateLimit;
|
||||
restoreRateLimit = (restoreRateLimit <= 0) ? 0 : restoreRateLimit;
|
||||
|
||||
newBackupableDBOptions(path, shareTableFiles, sync, destroyOldData,
|
||||
backupLogFiles, backupRateLimit, restoreRateLimit);
|
||||
File backupPath = path == null ? null : new File(path);
|
||||
if (backupPath == null || !backupPath.isDirectory() || !backupPath.canWrite()) {
|
||||
throw new IllegalArgumentException("Illegal path provided.");
|
||||
}
|
||||
newBackupableDBOptions(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the BackupableDB directory.
|
||||
* <p>Returns the path to the BackupableDB directory.</p>
|
||||
*
|
||||
* @return the path to the BackupableDB directory.
|
||||
*/
|
||||
|
@ -64,18 +45,227 @@ public class BackupableDBOptions extends RocksObject {
|
|||
return backupDir(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Share table files between backups.</p>
|
||||
*
|
||||
* @param shareTableFiles If {@code share_table_files == true}, backup will assume
|
||||
* that table files with same name have the same contents. This enables incremental
|
||||
* backups and avoids unnecessary data copies. If {@code share_table_files == false},
|
||||
* each backup will be on its own and will not share any data with other backups.
|
||||
*
|
||||
* <p>Default: true</p>
|
||||
*
|
||||
* @return instance of current BackupableDBOptions.
|
||||
*/
|
||||
public BackupableDBOptions setShareTableFiles(boolean shareTableFiles) {
|
||||
assert(isInitialized());
|
||||
setShareTableFiles(nativeHandle_, shareTableFiles);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Share table files between backups.</p>
|
||||
*
|
||||
* @return boolean value indicating if SST files will be shared between
|
||||
* backups.
|
||||
*/
|
||||
public boolean shareTableFiles() {
|
||||
assert(isInitialized());
|
||||
return shareTableFiles(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set synchronous backups.</p>
|
||||
*
|
||||
* @param sync If {@code sync == true}, we can guarantee you'll get consistent backup
|
||||
* even on a machine crash/reboot. Backup process is slower with sync enabled.
|
||||
* If {@code sync == false}, we don't guarantee anything on machine reboot.
|
||||
* However,chances are some of the backups are consistent.
|
||||
*
|
||||
* <p>Default: true</p>
|
||||
*
|
||||
* @return instance of current BackupableDBOptions.
|
||||
*/
|
||||
public BackupableDBOptions setSync(boolean sync) {
|
||||
assert(isInitialized());
|
||||
setSync(nativeHandle_, sync);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Are synchronous backups activated.</p>
|
||||
*
|
||||
* @return boolean value if synchronous backups are configured.
|
||||
*/
|
||||
public boolean sync() {
|
||||
assert(isInitialized());
|
||||
return sync(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set if old data will be destroyed.</p>
|
||||
*
|
||||
* @param destroyOldData If true, it will delete whatever backups there are already.
|
||||
*
|
||||
* <p>Default: false</p>
|
||||
*
|
||||
* @return instance of current BackupableDBOptions.
|
||||
*/
|
||||
public BackupableDBOptions setDestroyOldData(boolean destroyOldData) {
|
||||
assert(isInitialized());
|
||||
setDestroyOldData(nativeHandle_, destroyOldData);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns if old data will be destroyed will performing new backups.</p>
|
||||
*
|
||||
* @return boolean value indicating if old data will be destroyed.
|
||||
*/
|
||||
public boolean destroyOldData() {
|
||||
assert(isInitialized());
|
||||
return destroyOldData(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set if log files shall be persisted.</p>
|
||||
*
|
||||
* @param backupLogFiles If false, we won't backup log files. This option can be
|
||||
* useful for backing up in-memory databases where log file are persisted,but table
|
||||
* files are in memory.
|
||||
*
|
||||
* <p>Default: true</p>
|
||||
*
|
||||
* @return instance of current BackupableDBOptions.
|
||||
*/
|
||||
public BackupableDBOptions setBackupLogFiles(boolean backupLogFiles) {
|
||||
assert(isInitialized());
|
||||
setBackupLogFiles(nativeHandle_, backupLogFiles);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Return information if log files shall be persisted.</p>
|
||||
*
|
||||
* @return boolean value indicating if log files will be persisted.
|
||||
*/
|
||||
public boolean backupLogFiles() {
|
||||
assert(isInitialized());
|
||||
return backupLogFiles(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set backup rate limit.</p>
|
||||
*
|
||||
* @param backupRateLimit Max bytes that can be transferred in a second during backup.
|
||||
* If 0 or negative, then go as fast as you can.
|
||||
*
|
||||
* <p>Default: 0</p>
|
||||
*
|
||||
* @return instance of current BackupableDBOptions.
|
||||
*/
|
||||
public BackupableDBOptions setBackupRateLimit(long backupRateLimit) {
|
||||
assert(isInitialized());
|
||||
backupRateLimit = (backupRateLimit <= 0) ? 0 : backupRateLimit;
|
||||
setBackupRateLimit(nativeHandle_, backupRateLimit);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Return backup rate limit which described the max bytes that can be transferred in a
|
||||
* second during backup.</p>
|
||||
*
|
||||
* @return numerical value describing the backup transfer limit in bytes per second.
|
||||
*/
|
||||
public long backupRateLimit() {
|
||||
assert(isInitialized());
|
||||
return backupRateLimit(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Set restore rate limit.</p>
|
||||
*
|
||||
* @param restoreRateLimit Max bytes that can be transferred in a second during restore.
|
||||
* If 0 or negative, then go as fast as you can.
|
||||
*
|
||||
* <p>Default: 0</p>
|
||||
*
|
||||
* @return instance of current BackupableDBOptions.
|
||||
*/
|
||||
public BackupableDBOptions setRestoreRateLimit(long restoreRateLimit) {
|
||||
assert(isInitialized());
|
||||
restoreRateLimit = (restoreRateLimit <= 0) ? 0 : restoreRateLimit;
|
||||
setRestoreRateLimit(nativeHandle_, restoreRateLimit);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Return restore rate limit which described the max bytes that can be transferred in a
|
||||
* second during restore.</p>
|
||||
*
|
||||
* @return numerical value describing the restore transfer limit in bytes per second.
|
||||
*/
|
||||
public long restoreRateLimit() {
|
||||
assert(isInitialized());
|
||||
return restoreRateLimit(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Only used if share_table_files is set to true. If true, will consider that
|
||||
* backups can come from different databases, hence a sst is not uniquely
|
||||
* identified by its name, but by the triple (file name, crc32, file length)</p>
|
||||
*
|
||||
* @param shareFilesWithChecksum boolean value indicating if SST files are stored
|
||||
* using the triple (file name, crc32, file length) and not its name.
|
||||
*
|
||||
* <p>Note: this is an experimental option, and you'll need to set it manually
|
||||
* turn it on only if you know what you're doing*</p>
|
||||
*
|
||||
* <p>Default: false</p>
|
||||
*
|
||||
* @return instance of current BackupableDBOptions.
|
||||
*/
|
||||
public BackupableDBOptions setShareFilesWithChecksum(
|
||||
boolean shareFilesWithChecksum) {
|
||||
assert(isInitialized());
|
||||
setShareFilesWithChecksum(nativeHandle_, shareFilesWithChecksum);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Return of share files with checksum is active.</p>
|
||||
*
|
||||
* @return boolean value indicating if share files with checksum
|
||||
* is active.
|
||||
*/
|
||||
public boolean shareFilesWithChecksum() {
|
||||
assert(isInitialized());
|
||||
return shareFilesWithChecksum(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the memory allocated for the current instance
|
||||
* in the c++ side.
|
||||
*/
|
||||
@Override protected void disposeInternal() {
|
||||
assert(isInitialized());
|
||||
disposeInternal(nativeHandle_);
|
||||
}
|
||||
|
||||
private native void newBackupableDBOptions(String path,
|
||||
boolean shareTableFiles, boolean sync, boolean destroyOldData,
|
||||
boolean backupLogFiles, long backupRateLimit, long restoreRateLimit);
|
||||
private native void newBackupableDBOptions(String path);
|
||||
private native String backupDir(long handle);
|
||||
private native void setShareTableFiles(long handle, boolean flag);
|
||||
private native boolean shareTableFiles(long handle);
|
||||
private native void setSync(long handle, boolean flag);
|
||||
private native boolean sync(long handle);
|
||||
private native void setDestroyOldData(long handle, boolean flag);
|
||||
private native boolean destroyOldData(long handle);
|
||||
private native void setBackupLogFiles(long handle, boolean flag);
|
||||
private native boolean backupLogFiles(long handle);
|
||||
private native void setBackupRateLimit(long handle, long rateLimit);
|
||||
private native long backupRateLimit(long handle);
|
||||
private native void setRestoreRateLimit(long handle, long rateLimit);
|
||||
private native long restoreRateLimit(long handle);
|
||||
private native void setShareFilesWithChecksum(long handle, boolean flag);
|
||||
private native boolean shareFilesWithChecksum(long handle);
|
||||
private native void disposeInternal(long handle);
|
||||
}
|
||||
|
|
|
@ -8,15 +8,17 @@ package org.rocksdb;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used to access information about backups and restore from them.
|
||||
* <p>This class is used to access information about backups and
|
||||
* restore from them.</p>
|
||||
*
|
||||
* Note that dispose() must be called before this instance become out-of-scope
|
||||
* to release the allocated memory in c++.
|
||||
* <p>Note: {@code dispose()} must be called before this instance
|
||||
* become out-of-scope to release the allocated
|
||||
* memory in c++.</p>
|
||||
*
|
||||
*/
|
||||
public class RestoreBackupableDB extends RocksObject {
|
||||
/**
|
||||
* Constructor
|
||||
* <p>Construct new estoreBackupableDB instance.</p>
|
||||
*
|
||||
* @param options {@link org.rocksdb.BackupableDBOptions} instance
|
||||
*/
|
||||
|
@ -26,16 +28,18 @@ public class RestoreBackupableDB extends RocksObject {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>Restore from backup with backup_id.</p>
|
||||
*
|
||||
* 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.
|
||||
* <p><strong>Important</strong>: 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.</p>
|
||||
*
|
||||
* <p><strong>Example</strong>: 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.</p>
|
||||
*
|
||||
* @param backupId id pointing to backup
|
||||
* @param dbDir database directory to restore to
|
||||
|
@ -47,12 +51,13 @@ public class RestoreBackupableDB extends RocksObject {
|
|||
*/
|
||||
public void restoreDBFromBackup(long backupId, String dbDir, String walDir,
|
||||
RestoreOptions restoreOptions) throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
restoreDBFromBackup0(nativeHandle_, backupId, dbDir, walDir,
|
||||
restoreOptions.nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore from the latest backup.
|
||||
* <p>Restore from the latest backup.</p>
|
||||
*
|
||||
* @param dbDir database directory to restore to
|
||||
* @param walDir directory where wal files are located
|
||||
|
@ -63,12 +68,13 @@ public class RestoreBackupableDB extends RocksObject {
|
|||
*/
|
||||
public void restoreDBFromLatestBackup(String dbDir, String walDir,
|
||||
RestoreOptions restoreOptions) throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
restoreDBFromLatestBackup0(nativeHandle_, dbDir, walDir,
|
||||
restoreOptions.nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes old backups, keeping latest numBackupsToKeep alive.
|
||||
* <p>Deletes old backups, keeping latest numBackupsToKeep alive.</p>
|
||||
*
|
||||
* @param numBackupsToKeep of latest backups to keep
|
||||
*
|
||||
|
@ -76,11 +82,12 @@ public class RestoreBackupableDB extends RocksObject {
|
|||
* native library.
|
||||
*/
|
||||
public void purgeOldBackups(int numBackupsToKeep) throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
purgeOldBackups0(nativeHandle_, numBackupsToKeep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a specific backup.
|
||||
* <p>Deletes a specific backup.</p>
|
||||
*
|
||||
* @param backupId of backup to delete.
|
||||
*
|
||||
|
@ -88,25 +95,51 @@ public class RestoreBackupableDB extends RocksObject {
|
|||
* native library.
|
||||
*/
|
||||
public void deleteBackup(int backupId) throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
deleteBackup0(nativeHandle_, backupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of {@link BackupInfo} instances, which describe
|
||||
* already made backups.
|
||||
* <p>Returns a list of {@link BackupInfo} instances, which describe
|
||||
* already made backups.</p>
|
||||
*
|
||||
* @return List of {@link BackupInfo} instances.
|
||||
*/
|
||||
public List<BackupInfo> getBackupInfos() {
|
||||
assert(isInitialized());
|
||||
return getBackupInfo(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the memory allocated for the current instance
|
||||
* in the c++ side.
|
||||
* <p>Returns a list of corrupted backup ids. If there
|
||||
* is no corrupted backup the method will return an
|
||||
* empty list.</p>
|
||||
*
|
||||
* @return array of backup ids as int ids.
|
||||
*/
|
||||
public int[] getCorruptedBackups() {
|
||||
assert(isInitialized());
|
||||
return getCorruptedBackups(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Will delete all the files we don't need anymore. It will
|
||||
* do the full scan of the files/ directory and delete all the
|
||||
* files that are not referenced.</p>
|
||||
*
|
||||
* @throws RocksDBException thrown if error happens in underlying
|
||||
* native library.
|
||||
*/
|
||||
public void garbageCollect() throws RocksDBException {
|
||||
assert(isInitialized());
|
||||
garbageCollect(nativeHandle_);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Release the memory allocated for the current instance
|
||||
* in the c++ side.</p>
|
||||
*/
|
||||
@Override public synchronized void disposeInternal() {
|
||||
assert(isInitialized());
|
||||
dispose(nativeHandle_);
|
||||
}
|
||||
|
||||
|
@ -121,6 +154,9 @@ public class RestoreBackupableDB extends RocksObject {
|
|||
throws RocksDBException;
|
||||
private native void deleteBackup0(long nativeHandle, int backupId)
|
||||
throws RocksDBException;
|
||||
protected native List<BackupInfo> getBackupInfo(long handle);
|
||||
private native List<BackupInfo> getBackupInfo(long handle);
|
||||
private native int[] getCorruptedBackups(long handle);
|
||||
private native void garbageCollect(long handle)
|
||||
throws RocksDBException;
|
||||
private native void dispose(long nativeHandle);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
// 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.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.rocksdb.BackupableDBOptions;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class BackupableDBOptionsTest {
|
||||
|
||||
private final static String ARBITRARY_PATH = "/tmp";
|
||||
|
||||
@ClassRule
|
||||
public static final RocksMemoryResource rocksMemoryResource =
|
||||
new RocksMemoryResource();
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
public static final Random rand = PlatformRandomHelper.
|
||||
getPlatformSpecificRandomFactory();
|
||||
|
||||
@Test
|
||||
public void backupDir() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
assertThat(backupableDBOptions.backupDir()).
|
||||
isEqualTo(ARBITRARY_PATH);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shareTableFiles() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
boolean value = rand.nextBoolean();
|
||||
backupableDBOptions.setShareTableFiles(value);
|
||||
assertThat(backupableDBOptions.shareTableFiles()).
|
||||
isEqualTo(value);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sync() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
boolean value = rand.nextBoolean();
|
||||
backupableDBOptions.setSync(value);
|
||||
assertThat(backupableDBOptions.sync()).isEqualTo(value);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destroyOldData() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
boolean value = rand.nextBoolean();
|
||||
backupableDBOptions.setDestroyOldData(value);
|
||||
assertThat(backupableDBOptions.destroyOldData()).
|
||||
isEqualTo(value);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backupLogFiles() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
boolean value = rand.nextBoolean();
|
||||
backupableDBOptions.setBackupLogFiles(value);
|
||||
assertThat(backupableDBOptions.backupLogFiles()).
|
||||
isEqualTo(value);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backupRateLimit() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
long value = Math.abs(rand.nextLong());
|
||||
backupableDBOptions.setBackupRateLimit(value);
|
||||
assertThat(backupableDBOptions.backupRateLimit()).
|
||||
isEqualTo(value);
|
||||
// negative will be mapped to 0
|
||||
backupableDBOptions.setBackupRateLimit(-1);
|
||||
assertThat(backupableDBOptions.backupRateLimit()).
|
||||
isEqualTo(0);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restoreRateLimit() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
long value = Math.abs(rand.nextLong());
|
||||
backupableDBOptions.setRestoreRateLimit(value);
|
||||
assertThat(backupableDBOptions.restoreRateLimit()).
|
||||
isEqualTo(value);
|
||||
// negative will be mapped to 0
|
||||
backupableDBOptions.setRestoreRateLimit(-1);
|
||||
assertThat(backupableDBOptions.restoreRateLimit()).
|
||||
isEqualTo(0);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shareFilesWithChecksum() {
|
||||
BackupableDBOptions backupableDBOptions = null;
|
||||
try {
|
||||
backupableDBOptions = new BackupableDBOptions(ARBITRARY_PATH);
|
||||
boolean value = rand.nextBoolean();
|
||||
backupableDBOptions.setShareFilesWithChecksum(value);
|
||||
assertThat(backupableDBOptions.shareFilesWithChecksum()).
|
||||
isEqualTo(value);
|
||||
} finally {
|
||||
if (backupableDBOptions != null) {
|
||||
backupableDBOptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failBackupDirIsNull() {
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
new BackupableDBOptions(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failBackupDirIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.backupDir();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSetShareTableFilesIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.setShareTableFiles(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failShareTableFilesIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.shareTableFiles();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSetSyncIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.setSync(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSyncIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.sync();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSetDestroyOldDataIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.setDestroyOldData(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failDestroyOldDataIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.destroyOldData();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSetBackupLogFilesIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.setBackupLogFiles(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failBackupLogFilesIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.backupLogFiles();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSetBackupRateLimitIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.setBackupRateLimit(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failBackupRateLimitIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.backupRateLimit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSetRestoreRateLimitIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.setRestoreRateLimit(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failRestoreRateLimitIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.restoreRateLimit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failSetShareFilesWithChecksumIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.setShareFilesWithChecksum(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failShareFilesWithChecksumIfDisposed(){
|
||||
BackupableDBOptions options = setupUninitializedBackupableDBOptions(
|
||||
exception);
|
||||
options.shareFilesWithChecksum();
|
||||
}
|
||||
|
||||
private BackupableDBOptions setupUninitializedBackupableDBOptions(
|
||||
ExpectedException exception) {
|
||||
BackupableDBOptions backupableDBOptions =
|
||||
new BackupableDBOptions(ARBITRARY_PATH);
|
||||
backupableDBOptions.dispose();
|
||||
exception.expect(AssertionError.class);
|
||||
return backupableDBOptions;
|
||||
}
|
||||
}
|
|
@ -28,138 +28,387 @@ public class BackupableDBTest {
|
|||
public TemporaryFolder backupFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void backupableDb() throws RocksDBException {
|
||||
public void backupDb() throws RocksDBException {
|
||||
Options opt = null;
|
||||
BackupableDBOptions bopt = null;
|
||||
BackupableDB bdb = null;
|
||||
RestoreOptions ropt = null;
|
||||
RestoreBackupableDB rdb = null;
|
||||
try {
|
||||
opt = new Options();
|
||||
opt.setCreateIfMissing(true);
|
||||
|
||||
opt = new Options().setCreateIfMissing(true);
|
||||
bopt = new BackupableDBOptions(
|
||||
backupFolder.getRoot().getAbsolutePath(), false,
|
||||
true, false, true, 0, 0);
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
assertThat(bopt.backupDir()).isEqualTo(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
|
||||
List<BackupInfo> backupInfos;
|
||||
List<BackupInfo> restoreInfos;
|
||||
|
||||
// Open empty database.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
bdb.put("abc".getBytes(), "def".getBytes());
|
||||
bdb.put("ghi".getBytes(), "jkl".getBytes());
|
||||
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assertThat(backupInfos.size()).
|
||||
isEqualTo(0);
|
||||
|
||||
// Fill database with some test values
|
||||
prepareDatabase(bdb);
|
||||
// Create two backups
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(true);
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assertThat(backupInfos.size()).
|
||||
isEqualTo(1);
|
||||
|
||||
// Retrieving backup infos twice shall not
|
||||
// lead to different results
|
||||
List<BackupInfo> tmpBackupInfo = bdb.getBackupInfos();
|
||||
assertThat(tmpBackupInfo.get(0).backupId()).
|
||||
isEqualTo(backupInfos.get(0).backupId());
|
||||
assertThat(tmpBackupInfo.get(0).timestamp()).
|
||||
isEqualTo(backupInfos.get(0).timestamp());
|
||||
assertThat(tmpBackupInfo.get(0).size()).
|
||||
isEqualTo(backupInfos.get(0).size());
|
||||
assertThat(tmpBackupInfo.get(0).numberFiles()).
|
||||
isEqualTo(backupInfos.get(0).numberFiles());
|
||||
|
||||
// delete record after backup
|
||||
bdb.remove("abc".getBytes());
|
||||
byte[] value = bdb.get("abc".getBytes());
|
||||
assertThat(value).isNull();
|
||||
bdb.close();
|
||||
|
||||
// restore from backup
|
||||
ropt = new RestoreOptions(false);
|
||||
rdb = new RestoreBackupableDB(bopt);
|
||||
|
||||
// getting backup infos from restorable db should
|
||||
// lead to the same infos as from backupable db
|
||||
restoreInfos = rdb.getBackupInfos();
|
||||
assertThat(restoreInfos.size()).
|
||||
isEqualTo(backupInfos.size());
|
||||
assertThat(restoreInfos.get(0).backupId()).
|
||||
isEqualTo(backupInfos.get(0).backupId());
|
||||
assertThat(restoreInfos.get(0).timestamp()).
|
||||
isEqualTo(backupInfos.get(0).timestamp());
|
||||
assertThat(restoreInfos.get(0).size()).
|
||||
isEqualTo(backupInfos.get(0).size());
|
||||
assertThat(restoreInfos.get(0).numberFiles()).
|
||||
isEqualTo(backupInfos.get(0).numberFiles());
|
||||
|
||||
rdb.restoreDBFromLatestBackup(
|
||||
dbFolder.getRoot().getAbsolutePath(),
|
||||
dbFolder.getRoot().getAbsolutePath(),
|
||||
ropt);
|
||||
// do nothing because there is only one backup
|
||||
rdb.purgeOldBackups(1);
|
||||
restoreInfos = rdb.getBackupInfos();
|
||||
assertThat(restoreInfos.size()).
|
||||
isEqualTo(1);
|
||||
rdb.dispose();
|
||||
ropt.dispose();
|
||||
|
||||
// verify that backed up data contains deleted record
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
value = bdb.get("abc".getBytes());
|
||||
assertThat(new String(value)).
|
||||
isEqualTo("def");
|
||||
|
||||
bdb.createNewBackup(false);
|
||||
// after new backup there must be two backup infos
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assertThat(backupInfos.size()).
|
||||
isEqualTo(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();
|
||||
assertThat(backupInfos.size()).
|
||||
isEqualTo(1);
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(false);
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assertThat(backupInfos.size()).
|
||||
isEqualTo(4);
|
||||
// purge everything and keep two
|
||||
bdb.purgeOldBackups(2);
|
||||
// backup infos need to be two
|
||||
backupInfos = bdb.getBackupInfos();
|
||||
assertThat(backupInfos.size()).
|
||||
isEqualTo(2);
|
||||
assertThat(backupInfos.get(0).backupId()).
|
||||
isEqualTo(4);
|
||||
assertThat(backupInfos.get(1).backupId()).
|
||||
isEqualTo(5);
|
||||
verifyNumberOfValidBackups(bdb, 2);
|
||||
} finally {
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
if (bdb != null) {
|
||||
bdb.close();
|
||||
}
|
||||
if (bopt != null) {
|
||||
bopt.dispose();
|
||||
}
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteBackup() throws RocksDBException {
|
||||
Options opt = null;
|
||||
BackupableDBOptions bopt = null;
|
||||
BackupableDB bdb = null;
|
||||
try {
|
||||
opt = new Options().setCreateIfMissing(true);
|
||||
bopt = new BackupableDBOptions(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
assertThat(bopt.backupDir()).isEqualTo(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
// Open empty database.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Fill database with some test values
|
||||
prepareDatabase(bdb);
|
||||
// Create two backups
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(true);
|
||||
List<BackupInfo> backupInfo =
|
||||
verifyNumberOfValidBackups(bdb, 2);
|
||||
// Delete the first backup
|
||||
bdb.deleteBackup(backupInfo.get(0).backupId());
|
||||
List<BackupInfo> newBackupInfo =
|
||||
verifyNumberOfValidBackups(bdb, 1);
|
||||
// The second backup must remain.
|
||||
assertThat(newBackupInfo.get(0).backupId()).
|
||||
isEqualTo(backupInfo.get(1).backupId());
|
||||
} finally {
|
||||
if (bdb != null) {
|
||||
bdb.close();
|
||||
}
|
||||
if (ropt != null) {
|
||||
ropt.dispose();
|
||||
if (bopt != null) {
|
||||
bopt.dispose();
|
||||
}
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteBackupWithRestoreBackupableDB()
|
||||
throws RocksDBException {
|
||||
Options opt = null;
|
||||
BackupableDBOptions bopt = null;
|
||||
BackupableDB bdb = null;
|
||||
RestoreBackupableDB rdb = null;
|
||||
try {
|
||||
opt = new Options().setCreateIfMissing(true);
|
||||
bopt = new BackupableDBOptions(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
assertThat(bopt.backupDir()).isEqualTo(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
// Open empty database.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Fill database with some test values
|
||||
prepareDatabase(bdb);
|
||||
// Create two backups
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(true);
|
||||
List<BackupInfo> backupInfo =
|
||||
verifyNumberOfValidBackups(bdb, 2);
|
||||
// init RestoreBackupableDB
|
||||
rdb = new RestoreBackupableDB(bopt);
|
||||
// Delete the first backup
|
||||
rdb.deleteBackup(backupInfo.get(0).backupId());
|
||||
// Fetch backup info using RestoreBackupableDB
|
||||
List<BackupInfo> newBackupInfo = verifyNumberOfValidBackups(rdb, 1);
|
||||
// The second backup must remain.
|
||||
assertThat(newBackupInfo.get(0).backupId()).
|
||||
isEqualTo(backupInfo.get(1).backupId());
|
||||
} finally {
|
||||
if (bdb != null) {
|
||||
bdb.close();
|
||||
}
|
||||
if (rdb != null) {
|
||||
rdb.dispose();
|
||||
}
|
||||
if (bopt != null) {
|
||||
bopt.dispose();
|
||||
}
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void purgeOldBackups() throws RocksDBException {
|
||||
Options opt = null;
|
||||
BackupableDBOptions bopt = null;
|
||||
BackupableDB bdb = null;
|
||||
try {
|
||||
opt = new Options().setCreateIfMissing(true);
|
||||
bopt = new BackupableDBOptions(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
assertThat(bopt.backupDir()).isEqualTo(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
// Open empty database.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Fill database with some test values
|
||||
prepareDatabase(bdb);
|
||||
// Create two backups
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(true);
|
||||
bdb.createNewBackup(true);
|
||||
bdb.createNewBackup(true);
|
||||
List<BackupInfo> backupInfo =
|
||||
verifyNumberOfValidBackups(bdb, 4);
|
||||
// Delete everything except the latest backup
|
||||
bdb.purgeOldBackups(1);
|
||||
List<BackupInfo> newBackupInfo =
|
||||
verifyNumberOfValidBackups(bdb, 1);
|
||||
// The latest backup must remain.
|
||||
assertThat(newBackupInfo.get(0).backupId()).
|
||||
isEqualTo(backupInfo.get(3).backupId());
|
||||
} finally {
|
||||
if (bdb != null) {
|
||||
bdb.close();
|
||||
}
|
||||
if (bopt != null) {
|
||||
bopt.dispose();
|
||||
}
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void purgeOldBackupsWithRestoreBackupableDb()
|
||||
throws RocksDBException {
|
||||
Options opt = null;
|
||||
BackupableDBOptions bopt = null;
|
||||
BackupableDB bdb = null;
|
||||
RestoreBackupableDB rdb = null;
|
||||
try {
|
||||
opt = new Options().setCreateIfMissing(true);
|
||||
bopt = new BackupableDBOptions(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
assertThat(bopt.backupDir()).isEqualTo(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
// Open empty database.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Fill database with some test values
|
||||
prepareDatabase(bdb);
|
||||
// Create two backups
|
||||
bdb.createNewBackup(false);
|
||||
bdb.createNewBackup(true);
|
||||
bdb.createNewBackup(true);
|
||||
bdb.createNewBackup(true);
|
||||
verifyNumberOfValidBackups(bdb, 4);
|
||||
// init RestoreBackupableDB
|
||||
rdb = new RestoreBackupableDB(bopt);
|
||||
// the same number of backups must
|
||||
// exist using RestoreBackupableDB.
|
||||
verifyNumberOfValidBackups(rdb, 4);
|
||||
rdb.purgeOldBackups(1);
|
||||
verifyNumberOfValidBackups(rdb, 1);
|
||||
} finally {
|
||||
if (bdb != null) {
|
||||
bdb.close();
|
||||
}
|
||||
if (rdb != null) {
|
||||
rdb.dispose();
|
||||
}
|
||||
if (bopt != null) {
|
||||
bopt.dispose();
|
||||
}
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restoreLatestBackup()
|
||||
throws RocksDBException {
|
||||
Options opt = null;
|
||||
BackupableDBOptions bopt = null;
|
||||
BackupableDB bdb = null;
|
||||
RestoreBackupableDB rdb = null;
|
||||
try {
|
||||
opt = new Options().setCreateIfMissing(true);
|
||||
bopt = new BackupableDBOptions(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
assertThat(bopt.backupDir()).isEqualTo(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
// Open empty database.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Fill database with some test values
|
||||
prepareDatabase(bdb);
|
||||
bdb.createNewBackup(true);
|
||||
verifyNumberOfValidBackups(bdb, 1);
|
||||
bdb.put("key1".getBytes(), "valueV2".getBytes());
|
||||
bdb.put("key2".getBytes(), "valueV2".getBytes());
|
||||
bdb.createNewBackup(true);
|
||||
verifyNumberOfValidBackups(bdb, 2);
|
||||
bdb.put("key1".getBytes(), "valueV3".getBytes());
|
||||
bdb.put("key2".getBytes(), "valueV3".getBytes());
|
||||
assertThat(new String(bdb.get("key1".getBytes()))).endsWith("V3");
|
||||
assertThat(new String(bdb.get("key2".getBytes()))).endsWith("V3");
|
||||
bdb.close();
|
||||
|
||||
// init RestoreBackupableDB
|
||||
rdb = new RestoreBackupableDB(bopt);
|
||||
verifyNumberOfValidBackups(rdb, 2);
|
||||
// restore db from latest backup
|
||||
rdb.restoreDBFromLatestBackup(dbFolder.getRoot().getAbsolutePath(),
|
||||
dbFolder.getRoot().getAbsolutePath(),
|
||||
new RestoreOptions(false));
|
||||
// Open database again.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Values must have suffix V2 because of restoring latest backup.
|
||||
assertThat(new String(bdb.get("key1".getBytes()))).endsWith("V2");
|
||||
assertThat(new String(bdb.get("key2".getBytes()))).endsWith("V2");
|
||||
} finally {
|
||||
if (bdb != null) {
|
||||
bdb.close();
|
||||
}
|
||||
if (rdb != null) {
|
||||
rdb.dispose();
|
||||
}
|
||||
if (bopt != null) {
|
||||
bopt.dispose();
|
||||
}
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restoreFromBackup()
|
||||
throws RocksDBException {
|
||||
Options opt = null;
|
||||
BackupableDBOptions bopt = null;
|
||||
BackupableDB bdb = null;
|
||||
RestoreBackupableDB rdb = null;
|
||||
try {
|
||||
opt = new Options().setCreateIfMissing(true);
|
||||
bopt = new BackupableDBOptions(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
assertThat(bopt.backupDir()).isEqualTo(
|
||||
backupFolder.getRoot().getAbsolutePath());
|
||||
// Open empty database.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Fill database with some test values
|
||||
prepareDatabase(bdb);
|
||||
bdb.createNewBackup(true);
|
||||
verifyNumberOfValidBackups(bdb, 1);
|
||||
bdb.put("key1".getBytes(), "valueV2".getBytes());
|
||||
bdb.put("key2".getBytes(), "valueV2".getBytes());
|
||||
bdb.createNewBackup(true);
|
||||
verifyNumberOfValidBackups(bdb, 2);
|
||||
bdb.put("key1".getBytes(), "valueV3".getBytes());
|
||||
bdb.put("key2".getBytes(), "valueV3".getBytes());
|
||||
assertThat(new String(bdb.get("key1".getBytes()))).endsWith("V3");
|
||||
assertThat(new String(bdb.get("key2".getBytes()))).endsWith("V3");
|
||||
bdb.close();
|
||||
|
||||
// init RestoreBackupableDB
|
||||
rdb = new RestoreBackupableDB(bopt);
|
||||
List<BackupInfo> backupInfo = verifyNumberOfValidBackups(rdb, 2);
|
||||
// restore db from first backup
|
||||
rdb.restoreDBFromBackup(backupInfo.get(0).backupId(),
|
||||
dbFolder.getRoot().getAbsolutePath(),
|
||||
dbFolder.getRoot().getAbsolutePath(),
|
||||
new RestoreOptions(false));
|
||||
// Open database again.
|
||||
bdb = BackupableDB.open(opt, bopt,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
// Values must have suffix V2 because of restoring latest backup.
|
||||
assertThat(new String(bdb.get("key1".getBytes()))).endsWith("V1");
|
||||
assertThat(new String(bdb.get("key2".getBytes()))).endsWith("V1");
|
||||
} finally {
|
||||
if (bdb != null) {
|
||||
bdb.close();
|
||||
}
|
||||
if (rdb != null) {
|
||||
rdb.dispose();
|
||||
}
|
||||
if (bopt != null) {
|
||||
bopt.dispose();
|
||||
}
|
||||
if (opt != null) {
|
||||
opt.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify backups.
|
||||
*
|
||||
* @param bdb {@link BackupableDB} instance.
|
||||
* @param expectedNumberOfBackups numerical value
|
||||
* @throws RocksDBException thrown if an error occurs within the native
|
||||
* part of the library.
|
||||
*/
|
||||
private List<BackupInfo> verifyNumberOfValidBackups(BackupableDB bdb,
|
||||
int expectedNumberOfBackups) throws RocksDBException {
|
||||
// Verify that backups exist
|
||||
assertThat(bdb.getCorruptedBackups().length).
|
||||
isEqualTo(0);
|
||||
bdb.garbageCollect();
|
||||
List<BackupInfo> backupInfo = bdb.getBackupInfos();
|
||||
assertThat(backupInfo.size()).
|
||||
isEqualTo(expectedNumberOfBackups);
|
||||
return backupInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify backups.
|
||||
*
|
||||
* @param rdb {@link RestoreBackupableDB} instance.
|
||||
* @param expectedNumberOfBackups numerical value
|
||||
* @throws RocksDBException thrown if an error occurs within the native
|
||||
* part of the library.
|
||||
*/
|
||||
private List<BackupInfo> verifyNumberOfValidBackups(
|
||||
RestoreBackupableDB rdb, int expectedNumberOfBackups)
|
||||
throws RocksDBException {
|
||||
// Verify that backups exist
|
||||
assertThat(rdb.getCorruptedBackups().length).
|
||||
isEqualTo(0);
|
||||
rdb.garbageCollect();
|
||||
List<BackupInfo> backupInfo = rdb.getBackupInfos();
|
||||
assertThat(backupInfo.size()).
|
||||
isEqualTo(expectedNumberOfBackups);
|
||||
return backupInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill database with some test values.
|
||||
*
|
||||
* @param db {@link RocksDB} instance.
|
||||
* @throws RocksDBException thrown if an error occurs within the native
|
||||
* part of the library.
|
||||
*/
|
||||
private void prepareDatabase(RocksDB db)
|
||||
throws RocksDBException {
|
||||
db.put("key1".getBytes(), "valueV1".getBytes());
|
||||
db.put("key2".getBytes(), "valueV1".getBytes());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,45 @@ jobject Java_org_rocksdb_BackupableDB_getBackupInfo(
|
|||
backup_infos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDB
|
||||
* Method: getCorruptedBackups
|
||||
* Signature: (J)[I;
|
||||
*/
|
||||
jintArray Java_org_rocksdb_BackupableDB_getCorruptedBackups(
|
||||
JNIEnv* env, jobject jbdb, jlong jhandle) {
|
||||
std::vector<rocksdb::BackupID> backup_ids;
|
||||
reinterpret_cast<rocksdb::BackupableDB*>(jhandle)->
|
||||
GetCorruptedBackups(&backup_ids);
|
||||
// store backupids in int array
|
||||
const int kIdSize = backup_ids.size();
|
||||
int int_backup_ids[kIdSize];
|
||||
for (std::vector<rocksdb::BackupID>::size_type i = 0;
|
||||
i != backup_ids.size(); i++) {
|
||||
int_backup_ids[i] = backup_ids[i];
|
||||
}
|
||||
// Store ints in java array
|
||||
jintArray ret_backup_ids;
|
||||
ret_backup_ids = env->NewIntArray(kIdSize);
|
||||
env->SetIntArrayRegion(ret_backup_ids, 0, kIdSize, int_backup_ids);
|
||||
return ret_backup_ids;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDB
|
||||
* Method: garbageCollect
|
||||
* Signature: (J)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDB_garbageCollect(JNIEnv* env,
|
||||
jobject jobj, jlong jhandle) {
|
||||
auto db = reinterpret_cast<rocksdb::BackupableDB*>(jhandle);
|
||||
rocksdb::Status s = db->GarbageCollect();
|
||||
|
||||
if (!s.ok()) {
|
||||
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// BackupDBOptions
|
||||
|
||||
|
@ -101,20 +140,10 @@ jobject Java_org_rocksdb_BackupableDB_getBackupInfo(
|
|||
* Signature: (Ljava/lang/String;)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_newBackupableDBOptions(
|
||||
JNIEnv* env, jobject jobj, jstring jpath, jboolean jshare_table_files,
|
||||
jboolean jsync, jboolean jdestroy_old_data, jboolean jbackup_log_files,
|
||||
jlong jbackup_rate_limit, jlong jrestore_rate_limit) {
|
||||
jbackup_rate_limit = (jbackup_rate_limit <= 0) ? 0 : jbackup_rate_limit;
|
||||
jrestore_rate_limit = (jrestore_rate_limit <= 0) ? 0 : jrestore_rate_limit;
|
||||
|
||||
JNIEnv* env, jobject jobj, jstring jpath) {
|
||||
const char* cpath = env->GetStringUTFChars(jpath, 0);
|
||||
|
||||
auto bopt = new rocksdb::BackupableDBOptions(cpath, nullptr,
|
||||
jshare_table_files, nullptr, jsync, jdestroy_old_data, jbackup_log_files,
|
||||
jbackup_rate_limit, jrestore_rate_limit);
|
||||
|
||||
auto bopt = new rocksdb::BackupableDBOptions(cpath);
|
||||
env->ReleaseStringUTFChars(jpath, cpath);
|
||||
|
||||
rocksdb::BackupableDBOptionsJni::setHandle(env, jobj, bopt);
|
||||
}
|
||||
|
||||
|
@ -129,6 +158,160 @@ jstring Java_org_rocksdb_BackupableDBOptions_backupDir(
|
|||
return env->NewStringUTF(bopt->backup_dir.c_str());
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: setShareTableFiles
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_setShareTableFiles(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jboolean flag) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
bopt->share_table_files = flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: shareTableFiles
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
jboolean Java_org_rocksdb_BackupableDBOptions_shareTableFiles(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
return bopt->share_table_files;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: setSync
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_setSync(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jboolean flag) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
bopt->sync = flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: sync
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
jboolean Java_org_rocksdb_BackupableDBOptions_sync(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
return bopt->sync;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: setDestroyOldData
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_setDestroyOldData(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jboolean flag) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
bopt->destroy_old_data = flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: destroyOldData
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
jboolean Java_org_rocksdb_BackupableDBOptions_destroyOldData(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
return bopt->destroy_old_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: setBackupLogFiles
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_setBackupLogFiles(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jboolean flag) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
bopt->backup_log_files = flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: backupLogFiles
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
jboolean Java_org_rocksdb_BackupableDBOptions_backupLogFiles(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
return bopt->backup_log_files;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: setBackupRateLimit
|
||||
* Signature: (JJ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_setBackupRateLimit(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jlong jbackup_rate_limit) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
bopt->backup_rate_limit = jbackup_rate_limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: backupRateLimit
|
||||
* Signature: (J)J
|
||||
*/
|
||||
jlong Java_org_rocksdb_BackupableDBOptions_backupRateLimit(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
return bopt->backup_rate_limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: setRestoreRateLimit
|
||||
* Signature: (JJ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_setRestoreRateLimit(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jlong jrestore_rate_limit) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
bopt->restore_rate_limit = jrestore_rate_limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: restoreRateLimit
|
||||
* Signature: (J)J
|
||||
*/
|
||||
jlong Java_org_rocksdb_BackupableDBOptions_restoreRateLimit(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
return bopt->restore_rate_limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: setShareFilesWithChecksum
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
void Java_org_rocksdb_BackupableDBOptions_setShareFilesWithChecksum(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jboolean flag) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
bopt->share_files_with_checksum = flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: shareFilesWithChecksum
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
jboolean Java_org_rocksdb_BackupableDBOptions_shareFilesWithChecksum(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
return bopt->share_files_with_checksum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_BackupableDBOptions
|
||||
* Method: disposeInternal
|
||||
|
@ -139,6 +322,5 @@ void Java_org_rocksdb_BackupableDBOptions_disposeInternal(
|
|||
auto bopt = reinterpret_cast<rocksdb::BackupableDBOptions*>(jhandle);
|
||||
assert(bopt);
|
||||
delete bopt;
|
||||
|
||||
rocksdb::BackupableDBOptionsJni::setHandle(env, jopt, nullptr);
|
||||
}
|
||||
|
|
|
@ -145,6 +145,46 @@ jobject Java_org_rocksdb_RestoreBackupableDB_getBackupInfo(
|
|||
backup_infos);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_RestoreBackupableDB
|
||||
* Method: getCorruptedBackups
|
||||
* Signature: (J)[I;
|
||||
*/
|
||||
jintArray Java_org_rocksdb_RestoreBackupableDB_getCorruptedBackups(
|
||||
JNIEnv* env, jobject jbdb, jlong jhandle) {
|
||||
std::vector<rocksdb::BackupID> backup_ids;
|
||||
reinterpret_cast<rocksdb::RestoreBackupableDB*>(jhandle)->
|
||||
GetCorruptedBackups(&backup_ids);
|
||||
// store backupids in int array
|
||||
const int kIdSize = backup_ids.size();
|
||||
int int_backup_ids[kIdSize];
|
||||
for (std::vector<rocksdb::BackupID>::size_type i = 0;
|
||||
i != backup_ids.size(); i++) {
|
||||
int_backup_ids[i] = backup_ids[i];
|
||||
}
|
||||
// Store ints in java array
|
||||
jintArray ret_backup_ids;
|
||||
ret_backup_ids = env->NewIntArray(kIdSize);
|
||||
env->SetIntArrayRegion(ret_backup_ids, 0, kIdSize, int_backup_ids);
|
||||
return ret_backup_ids;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_RestoreBackupableDB
|
||||
* Method: garbageCollect
|
||||
* Signature: (J)V
|
||||
*/
|
||||
void Java_org_rocksdb_RestoreBackupableDB_garbageCollect(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle) {
|
||||
auto db = reinterpret_cast<rocksdb::RestoreBackupableDB*>(
|
||||
jhandle);
|
||||
rocksdb::Status s = db->GarbageCollect();
|
||||
|
||||
if (!s.ok()) {
|
||||
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_RestoreBackupableDB
|
||||
* Method: dispose
|
||||
|
|
Loading…
Reference in New Issue