@ -15,6 +15,11 @@
# include "db/forward_iterator.h"
# include "port/stack_trace.h"
namespace {
static bool enable_io_uring = true ;
extern " C " bool RocksDbIOUringEnable ( ) { return enable_io_uring ; }
} // namespace
namespace ROCKSDB_NAMESPACE {
class DBTestTailingIterator : public DBTestBase ,
@ -50,12 +55,22 @@ TEST_P(DBTestTailingIterator, TailingIteratorSingle) {
}
TEST_P ( DBTestTailingIterator , TailingIteratorKeepAdding ) {
CreateAndReopenWithCF ( { " pikachu " } , CurrentOptions ( ) ) ;
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
ReadOptions read_options ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
read_options . async_io = true ;
}
{
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
std : : string value ( 1024 , ' a ' ) ;
@ -73,17 +88,29 @@ TEST_P(DBTestTailingIterator, TailingIteratorKeepAdding) {
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
}
}
Close ( ) ;
}
TEST_P ( DBTestTailingIterator , TailingIteratorSeekToNext ) {
CreateAndReopenWithCF ( { " pikachu " } , CurrentOptions ( ) ) ;
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
ReadOptions read_options ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
read_options . async_io = true ;
}
{
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
std : : unique_ptr < Iterator > itern ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
std : : unique_ptr < Iterator > itern (
db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( itern - > status ( ) ) ;
std : : string value ( 1024 , ' a ' ) ;
@ -134,10 +161,19 @@ TEST_P(DBTestTailingIterator, TailingIteratorSeekToNext) {
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
}
}
Close ( ) ;
}
TEST_P ( DBTestTailingIterator , TailingIteratorTrimSeekToNext ) {
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
const uint64_t k150KB = 150 * 1024 ;
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options ;
options . env = env . get ( ) ;
options . write_buffer_size = k150KB ;
options . max_write_buffer_number = 3 ;
options . min_write_buffer_number_to_merge = 2 ;
@ -278,13 +314,21 @@ TEST_P(DBTestTailingIterator, TailingIteratorTrimSeekToNext) {
}
TEST_P ( DBTestTailingIterator , TailingIteratorDeletes ) {
CreateAndReopenWithCF ( { " pikachu " } , CurrentOptions ( ) ) ;
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
ReadOptions read_options ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
read_options . async_io = true ;
}
{
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
@ -320,14 +364,23 @@ TEST_P(DBTestTailingIterator, TailingIteratorDeletes) {
ASSERT_EQ ( count , num_records ) ;
}
Close ( ) ;
}
TEST_P ( DBTestTailingIterator , TailingIteratorPrefixSeek ) {
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
ReadOptions read_options ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
read_options . async_io = true ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
options . create_if_missing = true ;
options . disable_auto_compactions = true ;
options . prefix_extractor . reset ( NewFixedPrefixTransform ( 2 ) ) ;
@ -336,6 +389,7 @@ TEST_P(DBTestTailingIterator, TailingIteratorPrefixSeek) {
DestroyAndReopen ( options ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
{
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_OK ( Put ( 1 , " 0101 " , " test " ) ) ;
@ -355,9 +409,19 @@ TEST_P(DBTestTailingIterator, TailingIteratorPrefixSeek) {
iter - > Next ( ) ;
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
}
Close ( ) ;
}
TEST_P ( DBTestTailingIterator , TailingIteratorIncomplete ) {
CreateAndReopenWithCF ( { " pikachu " } , CurrentOptions ( ) ) ;
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
ReadOptions read_options ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
@ -370,6 +434,7 @@ TEST_P(DBTestTailingIterator, TailingIteratorIncomplete) {
ASSERT_OK ( db_ - > Put ( WriteOptions ( ) , key , value ) ) ;
{
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
iter - > SeekToFirst ( ) ;
@ -381,9 +446,18 @@ TEST_P(DBTestTailingIterator, TailingIteratorIncomplete) {
// should still be true after compaction
ASSERT_TRUE ( iter - > Valid ( ) | | iter - > status ( ) . IsIncomplete ( ) ) ;
}
Close ( ) ;
}
TEST_P ( DBTestTailingIterator , TailingIteratorSeekToSame ) {
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
options . compaction_style = kCompactionStyleUniversal ;
options . write_buffer_size = 1000 ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
@ -403,6 +477,7 @@ TEST_P(DBTestTailingIterator, TailingIteratorSeekToSame) {
ASSERT_OK ( db_ - > Put ( WriteOptions ( ) , key , value ) ) ;
}
{
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
// Seek to 00001. We expect to find 00002.
@ -419,12 +494,22 @@ TEST_P(DBTestTailingIterator, TailingIteratorSeekToSame) {
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( found , iter - > key ( ) . ToString ( ) ) ;
}
Close ( ) ;
}
// Sets iterate_upper_bound and verifies that ForwardIterator doesn't call
// Seek() on immutable iterators when target key is >= prev_key and all
// iterators, including the memtable iterator, are over the upper bound.
TEST_P ( DBTestTailingIterator , TailingIteratorUpperBound ) {
CreateAndReopenWithCF ( { " pikachu " } , CurrentOptions ( ) ) ;
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
const Slice upper_bound ( " 20 " , 3 ) ;
ReadOptions read_options ;
@ -441,7 +526,16 @@ TEST_P(DBTestTailingIterator, TailingIteratorUpperBound) {
// Add another key to the memtable.
ASSERT_OK ( Put ( 1 , " 21 " , " 21 " ) ) ;
std : : unique_ptr < Iterator > it ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
{
bool read_async_called = false ;
SyncPoint : : GetInstance ( ) - > SetCallBack (
" UpdateResults::io_uring_result " ,
[ & ] ( void * /*arg*/ ) { read_async_called = true ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
auto it =
std : : unique_ptr < Iterator > ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( it - > status ( ) ) ;
it - > Seek ( " 12 " ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
@ -461,15 +555,23 @@ TEST_P(DBTestTailingIterator, TailingIteratorUpperBound) {
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
it - > Seek ( " 13 " ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > DisableProcessing ( ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > ClearAllCallBacks ( ) ;
SyncPoint : : GetInstance ( ) - > SetCallBack (
" UpdateResults::io_uring_result " ,
[ & ] ( void * /*arg*/ ) { read_async_called = true ; } ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
ASSERT_FALSE ( it - > Valid ( ) ) ;
ASSERT_OK ( it - > status ( ) ) ;
if ( GetParam ( ) ) {
if ( GetParam ( ) & & read_async_called ) {
ASSERT_EQ ( 1 , immutable_seeks ) ;
} else {
ASSERT_EQ ( 0 , immutable_seeks ) ;
}
}
Close ( ) ;
}
TEST_P ( DBTestTailingIterator , TailingIteratorGap ) {
// level 1: [20, 25] [35, 40]
@ -480,7 +582,15 @@ TEST_P(DBTestTailingIterator, TailingIteratorGap) {
// the largest key of index n file and the smallest key of index n+1 file
// if both file fit in that gap. In this example, 25 < key < 35
// https://github.com/facebook/rocksdb/issues/1372
CreateAndReopenWithCF ( { " pikachu " } , CurrentOptions ( ) ) ;
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
ReadOptions read_options ;
read_options . tailing = true ;
@ -512,6 +622,7 @@ TEST_P(DBTestTailingIterator, TailingIteratorGap) {
ColumnFamilyMetaData meta ;
db_ - > GetColumnFamilyMetaData ( handles_ [ 1 ] , & meta ) ;
{
std : : unique_ptr < Iterator > it ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
it - > Seek ( " 30 " ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
@ -527,6 +638,8 @@ TEST_P(DBTestTailingIterator, TailingIteratorGap) {
ASSERT_OK ( it - > status ( ) ) ;
}
Close ( ) ;
}
TEST_P ( DBTestTailingIterator , SeekWithUpperBoundBug ) {
ReadOptions read_options ;