Skip to content

Commit 1078d86

Browse files
jay-zhuangfacebook-github-bot
authored andcommitted
Add an unittest for Periodic compaction conflict with ongoing compaction (#10908)
Summary: Add a tiered storage migration test which would conflict with an ongoing penultimate level compaction. Pull Request resolved: #10908 Test Plan: Test only change Reviewed By: anand1976 Differential Revision: D40864509 Pulled By: ajkr fbshipit-source-id: e316e849a01a6c71a41be130101f909b6c0498cb
1 parent 4d60cbc commit 1078d86

File tree

6 files changed

+211
-84
lines changed

6 files changed

+211
-84
lines changed

db/compaction/tiered_compaction_test.cc

Lines changed: 147 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,15 +1251,15 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeManualCompaction) {
12511251

12521252
// pass some time first, otherwise the first a few keys write time are going
12531253
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
1254-
dbfull()->TEST_WaitForPeridicTaskRun(
1254+
dbfull()->TEST_WaitForPeriodicTaskRun(
12551255
[&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec)); });
12561256

12571257
int sst_num = 0;
12581258
// Write files that are overlap and enough to trigger compaction
12591259
for (; sst_num < kNumTrigger; sst_num++) {
12601260
for (int i = 0; i < kNumKeys; i++) {
12611261
ASSERT_OK(Put(Key(sst_num * (kNumKeys - 1) + i), "value"));
1262-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1262+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
12631263
mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec));
12641264
});
12651265
}
@@ -1313,15 +1313,15 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeAutoCompaction) {
13131313

13141314
// pass some time first, otherwise the first a few keys write time are going
13151315
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
1316-
dbfull()->TEST_WaitForPeridicTaskRun(
1316+
dbfull()->TEST_WaitForPeriodicTaskRun(
13171317
[&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec)); });
13181318

13191319
int sst_num = 0;
13201320
// Write files that are overlap and enough to trigger compaction
13211321
for (; sst_num < kNumTrigger; sst_num++) {
13221322
for (int i = 0; i < kNumKeys; i++) {
13231323
ASSERT_OK(Put(Key(sst_num * (kNumKeys - 1) + i), "value"));
1324-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1324+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
13251325
mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec));
13261326
});
13271327
}
@@ -1355,7 +1355,7 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimeAutoCompaction) {
13551355
for (int i = 0; i < kNumKeys; i++) {
13561356
// the value needs to be big enough to trigger full compaction
13571357
ASSERT_OK(Put(Key(sst_num * (kNumKeys - 1) + i), rnd.RandomString(100)));
1358-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1358+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
13591359
mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec));
13601360
});
13611361
}
@@ -1389,15 +1389,15 @@ TEST_F(PrecludeLastLevelTest, MigrationFromPreserveTimePartial) {
13891389

13901390
// pass some time first, otherwise the first a few keys write time are going
13911391
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
1392-
dbfull()->TEST_WaitForPeridicTaskRun(
1392+
dbfull()->TEST_WaitForPeriodicTaskRun(
13931393
[&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec)); });
13941394

13951395
int sst_num = 0;
13961396
// Write files that are overlap and enough to trigger compaction
13971397
for (; sst_num < kNumTrigger; sst_num++) {
13981398
for (int i = 0; i < kNumKeys; i++) {
13991399
ASSERT_OK(Put(Key(sst_num * (kNumKeys - 1) + i), "value"));
1400-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1400+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
14011401
mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec));
14021402
});
14031403
}
@@ -1463,13 +1463,13 @@ TEST_F(PrecludeLastLevelTest, SmallPrecludeTime) {
14631463

14641464
Random rnd(301);
14651465

1466-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1466+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
14671467
mock_clock_->MockSleepForSeconds(static_cast<int>(rnd.Uniform(10) + 1));
14681468
});
14691469

14701470
for (int i = 0; i < kNumKeys; i++) {
14711471
ASSERT_OK(Put(Key(i), rnd.RandomString(100)));
1472-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1472+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
14731473
mock_clock_->MockSleepForSeconds(static_cast<int>(rnd.Uniform(2)));
14741474
});
14751475
}
@@ -1516,15 +1516,15 @@ TEST_F(PrecludeLastLevelTest, LastLevelOnlyCompactionPartial) {
15161516

15171517
// pass some time first, otherwise the first a few keys write time are going
15181518
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
1519-
dbfull()->TEST_WaitForPeridicTaskRun(
1519+
dbfull()->TEST_WaitForPeriodicTaskRun(
15201520
[&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec)); });
15211521

15221522
int sst_num = 0;
15231523
// Write files that are overlap and enough to trigger compaction
15241524
for (; sst_num < kNumTrigger; sst_num++) {
15251525
for (int i = 0; i < kNumKeys; i++) {
15261526
ASSERT_OK(Put(Key(sst_num * (kNumKeys - 1) + i), "value"));
1527-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1527+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
15281528
mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec));
15291529
});
15301530
}
@@ -1594,7 +1594,7 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
15941594

15951595
// pass some time first, otherwise the first a few keys write time are going
15961596
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
1597-
dbfull()->TEST_WaitForPeridicTaskRun(
1597+
dbfull()->TEST_WaitForPeriodicTaskRun(
15981598
[&] { mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec)); });
15991599

16001600
Random rnd(301);
@@ -1603,7 +1603,7 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
16031603
for (; sst_num < kNumTrigger; sst_num++) {
16041604
for (int i = 0; i < kNumKeys; i++) {
16051605
ASSERT_OK(Put(Key(sst_num * (kNumKeys - 1) + i), rnd.RandomString(100)));
1606-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1606+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
16071607
mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec));
16081608
});
16091609
}
@@ -1696,7 +1696,7 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
16961696
for (int i = 0; i < kNumKeys; i++) {
16971697
// the value needs to be big enough to trigger full compaction
16981698
ASSERT_OK(Put(Key(sst_num * (kNumKeys - 1) + i), "value"));
1699-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
1699+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
17001700
mock_clock_->MockSleepForSeconds(static_cast<int>(kKeyPerSec));
17011701
});
17021702
}
@@ -1721,6 +1721,133 @@ TEST_P(PrecludeLastLevelTestWithParms, LastLevelOnlyCompactionNoPreclude) {
17211721
Close();
17221722
}
17231723

1724+
TEST_P(PrecludeLastLevelTestWithParms, PeriodicCompactionToPenultimateLevel) {
1725+
// Test the last level only periodic compaction should also be blocked by an
1726+
// ongoing compaction in penultimate level if tiered compaction is enabled
1727+
// otherwise, the periodic compaction should just run for the last level.
1728+
const int kNumTrigger = 4;
1729+
const int kNumLevels = 7;
1730+
const int kPenultimateLevel = kNumLevels - 2;
1731+
const int kKeyPerSec = 1;
1732+
const int kNumKeys = 100;
1733+
1734+
bool enable_preclude_last_level = GetParam();
1735+
1736+
Options options = CurrentOptions();
1737+
options.compaction_style = kCompactionStyleUniversal;
1738+
options.preserve_internal_time_seconds = 20000;
1739+
options.env = mock_env_.get();
1740+
options.level0_file_num_compaction_trigger = kNumTrigger;
1741+
options.num_levels = kNumLevels;
1742+
options.ignore_max_compaction_bytes_for_input = false;
1743+
options.periodic_compaction_seconds = 10000;
1744+
DestroyAndReopen(options);
1745+
1746+
Random rnd(301);
1747+
1748+
for (int i = 0; i < 3 * kNumKeys; i++) {
1749+
ASSERT_OK(Put(Key(i), rnd.RandomString(100)));
1750+
dbfull()->TEST_WaitForPeriodicTaskRun(
1751+
[&] { mock_clock_->MockSleepForSeconds(kKeyPerSec); });
1752+
}
1753+
ASSERT_OK(Flush());
1754+
CompactRangeOptions cro;
1755+
cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
1756+
1757+
ASSERT_OK(db_->CompactRange(cro, nullptr, nullptr));
1758+
1759+
// make sure all data is compacted to the last level
1760+
ASSERT_EQ("0,0,0,0,0,0,1", FilesPerLevel());
1761+
1762+
// enable preclude feature
1763+
if (enable_preclude_last_level) {
1764+
options.preclude_last_level_data_seconds = 20000;
1765+
}
1766+
options.max_background_jobs = 8;
1767+
options.last_level_temperature = Temperature::kCold;
1768+
Reopen(options);
1769+
1770+
std::atomic_bool is_size_ratio_compaction_running = false;
1771+
std::atomic_bool verified_last_level_compaction = false;
1772+
1773+
SyncPoint::GetInstance()->SetCallBack(
1774+
"CompactionJob::ProcessKeyValueCompaction()::Processing", [&](void* arg) {
1775+
auto compaction = static_cast<Compaction*>(arg);
1776+
if (compaction->output_level() == kPenultimateLevel) {
1777+
is_size_ratio_compaction_running = true;
1778+
TEST_SYNC_POINT(
1779+
"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:"
1780+
"SizeRatioCompaction1");
1781+
TEST_SYNC_POINT(
1782+
"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:"
1783+
"SizeRatioCompaction2");
1784+
is_size_ratio_compaction_running = false;
1785+
}
1786+
});
1787+
1788+
SyncPoint::GetInstance()->SetCallBack(
1789+
"UniversalCompactionBuilder::PickCompaction:Return", [&](void* arg) {
1790+
auto compaction = static_cast<Compaction*>(arg);
1791+
1792+
if (is_size_ratio_compaction_running) {
1793+
if (enable_preclude_last_level) {
1794+
ASSERT_TRUE(compaction == nullptr);
1795+
} else {
1796+
ASSERT_TRUE(compaction != nullptr);
1797+
ASSERT_EQ(compaction->compaction_reason(),
1798+
CompactionReason::kPeriodicCompaction);
1799+
ASSERT_EQ(compaction->start_level(), kNumLevels - 1);
1800+
}
1801+
verified_last_level_compaction = true;
1802+
}
1803+
TEST_SYNC_POINT(
1804+
"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:"
1805+
"AutoCompactionPicked");
1806+
});
1807+
1808+
SyncPoint::GetInstance()->LoadDependency({
1809+
{"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:"
1810+
"SizeRatioCompaction1",
1811+
"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:DoneWrite"},
1812+
{"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:"
1813+
"AutoCompactionPicked",
1814+
"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:"
1815+
"SizeRatioCompaction2"},
1816+
});
1817+
1818+
auto stop_token =
1819+
dbfull()->TEST_write_controler().GetCompactionPressureToken();
1820+
1821+
for (int i = 0; i < kNumTrigger - 1; i++) {
1822+
for (int j = 0; j < kNumKeys; j++) {
1823+
ASSERT_OK(Put(Key(i * (kNumKeys - 1) + i), rnd.RandomString(10)));
1824+
dbfull()->TEST_WaitForPeriodicTaskRun(
1825+
[&] { mock_clock_->MockSleepForSeconds(kKeyPerSec); });
1826+
}
1827+
ASSERT_OK(Flush());
1828+
}
1829+
1830+
TEST_SYNC_POINT(
1831+
"PrecludeLastLevelTest::PeriodicCompactionToPenultimateLevel:DoneWrite");
1832+
1833+
// wait for periodic compaction time and flush to trigger the periodic
1834+
// compaction, which should be blocked by ongoing compaction in the
1835+
// penultimate level
1836+
mock_clock_->MockSleepForSeconds(10000);
1837+
for (int i = 0; i < 3 * kNumKeys; i++) {
1838+
ASSERT_OK(Put(Key(i), rnd.RandomString(10)));
1839+
dbfull()->TEST_WaitForPeriodicTaskRun(
1840+
[&] { mock_clock_->MockSleepForSeconds(kKeyPerSec); });
1841+
}
1842+
ASSERT_OK(Flush());
1843+
1844+
ASSERT_OK(dbfull()->WaitForCompact(true));
1845+
1846+
stop_token.reset();
1847+
1848+
Close();
1849+
}
1850+
17241851
INSTANTIATE_TEST_CASE_P(PrecludeLastLevelTestWithParms,
17251852
PrecludeLastLevelTestWithParms, testing::Bool());
17261853

@@ -1781,14 +1908,14 @@ TEST_F(PrecludeLastLevelTest, PartialPenultimateLevelCompaction) {
17811908

17821909
// pass some time first, otherwise the first a few keys write time are going
17831910
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
1784-
dbfull()->TEST_WaitForPeridicTaskRun(
1911+
dbfull()->TEST_WaitForPeriodicTaskRun(
17851912
[&] { mock_clock_->MockSleepForSeconds(static_cast<int>(10)); });
17861913

17871914
Random rnd(301);
17881915

17891916
for (int i = 0; i < 300; i++) {
17901917
ASSERT_OK(Put(Key(i), rnd.RandomString(100)));
1791-
dbfull()->TEST_WaitForPeridicTaskRun(
1918+
dbfull()->TEST_WaitForPeriodicTaskRun(
17921919
[&] { mock_clock_->MockSleepForSeconds(kKeyPerSec); });
17931920
}
17941921
ASSERT_OK(Flush());
@@ -1892,7 +2019,7 @@ TEST_F(PrecludeLastLevelTest, RangeDelsCauseFileEndpointsToOverlap) {
18922019

18932020
// pass some time first, otherwise the first a few keys write time are going
18942021
// to be zero, and internally zero has special meaning: kUnknownSeqnoTime
1895-
dbfull()->TEST_WaitForPeridicTaskRun([&] {
2022+
dbfull()->TEST_WaitForPeriodicTaskRun([&] {
18962023
mock_clock_->MockSleepForSeconds(static_cast<int>(kSecondsPerKey));
18972024
});
18982025

@@ -1917,13 +2044,13 @@ TEST_F(PrecludeLastLevelTest, RangeDelsCauseFileEndpointsToOverlap) {
19172044
Random rnd(301);
19182045
for (int i = 0; i < kNumKeys; i++) {
19192046
ASSERT_OK(Put(Key(i + 3), rnd.RandomString(kValueBytes)));
1920-
dbfull()->TEST_WaitForPeridicTaskRun(
2047+
dbfull()->TEST_WaitForPeriodicTaskRun(
19212048
[&] { mock_clock_->MockSleepForSeconds(kSecondsPerKey); });
19222049
}
19232050
auto* snap1 = db_->GetSnapshot();
19242051
for (int i = 0; i < kNumKeys; i++) {
19252052
ASSERT_OK(Put(Key(i), rnd.RandomString(kValueBytes)));
1926-
dbfull()->TEST_WaitForPeridicTaskRun(
2053+
dbfull()->TEST_WaitForPeriodicTaskRun(
19272054
[&] { mock_clock_->MockSleepForSeconds(kSecondsPerKey); });
19282055
}
19292056
auto* snap2 = db_->GetSnapshot();
@@ -1937,7 +2064,7 @@ TEST_F(PrecludeLastLevelTest, RangeDelsCauseFileEndpointsToOverlap) {
19372064
Key(2 * kNumKeysPerFile - 1),
19382065
Key(2 * kNumKeysPerFile + 1)));
19392066
ASSERT_OK(Flush());
1940-
dbfull()->TEST_WaitForPeridicTaskRun(
2067+
dbfull()->TEST_WaitForPeriodicTaskRun(
19412068
[&] { mock_clock_->MockSleepForSeconds(kSecondsPerKey); });
19422069
verify_db();
19432070

db/db_impl/db_impl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,7 @@ class DBImpl : public DB {
11611161
int TEST_BGCompactionsAllowed() const;
11621162
int TEST_BGFlushesAllowed() const;
11631163
size_t TEST_GetWalPreallocateBlockSize(uint64_t write_buffer_size) const;
1164-
void TEST_WaitForPeridicTaskRun(std::function<void()> callback) const;
1164+
void TEST_WaitForPeriodicTaskRun(std::function<void()> callback) const;
11651165
SeqnoToTimeMapping TEST_GetSeqnoToTimeMapping() const;
11661166
size_t TEST_EstimateInMemoryStatsHistorySize() const;
11671167

db/db_impl/db_impl_debug.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ size_t DBImpl::TEST_GetWalPreallocateBlockSize(
290290
}
291291

292292
#ifndef ROCKSDB_LITE
293-
void DBImpl::TEST_WaitForPeridicTaskRun(std::function<void()> callback) const {
293+
void DBImpl::TEST_WaitForPeriodicTaskRun(std::function<void()> callback) const {
294294
periodic_task_scheduler_.TEST_WaitForRun(callback);
295295
}
296296

0 commit comments

Comments
 (0)