@@ -7128,6 +7128,70 @@ TEST_F(DBCompactionTest, PartialManualCompaction) {
71287128 ASSERT_OK (dbfull ()->CompactRange (cro, nullptr , nullptr ));
71297129}
71307130
7131+ TEST_F (DBCompactionTest, ConcurrentFIFOPickingSameFileBug) {
7132+ Options opts = CurrentOptions ();
7133+ opts.compaction_style = CompactionStyle::kCompactionStyleLevel ;
7134+ opts.num_levels = 3 ;
7135+ opts.disable_auto_compactions = true ;
7136+ opts.max_background_jobs = 3 ;
7137+
7138+ DestroyAndReopen (opts);
7139+
7140+ ASSERT_OK (Put (" k1" , " v1" ));
7141+ ASSERT_OK (Flush ());
7142+
7143+ // Create a non-L0 SST file for multi-level FIFO size-based compaction later
7144+ MoveFilesToLevel (2 );
7145+
7146+ Options opts_new (opts);
7147+ opts_new.compaction_style = CompactionStyle::kCompactionStyleFIFO ;
7148+ opts_new.max_open_files = -1 ;
7149+ // Set a low threshold to trigger multi-level size-based compaction
7150+ opts_new.compaction_options_fifo .max_table_files_size = 1 ;
7151+
7152+ Reopen (opts_new);
7153+
7154+ const CompactRangeOptions cro;
7155+ const Slice begin_key (" k1" );
7156+ const Slice end_key (" k2" );
7157+
7158+ std::unique_ptr<port::Thread> concurrent_compaction;
7159+
7160+ bool within_first_compaction = true ;
7161+ SyncPoint::GetInstance ()->SetCallBack (
7162+ " VersionSet::LogAndApply:WriteManifestStart" , [&](void * /* arg*/ ) {
7163+ if (!within_first_compaction) {
7164+ return ;
7165+ }
7166+ within_first_compaction = false ;
7167+
7168+ // To allow the second/concurrent compaction to still see the non-L0
7169+ // SST file and coerce the bug of picking that file
7170+ SyncPoint::GetInstance ()->LoadDependency ({
7171+ {" DBImpl::BackgroundCompaction:BeforeCompaction" ,
7172+ " VersionSet::LogAndApply:WriteManifest" },
7173+ });
7174+
7175+ concurrent_compaction.reset (new port::Thread ([&]() {
7176+ // Before the fix, the second CompactRange() will either fail the
7177+ // assertion of double file picking `being_compacted !=
7178+ // inputs_[i][j]->being_compacted` in debug mode or cause LSM shape
7179+ // corruption "Cannot delete table file XXX from level 2 since it is
7180+ // not in the LSM tree" in release mode
7181+ Status s = db_->CompactRange (cro, &begin_key, &end_key);
7182+ ASSERT_OK (s);
7183+ }));
7184+ });
7185+
7186+ SyncPoint::GetInstance ()->EnableProcessing ();
7187+ Status s = db_->CompactRange (cro, &begin_key, &end_key);
7188+ SyncPoint::GetInstance ()->DisableProcessing ();
7189+
7190+ ASSERT_OK (s);
7191+
7192+ concurrent_compaction->join ();
7193+ }
7194+
71317195TEST_F (DBCompactionTest, ManualCompactionFailsInReadOnlyMode) {
71327196 // Regression test for bug where manual compaction hangs forever when the DB
71337197 // is in read-only mode. Verify it now at least returns, despite failing.
0 commit comments