@ -15,6 +15,11 @@
# include "db/forward_iterator.h"
# include "db/forward_iterator.h"
# include "port/stack_trace.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 {
namespace ROCKSDB_NAMESPACE {
class DBTestTailingIterator : public DBTestBase ,
class DBTestTailingIterator : public DBTestBase ,
@ -50,94 +55,125 @@ TEST_P(DBTestTailingIterator, TailingIteratorSingle) {
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorKeepAdding ) {
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 ;
ReadOptions read_options ;
read_options . tailing = true ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
if ( GetParam ( ) ) {
read_options . async_io = true ;
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 ' ) ;
const int num_records = 10000 ;
{
for ( int i = 0 ; i < num_records ; + + i ) {
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
char buf [ 32 ] ;
ASSERT_OK ( iter - > status ( ) ) ;
snprintf ( buf , sizeof ( buf ) , " %016d " , i ) ;
std : : string value ( 1024 , ' a ' ) ;
Slice key ( buf , 16 ) ;
const int num_records = 10000 ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
for ( int i = 0 ; i < num_records ; + + i ) {
char buf [ 32 ] ;
snprintf ( buf , sizeof ( buf ) , " %016d " , i ) ;
iter - > Seek ( key ) ;
Slice key ( buf , 16 ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
iter - > Seek ( key ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
}
}
}
Close ( ) ;
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorSeekToNext ) {
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 ;
ReadOptions read_options ;
read_options . tailing = true ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
if ( GetParam ( ) ) {
read_options . async_io = true ;
read_options . async_io = true ;
}
}
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
{
ASSERT_OK ( iter - > status ( ) ) ;
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
std : : unique_ptr < Iterator > itern ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_OK ( itern - > status ( ) ) ;
std : : unique_ptr < Iterator > itern (
std : : string value ( 1024 , ' a ' ) ;
db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( itern - > status ( ) ) ;
const int num_records = 1000 ;
std : : string value ( 1024 , ' a ' ) ;
for ( int i = 1 ; i < num_records ; + + i ) {
char buf1 [ 32 ] ;
const int num_records = 1000 ;
char buf2 [ 32 ] ;
for ( int i = 1 ; i < num_records ; + + i ) {
snprintf ( buf1 , sizeof ( buf1 ) , " 00a0%016d " , i * 5 ) ;
char buf1 [ 32 ] ;
char buf2 [ 32 ] ;
Slice key ( buf1 , 20 ) ;
snprintf ( buf1 , sizeof ( buf1 ) , " 00a0%016d " , i * 5 ) ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
Slice key ( buf1 , 20 ) ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
if ( i % 100 = = 99 ) {
ASSERT_OK ( Flush ( 1 ) ) ;
}
if ( i % 100 = = 99 ) {
snprintf ( buf2 , sizeof ( buf2 ) , " 00a0%016d " , i * 5 - 2 ) ;
ASSERT_OK ( Flush ( 1 ) ) ;
Slice target ( buf2 , 20 ) ;
iter - > Seek ( target ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
if ( i = = 1 ) {
itern - > SeekToFirst ( ) ;
} else {
itern - > Next ( ) ;
}
ASSERT_TRUE ( itern - > Valid ( ) ) ;
ASSERT_EQ ( itern - > key ( ) . compare ( key ) , 0 ) ;
}
}
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > ClearAllCallBacks ( ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > DisableProcessing ( ) ;
for ( int i = 2 * num_records ; i > 0 ; - - i ) {
char buf1 [ 32 ] ;
char buf2 [ 32 ] ;
snprintf ( buf1 , sizeof ( buf1 ) , " 00a0%016d " , i * 5 ) ;
Slice key ( buf1 , 20 ) ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
if ( i % 100 = = 99 ) {
ASSERT_OK ( Flush ( 1 ) ) ;
}
snprintf ( buf2 , sizeof ( buf2 ) , " 00a0%016d " , i * 5 - 2 ) ;
snprintf ( buf2 , sizeof ( buf2 ) , " 00a0%016d " , i * 5 - 2 ) ;
Slice target ( buf2 , 20 ) ;
Slice target ( buf2 , 20 ) ;
iter - > Seek ( target ) ;
iter - > Seek ( target ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
if ( i = = 1 ) {
itern - > SeekToFirst ( ) ;
} else {
itern - > Next ( ) ;
}
}
ASSERT_TRUE ( itern - > Valid ( ) ) ;
ASSERT_EQ ( itern - > key ( ) . compare ( key ) , 0 ) ;
}
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > ClearAllCallBacks ( ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > DisableProcessing ( ) ;
for ( int i = 2 * num_records ; i > 0 ; - - i ) {
char buf1 [ 32 ] ;
char buf2 [ 32 ] ;
snprintf ( buf1 , sizeof ( buf1 ) , " 00a0%016d " , i * 5 ) ;
Slice key ( buf1 , 20 ) ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
if ( i % 100 = = 99 ) {
ASSERT_OK ( Flush ( 1 ) ) ;
}
snprintf ( buf2 , sizeof ( buf2 ) , " 00a0%016d " , i * 5 - 2 ) ;
Slice target ( buf2 , 20 ) ;
iter - > Seek ( target ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( iter - > key ( ) . compare ( key ) , 0 ) ;
}
}
Close ( ) ;
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorTrimSeekToNext ) {
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 ;
const uint64_t k150KB = 150 * 1024 ;
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options ;
Options options ;
options . env = env . get ( ) ;
options . write_buffer_size = k150KB ;
options . write_buffer_size = k150KB ;
options . max_write_buffer_number = 3 ;
options . max_write_buffer_number = 3 ;
options . min_write_buffer_number_to_merge = 2 ;
options . min_write_buffer_number_to_merge = 2 ;
@ -278,56 +314,73 @@ TEST_P(DBTestTailingIterator, TailingIteratorTrimSeekToNext) {
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorDeletes ) {
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 ;
ReadOptions read_options ;
read_options . tailing = true ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
if ( GetParam ( ) ) {
read_options . async_io = true ;
read_options . async_io = true ;
}
}
{
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
// write a single record, read it using the iterator, then delete it
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_OK ( Put ( 1 , " 0test " , " test " ) ) ;
iter - > SeekToFirst ( ) ;
// write a single record, read it using the iterator, then delete it
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_OK ( Put ( 1 , " 0test " , " test " ) ) ;
ASSERT_EQ ( iter - > key ( ) . ToString ( ) , " 0test " ) ;
iter - > SeekToFirst ( ) ;
ASSERT_OK ( Delete ( 1 , " 0test " ) ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( iter - > key ( ) . ToString ( ) , " 0test " ) ;
ASSERT_OK ( Delete ( 1 , " 0test " ) ) ;
// write many more records
// write many more records
const int num_records = 10000 ;
const int num_records = 10000 ;
std : : string value ( 1024 , ' A ' ) ;
std : : string value ( 1024 , ' A ' ) ;
for ( int i = 0 ; i < num_records ; + + i ) {
for ( int i = 0 ; i < num_records ; + + i ) {
char buf [ 32 ] ;
char buf [ 32 ] ;
snprintf ( buf , sizeof ( buf ) , " 1%015d " , i ) ;
snprintf ( buf , sizeof ( buf ) , " 1%015d " , i ) ;
Slice key ( buf , 16 ) ;
Slice key ( buf , 16 ) ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
ASSERT_OK ( Put ( 1 , key , value ) ) ;
}
}
// force a flush to make sure that no records are read from memtable
// force a flush to make sure that no records are read from memtable
ASSERT_OK ( Flush ( 1 ) ) ;
ASSERT_OK ( Flush ( 1 ) ) ;
// skip "0test"
// skip "0test"
iter - > Next ( ) ;
iter - > Next ( ) ;
// make sure we can read all new records using the existing iterator
// make sure we can read all new records using the existing iterator
int count = 0 ;
int count = 0 ;
for ( ; iter - > Valid ( ) ; iter - > Next ( ) , + + count )
for ( ; iter - > Valid ( ) ; iter - > Next ( ) , + + count )
;
;
ASSERT_EQ ( count , num_records ) ;
ASSERT_EQ ( count , num_records ) ;
}
Close ( ) ;
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorPrefixSeek ) {
TEST_P ( DBTestTailingIterator , TailingIteratorPrefixSeek ) {
if ( mem_env_ | | encrypted_env_ ) {
ROCKSDB_GTEST_BYPASS ( " Test requires non-mem or non-encrypted environment " ) ;
return ;
}
ReadOptions read_options ;
ReadOptions read_options ;
read_options . tailing = true ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
if ( GetParam ( ) ) {
read_options . async_io = true ;
read_options . async_io = true ;
}
}
std : : unique_ptr < Env > env (
new CompositeEnvWrapper ( env_ , FileSystem : : Default ( ) ) ) ;
Options options = CurrentOptions ( ) ;
Options options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
options . create_if_missing = true ;
options . create_if_missing = true ;
options . disable_auto_compactions = true ;
options . disable_auto_compactions = true ;
options . prefix_extractor . reset ( NewFixedPrefixTransform ( 2 ) ) ;
options . prefix_extractor . reset ( NewFixedPrefixTransform ( 2 ) ) ;
@ -336,28 +389,39 @@ TEST_P(DBTestTailingIterator, TailingIteratorPrefixSeek) {
DestroyAndReopen ( options ) ;
DestroyAndReopen ( options ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
{
ASSERT_OK ( iter - > status ( ) ) ;
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_OK ( Put ( 1 , " 0101 " , " test " ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
ASSERT_OK ( Put ( 1 , " 0101 " , " test " ) ) ;
ASSERT_OK ( Flush ( 1 ) ) ;
ASSERT_OK ( Flush ( 1 ) ) ;
ASSERT_OK ( Put ( 1 , " 0202 " , " test " ) ) ;
ASSERT_OK ( Put ( 1 , " 0202 " , " test " ) ) ;
// Seek(0102) shouldn't find any records since 0202 has a different prefix
// Seek(0102) shouldn't find any records since 0202 has a different prefix
iter - > Seek ( " 0102 " ) ;
iter - > Seek ( " 0102 " ) ;
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
iter - > Seek ( " 0202 " ) ;
iter - > Seek ( " 0202 " ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( iter - > key ( ) . ToString ( ) , " 0202 " ) ;
ASSERT_EQ ( iter - > key ( ) . ToString ( ) , " 0202 " ) ;
iter - > Next ( ) ;
iter - > Next ( ) ;
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
}
Close ( ) ;
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorIncomplete ) {
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 ;
ReadOptions read_options ;
read_options . tailing = true ;
read_options . tailing = true ;
if ( GetParam ( ) ) {
if ( GetParam ( ) ) {
@ -370,20 +434,30 @@ TEST_P(DBTestTailingIterator, TailingIteratorIncomplete) {
ASSERT_OK ( db_ - > Put ( WriteOptions ( ) , key , value ) ) ;
ASSERT_OK ( db_ - > Put ( WriteOptions ( ) , key , value ) ) ;
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options ) ) ;
{
ASSERT_OK ( iter - > status ( ) ) ;
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options ) ) ;
iter - > SeekToFirst ( ) ;
ASSERT_OK ( iter - > status ( ) ) ;
// we either see the entry or it's not in cache
iter - > SeekToFirst ( ) ;
ASSERT_TRUE ( iter - > Valid ( ) | | iter - > status ( ) . IsIncomplete ( ) ) ;
// we either see the entry or it's not in cache
ASSERT_TRUE ( iter - > Valid ( ) | | iter - > status ( ) . IsIncomplete ( ) ) ;
ASSERT_OK ( db_ - > CompactRange ( CompactRangeOptions ( ) , nullptr , nullptr ) ) ;
iter - > SeekToFirst ( ) ;
ASSERT_OK ( db_ - > CompactRange ( CompactRangeOptions ( ) , nullptr , nullptr ) ) ;
// should still be true after compaction
iter - > SeekToFirst ( ) ;
ASSERT_TRUE ( iter - > Valid ( ) | | iter - > status ( ) . IsIncomplete ( ) ) ;
// should still be true after compaction
ASSERT_TRUE ( iter - > Valid ( ) | | iter - > status ( ) . IsIncomplete ( ) ) ;
}
Close ( ) ;
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorSeekToSame ) {
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 options = CurrentOptions ( ) ;
options . env = env . get ( ) ;
options . compaction_style = kCompactionStyleUniversal ;
options . compaction_style = kCompactionStyleUniversal ;
options . write_buffer_size = 1000 ;
options . write_buffer_size = 1000 ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
CreateAndReopenWithCF ( { " pikachu " } , options ) ;
@ -403,28 +477,39 @@ TEST_P(DBTestTailingIterator, TailingIteratorSeekToSame) {
ASSERT_OK ( db_ - > Put ( WriteOptions ( ) , key , value ) ) ;
ASSERT_OK ( db_ - > Put ( WriteOptions ( ) , key , value ) ) ;
}
}
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options ) ) ;
{
ASSERT_OK ( iter - > status ( ) ) ;
std : : unique_ptr < Iterator > iter ( db_ - > NewIterator ( read_options ) ) ;
// Seek to 00001. We expect to find 00002.
ASSERT_OK ( iter - > status ( ) ) ;
std : : string start_key = " 00001 " ;
// Seek to 00001. We expect to find 00002.
iter - > Seek ( start_key ) ;
std : : string start_key = " 00001 " ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
iter - > Seek ( start_key ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
std : : string found = iter - > key ( ) . ToString ( ) ;
std : : string found = iter - > key ( ) . ToString ( ) ;
ASSERT_EQ ( " 00002 " , found ) ;
ASSERT_EQ ( " 00002 " , found ) ;
// Now seek to the same key. The iterator should remain in the same
// Now seek to the same key. The iterator should remain in the same
// position.
// position.
iter - > Seek ( found ) ;
iter - > Seek ( found ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_TRUE ( iter - > Valid ( ) ) ;
ASSERT_EQ ( found , iter - > key ( ) . ToString ( ) ) ;
ASSERT_EQ ( found , iter - > key ( ) . ToString ( ) ) ;
}
Close ( ) ;
}
}
// Sets iterate_upper_bound and verifies that ForwardIterator doesn't call
// Sets iterate_upper_bound and verifies that ForwardIterator doesn't call
// Seek() on immutable iterators when target key is >= prev_key and all
// Seek() on immutable iterators when target key is >= prev_key and all
// iterators, including the memtable iterator, are over the upper bound.
// iterators, including the memtable iterator, are over the upper bound.
TEST_P ( DBTestTailingIterator , TailingIteratorUpperBound ) {
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 ) ;
const Slice upper_bound ( " 20 " , 3 ) ;
ReadOptions read_options ;
ReadOptions read_options ;
@ -441,34 +526,51 @@ TEST_P(DBTestTailingIterator, TailingIteratorUpperBound) {
// Add another key to the memtable.
// Add another key to the memtable.
ASSERT_OK ( Put ( 1 , " 21 " , " 21 " ) ) ;
ASSERT_OK ( Put ( 1 , " 21 " , " 21 " ) ) ;
std : : unique_ptr < Iterator > it ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
{
ASSERT_OK ( it - > status ( ) ) ;
bool read_async_called = false ;
it - > Seek ( " 12 " ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
SyncPoint : : GetInstance ( ) - > SetCallBack (
ASSERT_EQ ( " 12 " , it - > key ( ) . ToString ( ) ) ;
" UpdateResults::io_uring_result " ,
[ & ] ( void * /*arg*/ ) { read_async_called = true ; } ) ;
it - > Next ( ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
// Not valid since "21" is over the upper bound.
ASSERT_FALSE ( it - > Valid ( ) ) ;
auto it =
ASSERT_OK ( it - > status ( ) ) ;
std : : unique_ptr < Iterator > ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
// This keeps track of the number of times NeedToSeekImmutable() was true.
ASSERT_OK ( it - > status ( ) ) ;
int immutable_seeks = 0 ;
it - > Seek ( " 12 " ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
ASSERT_TRUE ( it - > Valid ( ) ) ;
" ForwardIterator::SeekInternal:Immutable " ,
ASSERT_EQ ( " 12 " , it - > key ( ) . ToString ( ) ) ;
[ & ] ( void * /*arg*/ ) { + + immutable_seeks ; } ) ;
it - > Next ( ) ;
// Seek to 13. This should not require any immutable seeks.
// Not valid since "21" is over the upper bound.
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > EnableProcessing ( ) ;
ASSERT_FALSE ( it - > Valid ( ) ) ;
it - > Seek ( " 13 " ) ;
ASSERT_OK ( it - > status ( ) ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > DisableProcessing ( ) ;
// This keeps track of the number of times NeedToSeekImmutable() was true.
int immutable_seeks = 0 ;
ASSERT_FALSE ( it - > Valid ( ) ) ;
ROCKSDB_NAMESPACE : : SyncPoint : : GetInstance ( ) - > SetCallBack (
ASSERT_OK ( it - > status ( ) ) ;
" ForwardIterator::SeekInternal:Immutable " ,
if ( GetParam ( ) ) {
[ & ] ( void * /*arg*/ ) { + + immutable_seeks ; } ) ;
ASSERT_EQ ( 1 , immutable_seeks ) ;
} else {
// Seek to 13. This should not require any immutable seeks.
ASSERT_EQ ( 0 , immutable_seeks ) ;
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 ( ) & & read_async_called ) {
ASSERT_EQ ( 1 , immutable_seeks ) ;
} else {
ASSERT_EQ ( 0 , immutable_seeks ) ;
}
}
}
Close ( ) ;
}
}
TEST_P ( DBTestTailingIterator , TailingIteratorGap ) {
TEST_P ( DBTestTailingIterator , TailingIteratorGap ) {
@ -480,7 +582,15 @@ TEST_P(DBTestTailingIterator, TailingIteratorGap) {
// the largest key of index n file and the smallest key of index n+1 file
// 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
// if both file fit in that gap. In this example, 25 < key < 35
// https://github.com/facebook/rocksdb/issues/1372
// 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 ;
ReadOptions read_options ;
read_options . tailing = true ;
read_options . tailing = true ;
@ -512,20 +622,23 @@ TEST_P(DBTestTailingIterator, TailingIteratorGap) {
ColumnFamilyMetaData meta ;
ColumnFamilyMetaData meta ;
db_ - > GetColumnFamilyMetaData ( handles_ [ 1 ] , & meta ) ;
db_ - > GetColumnFamilyMetaData ( handles_ [ 1 ] , & meta ) ;
std : : unique_ptr < Iterator > it ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
{
it - > Seek ( " 30 " ) ;
std : : unique_ptr < Iterator > it ( db_ - > NewIterator ( read_options , handles_ [ 1 ] ) ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
it - > Seek ( " 30 " ) ;
ASSERT_EQ ( " 30 " , it - > key ( ) . ToString ( ) ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
ASSERT_EQ ( " 30 " , it - > key ( ) . ToString ( ) ) ;
it - > Next ( ) ;
it - > Next ( ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
ASSERT_EQ ( " 35 " , it - > key ( ) . ToString ( ) ) ;
ASSERT_EQ ( " 35 " , it - > key ( ) . ToString ( ) ) ;
it - > Next ( ) ;
it - > Next ( ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
ASSERT_TRUE ( it - > Valid ( ) ) ;
ASSERT_EQ ( " 40 " , it - > key ( ) . ToString ( ) ) ;
ASSERT_EQ ( " 40 " , it - > key ( ) . ToString ( ) ) ;
ASSERT_OK ( it - > status ( ) ) ;
ASSERT_OK ( it - > status ( ) ) ;
}
Close ( ) ;
}
}
TEST_P ( DBTestTailingIterator , SeekWithUpperBoundBug ) {
TEST_P ( DBTestTailingIterator , SeekWithUpperBoundBug ) {