@@ -144,6 +144,7 @@ class MigrationManager : public std::enable_shared_from_this<MigrationManager> {
144144 const std::string &operator_name,
145145 const std::string &external_fencing_evidence);
146146 bool HasAsyncCopyStorageReference (const std::string &storage_name) const ;
147+ bool HasAsyncCopyInstanceReference (const std::string &instance_id) const ;
147148
148149 // ---- Copy 路径 ----
149150 // 同步完成"建目标 location + 提交 copy 任务",copy 字节复制异步执行;
@@ -240,6 +241,7 @@ class MigrationManager : public std::enable_shared_from_this<MigrationManager> {
240241 kTargetWritingExists , // 目标 storage 上存在 WRITING 副本(可能为其他迁移半成品)
241242 kSourceServingNotFound , // 源 storage 上没有 SERVING 副本,无可复制源
242243 kSourceRetrySuppressed , // 尚未被目标覆盖的源均处于失败退避,当前不应再次提交 Copy
244+ kSourcePinnedByGuard , // 源被另一条持久异步 Copy guard 钉住,不能并行派生新迁移
243245 };
244246
245247 struct CopyAdmission {
@@ -455,6 +457,7 @@ class MigrationManager : public std::enable_shared_from_this<MigrationManager> {
455457 struct PendingCopy {
456458 std::string instance_id;
457459 int64_t block_key = 0 ;
460+ size_t expected_items = 0 ;
458461 std::future<PlanExecuteResult> future;
459462 bool native_async = false ;
460463 std::future<AsyncCopyRemoteSubmitResult> remote_submit_future;
@@ -463,6 +466,16 @@ class MigrationManager : public std::enable_shared_from_this<MigrationManager> {
463466 std::chrono::steady_clock::time_point completion_retry_after{};
464467 };
465468
469+ // An async Copy is not fully cleaned up when its target/source metadata is
470+ // merely queued for deletion. Keep a reference until the executor finishes
471+ // the physical delete so RemoveStorage cannot close the backend underneath
472+ // the cleanup task.
473+ struct PendingLocationCleanup {
474+ std::string instance_id;
475+ std::string storage_name;
476+ std::future<PlanExecuteResult> future;
477+ };
478+
466479 struct ExpiringMark {
467480 int64_t deadline_ms = 0 ;
468481 std::string instance_id;
@@ -517,10 +530,15 @@ class MigrationManager : public std::enable_shared_from_this<MigrationManager> {
517530 bool ResumePendingGuardFinalization (const CopyTaskContext &ctx);
518531 bool PersistRemoteAsyncCopyAcceptance (const std::string &instance_id,
519532 int64_t block_key,
533+ size_t expected_items,
520534 const AsyncCopyRemoteSubmitResult &remote_result,
521535 CopyTaskContext &out_ctx,
522536 bool &out_cancel_requested);
523537 void SubmitPreparedTargetLocationDelete (const CopyTaskContext &ctx);
538+ void TrackLocationCleanup (const std::string &instance_id,
539+ const std::string &storage_name,
540+ std::future<PlanExecuteResult> future);
541+ void ProcessCompletedLocationCleanups ();
524542 bool ReserveAsyncCopyCredit (const MigrationRequest &request, uint64_t total_bytes);
525543 void ReleaseAsyncCopyCredit (const CopyTaskContext &ctx);
526544 void MoveAsyncCopyCreditToQuarantine (const CopyTaskContext &ctx, const std::string &reason);
@@ -682,6 +700,8 @@ class MigrationManager : public std::enable_shared_from_this<MigrationManager> {
682700 std::mutex pending_mutex_;
683701 std::condition_variable pending_cv_;
684702 std::deque<PendingCopy> pending_copies_;
703+ mutable std::mutex pending_cleanup_mutex_;
704+ std::deque<PendingLocationCleanup> pending_location_cleanups_;
685705
686706 std::mutex mark_expiry_mutex_;
687707 std::priority_queue<ExpiringMark, std::vector<ExpiringMark>, ExpiringMarkGreater> mark_expiry_queue_;
0 commit comments