@ -1251,7 +1251,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeManualCompaction) {
// pass some time first, otherwise the first a few keys write time are going
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ; } ) ;
int sst_num = 0 ;
@ -1259,7 +1259,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeManualCompaction) {
for ( ; sst_num < kNumTrigger ; sst_num + + ) {
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( sst_num * ( kNumKeys - 1 ) + i ) , " value " ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ;
} ) ;
}
@ -1313,7 +1313,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeAutoCompaction) {
// pass some time first, otherwise the first a few keys write time are going
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ; } ) ;
int sst_num = 0 ;
@ -1321,7 +1321,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeAutoCompaction) {
for ( ; sst_num < kNumTrigger ; sst_num + + ) {
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( sst_num * ( kNumKeys - 1 ) + i ) , " value " ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ;
} ) ;
}
@ -1355,7 +1355,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeAutoCompaction) {
for ( int i = 0 ; i < kNumKeys ; i + + ) {
// the value needs to be big enough to trigger full compaction
ASSERT_OK ( Put ( Key ( sst_num * ( kNumKeys - 1 ) + i ) , rnd . RandomString ( 100 ) ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ;
} ) ;
}
@ -1389,7 +1389,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimePartial) {
// pass some time first, otherwise the first a few keys write time are going
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ; } ) ;
int sst_num = 0 ;
@ -1397,7 +1397,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimePartial) {
for ( ; sst_num < kNumTrigger ; sst_num + + ) {
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( sst_num * ( kNumKeys - 1 ) + i ) , " value " ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ;
} ) ;
}
@ -1463,13 +1463,13 @@ TEST_F(PrecludeLastLevelTest, SmallPrecludeTime) {
Random rnd ( 301 ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( rnd . Uniform ( 10 ) + 1 ) ) ;
} ) ;
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( i ) , rnd . RandomString ( 100 ) ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( rnd . Uniform ( 2 ) ) ) ;
} ) ;
}
@ -1516,7 +1516,7 @@ TEST_F(PrecludeLastLevelTest, LastLevelOnlyCompactionPartial) {
// pass some time first, otherwise the first a few keys write time are going
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ; } ) ;
int sst_num = 0 ;
@ -1524,7 +1524,7 @@ TEST_F(PrecludeLastLevelTest, LastLevelOnlyCompactionPartial) {
for ( ; sst_num < kNumTrigger ; sst_num + + ) {
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( sst_num * ( kNumKeys - 1 ) + i ) , " value " ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ;
} ) ;
}
@ -1594,7 +1594,7 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
// pass some time first, otherwise the first a few keys write time are going
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ; } ) ;
Random rnd ( 301 ) ;
@ -1603,7 +1603,7 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
for ( ; sst_num < kNumTrigger ; sst_num + + ) {
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( sst_num * ( kNumKeys - 1 ) + i ) , rnd . RandomString ( 100 ) ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ;
} ) ;
}
@ -1696,7 +1696,7 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
for ( int i = 0 ; i < kNumKeys ; i + + ) {
// the value needs to be big enough to trigger full compaction
ASSERT_OK ( Put ( Key ( sst_num * ( kNumKeys - 1 ) + i ) , " value " ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kKeyPerSec ) ) ;
} ) ;
}
@ -1721,6 +1721,133 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
Close ( ) ;
}
TEST_P ( PrecludeLastLevelTestWithParms , PeriodicCompactionToPenultimateLevel ) {
// Test the last level only periodic compaction should also be blocked by an
// ongoing compaction in penultimate level if tiered compaction is enabled
// otherwise, the periodic compaction should just run for the last level.
const int kNumTrigger = 4 ;
const int kNumLevels = 7 ;
const int kPenultimateLevel = kNumLevels - 2 ;
const int kKeyPerSec = 1 ;
const int kNumKeys = 100 ;
bool enable_preclude_last_level = GetParam ( ) ;
Options options = CurrentOptions ( ) ;
options . compaction_style = kCompactionStyleUniversal ;
options . preserve_internal_time_seconds = 20000 ;
options . env = mock_env_ . get ( ) ;
options . level0_file_num_compaction_trigger = kNumTrigger ;
options . num_levels = kNumLevels ;
options . ignore_max_compaction_bytes_for_input = false ;
options . periodic_compaction_seconds = 10000 ;
DestroyAndReopen ( options ) ;
Random rnd ( 301 ) ;
for ( int i = 0 ; i < 3 * kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( i ) , rnd . RandomString ( 100 ) ) ) ;
dbfull ( ) - > TEST_WaitForPeriodicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( kKeyPerSec ) ; } ) ;
}
ASSERT_OK ( Flush ( ) ) ;
CompactRangeOptions cro ;
cro . bottommost_level_compaction = BottommostLevelCompaction : : kForce ;
ASSERT_OK ( db_ - > CompactRange ( cro , nullptr , nullptr ) ) ;
// make sure all data is compacted to the last level
ASSERT_EQ ( " 0,0,0,0,0,0,1 " , FilesPerLevel ( ) ) ;
// enable preclude feature
if ( enable_preclude_last_level ) {
options . preclude_last_level_data_seconds = 20000 ;
}
options . max_background_jobs = 8 ;
options . last_level_temperature = Temperature : : kCold ;
Reopen ( options ) ;
std : : atomic_bool is_size_ratio_compaction_running = false ;
std : : atomic_bool verified_last_level_compaction = false ;
SyncPoint : : GetInstance ( ) - > SetCallBack (
" CompactionJob::ProcessKeyValueCompaction()::Processing " , [ & ] ( void * arg ) {
auto compaction = static_cast < Compaction * > ( arg ) ;
if ( compaction - > output_level ( ) = = kPenultimateLevel ) {
is_size_ratio_compaction_running = true ;
TEST_SYNC_POINT (
" PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel: "
" SizeRatioCompaction1 " ) ;
TEST_SYNC_POINT (
" PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel: "
" SizeRatioCompaction2 " ) ;
is_size_ratio_compaction_running = false ;
}
} ) ;
SyncPoint : : GetInstance ( ) - > SetCallBack (
" UniversalCompactionBuilder::PickCompaction:Return " , [ & ] ( void * arg ) {
auto compaction = static_cast < Compaction * > ( arg ) ;
if ( is_size_ratio_compaction_running ) {
if ( enable_preclude_last_level ) {
ASSERT_TRUE ( compaction = = nullptr ) ;
} else {
ASSERT_TRUE ( compaction ! = nullptr ) ;
ASSERT_EQ ( compaction - > compaction_reason ( ) ,
CompactionReason : : kPeriodicCompaction ) ;
ASSERT_EQ ( compaction - > start_level ( ) , kNumLevels - 1 ) ;
}
verified_last_level_compaction = true ;
}
TEST_SYNC_POINT (
" PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel: "
" AutoCompactionPicked " ) ;
} ) ;
SyncPoint : : GetInstance ( ) - > LoadDependency ( {
{ " PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel: "
" SizeRatioCompaction1 " ,
" PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:DoneWrite " } ,
{ " PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel: "
" AutoCompactionPicked " ,
" PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel: "
" SizeRatioCompaction2 " } ,
} ) ;
auto stop_token =
dbfull ( ) - > TEST_write_controler ( ) . GetCompactionPressureToken ( ) ;
for ( int i = 0 ; i < kNumTrigger - 1 ; i + + ) {
for ( int j = 0 ; j < kNumKeys ; j + + ) {
ASSERT_OK ( Put ( Key ( i * ( kNumKeys - 1 ) + i ) , rnd . RandomString ( 10 ) ) ) ;
dbfull ( ) - > TEST_WaitForPeriodicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( kKeyPerSec ) ; } ) ;
}
ASSERT_OK ( Flush ( ) ) ;
}
TEST_SYNC_POINT (
" PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:DoneWrite " ) ;
// wait for periodic compaction time and flush to trigger the periodic
// compaction, which should be blocked by ongoing compaction in the
// penultimate level
mock_clock_ - > MockSleepForSeconds ( 10000 ) ;
for ( int i = 0 ; i < 3 * kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( i ) , rnd . RandomString ( 10 ) ) ) ;
dbfull ( ) - > TEST_WaitForPeriodicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( kKeyPerSec ) ; } ) ;
}
ASSERT_OK ( Flush ( ) ) ;
ASSERT_OK ( dbfull ( ) - > WaitForCompact ( true ) ) ;
stop_token . reset ( ) ;
Close ( ) ;
}
INSTANTIATE_TEST_CASE_P ( PrecludeLastLevelTestWithParms ,
PrecludeLastLevelTestWithParms , testing : : Bool ( ) ) ;
@ -1781,14 +1908,14 @@ TEST_F(PrecludeLastLevelTest, PartialPenultimateLevelCompaction) {
// pass some time first, otherwise the first a few keys write time are going
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( 10 ) ) ; } ) ;
Random rnd ( 301 ) ;
for ( int i = 0 ; i < 300 ; i + + ) {
ASSERT_OK ( Put ( Key ( i ) , rnd . RandomString ( 100 ) ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( kKeyPerSec ) ; } ) ;
}
ASSERT_OK ( Flush ( ) ) ;
@ -1892,7 +2019,7 @@ TEST_F(PrecludeLastLevelTest, RangeDelsCauseFileEndpointsToOverlap) {
// pass some time first, otherwise the first a few keys write time are going
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
dbfull ( ) - > TEST_WaitForPeridicTaskRun ( [ & ] {
dbfull ( ) - > TEST_WaitForPerio dicTaskRun ( [ & ] {
mock_clock_ - > MockSleepForSeconds ( static_cast < int > ( kSecondsPerKey ) ) ;
} ) ;
@ -1917,13 +2044,13 @@ TEST_F(PrecludeLastLevelTest, RangeDelsCauseFileEndpointsToOverlap) {
Random rnd ( 301 ) ;
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( i + 3 ) , rnd . RandomString ( kValueBytes ) ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( kSecondsPerKey ) ; } ) ;
}
auto * snap1 = db_ - > GetSnapshot ( ) ;
for ( int i = 0 ; i < kNumKeys ; i + + ) {
ASSERT_OK ( Put ( Key ( i ) , rnd . RandomString ( kValueBytes ) ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( kSecondsPerKey ) ; } ) ;
}
auto * snap2 = db_ - > GetSnapshot ( ) ;
@ -1937,7 +2064,7 @@ TEST_F(PrecludeLastLevelTest, RangeDelsCauseFileEndpointsToOverlap) {
Key ( 2 * kNumKeysPerFile - 1 ) ,
Key ( 2 * kNumKeysPerFile + 1 ) ) ) ;
ASSERT_OK ( Flush ( ) ) ;
dbfull ( ) - > TEST_WaitForPeridicTaskRun (
dbfull ( ) - > TEST_WaitForPerio dicTaskRun (
[ & ] { mock_clock_ - > MockSleepForSeconds ( kSecondsPerKey ) ; } ) ;
verify_db ( ) ;