001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.hadoop.hdfs.server.namenode;
019    
020    import java.util.Iterator;
021    import java.util.List;
022    
023    import org.apache.hadoop.fs.permission.FsPermission;
024    import org.apache.hadoop.fs.permission.PermissionStatus;
025    import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
026    import org.apache.hadoop.hdfs.server.namenode.Quota.Counts;
027    import org.apache.hadoop.util.GSet;
028    import org.apache.hadoop.util.LightWeightGSet;
029    
030    import com.google.common.base.Preconditions;
031    
032    /**
033     * Storing all the {@link INode}s and maintaining the mapping between INode ID
034     * and INode.  
035     */
036    public class INodeMap {
037      
038      static INodeMap newInstance(INodeDirectory rootDir) {
039        // Compute the map capacity by allocating 1% of total memory
040        int capacity = LightWeightGSet.computeCapacity(1, "INodeMap");
041        GSet<INode, INodeWithAdditionalFields> map
042            = new LightWeightGSet<INode, INodeWithAdditionalFields>(capacity);
043        map.put(rootDir);
044        return new INodeMap(map);
045      }
046      
047      /** Synchronized by external lock. */
048      private final GSet<INode, INodeWithAdditionalFields> map;
049      
050      public Iterator<INodeWithAdditionalFields> getMapIterator() {
051        return map.iterator();
052      }
053    
054      private INodeMap(GSet<INode, INodeWithAdditionalFields> map) {
055        Preconditions.checkArgument(map != null);
056        this.map = map;
057      }
058      
059      /**
060       * Add an {@link INode} into the {@link INode} map. Replace the old value if 
061       * necessary. 
062       * @param inode The {@link INode} to be added to the map.
063       */
064      public final void put(INode inode) {
065        if (inode instanceof INodeWithAdditionalFields) {
066          map.put((INodeWithAdditionalFields)inode);
067        }
068      }
069      
070      /**
071       * Remove a {@link INode} from the map.
072       * @param inode The {@link INode} to be removed.
073       */
074      public final void remove(INode inode) {
075        map.remove(inode);
076      }
077      
078      /**
079       * @return The size of the map.
080       */
081      public int size() {
082        return map.size();
083      }
084      
085      /**
086       * Get the {@link INode} with the given id from the map.
087       * @param id ID of the {@link INode}.
088       * @return The {@link INode} in the map with the given id. Return null if no 
089       *         such {@link INode} in the map.
090       */
091      public INode get(long id) {
092        INode inode = new INodeWithAdditionalFields(id, null, new PermissionStatus(
093            "", "", new FsPermission((short) 0)), 0, 0) {
094          
095          @Override
096          INode recordModification(int latestSnapshotId)
097              throws QuotaExceededException {
098            return null;
099          }
100          
101          @Override
102          public void destroyAndCollectBlocks(BlocksMapUpdateInfo collectedBlocks,
103              List<INode> removedINodes) {
104            // Nothing to do
105          }
106          
107          @Override
108          public Counts computeQuotaUsage(Counts counts, boolean useCache,
109              int lastSnapshotId) {
110            return null;
111          }
112          
113          @Override
114          public ContentSummaryComputationContext computeContentSummary(
115              ContentSummaryComputationContext summary) {
116            return null;
117          }
118          
119          @Override
120          public Counts cleanSubtree(int snapshotId, int priorSnapshotId,
121              BlocksMapUpdateInfo collectedBlocks, List<INode> removedINodes,
122              boolean countDiffChange) throws QuotaExceededException {
123            return null;
124          }
125        };
126          
127        return map.get(inode);
128      }
129      
130      /**
131       * Clear the {@link #map}
132       */
133      public void clear() {
134        map.clear();
135      }
136    }