Bugfix/fix manual flush blocking bug (#9893)
Summary: Fix https://github.com/facebook/rocksdb/issues/9892 Pull Request resolved: https://github.com/facebook/rocksdb/pull/9893 Reviewed By: jay-zhuang Differential Revision: D35880959 Pulled By: ajkr fbshipit-source-id: dad1139ad0983cfbd5c5cd6fa6b71022f889735a
This commit is contained in:
parent
fb9a167a55
commit
6d2577e567
@ -1,5 +1,8 @@
|
|||||||
# Rocksdb Change Log
|
# Rocksdb Change Log
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
### Bug Fixes
|
||||||
|
* Fixed a bug where manual flush would block forever even though flush options had wait=false.
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
* DB::GetLiveFilesStorageInfo is ready for production use.
|
* DB::GetLiveFilesStorageInfo is ready for production use.
|
||||||
|
|
||||||
|
@ -1704,9 +1704,11 @@ Status DBImpl::Flush(const FlushOptions& flush_options,
|
|||||||
Status s;
|
Status s;
|
||||||
if (immutable_db_options_.atomic_flush) {
|
if (immutable_db_options_.atomic_flush) {
|
||||||
s = AtomicFlushMemTables({cfh->cfd()}, flush_options,
|
s = AtomicFlushMemTables({cfh->cfd()}, flush_options,
|
||||||
FlushReason::kManualFlush);
|
FlushReason::kManualFlush,
|
||||||
|
write_controller().IsStopped());
|
||||||
} else {
|
} else {
|
||||||
s = FlushMemTable(cfh->cfd(), flush_options, FlushReason::kManualFlush);
|
s = FlushMemTable(cfh->cfd(), flush_options, FlushReason::kManualFlush,
|
||||||
|
write_controller().IsStopped());
|
||||||
}
|
}
|
||||||
|
|
||||||
ROCKS_LOG_INFO(immutable_db_options_.info_log,
|
ROCKS_LOG_INFO(immutable_db_options_.info_log,
|
||||||
|
@ -7034,6 +7034,51 @@ TEST_F(DBTest, MemoryUsageWithMaxWriteBufferSizeToMaintain) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DBTest, ManualFlushWithStoppedWritesTest) {
|
||||||
|
Options options = CurrentOptions();
|
||||||
|
|
||||||
|
// Setting a small write buffer size. This will block writes
|
||||||
|
// rather quickly until a flush is made.
|
||||||
|
constexpr unsigned int memtableSize = 1000;
|
||||||
|
options.db_write_buffer_size = memtableSize;
|
||||||
|
options.max_background_flushes = 1;
|
||||||
|
Reopen(options);
|
||||||
|
|
||||||
|
std::atomic<bool> done(false);
|
||||||
|
|
||||||
|
// Will suppress future flushes.
|
||||||
|
// This simulates a situation where the writes will be stopped for any reason.
|
||||||
|
ASSERT_OK(dbfull()->PauseBackgroundWork());
|
||||||
|
|
||||||
|
port::Thread backgroundWriter([&]() {
|
||||||
|
Random rnd(301);
|
||||||
|
// These writes won't finish.
|
||||||
|
ASSERT_OK(Put("k1", rnd.RandomString(memtableSize / 2)));
|
||||||
|
ASSERT_OK(Put("k2", rnd.RandomString(memtableSize / 2)));
|
||||||
|
ASSERT_OK(Put("k3", rnd.RandomString(memtableSize / 2)));
|
||||||
|
ASSERT_OK(Put("k4", rnd.RandomString(memtableSize / 2)));
|
||||||
|
done.store(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
env_->SleepForMicroseconds(1000000 / 2);
|
||||||
|
// make sure thread is stuck waiting for flush.
|
||||||
|
ASSERT_FALSE(done.load());
|
||||||
|
|
||||||
|
FlushOptions flushOptions;
|
||||||
|
flushOptions.wait = false;
|
||||||
|
flushOptions.allow_write_stall = true;
|
||||||
|
|
||||||
|
// This is the main goal of the test. This manual flush should not deadlock
|
||||||
|
// as we use wait=false, and even allow_write_stall=true for extra safety.
|
||||||
|
ASSERT_OK(dbfull()->Flush(flushOptions));
|
||||||
|
|
||||||
|
// This will re-allow background flushes.
|
||||||
|
ASSERT_OK(dbfull()->ContinueBackgroundWork());
|
||||||
|
|
||||||
|
backgroundWriter.join();
|
||||||
|
ASSERT_TRUE(done.load());
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace ROCKSDB_NAMESPACE
|
} // namespace ROCKSDB_NAMESPACE
|
||||||
|
Loading…
Reference in New Issue
Block a user