From 780a6bf14562fd9d1070a7c8e756fa1c3bc65d32 Mon Sep 17 00:00:00 2001 From: Kihwal Lee Date: Thu, 15 Jan 2015 16:44:11 -0600 Subject: [PATCH] HDFS-7457. DatanodeID generates excessive garbage. Contributed by Daryn Sharp. --- hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 2 ++ .../hadoop/hdfs/protocol/DatanodeID.java | 23 +++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 823b3d1660d..2d4c6348389 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -515,6 +515,8 @@ Release 2.7.0 - UNRELEASED particular namenode in a federated cluster with multiple namenodes can be specified in the path parameter. (szetszwo) + HDFS-7457. DatanodeID generates excessive garbage. (daryn via kihwal) + OPTIMIZATIONS HDFS-7454. Reduce memory footprint for AclEntries in NameNode. diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeID.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeID.java index c781e5b9ece..779e3b905f1 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeID.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeID.java @@ -46,6 +46,8 @@ public class DatanodeID implements Comparable { private int infoPort; // info server port private int infoSecurePort; // info server port private int ipcPort; // IPC server port + private String xferAddr; + private int hashCode = -1; /** * UUID identifying a given datanode. For upgraded Datanodes this is the @@ -86,10 +88,12 @@ public class DatanodeID implements Comparable { this.infoPort = infoPort; this.infoSecurePort = infoSecurePort; this.ipcPort = ipcPort; + updateXferAddrAndInvalidateHashCode(); } public void setIpAddr(String ipAddr) { this.ipAddr = ipAddr; + updateXferAddrAndInvalidateHashCode(); } public void setPeerHostName(String peerHostName) { @@ -106,6 +110,7 @@ public class DatanodeID implements Comparable { @VisibleForTesting public void setDatanodeUuidForTesting(String datanodeUuid) { this.datanodeUuid = datanodeUuid; + updateXferAddrAndInvalidateHashCode(); } private String checkDatanodeUuid(String uuid) { @@ -141,7 +146,7 @@ public class DatanodeID implements Comparable { * @return IP:xferPort string */ public String getXferAddr() { - return ipAddr + ":" + xferPort; + return xferAddr; } /** @@ -237,7 +242,11 @@ public class DatanodeID implements Comparable { @Override public int hashCode() { - return getXferAddr().hashCode()^ datanodeUuid.hashCode(); + if (hashCode == -1) { + int newHashCode = xferAddr.hashCode() ^ datanodeUuid.hashCode(); + hashCode = newHashCode & Integer.MAX_VALUE; + } + return hashCode; } @Override @@ -257,6 +266,7 @@ public class DatanodeID implements Comparable { infoPort = nodeReg.getInfoPort(); infoSecurePort = nodeReg.getInfoSecurePort(); ipcPort = nodeReg.getIpcPort(); + updateXferAddrAndInvalidateHashCode(); } /** @@ -269,4 +279,13 @@ public class DatanodeID implements Comparable { public int compareTo(DatanodeID that) { return getXferAddr().compareTo(that.getXferAddr()); } + + // NOTE: mutable hash codes are dangerous, however this class chooses to + // use them. this method must be called when a value mutates that is used + // to compute the hash, equality, or comparison of instances. + private void updateXferAddrAndInvalidateHashCode() { + xferAddr = ipAddr + ":" + xferPort; + // can't compute new hash yet because uuid might still null... + hashCode = -1; + } }