From 8dfef7d2dcc3d6b695d1a5794a15458428a12d1a Mon Sep 17 00:00:00 2001 From: Tsz-wo Sze Date: Tue, 31 Jan 2012 17:36:42 +0000 Subject: [PATCH] HDFS-2827. When the parent of a directory is the root, renaming the directory results in leases updated incorrectly. Contributed by Uma Maheswara Rao G git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1238700 13f79535-47bb-0310-9956-ffa450edef68 --- hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 4 ++ .../hdfs/server/namenode/FSNamesystem.java | 11 +++++- .../server/namenode/TestSaveNamespace.java | 39 +++++++++++++++++-- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 6257c48f43..3277ab2fc4 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -378,6 +378,10 @@ Release 0.23.1 - UNRELEASED HDFS-2791. If block report races with closing of file, replica is incorrectly marked corrupt. (todd) + HDFS-2827. When the parent of a directory is the root, renaming the + directory results in leases updated incorrectly. (Uma Maheswara Rao G + via szetszwo) + Release 0.23.0 - 2011-11-01 INCOMPATIBLE CHANGES diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java index c718c7dffd..efd6b9fb96 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java @@ -3907,7 +3907,12 @@ void unprotectedChangeLease(String src, String dst, HdfsFileStatus dinfo) { if (destinationExisted && dinfo.isDir()) { Path spath = new Path(src); - overwrite = spath.getParent().toString() + Path.SEPARATOR; + Path parent = spath.getParent(); + if (isRoot(parent)) { + overwrite = parent.toString(); + } else { + overwrite = parent.toString() + Path.SEPARATOR; + } replaceBy = dst + Path.SEPARATOR; } else { overwrite = src; @@ -3917,6 +3922,10 @@ void unprotectedChangeLease(String src, String dst, HdfsFileStatus dinfo) { leaseManager.changeLease(src, dst, overwrite, replaceBy); } + private boolean isRoot(Path path) { + return path.getParent() == null; + } + /** * Serializes leases. */ diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSaveNamespace.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSaveNamespace.java index 25a458b0c4..ed2162b7b9 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSaveNamespace.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestSaveNamespace.java @@ -18,9 +18,10 @@ package org.apache.hadoop.hdfs.server.namenode; import static org.apache.hadoop.hdfs.server.common.Util.fileAsURI; - -import static org.junit.Assert.*; - +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Matchers.anyObject; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; @@ -28,6 +29,7 @@ import java.io.File; import java.io.IOException; +import java.io.OutputStream; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -38,16 +40,19 @@ import org.apache.commons.logging.impl.Log4JLogger; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.PermissionStatus; import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSTestUtil; +import org.apache.hadoop.hdfs.DistributedFileSystem; import org.apache.hadoop.hdfs.HdfsConfiguration; import org.apache.hadoop.hdfs.MiniDFSCluster; import org.apache.hadoop.hdfs.protocol.HdfsConstants.SafeModeAction; import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NamenodeRole; import org.apache.hadoop.hdfs.server.common.Storage.StorageDirectory; import org.apache.hadoop.hdfs.util.MD5FileUtils; +import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.test.GenericTestUtils.DelayAnswer; import org.apache.log4j.Level; @@ -565,6 +570,34 @@ public Void call() throws Exception { } } } + + /** + * Test for save namespace should succeed when parent directory renamed with + * open lease and destination directory exist. + * This test is a regression for HDFS-2827 + */ + @Test + public void testSaveNamespaceWithRenamedLease() throws Exception { + MiniDFSCluster cluster = new MiniDFSCluster.Builder(new Configuration()) + .numDataNodes(1).build(); + cluster.waitActive(); + DistributedFileSystem fs = (DistributedFileSystem) cluster.getFileSystem(); + OutputStream out = null; + try { + fs.mkdirs(new Path("/test-target")); + out = fs.create(new Path("/test-source/foo")); // don't close + fs.rename(new Path("/test-source/"), new Path("/test-target/")); + + fs.setSafeMode(SafeModeAction.SAFEMODE_ENTER); + cluster.getNameNodeRpc().saveNamespace(); + fs.setSafeMode(SafeModeAction.SAFEMODE_LEAVE); + } finally { + IOUtils.cleanup(LOG, out, fs); + if (cluster != null) { + cluster.shutdown(); + } + } + } private void doAnEdit(FSNamesystem fsn, int id) throws IOException { // Make an edit