diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 6a701d6dcd6..077fc36ac28 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -1736,6 +1736,8 @@ Release 0.23.6 - UNRELEASED BUG FIXES + HDFS-4247. saveNamespace should be tolerant of dangling lease (daryn) + Release 0.23.5 - UNRELEASED 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 4f25b295c3e..b293d8c3637 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 @@ -4896,19 +4896,13 @@ public class FSNamesystem implements Namesystem, FSClusterStats, // lock on our behalf. If we took the read lock here, we could block // for fairness if a writer is waiting on the lock. synchronized (leaseManager) { - out.writeInt(leaseManager.countPath()); // write the size - - for (Lease lease : leaseManager.getSortedLeases()) { - for(String path : lease.getPaths()) { - // verify that path exists in namespace - final INodeFileUnderConstruction cons; - try { - cons = INodeFileUnderConstruction.valueOf(dir.getINode(path), path); - } catch (UnresolvedLinkException e) { - throw new AssertionError("Lease files should reside on this FS"); - } - FSImageSerialization.writeINodeUnderConstruction(out, cons, path); - } + Map nodes = + leaseManager.getINodesUnderConstruction(); + out.writeInt(nodes.size()); // write the size + for (Map.Entry entry + : nodes.entrySet()) { + FSImageSerialization.writeINodeUnderConstruction( + out, entry.getValue(), entry.getKey()); } } } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/LeaseManager.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/LeaseManager.java index b1764b7d3cb..0810e55a3ed 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/LeaseManager.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/LeaseManager.java @@ -429,6 +429,26 @@ public class LeaseManager { } } + /** + * Get the list of inodes corresponding to valid leases. + * @return list of inodes + * @throws UnresolvedLinkException + */ + Map getINodesUnderConstruction() { + Map inodes = + new TreeMap(); + for (String p : sortedLeasesByPath.keySet()) { + // verify that path exists in namespace + try { + INode node = fsnamesystem.dir.getINode(p); + inodes.put(p, INodeFileUnderConstruction.valueOf(node, p)); + } catch (IOException ioe) { + LOG.error(ioe); + } + } + return inodes; + } + /** Check the leases beginning from the oldest. * @return true is sync is needed. */ 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 d0764b98da6..f837a37bd35 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 @@ -603,6 +603,24 @@ public class TestSaveNamespace { } } + @Test + public void testSaveNamespaceWithDanglingLease() throws Exception { + MiniDFSCluster cluster = new MiniDFSCluster.Builder(new Configuration()) + .numDataNodes(1).build(); + cluster.waitActive(); + DistributedFileSystem fs = (DistributedFileSystem) cluster.getFileSystem(); + try { + cluster.getNamesystem().leaseManager.addLease("me", "/non-existent"); + fs.setSafeMode(SafeModeAction.SAFEMODE_ENTER); + cluster.getNameNodeRpc().saveNamespace(); + fs.setSafeMode(SafeModeAction.SAFEMODE_LEAVE); + } finally { + if (cluster != null) { + cluster.shutdown(); + } + } + } + private void doAnEdit(FSNamesystem fsn, int id) throws IOException { // Make an edit fsn.mkdirs(