diff options
author | lberki <lberki@google.com> | 2018-07-09 01:58:09 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-07-09 01:59:10 -0700 |
commit | 325e2ea234418d906778bee4aacea90163e2c311 (patch) | |
tree | 4fd30bc5153f391a61a81e39074eb6fd02b8b222 /src/main/java/com/google/devtools/build/lib/vfs | |
parent | 8f16879813383dad7026757e41111aac6bd8e7a1 (diff) |
Delete UnionFileSystem.
It was used in a single, Google-internal test which I cleaned up as pre-work for this change.
RELNOTES: None.
PiperOrigin-RevId: 203727293
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/vfs')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java | 513 |
1 files changed, 0 insertions, 513 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java b/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java deleted file mode 100644 index 2136633bc6..0000000000 --- a/src/main/java/com/google/devtools/build/lib/vfs/UnionFileSystem.java +++ /dev/null @@ -1,513 +0,0 @@ -// Copyright 2014 The Bazel Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.devtools.build.lib.vfs; - -import com.google.common.base.Preconditions; -import com.google.devtools.build.lib.concurrent.ThreadSafety; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; - -/** - * Presents a unified view of multiple virtual {@link FileSystem} instances, to which requests are - * delegated based on a {@link PathFragment} prefix mapping. If multiple prefixes apply to a given - * path, the *longest* (i.e. most specific) match is used. The order in which the delegates are - * specified does not influence the mapping. - * - * <p>Paths are preserved absolutely, contrary to how "mount" works, e.g.: /foo/bar maps to /foo/bar - * on the delegate, even if it is mounted at /foo. - * - * <p>For example: "/in" maps to InFileSystem, "/" maps to OtherFileSystem. Reading from - * "/in/base/BUILD" through the UnionFileSystem will delegate the read operation to InFileSystem, - * which will read "/in/base/BUILD" relative to its root. ("mount" behavior would remap it to - * "/base/BUILD" on the delegate). - * - * <p>Intra-filesystem symbolic links are resolved to their ultimate targets. Cross-filesystem links - * are not currently supported. - */ -@ThreadSafety.ThreadSafe -public final class UnionFileSystem extends FileSystem { - - private static class FileSystemAndPrefix { - final PathFragment prefix; - final FileSystem fileSystem; - - public FileSystemAndPrefix(PathFragment prefix, FileSystem fileSystem) { - this.prefix = prefix; - this.fileSystem = fileSystem; - } - } - - // List of file systems and their mappings, sorted by prefix length descending. - private final List<FileSystemAndPrefix> fileSystems; - private final FileSystem rootFileSystem; - - // True if the file path is case-sensitive on all the FileSystem - // or False if they are all case-insensitive, otherwise error. - private final boolean isCaseSensitive; - - /** - * Creates a new modifiable UnionFileSystem with prefix mappings specified by a map. - * - * @param prefixMapping map of path prefixes to {@link FileSystem}s - * @param rootFileSystem root for default requests; i.e. mapping of "/" - */ - public UnionFileSystem(Map<PathFragment, FileSystem> prefixMapping, FileSystem rootFileSystem) { - super(); - Preconditions.checkNotNull(prefixMapping); - Preconditions.checkNotNull(rootFileSystem); - Preconditions.checkArgument(rootFileSystem != this, "Circular root filesystem."); - Preconditions.checkArgument( - prefixMapping.keySet().stream().noneMatch(p -> p.getPathString().equals("/")), - "Attempted to specify an explicit root prefix mapping; " - + "please use the rootFileSystem argument instead."); - - this.fileSystems = new ArrayList<>(); - this.rootFileSystem = rootFileSystem; - this.isCaseSensitive = rootFileSystem.isFilePathCaseSensitive(); - - for (Map.Entry<PathFragment, FileSystem> prefix : prefixMapping.entrySet()) { - FileSystem delegate = prefix.getValue(); - Preconditions.checkArgument( - delegate.isFilePathCaseSensitive() == this.isCaseSensitive, - "The case sensitiveness of FileSystem are different in UnionFileSystem"); - PathFragment prefixPath = prefix.getKey(); - - // Extra slash prevents within-directory mappings, which Path can't handle. - fileSystems.add(new FileSystemAndPrefix(prefixPath, delegate)); - } - // Order by length descending. This ensures that more specific mapping takes precedence - // when we try to find the file system of a given path. - Comparator<FileSystemAndPrefix> comparator = - Comparator.comparing(f -> f.prefix.getPathString().length()); - fileSystems.sort(comparator.reversed()); - } - - /** - * Retrieves the filesystem delegate of a path mapping. Does not follow symlinks (but you can call - * on a path preprocessed with {@link #resolveSymbolicLinks} to support this use case). - * - * @param path the {@link Path} to map to a filesystem - * @throws IllegalArgumentException if no delegate exists for the path - */ - FileSystem getDelegate(Path path) { - Preconditions.checkNotNull(path); - FileSystem delegate = null; - // Linearly iterate over each mapped file system and find the one that handles this path. - // For small number of mappings, this will be more efficient than using a trie - for (FileSystemAndPrefix fileSystemAndPrefix : this.fileSystems) { - if (path.startsWith(fileSystemAndPrefix.prefix)) { - delegate = fileSystemAndPrefix.fileSystem; - break; - } - } - return delegate != null ? delegate : rootFileSystem; - } - - // Associates the path with the root of the given delegate filesystem. - // Necessary to avoid null pointer problems inside of the delegates. - Path adjustPath(Path path, FileSystem delegate) { - return delegate.getPath(path.getPathString()); - } - - /** - * Follow a symbolic link once using the appropriate delegate filesystem, also resolving parent - * directory symlinks. - * - * @param path {@link Path} to the symbolic link - */ - @Override - protected PathFragment readSymbolicLink(Path path) throws IOException { - Preconditions.checkNotNull(path); - FileSystem delegate = getDelegate(path); - return delegate.readSymbolicLink(adjustPath(path, delegate)); - } - - @Override - protected PathFragment resolveOneLink(Path path) throws IOException { - Preconditions.checkNotNull(path); - FileSystem delegate = getDelegate(path); - return delegate.resolveOneLink(adjustPath(path, delegate)); - } - - private void checkModifiable(Path path) { - if (!supportsModifications(path)) { - throw new UnsupportedOperationException( - String.format("Modifications to this %s are disabled.", getClass().getSimpleName())); - } - } - - @Override - public boolean supportsModifications(Path path) { - FileSystem delegate = getDelegate(path); - path = adjustPath(path, delegate); - return delegate.supportsModifications(path); - } - - @Override - public boolean supportsSymbolicLinksNatively(Path path) { - FileSystem delegate = getDelegate(path); - path = adjustPath(path, delegate); - return delegate.supportsSymbolicLinksNatively(path); - } - - @Override - public boolean supportsHardLinksNatively(Path path) { - FileSystem delegate = getDelegate(path); - path = adjustPath(path, delegate); - return delegate.supportsHardLinksNatively(path); - } - - @Override - public boolean isFilePathCaseSensitive() { - return isCaseSensitive; - } - - @Override - public String getFileSystemType(Path path) { - try { - path = internalResolveSymlink(path); - } catch (IOException e) { - return "unknown"; - } - FileSystem delegate = getDelegate(path); - return delegate.getFileSystemType(path); - } - - @Override - protected byte[] getDigest(Path path, DigestHashFunction hashFunction) throws IOException { - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - return delegate.getDigest(adjustPath(path, delegate), hashFunction); - } - - @Override - public boolean createDirectory(Path path) throws IOException { - checkModifiable(path); - // When creating the exact directory that is mapped, - // create it on both the parent's delegate and the path's delegate. - // This is necessary both for the parent to see the directory and for the - // delegate to use it. - // This is present to address this problematic case: - // / -> RootFs - // /foo -> FooFs - // mkdir /foo - // ls / ("foo" would be missing if not created on the parent) - // ls /foo (would fail if foo weren't also present on the child) - FileSystem delegate = getDelegate(path); - Path parent = path.getParentDirectory(); - if (parent != null) { - parent = internalResolveSymlink(parent); - FileSystem parentDelegate = getDelegate(parent); - if (parentDelegate != delegate) { - // There's a possibility it already exists on the parent, so don't die - // if the directory can't be created there. - parentDelegate.createDirectory(adjustPath(path, parentDelegate)); - } - } - return delegate.createDirectory(adjustPath(path, delegate)); - } - - @Override - public void createDirectoryAndParents(Path path) throws IOException { - checkModifiable(path); - FileSystem delegate = getDelegate(path); - delegate.createDirectoryAndParents(adjustPath(path, delegate)); - } - - @Override - protected long getFileSize(Path path, boolean followSymlinks) throws IOException { - path = followSymlinks ? internalResolveSymlink(path) : path; - FileSystem delegate = getDelegate(path); - return delegate.getFileSize(adjustPath(path, delegate), false); - } - - @Override - public boolean delete(Path path) throws IOException { - checkModifiable(path); - FileSystem delegate = getDelegate(path); - return delegate.delete(adjustPath(path, delegate)); - } - - @Override - protected long getLastModifiedTime(Path path, boolean followSymlinks) throws IOException { - path = followSymlinks ? internalResolveSymlink(path) : path; - FileSystem delegate = getDelegate(path); - return delegate.getLastModifiedTime(adjustPath(path, delegate), false); - } - - @Override - public void setLastModifiedTime(Path path, long newTime) throws IOException { - path = internalResolveSymlink(path); - checkModifiable(path); - FileSystem delegate = getDelegate(path); - delegate.setLastModifiedTime(adjustPath(path, delegate), newTime); - } - - @Override - protected boolean isSymbolicLink(Path path) { - FileSystem delegate = getDelegate(path); - path = adjustPath(path, delegate); - return delegate.isSymbolicLink(path); - } - - @Override - protected boolean isDirectory(Path path, boolean followSymlinks) { - try { - path = followSymlinks ? internalResolveSymlink(path) : path; - } catch (IOException e) { - return false; - } - FileSystem delegate = getDelegate(path); - return delegate.isDirectory(adjustPath(path, delegate), false); - } - - @Override - protected boolean isFile(Path path, boolean followSymlinks) { - try { - path = followSymlinks ? internalResolveSymlink(path) : path; - } catch (IOException e) { - return false; - } - FileSystem delegate = getDelegate(path); - return delegate.isFile(adjustPath(path, delegate), false); - } - - @Override - protected boolean isSpecialFile(Path path, boolean followSymlinks) { - try { - path = followSymlinks ? internalResolveSymlink(path) : path; - } catch (IOException e) { - return false; - } - FileSystem delegate = getDelegate(path); - return delegate.isSpecialFile(adjustPath(path, delegate), false); - } - - @Override - protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) throws IOException { - checkModifiable(linkPath); - if (!supportsSymbolicLinksNatively(linkPath)) { - throw new UnsupportedOperationException( - "Attempted to create a symlink, but symlink support is disabled."); - } - - FileSystem delegate = getDelegate(linkPath); - delegate.createSymbolicLink(adjustPath(linkPath, delegate), targetFragment); - } - - @Override - protected boolean exists(Path path, boolean followSymlinks) { - try { - path = followSymlinks ? internalResolveSymlink(path) : path; - } catch (IOException e) { - return false; - } - FileSystem delegate = getDelegate(path); - return delegate.exists(adjustPath(path, delegate), false); - } - - @Override - protected FileStatus stat(Path path, boolean followSymlinks) throws IOException { - path = followSymlinks ? internalResolveSymlink(path) : path; - FileSystem delegate = getDelegate(path); - return delegate.stat(adjustPath(path, delegate), false); - } - - // Needs to be overridden for the delegation logic, because the - // UnixFileSystem implements statNullable and stat as separate codepaths. - // More generally, we wish to delegate all filesystem operations. - @Override - protected FileStatus statNullable(Path path, boolean followSymlinks) { - try { - path = followSymlinks ? internalResolveSymlink(path) : path; - } catch (IOException e) { - return null; - } - FileSystem delegate = getDelegate(path); - return delegate.statNullable(adjustPath(path, delegate), false); - } - - @Override - @Nullable - protected FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException { - path = followSymlinks ? internalResolveSymlink(path) : path; - FileSystem delegate = getDelegate(path); - return delegate.statIfFound(adjustPath(path, delegate), false); - } - - /** - * Retrieves the directory entries for the specified path under the assumption that {@code - * resolvedPath} is the resolved path of {@code path} in one of the underlying file systems. - * - * @param path the {@link Path} whose children are to be retrieved - */ - @Override - protected Collection<String> getDirectoryEntries(Path path) throws IOException { - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - Path resolvedPath = adjustPath(path, delegate); - return delegate.getDirectoryEntries(resolvedPath); - } - - // No need for the more complex logic of getDirectoryEntries; it calls it implicitly. - @Override - protected Collection<Dirent> readdir(Path path, boolean followSymlinks) throws IOException { - path = followSymlinks ? internalResolveSymlink(path) : path; - FileSystem delegate = getDelegate(path); - return delegate.readdir(adjustPath(path, delegate), false); - } - - @Override - protected boolean isReadable(Path path) throws IOException { - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - return delegate.isReadable(adjustPath(path, delegate)); - } - - @Override - protected void setReadable(Path path, boolean readable) throws IOException { - path = internalResolveSymlink(path); - checkModifiable(path); - FileSystem delegate = getDelegate(path); - delegate.setReadable(adjustPath(path, delegate), readable); - } - - @Override - protected boolean isWritable(Path path) throws IOException { - if (!supportsModifications(path)) { - return false; - } - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - return delegate.isWritable(adjustPath(path, delegate)); - } - - @Override - public void setWritable(Path path, boolean writable) throws IOException { - checkModifiable(path); - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - delegate.setWritable(adjustPath(path, delegate), writable); - } - - @Override - protected boolean isExecutable(Path path) throws IOException { - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - return delegate.isExecutable(adjustPath(path, delegate)); - } - - @Override - protected void setExecutable(Path path, boolean executable) throws IOException { - path = internalResolveSymlink(path); - checkModifiable(path); - FileSystem delegate = getDelegate(path); - delegate.setExecutable(adjustPath(path, delegate), executable); - } - - @Override - protected byte[] getFastDigest(Path path, DigestHashFunction hashFunction) throws IOException { - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - return delegate.getFastDigest(adjustPath(path, delegate), hashFunction); - } - - @Override - public byte[] getxattr(Path path, String name) throws IOException { - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - return delegate.getxattr(adjustPath(path, delegate), name); - } - - @Override - protected InputStream getInputStream(Path path) throws IOException { - path = internalResolveSymlink(path); - FileSystem delegate = getDelegate(path); - return delegate.getInputStream(adjustPath(path, delegate)); - } - - @Override - protected OutputStream getOutputStream(Path path, boolean append) throws IOException { - path = internalResolveSymlink(path); - checkModifiable(path); - FileSystem delegate = getDelegate(path); - return delegate.getOutputStream(adjustPath(path, delegate), append); - } - - @Override - public void renameTo(Path sourcePath, Path targetPath) throws IOException { - sourcePath = internalResolveSymlink(sourcePath); - FileSystem sourceDelegate = getDelegate(sourcePath); - if (!sourceDelegate.supportsModifications(sourcePath)) { - throw new UnsupportedOperationException( - String.format( - "The filesystem for the source path %s does not support modifications.", - sourcePath.getPathString())); - } - sourcePath = adjustPath(sourcePath, sourceDelegate); - - FileSystem targetDelegate = getDelegate(targetPath); - if (!targetDelegate.supportsModifications(targetPath)) { - throw new UnsupportedOperationException( - String.format( - "The filesystem for the target path %s does not support modifications.", - targetPath.getPathString())); - } - targetPath = adjustPath(targetPath, targetDelegate); - - if (sourceDelegate == targetDelegate) { - // Easy, same filesystem. - sourceDelegate.renameTo(sourcePath, targetPath); - return; - } else { - // Copy across filesystems, then delete. - // copyFile throws on failure, so delete will never be reached if it fails. - FileSystemUtils.copyFile(sourcePath, targetPath); - sourceDelegate.delete(sourcePath); - } - } - - @Override - protected void createFSDependentHardLink(Path linkPath, Path originalPath) throws IOException { - checkModifiable(linkPath); - - originalPath = internalResolveSymlink(originalPath); - FileSystem originalDelegate = getDelegate(originalPath); - FileSystem linkDelegate = getDelegate(linkPath); - - if (!originalDelegate.equals(linkDelegate) - || !linkDelegate.supportsHardLinksNatively(linkPath)) { - throw new UnsupportedOperationException( - "Attempted to create a hard link, but hard link support is disabled."); - } - linkDelegate.createFSDependentHardLink( - adjustPath(linkPath, linkDelegate), adjustPath(originalPath, originalDelegate)); - } - - private Path internalResolveSymlink(Path path) throws IOException { - while (isSymbolicLink(path)) { - PathFragment pathFragment = resolveOneLink(path); - path = path.getRelative(pathFragment); - } - return path; - } -} |