Browse Source

HDFS-10987. Make Decommission less expensive when lot of blocks present. Contributed By Brahma Reddy Battula.

Brahma Reddy Battula 8 years ago
parent
commit
b95d63cdac

+ 3 - 0
hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt

@@ -280,6 +280,9 @@ Release 2.7.4 - UNRELEASED
 
 	HDFS-11674. reserveSpaceForReplicas is not released if append request failed
 	due to mirror down and replica recovered (vinayakumarb)
+	
+    HDFS-10987. Make Decommission less expensive when lot of blocks present. 
+    (Brahma Reddy Battula)
 
 Release 2.7.3 - 2016-08-25
 

+ 28 - 3
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DecommissionManager.java

@@ -347,6 +347,10 @@ public class DecommissionManager {
      * The number of blocks that have been checked on this tick.
      */
     private int numBlocksChecked = 0;
+    /**
+     * The number of blocks checked after (re)holding lock.
+     */
+    private int numBlocksCheckedPerLock = 0;
     /**
      * The number of nodes that have been checked on this tick. Used for 
      * testing.
@@ -385,6 +389,7 @@ public class DecommissionManager {
       }
       // Reset the checked count at beginning of each iteration
       numBlocksChecked = 0;
+      numBlocksCheckedPerLock = 0;
       numNodesChecked = 0;
       // Check decom progress
       namesystem.writeLock();
@@ -417,9 +422,8 @@ public class DecommissionManager {
           it = new CyclicIteration<>(decomNodeBlocks, iterkey).iterator();
       final LinkedList<DatanodeDescriptor> toRemove = new LinkedList<>();
 
-      while (it.hasNext()
-          && !exceededNumBlocksPerCheck()
-          && !exceededNumNodesPerCheck()) {
+      while (it.hasNext() && !exceededNumBlocksPerCheck()
+          && !exceededNumNodesPerCheck() && namesystem.isRunning()) {
         numNodesChecked++;
         final Map.Entry<DatanodeDescriptor, AbstractList<BlockInfoContiguous>>
             entry = it.next();
@@ -544,7 +548,28 @@ public class DecommissionManager {
       int decommissionOnlyReplicas = 0;
       int underReplicatedInOpenFiles = 0;
       while (it.hasNext()) {
+        if (insufficientlyReplicated == null
+            && numBlocksCheckedPerLock >= numBlocksPerCheck) {
+          // During fullscan insufficientlyReplicated will NOT be null, iterator
+          // will be DN's iterator. So should not yield lock, otherwise
+          // ConcurrentModificationException could occur.
+          // Once the fullscan done, iterator will be a copy. So can yield the
+          // lock.
+          // Yielding is required in case of block number is greater than the
+          // configured per-iteration-limit.
+          namesystem.writeUnlock();
+          try {
+            LOG.debug("Yielded lock during decommission check");
+            Thread.sleep(0, 500);
+          } catch (InterruptedException ignored) {
+            return;
+          }
+          //reset
+          numBlocksCheckedPerLock = 0;
+          namesystem.writeLock();
+        }
         numBlocksChecked++;
+        numBlocksCheckedPerLock++;
         final BlockInfoContiguous block = it.next();
         // Remove the block from the list if it's no longer in the block map,
         // e.g. the containing file has been deleted