INodeDirectory.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:11k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.hdfs.server.namenode;
  19. import java.io.FileNotFoundException;
  20. import java.util.ArrayList;
  21. import java.util.Collections;
  22. import java.util.List;
  23. import org.apache.hadoop.fs.permission.FsAction;
  24. import org.apache.hadoop.fs.permission.FsPermission;
  25. import org.apache.hadoop.fs.permission.PermissionStatus;
  26. import org.apache.hadoop.hdfs.protocol.Block;
  27. /**
  28.  * Directory INode class.
  29.  */
  30. class INodeDirectory extends INode {
  31.   protected static final int DEFAULT_FILES_PER_DIRECTORY = 5;
  32.   final static String ROOT_NAME = "";
  33.   private List<INode> children;
  34.   INodeDirectory(String name, PermissionStatus permissions) {
  35.     super(name, permissions);
  36.     this.children = null;
  37.   }
  38.   public INodeDirectory(PermissionStatus permissions, long mTime) {
  39.     super(permissions, mTime, 0);
  40.     this.children = null;
  41.   }
  42.   /** constructor */
  43.   INodeDirectory(byte[] localName, PermissionStatus permissions, long mTime) {
  44.     this(permissions, mTime);
  45.     this.name = localName;
  46.   }
  47.   
  48.   /** copy constructor
  49.    * 
  50.    * @param other
  51.    */
  52.   INodeDirectory(INodeDirectory other) {
  53.     super(other);
  54.     this.children = other.getChildren();
  55.   }
  56.   
  57.   /**
  58.    * Check whether it's a directory
  59.    */
  60.   public boolean isDirectory() {
  61.     return true;
  62.   }
  63.   INode removeChild(INode node) {
  64.     assert children != null;
  65.     int low = Collections.binarySearch(children, node.name);
  66.     if (low >= 0) {
  67.       return children.remove(low);
  68.     } else {
  69.       return null;
  70.     }
  71.   }
  72.   /** Replace a child that has the same name as newChild by newChild.
  73.    * 
  74.    * @param newChild Child node to be added
  75.    */
  76.   void replaceChild(INode newChild) {
  77.     if ( children == null ) {
  78.       throw new IllegalArgumentException("The directory is empty");
  79.     }
  80.     int low = Collections.binarySearch(children, newChild.name);
  81.     if (low>=0) { // an old child exists so replace by the newChild
  82.       children.set(low, newChild);
  83.     } else {
  84.       throw new IllegalArgumentException("No child exists to be replaced");
  85.     }
  86.   }
  87.   
  88.   INode getChild(String name) {
  89.     return getChildINode(string2Bytes(name));
  90.   }
  91.   private INode getChildINode(byte[] name) {
  92.     if (children == null) {
  93.       return null;
  94.     }
  95.     int low = Collections.binarySearch(children, name);
  96.     if (low >= 0) {
  97.       return children.get(low);
  98.     }
  99.     return null;
  100.   }
  101.   /**
  102.    */
  103.   private INode getNode(byte[][] components) {
  104.     INode[] inode  = new INode[1];
  105.     getExistingPathINodes(components, inode);
  106.     return inode[0];
  107.   }
  108.   /**
  109.    * This is the external interface
  110.    */
  111.   INode getNode(String path) {
  112.     return getNode(getPathComponents(path));
  113.   }
  114.   /**
  115.    * Retrieve existing INodes from a path. If existing is big enough to store
  116.    * all path components (existing and non-existing), then existing INodes
  117.    * will be stored starting from the root INode into existing[0]; if
  118.    * existing is not big enough to store all path components, then only the
  119.    * last existing and non existing INodes will be stored so that
  120.    * existing[existing.length-1] refers to the target INode.
  121.    * 
  122.    * <p>
  123.    * Example: <br>
  124.    * Given the path /c1/c2/c3 where only /c1/c2 exists, resulting in the
  125.    * following path components: ["","c1","c2","c3"],
  126.    * 
  127.    * <p>
  128.    * <code>getExistingPathINodes(["","c1","c2"], [?])</code> should fill the
  129.    * array with [c2] <br>
  130.    * <code>getExistingPathINodes(["","c1","c2","c3"], [?])</code> should fill the
  131.    * array with [null]
  132.    * 
  133.    * <p>
  134.    * <code>getExistingPathINodes(["","c1","c2"], [?,?])</code> should fill the
  135.    * array with [c1,c2] <br>
  136.    * <code>getExistingPathINodes(["","c1","c2","c3"], [?,?])</code> should fill
  137.    * the array with [c2,null]
  138.    * 
  139.    * <p>
  140.    * <code>getExistingPathINodes(["","c1","c2"], [?,?,?,?])</code> should fill
  141.    * the array with [rootINode,c1,c2,null], <br>
  142.    * <code>getExistingPathINodes(["","c1","c2","c3"], [?,?,?,?])</code> should
  143.    * fill the array with [rootINode,c1,c2,null]
  144.    * @param components array of path component name
  145.    * @param existing INode array to fill with existing INodes
  146.    * @return number of existing INodes in the path
  147.    */
  148.   int getExistingPathINodes(byte[][] components, INode[] existing) {
  149.     assert compareBytes(this.name, components[0]) == 0 :
  150.       "Incorrect name " + getLocalName() + " expected " + components[0];
  151.     INode curNode = this;
  152.     int count = 0;
  153.     int index = existing.length - components.length;
  154.     if (index > 0)
  155.       index = 0;
  156.     while ((count < components.length) && (curNode != null)) {
  157.       if (index >= 0)
  158.         existing[index] = curNode;
  159.       if (!curNode.isDirectory() || (count == components.length - 1))
  160.         break; // no more child, stop here
  161.       INodeDirectory parentDir = (INodeDirectory)curNode;
  162.       curNode = parentDir.getChildINode(components[count + 1]);
  163.       count += 1;
  164.       index += 1;
  165.     }
  166.     return count;
  167.   }
  168.   /**
  169.    * Retrieve the existing INodes along the given path. The first INode
  170.    * always exist and is this INode.
  171.    * 
  172.    * @param path the path to explore
  173.    * @return INodes array containing the existing INodes in the order they
  174.    *         appear when following the path from the root INode to the
  175.    *         deepest INodes. The array size will be the number of expected
  176.    *         components in the path, and non existing components will be
  177.    *         filled with null
  178.    *         
  179.    * @see #getExistingPathINodes(byte[][], INode[])
  180.    */
  181.   INode[] getExistingPathINodes(String path) {
  182.     byte[][] components = getPathComponents(path);
  183.     INode[] inodes = new INode[components.length];
  184.     this.getExistingPathINodes(components, inodes);
  185.     
  186.     return inodes;
  187.   }
  188.   /**
  189.    * Add a child inode to the directory.
  190.    * 
  191.    * @param node INode to insert
  192.    * @param inheritPermission inherit permission from parent?
  193.    * @return  null if the child with this name already exists; 
  194.    *          node, otherwise
  195.    */
  196.   <T extends INode> T addChild(final T node, boolean inheritPermission) {
  197.     if (inheritPermission) {
  198.       FsPermission p = getFsPermission();
  199.       //make sure the  permission has wx for the user
  200.       if (!p.getUserAction().implies(FsAction.WRITE_EXECUTE)) {
  201.         p = new FsPermission(p.getUserAction().or(FsAction.WRITE_EXECUTE),
  202.             p.getGroupAction(), p.getOtherAction());
  203.       }
  204.       node.setPermission(p);
  205.     }
  206.     if (children == null) {
  207.       children = new ArrayList<INode>(DEFAULT_FILES_PER_DIRECTORY);
  208.     }
  209.     int low = Collections.binarySearch(children, node.name);
  210.     if(low >= 0)
  211.       return null;
  212.     node.parent = this;
  213.     children.add(-low - 1, node);
  214.     // update modification time of the parent directory
  215.     setModificationTime(node.getModificationTime());
  216.     if (node.getGroupName() == null) {
  217.       node.setGroup(getGroupName());
  218.     }
  219.     return node;
  220.   }
  221.   /**
  222.    * Equivalent to addNode(path, newNode, false).
  223.    * @see #addNode(String, INode, boolean)
  224.    */
  225.   <T extends INode> T addNode(String path, T newNode) throws FileNotFoundException {
  226.     return addNode(path, newNode, false);
  227.   }
  228.   /**
  229.    * Add new INode to the file tree.
  230.    * Find the parent and insert 
  231.    * 
  232.    * @param path file path
  233.    * @param newNode INode to be added
  234.    * @param inheritPermission If true, copy the parent's permission to newNode.
  235.    * @return null if the node already exists; inserted INode, otherwise
  236.    * @throws FileNotFoundException if parent does not exist or 
  237.    * is not a directory.
  238.    */
  239.   <T extends INode> T addNode(String path, T newNode, boolean inheritPermission
  240.       ) throws FileNotFoundException {
  241.     if(addToParent(path, newNode, null, inheritPermission) == null)
  242.       return null;
  243.     return newNode;
  244.   }
  245.   /**
  246.    * Add new inode to the parent if specified.
  247.    * Optimized version of addNode() if parent is not null.
  248.    * 
  249.    * @return  parent INode if new inode is inserted
  250.    *          or null if it already exists.
  251.    * @throws  FileNotFoundException if parent does not exist or 
  252.    *          is not a directory.
  253.    */
  254.   <T extends INode> INodeDirectory addToParent(
  255.                                       String path,
  256.                                       T newNode,
  257.                                       INodeDirectory parent,
  258.                                       boolean inheritPermission
  259.                                     ) throws FileNotFoundException {
  260.     byte[][] pathComponents = getPathComponents(path);
  261.     assert pathComponents != null : "Incorrect path " + path;
  262.     int pathLen = pathComponents.length;
  263.     if (pathLen < 2)  // add root
  264.       return null;
  265.     if(parent == null) {
  266.       // Gets the parent INode
  267.       INode[] inodes  = new INode[2];
  268.       getExistingPathINodes(pathComponents, inodes);
  269.       INode inode = inodes[0];
  270.       if (inode == null) {
  271.         throw new FileNotFoundException("Parent path does not exist: "+path);
  272.       }
  273.       if (!inode.isDirectory()) {
  274.         throw new FileNotFoundException("Parent path is not a directory: "+path);
  275.       }
  276.       parent = (INodeDirectory)inode;
  277.     }
  278.     // insert into the parent children list
  279.     newNode.name = pathComponents[pathLen-1];
  280.     if(parent.addChild(newNode, inheritPermission) == null)
  281.       return null;
  282.     return parent;
  283.   }
  284.   /** {@inheritDoc} */
  285.   DirCounts spaceConsumedInTree(DirCounts counts) {
  286.     counts.nsCount += 1;
  287.     if (children != null) {
  288.       for (INode child : children) {
  289.         child.spaceConsumedInTree(counts);
  290.       }
  291.     }
  292.     return counts;    
  293.   }
  294.   /** {@inheritDoc} */
  295.   long[] computeContentSummary(long[] summary) {
  296.     if (children != null) {
  297.       for (INode child : children) {
  298.         child.computeContentSummary(summary);
  299.       }
  300.     }
  301.     summary[2]++;
  302.     return summary;
  303.   }
  304.   /**
  305.    */
  306.   List<INode> getChildren() {
  307.     return children==null ? new ArrayList<INode>() : children;
  308.   }
  309.   List<INode> getChildrenRaw() {
  310.     return children;
  311.   }
  312.   int collectSubtreeBlocksAndClear(List<Block> v) {
  313.     int total = 1;
  314.     if (children == null) {
  315.       return total;
  316.     }
  317.     for (INode child : children) {
  318.       total += child.collectSubtreeBlocksAndClear(v);
  319.     }
  320.     parent = null;
  321.     children = null;
  322.     return total;
  323.   }
  324. }