From 850b9d7540025a974870bc75a2412ee91469a198 Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Fri, 21 Jun 2019 11:00:05 +0200 Subject: [PATCH] Timeout measuring file timestamp resolution after 2 seconds It was reported that measuring file timestamp resolution may hang indefinitely on nfs. Hence timeout this measurement at the known worst filesystem timestamp resolution (FAT) of 2 seconds. Bug: 548188 Change-Id: I17004b0aa49d5b0e76360a008af3adb911b289c0 Signed-off-by: Matthias Sohn --- .../eclipse/jgit/internal/JGitText.properties | 1 + .../src/org/eclipse/jgit/internal/JGitText.java | 1 + .../src/org/eclipse/jgit/util/FS.java | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index b7805b19e..0a2f7029e 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -680,6 +680,7 @@ theFactoryMustNotBeNull=The factory must not be null threadInterruptedWhileRunning="Current thread interrupted while running {0}" timeIsUncertain=Time is uncertain timerAlreadyTerminated=Timer already terminated +timeoutMeasureFsTimestampResolution=measuring filesystem timestamp resolution for ''{0}'' timed out, fall back to resolution of 2 seconds tooManyCommands=Too many commands tooManyFilters=Too many "filter" lines in request tooManyIncludeRecursions=Too many recursions; circular includes in config file(s)? diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index da0ba4a77..bcd6d5ce2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -737,6 +737,7 @@ public class JGitText extends TranslationBundle { /***/ public String tagAlreadyExists; /***/ public String tagNameInvalid; /***/ public String tagOnRepoWithoutHEADCurrentlyNotSupported; + /***/ public String timeoutMeasureFsTimestampResolution; /***/ public String transactionAborted; /***/ public String theFactoryMustNotBeNull; /***/ public String threadInterruptedWhileRunning; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java index e559d2167..e7db6cee7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -208,7 +208,7 @@ public abstract class FS { FileStore s = Files.getFileStore(dir); FileStoreAttributeCache c = attributeCache.get(s); if (c == null) { - c = new FileStoreAttributeCache(dir); + c = new FileStoreAttributeCache(s, dir); attributeCache.put(s, c); if (LOG.isDebugEnabled()) { LOG.debug(c.toString()); @@ -228,16 +228,24 @@ public abstract class FS { return fsTimestampResolution; } - private FileStoreAttributeCache(Path dir) + private FileStoreAttributeCache(FileStore s, Path dir) throws IOException, InterruptedException { Path probe = dir.resolve(".probe-" + UUID.randomUUID()); //$NON-NLS-1$ Files.createFile(probe); try { + long start = System.nanoTime(); FileTime startTime = Files.getLastModifiedTime(probe); FileTime actTime = startTime; long sleepTime = 512; while (actTime.compareTo(startTime) <= 0) { TimeUnit.NANOSECONDS.sleep(sleepTime); + if (timeout(start)) { + LOG.warn(MessageFormat.format(JGitText + .get().timeoutMeasureFsTimestampResolution, + s.toString())); + fsTimestampResolution = FALLBACK_TIMESTAMP_RESOLUTION; + return; + } FileUtils.touch(probe); actTime = Files.getLastModifiedTime(probe); // limit sleep time to max. 100ms @@ -254,6 +262,11 @@ public abstract class FS { } } + private static boolean timeout(long start) { + return System.nanoTime() - start >= FALLBACK_TIMESTAMP_RESOLUTION + .toNanos(); + } + @SuppressWarnings("nls") @Override public String toString() {