Source:
<code>public void handleFileChangeForDirectory(WatchedDirectoryConfig config) throws Exception { if (!agentLock.tryLock(45, TimeUnit.SECONDS)) { LOG.warn("Failed to acquire lock for reload"); throw new LockTimeoutException("Timed out waiting to acquire lock for reload", agentLock); } try { List<Path> destinationFiles = getFilesInDirectory(config.getDestinationAsPath()); for (Path path : destinationFiles) { filesystemConfigHelper.backupFile(path.toAbsolutePath().toString()); } LOG.info("Backed up files in {}", destinationFiles.size(), config.getDestination()); try { LOG.info("Copying files from to {}", config.getSource(), config.getDestination()); List<Path> toCopy = getFilesInDirectory(config.getSourceAsPath()); for (Path from : toCopy) { Path to = Paths.get(from.toAbsolutePath().toString().replace(config.getSource(), config.getDestination())); Files.copy(from, to); } LOG.info("Copied files to {}", toCopy.size(), config.getDestination()); filesystemConfigHelper.checkAndReloadUnlocked(); LOG.info("File copy succeeded for {}", config); fileCopyErrorMessage.set(null); } catch (Exception e) { fileCopyErrorMessage.set(e.getMessage()); List<Path> toCleanUp = getFilesInDirectory(config.getDestinationAsPath()); for (Path path : toCleanUp) { Path absolute = path.toAbsolutePath(); if (filesystemConfigHelper.isBackupFile(absolute.toString())) { <START> Files.delete(absolute); <END> } else { filesystemConfigHelper.restoreFile(absolute.toString()); } } LOG.info("Cleaned up files in due to exception", toCleanUp.size(), config.getDestination()); throw e; } } finally { agentLock.unlock(); } }</code><technical_language>this potentially restoration fail if a backup is deleted restored, depending order of paths getFilesInDirectory? If so, do this a restoration pass a backup cleanup pass? Also, do need recreate backups of restored files here, in case of exception loop that? If so, backup cleanup pass a backups of restored files pass</technical_language>

Target:
public void handleFileChangeForDirectory(WatchedDirectoryConfig config) throws Exception { try { if (!agentLock.tryLock(45, TimeUnit.SECONDS)) { LOG.warn("Failed to acquire lock for reload"); throw new LockTimeoutException("Timed out waiting to acquire lock for reload", agentLock); } List<Path> backedUpFiles = new ArrayList<>(); List<Path> newCopiedFiles = new ArrayList<>(); try { List<Path> destinationFiles = getFilesInDirectory(config.getDestinationAsPath()); for (Path path : destinationFiles) { LOG.info("Backing up {}", path); filesystemConfigHelper.backupFile(path.toAbsolutePath().toString()); backedUpFiles.add(path); } LOG.info("Backed up files in {}", destinationFiles.size(), config.getDestination()); LOG.info("Files in destination dir are now {}", getFilesInDirectory(config.getDestinationAsPath())); try { LOG.info("Copying files from to {}", config.getSource(), config.getDestination()); List<Path> toCopy = getFilesInDirectory(config.getSourceAsPath()); for (Path from : toCopy) { Path to = config.getDestinationAsPath().resolve(from.getFileName().toString()); LOG.info("Copying to {}", from, to); Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING); newCopiedFiles.add(to); } LOG.info("Copied files to {}", toCopy.size(), config.getDestination()); LOG.info("Files in destination dir are now {}", getFilesInDirectory(config.getDestinationAsPath())); filesystemConfigHelper.checkAndReloadUnlocked(); LOG.info("File copy succeeded for {}", config); fileCopyErrorMessage.set(null); } catch (Exception e) { fileCopyErrorMessage.set(e.getMessage()); for (Path path : newCopiedFiles) { if (Files.exists(path)) { LOG.info("Deleting possibly invalid file {}", path); Files.delete(path); } } for (Path path : backedUpFiles) { LOG.info("Restoring file {}", path); filesystemConfigHelper.restoreFile(path.toString()); } LOG.info("Files in destination dir are now {}", getFilesInDirectory(config.getDestinationAsPath())); throw e; } } finally { agentLock.unlock(); } } finally { removePending(config); } }