diff options
author | Harald Musum <musum@oath.com> | 2018-04-04 08:38:25 +0200 |
---|---|---|
committer | Harald Musum <musum@oath.com> | 2018-04-04 08:38:25 +0200 |
commit | c020900d7aa020a1d434a0bcfe06f4d43840ac08 (patch) | |
tree | 2ae18b0564d43d1828ae3e07d71f5675196474c5 /configserver | |
parent | 99c4a2573660d7bbb0fea00444a8177f2c8acd43 (diff) |
Handle adding file reference where existing dir has invalid content
Diffstat (limited to 'configserver')
2 files changed, 55 insertions, 5 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileDirectory.java b/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileDirectory.java index 432cbc4d997..861f920e41e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileDirectory.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileDirectory.java @@ -101,18 +101,42 @@ public class FileDirectory { public FileReference addFile(File source) { try { Long hash = computeReference(source); - FileReference reference = new FileReference(Long.toHexString(hash)); - return addFile(source, reference); + verifyExistingFile(hash); + FileReference fileReference = fileReferenceFromHash(hash); + return addFile(source, fileReference); } catch (IOException e) { throw new IllegalArgumentException(e); } } + // If there is exists a directory for a file reference, but it does not have correct hash, we delete everything in it + private void verifyExistingFile(Long hashOfFileToBeAdded) throws IOException { + FileReference fileReference = fileReferenceFromHash(hashOfFileToBeAdded); + File destinationDir = destinationDir(fileReference); + if (!destinationDir.exists()) return; + + Long hashOfExistingFileReference = computeReference(destinationDir); + if (hashOfExistingFileReference.longValue() != hashOfFileToBeAdded.longValue()) { + log.log(LogLevel.ERROR, "Directory for file reference ' " + fileReference.value() + + "' has content that does not match its hash, deleting everything in " + + destinationDir.getAbsolutePath()); + IOUtils.recursiveDeleteDir(destinationDir); + } + } + + private File destinationDir(FileReference fileReference) { + return new File(root, fileReference.value()); + } + + private FileReference fileReferenceFromHash(Long hash) { + return new FileReference(Long.toHexString(hash)); + } + FileReference addFile(File source, FileReference reference) { ensureRootExist(); try { logfileInfo(source); - File destinationDir = new File(root, reference.value()); + File destinationDir = destinationDir(reference); Path tempDestinationDir = Files.createTempDirectory(root.toPath(), "writing"); File destination = new File(tempDestinationDir.toFile(), source.getName()); if (!destinationDir.exists()) { @@ -121,8 +145,9 @@ public class FileDirectory { if (source.isDirectory()) { log.log(LogLevel.DEBUG, "Copying source " + source.getAbsolutePath() + " to " + destination.getAbsolutePath()); IOUtils.copyDirectory(source, destination, -1); - } else + } else { copyFile(source, destination); + } if (!destinationDir.exists()) { log.log(LogLevel.DEBUG, "Moving from " + tempDestinationDir + " to " + destinationDir.getAbsolutePath()); if ( ! tempDestinationDir.toFile().renameTo(destinationDir)) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/filedistribution/FileDirectoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/filedistribution/FileDirectoryTest.java index 9b1d018f892..d35c6654658 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/filedistribution/FileDirectoryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/filedistribution/FileDirectoryTest.java @@ -11,6 +11,8 @@ import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -39,7 +41,6 @@ public class FileDirectoryTest { assertEquals("2b8e97f15c854e1d", bar.value()); } - @Test public void requireThatFileReferenceWithSubDirectoriesWorks() throws IOException { FileDirectory fileDirectory = new FileDirectory(temporaryFolder.getRoot()); @@ -64,6 +65,30 @@ public class FileDirectoryTest { assertEquals("9ca074b47a4b510c", fileReference.value()); } + @Test + public void requireThatExistingDirWithInvalidContentIsDeleted() throws IOException { + FileDirectory fileDirectory = new FileDirectory(temporaryFolder.getRoot()); + + String subdirName = "subdir"; + File subDirectory = new File(temporaryFolder.getRoot(), subdirName); + createFileInSubDir(subDirectory, "foo"); + FileReference fileReference = fileDirectory.addFile(subDirectory); + File dir = fileDirectory.getFile(fileReference); + assertTrue(dir.exists()); + assertTrue(new File(dir, "foo").exists()); + assertFalse(new File(dir, "doesnotexist").exists()); + assertEquals("1315a322fc323608", fileReference.value()); + + // Remove a file, directory should be deleted before adding a new file + Files.delete(Paths.get(fileDirectory.getPath(fileReference)).resolve("subdir").resolve("foo")); + fileReference = fileDirectory.addFile(subDirectory); + dir = fileDirectory.getFile(fileReference); + assertTrue(dir.exists()); + assertTrue(new File(dir, "foo").exists()); + assertFalse(new File(dir, "doesnotexist").exists()); + assertEquals("1315a322fc323608", fileReference.value()); + } + // Content in created file is equal to the filename string private FileReference createFile(String filename) throws IOException { File file = temporaryFolder.newFile(filename); |