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
This commit is contained in:
parent
4b3438d2d6
commit
b2ce59537c
@ -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
|
// Will lock the mutex_, will wait for completion if wait is true
|
||||||
void DBImpl::CancelAllBackgroundWork(bool wait) {
|
void DBImpl::CancelAllBackgroundWork(bool wait) {
|
||||||
InstrumentedMutexLock l(&mutex_);
|
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) &&
|
if (!shutting_down_.load(std::memory_order_acquire) &&
|
||||||
has_unpersisted_data_) {
|
has_unpersisted_data_) {
|
||||||
@ -399,7 +386,19 @@ DBImpl::~DBImpl() {
|
|||||||
}
|
}
|
||||||
versions_->GetColumnFamilySet()->FreeDeadColumnFamilies();
|
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
|
// CancelAllBackgroundWork called with false means we just set the shutdown
|
||||||
// marker. After this we do a variant of the waiting and unschedule work
|
// marker. After this we do a variant of the waiting and unschedule work
|
||||||
// (to consider: moving all the waiting into CancelAllBackgroundWork(true))
|
// (to consider: moving all the waiting into CancelAllBackgroundWork(true))
|
||||||
|
Loading…
Reference in New Issue
Block a user