@ -27,7 +27,7 @@ class CountingLogger : public Logger {
size_t log_count ;
size_t log_count ;
} ;
} ;
class CompactionPickerTest : public testing : : Test {
class CompactionPickerTestBase : public testing : : Test {
public :
public :
const Comparator * ucmp_ ;
const Comparator * ucmp_ ;
InternalKeyComparator icmp_ ;
InternalKeyComparator icmp_ ;
@ -49,9 +49,10 @@ class CompactionPickerTest : public testing::Test {
std : : vector < CompactionInputFiles > input_files_ ;
std : : vector < CompactionInputFiles > input_files_ ;
int compaction_level_start_ ;
int compaction_level_start_ ;
CompactionPickerTest ( )
explicit CompactionPickerTestBase ( const Comparator * _ucmp )
: ucmp_ ( BytewiseComparator ( ) ) ,
: ucmp_ ( _ucmp ) ,
icmp_ ( ucmp_ ) ,
icmp_ ( ucmp_ ) ,
options_ ( CreateOptions ( ucmp_ ) ) ,
ioptions_ ( options_ ) ,
ioptions_ ( options_ ) ,
mutable_cf_options_ ( options_ ) ,
mutable_cf_options_ ( options_ ) ,
mutable_db_options_ ( ) ,
mutable_db_options_ ( ) ,
@ -71,7 +72,7 @@ class CompactionPickerTest : public testing::Test {
std : : numeric_limits < uint64_t > : : max ( ) ) ;
std : : numeric_limits < uint64_t > : : max ( ) ) ;
}
}
~ CompactionPickerTest ( ) override { }
~ CompactionPickerTestBase ( ) override { }
void NewVersionStorage ( int num_levels , CompactionStyle style ) {
void NewVersionStorage ( int num_levels , CompactionStyle style ) {
DeleteVersionStorage ( ) ;
DeleteVersionStorage ( ) ;
@ -97,12 +98,17 @@ class CompactionPickerTest : public testing::Test {
input_files_ . clear ( ) ;
input_files_ . clear ( ) ;
}
}
// REQUIRES: smallest and largest are c-style strings ending with '\0'
void Add ( int level , uint32_t file_number , const char * smallest ,
void Add ( int level , uint32_t file_number , const char * smallest ,
const char * largest , uint64_t file_size = 1 , uint32_t path_id = 0 ,
const char * largest , uint64_t file_size = 1 , uint32_t path_id = 0 ,
SequenceNumber smallest_seq = 100 , SequenceNumber largest_seq = 100 ,
SequenceNumber smallest_seq = 100 , SequenceNumber largest_seq = 100 ,
size_t compensated_file_size = 0 , bool marked_for_compact = false ,
size_t compensated_file_size = 0 , bool marked_for_compact = false ,
Temperature temperature = Temperature : : kUnknown ,
Temperature temperature = Temperature : : kUnknown ,
uint64_t oldest_ancestor_time = kUnknownOldestAncesterTime ) {
uint64_t oldest_ancestor_time = kUnknownOldestAncesterTime ,
Slice ts_of_smallest = Slice ( ) , Slice ts_of_largest = Slice ( ) ) {
assert ( ts_of_smallest . size ( ) = = ucmp_ - > timestamp_size ( ) ) ;
assert ( ts_of_largest . size ( ) = = ucmp_ - > timestamp_size ( ) ) ;
VersionStorageInfo * vstorage ;
VersionStorageInfo * vstorage ;
if ( temp_vstorage_ ) {
if ( temp_vstorage_ ) {
vstorage = temp_vstorage_ . get ( ) ;
vstorage = temp_vstorage_ . get ( ) ;
@ -110,19 +116,46 @@ class CompactionPickerTest : public testing::Test {
vstorage = vstorage_ . get ( ) ;
vstorage = vstorage_ . get ( ) ;
}
}
assert ( level < vstorage - > num_levels ( ) ) ;
assert ( level < vstorage - > num_levels ( ) ) ;
char * smallest_key_buf = nullptr ;
char * largest_key_buf = nullptr ;
if ( ! ts_of_smallest . empty ( ) ) {
smallest_key_buf = new char [ strlen ( smallest ) + ucmp_ - > timestamp_size ( ) ] ;
memcpy ( smallest_key_buf , smallest , strlen ( smallest ) ) ;
memcpy ( smallest_key_buf + strlen ( smallest ) , ts_of_smallest . data ( ) ,
ucmp_ - > timestamp_size ( ) ) ;
largest_key_buf = new char [ strlen ( largest ) + ucmp_ - > timestamp_size ( ) ] ;
memcpy ( largest_key_buf , largest , strlen ( largest ) ) ;
memcpy ( largest_key_buf + strlen ( largest ) , ts_of_largest . data ( ) ,
ucmp_ - > timestamp_size ( ) ) ;
}
InternalKey smallest_ikey = InternalKey (
smallest_key_buf ? Slice ( smallest_key_buf ,
ucmp_ - > timestamp_size ( ) + strlen ( smallest ) )
: smallest ,
smallest_seq , kTypeValue ) ;
InternalKey largest_ikey = InternalKey (
largest_key_buf
? Slice ( largest_key_buf , ucmp_ - > timestamp_size ( ) + strlen ( largest ) )
: largest ,
largest_seq , kTypeValue ) ;
FileMetaData * f = new FileMetaData (
FileMetaData * f = new FileMetaData (
file_number , path_id , file_size ,
file_number , path_id , file_size , smallest_ikey , largest_ikey ,
InternalKey ( smallest , smallest_seq , kTypeValue ) ,
smallest_seq , largest_seq , marked_for_compact , temperature ,
InternalKey ( largest , largest_seq , kTypeValue ) , smallest_seq ,
kInvalidBlobFileNumber , kUnknownOldestAncesterTime ,
largest_seq , marked_for_compact , temperature , kInvalidBlobFileNumber ,
kUnknownFileCreationTime , kUnknownFileChecksum ,
kUnknownOldestAncesterTime , kUnknownFileCreationTime ,
kUnknownFileChecksumFuncName , kNullUniqueId64x2 ) ;
kUnknownFileChecksum , kUnknownFileChecksumFuncName , kNullUniqueId64x2 ) ;
f - > compensated_file_size =
f - > compensated_file_size =
( compensated_file_size ! = 0 ) ? compensated_file_size : file_size ;
( compensated_file_size ! = 0 ) ? compensated_file_size : file_size ;
f - > oldest_ancester_time = oldest_ancestor_time ;
f - > oldest_ancester_time = oldest_ancestor_time ;
vstorage - > AddFile ( level , f ) ;
vstorage - > AddFile ( level , f ) ;
files_ . emplace_back ( f ) ;
files_ . emplace_back ( f ) ;
file_map_ . insert ( { file_number , { f , level } } ) ;
file_map_ . insert ( { file_number , { f , level } } ) ;
delete [ ] smallest_key_buf ;
delete [ ] largest_key_buf ;
}
}
void SetCompactionInputFilesLevels ( int level_count , int start_level ) {
void SetCompactionInputFilesLevels ( int level_count , int start_level ) {
@ -155,9 +188,31 @@ class CompactionPickerTest : public testing::Test {
}
}
private :
private :
Options CreateOptions ( const Comparator * ucmp ) const {
Options opts ;
opts . comparator = ucmp ;
return opts ;
}
std : : unique_ptr < VersionStorageInfo > temp_vstorage_ ;
std : : unique_ptr < VersionStorageInfo > temp_vstorage_ ;
} ;
} ;
class CompactionPickerTest : public CompactionPickerTestBase {
public :
explicit CompactionPickerTest ( )
: CompactionPickerTestBase ( BytewiseComparator ( ) ) { }
~ CompactionPickerTest ( ) override { }
} ;
class CompactionPickerU64TsTest : public CompactionPickerTestBase {
public :
explicit CompactionPickerU64TsTest ( )
: CompactionPickerTestBase ( test : : BytewiseComparatorWithU64TsWrapper ( ) ) { }
~ CompactionPickerU64TsTest ( ) override { }
} ;
TEST_F ( CompactionPickerTest , Empty ) {
TEST_F ( CompactionPickerTest , Empty ) {
NewVersionStorage ( 6 , kCompactionStyleLevel ) ;
NewVersionStorage ( 6 , kCompactionStyleLevel ) ;
UpdateVersionStorageInfo ( ) ;
UpdateVersionStorageInfo ( ) ;
@ -3317,6 +3372,107 @@ TEST_F(CompactionPickerTest, UniversalSizeAmpTierCompactionLastLevel) {
ASSERT_EQ ( compaction - > input_levels ( 6 ) - > num_files , 0 ) ;
ASSERT_EQ ( compaction - > input_levels ( 6 ) - > num_files , 0 ) ;
}
}
TEST_F ( CompactionPickerU64TsTest , Overlap ) {
int num_levels = ioptions_ . num_levels ;
NewVersionStorage ( num_levels , kCompactionStyleLevel ) ;
constexpr int level = 0 ;
constexpr uint64_t file_number = 20ULL ;
constexpr char smallest [ 4 ] = " 500 " ;
constexpr char largest [ 4 ] = " 600 " ;
constexpr uint64_t ts_of_smallest = 12345ULL ;
constexpr uint64_t ts_of_largest = 56789ULL ;
{
std : : string ts1 ;
PutFixed64 ( & ts1 , ts_of_smallest ) ;
std : : string ts2 ;
PutFixed64 ( & ts2 , ts_of_largest ) ;
Add ( level , file_number , smallest , largest ,
/*file_size=*/ 1U , /*path_id=*/ 0 ,
/*smallest_seq=*/ 100 , /*largest_seq=*/ 100 , /*compensated_file_size=*/ 0 ,
/*marked_for_compact=*/ false , /*temperature=*/ Temperature : : kUnknown ,
/*oldest_ancestor_time=*/ kUnknownOldestAncesterTime , ts1 , ts2 ) ;
UpdateVersionStorageInfo ( ) ;
}
std : : unordered_set < uint64_t > input { file_number } ;
std : : vector < CompactionInputFiles > input_files ;
ASSERT_OK ( level_compaction_picker . GetCompactionInputsFromFileNumbers (
& input_files , & input , vstorage_ . get ( ) , CompactionOptions ( ) ) ) ;
std : : unique_ptr < Compaction > comp1 ( level_compaction_picker . CompactFiles (
CompactionOptions ( ) , input_files , level , vstorage_ . get ( ) ,
mutable_cf_options_ , mutable_db_options_ , /*output_path_id=*/ 0 ) ) ;
{
// [600, ts=50000] to [600, ts=50000] is the range to check.
// ucmp->Compare(smallest_user_key, c->GetLargestUserKey()) > 0, but
// ucmp->CompareWithoutTimestamp(smallest_user_key,
// c->GetLargestUserKey()) == 0.
// Should still be considered overlapping.
std : : string user_key_with_ts1 ( largest ) ;
PutFixed64 ( & user_key_with_ts1 , ts_of_largest - 1 ) ;
std : : string user_key_with_ts2 ( largest ) ;
PutFixed64 ( & user_key_with_ts2 , ts_of_largest - 1 ) ;
ASSERT_TRUE ( level_compaction_picker . RangeOverlapWithCompaction (
user_key_with_ts1 , user_key_with_ts2 , level ) ) ;
}
{
// [500, ts=60000] to [500, ts=60000] is the range to check.
// ucmp->Compare(largest_user_key, c->GetSmallestUserKey()) < 0, but
// ucmp->CompareWithoutTimestamp(largest_user_key,
// c->GetSmallestUserKey()) == 0.
// Should still be considered overlapping.
std : : string user_key_with_ts1 ( smallest ) ;
PutFixed64 ( & user_key_with_ts1 , ts_of_smallest + 1 ) ;
std : : string user_key_with_ts2 ( smallest ) ;
PutFixed64 ( & user_key_with_ts2 , ts_of_smallest + 1 ) ;
ASSERT_TRUE ( level_compaction_picker . RangeOverlapWithCompaction (
user_key_with_ts1 , user_key_with_ts2 , level ) ) ;
}
}
TEST_F ( CompactionPickerU64TsTest , CannotTrivialMoveUniversal ) {
constexpr uint64_t kFileSize = 100000 ;
mutable_cf_options_ . level0_file_num_compaction_trigger = 2 ;
mutable_cf_options_ . compaction_options_universal . allow_trivial_move = true ;
NewVersionStorage ( 1 , kCompactionStyleUniversal ) ;
UniversalCompactionPicker universal_compaction_picker ( ioptions_ , & icmp_ ) ;
UpdateVersionStorageInfo ( ) ;
// must return false when there's no files.
ASSERT_FALSE ( universal_compaction_picker . NeedsCompaction ( vstorage_ . get ( ) ) ) ;
std : : string ts1 ;
PutFixed64 ( & ts1 , 9000 ) ;
std : : string ts2 ;
PutFixed64 ( & ts2 , 8000 ) ;
std : : string ts3 ;
PutFixed64 ( & ts3 , 7000 ) ;
std : : string ts4 ;
PutFixed64 ( & ts4 , 6000 ) ;
NewVersionStorage ( 3 , kCompactionStyleUniversal ) ;
// A compaction should be triggered and pick file 2
Add ( 1 , 1U , " 150 " , " 150 " , kFileSize , /*path_id=*/ 0 , /*smallest_seq=*/ 100 ,
/*largest_seq=*/ 100 , /*compensated_file_size=*/ kFileSize ,
/*marked_for_compact=*/ false , Temperature : : kUnknown ,
kUnknownOldestAncesterTime , ts1 , ts2 ) ;
Add ( 2 , 2U , " 150 " , " 150 " , kFileSize , /*path_id=*/ 0 , /*smallest_seq=*/ 100 ,
/*largest_seq=*/ 100 , /*compensated_file_size=*/ kFileSize ,
/*marked_for_compact=*/ false , Temperature : : kUnknown ,
kUnknownOldestAncesterTime , ts3 , ts4 ) ;
UpdateVersionStorageInfo ( ) ;
std : : unique_ptr < Compaction > compaction (
universal_compaction_picker . PickCompaction (
cf_name_ , mutable_cf_options_ , mutable_db_options_ , vstorage_ . get ( ) ,
& log_buffer_ ) ) ;
assert ( compaction ) ;
ASSERT_TRUE ( ! compaction - > is_trivial_move ( ) ) ;
}
class PerKeyPlacementCompactionPickerTest
class PerKeyPlacementCompactionPickerTest
: public CompactionPickerTest ,
: public CompactionPickerTest ,
public testing : : WithParamInterface < bool > {
public testing : : WithParamInterface < bool > {