Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
kvdb
rocksdb
提交
5ff8aec4
R
rocksdb
项目概览
kvdb
/
rocksdb
12 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
5ff8aec4
编写于
11月 21, 2014
作者:
F
fyrz
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[RocksJava] TTL Support
上级
ca47da9e
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
213 addition
and
24 deletion
+213
-24
java/org/rocksdb/TtlDB.java
java/org/rocksdb/TtlDB.java
+111
-17
java/org/rocksdb/test/TtlDBTest.java
java/org/rocksdb/test/TtlDBTest.java
+69
-7
java/rocksjni/ttl.cc
java/rocksjni/ttl.cc
+33
-0
未找到文件。
java/org/rocksdb/TtlDB.java
浏览文件 @
5ff8aec4
...
...
@@ -7,20 +7,85 @@ package org.rocksdb;
import
java.util.List
;
/**
* Database with TTL support.
*
* <p><strong>Use case</strong></p>
* <p>This API should be used to open the db when key-values inserted are
* meant to be removed from the db in a non-strict 'ttl' amount of time
* Therefore, this guarantees that key-values inserted will remain in the
* db for >= ttl amount of time and the db will make efforts to remove the
* key-values as soon as possible after ttl seconds of their insertion.
* </p>
*
* <p><strong>Behaviour</strong></p>
* <p>TTL is accepted in seconds
* (int32_t)Timestamp(creation) is suffixed to values in Put internally
* Expired TTL values deleted in compaction only:(Timestamp+ttl<time_now)
* Get/Iterator may return expired entries(compaction not run on them yet)
* Different TTL may be used during different Opens
* </p>
*
* <p><strong>Example</strong></p>
* <ul>
* <li>Open1 at t=0 with ttl=4 and insert k1,k2, close at t=2</li>
* <li>Open2 at t=3 with ttl=5. Now k1,k2 should be deleted at t>=5</li>
* </ul>
*
* <p>
* read_only=true opens in the usual read-only mode. Compactions will not be
* triggered(neither manual nor automatic), so no expired entries removed
* </p>
*
* <p><strong>Constraints</strong></p>
* <p>Not specifying/passing or non-positive TTL behaves
* like TTL = infinity</p>
*
* <p><strong>!!!WARNING!!!</strong></p>
* <p>Calling DB::Open directly to re-open a db created by this API will get
* corrupt values(timestamp suffixed) and no ttl effect will be there
* during the second Open, so use this API consistently to open the db
* Be careful when passing ttl with a small positive value because the
* whole database may be deleted in a small amount of time.</p>
*/
public
class
TtlDB
extends
RocksDB
{
//static Status Open(const Options& options, const std::string& dbname,
// DBWithTTL** dbptr, int32_t ttl = 0,
// bool read_only = false);
/**
* <p>Opens a TtlDB.</p>
*
* <p>Database is opened in read-write mode without default TTL.</p>
*
* @param options {@link org.rocksdb.Options} instance.
* @param db_path path to database.
*
* @return TtlDB instance.
*
* @throws RocksDBException thrown if an error occurs within the native
* part of the library.
*/
public
static
TtlDB
open
(
Options
options
,
String
db_path
)
throws
RocksDBException
{
return
open
(
options
,
db_path
,
0
,
false
);
}
/**
* <p>Opens a TtlDB.</p>
*
* @param options {@link org.rocksdb.Options} instance.
* @param db_path path to database.
* @param ttl time to live for new entries.
* @param readOnly boolean value indicating if database if db is
* opened read-only.
*
* @return TtlDB instance.
*
* @throws RocksDBException thrown if an error occurs within the native
* part of the library.
*/
public
static
TtlDB
open
(
Options
options
,
String
db_path
,
int
ttl
,
boolean
readOnly
)
throws
RocksDBException
{
TtlDB
ttldb
=
new
TtlDB
();
ttldb
.
open
(
options
.
nativeHandle_
,
db_path
,
ttl
,
readOnly
);
// Prevent the RocksDB object from attempting to delete
// the underly C++ DB object.
//ttldb.disOwnNativeHandle();
return
ttldb
;
}
...
...
@@ -38,17 +103,39 @@ public class TtlDB extends RocksDB {
return
null
;
}
/**
* <p>Creates a new ttl based column family with a name defined
* in given ColumnFamilyDescriptor and allocates a
* ColumnFamilyHandle within an internal structure.</p>
*
* <p>The ColumnFamilyHandle is automatically disposed with DB
* disposal.</p>
*
* @param columnFamilyDescriptor column family to be created.
* @param ttl TTL to set for this column family.
*
* @return {@link org.rocksdb.ColumnFamilyHandle} instance.
*
* @throws RocksDBException thrown if error happens in underlying
* native library.
*/
public
ColumnFamilyHandle
createColumnFamilyWithTtl
(
ColumnFamilyDescriptor
columnFamilyDescriptor
,
int
ttl
)
{
return
null
;
ColumnFamilyDescriptor
columnFamilyDescriptor
,
int
ttl
)
throws
RocksDBException
{
assert
(
isInitialized
());
return
new
ColumnFamilyHandle
(
this
,
createColumnFamilyWithTtl
(
nativeHandle_
,
columnFamilyDescriptor
,
ttl
));
}
/**
*
Close the TtlDB instance and release resource.
*
<p>Close the TtlDB instance and release resource.</p>
*
* Internally, TtlDB 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::TtlDB} and should be transparent to Java developers.
* <p>Internally, TtlDB 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::TtlDB} and should be transparent to
* Java developers.</p>
*/
@Override
public
synchronized
void
close
()
{
if
(
isInitialized
())
{
...
...
@@ -57,9 +144,13 @@ public class TtlDB extends RocksDB {
}
/**
* A protected construction that will be used in the static factory
* method {@link #open(DBOptions, String, java.util.List, java.util.List)} and
* {@link #open(DBOptions, String, java.util.List, java.util.List, java.util.List, boolean)}.
* <p>A protected constructor that will be used in the static
* factory method
* {@link #open(DBOptions, String, java.util.List, java.util.List)}
* and
* {@link #open(DBOptions, String, java.util.List,
* java.util.List, java.util.List, boolean)}.
* </p>
*/
protected
TtlDB
()
{
super
();
...
...
@@ -72,4 +163,7 @@ public class TtlDB extends RocksDB {
private
native
void
open
(
long
optionsHandle
,
String
db_path
,
int
ttl
,
boolean
readOnly
)
throws
RocksDBException
;
private
native
long
createColumnFamilyWithTtl
(
long
handle
,
ColumnFamilyDescriptor
columnFamilyDescriptor
,
int
ttl
)
throws
RocksDBException
;
}
java/org/rocksdb/test/TtlDBTest.java
浏览文件 @
5ff8aec4
...
...
@@ -9,9 +9,9 @@ import org.junit.ClassRule;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.rules.TemporaryFolder
;
import
org.rocksdb.
Options
;
import
org.rocksdb.RocksDBException
;
import
org.rocksdb.TtlDB
;
import
org.rocksdb.
*
;
import
java.util.concurrent.TimeUnit
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
...
@@ -25,19 +25,49 @@ public class TtlDBTest {
public
TemporaryFolder
dbFolder
=
new
TemporaryFolder
();
@Test
public
void
ttlDBOpen
()
throws
RocksDBException
,
InterruptedException
{
public
void
ttlDBOpen
()
throws
RocksDBException
,
InterruptedException
{
Options
options
=
null
;
TtlDB
ttlDB
=
null
;
try
{
options
=
new
Options
().
setCreateIfMissing
(
true
);
options
=
new
Options
().
setCreateIfMissing
(
true
).
setMaxGrandparentOverlapFactor
(
0
).
setMaxMemCompactionLevel
(
0
);
ttlDB
=
TtlDB
.
open
(
options
,
dbFolder
.
getRoot
().
getAbsolutePath
());
ttlDB
.
put
(
"key"
.
getBytes
(),
"value"
.
getBytes
());
assertThat
(
ttlDB
.
get
(
"key"
.
getBytes
())).
isEqualTo
(
"value"
.
getBytes
());
assertThat
(
ttlDB
.
get
(
"key"
.
getBytes
())).
isNotNull
();
}
finally
{
if
(
ttlDB
!=
null
)
{
ttlDB
.
close
();
}
if
(
options
!=
null
)
{
options
.
dispose
();
}
}
}
@Test
public
void
ttlDBOpenWithTtl
()
throws
RocksDBException
,
InterruptedException
{
Options
options
=
null
;
TtlDB
ttlDB
=
null
;
try
{
options
=
new
Options
().
setCreateIfMissing
(
true
).
setMaxGrandparentOverlapFactor
(
0
).
setMaxMemCompactionLevel
(
0
);
ttlDB
=
TtlDB
.
open
(
options
,
dbFolder
.
getRoot
().
getAbsolutePath
(),
1
,
false
);
ttlDB
.
put
(
"key"
.
getBytes
(),
"value"
.
getBytes
());
assertThat
(
ttlDB
.
get
(
"key"
.
getBytes
())).
isEqualTo
(
"value"
.
getBytes
());
Thread
.
sleep
(
1250
);
ttlDB
.
compactRange
();
TimeUnit
.
SECONDS
.
sleep
(
2
);
ttlDB
.
compactRange
();
assertThat
(
ttlDB
.
get
(
"key"
.
getBytes
())).
isNull
();
}
finally
{
if
(
ttlDB
!=
null
)
{
...
...
@@ -48,4 +78,36 @@ public class TtlDBTest {
}
}
}
@Test
public
void
createTtlColumnFamily
()
throws
RocksDBException
,
InterruptedException
{
Options
options
=
null
;
TtlDB
ttlDB
=
null
;
ColumnFamilyHandle
columnFamilyHandle
=
null
;
try
{
options
=
new
Options
().
setCreateIfMissing
(
true
);
ttlDB
=
TtlDB
.
open
(
options
,
dbFolder
.
getRoot
().
getAbsolutePath
());
columnFamilyHandle
=
ttlDB
.
createColumnFamilyWithTtl
(
new
ColumnFamilyDescriptor
(
"new_cf"
),
1
);
ttlDB
.
put
(
columnFamilyHandle
,
"key"
.
getBytes
(),
"value"
.
getBytes
());
assertThat
(
ttlDB
.
get
(
columnFamilyHandle
,
"key"
.
getBytes
())).
isEqualTo
(
"value"
.
getBytes
());
Thread
.
sleep
(
2500
);
ttlDB
.
compactRange
(
columnFamilyHandle
);
assertThat
(
ttlDB
.
get
(
columnFamilyHandle
,
"key"
.
getBytes
())).
isNull
();
}
finally
{
if
(
columnFamilyHandle
!=
null
)
{
columnFamilyHandle
.
dispose
();
}
if
(
ttlDB
!=
null
)
{
ttlDB
.
close
();
}
if
(
options
!=
null
)
{
options
.
dispose
();
}
}
}
}
java/rocksjni/ttl.cc
浏览文件 @
5ff8aec4
...
...
@@ -40,3 +40,36 @@ void Java_org_rocksdb_TtlDB_open(JNIEnv* env, jobject jttldb,
}
rocksdb
::
RocksDBExceptionJni
::
ThrowNew
(
env
,
s
);
}
/*
* Class: org_rocksdb_TtlDB
* Method: createColumnFamilyWithTtl
* Signature: (JLorg/rocksdb/ColumnFamilyDescriptor;I)J;
*/
jlong
Java_org_rocksdb_TtlDB_createColumnFamilyWithTtl
(
JNIEnv
*
env
,
jobject
jobj
,
jlong
jdb_handle
,
jobject
jcf_descriptor
,
jint
jttl
)
{
rocksdb
::
ColumnFamilyHandle
*
handle
;
auto
db_handle
=
reinterpret_cast
<
rocksdb
::
DBWithTTL
*>
(
jdb_handle
);
jstring
jstr
=
(
jstring
)
env
->
CallObjectMethod
(
jcf_descriptor
,
rocksdb
::
ColumnFamilyDescriptorJni
::
getColumnFamilyNameMethod
(
env
));
// get CF Options
jobject
jcf_opt_obj
=
env
->
CallObjectMethod
(
jcf_descriptor
,
rocksdb
::
ColumnFamilyDescriptorJni
::
getColumnFamilyOptionsMethod
(
env
));
rocksdb
::
ColumnFamilyOptions
*
cfOptions
=
rocksdb
::
ColumnFamilyOptionsJni
::
getHandle
(
env
,
jcf_opt_obj
);
const
char
*
cfname
=
env
->
GetStringUTFChars
(
jstr
,
0
);
rocksdb
::
Status
s
=
db_handle
->
CreateColumnFamilyWithTtl
(
*
cfOptions
,
cfname
,
&
handle
,
jttl
);
env
->
ReleaseStringUTFChars
(
jstr
,
cfname
);
if
(
s
.
ok
())
{
return
reinterpret_cast
<
jlong
>
(
handle
);
}
rocksdb
::
RocksDBExceptionJni
::
ThrowNew
(
env
,
s
);
return
0
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录