Skip to content

Commit

Permalink
Merge branch 'main' into fix-multiget-findtable-ioerror
Browse files Browse the repository at this point in the history
  • Loading branch information
ajkr authored Apr 29, 2024
2 parents e08bfc5 + e36b0a2 commit 2caca29
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 1 deletion.
7 changes: 7 additions & 0 deletions db/db_impl/db_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,8 @@ class DBImpl : public DB {

uint64_t MinLogNumberToKeep();

uint64_t MinLogNumberToRecycle();

// Returns the lower bound file number for SSTs that won't be deleted, even if
// they're obsolete. This lower bound is used internally to prevent newly
// created flush/compaction output files from being deleted before they're
Expand Down Expand Up @@ -2482,6 +2484,11 @@ class DBImpl : public DB {
uint64_t logfile_number_;
// Log files that we can recycle. Must be protected by db mutex_.
std::deque<uint64_t> log_recycle_files_;
// The minimum log file number taht can be recycled, if log recycling is
// enabled. This is used to ensure that log files created by previous
// instances of the database are not recycled, as we cannot be sure they
// were created in the recyclable format.
uint64_t min_log_number_to_recycle_;
// Protected by log_write_mutex_.
bool log_dir_synced_;
// Without two_write_queues, read and writes to log_empty_ are protected by
Expand Down
5 changes: 4 additions & 1 deletion db/db_impl/db_impl_files.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ uint64_t DBImpl::MinLogNumberToKeep() {
return versions_->min_log_number_to_keep();
}

uint64_t DBImpl::MinLogNumberToRecycle() { return min_log_number_to_recycle_; }

uint64_t DBImpl::MinObsoleteSstNumberToKeep() {
mutex_.AssertHeld();
if (!pending_outputs_.empty()) {
Expand Down Expand Up @@ -298,7 +300,8 @@ void DBImpl::FindObsoleteFiles(JobContext* job_context, bool force,
while (alive_log_files_.begin()->number < min_log_number) {
auto& earliest = *alive_log_files_.begin();
if (immutable_db_options_.recycle_log_file_num >
log_recycle_files_.size()) {
log_recycle_files_.size() &&
earliest.number >= MinLogNumberToRecycle()) {
ROCKS_LOG_INFO(immutable_db_options_.info_log,
"adding log %" PRIu64 " to recycle list\n",
earliest.number);
Expand Down
5 changes: 5 additions & 0 deletions db/db_impl/db_impl_open.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,11 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
impl->GetWalPreallocateBlockSize(max_write_buffer_size);
s = impl->CreateWAL(write_options, new_log_number, 0 /*recycle_log_number*/,
preallocate_block_size, &new_log);
if (s.ok()) {
// Prevent log files created by previous instance from being recycled.
// They might be in alive_log_file_, and might get recycled otherwise.
impl->min_log_number_to_recycle_ = new_log_number;
}
if (s.ok()) {
InstrumentedMutexLock wl(&impl->log_write_mutex_);
impl->logfile_number_ = new_log_number;
Expand Down
26 changes: 26 additions & 0 deletions db/db_write_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,32 @@ TEST_P(DBWriteTest, RecycleLogTestCFAheadOfWAL) {
Status::Corruption());
}

TEST_P(DBWriteTest, RecycleLogToggleTest) {
Options options = GetOptions();
options.recycle_log_file_num = 0;
options.avoid_flush_during_recovery = true;
options.wal_recovery_mode = WALRecoveryMode::kPointInTimeRecovery;

Destroy(options);
Reopen(options);
// After opening, a new log gets created, say 1.log
ASSERT_OK(Put(Key(1), "val1"));

options.recycle_log_file_num = 1;
Reopen(options);
// 1.log is added to alive_log_files_
ASSERT_OK(Put(Key(2), "val1"));
ASSERT_OK(Flush());
// 1.log should be deleted and not recycled, since it
// was created by the previous Reopen
ASSERT_OK(Put(Key(1), "val2"));
ASSERT_OK(Flush());

options.recycle_log_file_num = 1;
Reopen(options);
ASSERT_EQ(Get(Key(1)), "val2");
}

INSTANTIATE_TEST_CASE_P(DBWriteTestInstance, DBWriteTest,
testing::Values(DBTestBase::kDefault,
DBTestBase::kConcurrentWALWrites,
Expand Down
1 change: 1 addition & 0 deletions unreleased_history/bug_fixes/recycle_logs_toggle_bug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a bug when the recycle_log_file_num in DBOptions is changed from 0 to non-zero when a DB is reopened. On a subsequent reopen, if a log file created when recycle_log_file_num==0 was reused previously, is alive and is empty, we could end up inserting stale WAL records into the memtable.

0 comments on commit 2caca29

Please sign in to comment.