Skip to content

Commit 12d8819

Browse files
yabmek-msfttzuvich
andauthored
Task AB# 1310789: [LevelDB] Add mechanism to request suspension of background (BG Thread) tasks, to allow the db to go into a suspended state and fix deadlock caused by mechanism (#6)
* Added mechanism to request suspension of background (BG Thread) tasks, to allow the db to go into a suspended state * Fix deadlock in leveldbd that could occur when attempting to shut down while db was in the middle of compaction phase. * fixing tests --------- Co-authored-by: tedzu <[email protected]>
1 parent 336b207 commit 12d8819

File tree

4 files changed

+52
-3
lines changed

4 files changed

+52
-3
lines changed

db/db_impl.cc

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,13 @@ DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
147147
background_compaction_scheduled_(false),
148148
manual_compaction_(nullptr),
149149
versions_(new VersionSet(dbname_, &options_, table_cache_,
150-
&internal_comparator_)) {}
150+
&internal_comparator_)),
151+
suspending_compaction_(false) {}
151152

152153
DBImpl::~DBImpl() {
153154
// Wait for background work to finish.
154155
mutex_.Lock();
156+
suspending_compaction_.store(false, std::memory_order_release); // make sure that the suspend flag is clear
155157
shutting_down_.store(true, std::memory_order_release);
156158
while (background_compaction_scheduled_) {
157159
background_work_finished_signal_.Wait();
@@ -670,6 +672,8 @@ void DBImpl::MaybeScheduleCompaction() {
670672
// Already scheduled
671673
} else if (shutting_down_.load(std::memory_order_acquire)) {
672674
// DB is being deleted; no more background compactions
675+
} else if (imm_ == nullptr && suspending_compaction_.load(std::memory_order_acquire)) {
676+
// DB is being suspended; no more background compactions
673677
} else if (!bg_error_.ok()) {
674678
// Already got an error; no more changes
675679
} else if (imm_ == nullptr && manual_compaction_ == nullptr &&
@@ -681,6 +685,23 @@ void DBImpl::MaybeScheduleCompaction() {
681685
}
682686
}
683687

688+
void DBImpl::SuspendCompaction() {
689+
// set suspend flag and wait for any currently executing bg tasks to complete
690+
Log(options_.info_log, "BG suspend compaction\n");
691+
mutex_.Lock();
692+
suspending_compaction_.store(true, std::memory_order_release);
693+
mutex_.Unlock();
694+
Log(options_.info_log, "BG suspended\n");
695+
}
696+
697+
void DBImpl::ResumeCompaction() {
698+
Log(options_.info_log, "BG resume compaction\n");
699+
mutex_.Lock();
700+
suspending_compaction_.store(false, std::memory_order_release);
701+
mutex_.Unlock();
702+
Log(options_.info_log, "db BG resumed\n");
703+
}
704+
684705
void DBImpl::BGWork(void* db) {
685706
reinterpret_cast<DBImpl*>(db)->BackgroundCall();
686707
}
@@ -700,7 +721,9 @@ void DBImpl::BackgroundCall() {
700721

701722
// Previous compaction may have produced too many files in a level,
702723
// so reschedule another compaction if needed.
703-
MaybeScheduleCompaction();
724+
if (!suspending_compaction_.load(std::memory_order_acquire)) {
725+
MaybeScheduleCompaction();
726+
}
704727
background_work_finished_signal_.SignalAll();
705728
}
706729

@@ -766,6 +789,8 @@ void DBImpl::BackgroundCompaction() {
766789
// Done
767790
} else if (shutting_down_.load(std::memory_order_acquire)) {
768791
// Ignore compaction errors found during shutting down
792+
} else if (suspending_compaction_.load(std::memory_order_acquire)) {
793+
// Ignore compaction errors found during suspend
769794
} else {
770795
Log(options_.info_log, "Compaction error: %s", status.ToString().c_str());
771796
}
@@ -1353,6 +1378,9 @@ Status DBImpl::MakeRoomForWrite(bool force) {
13531378
(mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) {
13541379
// There is room in current memtable
13551380
break;
1381+
} else if (suspending_compaction_.load(std::memory_order_acquire)) {
1382+
// suspending, don't do this now
1383+
break;
13561384
} else if (imm_ != nullptr) {
13571385
// We have filled up the current memtable, but the previous
13581386
// one is still being compacted, so we wait.
@@ -1397,7 +1425,9 @@ Status DBImpl::MakeRoomForWrite(bool force) {
13971425
mem_ = new MemTable(internal_comparator_);
13981426
mem_->Ref();
13991427
force = false; // Do not force another compaction if have room
1400-
MaybeScheduleCompaction();
1428+
if (!suspending_compaction_.load(std::memory_order_acquire)) {
1429+
MaybeScheduleCompaction();
1430+
}
14011431
}
14021432
}
14031433
return s;

db/db_impl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ class DBImpl : public DB {
4848
bool GetProperty(const Slice& property, std::string* value) override;
4949
void GetApproximateSizes(const Range* range, int n, uint64_t* sizes) override;
5050
void CompactRange(const Slice* begin, const Slice* end) override;
51+
// Set the suspend flag, which tells the database not to schedule background
52+
// work until resume
53+
// Waits for any currently executing BG work to complete before returning
54+
void SuspendCompaction() override;
55+
// Clears the suspend flag, so that the database can schedule background work
56+
void ResumeCompaction() override;
5157

5258
// Extra methods (for testing) that are not in the public DB interface
5359

@@ -195,6 +201,9 @@ class DBImpl : public DB {
195201
// Has a background compaction been scheduled or is running?
196202
bool background_compaction_scheduled_ GUARDED_BY(mutex_);
197203

204+
// Has anyone issued a request to suspend background work?
205+
std::atomic<bool> suspending_compaction_ GUARDED_BY(mutex_);
206+
198207
ManualCompaction* manual_compaction_ GUARDED_BY(mutex_);
199208

200209
VersionSet* const versions_ GUARDED_BY(mutex_);

db/db_test.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,10 @@ class ModelDB : public DB {
21692169
}
21702170
void CompactRange(const Slice* start, const Slice* end) override {}
21712171

2172+
void SuspendCompaction() override {}
2173+
2174+
void ResumeCompaction() override {}
2175+
21722176
private:
21732177
class ModelIter : public Iterator {
21742178
public:

include/leveldb/db.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ class LEVELDB_EXPORT DB {
145145
// Therefore the following call will compact the entire database:
146146
// db->CompactRange(nullptr, nullptr);
147147
virtual void CompactRange(const Slice* begin, const Slice* end) = 0;
148+
149+
// Allows the underlying storage to prepare for an application suspend event
150+
virtual void SuspendCompaction() = 0;
151+
152+
// Allow the underlying storage to react to an application resume event
153+
virtual void ResumeCompaction() = 0;
148154
};
149155

150156
// Destroy the contents of the specified database.

0 commit comments

Comments
 (0)