diff options
author | Thomas Wolf <thomas.wolf@paranor.ch> | 2019-05-18 23:48:54 +0200 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2019-06-06 19:06:09 +0200 |
commit | 1609ce75931b2caa4051b51a3e3e4d6fe242c2f9 (patch) | |
tree | e759294c516d9e35d8824dab0d3bf9e9efb01b9b /org.eclipse.jgit | |
parent | d7bd2e700c7eb1ea4f3b4a65087331c4ee96a9e5 (diff) | |
download | jgit-1609ce75931b2caa4051b51a3e3e4d6fe242c2f9.tar.gz jgit-1609ce75931b2caa4051b51a3e3e4d6fe242c2f9.zip |
Determine hard-linking and nlink support per FileStore
It's quite possible that JGit can use the hard-linking mechanism
for atomic file creation on some volumes but not on others.
Ultimately it depends on the file systems on the mounted volumes.
Cache the information per FileStore instead of using a single
global flag. Also catch FileSystemException, it may be thrown
if the operating system reports a failure. The previously caught
AccessDeniedException is a sub-class of FileSystemException.
Bug: 547332
Change-Id: I1ef672b3468b0be79e71674344f16f28f9d11ba1
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java index 716711e067..588855b1f8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java @@ -48,7 +48,8 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.nio.charset.Charset; -import java.nio.file.AccessDeniedException; +import java.nio.file.FileStore; +import java.nio.file.FileSystemException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -57,9 +58,11 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.api.errors.JGitInternalException; @@ -84,7 +87,7 @@ public class FS_POSIX extends FS { private static final int DEFAULT_UMASK = 0022; private volatile int umask = -1; - private volatile boolean supportsUnixNLink = true; + private static final Map<FileStore, Boolean> CAN_HARD_LINK = new ConcurrentHashMap<>(); private volatile AtomicFileCreation supportsAtomicCreateNewFile = AtomicFileCreation.UNDEFINED; @@ -388,12 +391,18 @@ public class FS_POSIX extends FS { if (!lock.createNewFile()) { return false; } - if (supportsAtomicCreateNewFile() || !supportsUnixNLink) { + if (supportsAtomicCreateNewFile()) { return true; } Path lockPath = lock.toPath(); Path link = null; + FileStore store = Files.getFileStore(lockPath); try { + Boolean canLink = CAN_HARD_LINK.computeIfAbsent(store, + s -> Boolean.TRUE); + if (canLink == Boolean.FALSE) { + return true; + } link = Files.createLink( Paths.get(lock.getAbsolutePath() + ".lnk"), //$NON-NLS-1$ lockPath); @@ -405,11 +414,11 @@ public class FS_POSIX extends FS { nlink)); return false; } else if (nlink < 2) { - supportsUnixNLink = false; + CAN_HARD_LINK.put(store, Boolean.FALSE); } return true; } catch (UnsupportedOperationException | IllegalArgumentException e) { - supportsUnixNLink = false; + CAN_HARD_LINK.put(store, Boolean.FALSE); return true; } finally { if (link != null) { @@ -448,12 +457,18 @@ public class FS_POSIX extends FS { if (!file.createNewFile()) { return token(false, null); } - if (supportsAtomicCreateNewFile() || !supportsUnixNLink) { + if (supportsAtomicCreateNewFile()) { return token(true, null); } Path link = null; Path path = file.toPath(); + FileStore store = Files.getFileStore(path); try { + Boolean canLink = CAN_HARD_LINK.computeIfAbsent(store, + s -> Boolean.TRUE); + if (canLink == Boolean.FALSE) { + return token(true, null); + } link = Files.createLink(Paths.get(uniqueLinkPath(file)), path); Integer nlink = (Integer) (Files.getAttribute(path, "unix:nlink")); //$NON-NLS-1$ @@ -462,12 +477,12 @@ public class FS_POSIX extends FS { JGitText.get().failedAtomicFileCreation, path, nlink)); return token(false, link); } else if (nlink.intValue() < 2) { - supportsUnixNLink = false; + CAN_HARD_LINK.put(store, Boolean.FALSE); } return token(true, link); } catch (UnsupportedOperationException | IllegalArgumentException - | AccessDeniedException | SecurityException e) { - supportsUnixNLink = false; + | FileSystemException | SecurityException e) { + CAN_HARD_LINK.put(store, Boolean.FALSE); return token(true, link); } } |