Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
kvdb
rocksdb
提交
4f882924
R
rocksdb
项目概览
kvdb
/
rocksdb
11 个月 前同步成功
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rocksdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4f882924
编写于
11月 21, 2014
作者:
Y
Yueh-Hsuan Chiang
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #404 from fyrz/RocksJava-Backup-Restore-3.8
[RocksJava] Update BackupableDB and RestoreBackupableDB to 3.8.0.
上级
4b63fcbf
faa8d32b
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
1199 addition
and
180 deletion
+1199
-180
java/Makefile
java/Makefile
+2
-1
java/org/rocksdb/BackupableDB.java
java/org/rocksdb/BackupableDB.java
+53
-16
java/org/rocksdb/BackupableDBOptions.java
java/org/rocksdb/BackupableDBOptions.java
+218
-28
java/org/rocksdb/RestoreBackupableDB.java
java/org/rocksdb/RestoreBackupableDB.java
+58
-22
java/org/rocksdb/test/BackupableDBOptionsTest.java
java/org/rocksdb/test/BackupableDBOptionsTest.java
+284
-0
java/org/rocksdb/test/BackupableDBTest.java
java/org/rocksdb/test/BackupableDBTest.java
+349
-100
java/rocksjni/backupablejni.cc
java/rocksjni/backupablejni.cc
+195
-13
java/rocksjni/restorejni.cc
java/rocksjni/restorejni.cc
+40
-0
未找到文件。
java/Makefile
浏览文件 @
4f882924
...
...
@@ -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
\
...
...
java/org/rocksdb/BackupableDB.java
浏览文件 @
4f882924
...
...
@@ -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>
*
* @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>
*
* 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.
* <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
;
}
java/org/rocksdb/BackupableDBOptions.java
浏览文件 @
4f882924
...
...
@@ -5,63 +5,242 @@
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"}
* Best to set this to {@code db name_ + "/backups"}
* @throws java.lang.IllegalArgumentException if illegal path is used.
*/
public
BackupableDBOptions
(
String
path
)
{
super
();
File
backupPath
=
path
==
null
?
null
:
new
File
(
path
);
if
(
backupPath
==
null
||
!
backupPath
.
isDirectory
()
||
!
backupPath
.
canWrite
())
{
throw
new
IllegalArgumentException
(
"Illegal path provided."
);
}
newBackupableDBOptions
(
path
);
}
/**
* <p>Returns the path to the BackupableDB directory.</p>
*
* @return the path to the BackupableDB directory.
*/
public
String
backupDir
()
{
assert
(
isInitialized
());
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.
* Default: true
*
* <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.
* Default: true
*
* <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.
* Default: false
*
* <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.
* 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
*
* <p>Default: true</p>
*
* @return instance of current BackupableDBOptions.
*/
public
BackupableDBOptions
(
String
path
,
boolean
shareTableFiles
,
boolean
sync
,
boolean
destroyOldData
,
boolean
backupLogFiles
,
long
backupRateLimit
,
long
restoreRateLimit
)
{
super
();
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_
);
}
newBackupableDBOptions
(
path
,
shareTableFiles
,
sync
,
destroyOldData
,
backupLogFiles
,
backupRateLimit
,
restoreRateLimit
);
/**
* <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
;
}
/**
*
Returns the path to the BackupableDB directory.
*
<p>Return of share files with checksum is active.</p>
*
* @return the path to the BackupableDB directory.
* @return boolean value indicating if share files with checksum
* is active.
*/
public
String
backupDir
()
{
public
boolean
shareFilesWithChecksum
()
{
assert
(
isInitialized
());
return
backupDir
(
nativeHandle_
);
return
shareFilesWithChecksum
(
nativeHandle_
);
}
/**
...
...
@@ -69,13 +248,24 @@ public class BackupableDBOptions extends RocksObject {
* 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
);
}
java/org/rocksdb/RestoreBackupableDB.java
浏览文件 @
4f882924
...
...
@@ -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.
*/
@Override
public
synchronized
void
disposeInternal
()
{
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
()
{
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
);
}
java/org/rocksdb/test/BackupableDBOptionsTest.java
0 → 100644
浏览文件 @
4f882924
// 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
;
}
}
java/org/rocksdb/test/BackupableDBTest.java
浏览文件 @
4f882924
...
...
@@ -28,138 +28,387 @@ public class BackupableDBTest {
public
TemporaryFolder
backupFolder
=
new
TemporaryFolder
();
@Test
public
void
backup
able
Db
()
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
());
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
);
verifyNumberOfValidBackups
(
bdb
,
2
);
}
finally
{
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
(),
false
,
true
,
false
,
true
,
0
,
0
);
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
(
bopt
!=
null
)
{
bopt
.
dispose
();
}
if
(
opt
!=
null
)
{
opt
.
dispose
();
}
}
}
List
<
BackupInfo
>
backupInfos
;
List
<
BackupInfo
>
restoreInfos
;
@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
());
bdb
.
put
(
"abc"
.
getBytes
(),
"def"
.
getBytes
());
bdb
.
put
(
"ghi"
.
getBytes
(),
"jkl"
.
getBytes
());
// 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
();
}
}
}
backupInfos
=
bdb
.
getBackupInfos
();
assertThat
(
backupInfos
.
size
()).
isEqualTo
(
0
);
@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
);
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
();
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
();
// restore from backup
ropt
=
new
RestoreOptions
(
false
);
// init RestoreBackupableDB
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
(
verifyNumberOfValidBackups
(
rdb
,
2
);
// restore db from latest backup
rdb
.
restoreDBFromLatestBackup
(
dbFolder
.
getRoot
().
getAbsolutePath
(),
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
new
RestoreOptions
(
false
));
// Open database again.
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
);
// 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
(
opt
!=
null
)
{
opt
.
dispose
();
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
(
ropt
!=
null
)
{
ropt
.
dispose
();
}
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
());
}
}
java/rocksjni/backupablejni.cc
浏览文件 @
4f882924
...
...
@@ -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
);
}
java/rocksjni/restorejni.cc
浏览文件 @
4f882924
...
...
@@ -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
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录