Trigger non-trivial compaction in fault_injection_test
Summary: Now the major test cases of fault_injection_test only insert keys in sorted order so compactions will be trivial move. Add a new mode to insert in non-sequential order to trigger non-trivial compactions. Test Plan: Run the test Reviewers: kradhakrishnan, anthony, IslamAbdelRahman, yhchiang, igor Reviewed By: igor Subscribers: leveldb, dhruba Differential Revision: https://reviews.facebook.net/D42435
This commit is contained in:
parent
59eca2cc99
commit
58b4209e05
@ -424,7 +424,8 @@ Status TestWritableFile::Sync() {
|
|||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
class FaultInjectionTest : public testing::Test {
|
class FaultInjectionTest : public testing::Test,
|
||||||
|
public testing::WithParamInterface<bool> {
|
||||||
protected:
|
protected:
|
||||||
enum OptionConfig {
|
enum OptionConfig {
|
||||||
kDefault,
|
kDefault,
|
||||||
@ -441,6 +442,8 @@ class FaultInjectionTest : public testing::Test {
|
|||||||
// When need to make sure data is persistent, call DB::CompactRange()
|
// When need to make sure data is persistent, call DB::CompactRange()
|
||||||
bool sync_use_compact_;
|
bool sync_use_compact_;
|
||||||
|
|
||||||
|
bool sequential_order_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
public:
|
public:
|
||||||
enum ExpectedVerifResult { kValExpectFound, kValExpectNoError };
|
enum ExpectedVerifResult { kValExpectFound, kValExpectNoError };
|
||||||
@ -467,6 +470,11 @@ class FaultInjectionTest : public testing::Test {
|
|||||||
db_(NULL) {
|
db_(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~FaultInjectionTest() {
|
||||||
|
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||||
|
rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||||
|
}
|
||||||
|
|
||||||
bool ChangeOptions() {
|
bool ChangeOptions() {
|
||||||
option_config_++;
|
option_config_++;
|
||||||
if (option_config_ >= kEnd) {
|
if (option_config_ >= kEnd) {
|
||||||
@ -547,7 +555,10 @@ class FaultInjectionTest : public testing::Test {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUp() override { ASSERT_OK(NewDB()); }
|
void SetUp() override {
|
||||||
|
sequential_order_ = GetParam();
|
||||||
|
ASSERT_OK(NewDB());
|
||||||
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
void TearDown() override {
|
||||||
CloseDB();
|
CloseDB();
|
||||||
@ -562,34 +573,33 @@ class FaultInjectionTest : public testing::Test {
|
|||||||
ASSERT_OK(s);
|
ASSERT_OK(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Build(const WriteOptions& write_options, int start_idx, int num_vals,
|
void Build(const WriteOptions& write_options, int start_idx, int num_vals) {
|
||||||
bool sequential = true) {
|
|
||||||
std::string key_space, value_space;
|
std::string key_space, value_space;
|
||||||
WriteBatch batch;
|
WriteBatch batch;
|
||||||
for (int i = start_idx; i < start_idx + num_vals; i++) {
|
for (int i = start_idx; i < start_idx + num_vals; i++) {
|
||||||
Slice key = Key(sequential, i, &key_space);
|
Slice key = Key(i, &key_space);
|
||||||
batch.Clear();
|
batch.Clear();
|
||||||
batch.Put(key, Value(i, &value_space));
|
batch.Put(key, Value(i, &value_space));
|
||||||
ASSERT_OK(db_->Write(write_options, &batch));
|
ASSERT_OK(db_->Write(write_options, &batch));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status ReadValue(int i, std::string* val, bool sequential) const {
|
Status ReadValue(int i, std::string* val) const {
|
||||||
std::string key_space, value_space;
|
std::string key_space, value_space;
|
||||||
Slice key = Key(sequential, i, &key_space);
|
Slice key = Key(i, &key_space);
|
||||||
Value(i, &value_space);
|
Value(i, &value_space);
|
||||||
ReadOptions options;
|
ReadOptions options;
|
||||||
return db_->Get(options, key, val);
|
return db_->Get(options, key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status Verify(int start_idx, int num_vals, ExpectedVerifResult expected,
|
Status Verify(int start_idx, int num_vals,
|
||||||
bool sequential = true) const {
|
ExpectedVerifResult expected) const {
|
||||||
std::string val;
|
std::string val;
|
||||||
std::string value_space;
|
std::string value_space;
|
||||||
Status s;
|
Status s;
|
||||||
for (int i = start_idx; i < start_idx + num_vals && s.ok(); i++) {
|
for (int i = start_idx; i < start_idx + num_vals && s.ok(); i++) {
|
||||||
Value(i, &value_space);
|
Value(i, &value_space);
|
||||||
s = ReadValue(i, &val, sequential);
|
s = ReadValue(i, &val);
|
||||||
if (s.ok()) {
|
if (s.ok()) {
|
||||||
EXPECT_EQ(value_space, val);
|
EXPECT_EQ(value_space, val);
|
||||||
}
|
}
|
||||||
@ -609,9 +619,9 @@ class FaultInjectionTest : public testing::Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the ith key
|
// Return the ith key
|
||||||
Slice Key(bool sequential, int i, std::string* storage) const {
|
Slice Key(int i, std::string* storage) const {
|
||||||
int num = i;
|
int num = i;
|
||||||
if (!sequential) {
|
if (!sequential_order_) {
|
||||||
// random transfer
|
// random transfer
|
||||||
const int m = 0x5bd1e995;
|
const int m = 0x5bd1e995;
|
||||||
num *= m;
|
num *= m;
|
||||||
@ -701,6 +711,10 @@ class FaultInjectionTest : public testing::Test {
|
|||||||
ASSERT_OK(Verify(0, num_pre_sync, FaultInjectionTest::kValExpectFound));
|
ASSERT_OK(Verify(0, num_pre_sync, FaultInjectionTest::kValExpectFound));
|
||||||
ASSERT_OK(Verify(num_pre_sync, num_post_sync,
|
ASSERT_OK(Verify(num_pre_sync, num_post_sync,
|
||||||
FaultInjectionTest::kValExpectNoError));
|
FaultInjectionTest::kValExpectNoError));
|
||||||
|
WaitCompactionFinish();
|
||||||
|
ASSERT_OK(Verify(0, num_pre_sync, FaultInjectionTest::kValExpectFound));
|
||||||
|
ASSERT_OK(Verify(num_pre_sync, num_post_sync,
|
||||||
|
FaultInjectionTest::kValExpectNoError));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoWriteTestPreFault() {
|
void NoWriteTestPreFault() {
|
||||||
@ -711,9 +725,14 @@ class FaultInjectionTest : public testing::Test {
|
|||||||
ResetDBState(reset_method);
|
ResetDBState(reset_method);
|
||||||
ASSERT_OK(OpenDB());
|
ASSERT_OK(OpenDB());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaitCompactionFinish() {
|
||||||
|
static_cast<DBImpl*>(db_)->TEST_WaitForCompact();
|
||||||
|
ASSERT_OK(db_->Put(WriteOptions(), "", ""));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(FaultInjectionTest, FaultTest) {
|
TEST_P(FaultInjectionTest, FaultTest) {
|
||||||
do {
|
do {
|
||||||
Random rnd(301);
|
Random rnd(301);
|
||||||
|
|
||||||
@ -787,7 +806,7 @@ class SleepingBackgroundTask {
|
|||||||
// Disable the test because it is not passing.
|
// Disable the test because it is not passing.
|
||||||
// Previous log file is not fsynced if sync is forced after log rolling.
|
// Previous log file is not fsynced if sync is forced after log rolling.
|
||||||
// TODO(FB internal task#6730880) Fix the bug
|
// TODO(FB internal task#6730880) Fix the bug
|
||||||
TEST_F(FaultInjectionTest, DISABLED_WriteOptionSyncTest) {
|
TEST_P(FaultInjectionTest, DISABLED_WriteOptionSyncTest) {
|
||||||
SleepingBackgroundTask sleeping_task_low;
|
SleepingBackgroundTask sleeping_task_low;
|
||||||
env_->SetBackgroundThreads(1, Env::HIGH);
|
env_->SetBackgroundThreads(1, Env::HIGH);
|
||||||
// Block the job queue to prevent flush job from running.
|
// Block the job queue to prevent flush job from running.
|
||||||
@ -798,14 +817,14 @@ TEST_F(FaultInjectionTest, DISABLED_WriteOptionSyncTest) {
|
|||||||
write_options.sync = false;
|
write_options.sync = false;
|
||||||
|
|
||||||
std::string key_space, value_space;
|
std::string key_space, value_space;
|
||||||
ASSERT_OK(db_->Put(write_options, Key(true, 1, &key_space),
|
ASSERT_OK(
|
||||||
Value(1, &value_space)));
|
db_->Put(write_options, Key(1, &key_space), Value(1, &value_space)));
|
||||||
FlushOptions flush_options;
|
FlushOptions flush_options;
|
||||||
flush_options.wait = false;
|
flush_options.wait = false;
|
||||||
ASSERT_OK(db_->Flush(flush_options));
|
ASSERT_OK(db_->Flush(flush_options));
|
||||||
write_options.sync = true;
|
write_options.sync = true;
|
||||||
ASSERT_OK(db_->Put(write_options, Key(true, 2, &key_space),
|
ASSERT_OK(
|
||||||
Value(2, &value_space)));
|
db_->Put(write_options, Key(2, &key_space), Value(2, &value_space)));
|
||||||
|
|
||||||
env_->SetFilesystemActive(false);
|
env_->SetFilesystemActive(false);
|
||||||
NoWriteTestReopenWithFault(kResetDropAndDeleteUnsynced);
|
NoWriteTestReopenWithFault(kResetDropAndDeleteUnsynced);
|
||||||
@ -814,15 +833,15 @@ TEST_F(FaultInjectionTest, DISABLED_WriteOptionSyncTest) {
|
|||||||
ASSERT_OK(OpenDB());
|
ASSERT_OK(OpenDB());
|
||||||
std::string val;
|
std::string val;
|
||||||
Value(2, &value_space);
|
Value(2, &value_space);
|
||||||
ASSERT_OK(ReadValue(2, &val, true));
|
ASSERT_OK(ReadValue(2, &val));
|
||||||
ASSERT_EQ(value_space, val);
|
ASSERT_EQ(value_space, val);
|
||||||
|
|
||||||
Value(1, &value_space);
|
Value(1, &value_space);
|
||||||
ASSERT_OK(ReadValue(1, &val, true));
|
ASSERT_OK(ReadValue(1, &val));
|
||||||
ASSERT_EQ(value_space, val);
|
ASSERT_EQ(value_space, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FaultInjectionTest, UninstalledCompaction) {
|
TEST_P(FaultInjectionTest, UninstalledCompaction) {
|
||||||
options_.target_file_size_base = 32 * 1024;
|
options_.target_file_size_base = 32 * 1024;
|
||||||
options_.write_buffer_size = 100 << 10; // 100KB
|
options_.write_buffer_size = 100 << 10; // 100KB
|
||||||
options_.level0_file_num_compaction_trigger = 6;
|
options_.level0_file_num_compaction_trigger = 6;
|
||||||
@ -831,16 +850,18 @@ TEST_F(FaultInjectionTest, UninstalledCompaction) {
|
|||||||
options_.max_background_compactions = 1;
|
options_.max_background_compactions = 1;
|
||||||
OpenDB();
|
OpenDB();
|
||||||
|
|
||||||
|
if (!sequential_order_) {
|
||||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||||
{"FaultInjectionTest::FaultTest:0", "DBImpl::BGWorkCompaction"},
|
{"FaultInjectionTest::FaultTest:0", "DBImpl::BGWorkCompaction"},
|
||||||
{"CompactionJob::Run():End", "FaultInjectionTest::FaultTest:1"},
|
{"CompactionJob::Run():End", "FaultInjectionTest::FaultTest:1"},
|
||||||
{"FaultInjectionTest::FaultTest:2",
|
{"FaultInjectionTest::FaultTest:2",
|
||||||
"DBImpl::BackgroundCompaction:NonTrivial:AfterRun"},
|
"DBImpl::BackgroundCompaction:NonTrivial:AfterRun"},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||||
|
|
||||||
int kNumKeys = 1000;
|
int kNumKeys = 1000;
|
||||||
Build(WriteOptions(), 0, kNumKeys, false);
|
Build(WriteOptions(), 0, kNumKeys);
|
||||||
FlushOptions flush_options;
|
FlushOptions flush_options;
|
||||||
flush_options.wait = true;
|
flush_options.wait = true;
|
||||||
db_->Flush(flush_options);
|
db_->Flush(flush_options);
|
||||||
@ -861,12 +882,15 @@ TEST_F(FaultInjectionTest, UninstalledCompaction) {
|
|||||||
[&](void* arg) { ASSERT_TRUE(opened.load()); });
|
[&](void* arg) { ASSERT_TRUE(opened.load()); });
|
||||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||||
ASSERT_OK(OpenDB());
|
ASSERT_OK(OpenDB());
|
||||||
static_cast<DBImpl*>(db_)->TEST_WaitForCompact();
|
ASSERT_OK(Verify(0, kNumKeys, FaultInjectionTest::kValExpectFound));
|
||||||
ASSERT_OK(Verify(0, kNumKeys, FaultInjectionTest::kValExpectFound, false));
|
WaitCompactionFinish();
|
||||||
ASSERT_OK(db_->Put(WriteOptions(), "", ""));
|
ASSERT_OK(Verify(0, kNumKeys, FaultInjectionTest::kValExpectFound));
|
||||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||||
|
rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(FaultTest, FaultInjectionTest, ::testing::Bool());
|
||||||
|
|
||||||
} // namespace rocksdb
|
} // namespace rocksdb
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
Loading…
Reference in New Issue
Block a user