presto-raptor-legacy/src/main/java/io/prestosql/plugin/raptor/legacy/storage/ShardRecoveryManager.java/ShardRecoveryManager/restoreFromBackup
class ShardRecoveryManager:    @VisibleForTesting
    void restoreFromBackup(UUID shardUuid, long shardSize, OptionalLong shardXxhash64)
    {
        File storageFile = storageService.getStorageFile(shardUuid);

        if (!backupStore.get().shardExists(shardUuid)) {
            stats.incrementShardRecoveryBackupNotFound();
            throw new PrestoException(RAPTOR_RECOVERY_ERROR, "No backup file found for shard: " + shardUuid);
        }

        if (storageFile.exists()) {
            if (!isFileCorrupt(storageFile, shardSize, shardXxhash64)) {
                return;
            }
            stats.incrementCorruptLocalFile();
            quarantineFile(shardUuid, storageFile, "Local file is corrupt.");
        }

        // create a temporary file in the staging directory
        File stagingFile = temporarySuffix(storageService.getStagingFile(shardUuid));
        storageService.createParents(stagingFile);

        // copy to temporary file
        log.info("Copying shard %s from backup...", shardUuid);
        long start = System.nanoTime();

        try {
            backupStore.get().restoreShard(shardUuid, stagingFile);
        }
        catch (PrestoException e) {
            stats.incrementShardRecoveryFailure();
            stagingFile.delete();
            throw e;
        }

        Duration duration = nanosSince(start);
        DataSize size = succinctBytes(stagingFile.length());
        DataSize rate = dataRate(size, duration).convertToMostSuccinctDataSize();
        stats.addShardRecoveryDataRate(rate, size, duration);

        log.info("Copied shard %s from backup in %s (%s at %s/s)", shardUuid, duration, size, rate);

        // move to final location
        storageService.createParents(storageFile);
        try {
            Files.move(stagingFile.toPath(), storageFile.toPath(), ATOMIC_MOVE);
        }
        catch (FileAlreadyExistsException e) {
            // someone else already created it (should not happen, but safe to ignore)
        }
        catch (IOException e) {
            stats.incrementShardRecoveryFailure();
            throw new PrestoException(RAPTOR_RECOVERY_ERROR, "Failed to move shard: " + shardUuid, e);
        }
        finally {
            stagingFile.delete();
        }

        if (!storageFile.exists()) {
            stats.incrementShardRecoveryFailure();
            throw new PrestoException(RAPTOR_RECOVERY_ERROR, "File does not exist after recovery: " + shardUuid);
        }

        if (isFileCorrupt(storageFile, shardSize, shardXxhash64)) {
            stats.incrementShardRecoveryFailure();
            stats.incrementCorruptRecoveredFile();
            quarantineFile(shardUuid, storageFile, "Local file is corrupt after recovery.");
            throw new PrestoException(RAPTOR_BACKUP_CORRUPTION, "Backup is corrupt after read: " + shardUuid);
        }

        stats.incrementShardRecoverySuccess();
    }