diff options
author | felly <felly@google.com> | 2018-07-26 07:46:15 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-07-26 07:47:48 -0700 |
commit | 09efb3fb5cbefe48d7c6685b01cfd72f848563c8 (patch) | |
tree | 24f28786c42e6245ff0c8f99391a645d7610d741 /src/main/java/com/google/devtools/build/lib/vfs | |
parent | 74146fdbcc4eb0463e64588a764b22e253a405ac (diff) |
Use the path resolver when dealing with tree artifacts.
RELNOTES: None
PiperOrigin-RevId: 206157591
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs')
4 files changed, 116 insertions, 45 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java index db2660cd26..4ac878aa56 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/FileInfo.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.vfs.inmemoryfs; import com.google.devtools.build.lib.clock.Clock; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; /** @@ -47,7 +48,11 @@ public abstract class FileInfo extends InMemoryContentInfo { return false; } - protected abstract byte[] readContent() throws IOException; + public abstract OutputStream getOutputStream(boolean append) throws IOException; - protected abstract OutputStream getOutputStream(boolean append) throws IOException; + public abstract InputStream getInputStream() throws IOException; + + public abstract byte[] getxattr(String name) throws IOException; + + public abstract byte[] getFastDigest() throws IOException; } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java index 93c4eb294c..155e9762c7 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryContentInfo.java @@ -31,7 +31,7 @@ import java.io.IOException; @ThreadSafe public abstract class InMemoryContentInfo implements FileStatus { - private final Clock clock; + protected final Clock clock; /** * Stores the time when the file was last modified. This is atomically updated @@ -95,7 +95,7 @@ public abstract class InMemoryContentInfo implements FileStatus { * size of links is unspecified. */ @Override - public abstract long getSize() throws IOException; + public abstract long getSize(); /** * Returns the time when the entity denoted by the current object was last diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileInfo.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileInfo.java index 49777190f7..d73c4cc24d 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileInfo.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileInfo.java @@ -14,10 +14,13 @@ package com.google.devtools.build.lib.vfs.inmemoryfs; import com.google.common.base.Preconditions; +import com.google.common.io.ByteStreams; import com.google.devtools.build.lib.clock.Clock; import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; /** @@ -32,7 +35,7 @@ public class InMemoryFileInfo extends FileInfo { */ protected byte[] content; - protected InMemoryFileInfo(Clock clock) { + public InMemoryFileInfo(Clock clock) { super(clock); content = new byte[0]; // New files start out empty. } @@ -43,8 +46,13 @@ public class InMemoryFileInfo extends FileInfo { } @Override - public synchronized byte[] readContent() { - return content.clone(); + public byte[] getxattr(String name) { + return null; + } + + @Override + public byte[] getFastDigest() { + return null; } private synchronized void setContent(byte[] newContent) { @@ -53,44 +61,69 @@ public class InMemoryFileInfo extends FileInfo { } @Override - protected synchronized OutputStream getOutputStream(boolean append) - throws IOException { - OutputStream out = new ByteArrayOutputStream() { - private boolean closed = false; - - @Override - public void write(byte[] data) throws IOException { - Preconditions.checkState(!closed); - super.write(data); - } + public synchronized InputStream getInputStream() { + return new ByteArrayInputStream(content); + } - @Override - public synchronized void write(int dataByte) { - Preconditions.checkState(!closed); - super.write(dataByte); + @Override + public synchronized OutputStream getOutputStream(boolean append) { + OutputStream out = new InMemoryOutputStream(this::setContent); + if (append) { + try (InputStream in = getInputStream()) { + ByteStreams.copy(in, out); + } catch (IOException e) { + throw new IllegalStateException(e); } + } + return out; + } - @Override - public synchronized void write(byte[] data, int offset, int length) { - Preconditions.checkState(!closed); - super.write(data, offset, length); - } + /** + * A {@link ByteArrayOutputStream} which notifiers a callback when it has flushed its data. + */ + public static class InMemoryOutputStream extends ByteArrayOutputStream { + private final IOByteReceiver receiver; + private boolean closed = false; - @Override - public void close() { - flush(); - closed = true; - } + public InMemoryOutputStream(IOByteReceiver receiver) { + this.receiver = receiver; + } - @Override - public void flush() { - setContent(toByteArray().clone()); - } - }; + @Override + public void write(byte[] data) throws IOException { + Preconditions.checkState(!closed); + super.write(data); + } - if (append) { - out.write(readContent()); + @Override + public synchronized void write(int dataByte) { + Preconditions.checkState(!closed); + super.write(dataByte); } - return out; + + @Override + public synchronized void write(byte[] data, int offset, int length) { + Preconditions.checkState(!closed); + super.write(data, offset, length); + } + + @Override + public synchronized void close() throws IOException { + flush(); + closed = true; + } + + @Override + public synchronized void flush() throws IOException { + receiver.accept(toByteArray().clone()); + } + } + + /** + * Similar to {@link com.google.common.base.Receiver}, but allows implementations to throw + * {@link IOException}. + */ + public interface IOByteReceiver { + void accept(byte[] bytes) throws IOException; } } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java index bebe5b380c..f24a3d99a8 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystem.java @@ -25,7 +25,6 @@ import com.google.devtools.build.lib.vfs.FileStatus; import com.google.devtools.build.lib.vfs.FileSystem; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; -import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -51,7 +50,7 @@ import javax.annotation.Nullable; public class InMemoryFileSystem extends FileSystem { private final PathFragment scopeRoot; - private final Clock clock; + protected final Clock clock; // The root inode (a directory). private final InMemoryDirectoryInfo rootInode; @@ -319,13 +318,17 @@ public class InMemoryFileSystem extends FileSystem { if (!create) { throw Error.ENOENT.exception(path); } else { - child = new InMemoryFileInfo(clock); + child = newFile(clock, path); insert(imdi, name, child, path); } } return child; } + protected FileInfo newFile(Clock clock, Path path) { + return new InMemoryFileInfo(clock); + } + /** * Low-level path-to-inode lookup routine. Analogous to path_walk() in many UNIX kernels. Given * 'path', walks the directory tree from the root, resolving all symbolic links, and returns the @@ -462,7 +465,7 @@ public class InMemoryFileSystem extends FileSystem { * Version of stat that returns an inode if the input path stays entirely within this file * system's scope, otherwise throws. */ - private InMemoryContentInfo scopeLimitedStat(Path path, boolean followSymlinks) + protected InMemoryContentInfo scopeLimitedStat(Path path, boolean followSymlinks) throws IOException { if (followSymlinks) { return pathWalk(path, false); @@ -747,12 +750,42 @@ public class InMemoryFileSystem extends FileSystem { throw Error.EACCES.exception(path); } Preconditions.checkState(status instanceof FileInfo); - return new ByteArrayInputStream(((FileInfo) status).readContent()); + return ((FileInfo) status).getInputStream(); + } + } + + @Override + public byte[] getxattr(Path path, String name) throws IOException { + synchronized (this) { + InMemoryContentInfo status = scopeLimitedStat(path, true); + if (status.isDirectory()) { + throw Error.EISDIR.exception(path); + } + if (!path.isReadable()) { + throw Error.EACCES.exception(path); + } + Preconditions.checkState(status instanceof FileInfo); + return ((FileInfo) status).getxattr(name); + } + } + + @Override + protected byte[] getFastDigest(Path path) throws IOException { + synchronized (this) { + InMemoryContentInfo status = scopeLimitedStat(path, true); + if (status.isDirectory()) { + throw Error.EISDIR.exception(path); + } + if (!path.isReadable()) { + throw Error.EACCES.exception(path); + } + Preconditions.checkState(status instanceof FileInfo); + return ((FileInfo) status).getFastDigest(); } } /** Creates a new file at the given path and returns its inode. */ - private InMemoryContentInfo getOrCreateWritableInode(Path path) throws IOException { + protected InMemoryContentInfo getOrCreateWritableInode(Path path) throws IOException { // open(WR_ONLY) of a dangling link writes through the link. That means // that the usual path lookup operations have to behave differently when // resolving a path with the intent to create it: instead of failing with |