--- leveldb-1.20/db/db_impl.cc.0002~ 2017-03-02 01:08:02.000000000 +0100 +++ leveldb-1.20/db/db_impl.cc 2017-06-02 10:40:40.888354189 +0200 @@ -125,6 +125,9 @@ DBImpl::DBImpl(const Options& raw_option dbname_(dbname), db_lock_(NULL), shutting_down_(NULL), + suspend_cv(&suspend_mutex), + suspend_count(0), + suspended(false), bg_cv_(&mutex_), mem_(NULL), imm_(NULL), @@ -1471,6 +1474,39 @@ void DBImpl::GetApproximateSizes( } } +void DBImpl::SuspendCompactions() { + MutexLock l(& suspend_mutex); + env_->Schedule(&SuspendWork, this); + suspend_count++; + while( !suspended ) { + suspend_cv.Wait(); + } +} +void DBImpl::SuspendWork(void* db) { + reinterpret_cast<DBImpl*>(db)->SuspendCallback(); +} +void DBImpl::SuspendCallback() { + MutexLock l(&suspend_mutex); + Log(options_.info_log, "Compactions suspended"); + suspended = true; + suspend_cv.SignalAll(); + while( suspend_count > 0 ) { + suspend_cv.Wait(); + } + suspended = false; + suspend_cv.SignalAll(); + Log(options_.info_log, "Compactions resumed"); +} +void DBImpl::ResumeCompactions() { + MutexLock l(&suspend_mutex); + suspend_count--; + suspend_cv.SignalAll(); + while( suspended ) { + suspend_cv.Wait(); + } +} + + // Default implementations of convenience methods that subclasses of DB // can call if they wish Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { --- leveldb-1.20/db/db_impl.h.0002~ 2017-03-02 01:08:02.000000000 +0100 +++ leveldb-1.20/db/db_impl.h 2017-06-02 10:40:09.517069848 +0200 @@ -41,6 +41,8 @@ class DBImpl : public DB { virtual bool GetProperty(const Slice& property, std::string* value); virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes); virtual void CompactRange(const Slice* begin, const Slice* end); + virtual void SuspendCompactions(); + virtual void ResumeCompactions(); // Extra methods (for testing) that are not in the public DB interface @@ -133,6 +135,13 @@ class DBImpl : public DB { // Lock over the persistent DB state. Non-NULL iff successfully acquired. FileLock* db_lock_; + port::Mutex suspend_mutex; + port::CondVar suspend_cv; + int suspend_count; + bool suspended; + static void SuspendWork(void* db); + void SuspendCallback(); + // State below is protected by mutex_ port::Mutex mutex_; port::AtomicPointer shutting_down_; --- leveldb-1.20/db/db_test.cc.0002~ 2017-03-02 01:08:02.000000000 +0100 +++ leveldb-1.20/db/db_test.cc 2017-06-02 10:40:09.517069848 +0200 @@ -1866,6 +1866,10 @@ class ModelDB: public DB { explicit ModelDB(const Options& options): options_(options) { } ~ModelDB() { } + + virtual void SuspendCompactions() {} + virtual void ResumeCompactions() {} + virtual Status Put(const WriteOptions& o, const Slice& k, const Slice& v) { return DB::Put(o, k, v); } --- leveldb-1.20/include/leveldb/db.h.0002~ 2017-03-02 01:08:02.000000000 +0100 +++ leveldb-1.20/include/leveldb/db.h 2017-06-02 10:40:09.517069848 +0200 @@ -142,6 +142,12 @@ class DB { // db->CompactRange(NULL, NULL); virtual void CompactRange(const Slice* begin, const Slice* end) = 0; + // Suspends the background compaction thread. This methods + // returns once suspended. + virtual void SuspendCompactions() = 0; + // Resumes a suspended background compation thread. + virtual void ResumeCompactions() = 0; + private: // No copying allowed DB(const DB&);