From 021fcc6c5e931fd454f10dc8ede47dbcc34d6139 Mon Sep 17 00:00:00 2001 From: Viraj Jasani Date: Tue, 14 Feb 2023 03:48:48 -0800 Subject: [PATCH] HADOOP-18628. IPC Server Connection should log host name before returning VersionMismatch error (#5385) Contributed by Viraj Jasani --- .../java/org/apache/hadoop/ipc/Server.java | 42 +++++++++++++------ .../java/org/apache/hadoop/ipc/TestIPC.java | 4 ++ .../java/org/apache/hadoop/ipc/TestRPC.java | 5 +++ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java index a79fc2eeb5..26f519716f 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java @@ -1985,11 +1985,26 @@ public class Connection { private long lastContact; private int dataLength; private Socket socket; + // Cache the remote host & port info so that even if the socket is // disconnected, we can say where it used to connect to. - private String hostAddress; - private int remotePort; - private InetAddress addr; + + /** + * Client Host IP address from where the socket connection is being established to the Server. + */ + private final String hostAddress; + /** + * Client remote port used for the given socket connection. + */ + private final int remotePort; + /** + * Address to which the socket is connected to. + */ + private final InetAddress addr; + /** + * Client Host address from where the socket connection is being established to the Server. + */ + private final String hostName; IpcConnectionContextProto connectionContext; String protocolName; @@ -2033,8 +2048,12 @@ public Connection(SocketChannel channel, long lastContact, this.isOnAuxiliaryPort = isOnAuxiliaryPort; if (addr == null) { this.hostAddress = "*Unknown*"; + this.hostName = this.hostAddress; } else { + // host IP address this.hostAddress = addr.getHostAddress(); + // host name for the IP address + this.hostName = addr.getHostName(); } this.remotePort = socket.getPort(); this.responseQueue = new LinkedList(); @@ -2050,7 +2069,7 @@ public Connection(SocketChannel channel, long lastContact, @Override public String toString() { - return getHostAddress() + ":" + remotePort; + return hostName + ":" + remotePort + " / " + hostAddress + ":" + remotePort; } boolean setShouldClose() { @@ -2463,19 +2482,18 @@ public int readAndProcess() throws IOException, InterruptedException { return -1; } - if(!RpcConstants.HEADER.equals(dataLengthBuffer)) { - LOG.warn("Incorrect RPC Header length from {}:{} " - + "expected length: {} got length: {}", - hostAddress, remotePort, RpcConstants.HEADER, dataLengthBuffer); + if (!RpcConstants.HEADER.equals(dataLengthBuffer)) { + LOG.warn("Incorrect RPC Header length from {}:{} / {}:{}. Expected: {}. Actual: {}", + hostName, remotePort, hostAddress, remotePort, RpcConstants.HEADER, + dataLengthBuffer); setupBadVersionResponse(version); return -1; } if (version != CURRENT_VERSION) { //Warning is ok since this is not supposed to happen. - LOG.warn("Version mismatch from " + - hostAddress + ":" + remotePort + - " got version " + version + - " expected version " + CURRENT_VERSION); + LOG.warn("Version mismatch from {}:{} / {}:{}. " + + "Expected version: {}. Actual version: {} ", hostName, + remotePort, hostAddress, remotePort, CURRENT_VERSION, version); setupBadVersionResponse(version); return -1; } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestIPC.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestIPC.java index b65f86a0f7..59966b340c 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestIPC.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestIPC.java @@ -1168,6 +1168,10 @@ private static void callAndVerify(Server server, InetSocketAddress addr, call(client, addr, serviceClass, conf); Connection connection = server.getConnections()[0]; + LOG.info("Connection is from: {}", connection); + assertEquals( + "Connection string representation should include both IP address and Host name", 2, + connection.toString().split(" / ").length); int serviceClass2 = connection.getServiceClass(); assertFalse(noChanged ^ serviceClass == serviceClass2); client.stop(); diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestRPC.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestRPC.java index a7727716c4..9126316fca 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestRPC.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestRPC.java @@ -1849,6 +1849,11 @@ public RpcStatusProto getRpcStatusProto() { // if it wasn't fatal, verify there's only one open connection. Connection[] conns = server.getConnections(); assertEquals(reqName, 1, conns.length); + String connectionInfo = conns[0].toString(); + LOG.info("Connection is from: {}", connectionInfo); + assertEquals( + "Connection string representation should include both IP address and Host name", 2, + connectionInfo.split(" / ").length); // verify whether the connection should have been reused. if (isDisconnected) { assertNotSame(reqName, lastConn, conns[0]);