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]