From fbd1c982556c989fb78e66a94d3387880e2b37da Mon Sep 17 00:00:00 2001 From: Andrew Kryczka Date: Thu, 15 Sep 2016 11:40:48 -0700 Subject: [PATCH] Fix recovery for WALs without data for all CFs Summary: if one or more CFs had no data in the WAL, the log number that's used by FindObsoleteFiles() wasn't updated. We need to treat this case the same as if the data for that WAL had been flushed. Test Plan: new unit test Reviewers: IslamAbdelRahman, yiwu, sdong Reviewed By: sdong Subscribers: andrewkr, dhruba, leveldb Differential Revision: https://reviews.facebook.net/D63963 --- db/db_impl.cc | 2 +- db/db_wal_test.cc | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/db/db_impl.cc b/db/db_impl.cc index 126c3e943..f750ef839 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -1701,7 +1701,7 @@ Status DBImpl::RecoverLogFiles(const std::vector& log_numbers, // recovered and should be ignored on next reincarnation. // Since we already recovered max_log_number, we want all logs // with numbers `<= max_log_number` (includes this one) to be ignored - if (flushed) { + if (flushed || cfd->mem()->GetFirstSequenceNumber() == 0) { edit->SetLogNumber(max_log_number + 1); } // we must mark the next log number as used, even though it's diff --git a/db/db_wal_test.cc b/db/db_wal_test.cc index 34d780511..10520b774 100644 --- a/db/db_wal_test.cc +++ b/db/db_wal_test.cc @@ -305,6 +305,31 @@ TEST_F(DBWALTest, GetSortedWalFiles) { } while (ChangeOptions()); } +TEST_F(DBWALTest, RecoveryWithLogDataForSomeCFs) { + // Test for regression of WAL cleanup missing files that don't contain data + // for every column family. + do { + CreateAndReopenWithCF({"pikachu"}, CurrentOptions()); + ASSERT_OK(Put(1, "foo", "v1")); + ASSERT_OK(Put(1, "foo", "v2")); + std::array earliest_log_nums; + for (int i = 0; i < 2; ++i) { + if (i > 0) { + ReopenWithColumnFamilies({"default", "pikachu"}, CurrentOptions()); + } + VectorLogPtr log_files; + ASSERT_OK(dbfull()->GetSortedWalFiles(log_files)); + if (log_files.size() > 0) { + earliest_log_nums[i] = log_files[0]->LogNumber(); + } else { + earliest_log_nums[i] = port::kMaxUint64; + } + } + // Check at least the first WAL was cleaned up during the recovery. + ASSERT_LT(earliest_log_nums[0], earliest_log_nums[1]); + } while (ChangeOptions()); +} + TEST_F(DBWALTest, RecoverWithLargeLog) { do { {