From b2ce59537cb89422be2abb6bf56e5dc3984a2805 Mon Sep 17 00:00:00 2001 From: Justin Gibbs Date: Thu, 25 Aug 2016 12:24:22 -0700 Subject: [PATCH] Persist data during user initiated shutdown Summary: Move the manual memtable flush for databases containing data that has bypassed the WAL from DBImpl's destructor to CancleAllBackgroundWork(). CancelAllBackgroundWork() is a publicly exposed API which allows async operations performed by background threads to be disabled on a database. In effect, this places the database into a "shutdown" state in advance of calling the database object's destructor. No compactions or flushing of SST files can occur once a call to this API completes. When writes are issued to a database with WriteOptions::disableWAL set to true, DBImpl::has_unpersisted_data_ is set so that memtables can be flushed when the database object is destroyed. If CancelAllBackgroundWork() has been called prior to DBImpl's destructor, this flush operation is not possible and is skipped, causing unnecessary loss of data. Since CancelAllBackgroundWork() is already invoked by DBImpl's destructor in order to perform the thread join portion of its cleanup processing, moving the manual memtable flush to CancelAllBackgroundWork() ensures data is persisted regardless of client behavior. Test Plan: Write an amount of data that will not cause a memtable flush to a rocksdb database with all writes marked with WriteOptions::disableWAL. Properly "close" the database. Reopen database and verify that the data was persisted. Reviewers: IslamAbdelRahman, yiwu, yoshinorim, sdong Reviewed By: sdong Subscribers: andrewkr, dhruba Differential Revision: https://reviews.facebook.net/D62277 --- db/db_impl.cc | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/db/db_impl.cc b/db/db_impl.cc index 626b9756e..61537dd1f 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -372,19 +372,6 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname) // Will lock the mutex_, will wait for completion if wait is true void DBImpl::CancelAllBackgroundWork(bool wait) { InstrumentedMutexLock l(&mutex_); - shutting_down_.store(true, std::memory_order_release); - bg_cv_.SignalAll(); - if (!wait) { - return; - } - // Wait for background work to finish - while (bg_compaction_scheduled_ || bg_flush_scheduled_) { - bg_cv_.Wait(); - } -} - -DBImpl::~DBImpl() { - mutex_.Lock(); if (!shutting_down_.load(std::memory_order_acquire) && has_unpersisted_data_) { @@ -399,7 +386,19 @@ DBImpl::~DBImpl() { } versions_->GetColumnFamilySet()->FreeDeadColumnFamilies(); } - mutex_.Unlock(); + + shutting_down_.store(true, std::memory_order_release); + bg_cv_.SignalAll(); + if (!wait) { + return; + } + // Wait for background work to finish + while (bg_compaction_scheduled_ || bg_flush_scheduled_) { + bg_cv_.Wait(); + } +} + +DBImpl::~DBImpl() { // CancelAllBackgroundWork called with false means we just set the shutdown // marker. After this we do a variant of the waiting and unschedule work // (to consider: moving all the waiting into CancelAllBackgroundWork(true))