@@ -548,8 +548,6 @@ void StorageMergeTree::exportPartitionToTable(const PartitionCommand & command,
548548 return ;
549549 }
550550
551- std::vector<std::shared_ptr<CurrentlyExportingPartsTagger>> taggers;
552-
553551 {
554552 // / Do not put this in a scope because `CurrentlyExportingPartsTagger` instantiated above relies on this already being locked
555553 // / shitty design I came up with huh
@@ -559,12 +557,11 @@ void StorageMergeTree::exportPartitionToTable(const PartitionCommand & command,
559557 {
560558 throw Exception (ErrorCodes::PART_IS_LOCKED, " Partition {} has already been exported" , partition_id);
561559 }
562-
563- taggers.reserve (all_parts.size ());
564560
565561 for (const auto & part : all_parts)
566562 {
567- taggers.push_back (std::make_shared<CurrentlyExportingPartsTagger>(part, *this ));
563+ if (!currently_merging_mutating_parts.emplace (part).second )
564+ throw Exception (ErrorCodes::LOGICAL_ERROR, " Tagging already tagged part {}. This is a bug." , part->name );
568565 }
569566 }
570567
@@ -584,14 +581,7 @@ void StorageMergeTree::exportPartitionToTable(const PartitionCommand & command,
584581 export_partition_transaction_id_to_manifest[transaction_id] = manifest;
585582 }
586583
587- for (const auto & tagger : taggers)
588- {
589- auto task = std::make_shared<ExportPartPlainMergeTreeTask>(*this , tagger, dest_storage, getContext (), manifest, moves_assignee_trigger);
590- if (!background_moves_assignee.scheduleMoveTask (task))
591- {
592- LOG_ERROR (log, " Failed to schedule export task for part {}" , tagger->part_to_export ->name );
593- }
594- }
584+ background_moves_assignee.trigger ();
595585}
596586
597587// / While exists, marks parts as 'currently_merging_mutating_parts' and reserves free space on filesystem.
@@ -1198,58 +1188,53 @@ void StorageMergeTree::readExportPartitionManifests()
11981188 }
11991189 }
12001190 }
1191+
1192+ background_moves_assignee.trigger ();
12011193}
12021194
12031195void StorageMergeTree::resumeExportPartitionTasks ()
12041196{
12051197 // / Initially I opted for having two separate methods: read and resume because I wanted to schedule the tasks in order
12061198 // / but it turns out the background executor schedules tasks based on their priority, so it is likely this is not needed anymore.
1207- for (const auto & [transaction_id, manifest] : export_partition_transaction_id_to_manifest)
1208- {
1209- if (manifest->status != MergeTreeExportManifest::Status::pending)
1210- continue ;
1199+ // for (const auto & [transaction_id, manifest] : export_partition_transaction_id_to_manifest)
1200+ // {
1201+ // if (manifest->status != MergeTreeExportManifest::Status::pending)
1202+ // continue;
12111203
1212- auto destination_storage = DatabaseCatalog::instance ().tryGetTable (manifest->destination_storage_id , getContext ());
1213- if (!destination_storage)
1214- {
1215- LOG_ERROR (log, " Failed to reconstruct destination storage: {}" , manifest->destination_storage_id .getNameForLogs ());
1216- continue ;
1217- }
1204+ // auto destination_storage = DatabaseCatalog::instance().tryGetTable(manifest->destination_storage_id, getContext());
1205+ // if (!destination_storage)
1206+ // {
1207+ // LOG_ERROR(log, "Failed to reconstruct destination storage: {}", manifest->destination_storage_id.getNameForLogs());
1208+ // continue;
1209+ // }
12181210
1219- auto pending_part_names = manifest->pendingParts ();
1211+ // auto pending_part_names = manifest->pendingParts();
12201212
1221- // / apparently, it is possible that pending parts are empty
1222- // / if it is empty, I have to somehow commit and mark as completed..
1213+ // /// apparently, it is possible that pending parts are empty
1214+ // /// if it is empty, I have to somehow commit and mark as completed..
12231215
1224- std::vector<DataPartPtr> parts_to_export;
1216+ // std::vector<DataPartPtr> parts_to_export;
12251217
1226- for (const auto & part_name : pending_part_names)
1227- {
1228- auto part = getPartIfExists (part_name, {MergeTreeDataPartState::Active});
1218+ // for (const auto & part_name : pending_part_names)
1219+ // {
1220+ // auto part = getPartIfExists(part_name, {MergeTreeDataPartState::Active});
12291221
1230- if (!part)
1231- {
1232- LOG_ERROR (log, " Part {} is present in the manifest file {}, but not found in the storage {}" ,
1233- part_name,
1234- manifest->transaction_id ,
1235- getStorageID ().getNameForLogs ());
1236- manifest->status = MergeTreeExportManifest::Status::failed;
1237- manifest->write ();
1238-
1239- already_exported_partition_ids.erase (manifest->partition_id );
1240- continue ;
1241- }
1222+ // if (!part)
1223+ // {
1224+ // LOG_ERROR(log, "Part {} is present in the manifest file {}, but not found in the storage {}",
1225+ // part_name,
1226+ // manifest->transaction_id,
1227+ // getStorageID().getNameForLogs());
1228+ // manifest->status = MergeTreeExportManifest::Status::failed;
1229+ // manifest->write();
12421230
1243- parts_to_export.emplace_back (part);
1244- }
1231+ // already_exported_partition_ids.erase(manifest->partition_id);
1232+ // continue;
1233+ // }
12451234
1246- for (const auto & part : parts_to_export)
1247- {
1248- auto tagger = std::make_shared<CurrentlyExportingPartsTagger>(part, *this );
1249- auto task = std::make_shared<ExportPartPlainMergeTreeTask>(*this , tagger, destination_storage, getContext (), manifest, moves_assignee_trigger);
1250- background_moves_assignee.scheduleMoveTask (task);
1251- }
1252- }
1235+ // parts_to_export.emplace_back(part);
1236+ // }
1237+ // }
12531238}
12541239
12551240void StorageMergeTree::loadExportPartition ()
@@ -1662,6 +1647,57 @@ UInt32 StorageMergeTree::getMaxLevelInBetween(const PartProperties & left, const
16621647 return level;
16631648}
16641649
1650+
1651+ bool StorageMergeTree::scheduleDataMovingJob (BackgroundJobsAssignee & assignee)
1652+ {
1653+ if (MergeTreeData::scheduleDataMovingJob (assignee))
1654+ {
1655+ return true ;
1656+ }
1657+
1658+ // / Try to schedule one export part task if any pending export exists
1659+ {
1660+ std::lock_guard lock (export_partition_transaction_id_to_manifest_mutex);
1661+ for (const auto & [transaction_id, manifest] : export_partition_transaction_id_to_manifest)
1662+ {
1663+ if (manifest->status != MergeTreeExportManifest::Status::pending)
1664+ continue ;
1665+
1666+ auto destination_storage = DatabaseCatalog::instance ().tryGetTable (manifest->destination_storage_id , getContext ());
1667+ if (!destination_storage)
1668+ {
1669+ LOG_ERROR (log, " Failed to reconstruct destination storage: {}" , manifest->destination_storage_id .getNameForLogs ());
1670+ continue ;
1671+ }
1672+
1673+ for (auto & item : manifest->items )
1674+ {
1675+ if (item.in_progress )
1676+ continue ;
1677+
1678+ auto part = getPartIfExists (item.part_name , {MergeTreeDataPartState::Active});
1679+ if (!part)
1680+ {
1681+ LOG_ERROR (log, " Part {} is present in the manifest file {}, but not found in the storage {}" ,
1682+ item.part_name ,
1683+ manifest->transaction_id ,
1684+ getStorageID ().getNameForLogs ());
1685+ manifest->status = MergeTreeExportManifest::Status::failed;
1686+ manifest->write ();
1687+ already_exported_partition_ids.erase (manifest->partition_id );
1688+ continue ;
1689+ }
1690+
1691+ auto task = std::make_shared<ExportPartPlainMergeTreeTask>(*this , part, destination_storage, getContext (), manifest, moves_assignee_trigger);
1692+ item.in_progress = background_moves_assignee.scheduleMoveTask (task);
1693+ return true ;
1694+
1695+ }
1696+ }
1697+ }
1698+ return false ;
1699+ }
1700+
16651701bool StorageMergeTree::scheduleDataProcessingJob (BackgroundJobsAssignee & assignee)
16661702{
16671703 if (shutdown_called)
@@ -2949,8 +2985,8 @@ MutationCounters StorageMergeTree::getMutationCounters() const
29492985
29502986void StorageMergeTree::startBackgroundMovesIfNeeded ()
29512987{
2952- if (areBackgroundMovesNeeded ())
2953- background_moves_assignee.start ();
2988+ // if (areBackgroundMovesNeeded())
2989+ background_moves_assignee.start ();
29542990}
29552991
29562992std::unique_ptr<MergeTreeSettings> StorageMergeTree::getDefaultSettings () const
0 commit comments