Browse Source

HDFS-7457. DatanodeID generates excessive garbage. Contributed by Daryn Sharp.
(cherry picked from commit 780a6bf14562fd9d1070a7c8e756fa1c3bc65d32)

Kihwal Lee 10 years ago
parent
commit
6f792fc198

+ 2 - 0
hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt

@@ -245,6 +245,8 @@ Release 2.7.0 - UNRELEASED
     particular namenode in a federated cluster with multiple namenodes
     particular namenode in a federated cluster with multiple namenodes
     can be specified in the path parameter.  (szetszwo)
     can be specified in the path parameter.  (szetszwo)
 
 
+    HDFS-7457. DatanodeID generates excessive garbage. (daryn via kihwal)
+
   OPTIMIZATIONS
   OPTIMIZATIONS
 
 
     HDFS-7454. Reduce memory footprint for AclEntries in NameNode.
     HDFS-7454. Reduce memory footprint for AclEntries in NameNode.

+ 21 - 2
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/DatanodeID.java

@@ -46,6 +46,8 @@ public class DatanodeID implements Comparable<DatanodeID> {
   private int infoPort;      // info server port
   private int infoPort;      // info server port
   private int infoSecurePort; // info server port
   private int infoSecurePort; // info server port
   private int ipcPort;       // IPC 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
    * UUID identifying a given datanode. For upgraded Datanodes this is the
@@ -86,10 +88,12 @@ public class DatanodeID implements Comparable<DatanodeID> {
     this.infoPort = infoPort;
     this.infoPort = infoPort;
     this.infoSecurePort = infoSecurePort;
     this.infoSecurePort = infoSecurePort;
     this.ipcPort = ipcPort;
     this.ipcPort = ipcPort;
+    updateXferAddrAndInvalidateHashCode();
   }
   }
   
   
   public void setIpAddr(String ipAddr) {
   public void setIpAddr(String ipAddr) {
     this.ipAddr = ipAddr;
     this.ipAddr = ipAddr;
+    updateXferAddrAndInvalidateHashCode();
   }
   }
 
 
   public void setPeerHostName(String peerHostName) {
   public void setPeerHostName(String peerHostName) {
@@ -106,6 +110,7 @@ public class DatanodeID implements Comparable<DatanodeID> {
   @VisibleForTesting
   @VisibleForTesting
   public void setDatanodeUuidForTesting(String datanodeUuid) {
   public void setDatanodeUuidForTesting(String datanodeUuid) {
     this.datanodeUuid = datanodeUuid;
     this.datanodeUuid = datanodeUuid;
+    updateXferAddrAndInvalidateHashCode();
   }
   }
 
 
   private String checkDatanodeUuid(String uuid) {
   private String checkDatanodeUuid(String uuid) {
@@ -141,7 +146,7 @@ public class DatanodeID implements Comparable<DatanodeID> {
    * @return IP:xferPort string
    * @return IP:xferPort string
    */
    */
   public String getXferAddr() {
   public String getXferAddr() {
-    return ipAddr + ":" + xferPort;
+    return xferAddr;
   }
   }
 
 
   /**
   /**
@@ -237,7 +242,11 @@ public class DatanodeID implements Comparable<DatanodeID> {
   
   
   @Override
   @Override
   public int hashCode() {
   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
   @Override
@@ -257,6 +266,7 @@ public class DatanodeID implements Comparable<DatanodeID> {
     infoPort = nodeReg.getInfoPort();
     infoPort = nodeReg.getInfoPort();
     infoSecurePort = nodeReg.getInfoSecurePort();
     infoSecurePort = nodeReg.getInfoSecurePort();
     ipcPort = nodeReg.getIpcPort();
     ipcPort = nodeReg.getIpcPort();
+    updateXferAddrAndInvalidateHashCode();
   }
   }
     
     
   /**
   /**
@@ -269,4 +279,13 @@ public class DatanodeID implements Comparable<DatanodeID> {
   public int compareTo(DatanodeID that) {
   public int compareTo(DatanodeID that) {
     return getXferAddr().compareTo(that.getXferAddr());
     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;
+  }
 }
 }