From 55dca911cc67d498be5e0c58afb22e9d808c72d4 Mon Sep 17 00:00:00 2001 From: yu liang <62563545+liangyu-1@users.noreply.github.com> Date: Sun, 24 Mar 2024 10:14:27 +0800 Subject: [PATCH] HADOOP-19052.Hadoop use Shell command to get the count of the hard link which takes a lot of time (#6587) Contributed by liangyu. Signed-off-by: Shilun Fan --- .../java/org/apache/hadoop/fs/HardLink.java | 28 +++++++++++++++++++ .../org/apache/hadoop/fs/TestHardLink.java | 10 +++++++ 2 files changed, 38 insertions(+) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/HardLink.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/HardLink.java index 1624c5d395..5e46e73157 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/HardLink.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/HardLink.java @@ -23,6 +23,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.StringReader; +import java.nio.file.FileStore; +import java.nio.file.Files; import org.apache.hadoop.io.IOUtils; import org.apache.hadoop.util.Shell; @@ -30,6 +32,8 @@ import org.apache.hadoop.util.Shell.ShellCommandExecutor; import org.apache.hadoop.classification.VisibleForTesting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static java.nio.file.Files.createLink; @@ -50,6 +54,11 @@ public class HardLink { private static HardLinkCommandGetter getHardLinkCommand; public final LinkStats linkStats; //not static + + static final Logger LOG = LoggerFactory.getLogger(HardLink.class); + + private static final String FILE_ATTRIBUTE_VIEW = "unix"; + private static final String FILE_ATTRIBUTE = "unix:nlink"; //initialize the command "getters" statically, so can use their //methods without instantiating the HardLink object @@ -204,6 +213,21 @@ public static void createHardLinkMult(File parentDir, String[] fileBaseNames, } } + /** + * Determines whether the system supports hardlinks. + * @param f - file to examine + * @return true if hardlinks are supported, false otherwise + */ + public static boolean supportsHardLink(File f) { + try { + FileStore store = Files.getFileStore(f.toPath()); + return store.supportsFileAttributeView(FILE_ATTRIBUTE_VIEW); + } catch (IOException e) { + LOG.warn("Failed to determine if hardlink is supported", e); + return false; + } + } + /** * Retrieves the number of links to the specified file. * @@ -220,6 +244,10 @@ public static int getLinkCount(File fileName) throws IOException { throw new FileNotFoundException(fileName + " not found."); } + if (supportsHardLink(fileName)) { + return (int) Files.getAttribute(fileName.toPath(), FILE_ATTRIBUTE); + } + // construct and execute shell command String[] cmd = getHardLinkCommand.linkCount(fileName); String inpMsg = null; diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestHardLink.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestHardLink.java index b08e15ca11..98ae8df891 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestHardLink.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestHardLink.java @@ -219,6 +219,16 @@ public void testGetLinkCount() throws IOException { assertEquals(1, getLinkCount(x3)); } + @Test + public void testGetLinkCountFromFileAttribute() throws IOException { + assertTrue(supportsHardLink(x1)); + assertEquals(1, getLinkCount(x1)); + assertTrue(supportsHardLink(x2)); + assertEquals(1, getLinkCount(x2)); + assertTrue(supportsHardLink(x3)); + assertEquals(1, getLinkCount(x3)); + } + /** * Test the single-file method HardLink.createHardLink(). * Also tests getLinkCount() with values greater than one.