| 612 | } |
| 613 | |
| 614 | MergeTreeMetaBase::MutableDataPartPtr MergeTreeMetaBase::cloneAndLoadDataPartOnSameDisk( |
| 615 | const MergeTreeMetaBase::DataPartPtr & src_part, |
| 616 | const String & tmp_part_prefix, |
| 617 | const MergeTreePartInfo & dst_part_info, |
| 618 | const StorageMetadataPtr & metadata_snapshot) |
| 619 | { |
| 620 | /// Check that the storage policy contains the disk where the src_part is located. |
| 621 | bool does_storage_policy_allow_same_disk = false; |
| 622 | for (const DiskPtr & disk : getStoragePolicy(IStorage::StorageLocation::MAIN)->getDisks()) |
| 623 | { |
| 624 | if (disk->getName() == src_part->volume->getDisk()->getName()) |
| 625 | { |
| 626 | does_storage_policy_allow_same_disk = true; |
| 627 | break; |
| 628 | } |
| 629 | } |
| 630 | if (!does_storage_policy_allow_same_disk) |
| 631 | throw Exception( |
| 632 | "Could not clone and load part " + quoteString(src_part->getFullPath()) + " because disk does not belong to storage policy", |
| 633 | ErrorCodes::BAD_ARGUMENTS); |
| 634 | |
| 635 | String dst_part_name = src_part->getNewName(dst_part_info); |
| 636 | String tmp_dst_part_name = tmp_part_prefix + dst_part_name; |
| 637 | |
| 638 | auto reservation = reserveSpace(src_part->getBytesOnDisk(), src_part->volume->getDisk()); |
| 639 | auto disk = reservation->getDisk(); |
| 640 | String src_part_path = src_part->getFullRelativePath(); |
| 641 | String dst_part_path = relative_data_path + tmp_dst_part_name; |
| 642 | |
| 643 | if (disk->exists(dst_part_path)) |
| 644 | throw Exception("Part in " + fullPath(disk, dst_part_path) + " already exists", ErrorCodes::DIRECTORY_ALREADY_EXISTS); |
| 645 | |
| 646 | /// If source part is in memory, flush it to disk and clone it already in on-disk format |
| 647 | if (auto src_part_in_memory = asInMemoryPart(src_part)) |
| 648 | { |
| 649 | const auto & src_relative_data_path = src_part_in_memory->storage.getRelativeDataPath(IStorage::StorageLocation::MAIN); |
| 650 | auto flushed_part_path = src_part_in_memory->getRelativePathForPrefix(tmp_part_prefix, /*is_detach*/false); |
| 651 | src_part_in_memory->flushToDisk(src_relative_data_path, flushed_part_path, metadata_snapshot); |
| 652 | src_part_path = fs::path(src_relative_data_path) / flushed_part_path / ""; |
| 653 | } |
| 654 | |
| 655 | LOG_DEBUG(log, "Cloning part {} to {}", fullPath(disk, src_part_path), fullPath(disk, dst_part_path)); |
| 656 | localBackup(disk, src_part_path, dst_part_path); |
| 657 | disk->removeFileIfExists(fs::path(dst_part_path) / IMergeTreeDataPart::DELETE_ON_DESTROY_MARKER_FILE_NAME); |
| 658 | |
| 659 | auto single_disk_volume = std::make_shared<SingleDiskVolume>(disk->getName(), disk, 0); |
| 660 | auto dst_data_part = createPart(dst_part_name, dst_part_info, single_disk_volume, tmp_dst_part_name); |
| 661 | |
| 662 | dst_data_part->is_temp = true; |
| 663 | |
| 664 | dst_data_part->loadColumnsChecksumsIndexes(require_part_metadata, true); |
| 665 | dst_data_part->modification_time = disk->getLastModified(dst_part_path).epochTime(); |
| 666 | return dst_data_part; |
| 667 | } |
| 668 | |
| 669 | String MergeTreeMetaBase::getFullPathOnDisk(StorageLocation location, const DiskPtr & disk) const |
| 670 | { |
no test coverage detected