diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 45ae0691c67..d511db5f08c 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -1726,6 +1726,8 @@ Release 0.23.5 - UNRELEASED HDFS-4172. namenode does not URI-encode parameters when building URI for datanode request (Derek Dagit via bobby) + HDFS-4182. SecondaryNameNode leaks NameCache entries (bobby) + Release 0.23.4 - UNRELEASED INCOMPATIBLE CHANGES diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java index ef9ab48d262..4d2888db24b 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java @@ -59,6 +59,7 @@ import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.BlockUCState; import org.apache.hadoop.hdfs.util.ByteArray; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; /************************************************* @@ -173,6 +174,12 @@ void setReady() { writeUnlock(); } } + + //This is for testing purposes only + @VisibleForTesting + boolean isReady() { + return ready; + } // exposed for unit tests protected void setReady(boolean flag) { @@ -2003,9 +2010,16 @@ private boolean unprotectedSetTimes(String src, INode inode, long mtime, * Reset the entire namespace tree. */ void reset() { - rootDir = new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME, - getFSNamesystem().createFsOwnerPermissions(new FsPermission((short)0755)), - Integer.MAX_VALUE, -1); + writeLock(); + try { + setReady(false); + rootDir = new INodeDirectoryWithQuota(INodeDirectory.ROOT_NAME, + getFSNamesystem().createFsOwnerPermissions(new FsPermission((short)0755)), + Integer.MAX_VALUE, -1); + nameCache.reset(); + } finally { + writeUnlock(); + } } /** diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameCache.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameCache.java index 59c0a30b07f..cf4f9a739da 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameCache.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameCache.java @@ -152,4 +152,14 @@ private void promote(final K name) { cache.put(name, name); lookups += useThreshold; } + + public void reset() { + initialized = false; + cache.clear(); + if (transientMap == null) { + transientMap = new HashMap(); + } else { + transientMap.clear(); + } + } } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java index 9b1b9fcab58..cd6227397ba 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/SecondaryNameNode.java @@ -886,6 +886,7 @@ static void doMerge( "just been downloaded"); } dstImage.reloadFromImageFile(file, dstNamesystem); + dstNamesystem.dir.imageLoadComplete(); } Checkpointer.rollForwardByApplyingLogs(manifest, dstImage, dstNamesystem); diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameCache.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameCache.java index 8d635f63bc0..e32e77e3519 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameCache.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestNameCache.java @@ -58,6 +58,17 @@ public void testDictionary() throws Exception { for (String s : notMatching) { verifyNameReuse(cache, s, false); } + + cache.reset(); + cache.initialized(); + + for (String s : matching) { + verifyNameReuse(cache, s, false); + } + + for (String s : notMatching) { + verifyNameReuse(cache, s, false); + } } private void verifyNameReuse(NameCache cache, String s, boolean reused) {