提交 ac0e54b4 编写于 作者: S sdong

CompactedDB should not be used if there is outstanding WAL files

Summary: CompactedDB skips memtable. So we shouldn't use compacted DB if there is outstanding WAL files.

Test Plan: Change to options.max_open_files = -1 perf context test to create a compacted DB, which we shouldn't do.

Reviewers: yhchiang, kradhakrishnan, IslamAbdelRahman

Reviewed By: IslamAbdelRahman

Subscribers: leveldb, andrewkr, dhruba

Differential Revision: https://reviews.facebook.net/D57057
上级 d719b095
...@@ -93,7 +93,7 @@ Status CompactedDBImpl::Init(const Options& options) { ...@@ -93,7 +93,7 @@ Status CompactedDBImpl::Init(const Options& options) {
mutex_.Lock(); mutex_.Lock();
ColumnFamilyDescriptor cf(kDefaultColumnFamilyName, ColumnFamilyDescriptor cf(kDefaultColumnFamilyName,
ColumnFamilyOptions(options)); ColumnFamilyOptions(options));
Status s = Recover({ cf }, true /* read only */, false); Status s = Recover({cf}, true /* read only */, false, true);
if (s.ok()) { if (s.ok()) {
cfd_ = reinterpret_cast<ColumnFamilyHandleImpl*>( cfd_ = reinterpret_cast<ColumnFamilyHandleImpl*>(
DefaultColumnFamily())->cfd(); DefaultColumnFamily())->cfd();
......
...@@ -988,7 +988,7 @@ Directory* DBImpl::Directories::GetDataDir(size_t path_id) { ...@@ -988,7 +988,7 @@ Directory* DBImpl::Directories::GetDataDir(size_t path_id) {
Status DBImpl::Recover( Status DBImpl::Recover(
const std::vector<ColumnFamilyDescriptor>& column_families, bool read_only, const std::vector<ColumnFamilyDescriptor>& column_families, bool read_only,
bool error_if_log_file_exist) { bool error_if_log_file_exist, bool error_if_data_exists_in_logs) {
mutex_.AssertHeld(); mutex_.AssertHeld();
bool is_new_db = false; bool is_new_db = false;
...@@ -1083,10 +1083,25 @@ Status DBImpl::Recover( ...@@ -1083,10 +1083,25 @@ Status DBImpl::Recover(
} }
} }
if (logs.size() > 0 && error_if_log_file_exist) { if (logs.size() > 0) {
return Status::Corruption("" if (error_if_log_file_exist) {
"The db was opened in readonly mode with error_if_log_file_exist" return Status::Corruption(
"flag but a log file already exists"); "The db was opened in readonly mode with error_if_log_file_exist"
"flag but a log file already exists");
} else if (error_if_data_exists_in_logs) {
for (auto& log : logs) {
std::string fname = LogFileName(db_options_.wal_dir, log);
uint64_t bytes;
s = env_->GetFileSize(fname, &bytes);
if (s.ok()) {
if (bytes > 0) {
return Status::Corruption(
"error_if_data_exists_in_logs is set but there are data "
" in log files.");
}
}
}
}
} }
if (!logs.empty()) { if (!logs.empty()) {
......
...@@ -483,7 +483,8 @@ class DBImpl : public DB { ...@@ -483,7 +483,8 @@ class DBImpl : public DB {
// amount of work to recover recently logged updates. Any changes to // amount of work to recover recently logged updates. Any changes to
// be made to the descriptor are added to *edit. // be made to the descriptor are added to *edit.
Status Recover(const std::vector<ColumnFamilyDescriptor>& column_families, Status Recover(const std::vector<ColumnFamilyDescriptor>& column_families,
bool read_only = false, bool error_if_log_file_exist = false); bool read_only = false, bool error_if_log_file_exist = false,
bool error_if_data_exists_in_logs = false);
void MaybeIgnoreError(Status* s) const; void MaybeIgnoreError(Status* s) const;
......
...@@ -338,6 +338,15 @@ TEST_F(DBTest, CompactedDB) { ...@@ -338,6 +338,15 @@ TEST_F(DBTest, CompactedDB) {
ASSERT_OK(status_list[4]); ASSERT_OK(status_list[4]);
ASSERT_EQ(DummyString(kFileSize / 2, 'i'), values[4]); ASSERT_EQ(DummyString(kFileSize / 2, 'i'), values[4]);
ASSERT_TRUE(status_list[5].IsNotFound()); ASSERT_TRUE(status_list[5].IsNotFound());
Reopen(options);
// Add a key
ASSERT_OK(Put("fff", DummyString(kFileSize / 2, 'f')));
Close();
ASSERT_OK(ReadOnlyReopen(options));
s = Put("new", "value");
ASSERT_EQ(s.ToString(),
"Not implemented: Not supported operation in read only mode.");
} }
TEST_F(DBTest, LevelLimitReopen) { TEST_F(DBTest, LevelLimitReopen) {
......
...@@ -37,6 +37,7 @@ std::shared_ptr<DB> OpenDb(bool read_only = false) { ...@@ -37,6 +37,7 @@ std::shared_ptr<DB> OpenDb(bool read_only = false) {
DB* db; DB* db;
Options options; Options options;
options.create_if_missing = true; options.create_if_missing = true;
options.max_open_files = -1;
options.write_buffer_size = FLAGS_write_buffer_size; options.write_buffer_size = FLAGS_write_buffer_size;
options.max_write_buffer_number = FLAGS_max_write_buffer_number; options.max_write_buffer_number = FLAGS_max_write_buffer_number;
options.min_write_buffer_number_to_merge = options.min_write_buffer_number_to_merge =
...@@ -279,14 +280,19 @@ void ProfileQueries(bool enabled_time = false) { ...@@ -279,14 +280,19 @@ void ProfileQueries(bool enabled_time = false) {
#endif #endif
for (const int i : keys) { for (const int i : keys) {
if (i == kFlushFlag) {
continue;
}
std::string key = "k" + ToString(i); std::string key = "k" + ToString(i);
std::string value = "v" + ToString(i); std::string expected_value = "v" + ToString(i);
std::string value;
std::vector<Slice> multiget_keys = {Slice(key)}; std::vector<Slice> multiget_keys = {Slice(key)};
std::vector<std::string> values; std::vector<std::string> values;
perf_context.Reset(); perf_context.Reset();
db->Get(read_options, key, &value); ASSERT_OK(db->Get(read_options, key, &value));
ASSERT_EQ(expected_value, value);
hist_get_snapshot.Add(perf_context.get_snapshot_time); hist_get_snapshot.Add(perf_context.get_snapshot_time);
hist_get_memtable.Add(perf_context.get_from_memtable_time); hist_get_memtable.Add(perf_context.get_from_memtable_time);
hist_get_files.Add(perf_context.get_from_output_files_time); hist_get_files.Add(perf_context.get_from_output_files_time);
...@@ -375,14 +381,19 @@ void ProfileQueries(bool enabled_time = false) { ...@@ -375,14 +381,19 @@ void ProfileQueries(bool enabled_time = false) {
hist_mget_num_memtable_checked.Clear(); hist_mget_num_memtable_checked.Clear();
for (const int i : keys) { for (const int i : keys) {
if (i == kFlushFlag) {
continue;
}
std::string key = "k" + ToString(i); std::string key = "k" + ToString(i);
std::string value = "v" + ToString(i); std::string expected_value = "v" + ToString(i);
std::string value;
std::vector<Slice> multiget_keys = {Slice(key)}; std::vector<Slice> multiget_keys = {Slice(key)};
std::vector<std::string> values; std::vector<std::string> values;
perf_context.Reset(); perf_context.Reset();
db->Get(read_options, key, &value); ASSERT_OK(db->Get(read_options, key, &value));
ASSERT_EQ(expected_value, value);
hist_get_snapshot.Add(perf_context.get_snapshot_time); hist_get_snapshot.Add(perf_context.get_snapshot_time);
hist_get_memtable.Add(perf_context.get_from_memtable_time); hist_get_memtable.Add(perf_context.get_from_memtable_time);
hist_get_files.Add(perf_context.get_from_output_files_time); hist_get_files.Add(perf_context.get_from_output_files_time);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册