| 1497 | } |
| 1498 | |
| 1499 | void IMergeTreeDataPart::removeImpl(bool keep_shared_data) const |
| 1500 | { |
| 1501 | /// load checksums before move any part files |
| 1502 | ChecksumsPtr checksums; |
| 1503 | try |
| 1504 | { |
| 1505 | checksums = getChecksums(); |
| 1506 | |
| 1507 | /// load checksums for projections parts before removing parent part. |
| 1508 | for (const auto & [ _, projection_part] : projection_parts) |
| 1509 | projection_part->getChecksums(); |
| 1510 | } |
| 1511 | catch(const Exception & e) |
| 1512 | { |
| 1513 | if (e.code() == ErrorCodes::NO_FILE_IN_DATA_PART) |
| 1514 | { |
| 1515 | LOG_WARNING(storage.log, "No checksum.txt when getting part's checksums, most likely the part is generated by an aborted task."); |
| 1516 | } |
| 1517 | else |
| 1518 | throw; |
| 1519 | } |
| 1520 | |
| 1521 | // remove deleted files in checksums to avoid removing the deleted columns/projections |
| 1522 | if (checksums) |
| 1523 | { |
| 1524 | for (auto it = checksums->files.begin(); it != checksums->files.end();) |
| 1525 | { |
| 1526 | const auto & file = it->second; |
| 1527 | if (file.is_deleted) |
| 1528 | it = checksums->files.erase(it); |
| 1529 | else |
| 1530 | ++it; |
| 1531 | } |
| 1532 | } |
| 1533 | |
| 1534 | /** Atomic directory removal: |
| 1535 | * - rename directory to temporary name; |
| 1536 | * - remove it recursive. |
| 1537 | * |
| 1538 | * For temporary name we use "delete_tmp_" prefix. |
| 1539 | * |
| 1540 | * NOTE: We cannot use "tmp_delete_" prefix, because there is a second thread, |
| 1541 | * that calls "clearOldTemporaryDirectories" and removes all directories, that begin with "tmp_" and are old enough. |
| 1542 | * But when we removing data part, it can be old enough. And rename doesn't change mtime. |
| 1543 | * And a race condition can happen that will lead to "File not found" error here. |
| 1544 | */ |
| 1545 | |
| 1546 | fs::path from = fs::path(storage.getRelativeDataPath(location)) / relative_path; |
| 1547 | fs::path to = fs::path(storage.getRelativeDataPath(location)) / ("delete_tmp_" + name); |
| 1548 | // TODO directory delete_tmp_<name> is never removed if server crashes before returning from this function |
| 1549 | |
| 1550 | auto disk = volume->getDisk(); |
| 1551 | if (disk->exists(to)) |
| 1552 | { |
| 1553 | LOG_WARNING(storage.log, "Directory {} (to which part must be renamed before removing) already exists. Most likely this is due to unclean restart. Removing it.", fullPath(disk, to)); |
| 1554 | try |
| 1555 | { |
| 1556 | disk->removeSharedRecursive(fs::path(to) / "", keep_shared_data); |
nothing calls this directly
no test coverage detected