Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
kvdb
rocksdb
提交
20065406
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,发现更多精彩内容 >>
提交
20065406
编写于
4月 01, 2016
作者:
A
Adam Retter
提交者:
Yueh-Hsuan Chiang
4月 01, 2016
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Merge pull request #1053 from adamretter/benchmark-java-comparator
Benchmark Java comparator vs C++ comparator
上级
f2c43a4a
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
746 addition
and
2 deletion
+746
-2
java/Makefile
java/Makefile
+1
-0
java/benchmark/src/main/java/org/rocksdb/benchmark/DbBenchmark.java
...mark/src/main/java/org/rocksdb/benchmark/DbBenchmark.java
+48
-1
java/src/main/java/org/rocksdb/AbstractSlice.java
java/src/main/java/org/rocksdb/AbstractSlice.java
+1
-1
java/src/main/java/org/rocksdb/util/BytewiseComparator.java
java/src/main/java/org/rocksdb/util/BytewiseComparator.java
+91
-0
java/src/main/java/org/rocksdb/util/DirectBytewiseComparator.java
.../main/java/org/rocksdb/util/DirectBytewiseComparator.java
+88
-0
java/src/main/java/org/rocksdb/util/ReverseBytewiseComparator.java
...main/java/org/rocksdb/util/ReverseBytewiseComparator.java
+37
-0
java/src/test/java/org/rocksdb/util/BytewiseComparatorTest.java
...rc/test/java/org/rocksdb/util/BytewiseComparatorTest.java
+480
-0
未找到文件。
java/Makefile
浏览文件 @
20065406
...
...
@@ -64,6 +64,7 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
org.rocksdb.BackupEngineTest
\
org.rocksdb.BackupableDBTest
\
org.rocksdb.BlockBasedTableConfigTest
\
org.rocksdb.util.BytewiseComparatorTest
\
org.rocksdb.CheckPointTest
\
org.rocksdb.ColumnFamilyOptionsTest
\
org.rocksdb.ColumnFamilyTest
\
...
...
java/benchmark/src/main/java/org/rocksdb/benchmark/DbBenchmark.java
浏览文件 @
20065406
...
...
@@ -21,10 +21,14 @@
*/
package
org.rocksdb.benchmark
;
import
java.io.IOException
;
import
java.lang.Runnable
;
import
java.lang.Math
;
import
java.io.File
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationTargetException
;
import
java.nio.ByteBuffer
;
import
java.nio.file.Files
;
import
java.util.Collection
;
import
java.util.Date
;
import
java.util.EnumMap
;
...
...
@@ -601,6 +605,11 @@ public class DbBenchmark {
(
Integer
)
flags_
.
get
(
Flag
.
max_successive_merges
));
options
.
setWalTtlSeconds
((
Long
)
flags_
.
get
(
Flag
.
wal_ttl_seconds
));
options
.
setWalSizeLimitMB
((
Long
)
flags_
.
get
(
Flag
.
wal_size_limit_MB
));
if
(
flags_
.
get
(
Flag
.
java_comparator
)
!=
null
)
{
options
.
setComparator
(
(
AbstractComparator
)
flags_
.
get
(
Flag
.
java_comparator
));
}
/* TODO(yhchiang): enable the following parameters
options.setCompressionType((String)flags_.get(Flag.compression_type));
options.setCompressionLevel((Integer)flags_.get(Flag.compression_level));
...
...
@@ -774,6 +783,7 @@ public class DbBenchmark {
}
private
void
open
(
Options
options
)
throws
RocksDBException
{
System
.
out
.
println
(
"Using database directory: "
+
databaseDir_
);
db_
=
RocksDB
.
open
(
options
,
databaseDir_
);
}
...
...
@@ -1475,7 +1485,7 @@ public class DbBenchmark {
return
Integer
.
parseInt
(
value
);
}
},
db
(
"/tmp/rocksdbjni-bench"
,
db
(
getTempDir
(
"rocksdb-jni"
)
,
"Use the db with the following name."
)
{
@Override
public
Object
parseValue
(
String
value
)
{
return
value
;
...
...
@@ -1486,6 +1496,31 @@ public class DbBenchmark {
@Override
public
Object
parseValue
(
String
value
)
{
return
parseBoolean
(
value
);
}
},
java_comparator
(
null
,
"Class name of a Java Comparator to use instead\n"
+
"\tof the default C++ ByteWiseComparatorImpl. Must be available on\n"
+
"\tthe classpath"
)
{
@Override
protected
Object
parseValue
(
final
String
value
)
{
try
{
final
ComparatorOptions
copt
=
new
ComparatorOptions
();
final
Class
<
AbstractComparator
>
clsComparator
=
(
Class
<
AbstractComparator
>)
Class
.
forName
(
value
);
final
Constructor
cstr
=
clsComparator
.
getConstructor
(
ComparatorOptions
.
class
);
return
cstr
.
newInstance
(
copt
);
}
catch
(
final
ClassNotFoundException
cnfe
)
{
throw
new
IllegalArgumentException
(
"Java Comparator '"
+
value
+
"'"
+
" not found on the classpath"
,
cnfe
);
}
catch
(
final
NoSuchMethodException
nsme
)
{
throw
new
IllegalArgumentException
(
"Java Comparator '"
+
value
+
"'"
+
" does not have a public ComparatorOptions constructor"
,
nsme
);
}
catch
(
final
IllegalAccessException
|
InstantiationException
|
InvocationTargetException
ie
)
{
throw
new
IllegalArgumentException
(
"Unable to construct Java"
+
" Comparator '"
+
value
+
"'"
,
ie
);
}
}
};
private
Flag
(
Object
defaultValue
,
String
desc
)
{
...
...
@@ -1516,6 +1551,18 @@ public class DbBenchmark {
private
final
String
desc_
;
}
private
final
static
String
DEFAULT_TEMP_DIR
=
"/tmp"
;
private
static
String
getTempDir
(
final
String
dirName
)
{
try
{
return
Files
.
createTempDirectory
(
dirName
).
toAbsolutePath
().
toString
();
}
catch
(
final
IOException
ioe
)
{
System
.
err
.
println
(
"Unable to create temp directory, defaulting to: "
+
DEFAULT_TEMP_DIR
);
return
DEFAULT_TEMP_DIR
+
File
.
pathSeparator
+
dirName
;
}
}
private
static
class
RandomGenerator
{
private
final
byte
[]
data_
;
private
int
dataLength_
;
...
...
java/src/main/java/org/rocksdb/AbstractSlice.java
浏览文件 @
20065406
...
...
@@ -24,7 +24,7 @@ package org.rocksdb;
* C++ BaseComparatorJniCallback subclass, which in turn destroys the
* Java @see org.rocksdb.AbstractSlice subclass Objects.
*/
abstract
class
AbstractSlice
<
T
>
extends
RocksMutableObject
{
public
abstract
class
AbstractSlice
<
T
>
extends
RocksMutableObject
{
protected
AbstractSlice
()
{
super
();
...
...
java/src/main/java/org/rocksdb/util/BytewiseComparator.java
0 → 100644
浏览文件 @
20065406
// Copyright (c) 2011-present, 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.util
;
import
org.rocksdb.*
;
import
java.nio.ByteBuffer
;
/**
* This is a Java Native implementation of the C++
* equivalent BytewiseComparatorImpl using {@link Slice}
*
* The performance of Comparators implemented in Java is always
* less than their C++ counterparts due to the bridging overhead,
* as such you likely don't want to use this apart from benchmarking
* and you most likely instead wanted
* {@link org.rocksdb.BuiltinComparator#BYTEWISE_COMPARATOR}
*/
public
class
BytewiseComparator
extends
Comparator
{
public
BytewiseComparator
(
final
ComparatorOptions
copt
)
{
super
(
copt
);
}
@Override
public
String
name
()
{
return
"rocksdb.java.BytewiseComparator"
;
}
@Override
public
int
compare
(
final
Slice
a
,
final
Slice
b
)
{
return
compare
(
a
.
data
(),
b
.
data
());
}
@Override
public
String
findShortestSeparator
(
final
String
start
,
final
Slice
limit
)
{
final
byte
[]
startBytes
=
start
.
getBytes
();
final
byte
[]
limitBytes
=
limit
.
data
();
// Find length of common prefix
final
int
min_length
=
Math
.
min
(
startBytes
.
length
,
limit
.
size
());
int
diff_index
=
0
;
while
((
diff_index
<
min_length
)
&&
(
startBytes
[
diff_index
]
==
limitBytes
[
diff_index
]))
{
diff_index
++;
}
if
(
diff_index
>=
min_length
)
{
// Do not shorten if one string is a prefix of the other
}
else
{
final
byte
diff_byte
=
startBytes
[
diff_index
];
if
(
diff_byte
<
0xff
&&
diff_byte
+
1
<
limitBytes
[
diff_index
])
{
final
byte
shortest
[]
=
new
byte
[
diff_index
+
1
];
System
.
arraycopy
(
startBytes
,
0
,
shortest
,
0
,
diff_index
+
1
);
shortest
[
diff_index
]++;
assert
(
compare
(
shortest
,
limitBytes
)
<
0
);
return
new
String
(
shortest
);
}
}
return
null
;
}
private
static
int
compare
(
final
byte
[]
a
,
final
byte
[]
b
)
{
return
ByteBuffer
.
wrap
(
a
).
compareTo
(
ByteBuffer
.
wrap
(
b
));
}
@Override
public
String
findShortSuccessor
(
final
String
key
)
{
final
byte
[]
keyBytes
=
key
.
getBytes
();
// Find first character that can be incremented
final
int
n
=
keyBytes
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
final
byte
byt
=
keyBytes
[
i
];
if
(
byt
!=
0xff
)
{
final
byte
shortSuccessor
[]
=
new
byte
[
i
+
1
];
System
.
arraycopy
(
keyBytes
,
0
,
shortSuccessor
,
0
,
i
+
1
);
shortSuccessor
[
i
]++;
return
new
String
(
shortSuccessor
);
}
}
// *key is a run of 0xffs. Leave it alone.
return
null
;
}
}
java/src/main/java/org/rocksdb/util/DirectBytewiseComparator.java
0 → 100644
浏览文件 @
20065406
// Copyright (c) 2011-present, 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.util
;
import
org.rocksdb.ComparatorOptions
;
import
org.rocksdb.DirectComparator
;
import
org.rocksdb.DirectSlice
;
import
java.nio.ByteBuffer
;
/**
* This is a Java Native implementation of the C++
* equivalent BytewiseComparatorImpl using {@link DirectSlice}
*
* The performance of Comparators implemented in Java is always
* less than their C++ counterparts due to the bridging overhead,
* as such you likely don't want to use this apart from benchmarking
* and you most likely instead wanted
* {@link org.rocksdb.BuiltinComparator#BYTEWISE_COMPARATOR}
*/
public
class
DirectBytewiseComparator
extends
DirectComparator
{
public
DirectBytewiseComparator
(
final
ComparatorOptions
copt
)
{
super
(
copt
);
}
@Override
public
String
name
()
{
return
"rocksdb.java.DirectBytewiseComparator"
;
}
@Override
public
int
compare
(
final
DirectSlice
a
,
final
DirectSlice
b
)
{
return
a
.
data
().
compareTo
(
b
.
data
());
}
@Override
public
String
findShortestSeparator
(
final
String
start
,
final
DirectSlice
limit
)
{
final
byte
[]
startBytes
=
start
.
getBytes
();
// Find length of common prefix
final
int
min_length
=
Math
.
min
(
startBytes
.
length
,
limit
.
size
());
int
diff_index
=
0
;
while
((
diff_index
<
min_length
)
&&
(
startBytes
[
diff_index
]
==
limit
.
get
(
diff_index
)))
{
diff_index
++;
}
if
(
diff_index
>=
min_length
)
{
// Do not shorten if one string is a prefix of the other
}
else
{
final
byte
diff_byte
=
startBytes
[
diff_index
];
if
(
diff_byte
<
0xff
&&
diff_byte
+
1
<
limit
.
get
(
diff_index
))
{
final
byte
shortest
[]
=
new
byte
[
diff_index
+
1
];
System
.
arraycopy
(
startBytes
,
0
,
shortest
,
0
,
diff_index
+
1
);
shortest
[
diff_index
]++;
assert
(
ByteBuffer
.
wrap
(
shortest
).
compareTo
(
limit
.
data
())
<
0
);
return
new
String
(
shortest
);
}
}
return
null
;
}
@Override
public
String
findShortSuccessor
(
final
String
key
)
{
final
byte
[]
keyBytes
=
key
.
getBytes
();
// Find first character that can be incremented
final
int
n
=
keyBytes
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
final
byte
byt
=
keyBytes
[
i
];
if
(
byt
!=
0xff
)
{
final
byte
shortSuccessor
[]
=
new
byte
[
i
+
1
];
System
.
arraycopy
(
keyBytes
,
0
,
shortSuccessor
,
0
,
i
+
1
);
shortSuccessor
[
i
]++;
return
new
String
(
shortSuccessor
);
}
}
// *key is a run of 0xffs. Leave it alone.
return
null
;
}
}
java/src/main/java/org/rocksdb/util/ReverseBytewiseComparator.java
0 → 100644
浏览文件 @
20065406
// Copyright (c) 2011-present, 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.util
;
import
org.rocksdb.BuiltinComparator
;
import
org.rocksdb.ComparatorOptions
;
import
org.rocksdb.Slice
;
/**
* This is a Java Native implementation of the C++
* equivalent ReverseBytewiseComparatorImpl using {@link Slice}
*
* The performance of Comparators implemented in Java is always
* less than their C++ counterparts due to the bridging overhead,
* as such you likely don't want to use this apart from benchmarking
* and you most likely instead wanted
* {@link BuiltinComparator#REVERSE_BYTEWISE_COMPARATOR}
*/
public
class
ReverseBytewiseComparator
extends
BytewiseComparator
{
public
ReverseBytewiseComparator
(
final
ComparatorOptions
copt
)
{
super
(
copt
);
}
@Override
public
String
name
()
{
return
"rocksdb.java.ReverseBytewiseComparator"
;
}
@Override
public
int
compare
(
final
Slice
a
,
final
Slice
b
)
{
return
-
super
.
compare
(
a
,
b
);
}
}
java/src/test/java/org/rocksdb/util/BytewiseComparatorTest.java
0 → 100644
浏览文件 @
20065406
// Copyright (c) 2011-present, 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.util
;
import
org.junit.Test
;
import
org.rocksdb.*
;
import
org.rocksdb.Comparator
;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.FileVisitResult
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.SimpleFileVisitor
;
import
java.nio.file.attribute.BasicFileAttributes
;
import
java.util.*
;
import
static
org
.
junit
.
Assert
.*;
/**
* This is a direct port of various C++
* tests from db/comparator_db_test.cc
* and some code to adapt it to RocksJava
*/
public
class
BytewiseComparatorTest
{
/**
* Open the database using the C++ BytewiseComparatorImpl
* and test the results against our Java BytewiseComparator
*/
@Test
public
void
java_vs_cpp_bytewiseComparator
()
throws
IOException
,
RocksDBException
{
for
(
int
rand_seed
=
301
;
rand_seed
<
306
;
rand_seed
++)
{
final
Path
dbDir
=
Files
.
createTempDirectory
(
"comparator_db_test"
);
try
(
final
RocksDB
db
=
openDatabase
(
dbDir
,
BuiltinComparator
.
BYTEWISE_COMPARATOR
))
{
final
Random
rnd
=
new
Random
(
rand_seed
);
doRandomIterationTest
(
db
,
toJavaComparator
(
new
BytewiseComparator
(
new
ComparatorOptions
())),
Arrays
.
asList
(
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
,
"g"
,
"h"
,
"i"
),
rnd
,
8
,
100
,
3
);
}
finally
{
removeData
(
dbDir
);
}
}
}
/**
* Open the database using the Java BytewiseComparator
* and test the results against another Java BytewiseComparator
*/
@Test
public
void
java_vs_java_bytewiseComparator
()
throws
IOException
,
RocksDBException
{
for
(
int
rand_seed
=
301
;
rand_seed
<
306
;
rand_seed
++)
{
final
Path
dbDir
=
Files
.
createTempDirectory
(
"comparator_db_test"
);
try
(
final
RocksDB
db
=
openDatabase
(
dbDir
,
new
BytewiseComparator
(
new
ComparatorOptions
())))
{
final
Random
rnd
=
new
Random
(
rand_seed
);
doRandomIterationTest
(
db
,
toJavaComparator
(
new
BytewiseComparator
(
new
ComparatorOptions
())),
Arrays
.
asList
(
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
,
"g"
,
"h"
,
"i"
),
rnd
,
8
,
100
,
3
);
}
finally
{
removeData
(
dbDir
);
}
}
}
/**
* Open the database using the C++ BytewiseComparatorImpl
* and test the results against our Java DirectBytewiseComparator
*/
@Test
public
void
java_vs_cpp_directBytewiseComparator
()
throws
IOException
,
RocksDBException
{
for
(
int
rand_seed
=
301
;
rand_seed
<
306
;
rand_seed
++)
{
final
Path
dbDir
=
Files
.
createTempDirectory
(
"comparator_db_test"
);
try
(
final
RocksDB
db
=
openDatabase
(
dbDir
,
BuiltinComparator
.
BYTEWISE_COMPARATOR
))
{
final
Random
rnd
=
new
Random
(
rand_seed
);
doRandomIterationTest
(
db
,
toJavaComparator
(
new
DirectBytewiseComparator
(
new
ComparatorOptions
())
),
Arrays
.
asList
(
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
,
"g"
,
"h"
,
"i"
),
rnd
,
8
,
100
,
3
);
}
finally
{
removeData
(
dbDir
);
}
}
}
/**
* Open the database using the Java DirectBytewiseComparator
* and test the results against another Java DirectBytewiseComparator
*/
@Test
public
void
java_vs_java_directBytewiseComparator
()
throws
IOException
,
RocksDBException
{
for
(
int
rand_seed
=
301
;
rand_seed
<
306
;
rand_seed
++)
{
final
Path
dbDir
=
Files
.
createTempDirectory
(
"comparator_db_test"
);
try
(
final
RocksDB
db
=
openDatabase
(
dbDir
,
new
DirectBytewiseComparator
(
new
ComparatorOptions
())))
{
final
Random
rnd
=
new
Random
(
rand_seed
);
doRandomIterationTest
(
db
,
toJavaComparator
(
new
DirectBytewiseComparator
(
new
ComparatorOptions
())
),
Arrays
.
asList
(
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
,
"g"
,
"h"
,
"i"
),
rnd
,
8
,
100
,
3
);
}
finally
{
removeData
(
dbDir
);
}
}
}
/**
* Open the database using the C++ ReverseBytewiseComparatorImpl
* and test the results against our Java ReverseBytewiseComparator
*/
@Test
public
void
java_vs_cpp_reverseBytewiseComparator
()
throws
IOException
,
RocksDBException
{
for
(
int
rand_seed
=
301
;
rand_seed
<
306
;
rand_seed
++)
{
final
Path
dbDir
=
Files
.
createTempDirectory
(
"comparator_db_test"
);
try
(
final
RocksDB
db
=
openDatabase
(
dbDir
,
BuiltinComparator
.
REVERSE_BYTEWISE_COMPARATOR
))
{
final
Random
rnd
=
new
Random
(
rand_seed
);
doRandomIterationTest
(
db
,
toJavaComparator
(
new
ReverseBytewiseComparator
(
new
ComparatorOptions
())
),
Arrays
.
asList
(
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
,
"g"
,
"h"
,
"i"
),
rnd
,
8
,
100
,
3
);
}
finally
{
removeData
(
dbDir
);
}
}
}
/**
* Open the database using the Java ReverseBytewiseComparator
* and test the results against another Java ReverseBytewiseComparator
*/
@Test
public
void
java_vs_java_reverseBytewiseComparator
()
throws
IOException
,
RocksDBException
{
for
(
int
rand_seed
=
301
;
rand_seed
<
306
;
rand_seed
++)
{
final
Path
dbDir
=
Files
.
createTempDirectory
(
"comparator_db_test"
);
try
(
final
RocksDB
db
=
openDatabase
(
dbDir
,
new
ReverseBytewiseComparator
(
new
ComparatorOptions
())))
{
final
Random
rnd
=
new
Random
(
rand_seed
);
doRandomIterationTest
(
db
,
toJavaComparator
(
new
ReverseBytewiseComparator
(
new
ComparatorOptions
())
),
Arrays
.
asList
(
"a"
,
"b"
,
"c"
,
"d"
,
"e"
,
"f"
,
"g"
,
"h"
,
"i"
),
rnd
,
8
,
100
,
3
);
}
finally
{
removeData
(
dbDir
);
}
}
}
private
void
doRandomIterationTest
(
final
RocksDB
db
,
final
java
.
util
.
Comparator
<
String
>
javaComparator
,
final
List
<
String
>
source_strings
,
final
Random
rnd
,
final
int
num_writes
,
final
int
num_iter_ops
,
final
int
num_trigger_flush
)
throws
RocksDBException
{
final
TreeMap
<
String
,
String
>
map
=
new
TreeMap
<>(
javaComparator
);
for
(
int
i
=
0
;
i
<
num_writes
;
i
++)
{
if
(
num_trigger_flush
>
0
&&
i
!=
0
&&
i
%
num_trigger_flush
==
0
)
{
db
.
flush
(
new
FlushOptions
());
}
final
int
type
=
rnd
.
nextInt
(
2
);
final
int
index
=
rnd
.
nextInt
(
source_strings
.
size
());
final
String
key
=
source_strings
.
get
(
index
);
switch
(
type
)
{
case
0
:
// put
map
.
put
(
key
,
key
);
db
.
put
(
new
WriteOptions
(),
bytes
(
key
),
bytes
(
key
));
break
;
case
1
:
// delete
if
(
map
.
containsKey
(
key
))
{
map
.
remove
(
key
);
}
db
.
remove
(
new
WriteOptions
(),
bytes
(
key
));
break
;
default
:
fail
(
"Should not be able to generate random outside range 1..2"
);
}
}
try
(
final
RocksIterator
iter
=
db
.
newIterator
(
new
ReadOptions
()))
{
final
KVIter
<
String
,
String
>
result_iter
=
new
KVIter
(
map
);
boolean
is_valid
=
false
;
for
(
int
i
=
0
;
i
<
num_iter_ops
;
i
++)
{
// Random walk and make sure iter and result_iter returns the
// same key and value
final
int
type
=
rnd
.
nextInt
(
6
);
iter
.
status
();
switch
(
type
)
{
case
0
:
// Seek to First
iter
.
seekToFirst
();
result_iter
.
seekToFirst
();
break
;
case
1
:
// Seek to last
iter
.
seekToLast
();
result_iter
.
seekToLast
();
break
;
case
2
:
{
// Seek to random key
final
int
key_idx
=
rnd
.
nextInt
(
source_strings
.
size
());
final
String
key
=
source_strings
.
get
(
key_idx
);
iter
.
seek
(
bytes
(
key
));
result_iter
.
seek
(
bytes
(
key
));
break
;
}
case
3
:
// Next
if
(
is_valid
)
{
iter
.
next
();
result_iter
.
next
();
}
else
{
continue
;
}
break
;
case
4
:
// Prev
if
(
is_valid
)
{
iter
.
prev
();
result_iter
.
prev
();
}
else
{
continue
;
}
break
;
default
:
{
assert
(
type
==
5
);
final
int
key_idx
=
rnd
.
nextInt
(
source_strings
.
size
());
final
String
key
=
source_strings
.
get
(
key_idx
);
final
byte
[]
result
=
db
.
get
(
new
ReadOptions
(),
bytes
(
key
));
if
(!
map
.
containsKey
(
key
))
{
assertNull
(
result
);
}
else
{
assertArrayEquals
(
bytes
(
map
.
get
(
key
)),
result
);
}
break
;
}
}
assertEquals
(
result_iter
.
isValid
(),
iter
.
isValid
());
is_valid
=
iter
.
isValid
();
if
(
is_valid
)
{
assertArrayEquals
(
bytes
(
result_iter
.
key
()),
iter
.
key
());
//note that calling value on a non-valid iterator from the Java API
//results in a SIGSEGV
assertArrayEquals
(
bytes
(
result_iter
.
value
()),
iter
.
value
());
}
}
}
}
/**
* Open the database using a C++ Comparator
*/
private
RocksDB
openDatabase
(
final
Path
dbDir
,
final
BuiltinComparator
cppComparator
)
throws
IOException
,
RocksDBException
{
final
Options
options
=
new
Options
()
.
setCreateIfMissing
(
true
)
.
setComparator
(
cppComparator
);
return
RocksDB
.
open
(
options
,
dbDir
.
toAbsolutePath
().
toString
());
}
/**
* Open the database using a Java Comparator
*/
private
RocksDB
openDatabase
(
final
Path
dbDir
,
final
AbstractComparator
<?
extends
AbstractSlice
<?>>
javaComparator
)
throws
IOException
,
RocksDBException
{
final
Options
options
=
new
Options
()
.
setCreateIfMissing
(
true
)
.
setComparator
(
javaComparator
);
return
RocksDB
.
open
(
options
,
dbDir
.
toAbsolutePath
().
toString
());
}
private
void
closeDatabase
(
final
RocksDB
db
)
{
db
.
close
();
}
private
void
removeData
(
final
Path
dbDir
)
throws
IOException
{
Files
.
walkFileTree
(
dbDir
,
new
SimpleFileVisitor
<
Path
>()
{
@Override
public
FileVisitResult
visitFile
(
final
Path
file
,
final
BasicFileAttributes
attrs
)
throws
IOException
{
Files
.
delete
(
file
);
return
FileVisitResult
.
CONTINUE
;
}
@Override
public
FileVisitResult
postVisitDirectory
(
final
Path
dir
,
final
IOException
exc
)
throws
IOException
{
Files
.
delete
(
dir
);
return
FileVisitResult
.
CONTINUE
;
}
});
}
private
byte
[]
bytes
(
final
String
s
)
{
return
s
.
getBytes
(
StandardCharsets
.
UTF_8
);
}
private
java
.
util
.
Comparator
<
String
>
toJavaComparator
(
final
Comparator
rocksComparator
)
{
return
new
java
.
util
.
Comparator
<
String
>()
{
@Override
public
int
compare
(
final
String
s1
,
final
String
s2
)
{
return
rocksComparator
.
compare
(
new
Slice
(
s1
),
new
Slice
(
s2
));
}
};
}
private
java
.
util
.
Comparator
<
String
>
toJavaComparator
(
final
DirectComparator
rocksComparator
)
{
return
new
java
.
util
.
Comparator
<
String
>()
{
@Override
public
int
compare
(
final
String
s1
,
final
String
s2
)
{
return
rocksComparator
.
compare
(
new
DirectSlice
(
s1
),
new
DirectSlice
(
s2
));
}
};
}
private
class
KVIter
<
K
,
V
>
implements
RocksIteratorInterface
{
private
final
List
<
Map
.
Entry
<
K
,
V
>>
entries
;
private
final
java
.
util
.
Comparator
<?
super
K
>
comparator
;
private
int
offset
=
-
1
;
private
int
lastPrefixMatchIdx
=
-
1
;
private
int
lastPrefixMatch
=
0
;
public
KVIter
(
final
TreeMap
<
K
,
V
>
map
)
{
this
.
entries
=
new
ArrayList
<>();
final
Iterator
<
Map
.
Entry
<
K
,
V
>>
iterator
=
map
.
entrySet
().
iterator
();
while
(
iterator
.
hasNext
())
{
entries
.
add
(
iterator
.
next
());
}
this
.
comparator
=
map
.
comparator
();
}
@Override
public
boolean
isValid
()
{
return
offset
>
-
1
&&
offset
<
entries
.
size
();
}
@Override
public
void
seekToFirst
()
{
offset
=
0
;
}
@Override
public
void
seekToLast
()
{
offset
=
entries
.
size
()
-
1
;
}
@Override
public
void
seek
(
final
byte
[]
target
)
{
for
(
offset
=
0
;
offset
<
entries
.
size
();
offset
++)
{
if
(
comparator
.
compare
(
entries
.
get
(
offset
).
getKey
(),
(
K
)
new
String
(
target
,
StandardCharsets
.
UTF_8
))
>=
0
)
{
return
;
}
}
}
/**
* Is `a` a prefix of `b`
*
* @return The length of the matching prefix, or 0 if it is not a prefix
*/
private
int
isPrefix
(
final
byte
[]
a
,
final
byte
[]
b
)
{
if
(
b
.
length
>=
a
.
length
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
return
i
;
}
}
return
a
.
length
;
}
else
{
return
0
;
}
}
@Override
public
void
next
()
{
if
(
offset
<
entries
.
size
())
{
offset
++;
}
}
@Override
public
void
prev
()
{
if
(
offset
>=
0
)
{
offset
--;
}
}
@Override
public
void
status
()
throws
RocksDBException
{
if
(
offset
<
0
||
offset
>=
entries
.
size
())
{
throw
new
RocksDBException
(
"Index out of bounds. Size is: "
+
entries
.
size
()
+
", offset is: "
+
offset
);
}
}
public
K
key
()
{
if
(!
isValid
())
{
if
(
entries
.
isEmpty
())
{
return
(
K
)
""
;
}
else
if
(
offset
==
-
1
){
return
entries
.
get
(
0
).
getKey
();
}
else
if
(
offset
==
entries
.
size
())
{
return
entries
.
get
(
offset
-
1
).
getKey
();
}
else
{
return
(
K
)
""
;
}
}
else
{
return
entries
.
get
(
offset
).
getKey
();
}
}
public
V
value
()
{
if
(!
isValid
())
{
return
(
V
)
""
;
}
else
{
return
entries
.
get
(
offset
).
getValue
();
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录