From d7d6a9a41dbc064e4a225ca87fcd78fe9721869e 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 5b4ad092a..835d2c5ab 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 { {