Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Sohn2019-07-08 08:20:16 +0000
committerMatthias Sohn2019-07-19 12:45:55 +0000
commit99d351d0cbcf93502a5a6888c4032b8bb1fc2e92 (patch)
treeee057d71ca56dc39869fd1de75a44f23c47390cb /org.eclipse.jgit/src
parent37f7679fc956729a5e06509593c7cfc0d5801a2c (diff)
downloadjgit-99d351d0cbcf93502a5a6888c4032b8bb1fc2e92.tar.gz
jgit-99d351d0cbcf93502a5a6888c4032b8bb1fc2e92.tar.xz
jgit-99d351d0cbcf93502a5a6888c4032b8bb1fc2e92.zip
Measure stored timestamp resolution instead of time to touch file
Measure granularity of timestamps stored in the filesystem by setting and then getting lastModified timestamp until the read value changed. Increase increment exponentially to limit number of iterations starting with 1 microsecond since Java's FileTime (up to Java 12) truncates timestamps to 1 microsecond resolution. The chosen algorithm yields 2000 steps between 1 ms and 2.5 s. Also measure clock resolution and add that for the total timestamp resolution. This avoids systematic measurement errors introduced by doing IO to touch a file. Change-Id: I9b37138619422452373e298d9d8c7cb2c384db3f Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java49
1 files changed, 24 insertions, 25 deletions
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 7a03593aba..e33c4bff96 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -299,46 +299,45 @@ public abstract class FS {
Path probe = dir.resolve(".probe-" + UUID.randomUUID()); //$NON-NLS-1$
try {
Files.createFile(probe);
- // ensure we always use the local system clock
- FileUtils.touch(probe);
- long wait = 512;
- long start = System.nanoTime();
FileTime t1 = Files.getLastModifiedTime(probe);
FileTime t2 = t1;
- while (t2.compareTo(t1) <= 0) {
- TimeUnit.NANOSECONDS.sleep(wait);
- checkTimeout(s, start);
- FileUtils.touch(probe);
+ Instant t1i = t1.toInstant();
+ for (long i = 1; t2.compareTo(t1) <= 0; i += 1 + i / 20) {
+ Files.setLastModifiedTime(probe,
+ FileTime.from(t1i.plusNanos(i * 1000)));
t2 = Files.getLastModifiedTime(probe);
- if (wait < 100_000_000L) {
- wait = wait * 2;
- }
}
- Duration resolution = Duration.between(t1.toInstant(), t2.toInstant());
- saveFileTimeResolution(s, resolution);
- return Optional.of(resolution);
+ Duration fsResolution = Duration.between(t1.toInstant(), t2.toInstant());
+ Duration clockResolution = measureClockResolution();
+ fsResolution = fsResolution.plus(clockResolution);
+ saveFileTimeResolution(s, fsResolution);
+ return Optional.of(fsResolution);
} catch (AccessDeniedException e) {
LOG.warn(e.getLocalizedMessage(), e); // see bug 548648
- } catch (IOException | TimeoutException e) {
- LOG.error(e.getLocalizedMessage(), e);
- } catch (InterruptedException e) {
+ } catch (IOException e) {
LOG.error(e.getLocalizedMessage(), e);
- Thread.currentThread().interrupt();
} finally {
deleteProbe(probe);
}
return Optional.empty();
}
- private static void checkTimeout(FileStore s, long start)
- throws TimeoutException {
- if (System.nanoTime() - start >= FALLBACK_TIMESTAMP_RESOLUTION
- .toNanos()) {
- throw new TimeoutException(MessageFormat.format(JGitText
- .get().timeoutMeasureFsTimestampResolution,
- s.toString()));
+ private static Duration measureClockResolution() {
+ Duration clockResolution = Duration.ZERO;
+ for (int i = 0; i < 10; i++) {
+ Instant t1 = Instant.now();
+ Instant t2 = t1;
+ while (t2.compareTo(t1) <= 0) {
+ t2 = Instant.now();
+ }
+ Duration r = Duration.between(t1, t2);
+ if (r.compareTo(clockResolution) > 0) {
+ clockResolution = r;
+ }
}
+ return clockResolution;
}
+
private static void deleteProbe(Path probe) {
if (Files.exists(probe)) {
try {

Back to the top