Package org.apache.hadoop.fs.viewfs

Source Code of org.apache.hadoop.fs.viewfs.ViewFs$InternalDirOfViewFs

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.hadoop.fs.viewfs;

import static org.apache.hadoop.fs.viewfs.Constants.PERMISSION_RRR;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map.Entry;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.AbstractFileSystem;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.CreateFlag;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileAlreadyExistsException;
import org.apache.hadoop.fs.FileChecksum;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FsConstants;
import org.apache.hadoop.fs.FsServerDefaults;
import org.apache.hadoop.fs.FsStatus;
import org.apache.hadoop.fs.Options.ChecksumOpt;
import org.apache.hadoop.fs.ParentNotDirectoryException;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.fs.UnresolvedLinkException;
import org.apache.hadoop.fs.UnsupportedFileSystemException;
import org.apache.hadoop.fs.local.LocalConfigKeys;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.fs.viewfs.InodeTree.INode;
import org.apache.hadoop.fs.viewfs.InodeTree.INodeLink;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.util.Time;


/**
* ViewFs (extends the AbstractFileSystem interface) implements a client-side
* mount table. The viewFs file system is implemented completely in memory on
* the client side. The client-side mount table allows a client to provide a
* customized view of a file system namespace that is composed from
* one or more individual file systems (a localFs or Hdfs, S3fs, etc).
* For example one could have a mount table that provides links such as
* <ul>
* <li>  /user          -> hdfs://nnContainingUserDir/user
* <li>  /project/foo   -> hdfs://nnProject1/projects/foo
* <li>  /project/bar   -> hdfs://nnProject2/projects/bar
* <li>  /tmp           -> hdfs://nnTmp/privateTmpForUserXXX
* </ul>
*
* ViewFs is specified with the following URI: <b>viewfs:///</b>
* <p>
* To use viewfs one would typically set the default file system in the
* config  (i.e. fs.default.name< = viewfs:///) along with the
* mount table config variables as described below.
*
* <p>
* <b> ** Config variables to specify the mount table entries ** </b>
* <p>
*
* The file system is initialized from the standard Hadoop config through
* config variables.
* See {@link FsConstants} for URI and Scheme constants;
* See {@link Constants} for config var constants;
* see {@link ConfigUtil} for convenient lib.
*
* <p>
* All the mount table config entries for view fs are prefixed by
* <b>fs.viewfs.mounttable.</b>
* For example the above example can be specified with the following
*  config variables:
<ul>
<li> fs.viewfs.mounttable.default.link./user=
*  hdfs://nnContainingUserDir/user
<li> fs.viewfs.mounttable.default.link./project/foo=
*  hdfs://nnProject1/projects/foo
<li> fs.viewfs.mounttable.default.link./project/bar=
*  hdfs://nnProject2/projects/bar
<li> fs.viewfs.mounttable.default.link./tmp=
*  hdfs://nnTmp/privateTmpForUserXXX
</ul>
* The default mount table (when no authority is specified) is
* from config variables prefixed by <b>fs.viewFs.mounttable.default </b>
* The authority component of a URI can be used to specify a different mount
* table. For example,
* <ul>
* <li>  viewfs://sanjayMountable/
* </ul>
* is initialized from fs.viewFs.mounttable.sanjayMountable.* config variables.
*
<p>
<b> **** Merge Mounts **** </b>(NOTE: merge mounts are not implemented yet.)
<p>
*   One can also use "MergeMounts" to merge several directories (this is
*   sometimes  called union-mounts or junction-mounts in the literature.
*   For example of the home directories are stored on say two file systems
*   (because they do not fit on one) then one could specify a mount
*   entry such as following merges two dirs:
*   <ul>
*   <li> /user -> hdfs://nnUser1/user,hdfs://nnUser2/user
*   </ul>
*  Such a mergeLink can be specified with the following config var where ","
*  is used as the separator for each of links to be merged:
<ul>
<li> fs.viewfs.mounttable.default.linkMerge./user=
*  hdfs://nnUser1/user,hdfs://nnUser1/user
</ul>
*   A special case of the merge mount is where mount table's root is merged
*   with the root (slash) of another file system:
*   <ul>
*   <li>    fs.viewfs.mounttable.default.linkMergeSlash=hdfs://nn99/
*   </ul>
*   In this cases the root of the mount table is merged with the root of
*            <b>hdfs://nn99/ </b>
*/

@InterfaceAudience.Public
@InterfaceStability.Evolving /*Evolving for a release,to be changed to Stable */
public class ViewFs extends AbstractFileSystem {
  final long creationTime; // of the the mount table
  final UserGroupInformation ugi; // the user/group of user who created mtable
  final Configuration config;
  InodeTree<AbstractFileSystem> fsState;  // the fs state; ie the mount table
  Path homeDir = null;
 
  static AccessControlException readOnlyMountTable(final String operation,
      final String p) {
    return new AccessControlException(
        "InternalDir of ViewFileSystem is readonly; operation=" + operation +
        "Path=" + p);
  }
  static AccessControlException readOnlyMountTable(final String operation,
      final Path p) {
    return readOnlyMountTable(operation, p.toString());
  }
 
 
  static public class MountPoint {
    private Path src;       // the src of the mount
    private URI[] targets; //  target of the mount; Multiple targets imply mergeMount
    MountPoint(Path srcPath, URI[] targetURIs) {
      src = srcPath;
      targets = targetURIs;
    }
    Path getSrc() {
      return src;
    }
    URI[] getTargets() {
      return targets;
    }
  }
 
  public ViewFs(final Configuration conf) throws IOException,
      URISyntaxException {
    this(FsConstants.VIEWFS_URI, conf);
  }
 
  /**
   * 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 FsServerDefaults getServerDefaults() throws IOException {
    return LocalConfigKeys.getServerDefaults();
  }

  @Override
  public int getUriDefaultPort() {
    return -1;
  }
  @Override
  public Path getHomeDirectory() {
    if (homeDir == null) {
      String base = fsState.getHomeDirPrefixValue();
      if (base == null) {
        base = "/user";
      }
      homeDir = (base.equals("/") ?
        this.makeQualified(new Path(base + ugi.getShortUserName())):
        this.makeQualified(new Path(base + "/" + ugi.getShortUserName())));
    }
    return homeDir;
  }
 
  @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 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 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 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 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 FsStatus getFsStatus() throws AccessControlException,
      FileNotFoundException, IOException {
    return new FsStatus(0, 0, 0);
  }

  @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)));
      }
    };
  }
 
  @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 mkdir(final Path dir, final FsPermission permission,
      final boolean createParent) throws AccessControlException,
      FileAlreadyExistsException,
      FileNotFoundException, UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(dir), false);
    res.targetFileSystem.mkdir(res.remainingPath, permission, createParent);
  }

  @Override
  public FSDataInputStream open(final Path f, final int bufferSize)
      throws AccessControlException, FileNotFoundException,
      UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
        fsState.resolve(getUriPath(f), true);
    return res.targetFileSystem.open(res.remainingPath, bufferSize);
  }

 
  @Override
  public void renameInternal(final Path src, final Path dst,
      final boolean overwrite) throws IOException, UnresolvedLinkException {
    // passing resolveLastComponet as false to catch renaming a mount point
    // itself we need to catch this as an internal operation and fail.
    InodeTree.ResolveResult<AbstractFileSystem> resSrc =
      fsState.resolve(getUriPath(src), false);
 
    if (resSrc.isInternalDir()) {
      throw new AccessControlException(
          "Cannot Rename within internal dirs of mount table: it is readOnly");
    }
     
    InodeTree.ResolveResult<AbstractFileSystem> resDst =
                                fsState.resolve(getUriPath(dst), false);
    if (resDst.isInternalDir()) {
      throw new AccessControlException(
          "Cannot Rename within internal dirs of mount table: it is readOnly");
    }
   
    /**
    // Alternate 1: renames within same file system - valid but we disallow
    // Alternate 2: (as described in next para - valid but we have disallowed it
    //
    // Note we compare the URIs. the URIs include the link targets.
    // hence we allow renames across mount links as long as the mount links
    // point to the same target.
    if (!resSrc.targetFileSystem.getUri().equals(
              resDst.targetFileSystem.getUri())) {
      throw new IOException("Renames across Mount points not supported");
    }
    */
   
    //
    // Alternate 3 : renames ONLY within the the same mount links.
    //

    if (resSrc.targetFileSystem !=resDst.targetFileSystem) {
      throw new IOException("Renames across Mount points not supported");
    }
   
    resSrc.targetFileSystem.renameInternal(resSrc.remainingPath,
      resDst.remainingPath, overwrite);
  }

  @Override
  public void renameInternal(final Path src, final Path dst)
      throws AccessControlException, FileAlreadyExistsException,
      FileNotFoundException, ParentNotDirectoryException,
      UnresolvedLinkException, IOException {
    renameInternal(src, dst, false);
  }
 
  @Override
  public boolean supportsSymlinks() {
    return true;
  }
 
  @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 Path getLinkTarget(final Path f) throws IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(f), false); // do not follow mount link
    return res.targetFileSystem.getLinkTarget(res.remainingPath);
  }

  @Override
  public void setOwner(final Path f, final String username,
      final String groupname) throws AccessControlException,
      FileNotFoundException, UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(f), true);
    res.targetFileSystem.setOwner(res.remainingPath, username, groupname);
  }

  @Override
  public void setPermission(final Path f, final FsPermission permission)
      throws AccessControlException, FileNotFoundException,
      UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(f), true);
    res.targetFileSystem.setPermission(res.remainingPath, permission);
   
  }

  @Override
  public boolean setReplication(final Path f, final short replication)
      throws AccessControlException, FileNotFoundException,
      UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(f), true);
    return res.targetFileSystem.setReplication(res.remainingPath, replication);
  }

  @Override
  public void setTimes(final Path f, final long mtime, final long atime)
      throws AccessControlException, FileNotFoundException,
      UnresolvedLinkException, IOException {
    InodeTree.ResolveResult<AbstractFileSystem> res =
      fsState.resolve(getUriPath(f), true);
    res.targetFileSystem.setTimes(res.remainingPath, mtime, atime);
  }

  @Override
  public void setVerifyChecksum(final boolean verifyChecksum)
      throws AccessControlException, IOException {
    // This is a file system level operations, however ViewFs
    // points to many file systems. Noop for ViewFs.
  }
 
  public MountPoint[] getMountPoints() {
    List<InodeTree.MountPoint<AbstractFileSystem>> mountPoints =
                  fsState.getMountPoints();
   
    MountPoint[] result = new MountPoint[mountPoints.size()];
    for ( int i = 0; i < mountPoints.size(); ++i ) {
      result[i] = new MountPoint(new Path(mountPoints.get(i).src),
                              mountPoints.get(i).target.targetDirLinkList);
    }
    return result;
  }
 
  @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;
  }

  @Override
  public boolean isValidName(String src) {
    // Prefix validated at mount time and rest of path validated by mount target.
    return true;
  }

 
 
  /*
   * An instance of this class represents an internal dir of the viewFs
   * ie internal dir of the mount table.
   * It is a ready only mount tbale and create, mkdir or delete operations
   * are not allowed.
   * If called on create or mkdir then this target is the parent of the
   * directory in which one is trying to create or mkdir; hence
   * in this case the path name passed in is the last component.
   * Otherwise this target is the end point of the path and hence
   * the path name passed in is null.
   */
  static class InternalDirOfViewFs extends AbstractFileSystem {
   
    final InodeTree.INodeDir<AbstractFileSystem>  theInternalDir;
    final long creationTime; // of the the mount table
    final UserGroupInformation ugi; // the user/group of user who created mtable
    final URI myUri; // the URI of the outer ViewFs
   
    public InternalDirOfViewFs(final InodeTree.INodeDir<AbstractFileSystem> dir,
        final long cTime, final UserGroupInformation ugi, final URI uri)
      throws URISyntaxException {
      super(FsConstants.VIEWFS_URI, FsConstants.VIEWFS_SCHEME, false, -1);
      theInternalDir = dir;
      creationTime = cTime;
      this.ugi = ugi;
      myUri = uri;
    }

    static private void checkPathIsSlash(final Path f) throws IOException {
      if (f != InodeTree.SlashPath) {
        throw new IOException (
        "Internal implementation error: expected file name to be /" );
      }
    }

    @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 {
      throw readOnlyMountTable("create", f);
    }

    @Override
    public boolean delete(final Path f, final boolean recursive)
        throws AccessControlException, IOException {
      checkPathIsSlash(f);
      throw readOnlyMountTable("delete", f);
    }

    @Override
    public BlockLocation[] getFileBlockLocations(final Path f, final long start,
        final long len) throws FileNotFoundException, IOException {
      checkPathIsSlash(f);
      throw new FileNotFoundException("Path points to dir not a file");
    }

    @Override
    public FileChecksum getFileChecksum(final Path f)
        throws FileNotFoundException, IOException {
      checkPathIsSlash(f);
      throw new FileNotFoundException("Path points to dir not a file");
    }

    @Override
    public FileStatus getFileStatus(final Path f) throws IOException {
      checkPathIsSlash(f);
      return new FileStatus(0, true, 0, 0, creationTime, creationTime,
          PERMISSION_RRR, ugi.getUserName(), ugi.getGroupNames()[0],
          new Path(theInternalDir.fullPath).makeQualified(
              myUri, null));
    }
   
    @Override
    public FileStatus getFileLinkStatus(final Path f)
        throws FileNotFoundException {
      // look up i internalDirs children - ignore first Slash
      INode<AbstractFileSystem> inode =
        theInternalDir.children.get(f.toUri().toString().substring(1));
      if (inode == null) {
        throw new FileNotFoundException(
            "viewFs internal mount table - missing entry:" + f);
      }
      FileStatus result;
      if (inode instanceof INodeLink) {
        INodeLink<AbstractFileSystem> inodelink =
          (INodeLink<AbstractFileSystem>) inode;
        result = new FileStatus(0, false, 0, 0, creationTime, creationTime,
            PERMISSION_RRR, ugi.getUserName(), ugi.getGroupNames()[0],
            inodelink.getTargetLink(),
            new Path(inode.fullPath).makeQualified(
                myUri, null));
      } else {
        result = new FileStatus(0, true, 0, 0, creationTime, creationTime,
          PERMISSION_RRR, ugi.getUserName(), ugi.getGroupNames()[0],
          new Path(inode.fullPath).makeQualified(
              myUri, null));
      }
      return result;
    }
   
    @Override
    public FsStatus getFsStatus() {
      return new FsStatus(0, 0, 0);
    }

    @Override
    public FsServerDefaults getServerDefaults() throws IOException {
      throw new IOException("FsServerDefaults not implemented yet");
    }

    @Override
    public int getUriDefaultPort() {
      return -1;
    }

    @Override
    public FileStatus[] listStatus(final Path f) throws AccessControlException,
        IOException {
      checkPathIsSlash(f);
      FileStatus[] result = new FileStatus[theInternalDir.children.size()];
      int i = 0;
      for (Entry<String, INode<AbstractFileSystem>> iEntry :
                                          theInternalDir.children.entrySet()) {
        INode<AbstractFileSystem> inode = iEntry.getValue();

       
        if (inode instanceof INodeLink ) {
          INodeLink<AbstractFileSystem> link =
            (INodeLink<AbstractFileSystem>) inode;

          result[i++] = new FileStatus(0, false, 0, 0,
            creationTime, creationTime,
            PERMISSION_RRR, ugi.getUserName(), ugi.getGroupNames()[0],
            link.getTargetLink(),
            new Path(inode.fullPath).makeQualified(
                myUri, null));
        } else {
          result[i++] = new FileStatus(0, true, 0, 0,
            creationTime, creationTime,
            PERMISSION_RRR, ugi.getUserName(), ugi.getGroupNames()[0],
            new Path(inode.fullPath).makeQualified(
                myUri, null));
        }
      }
      return result;
    }

    @Override
    public void mkdir(final Path dir, final FsPermission permission,
        final boolean createParent) throws AccessControlException,
        FileAlreadyExistsException {
      if (theInternalDir.isRoot && dir == null) {
        throw new FileAlreadyExistsException("/ already exits");
      }
      throw readOnlyMountTable("mkdir", dir);
    }

    @Override
    public FSDataInputStream open(final Path f, final int bufferSize)
        throws FileNotFoundException, IOException {
      checkPathIsSlash(f);
      throw new FileNotFoundException("Path points to dir not a file");
    }

    @Override
    public void renameInternal(final Path src, final Path dst)
        throws AccessControlException, IOException {
      checkPathIsSlash(src);
      checkPathIsSlash(dst);
      throw readOnlyMountTable("rename", src);    
    }

    @Override
    public boolean supportsSymlinks() {
      return true;
    }
   
    @Override
    public void createSymlink(final Path target, final Path link,
        final boolean createParent) throws AccessControlException {
      throw readOnlyMountTable("createSymlink", link);   
    }

    @Override
    public Path getLinkTarget(final Path f) throws FileNotFoundException,
        IOException {
      return getFileLinkStatus(f).getSymlink();
    }

    @Override
    public void setOwner(final Path f, final String username,
        final String groupname) throws AccessControlException, IOException {
      checkPathIsSlash(f);
      throw readOnlyMountTable("setOwner", f);
    }

    @Override
    public void setPermission(final Path f, final FsPermission permission)
        throws AccessControlException, IOException {
      checkPathIsSlash(f);
      throw readOnlyMountTable("setPermission", f);   
    }

    @Override
    public boolean setReplication(final Path f, final short replication)
        throws AccessControlException, IOException {
      checkPathIsSlash(f);
      throw readOnlyMountTable("setReplication", f);
    }

    @Override
    public void setTimes(final Path f, final long mtime, final long atime)
        throws AccessControlException, IOException {
      checkPathIsSlash(f);
      throw readOnlyMountTable("setTimes", f);   
    }

    @Override
    public void setVerifyChecksum(final boolean verifyChecksum)
        throws AccessControlException {
      throw readOnlyMountTable("setVerifyChecksum", "");  
    }
  }
}
TOP

Related Classes of org.apache.hadoop.fs.viewfs.ViewFs$InternalDirOfViewFs

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.