@@ -4694,6 +4694,16 @@ Status DBImpl::IngestExternalFiles(
46944694 if (args.empty ()) {
46954695 return Status::InvalidArgument (" ingestion arg list is empty" );
46964696 }
4697+ // Supported only when all args have the consistent `allow_write` behavior, as
4698+ // `allow_write` determines whether stopping writes to the DB affects all
4699+ // args.
4700+ bool allow_write = args[0 ].options .allow_write ;
4701+ for (const auto & arg : args) {
4702+ if (arg.options .allow_write != allow_write) {
4703+ return Status::InvalidArgument (
4704+ " Inconsistent allow_writes values across ingestion arguments" );
4705+ }
4706+ }
46974707 {
46984708 std::unordered_set<ColumnFamilyHandle*> unique_cfhs;
46994709 for (const auto & arg : args) {
@@ -4801,20 +4811,25 @@ Status DBImpl::IngestExternalFiles(
48014811 InstrumentedMutexLock l (&mutex_);
48024812 TEST_SYNC_POINT (" DBImpl::AddFile:MutexLock" );
48034813
4804- // Stop writes to the DB by entering both write threads
48054814 WriteThread::Writer w;
4806- write_thread_.EnterUnbatched (&w, &mutex_);
48074815 WriteThread::Writer nonmem_w;
4808- if (two_write_queues_) {
4809- nonmem_write_thread_.EnterUnbatched (&nonmem_w, &mutex_);
4816+ if (!allow_write) {
4817+ // Stop writes to the DB by entering both write threads.
4818+ write_thread_.EnterUnbatched (&w, &mutex_);
4819+ if (two_write_queues_) {
4820+ nonmem_write_thread_.EnterUnbatched (&nonmem_w, &mutex_);
4821+ }
4822+
4823+ // When unordered_write is enabled, the keys are writing to memtable in an
4824+ // unordered way. If the ingestion job checks memtable key range before
4825+ // the key landing in memtable, the ingestion job may skip the necessary
4826+ // memtable flush.
4827+ // So wait here to ensure there is no pending write to memtable.
4828+ WaitForPendingWrites ();
48104829 }
48114830
4812- // When unordered_write is enabled, the keys are writing to memtable in an
4813- // unordered way. If the ingestion job checks memtable key range before the
4814- // key landing in memtable, the ingestion job may skip the necessary
4815- // memtable flush.
4816- // So wait here to ensure there is no pending write to memtable.
4817- WaitForPendingWrites ();
4831+ TEST_SYNC_POINT_CALLBACK (" DBImpl::IngestExternalFile:AfterAllowWriteCheck" ,
4832+ nullptr );
48184833
48194834 num_running_ingest_file_ += static_cast <int >(num_cfs);
48204835 TEST_SYNC_POINT (" DBImpl::IngestExternalFile:AfterIncIngestFileCounter" );
@@ -4852,7 +4867,7 @@ Status DBImpl::IngestExternalFiles(
48524867 mutex_.Unlock ();
48534868 status = AtomicFlushMemTables (cfds_to_flush, flush_opts,
48544869 FlushReason::kExternalFileIngestion ,
4855- true /* writes_stopped */ );
4870+ !allow_write /* entered_write_thread */ );
48564871 mutex_.Lock ();
48574872 } else {
48584873 for (size_t i = 0 ; i != num_cfs; ++i) {
@@ -4863,7 +4878,7 @@ Status DBImpl::IngestExternalFiles(
48634878 ->cfd ();
48644879 status = FlushMemTable (cfd, flush_opts,
48654880 FlushReason::kExternalFileIngestion ,
4866- true /* writes_stopped */ );
4881+ !allow_write /* entered_write_thread */ );
48674882 mutex_.Lock ();
48684883 if (!status.ok ()) {
48694884 break ;
@@ -4954,11 +4969,12 @@ Status DBImpl::IngestExternalFiles(
49544969 error_handler_.SetBGError (io_s, BackgroundErrorReason::kManifestWrite );
49554970 }
49564971
4957- // Resume writes to the DB
4958- if (two_write_queues_) {
4959- nonmem_write_thread_.ExitUnbatched (&nonmem_w);
4972+ if (!allow_write) {
4973+ if (two_write_queues_) {
4974+ nonmem_write_thread_.ExitUnbatched (&nonmem_w);
4975+ }
4976+ write_thread_.ExitUnbatched (&w);
49604977 }
4961- write_thread_.ExitUnbatched (&w);
49624978
49634979 if (status.ok ()) {
49644980 for (auto & job : ingestion_jobs) {
0 commit comments