summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@verizonmedia.com>2020-03-27 19:51:39 +0100
committerHåkon Hallingstad <hakon@verizonmedia.com>2020-03-27 19:51:39 +0100
commit890c7594b2c2da2dd8eb18939696fdf8fc0ea274 (patch)
treec0883810627e2abfcafa5ea19ce7cdb4b3899146
parenta51ae610f0a825315b56dce1c6015b34fdd411b9 (diff)
UnixPath support for atomicWrite, getFilename, getParent, setLastModifiedTime
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java48
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java42
2 files changed, 80 insertions, 10 deletions
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java
index 268e0a5ccfd..f6eb7190db3 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java
@@ -11,6 +11,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
@@ -37,22 +38,33 @@ import static com.yahoo.yolean.Exceptions.uncheck;
public class UnixPath {
private final Path path;
- public UnixPath(Path path) {
- this.path = path;
- }
+ public UnixPath(Path path) { this.path = path; }
+ public UnixPath(String path) { this(Paths.get(path)); }
- public UnixPath(String path) {
- this(Paths.get(path));
- }
+ public Path toPath() { return path; }
+ public UnixPath resolve(String relativeOrAbsolutePath) { return new UnixPath(path.resolve(relativeOrAbsolutePath)); }
+
+ public UnixPath getParent() {
+ Path parentPath = path.getParent();
+ if (parentPath == null) {
+ throw new IllegalStateException("Path has no parent directory: '" + path + "'");
+ }
- public Path toPath() {
- return path;
+ return new UnixPath(parentPath);
}
- public boolean exists() {
- return Files.exists(path);
+ public String getFilename() {
+ Path filename = path.getFileName();
+ if (filename == null) {
+ // E.g. "/".
+ throw new IllegalStateException("Path has no filename: '" + path.toString() + "'");
+ }
+
+ return filename.toString();
}
+ public boolean exists() { return Files.exists(path); }
+
public String readUtf8File() {
return new String(readBytes(), StandardCharsets.UTF_8);
}
@@ -91,6 +103,18 @@ public class UnixPath {
return this;
}
+ public void atomicWriteUt8(String content) {
+ atomicWriteBytes(content.getBytes(StandardCharsets.UTF_8));
+ }
+
+ /** Write a file to the same dir as this, and then atomically move it to this' path. */
+ public void atomicWriteBytes(byte[] content) {
+ Path tempPath = path.getParent().resolve(path.getFileName() + ".10Ia2f4N5");
+ UnixPath temporaryPath = getParent().resolve(getFilename() + ".10Ia2f4N5");
+ temporaryPath.writeBytes(content);
+ temporaryPath.atomicMove(path);
+ }
+
public String getPermissions() {
return getAttributes().permissions();
}
@@ -135,6 +159,10 @@ public class UnixPath {
return getAttributes().lastModifiedTime();
}
+ public void setLastModifiedTime(Instant instant) {
+ uncheck(() -> Files.setLastModifiedTime(path, FileTime.from(Instant.now())));
+ }
+
public FileAttributes getAttributes() {
PosixFileAttributes attributes = uncheck(() ->
Files.getFileAttributeView(path, PosixFileAttributeView.class).readAttributes());
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java
index 3b839f7f446..3159689c22e 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java
@@ -3,6 +3,7 @@
package com.yahoo.vespa.hosted.node.admin.task.util.file;
import com.yahoo.vespa.test.file.TestFileSystem;
+import org.junit.ComparisonFailure;
import org.junit.Test;
import java.nio.file.FileSystem;
@@ -13,6 +14,7 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* @author hakonhall
@@ -124,4 +126,44 @@ public class UnixPathTest {
assertFalse(dir1 + " deleted recursively", Files.exists(dir1));
}
+ @Test
+ public void atomicWrite() {
+ var path = new UnixPath(fs.getPath("/dir/foo"));
+ path.createParents();
+ path.writeUtf8File("bar");
+ path.atomicWriteUt8("bar v2");
+ assertEquals("bar v2", path.readUtf8File());
+ }
+
+ @Test
+ public void testParentAndFilename() {
+ var absolutePath = new UnixPath("/foo/bar");
+ assertEquals("/foo", absolutePath.getParent().toString());
+ assertEquals("bar", absolutePath.getFilename());
+
+ var pathWithoutSlash = new UnixPath("foo");
+ assertRuntimeException(IllegalStateException.class, "Path has no parent directory: 'foo'", () -> pathWithoutSlash.getParent());
+ assertEquals("foo", pathWithoutSlash.getFilename());
+
+ var pathWithSlash = new UnixPath("/foo");
+ assertEquals("/", pathWithSlash.getParent().toString());
+ assertEquals("foo", pathWithSlash.getFilename());
+
+ assertRuntimeException(IllegalStateException.class, "Path has no parent directory: '/'", () -> new UnixPath("/").getParent());
+ assertRuntimeException(IllegalStateException.class, "Path has no filename: '/'", () -> new UnixPath("/").getFilename());
+ }
+
+ private <T extends RuntimeException> void assertRuntimeException(Class<T> baseClass, String message, Runnable runnable) {
+ try {
+ runnable.run();
+ fail("No exception was thrown");
+ } catch (RuntimeException e) {
+ if (!baseClass.isInstance(e)) {
+ throw new ComparisonFailure("Exception class mismatch", baseClass.getName(), e.getClass().getName());
+ }
+
+ assertEquals(message, e.getMessage());
+ }
+ }
+
}