This is an automated email from the ASF dual-hosted git repository.

Hexiaoqiao pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 2c42355e135 HDFS-17891 HostSet.add() throws uncaught exception if 
DataNode hostname is not resolved (#8341). Contributed by Jim Halfpenny
2c42355e135 is described below

commit 2c42355e135b6ecb1be6c41920d307a2365e52fe
Author: Jim Halfpenny <[email protected]>
AuthorDate: Fri May 15 05:31:03 2026 +0100

    HDFS-17891 HostSet.add() throws uncaught exception if DataNode hostname is 
not resolved (#8341). Contributed by Jim Halfpenny
    
    Signed-off-by: He Xiaoqiao <[email protected]>
---
 .../hdfs/server/blockmanagement/HostSet.java       | 11 ++-
 .../hdfs/server/blockmanagement/TestHostSet.java   | 97 ++++++++++++++++++++++
 2 files changed, 106 insertions(+), 2 deletions(-)

diff --git 
a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/HostSet.java
 
b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/HostSet.java
index d12e5fbae13..7feab531512 100644
--- 
a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/HostSet.java
+++ 
b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/HostSet.java
@@ -18,10 +18,11 @@
 package org.apache.hadoop.hdfs.server.blockmanagement;
 
 
-import org.apache.hadoop.util.Preconditions;
 import org.apache.hadoop.thirdparty.com.google.common.collect.HashMultimap;
 import org.apache.hadoop.thirdparty.com.google.common.collect.Multimap;
 import 
org.apache.hadoop.thirdparty.com.google.common.collect.UnmodifiableIterator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
@@ -38,6 +39,8 @@
  * .getPort() || B.getPort() == 0.
  */
 public class HostSet implements Iterable<InetSocketAddress> {
+  private static final Logger LOG = LoggerFactory.getLogger(HostSet.class);
+
   // Host -> lists of ports
   private final Multimap<InetAddress, Integer> addrs = HashMultimap.create();
 
@@ -72,7 +75,11 @@ int size() {
   }
 
   void add(InetSocketAddress addr) {
-    Preconditions.checkArgument(!addr.isUnresolved());
+    LOG.debug("Adding address to HostSet: {}", addr);
+    if (addr.isUnresolved()) {
+      LOG.warn("Unresolved address not added to HostSet: {}", addr);
+      return;
+    }
     addrs.put(addr.getAddress(), addr.getPort());
   }
 
diff --git 
a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestHostSet.java
 
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestHostSet.java
new file mode 100644
index 00000000000..98494e3923d
--- /dev/null
+++ 
b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestHostSet.java
@@ -0,0 +1,97 @@
+/*
+ * 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.server.blockmanagement;
+
+import org.junit.jupiter.api.Test;
+
+import java.net.InetSocketAddress;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for {@link HostSet}.
+ */
+public class TestHostSet {
+
+  /**
+   * HDFS-17891: HostSet.add() must silently skip unresolved addresses
+   * instead of throwing IllegalArgumentException.
+   *
+   * Regression test: before the fix, adding an unresolved InetSocketAddress
+   * caused an uncaught exception that broke dfsadmin -report and the
+   * NameNode web UI whenever any DataNode hostname was unresolvable.
+   */
+  @Test
+  public void testAddUnresolvedAddressDoesNotThrow() {
+    HostSet hostSet = new HostSet();
+    InetSocketAddress unresolved =
+        InetSocketAddress.createUnresolved("does-not-exist.example.local", 
50010);
+
+    assertTrue(unresolved.isUnresolved(), "Hostname should be unresolved");
+
+    // Must not throw IllegalArgumentException (the pre-fix behaviour).
+    hostSet.add(unresolved);
+
+    // The unresolved address should be silently skipped, not added.
+    assertEquals(0, hostSet.size(), "HostSet should be empty after adding an 
unresolved address");
+  }
+
+  /**
+   * A resolved address must still be added normally. The fix must not
+   * regress the happy path.
+   */
+  @Test
+  public void testAddResolvedAddressSucceeds() {
+    HostSet hostSet = new HostSet();
+    // 127.0.0.1 is always resolvable without network access.
+    InetSocketAddress resolved =
+        new InetSocketAddress("127.0.0.1", 50010);
+
+    assertFalse(resolved.isUnresolved(), "Hostname should be resolvable");
+
+    hostSet.add(resolved);
+
+    assertEquals(1, hostSet.size(), "HostSet should contain exactly one 
entry");
+  }
+
+  /**
+   * Mixed batch: one unresolved address among resolved ones.
+   * Only the resolved addresses should end up in the set; the unresolved one
+   * must be skipped without aborting the whole operation.
+   *
+   * This mirrors the real scenario (Kubernetes node deleted, one DataNode
+   * DNS entry gone) where dfsadmin -report broke for the entire cluster.
+   */
+  @Test
+  public void testAddMixedAddressesSkipsUnresolved() {
+    HostSet hostSet = new HostSet();
+
+    InetSocketAddress resolved1 = new InetSocketAddress("127.0.0.1", 50010);
+    InetSocketAddress resolved2 = new InetSocketAddress("127.0.0.1", 50020);
+    InetSocketAddress unresolved =
+        InetSocketAddress.createUnresolved("dead-node.example.local", 50030);
+
+    hostSet.add(resolved1);
+    hostSet.add(unresolved);  // Must not throw or abort.
+    hostSet.add(resolved2);
+
+    assertEquals(2, hostSet.size(), "Only the two resolved addresses should be 
in the HostSet");
+  }
+}


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

Reply via email to