public ChRootedFs(final AbstractFileSystem fs, final Path theRoot) throws URISyntaxException { super(fs.getUri(), fs.getUri().getScheme(), fs.getUri().getAuthority() != null, fs.getUriDefaultPort()); myFs = fs; myFs.checkPath(theRoot); chRootPathPart = new Path(myFs.getUriPath(theRoot)); chRootPathPartString = chRootPathPart.toUri().getPath(); /* * We are making URI include the chrootedPath: e.g. file:///chrootedPath. * This is questionable since Path#makeQualified(uri, path) ignores * the pathPart of a uri. Since this class is internal we can ignore * this issue but if we were to make it external then this needs * to be resolved. */ // Handle the two cases: // scheme:/// and scheme://authority/ myUri = new URI(myFs.getUri().toString() + (myFs.getUri().getAuthority() == null ? "" : Path.SEPARATOR) + chRootPathPart.toUri().getPath().substring(1)); super.checkPath(theRoot); }
@Override public FSDataOutputStream createInternal(final Path f, final EnumSet<CreateFlag> flag, final FsPermission absolutePermission, final int bufferSize, final short replication, final long blockSize, final Progressable progress, final ChecksumOpt checksumOpt, final boolean createParent) throws AccessControlException, FileAlreadyExistsException, FileNotFoundException, ParentNotDirectoryException, UnsupportedFileSystemException, UnresolvedLinkException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res; try { res = fsState.resolve(getUriPath(f), false); } catch (FileNotFoundException e) { if (createParent) { throw readOnlyMountTable("create", f); } else { throw e; } } assert(res.remainingPath != null); return res.targetFileSystem.createInternal(res.remainingPath, flag, absolutePermission, bufferSize, replication, blockSize, progress, checksumOpt, createParent); }
@Override public FileStatus getFileStatus(final Path f) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(f), true); // FileStatus#getPath is a fully qualified path relative to the root of // target file system. // We need to change it to viewfs URI - relative to root of mount table. // The implementors of RawLocalFileSystem were trying to be very smart. // They implement FileStatus#getOwener lazily -- the object // returned is really a RawLocalFileSystem that expect the // FileStatus#getPath to be unchanged so that it can get owner when needed. // Hence we need to interpose a new ViewFsFileStatus that works around. FileStatus status = res.targetFileSystem.getFileStatus(res.remainingPath); return new ViewFsFileStatus(status, this.makeQualified(f)); }
@Override public FileStatus[] listStatus(final Path f) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(f), true); FileStatus[] statusLst = res.targetFileSystem.listStatus(res.remainingPath); if (!res.isInternalDir()) { // We need to change the name in the FileStatus as described in // {@link #getFileStatus } ChRootedFs targetFs; targetFs = (ChRootedFs) res.targetFileSystem; int i = 0; for (FileStatus status : statusLst) { String suffix = targetFs.stripOutRoot(status.getPath()); statusLst[i++] = new ViewFsFileStatus(status, this.makeQualified( suffix.length() == 0 ? f : new Path(res.resolvedPath, suffix))); } } return statusLst; }
@Override public void createSymlink(final Path target, final Path link, final boolean createParent) throws IOException, UnresolvedLinkException { InodeTree.ResolveResult<AbstractFileSystem> res; try { res = fsState.resolve(getUriPath(link), false); } catch (FileNotFoundException e) { if (createParent) { throw readOnlyMountTable("createSymlink", link); } else { throw e; } } assert(res.remainingPath != null); res.targetFileSystem.createSymlink(target, res.remainingPath, createParent); }
@Override public List<Token<?>> getDelegationTokens(String renewer) throws IOException { List<InodeTree.MountPoint<AbstractFileSystem>> mountPoints = fsState.getMountPoints(); int initialListSize = 0; for (InodeTree.MountPoint<AbstractFileSystem> im : mountPoints) { initialListSize += im.target.targetDirLinkList.length; } List<Token<?>> result = new ArrayList<Token<?>>(initialListSize); for ( int i = 0; i < mountPoints.size(); ++i ) { List<Token<?>> tokens = mountPoints.get(i).target.targetFileSystem.getDelegationTokens(renewer); if (tokens != null) { result.addAll(tokens); } } return result; }
@Test public void testGetFileChecksum() throws AccessControlException , UnresolvedLinkException, IOException { AbstractFileSystem mockAFS = Mockito.mock(AbstractFileSystem.class); InodeTree.ResolveResult<AbstractFileSystem> res = new InodeTree.ResolveResult<AbstractFileSystem>(null, mockAFS , null, new Path("someFile")); @SuppressWarnings("unchecked") InodeTree<AbstractFileSystem> fsState = Mockito.mock(InodeTree.class); Mockito.when(fsState.resolve(Mockito.anyString() , Mockito.anyBoolean())).thenReturn(res); ViewFs vfs = Mockito.mock(ViewFs.class); vfs.fsState = fsState; Mockito.when(vfs.getFileChecksum(new Path("/tmp/someFile"))) .thenCallRealMethod(); vfs.getFileChecksum(new Path("/tmp/someFile")); Mockito.verify(mockAFS).getFileChecksum(new Path("someFile")); }
@Test(timeout = 30000) public void testCreateSnapshot() throws Exception { Path snapRootPath = new Path("/snapPath"); Path chRootedSnapRootPath = new Path( Path.getPathWithoutSchemeAndAuthority(chrootedTo), "snapPath"); AbstractFileSystem baseFs = Mockito.spy(fc.getDefaultFileSystem()); ChRootedFs chRootedFs = new ChRootedFs(baseFs, chrootedTo); Mockito.doReturn(snapRootPath).when(baseFs) .createSnapshot(chRootedSnapRootPath, "snap1"); Assert.assertEquals(snapRootPath, chRootedFs.createSnapshot(snapRootPath, "snap1")); Mockito.verify(baseFs).createSnapshot(chRootedSnapRootPath, "snap1"); }
@Test(timeout = 30000) public void testDeleteSnapshot() throws Exception { Path snapRootPath = new Path("/snapPath"); Path chRootedSnapRootPath = new Path( Path.getPathWithoutSchemeAndAuthority(chrootedTo), "snapPath"); AbstractFileSystem baseFs = Mockito.spy(fc.getDefaultFileSystem()); ChRootedFs chRootedFs = new ChRootedFs(baseFs, chrootedTo); Mockito.doNothing().when(baseFs) .deleteSnapshot(chRootedSnapRootPath, "snap1"); chRootedFs.deleteSnapshot(snapRootPath, "snap1"); Mockito.verify(baseFs).deleteSnapshot(chRootedSnapRootPath, "snap1"); }
@Test(timeout = 30000) public void testRenameSnapshot() throws Exception { Path snapRootPath = new Path("/snapPath"); Path chRootedSnapRootPath = new Path( Path.getPathWithoutSchemeAndAuthority(chrootedTo), "snapPath"); AbstractFileSystem baseFs = Mockito.spy(fc.getDefaultFileSystem()); ChRootedFs chRootedFs = new ChRootedFs(baseFs, chrootedTo); Mockito.doNothing().when(baseFs) .renameSnapshot(chRootedSnapRootPath, "snapOldName", "snapNewName"); chRootedFs.renameSnapshot(snapRootPath, "snapOldName", "snapNewName"); Mockito.verify(baseFs).renameSnapshot(chRootedSnapRootPath, "snapOldName", "snapNewName"); }
@Test public void testWasbAsDefaultFileSystemHasNoPort() throws Exception { try { testAccount = AzureBlobStorageTestAccount.createMock(); Configuration conf = testAccount.getFileSystem().getConf(); String authority = testAccount.getFileSystem().getUri().getAuthority(); URI defaultUri = new URI("wasb", authority, null, null, null); conf.set(FS_DEFAULT_NAME_KEY, defaultUri.toString()); conf.addResource("azure-test.xml"); FileSystem fs = FileSystem.get(conf); assertTrue(fs instanceof NativeAzureFileSystem); assertEquals(-1, fs.getUri().getPort()); AbstractFileSystem afs = FileContext.getFileContext(conf) .getDefaultFileSystem(); assertTrue(afs instanceof Wasb); assertEquals(-1, afs.getUri().getPort()); } finally { FileSystem.closeAll(); } }
/** * This constructor has the signature needed by * {@link AbstractFileSystem#createFileSystem(URI, Configuration)}. * * @param theUri which must be that of ViewFs * @param conf * @throws IOException * @throws URISyntaxException */ ViewFs(final URI theUri, final Configuration conf) throws IOException, URISyntaxException { super(theUri, FsConstants.VIEWFS_SCHEME, false, -1); creationTime = Time.now(); ugi = UserGroupInformation.getCurrentUser(); config = conf; // Now build client side view (i.e. client side mount table) from config. String authority = theUri.getAuthority(); fsState = new InodeTree<AbstractFileSystem>(conf, authority) { @Override protected AbstractFileSystem getTargetFileSystem(final URI uri) throws URISyntaxException, UnsupportedFileSystemException { String pathString = uri.getPath(); if (pathString.isEmpty()) { pathString = "/"; } return new ChRootedFs( AbstractFileSystem.createFileSystem(uri, config), new Path(pathString)); } @Override protected AbstractFileSystem getTargetFileSystem( final INodeDir<AbstractFileSystem> dir) throws URISyntaxException { return new InternalDirOfViewFs(dir, creationTime, ugi, getUri()); } @Override protected AbstractFileSystem getTargetFileSystem(URI[] mergeFsURIList) throws URISyntaxException, UnsupportedFileSystemException { throw new UnsupportedFileSystemException("mergefs not implemented yet"); // return MergeFs.createMergeFs(mergeFsURIList, config); } }; }
@Override public Path resolvePath(final Path f) throws FileNotFoundException, AccessControlException, UnresolvedLinkException, IOException { final InodeTree.ResolveResult<AbstractFileSystem> res; res = fsState.resolve(getUriPath(f), true); if (res.isInternalDir()) { return f; } return res.targetFileSystem.resolvePath(res.remainingPath); }
@Override public boolean delete(final Path f, final boolean recursive) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(f), true); // If internal dir or target is a mount link (ie remainingPath is Slash) if (res.isInternalDir() || res.remainingPath == InodeTree.SlashPath) { throw new AccessControlException( "Cannot delete internal mount table directory: " + f); } return res.targetFileSystem.delete(res.remainingPath, recursive); }
@Override public BlockLocation[] getFileBlockLocations(final Path f, final long start, final long len) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(f), true); return res.targetFileSystem.getFileBlockLocations(res.remainingPath, start, len); }
@Override public FileChecksum getFileChecksum(final Path f) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(f), true); return res.targetFileSystem.getFileChecksum(res.remainingPath); }
@Override public void access(Path path, FsAction mode) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(path), true); res.targetFileSystem.access(res.remainingPath, mode); }
@Override public FileStatus getFileLinkStatus(final Path f) throws AccessControlException, FileNotFoundException, UnsupportedFileSystemException, IOException { InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(f), false); // do not follow mount link return res.targetFileSystem.getFileLinkStatus(res.remainingPath); }
@Override public RemoteIterator<FileStatus> listStatusIterator(final Path f) throws AccessControlException, FileNotFoundException, UnresolvedLinkException, IOException { final InodeTree.ResolveResult<AbstractFileSystem> res = fsState.resolve(getUriPath(f), true); final RemoteIterator<FileStatus> fsIter = res.targetFileSystem.listStatusIterator(res.remainingPath); if (res.isInternalDir()) { return fsIter; } return new RemoteIterator<FileStatus>() { final RemoteIterator<FileStatus> myIter; final ChRootedFs targetFs; { // Init myIter = fsIter; targetFs = (ChRootedFs) res.targetFileSystem; } @Override public boolean hasNext() throws IOException { return myIter.hasNext(); } @Override public FileStatus next() throws IOException { FileStatus status = myIter.next(); String suffix = targetFs.stripOutRoot(status.getPath()); return new ViewFsFileStatus(status, makeQualified( suffix.length() == 0 ? f : new Path(res.resolvedPath, suffix))); } }; }