@@ -244,6 +244,7 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
244
244
super_version_(nullptr ),
245
245
tmp_batch_(),
246
246
bg_compaction_scheduled_(0 ),
247
+ bg_manual_only_(0 ),
247
248
bg_flush_scheduled_(0 ),
248
249
bg_logstats_scheduled_(false ),
249
250
manual_compaction_(nullptr ),
@@ -1608,45 +1609,44 @@ void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) {
1608
1609
1609
1610
MutexLock l (&mutex_);
1610
1611
1611
- // When a manual compaction arrives, temporarily throttle down
1612
- // the number of background compaction threads to 1. This is
1613
- // needed to ensure that this manual compaction can compact
1614
- // any range of keys/files. We artificialy increase
1615
- // bg_compaction_scheduled_ by a large number, this causes
1616
- // the system to have a single background thread. Now,
1617
- // this manual compaction can progress without stomping
1618
- // on any other concurrent compactions.
1619
- const int LargeNumber = 10000000 ;
1620
- const int newvalue = options_.max_background_compactions -1 ;
1621
- bg_compaction_scheduled_ += LargeNumber;
1622
- while (bg_compaction_scheduled_ > LargeNumber) {
1623
- Log (options_.info_log , " Manual compaction request waiting for background threads to fall below 1" );
1612
+ // When a manual compaction arrives, temporarily disable scheduling of
1613
+ // non-manual compactions and wait until the number of scheduled compaction
1614
+ // jobs drops to zero. This is needed to ensure that this manual compaction
1615
+ // can compact any range of keys/files.
1616
+ //
1617
+ // bg_manual_only_ is non-zero when at least one thread is inside
1618
+ // TEST_CompactRange(), i.e. during that time no other compaction will
1619
+ // get scheduled (see MaybeScheduleFlushOrCompaction).
1620
+ //
1621
+ // Note that the following loop doesn't stop more that one thread calling
1622
+ // TEST_CompactRange() from getting to the second while loop below.
1623
+ // However, only one of them will actually schedule compaction, while
1624
+ // others will wait on a condition variable until it completes.
1625
+
1626
+ ++bg_manual_only_;
1627
+ while (bg_compaction_scheduled_ > 0 ) {
1628
+ Log (options_.info_log ,
1629
+ " Manual compaction waiting for all other scheduled background "
1630
+ " compactions to finish" );
1624
1631
bg_cv_.Wait ();
1625
1632
}
1633
+
1626
1634
Log (options_.info_log , " Manual compaction starting" );
1627
1635
1628
- while (!manual.done ) {
1629
- while (manual_compaction_ != nullptr ) {
1630
- bg_cv_.Wait ();
1631
- }
1632
- manual_compaction_ = &manual;
1633
- if (bg_compaction_scheduled_ == LargeNumber) {
1634
- bg_compaction_scheduled_ = newvalue;
1635
- }
1636
- MaybeScheduleFlushOrCompaction ();
1637
- while (manual_compaction_ == &manual) {
1636
+ while (!manual.done && !shutting_down_.Acquire_Load () && bg_error_.ok ()) {
1637
+ assert (bg_manual_only_ > 0 );
1638
+ if (manual_compaction_ != nullptr ) {
1639
+ // Running either this or some other manual compaction
1638
1640
bg_cv_.Wait ();
1641
+ } else {
1642
+ manual_compaction_ = &manual;
1643
+ MaybeScheduleFlushOrCompaction ();
1639
1644
}
1640
1645
}
1641
- assert (!manual.in_progress );
1642
1646
1643
- // wait till there are no background threads scheduled
1644
- bg_compaction_scheduled_ += LargeNumber;
1645
- while (bg_compaction_scheduled_ > LargeNumber + newvalue) {
1646
- Log (options_.info_log , " Manual compaction resetting background threads" );
1647
- bg_cv_.Wait ();
1648
- }
1649
- bg_compaction_scheduled_ = 0 ;
1647
+ assert (!manual.in_progress );
1648
+ assert (bg_manual_only_ > 0 );
1649
+ --bg_manual_only_;
1650
1650
}
1651
1651
1652
1652
Status DBImpl::FlushMemTable (const FlushOptions& options) {
@@ -1711,11 +1711,16 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
1711
1711
env_->Schedule (&DBImpl::BGWorkFlush, this , Env::Priority::HIGH);
1712
1712
}
1713
1713
1714
+ // Schedule BGWorkCompaction if there's a compaction pending (or a memtable
1715
+ // flush, but the HIGH pool is not enabled). Do it only if
1716
+ // max_background_compactions hasn't been reached and, in case
1717
+ // bg_manual_only_ > 0, if it's a manual compaction.
1714
1718
if ((manual_compaction_ ||
1715
1719
versions_->NeedsCompaction () ||
1716
1720
(is_flush_pending && (options_.max_background_flushes <= 0 ))) &&
1717
- bg_compaction_scheduled_ < options_.max_background_compactions ) {
1718
- // compaction needed, or memtable flush needed but HIGH pool not enabled.
1721
+ bg_compaction_scheduled_ < options_.max_background_compactions &&
1722
+ (!bg_manual_only_ || manual_compaction_)) {
1723
+
1719
1724
bg_compaction_scheduled_++;
1720
1725
env_->Schedule (&DBImpl::BGWorkCompaction, this , Env::Priority::LOW);
1721
1726
}
0 commit comments