summaryrefslogtreecommitdiffstats
path: root/configserver
diff options
context:
space:
mode:
authorHarald Musum <musum@oath.com>2018-04-04 08:38:25 +0200
committerHarald Musum <musum@oath.com>2018-04-04 08:38:25 +0200
commitc020900d7aa020a1d434a0bcfe06f4d43840ac08 (patch)
tree2ae18b0564d43d1828ae3e07d71f5675196474c5 /configserver
parent99c4a2573660d7bbb0fea00444a8177f2c8acd43 (diff)
Handle adding file reference where existing dir has invalid content
Diffstat (limited to 'configserver')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/filedistribution/FileDirectory.java33
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/filedistribution/FileDirectoryTest.java27
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);