From 406a5682eb41f7d84908dbeb3eba4bb0a99babac Mon Sep 17 00:00:00 2001 From: Venkatesh Radhakrishnan Date: Tue, 9 Jun 2015 10:39:49 -0700 Subject: [PATCH] Fix hang when closing a DB after doing loads with WAL disabled. Summary: There is a hang during DB close in the following scenario: a) a load with WAL disabled was done, b) CancelAllBackgroundWork was called, c) DB Close was called This was because in that we will wait for a flush but we cannot do a background flush because we have called CancelAllBackgroundWork which marks the DB as shutting downn. Test Plan: Added DBTest FlushOnDestroy Reviewers: sdong Reviewed By: sdong Subscribers: yoshinorim, hermanlee4, dhruba, leveldb Differential Revision: https://reviews.facebook.net/D39747 --- HISTORY.md | 1 + db/db_impl.cc | 2 +- db/db_test.cc | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index acb1b43a2..290b613d9 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,6 +10,7 @@ * Add max_write_buffer_number_to_maintain option * DB::CompactRange()'s parameter reduce_level is changed to change_level, to allow users to move levels to lower levels if allowed. It can be used to migrate a DB from options.level_compaction_dynamic_level_bytes=false to options.level_compaction_dynamic_level_bytes.true. * Change default value for options.compaction_filter_factory and options.compaction_filter_factory_v2 to nullptr instead of DefaultCompactionFilterFactory and DefaultCompactionFilterFactoryV2. +* If CancelAllBackgroundWork is called without doing a flush after doing loads with WAL disabled, the changes which haven't been flushed before the call to CancelAllBackgroundWork will be lost. ## 3.11.0 (5/19/2015) ### New Features diff --git a/db/db_impl.cc b/db/db_impl.cc index 76382ecf4..d80c5921d 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -288,7 +288,7 @@ DBImpl::~DBImpl() { EraseThreadStatusDbInfo(); mutex_.Lock(); - if (flush_on_destroy_) { + if (!shutting_down_.load(std::memory_order_acquire) && flush_on_destroy_) { for (auto cfd : *versions_->GetColumnFamilySet()) { if (!cfd->IsDropped() && !cfd->mem()->IsEmpty()) { cfd->Ref(); diff --git a/db/db_test.cc b/db/db_test.cc index 079cdc684..3465e51d7 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -11097,6 +11097,13 @@ TEST_F(DBTest, PreShutdownCompactionMiddle) { #endif // ROCKSDB_USING_THREAD_STATUS +TEST_F(DBTest, FlushOnDestroy) { + WriteOptions wo; + wo.disableWAL = true; + ASSERT_OK(Put("foo", "v1", wo)); + CancelAllBackgroundWork(db_); +} + TEST_F(DBTest, DynamicLevelMaxBytesBase) { // Use InMemoryEnv, or it would be too slow. unique_ptr env(new MockEnv(env_));