|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
|
|
// This source code is licensed under the BSD-style license found in the
|
|
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
//
|
|
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
|
|
#include "db/db_test_util.h"
|
|
|
|
#include "port/stack_trace.h"
|
|
|
|
#include "util/sync_point.h"
|
|
|
|
|
|
|
|
namespace rocksdb {
|
|
|
|
|
|
|
|
class DBOptionsTest : public DBTestBase {
|
|
|
|
public:
|
|
|
|
DBOptionsTest() : DBTestBase("/db_options_test") {}
|
|
|
|
};
|
|
|
|
|
|
|
|
// RocksDB lite don't support dynamic options.
|
|
|
|
#ifndef ROCKSDB_LITE
|
|
|
|
|
|
|
|
// When write stalls, user can enable auto compaction to unblock writes.
|
|
|
|
// However, we had an issue where the stalled write thread blocks the attempt
|
|
|
|
// to persist auto compaction option, thus creating a deadlock. The test
|
|
|
|
// verifies the issue is fixed.
|
|
|
|
TEST_F(DBOptionsTest, EnableAutoCompactionToUnblockWrites) {
|
|
|
|
Options options;
|
|
|
|
options.disable_auto_compactions = true;
|
|
|
|
options.write_buffer_size = 1000 * 1000; // 1M
|
|
|
|
options.level0_file_num_compaction_trigger = 1;
|
|
|
|
options.level0_slowdown_writes_trigger = 1;
|
|
|
|
options.level0_stop_writes_trigger = 1;
|
|
|
|
options.compression = kNoCompression;
|
|
|
|
|
|
|
|
SyncPoint::GetInstance()->LoadDependency(
|
|
|
|
{{"DBImpl::DelayWrite:Wait",
|
|
|
|
"DBOptionsTest::EnableAutoCompactionToUnblockWrites:1"},
|
|
|
|
{"DBImpl::BackgroundCompaction:Finish",
|
|
|
|
"DBOptionsTest::EnableAutoCompactionToUnblockWrites:1"}});
|
|
|
|
SyncPoint::GetInstance()->EnableProcessing();
|
|
|
|
|
|
|
|
// Stall writes.
|
|
|
|
Reopen(options);
|
|
|
|
env_->StartThread(
|
|
|
|
[](void* arg) {
|
|
|
|
std::string value(1000, 'v');
|
|
|
|
auto* t = static_cast<DBOptionsTest*>(arg);
|
|
|
|
for (int i = 0; i < 2000; i++) {
|
|
|
|
ASSERT_OK(t->Put(t->Key(i), value));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
this);
|
|
|
|
TEST_SYNC_POINT("DBOptionsTest::EnableAutoCompactionToUnblockWrites:1");
|
|
|
|
ASSERT_TRUE(dbfull()->TEST_write_controler().IsStopped());
|
|
|
|
ColumnFamilyHandle* handle = dbfull()->DefaultColumnFamily();
|
|
|
|
// We will get a deadlock here if we hit the issue.
|
|
|
|
ASSERT_OK(dbfull()->EnableAutoCompaction({handle}));
|
|
|
|
env_->WaitForJoin();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Similar to EnableAutoCompactionAfterStallDeadlock. See comments there.
|
|
|
|
TEST_F(DBOptionsTest, ToggleStopTriggerToUnblockWrites) {
|
|
|
|
Options options;
|
|
|
|
options.disable_auto_compactions = true;
|
|
|
|
options.write_buffer_size = 1000 * 1000; // 1M
|
|
|
|
options.level0_file_num_compaction_trigger = 1;
|
|
|
|
options.level0_slowdown_writes_trigger = 1;
|
|
|
|
options.level0_stop_writes_trigger = 1;
|
|
|
|
options.compression = kNoCompression;
|
|
|
|
|
|
|
|
SyncPoint::GetInstance()->LoadDependency(
|
|
|
|
{{"DBImpl::DelayWrite:Wait",
|
|
|
|
"DBOptionsTest::ToggleStopTriggerToUnblockWrites:1"},
|
|
|
|
{"DBImpl::BackgroundCompaction:Finish",
|
|
|
|
"DBOptionsTest::ToggleStopTriggerToUnblockWrites:1"}});
|
|
|
|
SyncPoint::GetInstance()->EnableProcessing();
|
|
|
|
|
|
|
|
// Stall writes.
|
|
|
|
Reopen(options);
|
|
|
|
env_->StartThread(
|
|
|
|
[](void* arg) {
|
|
|
|
std::string value(1000, 'v');
|
|
|
|
auto* t = static_cast<DBOptionsTest*>(arg);
|
|
|
|
for (int i = 0; i < 2000; i++) {
|
|
|
|
ASSERT_OK(t->Put(t->Key(i), value));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
this);
|
|
|
|
TEST_SYNC_POINT("DBOptionsTest::ToggleStopTriggerToUnblockWrites:1");
|
|
|
|
ASSERT_TRUE(dbfull()->TEST_write_controler().IsStopped());
|
|
|
|
// We will get a deadlock here if we hit the issue.
|
|
|
|
ASSERT_OK(
|
|
|
|
dbfull()->SetOptions({{"level0_stop_writes_trigger", "1000000"},
|
|
|
|
{"level0_slowdown_writes_trigger", "1000000"}}));
|
|
|
|
env_->WaitForJoin();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // ROCKSDB_LITE
|
|
|
|
|
|
|
|
} // namespace rocksdb
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
rocksdb::port::InstallStackTraceHandler();
|
|
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
return RUN_ALL_TESTS();
|
|
|
|
}
|