joseluisll commented on code in PR #8778:
URL: https://github.com/apache/hadoop/pull/8778#discussion_r4238923408


##########
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/datanode/TestBlockRecovery2.java:
##########
@@ -467,4 +475,103 @@ public void testRecoveryWillIgnoreMinReplication() throws 
Exception {
     }
   }
 
+  /**
+   * A datanode that is still loading its replicas after a restart must not
+   * report "no replica" to block recovery. Otherwise, if the other replicas
+   * cannot be used, block recovery deletes the block although the restarting
+   * datanode holds a valid replica.
+   */
+  @Test
+  @Timeout(180)
+  public void testBlockRecoveryWhileReplicasAreLoading() throws Exception {
+    tearDown(); // Stop the Mocked DN started in startup()
+
+    final Path filePath = new 
Path("/testBlockRecoveryWhileReplicasAreLoading");
+    final byte[] data = AppendTestUtil.randomBytes(0xC0FFEEL, 4096);
+    Configuration configuration = new HdfsConfiguration();
+    configuration.setLong(DFS_HEARTBEAT_INTERVAL_KEY, 1);
+    MiniDFSCluster cluster = null;
+    DataNodeFaultInjector oldInjector = DataNodeFaultInjector.get();
+    CountDownLatch resumeLoading = new CountDownLatch(1);
+    LogCapturer logs = LogCapturer.captureLogs(BlockRecoveryWorker.LOG);
+    try {
+      cluster = new MiniDFSCluster.Builder(configuration).numDataNodes(2)
+          .build();
+      cluster.waitActive();
+      // Retry a failed block recovery quickly.
+      cluster.getNamesystem().getBlockManager().setBlockRecoveryTimeout(3000);
+      final DistributedFileSystem dfs = cluster.getFileSystem();
+
+      FSDataOutputStream out = dfs.create(filePath, (short) 2);
+      out.write(data);
+      out.hsync();
+      DFSTestUtil.abortStream((DFSOutputStream) out.getWrappedStream());
+      ExtendedBlock block = cluster.getNameNodeRpc()
+          .getBlockLocations(filePath.toString(), 0, Long.MAX_VALUE).get(0)
+          .getBlock();
+
+      // Block recovery cannot use the replica on datanode 1.
+      cluster.getMaterializedReplica(1, block).deleteMeta();
+      final DatanodeManager dm =
+          cluster.getNamesystem().getBlockManager().getDatanodeManager();
+      final String dn0Uuid = cluster.getDataNodes().get(0).getDatanodeUuid();
+      final String dn1Uuid = cluster.getDataNodes().get(1).getDatanodeUuid();
+
+      // Restart datanode 0 and hold it while it loads its replicas.
+      CountDownLatch loading = new CountDownLatch(1);
+      DataNodeFaultInjector.set(new DataNodeFaultInjector() {
+        @Override
+        public void delayLoadingReplicas() {
+          loading.countDown();
+          try {
+            resumeLoading.await();
+          } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+          }
+        }
+      });
+      cluster.restartDataNode(cluster.stopDataNode(0), true);
+      assertTrue(loading.await(60, TimeUnit.SECONDS),
+          "datanode 0 did not start loading its replicas");
+      // The primary is the replica with the most recent heartbeat; make that
+      // datanode 1, as datanode 0 does not heartbeat while it is loading.
+      GenericTestUtils.waitFor(
+          () -> dm.getDatanode(dn1Uuid).getLastUpdateMonotonic()
+              > dm.getDatanode(dn0Uuid).getLastUpdateMonotonic(),
+          100, 10000);
+
+      // Datanode 1 becomes the recovery primary and queries datanode 0.
+      DistributedFileSystem newDfs = (DistributedFileSystem) FileSystem
+          .newInstance(cluster.getConfiguration(0));

Review Comment:
   nit: `newDfs` isn't closed; please close it in the `finally` block.
   
   ---
   _Generated by [Claude Code](https://claude.ai/code)_



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to