@ -38,8 +38,8 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
// complexity: human readable strings are easier to compress than random
// complexity: human readable strings are easier to compress than random
// strings.
// strings.
static std : : map < std : : string , std : : string > GenerateKVMap (
static std : : map < std : : string , std : : string > GenerateKVMap (
int num_block = 100 ,
int num_block = 100 , bool mixed_with_human_readable_string_value = false ,
bool mixed_with_human_readable_string_value = false ) {
size_t ts_sz = 0 ) {
std : : map < std : : string , std : : string > kv ;
std : : map < std : : string , std : : string > kv ;
Random rnd ( 101 ) ;
Random rnd ( 101 ) ;
@ -58,7 +58,13 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
} else {
} else {
v = rnd . RandomString ( 256 ) ;
v = rnd . RandomString ( 256 ) ;
}
}
if ( ts_sz > 0 ) {
std : : string user_key ;
AppendKeyWithMinTimestamp ( & user_key , std : : string ( k ) , ts_sz ) ;
kv [ user_key ] = v ;
} else {
kv [ std : : string ( k ) ] = v ;
kv [ std : : string ( k ) ] = v ;
}
key + + ;
key + + ;
}
}
}
}
@ -80,21 +86,29 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
// Creates a table with the specificied key value pairs (kv).
// Creates a table with the specificied key value pairs (kv).
void CreateTable ( const std : : string & table_name ,
void CreateTable ( const std : : string & table_name ,
const ImmutableOptions & ioptions ,
const CompressionType & compression_type ,
const CompressionType & compression_type ,
const std : : map < std : : string , std : : string > & kv ) {
const std : : map < std : : string , std : : string > & kv ,
uint32_t compression_parallel_threads = 1 ,
uint32_t compression_dict_bytes = 0 ) {
std : : unique_ptr < WritableFileWriter > writer ;
std : : unique_ptr < WritableFileWriter > writer ;
NewFileWriter ( table_name , & writer ) ;
NewFileWriter ( table_name , & writer ) ;
// Create table builder.
InternalKeyComparator comparator ( ioptions . user_comparator ) ;
ImmutableOptions ioptions ( options_ ) ;
InternalKeyComparator comparator ( options_ . comparator ) ;
ColumnFamilyOptions cf_options ;
ColumnFamilyOptions cf_options ;
cf_options . prefix_extractor = options_ . prefix_extractor ;
MutableCFOptions moptions ( cf_options ) ;
MutableCFOptions moptions ( cf_options ) ;
CompressionOptions compression_opts ;
compression_opts . parallel_threads = compression_parallel_threads ;
// Enable compression dictionary and set a buffering limit that is the same
// as each block's size.
compression_opts . max_dict_bytes = compression_dict_bytes ;
compression_opts . max_dict_buffer_bytes = compression_dict_bytes ;
IntTblPropCollectorFactories factories ;
IntTblPropCollectorFactories factories ;
std : : unique_ptr < TableBuilder > table_builder (
std : : unique_ptr < TableBuilder > table_builder (
options_ . table_factory - > NewTableBuilder (
options_ . table_factory - > NewTableBuilder (
TableBuilderOptions ( ioptions , moptions , comparator , & factories ,
TableBuilderOptions ( ioptions , moptions , comparator , & factories ,
compression_type , CompressionOptions ( ) ,
compression_type , compression_opts ,
0 /* column_family_id */ ,
0 /* column_family_id */ ,
kDefaultColumnFamilyName , - 1 /* level */ ) ,
kDefaultColumnFamilyName , - 1 /* level */ ) ,
writer . get ( ) ) ) ;
writer . get ( ) ) ) ;
@ -114,11 +128,17 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
const std : : string & table_name ,
const std : : string & table_name ,
std : : unique_ptr < BlockBasedTable > * table ,
std : : unique_ptr < BlockBasedTable > * table ,
bool prefetch_index_and_filter_in_cache = true ,
bool prefetch_index_and_filter_in_cache = true ,
Status * status = nullptr ) {
Status * status = nullptr ,
bool user_defined_timestamps_persisted = true ) {
const MutableCFOptions moptions ( options_ ) ;
const MutableCFOptions moptions ( options_ ) ;
TableReaderOptions table_reader_options =
TableReaderOptions table_reader_options = TableReaderOptions (
TableReaderOptions ( ioptions , moptions . prefix_extractor , EnvOptions ( ) ,
ioptions , moptions . prefix_extractor , EnvOptions ( ) , comparator ,
comparator , 0 /* block_protection_bytes_per_key */ ) ;
0 /* block_protection_bytes_per_key */ , false /* _skip_filters */ ,
false /* _immortal */ , false /* _force_direct_prefetch */ ,
- 1 /* _level */ , nullptr /* _block_cache_tracer */ ,
0 /* _max_file_size_for_l0_meta_pin */ , " " /* _cur_db_session_id */ ,
0 /* _cur_file_num */ , { } /* _unique_id */ , 0 /* _largest_seqno */ ,
0 /* _tail_size */ , user_defined_timestamps_persisted ) ;
std : : unique_ptr < RandomAccessFileReader > file ;
std : : unique_ptr < RandomAccessFileReader > file ;
NewFileReader ( table_name , foptions , & file ) ;
NewFileReader ( table_name , foptions , & file ) ;
@ -126,9 +146,11 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
uint64_t file_size = 0 ;
uint64_t file_size = 0 ;
ASSERT_OK ( env_ - > GetFileSize ( Path ( table_name ) , & file_size ) ) ;
ASSERT_OK ( env_ - > GetFileSize ( Path ( table_name ) , & file_size ) ) ;
ReadOptions read_opts ;
read_opts . verify_checksums = true ;
std : : unique_ptr < TableReader > general_table ;
std : : unique_ptr < TableReader > general_table ;
Status s = options_ . table_factory - > NewTableReader (
Status s = options_ . table_factory - > NewTableReader (
ReadOptions ( ) , table_reader_options , std : : move ( file ) , file_size ,
read_opts , table_reader_options , std : : move ( file ) , file_size ,
& general_table , prefetch_index_and_filter_in_cache ) ;
& general_table , prefetch_index_and_filter_in_cache ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
@ -147,6 +169,11 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
std : : shared_ptr < FileSystem > fs_ ;
std : : shared_ptr < FileSystem > fs_ ;
Options options_ ;
Options options_ ;
std : : string ToInternalKey ( const std : : string & key ) {
InternalKey internal_key ( key , 0 , ValueType : : kTypeValue ) ;
return internal_key . Encode ( ) . ToString ( ) ;
}
private :
private :
void WriteToFile ( const std : : string & content , const std : : string & filename ) {
void WriteToFile ( const std : : string & content , const std : : string & filename ) {
std : : unique_ptr < FSWritableFile > f ;
std : : unique_ptr < FSWritableFile > f ;
@ -173,21 +200,31 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
reader - > reset ( new RandomAccessFileReader ( std : : move ( f ) , path ,
reader - > reset ( new RandomAccessFileReader ( std : : move ( f ) , path ,
env_ - > GetSystemClock ( ) . get ( ) ) ) ;
env_ - > GetSystemClock ( ) . get ( ) ) ) ;
}
}
std : : string ToInternalKey ( const std : : string & key ) {
InternalKey internal_key ( key , 0 , ValueType : : kTypeValue ) ;
return internal_key . Encode ( ) . ToString ( ) ;
}
} ;
} ;
// Param 1: compression type
// Param 2: whether to use direct reads
// Param 3: Block Based Table Index type
// Param 4: BBTO no_block_cache option
// Param 5: test mode for the user-defined timestamp feature
// Param 6: number of parallel compression threads
// Param 7: CompressionOptions.max_dict_bytes and
// CompressionOptions.max_dict_buffer_bytes to enable/disable
// compression dictionary.
class BlockBasedTableReaderTest
class BlockBasedTableReaderTest
: public BlockBasedTableReaderBaseTest ,
: public BlockBasedTableReaderBaseTest ,
public testing : : WithParamInterface < std : : tuple <
public testing : : WithParamInterface < std : : tuple <
CompressionType , bool , BlockBasedTableOptions : : IndexType , bool > > {
CompressionType , bool , BlockBasedTableOptions : : IndexType , bool ,
test : : UserDefinedTimestampTestMode , uint32_t , uint32_t > > {
protected :
protected :
void SetUp ( ) override {
void SetUp ( ) override {
compression_type_ = std : : get < 0 > ( GetParam ( ) ) ;
compression_type_ = std : : get < 0 > ( GetParam ( ) ) ;
use_direct_reads_ = std : : get < 1 > ( GetParam ( ) ) ;
use_direct_reads_ = std : : get < 1 > ( GetParam ( ) ) ;
test : : UserDefinedTimestampTestMode udt_test_mode = std : : get < 4 > ( GetParam ( ) ) ;
udt_enabled_ = test : : IsUDTEnabled ( udt_test_mode ) ;
persist_udt_ = test : : ShouldPersistUDT ( udt_test_mode ) ;
compression_parallel_threads_ = std : : get < 5 > ( GetParam ( ) ) ;
compression_dict_bytes_ = std : : get < 6 > ( GetParam ( ) ) ;
BlockBasedTableReaderBaseTest : : SetUp ( ) ;
BlockBasedTableReaderBaseTest : : SetUp ( ) ;
}
}
@ -195,24 +232,45 @@ class BlockBasedTableReaderTest
BlockBasedTableOptions opts ;
BlockBasedTableOptions opts ;
opts . index_type = std : : get < 2 > ( GetParam ( ) ) ;
opts . index_type = std : : get < 2 > ( GetParam ( ) ) ;
opts . no_block_cache = std : : get < 3 > ( GetParam ( ) ) ;
opts . no_block_cache = std : : get < 3 > ( GetParam ( ) ) ;
opts . filter_policy . reset ( NewBloomFilterPolicy ( 10 , false ) ) ;
opts . partition_filters =
opts . index_type = =
BlockBasedTableOptions : : IndexType : : kTwoLevelIndexSearch ;
options_ . table_factory . reset (
options_ . table_factory . reset (
static_cast < BlockBasedTableFactory * > ( NewBlockBasedTableFactory ( opts ) ) ) ;
static_cast < BlockBasedTableFactory * > ( NewBlockBasedTableFactory ( opts ) ) ) ;
options_ . prefix_extractor =
std : : shared_ptr < const SliceTransform > ( NewFixedPrefixTransform ( 3 ) ) ;
}
}
CompressionType compression_type_ ;
CompressionType compression_type_ ;
bool use_direct_reads_ ;
bool use_direct_reads_ ;
bool udt_enabled_ ;
bool persist_udt_ ;
uint32_t compression_parallel_threads_ ;
uint32_t compression_dict_bytes_ ;
} ;
} ;
// Tests MultiGet in both direct IO and non-direct IO mode.
// Tests MultiGet in both direct IO and non-direct IO mode.
// The keys should be in cache after MultiGet.
// The keys should be in cache after MultiGet.
TEST_P ( BlockBasedTableReaderTest , MultiGet ) {
TEST_P ( BlockBasedTableReaderTest , MultiGet ) {
Options options ;
ReadOptions read_opts ;
std : : string dummy_ts ( sizeof ( uint64_t ) , ' \0 ' ) ;
Slice read_timestamp = dummy_ts ;
if ( udt_enabled_ ) {
options . comparator = test : : BytewiseComparatorWithU64TsWrapper ( ) ;
read_opts . timestamp = & read_timestamp ;
}
options . persist_user_defined_timestamps = persist_udt_ ;
size_t ts_sz = options . comparator - > timestamp_size ( ) ;
std : : map < std : : string , std : : string > kv =
std : : map < std : : string , std : : string > kv =
BlockBasedTableReaderBaseTest : : GenerateKVMap (
BlockBasedTableReaderBaseTest : : GenerateKVMap (
100 /* num_block */ ,
100 /* num_block */ ,
true /* mixed_with_human_readable_string_value */ ) ;
true /* mixed_with_human_readable_string_value */ , ts_sz ) ;
// Prepare keys, values, and statuses for MultiGet.
// Prepare keys, values, and statuses for MultiGet.
autovector < Slice , MultiGetContext : : MAX_BATCH_SIZE > keys ;
autovector < Slice , MultiGetContext : : MAX_BATCH_SIZE > keys ;
autovector < Slice , MultiGetContext : : MAX_BATCH_SIZE > keys_without_timestamps ;
autovector < PinnableSlice , MultiGetContext : : MAX_BATCH_SIZE > values ;
autovector < PinnableSlice , MultiGetContext : : MAX_BATCH_SIZE > values ;
autovector < Status , MultiGetContext : : MAX_BATCH_SIZE > statuses ;
autovector < Status , MultiGetContext : : MAX_BATCH_SIZE > statuses ;
{
{
@ -221,27 +279,40 @@ TEST_P(BlockBasedTableReaderTest, MultiGet) {
auto it = kv . begin ( ) ;
auto it = kv . begin ( ) ;
for ( int i = 0 ; i < MultiGetContext : : MAX_BATCH_SIZE ; i + + ) {
for ( int i = 0 ; i < MultiGetContext : : MAX_BATCH_SIZE ; i + + ) {
keys . emplace_back ( it - > first ) ;
keys . emplace_back ( it - > first ) ;
if ( ts_sz > 0 ) {
Slice ukey_without_ts = StripTimestampFromUserKey ( it - > first , ts_sz ) ;
keys_without_timestamps . push_back ( ukey_without_ts ) ;
} else {
keys_without_timestamps . emplace_back ( it - > first ) ;
}
values . emplace_back ( ) ;
values . emplace_back ( ) ;
statuses . emplace_back ( ) ;
statuses . emplace_back ( ) ;
std : : advance ( it , step ) ;
std : : advance ( it , step ) ;
}
}
}
}
std : : string table_name =
std : : string table_name = " BlockBasedTableReaderTest_MultiGet " +
" BlockBasedTableReaderTest " + CompressionTypeToString ( compression_type_ ) ;
CompressionTypeToString ( compression_type_ ) ;
CreateTable ( table_name , compression_type_ , kv ) ;
std : : unique_ptr < BlockBasedTable > table ;
Options options ;
ImmutableOptions ioptions ( options ) ;
ImmutableOptions ioptions ( options ) ;
CreateTable ( table_name , ioptions , compression_type_ , kv ,
compression_parallel_threads_ , compression_dict_bytes_ ) ;
std : : unique_ptr < BlockBasedTable > table ;
FileOptions foptions ;
FileOptions foptions ;
foptions . use_direct_reads = use_direct_reads_ ;
foptions . use_direct_reads = use_direct_reads_ ;
InternalKeyComparator comparator ( options . comparator ) ;
InternalKeyComparator comparator ( options . comparator ) ;
NewBlockBasedTableReader ( foptions , ioptions , comparator , table_name , & table ) ;
NewBlockBasedTableReader ( foptions , ioptions , comparator , table_name , & table ,
true /* bool prefetch_index_and_filter_in_cache */ ,
nullptr /* status */ , persist_udt_ ) ;
ASSERT_OK (
table - > VerifyChecksum ( read_opts , TableReaderCaller : : kUserVerifyChecksum ) ) ;
// Ensure that keys are not in cache before MultiGet.
// Ensure that keys are not in cache before MultiGet.
for ( auto & key : keys ) {
for ( auto & key : keys ) {
ASSERT_FALSE ( table - > TEST_KeyInCache ( ReadOptions ( ) , key ) ) ;
std : : string ikey = ToInternalKey ( key . ToString ( ) ) ;
ASSERT_FALSE ( table - > TEST_KeyInCache ( read_opts , ikey ) ) ;
}
}
// Prepare MultiGetContext.
// Prepare MultiGetContext.
@ -249,26 +320,26 @@ TEST_P(BlockBasedTableReaderTest, MultiGet) {
autovector < KeyContext , MultiGetContext : : MAX_BATCH_SIZE > key_context ;
autovector < KeyContext , MultiGetContext : : MAX_BATCH_SIZE > key_context ;
autovector < KeyContext * , MultiGetContext : : MAX_BATCH_SIZE > sorted_keys ;
autovector < KeyContext * , MultiGetContext : : MAX_BATCH_SIZE > sorted_keys ;
for ( size_t i = 0 ; i < keys . size ( ) ; + + i ) {
for ( size_t i = 0 ; i < keys . size ( ) ; + + i ) {
get_context . emplace_back ( BytewiseComparator ( ) , nullptr , nullptr , nullptr ,
get_context . emplace_back ( options . comparator , nullptr , nullptr , nullptr ,
GetContext : : kNotFound , keys [ i ] , & values [ i ] ,
GetContext : : kNotFound , keys [ i ] , & values [ i ] ,
nullptr , nullptr , nullptr , nullptr ,
nullptr , nullptr , nullptr , nullptr ,
true /* do_merge */ , nullptr , nullptr , nullptr ,
true /* do_merge */ , nullptr , nullptr , nullptr ,
nullptr , nullptr , nullptr ) ;
nullptr , nullptr , nullptr ) ;
key_context . emplace_back ( nullptr , keys [ i ] , & values [ i ] , nullptr , nullptr ,
key_context . emplace_back ( nullptr , keys_without_timestamps [ i ] , & values [ i ] ,
& statuses . back ( ) ) ;
nullptr , nullptr , & statuses . back ( ) ) ;
key_context . back ( ) . get_context = & get_context . back ( ) ;
key_context . back ( ) . get_context = & get_context . back ( ) ;
}
}
for ( auto & key_ctx : key_context ) {
for ( auto & key_ctx : key_context ) {
sorted_keys . emplace_back ( & key_ctx ) ;
sorted_keys . emplace_back ( & key_ctx ) ;
}
}
MultiGetContext ctx ( & sorted_keys , 0 , sorted_keys . size ( ) , 0 , ReadOptions ( ) ,
MultiGetContext ctx ( & sorted_keys , 0 , sorted_keys . size ( ) , 0 , read_opts ,
fs_ . get ( ) , nullptr ) ;
fs_ . get ( ) , nullptr ) ;
// Execute MultiGet.
// Execute MultiGet.
MultiGetContext : : Range range = ctx . GetMultiGetRange ( ) ;
MultiGetContext : : Range range = ctx . GetMultiGetRange ( ) ;
PerfContext * perf_ctx = get_perf_context ( ) ;
PerfContext * perf_ctx = get_perf_context ( ) ;
perf_ctx - > Reset ( ) ;
perf_ctx - > Reset ( ) ;
table - > MultiGet ( ReadOptions ( ) , & range , nullptr ) ;
table - > MultiGet ( read_opts , & range , nullptr ) ;
ASSERT_GE ( perf_ctx - > block_read_count - perf_ctx - > index_block_read_count -
ASSERT_GE ( perf_ctx - > block_read_count - perf_ctx - > index_block_read_count -
perf_ctx - > filter_block_read_count -
perf_ctx - > filter_block_read_count -
@ -281,11 +352,78 @@ TEST_P(BlockBasedTableReaderTest, MultiGet) {
}
}
// Check that keys are in cache after MultiGet.
// Check that keys are in cache after MultiGet.
for ( size_t i = 0 ; i < keys . size ( ) ; i + + ) {
for ( size_t i = 0 ; i < keys . size ( ) ; i + + ) {
ASSERT_TRUE ( table - > TEST_KeyInCache ( ReadOptions ( ) , keys [ i ] ) ) ;
std : : string ikey = ToInternalKey ( keys [ i ] . ToString ( ) ) ;
ASSERT_TRUE ( table - > TEST_KeyInCache ( read_opts , ikey ) ) ;
ASSERT_EQ ( values [ i ] . ToString ( ) , kv [ keys [ i ] . ToString ( ) ] ) ;
ASSERT_EQ ( values [ i ] . ToString ( ) , kv [ keys [ i ] . ToString ( ) ] ) ;
}
}
}
}
TEST_P ( BlockBasedTableReaderTest , NewIterator ) {
Options options ;
ReadOptions read_opts ;
std : : string dummy_ts ( sizeof ( uint64_t ) , ' \0 ' ) ;
Slice read_timestamp = dummy_ts ;
if ( udt_enabled_ ) {
options . comparator = test : : BytewiseComparatorWithU64TsWrapper ( ) ;
read_opts . timestamp = & read_timestamp ;
}
options . persist_user_defined_timestamps = persist_udt_ ;
size_t ts_sz = options . comparator - > timestamp_size ( ) ;
std : : map < std : : string , std : : string > kv =
BlockBasedTableReaderBaseTest : : GenerateKVMap (
100 /* num_block */ ,
true /* mixed_with_human_readable_string_value */ , ts_sz ) ;
std : : string table_name = " BlockBasedTableReaderTest_NewIterator " +
CompressionTypeToString ( compression_type_ ) ;
ImmutableOptions ioptions ( options ) ;
CreateTable ( table_name , ioptions , compression_type_ , kv ,
compression_parallel_threads_ , compression_dict_bytes_ ) ;
std : : unique_ptr < BlockBasedTable > table ;
FileOptions foptions ;
foptions . use_direct_reads = use_direct_reads_ ;
InternalKeyComparator comparator ( options . comparator ) ;
NewBlockBasedTableReader ( foptions , ioptions , comparator , table_name , & table ,
true /* bool prefetch_index_and_filter_in_cache */ ,
nullptr /* status */ , persist_udt_ ) ;
ASSERT_OK (
table - > VerifyChecksum ( read_opts , TableReaderCaller : : kUserVerifyChecksum ) ) ;
std : : unique_ptr < InternalIterator > iter ;
iter . reset ( table - > NewIterator (
read_opts , options_ . prefix_extractor . get ( ) , /*arena=*/ nullptr ,
/*skip_filters=*/ false , TableReaderCaller : : kUncategorized ) ) ;
// Test forward scan.
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
iter - > SeekToFirst ( ) ;
ASSERT_OK ( iter - > status ( ) ) ;
for ( auto kv_iter = kv . begin ( ) ; kv_iter ! = kv . end ( ) ; kv_iter + + ) {
std : : string ikey = ToInternalKey ( kv_iter - > first ) ;
ASSERT_EQ ( iter - > key ( ) . ToString ( ) , ikey ) ;
ASSERT_EQ ( iter - > value ( ) . ToString ( ) , kv_iter - > second ) ;
iter - > Next ( ) ;
ASSERT_OK ( iter - > status ( ) ) ;
}
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
// Test backward scan.
iter - > SeekToLast ( ) ;
ASSERT_OK ( iter - > status ( ) ) ;
for ( auto kv_iter = kv . rbegin ( ) ; kv_iter ! = kv . rend ( ) ; kv_iter + + ) {
std : : string ikey = ToInternalKey ( kv_iter - > first ) ;
ASSERT_EQ ( iter - > key ( ) . ToString ( ) , ikey ) ;
ASSERT_EQ ( iter - > value ( ) . ToString ( ) , kv_iter - > second ) ;
iter - > Prev ( ) ;
ASSERT_OK ( iter - > status ( ) ) ;
}
ASSERT_TRUE ( ! iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
}
class ChargeTableReaderTest
class ChargeTableReaderTest
: public BlockBasedTableReaderBaseTest ,
: public BlockBasedTableReaderBaseTest ,
public testing : : WithParamInterface <
public testing : : WithParamInterface <
@ -374,7 +512,8 @@ class ChargeTableReaderTest
std : : size_t approx_table_reader_mem = 0 ;
std : : size_t approx_table_reader_mem = 0 ;
std : : string table_name = " table_for_approx_table_reader_mem " ;
std : : string table_name = " table_for_approx_table_reader_mem " ;
CreateTable ( table_name , compression_type_ , kv_ ) ;
ImmutableOptions ioptions ( options_ ) ;
CreateTable ( table_name , ioptions , compression_type_ , kv_ ) ;
std : : unique_ptr < BlockBasedTable > table ;
std : : unique_ptr < BlockBasedTable > table ;
Status s ;
Status s ;
@ -424,13 +563,14 @@ TEST_P(ChargeTableReaderTest, Basic) {
std : : size_t opened_table_reader_num = 0 ;
std : : size_t opened_table_reader_num = 0 ;
std : : string table_name ;
std : : string table_name ;
std : : vector < std : : unique_ptr < BlockBasedTable > > tables ;
std : : vector < std : : unique_ptr < BlockBasedTable > > tables ;
ImmutableOptions ioptions ( options_ ) ;
// Keep creating BlockBasedTableReader till hiting the memory limit based on
// Keep creating BlockBasedTableReader till hiting the memory limit based on
// cache capacity and creation fails (when charge_table_reader_ ==
// cache capacity and creation fails (when charge_table_reader_ ==
// kEnabled) or reaching a specfied big number of table readers (when
// kEnabled) or reaching a specfied big number of table readers (when
// charge_table_reader_ == kDisabled)
// charge_table_reader_ == kDisabled)
while ( s . ok ( ) & & opened_table_reader_num < max_table_reader_num_uncapped ) {
while ( s . ok ( ) & & opened_table_reader_num < max_table_reader_num_uncapped ) {
table_name = " table_ " + std : : to_string ( opened_table_reader_num ) ;
table_name = " table_ " + std : : to_string ( opened_table_reader_num ) ;
CreateTable ( table_name , compression_type_ , kv_ ) ;
CreateTable ( table_name , ioptions , compression_type_ , kv_ ) ;
tables . push_back ( std : : unique_ptr < BlockBasedTable > ( ) ) ;
tables . push_back ( std : : unique_ptr < BlockBasedTable > ( ) ) ;
NewBlockBasedTableReader (
NewBlockBasedTableReader (
FileOptions ( ) , ImmutableOptions ( options_ ) ,
FileOptions ( ) , ImmutableOptions ( options_ ) ,
@ -465,7 +605,7 @@ TEST_P(ChargeTableReaderTest, Basic) {
- - opened_table_reader_num ;
- - opened_table_reader_num ;
}
}
table_name = " table_for_successful_table_reader_open " ;
table_name = " table_for_successful_table_reader_open " ;
CreateTable ( table_name , compression_type_ , kv_ ) ;
CreateTable ( table_name , ioptions , compression_type_ , kv_ ) ;
tables . push_back ( std : : unique_ptr < BlockBasedTable > ( ) ) ;
tables . push_back ( std : : unique_ptr < BlockBasedTable > ( ) ) ;
NewBlockBasedTableReader (
NewBlockBasedTableReader (
FileOptions ( ) , ImmutableOptions ( options_ ) ,
FileOptions ( ) , ImmutableOptions ( options_ ) ,
@ -491,28 +631,42 @@ class BlockBasedTableReaderTestVerifyChecksum
} ;
} ;
TEST_P ( BlockBasedTableReaderTestVerifyChecksum , ChecksumMismatch ) {
TEST_P ( BlockBasedTableReaderTestVerifyChecksum , ChecksumMismatch ) {
Options options ;
ReadOptions read_opts ;
std : : string dummy_ts ( sizeof ( uint64_t ) , ' \0 ' ) ;
Slice read_timestamp = dummy_ts ;
if ( udt_enabled_ ) {
options . comparator = test : : BytewiseComparatorWithU64TsWrapper ( ) ;
read_opts . timestamp = & read_timestamp ;
}
options . persist_user_defined_timestamps = persist_udt_ ;
size_t ts_sz = options . comparator - > timestamp_size ( ) ;
std : : map < std : : string , std : : string > kv =
std : : map < std : : string , std : : string > kv =
BlockBasedTableReaderBaseTest : : GenerateKVMap ( 800 /* num_block */ ) ;
BlockBasedTableReaderBaseTest : : GenerateKVMap (
800 /* num_block */ ,
false /* mixed_with_human_readable_string_value=*/ , ts_sz ) ;
options . statistics = CreateDBStatistics ( ) ;
ImmutableOptions ioptions ( options ) ;
std : : string table_name =
std : : string table_name =
" BlockBasedTableReaderTest " + CompressionTypeToString ( compression_type_ ) ;
" BlockBasedTableReaderTest " + CompressionTypeToString ( compression_type_ ) ;
CreateTable ( table_name , compression_type_ , kv ) ;
CreateTable ( table_name , ioptions , compression_type_ , kv ,
compression_parallel_threads_ , compression_dict_bytes_ ) ;
std : : unique_ptr < BlockBasedTable > table ;
std : : unique_ptr < BlockBasedTable > table ;
Options options ;
options . statistics = CreateDBStatistics ( ) ;
ImmutableOptions ioptions ( options ) ;
FileOptions foptions ;
FileOptions foptions ;
foptions . use_direct_reads = use_direct_reads_ ;
foptions . use_direct_reads = use_direct_reads_ ;
InternalKeyComparator comparator ( options . comparator ) ;
InternalKeyComparator comparator ( options . comparator ) ;
NewBlockBasedTableReader ( foptions , ioptions , comparator , table_name , & table ) ;
NewBlockBasedTableReader ( foptions , ioptions , comparator , table_name , & table ,
true /* bool prefetch_index_and_filter_in_cache */ ,
nullptr /* status */ , persist_udt_ ) ;
// Use the top level iterator to find the offset/size of the first
// Use the top level iterator to find the offset/size of the first
// 2nd level index block and corrupt the block
// 2nd level index block and corrupt the block
IndexBlockIter iiter_on_stack ;
IndexBlockIter iiter_on_stack ;
BlockCacheLookupContext context { TableReaderCaller : : kUserVerifyChecksum } ;
BlockCacheLookupContext context { TableReaderCaller : : kUserVerifyChecksum } ;
InternalIteratorBase < IndexValue > * iiter = table - > NewIndexIterator (
InternalIteratorBase < IndexValue > * iiter = table - > NewIndexIterator (
ReadOptions ( ) , /*disable_prefix_see k=*/false , & iiter_on_stack ,
read_opts , /*need_upper_bound_chec k=*/false , & iiter_on_stack ,
/*get_context=*/ nullptr , & context ) ;
/*get_context=*/ nullptr , & context ) ;
std : : unique_ptr < InternalIteratorBase < IndexValue > > iiter_unique_ptr ;
std : : unique_ptr < InternalIteratorBase < IndexValue > > iiter_unique_ptr ;
if ( iiter ! = & iiter_on_stack ) {
if ( iiter ! = & iiter_on_stack ) {
@ -529,11 +683,13 @@ TEST_P(BlockBasedTableReaderTestVerifyChecksum, ChecksumMismatch) {
ASSERT_OK ( test : : CorruptFile ( options . env , Path ( table_name ) ,
ASSERT_OK ( test : : CorruptFile ( options . env , Path ( table_name ) ,
static_cast < int > ( handle . offset ( ) ) , 128 ) ) ;
static_cast < int > ( handle . offset ( ) ) , 128 ) ) ;
NewBlockBasedTableReader ( foptions , ioptions , comparator , table_name , & table ) ;
NewBlockBasedTableReader ( foptions , ioptions , comparator , table_name , & table ,
true /* bool prefetch_index_and_filter_in_cache */ ,
nullptr /* status */ , persist_udt_ ) ;
ASSERT_EQ ( 0 ,
ASSERT_EQ ( 0 ,
options . statistics - > getTickerCount ( BLOCK_CHECKSUM_MISMATCH_COUNT ) ) ;
options . statistics - > getTickerCount ( BLOCK_CHECKSUM_MISMATCH_COUNT ) ) ;
Status s = table - > VerifyChecksum ( ReadOptions ( ) ,
Status s =
TableReaderCaller : : kUserVerifyChecksum ) ;
table - > VerifyChecksum ( read_opts , TableReaderCaller : : kUserVerifyChecksum ) ;
ASSERT_EQ ( 1 ,
ASSERT_EQ ( 1 ,
options . statistics - > getTickerCount ( BLOCK_CHECKSUM_MISMATCH_COUNT ) ) ;
options . statistics - > getTickerCount ( BLOCK_CHECKSUM_MISMATCH_COUNT ) ) ;
ASSERT_EQ ( s . code ( ) , Status : : kCorruption ) ;
ASSERT_EQ ( s . code ( ) , Status : : kCorruption ) ;
@ -541,14 +697,25 @@ TEST_P(BlockBasedTableReaderTestVerifyChecksum, ChecksumMismatch) {
// Param 1: compression type
// Param 1: compression type
// Param 2: whether to use direct reads
// Param 2: whether to use direct reads
// Param 3: Block Based Table Index type
// Param 3: Block Based Table Index type, partitioned filters are also enabled
// when index type is kTwoLevelIndexSearch
// Param 4: BBTO no_block_cache option
// Param 4: BBTO no_block_cache option
// Param 5: test mode for the user-defined timestamp feature
// Param 6: number of parallel compression threads
// Param 7: CompressionOptions.max_dict_bytes and
// CompressionOptions.max_dict_buffer_bytes. This enable/disables
// compression dictionary.
INSTANTIATE_TEST_CASE_P (
INSTANTIATE_TEST_CASE_P (
MultiGet , BlockBasedTableReaderTest ,
BlockBasedTableReaderTes t, BlockBasedTableReaderTest ,
: : testing : : Combine (
: : testing : : Combine (
: : testing : : ValuesIn ( GetSupportedCompressions ( ) ) , : : testing : : Bool ( ) ,
: : testing : : ValuesIn ( GetSupportedCompressions ( ) ) , : : testing : : Bool ( ) ,
: : testing : : Values ( BlockBasedTableOptions : : IndexType : : kBinarySearch ) ,
: : testing : : Values (
: : testing : : Values ( false ) ) ) ;
BlockBasedTableOptions : : IndexType : : kBinarySearch ,
BlockBasedTableOptions : : IndexType : : kHashSearch ,
BlockBasedTableOptions : : IndexType : : kTwoLevelIndexSearch ,
BlockBasedTableOptions : : IndexType : : kBinarySearchWithFirstKey ) ,
: : testing : : Values ( false ) , : : testing : : ValuesIn ( test : : GetUDTTestModes ( ) ) ,
: : testing : : Values ( 1 , 2 ) , : : testing : : Values ( 0 , 4096 ) ) ) ;
INSTANTIATE_TEST_CASE_P (
INSTANTIATE_TEST_CASE_P (
VerifyChecksum , BlockBasedTableReaderTestVerifyChecksum ,
VerifyChecksum , BlockBasedTableReaderTestVerifyChecksum ,
: : testing : : Combine (
: : testing : : Combine (
@ -556,7 +723,8 @@ INSTANTIATE_TEST_CASE_P(
: : testing : : Values ( false ) ,
: : testing : : Values ( false ) ,
: : testing : : Values (
: : testing : : Values (
BlockBasedTableOptions : : IndexType : : kTwoLevelIndexSearch ) ,
BlockBasedTableOptions : : IndexType : : kTwoLevelIndexSearch ) ,
: : testing : : Values ( true ) ) ) ;
: : testing : : Values ( true ) , : : testing : : ValuesIn ( test : : GetUDTTestModes ( ) ) ,
: : testing : : Values ( 1 , 2 ) , : : testing : : Values ( 0 ) ) ) ;
} // namespace ROCKSDB_NAMESPACE
} // namespace ROCKSDB_NAMESPACE