소스 검색

HDFS-15877. BlockReconstructionWork should resetTargets() before BlockManager#validateReconstructionWork return false (#2747)

huhaiyang 4 년 전
부모
커밋
acd712ca92

+ 3 - 1
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java

@@ -2246,7 +2246,8 @@ public class BlockManager implements BlockStatsMXBean {
     }
   }
 
-  private boolean validateReconstructionWork(BlockReconstructionWork rw) {
+  @VisibleForTesting
+  boolean validateReconstructionWork(BlockReconstructionWork rw) {
     BlockInfo block = rw.getBlock();
     int priority = rw.getPriority();
     // Recheck since global lock was released
@@ -2281,6 +2282,7 @@ public class BlockManager implements BlockStatsMXBean {
               placementStatus.getAdditionalReplicasRequired())) {
         // If the new targets do not meet the placement policy, or at least
         // reduce the number of replicas needed, then no use continuing.
+        rw.resetTargets();
         return false;
       }
       // mark that the reconstruction work is to replicate internal block to a

+ 22 - 0
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockManager.java

@@ -1949,4 +1949,26 @@ public class TestBlockManager {
     assertEquals(0, ibs.getBlocks());
     assertEquals(0, ibs.getECBlocks());
   }
+
+  @Test
+  public void testValidateReconstructionWorkAndRacksNotEnough() {
+    addNodes(nodes);
+    // Originally on only nodes in rack A.
+    List<DatanodeDescriptor> origNodes = rackA;
+    BlockInfo blockInfo = addBlockOnNodes(0, origNodes);
+    BlockPlacementStatus status = bm.getBlockPlacementStatus(blockInfo);
+    // Block has enough copies, but not enough racks.
+    assertFalse(status.isPlacementPolicySatisfied());
+    DatanodeStorageInfo newNode = DFSTestUtil.createDatanodeStorageInfo(
+            "storage8", "8.8.8.8", "/rackA", "host8");
+    BlockReconstructionWork work = bm.scheduleReconstruction(blockInfo, 3);
+    assertNotNull(work);
+    assertEquals(1, work.getAdditionalReplRequired());
+    // the new targets in rack A.
+    work.setTargets(new DatanodeStorageInfo[]{newNode});
+    // the new targets do not meet the placement policy return false.
+    assertFalse(bm.validateReconstructionWork(work));
+    // validateReconstructionWork return false, need to perform resetTargets().
+    assertNull(work.getTargets());
+  }
 }