Browse Source

HDFS-1119. Introduce a GSet interface to BlocksMap.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/hdfs/trunk@948908 13f79535-47bb-0310-9956-ffa450edef68
Tsz-wo Sze 15 years ago
parent
commit
3e446c4de1

+ 2 - 0
CHANGES.txt

@@ -25,6 +25,8 @@ Trunk (unreleased changes)
 
     HDFS-1112. Edit log buffer should not grow unfoundedly. (hairong)
 
+    HDFS-1119. Introduce a GSet interface to BlocksMap.  (szetszwo)
+
   BUG FIXES
 
     HDFS-1038. In nn_browsedfscontent.jsp fetch delegation token only 

+ 0 - 5
src/java/org/apache/hadoop/hdfs/server/namenode/BlockManager.java

@@ -1687,11 +1687,6 @@ public class BlockManager {
     }
   }
   
-  float getLoadFactor() {
-    return blocksMap.getLoadFactor();
-  }
-  
-  
   /**
    * Return a range of corrupt replica block ids. Up to numExpectedBlocks 
    * blocks starting at the next block after startingBlockId are returned

+ 23 - 27
src/java/org/apache/hadoop/hdfs/server/namenode/BlocksMap.java

@@ -17,12 +17,11 @@
  */
 package org.apache.hadoop.hdfs.server.namenode;
 
-import java.util.Collection;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
 
 import org.apache.hadoop.hdfs.protocol.Block;
+import org.apache.hadoop.hdfs.util.GSet;
+import org.apache.hadoop.hdfs.util.GSetByHashMap;
 
 /**
  * This class maintains the map from a block to its metadata.
@@ -56,7 +55,7 @@ class BlocksMap {
   private int capacity;
   private final float loadFactor;
   
-  private Map<BlockInfo, BlockInfo> map;
+  private GSet<Block, BlockInfo> blocks;
 
   BlocksMap(int initialCapacity, float loadFactor) {
     this.capacity = 1;
@@ -64,11 +63,12 @@ class BlocksMap {
     while (this.capacity < initialCapacity)
       this.capacity <<= 1;
     this.loadFactor = loadFactor;
-    this.map = new HashMap<BlockInfo, BlockInfo>(initialCapacity, loadFactor);
+    this.blocks = new GSetByHashMap<Block, BlockInfo>(
+        initialCapacity, loadFactor);
   }
 
   INodeFile getINode(Block b) {
-    BlockInfo info = map.get(b);
+    BlockInfo info = blocks.get(b);
     return (info != null) ? info.getINode() : null;
   }
 
@@ -76,10 +76,10 @@ class BlocksMap {
    * Add block b belonging to the specified file inode to the map.
    */
   BlockInfo addINode(BlockInfo b, INodeFile iNode) {
-    BlockInfo info = map.get(b);
+    BlockInfo info = blocks.get(b);
     if (info != b) {
       info = b;
-      map.put(info, info);
+      blocks.put(info);
     }
     info.setINode(iNode);
     return info;
@@ -91,7 +91,7 @@ class BlocksMap {
    * and remove all data-node locations associated with the block.
    */
   void removeBlock(Block block) {
-    BlockInfo blockInfo = map.remove(block);
+    BlockInfo blockInfo = blocks.remove(block);
     if (blockInfo == null)
       return;
 
@@ -104,7 +104,7 @@ class BlocksMap {
   
   /** Returns the block object it it exists in the map. */
   BlockInfo getStoredBlock(Block b) {
-    return map.get(b);
+    return blocks.get(b);
   }
 
   /**
@@ -112,7 +112,7 @@ class BlocksMap {
    * returns Iterator that iterates through the nodes the block belongs to.
    */
   Iterator<DatanodeDescriptor> nodeIterator(Block b) {
-    return nodeIterator(map.get(b));
+    return nodeIterator(blocks.get(b));
   }
 
   /**
@@ -125,7 +125,7 @@ class BlocksMap {
 
   /** counts number of containing nodes. Better than using iterator. */
   int numNodes(Block b) {
-    BlockInfo info = map.get(b);
+    BlockInfo info = blocks.get(b);
     return info == null ? 0 : info.numNodes();
   }
 
@@ -135,7 +135,7 @@ class BlocksMap {
    * only if it does not belong to any file and data-nodes.
    */
   boolean removeNode(Block b, DatanodeDescriptor node) {
-    BlockInfo info = map.get(b);
+    BlockInfo info = blocks.get(b);
     if (info == null)
       return false;
 
@@ -144,30 +144,31 @@ class BlocksMap {
 
     if (info.getDatanode(0) == null     // no datanodes left
               && info.getINode() == null) {  // does not belong to a file
-      map.remove(b);  // remove block from the map
+      blocks.remove(b);  // remove block from the map
     }
     return removed;
   }
 
   int size() {
-    return map.size();
+    return blocks.size();
   }
 
-  Collection<BlockInfo> getBlocks() {
-    return map.values();
+  Iterable<BlockInfo> getBlocks() {
+    return blocks;
   }
+
   /**
    * Check if the block exists in map
    */
   boolean contains(Block block) {
-    return map.containsKey(block);
+    return blocks.contains(block);
   }
   
   /**
    * Check if the replica at the given datanode exists in map
    */
   boolean contains(Block block, DatanodeDescriptor datanode) {
-    BlockInfo info = map.get(block);
+    BlockInfo info = blocks.get(block);
     if (info == null)
       return false;
     
@@ -180,16 +181,11 @@ class BlocksMap {
   /** Get the capacity of the HashMap that stores blocks */
   int getCapacity() {
     // Capacity doubles every time the map size reaches the threshold
-    while (map.size() > (int)(capacity * loadFactor)) {
+    while (blocks.size() > (int)(capacity * loadFactor)) {
       capacity <<= 1;
     }
     return capacity;
   }
-  
-  /** Get the load factor of the map */
-  float getLoadFactor() {
-    return loadFactor;
-  }
 
   /**
    * Replace a block in the block map by a new block.
@@ -198,7 +194,7 @@ class BlocksMap {
    * @return new block
    */
   BlockInfo replaceBlock(BlockInfo newBlock) {
-    BlockInfo currentBlock = map.get(newBlock);
+    BlockInfo currentBlock = blocks.get(newBlock);
     assert currentBlock != null : "the block if not in blocksMap";
     // replace block in data-node lists
     for(int idx = currentBlock.numNodes()-1; idx >= 0; idx--) {
@@ -206,7 +202,7 @@ class BlocksMap {
       dn.replaceBlock(currentBlock, newBlock);
     }
     // replace block in the map itself
-    map.put(newBlock, newBlock);
+    blocks.put(newBlock);
     return newBlock;
   }
 }

+ 77 - 0
src/java/org/apache/hadoop/hdfs/util/GSet.java

@@ -0,0 +1,77 @@
+/**
+ * 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.hdfs.util;
+
+/**
+ * A {@link GSet} is set,
+ * which supports the {@link #get(Object)} operation.
+ * The {@link #get(Object)} operation uses a key to lookup an element.
+ * 
+ * Null element is not supported.
+ * 
+ * @param <K> The type of the keys.
+ * @param <E> The type of the elements, which must be a subclass of the keys.
+ */
+public interface GSet<K, E extends K> extends Iterable<E> {
+  /**
+   * @return The size of this set.
+   */
+  int size();
+
+  /**
+   * Does this set contain an element corresponding to the given key?
+   * @param key The given key.
+   * @return true if the given key equals to a stored element.
+   *         Otherwise, return false.
+   */
+  boolean contains(K key);
+
+  /**
+   * Return the stored element which is equal to the given key.
+   * This operation is similar to {@link java.util.Map#get(Object)}.
+   * @param key The given key.
+   * @return The stored element if it exists.
+   *         Otherwise, return null.
+   */
+  E get(K key);
+
+  /**
+   * Add/replace an element.
+   * If the element does not exist, add it to the set.
+   * Otherwise, replace the existing element.
+   *
+   * Note that this operation
+   * is similar to {@link java.util.Map#put(Object, Object)}
+   * but is different from {@link java.util.Set#add(Object)}
+   * which does not replace the existing element if there is any.
+   *
+   * @param element The element being put.
+   * @return the previous stored element if there is any.
+   *         Otherwise, return null.
+   */
+  E put(E element);
+
+  /**
+   * Remove the element corresponding to the given key. 
+   * This operation is similar to {@link java.util.Map#remove(Object)}.
+   * @param key The key of the element being removed.
+   * @return If such element exists, return it.
+   *         Otherwise, return null. 
+   */
+  E remove(K key);
+}

+ 65 - 0
src/java/org/apache/hadoop/hdfs/util/GSetByHashMap.java

@@ -0,0 +1,65 @@
+/**
+ * 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.hdfs.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A {@link GSet} implementation by {@link HashMap}.
+ */
+public class GSetByHashMap<K, E extends K> implements GSet<K, E> {
+  private final HashMap<K, E> m;
+
+  public GSetByHashMap(int initialCapacity, float loadFactor) {
+    m = new HashMap<K, E>(initialCapacity, loadFactor);
+  }
+
+  @Override
+  public int size() {
+    return m.size();
+  }
+
+  @Override
+  public boolean contains(K k) {
+    return m.containsKey(k);
+  }
+
+  @Override
+  public E get(K k) {
+    return m.get(k);
+  }
+
+  @Override
+  public E put(E element) {
+    if (element == null) {
+      throw new UnsupportedOperationException("Null element is not supported.");
+    }
+    return m.put(element, element);
+  }
+
+  @Override
+  public E remove(K k) {
+    return m.remove(k);
+  }
+
+  @Override
+  public Iterator<E> iterator() {
+    return m.values().iterator();
+  }
+}