diff --git a/org.eclipse.jgit.ant.test/src/org/eclipse/jgit/ant/tasks/GitCloneTaskTest.java b/org.eclipse.jgit.ant.test/src/org/eclipse/jgit/ant/tasks/GitCloneTaskTest.java index 9f9d459a6..8043d2b18 100644 --- a/org.eclipse.jgit.ant.test/src/org/eclipse/jgit/ant/tasks/GitCloneTaskTest.java +++ b/org.eclipse.jgit.ant.test/src/org/eclipse/jgit/ant/tasks/GitCloneTaskTest.java @@ -66,7 +66,7 @@ public class GitCloneTaskTest extends LocalDiskRepositoryTestCase { @Before public void before() throws IOException { dest = createTempFile(); - FS.getFileStoreAttributeCache(dest.toPath().getParent()); + FS.getFileStoreAttributes(dest.toPath().getParent()); project = new Project(); project.init(); enableLogging(); diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java index fb8295fa4..af23ad1e3 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java @@ -130,7 +130,7 @@ public abstract class LocalDiskRepositoryTestCase { // measure timer resolution before the test to avoid time critical tests // are affected by time needed for measurement - FS.getFileStoreAttributeCache(tmp.toPath().getParent()); + FS.getFileStoreAttributes(tmp.toPath().getParent()); mockSystemReader = new MockSystemReader(); mockSystemReader.userGitConfig = new FileBasedConfig(new File(tmp, diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java index ebd13e411..5aacbbade 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/RepositoryTestCase.java @@ -378,7 +378,7 @@ public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase { tmp = File.createTempFile("fsTickTmpFile", null, lastFile.getParentFile()); } - long res = FS.getFileStoreAttributeCache(tmp.toPath()) + long res = FS.getFileStoreAttributes(tmp.toPath()) .getFsTimestampResolution().toNanos(); long sleepTime = res / 10; try { diff --git a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java index 92a6ec351..ec44da4ca 100644 --- a/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java +++ b/org.eclipse.jgit.lfs.server.test/tst/org/eclipse/jgit/lfs/server/fs/LfsServerTest.java @@ -123,7 +123,7 @@ public abstract class LfsServerTest { // measure timer resolution before the test to avoid time critical tests // are affected by time needed for measurement - FS.getFileStoreAttributeCache(tmp.getParent()); + FS.getFileStoreAttributes(tmp.getParent()); server = new AppServer(); ServletContextHandler app = server.addContext("/lfs"); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java index 012407f71..40af9e2a0 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileSnapshotTest.java @@ -62,7 +62,7 @@ import java.util.ArrayList; import java.util.concurrent.TimeUnit; import org.eclipse.jgit.util.FS; -import org.eclipse.jgit.util.FS.FileStoreAttributeCache; +import org.eclipse.jgit.util.FS.FileStoreAttributes; import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.Stats; import org.eclipse.jgit.util.SystemReader; @@ -79,7 +79,7 @@ public class FileSnapshotTest { private Path trash; - private FileStoreAttributeCache fsAttrCache; + private FileStoreAttributes fsAttrCache; @Before public void setUp() throws Exception { @@ -87,7 +87,7 @@ public class FileSnapshotTest { // measure timer resolution before the test to avoid time critical tests // are affected by time needed for measurement fsAttrCache = FS - .getFileStoreAttributeCache(trash.getParent()); + .getFileStoreAttributes(trash.getParent()); } @Before diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java index 77f5febc1..1adddb5ea 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileBasedConfigTest.java @@ -83,7 +83,7 @@ public class FileBasedConfigTest { @Before public void setUp() throws Exception { trash = Files.createTempDirectory("tmp_"); - FS.getFileStoreAttributeCache(trash.getParent()); + FS.getFileStoreAttributes(trash.getParent()); } @After diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java index 63e295ec8..2054e1efa 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FSTest.java @@ -203,7 +203,7 @@ public class FSTest { .ofPattern("uuuu-MMM-dd HH:mm:ss.nnnnnnnnn", Locale.ENGLISH) .withZone(ZoneId.systemDefault()); Path dir = Files.createTempDirectory("probe-filesystem"); - Duration resolution = FS.getFileStoreAttributeCache(dir) + Duration resolution = FS.getFileStoreAttributes(dir) .getFsTimestampResolution(); long resolutionNs = resolution.toNanos(); assertTrue(resolutionNs > 0); diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index a027caaf0..8277735e2 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -49,6 +49,12 @@ + + + + + + @@ -72,6 +78,14 @@ + + + + + + + + @@ -174,7 +188,7 @@ - + @@ -192,7 +206,7 @@ - + @@ -210,11 +224,11 @@ - + - + diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java index aa9f1cc45..e81a88451 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java @@ -43,7 +43,7 @@ package org.eclipse.jgit.internal.storage.file; -import static org.eclipse.jgit.util.FS.FileStoreAttributeCache.FALLBACK_FILESTORE_ATTRIBUTES; +import static org.eclipse.jgit.util.FS.FileStoreAttributes.FALLBACK_FILESTORE_ATTRIBUTES; import java.io.File; import java.io.IOException; @@ -58,7 +58,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.util.FS; -import org.eclipse.jgit.util.FS.FileStoreAttributeCache; +import org.eclipse.jgit.util.FS.FileStoreAttributes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -215,7 +215,7 @@ public class FileSnapshot { private final long size; /** measured FileStore attributes */ - private FileStoreAttributeCache fileStoreAttributeCache; + private FileStoreAttributes fileStoreAttributeCache; /** * Object that uniquely identifies the given file, or {@code @@ -254,7 +254,7 @@ public class FileSnapshot { this.file = file; this.lastRead = Instant.now(); this.fileStoreAttributeCache = useConfig - ? FS.getFileStoreAttributeCache(file.toPath().getParent()) + ? FS.getFileStoreAttributes(file.toPath().getParent()) : FALLBACK_FILESTORE_ATTRIBUTES; BasicFileAttributes fileAttributes = null; try { @@ -293,7 +293,7 @@ public class FileSnapshot { this.file = null; this.lastRead = read; this.lastModified = modified; - this.fileStoreAttributeCache = new FileStoreAttributeCache( + this.fileStoreAttributeCache = new FileStoreAttributes( fsTimestampResolution); this.size = size; this.fileKey = fileKey; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java index 4f636d455..82ccd7b03 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java @@ -444,4 +444,11 @@ public final class ConfigConstants { * @since 5.1.9 */ public static final String CONFIG_KEY_TIMESTAMP_RESOLUTION = "timestampResolution"; + + /** + * The "minRacyThreshold" key + * + * @since 5.1.9 + */ + public static final String CONFIG_KEY_MIN_RACY_THRESHOLD = "minRacyThreshold"; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java index 3a41643e6..633632dc0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java @@ -149,13 +149,37 @@ public class FileBasedConfig extends StoredConfig { */ @Override public void load() throws IOException, ConfigInvalidException { + load(true); + } + + /** + * Load the configuration as a Git text style configuration file. + *

+ * If the file does not exist, this configuration is cleared, and thus + * behaves the same as though the file exists, but is empty. + * + * @param useFileSnapshotWithConfig + * if {@code true} use the FileSnapshot with config, otherwise + * use it without config + * @throws IOException + * if IO failed + * @throws ConfigInvalidException + * if config is invalid + * @since 5.1.9 + */ + public void load(boolean useFileSnapshotWithConfig) + throws IOException, ConfigInvalidException { final int maxStaleRetries = 5; int retries = 0; while (true) { final FileSnapshot oldSnapshot = snapshot; - // don't use config in this snapshot to avoid endless recursion - final FileSnapshot newSnapshot = FileSnapshot - .saveNoConfig(getFile()); + final FileSnapshot newSnapshot; + if (useFileSnapshotWithConfig) { + newSnapshot = FileSnapshot.save(getFile()); + } else { + // don't use config in this snapshot to avoid endless recursion + newSnapshot = FileSnapshot.saveNoConfig(getFile()); + } try { final byte[] in = IO.readFully(getFile()); final ObjectId newHash = hash(in); 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 08dab3201..16810e0dc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -208,9 +208,9 @@ public abstract class FS { * * @since 5.1.9 */ - public final static class FileStoreAttributeCache { + public final static class FileStoreAttributes { - private static final Duration UNDEFINED_RESOLUTION = Duration + private static final Duration UNDEFINED_DURATION = Duration .ofNanos(Long.MAX_VALUE); /** @@ -218,10 +218,10 @@ public abstract class FS { * filesystem timestamp resolution. The last modified time granularity * of FAT filesystems is 2 seconds. */ - public static final FileStoreAttributeCache FALLBACK_FILESTORE_ATTRIBUTES = new FileStoreAttributeCache( + public static final FileStoreAttributes FALLBACK_FILESTORE_ATTRIBUTES = new FileStoreAttributes( Duration.ofMillis(2000)); - private static final Map attributeCache = new ConcurrentHashMap<>(); + private static final Map attributeCache = new ConcurrentHashMap<>(); private static AtomicBoolean background = new AtomicBoolean(); @@ -239,22 +239,24 @@ public abstract class FS { .ofMillis(10); /** + * Get the FileStoreAttributes for the given FileStore + * * @param path * file residing in the FileStore to get attributes for - * @return FileStoreAttributeCache entry for the given path. + * @return FileStoreAttributes for the given path. */ - public static FileStoreAttributeCache get(Path path) { + public static FileStoreAttributes get(Path path) { path = path.toAbsolutePath(); Path dir = Files.isDirectory(path) ? path : path.getParent(); - return getFileAttributeCache(dir); + return getFileStoreAttributes(dir); } - private static FileStoreAttributeCache getFileAttributeCache(Path dir) { + private static FileStoreAttributes getFileStoreAttributes(Path dir) { FileStore s; try { if (Files.exists(dir)) { s = Files.getFileStore(dir); - FileStoreAttributeCache c = attributeCache.get(s); + FileStoreAttributes c = attributeCache.get(s); if (c != null) { return c; } @@ -272,7 +274,8 @@ public abstract class FS { Thread.currentThread(), dir); return FALLBACK_FILESTORE_ATTRIBUTES; } - CompletableFuture> f = CompletableFuture + + CompletableFuture> f = CompletableFuture .supplyAsync(() -> { Lock lock = locks.computeIfAbsent(s, l -> new ReentrantLock()); @@ -282,21 +285,27 @@ public abstract class FS { Thread.currentThread(), dir); return Optional.empty(); } - Optional cache = Optional + Optional attributes = Optional .empty(); try { // Some earlier future might have set the value // and removed itself since we checked for the // value above. Hence check cache again. - FileStoreAttributeCache c = attributeCache + FileStoreAttributes c = attributeCache .get(s); if (c != null) { return Optional.of(c); } + attributes = readFromConfig(s); + if (attributes.isPresent()) { + attributeCache.put(s, attributes.get()); + return attributes; + } + Optional resolution = measureFsTimestampResolution( s, dir); if (resolution.isPresent()) { - c = new FileStoreAttributeCache( + c = new FileStoreAttributes( resolution.get()); attributeCache.put(s, c); // for high timestamp resolution measure @@ -304,24 +313,28 @@ public abstract class FS { if (c.fsTimestampResolution .toNanos() < 100_000_000L) { c.minimalRacyInterval = measureMinimalRacyInterval( - dir); + dir); } if (LOG.isDebugEnabled()) { LOG.debug(c.toString()); } - cache = Optional.of(c); + saveToConfig(s, c); } + attributes = Optional.of(c); } finally { lock.unlock(); locks.remove(s); } - return cache; + return attributes; }); + f.exceptionally(e -> { + LOG.error(e.getLocalizedMessage(), e); + return Optional.empty(); + }); // even if measuring in background wait a little - if the result // arrives, it's better than returning the large fallback - Optional d = f.get( - background.get() ? 100 : 5000, - TimeUnit.MILLISECONDS); + Optional d = background.get() ? f.get( + 100, TimeUnit.MILLISECONDS) : f.get(); if (d.isPresent()) { return d.get(); } @@ -341,14 +354,16 @@ public abstract class FS { private static Duration measureMinimalRacyInterval(Path dir) { LOG.debug("{}: start measure minimal racy interval in {}", //$NON-NLS-1$ Thread.currentThread(), dir); + int n = 0; int failures = 0; long racyNanos = 0; - final int COUNT = 1000; ArrayList deltas = new ArrayList<>(); Path probe = dir.resolve(".probe-" + UUID.randomUUID()); //$NON-NLS-1$ + Instant end = Instant.now().plusSeconds(3); try { Files.createFile(probe); - for (int i = 0; i < COUNT; i++) { + do { + n++; write(probe, "a"); //$NON-NLS-1$ FileSnapshot snapshot = FileSnapshot.save(probe.toFile()); read(probe); @@ -358,7 +373,7 @@ public abstract class FS { racyNanos = snapshot.lastRacyThreshold(); failures++; } - } + } while (Instant.now().compareTo(end) < 0); } catch (IOException e) { LOG.error(e.getMessage(), e); return FALLBACK_MIN_RACY_INTERVAL; @@ -376,7 +391,7 @@ public abstract class FS { + " delta max [ns], delta avg [ns]," //$NON-NLS-1$ + " delta stddev [ns]\n" //$NON-NLS-1$ + "{}, {}, {}, {}, {}, {}, {}", //$NON-NLS-1$ - COUNT, failures, racyNanos, stats.min(), stats.max(), + n, failures, racyNanos, stats.min(), stats.max(), stats.avg(), stats.stddev()); return Duration .ofNanos(Double.valueOf(stats.max()).longValue()); @@ -405,10 +420,6 @@ public abstract class FS { FileStore s, Path dir) { LOG.debug("{}: start measure timestamp resolution {} in {}", //$NON-NLS-1$ Thread.currentThread(), s, dir); - Duration configured = readFileTimeResolution(s); - if (!UNDEFINED_RESOLUTION.equals(configured)) { - return Optional.of(configured); - } Path probe = dir.resolve(".probe-" + UUID.randomUUID()); //$NON-NLS-1$ try { Files.createFile(probe); @@ -423,7 +434,6 @@ public abstract class FS { Duration fsResolution = Duration.between(t1.toInstant(), t2.toInstant()); Duration clockResolution = measureClockResolution(); fsResolution = fsResolution.plus(clockResolution); - saveFileTimeResolution(s, fsResolution); LOG.debug("{}: end measure timestamp resolution {} in {}", //$NON-NLS-1$ Thread.currentThread(), s, dir); return Optional.of(fsResolution); @@ -454,20 +464,20 @@ public abstract class FS { } private static void deleteProbe(Path probe) { - if (Files.exists(probe)) { - try { - Files.delete(probe); - } catch (IOException e) { - LOG.error(e.getLocalizedMessage(), e); - } + try { + FileUtils.delete(probe.toFile(), + FileUtils.SKIP_MISSING | FileUtils.RETRY); + } catch (IOException e) { + LOG.error(e.getMessage(), e); } } - private static Duration readFileTimeResolution(FileStore s) { + private static Optional readFromConfig( + FileStore s) { FileBasedConfig userConfig = SystemReader.getInstance() .openUserConfig(null, FS.DETECTED); try { - userConfig.load(); + userConfig.load(false); } catch (IOException e) { LOG.error(MessageFormat.format(JGitText.get().readConfigFailed, userConfig.getFile().getAbsolutePath()), e); @@ -477,49 +487,65 @@ public abstract class FS { userConfig.getFile().getAbsolutePath(), e.getMessage())); } - Duration configured = Duration - .ofNanos(userConfig.getTimeUnit( - ConfigConstants.CONFIG_FILESYSTEM_SECTION, - javaVersionPrefix + s.name(), - ConfigConstants.CONFIG_KEY_TIMESTAMP_RESOLUTION, - UNDEFINED_RESOLUTION.toNanos(), - TimeUnit.NANOSECONDS)); - return configured; + String key = getConfigKey(s); + Duration resolution = Duration.ofNanos(userConfig.getTimeUnit( + ConfigConstants.CONFIG_FILESYSTEM_SECTION, key, + ConfigConstants.CONFIG_KEY_TIMESTAMP_RESOLUTION, + UNDEFINED_DURATION.toNanos(), TimeUnit.NANOSECONDS)); + if (UNDEFINED_DURATION.equals(resolution)) { + return Optional.empty(); + } + Duration minRacyThreshold = Duration.ofNanos(userConfig.getTimeUnit( + ConfigConstants.CONFIG_FILESYSTEM_SECTION, key, + ConfigConstants.CONFIG_KEY_MIN_RACY_THRESHOLD, + UNDEFINED_DURATION.toNanos(), TimeUnit.NANOSECONDS)); + FileStoreAttributes c = new FileStoreAttributes(resolution); + if (!UNDEFINED_DURATION.equals(minRacyThreshold)) { + c.minimalRacyInterval = minRacyThreshold; + } + return Optional.of(c); } - private static void saveFileTimeResolution(FileStore s, - Duration resolution) { + private static void saveToConfig(FileStore s, + FileStoreAttributes c) { FileBasedConfig userConfig = SystemReader.getInstance() .openUserConfig(null, FS.DETECTED); - long nanos = resolution.toNanos(); - TimeUnit unit; - if (nanos < 200_000L) { - unit = TimeUnit.NANOSECONDS; - } else if (nanos < 200_000_000L) { - unit = TimeUnit.MICROSECONDS; - } else { - unit = TimeUnit.MILLISECONDS; - } + long resolution = c.getFsTimestampResolution().toNanos(); + TimeUnit resolutionUnit = getUnit(resolution); + long resolutionValue = resolutionUnit.convert(resolution, + TimeUnit.NANOSECONDS); + + long minRacyThreshold = c.getMinimalRacyInterval().toNanos(); + TimeUnit minRacyThresholdUnit = getUnit(minRacyThreshold); + long minRacyThresholdValue = minRacyThresholdUnit + .convert(minRacyThreshold, TimeUnit.NANOSECONDS); final int max_retries = 5; int retries = 0; boolean succeeded = false; - long value = unit.convert(nanos, TimeUnit.NANOSECONDS); + String key = getConfigKey(s); while (!succeeded && retries < max_retries) { try { - userConfig.load(); + userConfig.load(false); userConfig.setString( - ConfigConstants.CONFIG_FILESYSTEM_SECTION, - javaVersionPrefix + s.name(), + ConfigConstants.CONFIG_FILESYSTEM_SECTION, key, ConfigConstants.CONFIG_KEY_TIMESTAMP_RESOLUTION, String.format("%d %s", //$NON-NLS-1$ - Long.valueOf(value), - unit.name().toLowerCase())); + Long.valueOf(resolutionValue), + resolutionUnit.name().toLowerCase())); + userConfig.setString( + ConfigConstants.CONFIG_FILESYSTEM_SECTION, key, + ConfigConstants.CONFIG_KEY_MIN_RACY_THRESHOLD, + String.format("%d %s", //$NON-NLS-1$ + Long.valueOf(minRacyThresholdValue), + minRacyThresholdUnit.name().toLowerCase())); userConfig.save(); succeeded = true; } catch (LockFailedException e) { // race with another thread, wait a bit and try again try { + LOG.warn(MessageFormat.format(JGitText.get().cannotLock, + userConfig.getFile().getAbsolutePath())); retries++; Thread.sleep(20); } catch (InterruptedException e1) { @@ -538,6 +564,38 @@ public abstract class FS { } } + private static String getConfigKey(FileStore s) { + final String storeKey; + if (SystemReader.getInstance().isWindows()) { + Object attribute = null; + try { + attribute = s.getAttribute("volume:vsn"); //$NON-NLS-1$ + } catch (IOException ignored) { + // ignore + } + if (attribute instanceof Integer) { + storeKey = attribute.toString(); + } else { + storeKey = s.name(); + } + } else { + storeKey = s.name(); + } + return javaVersionPrefix + storeKey; + } + + private static TimeUnit getUnit(long nanos) { + TimeUnit unit; + if (nanos < 200_000L) { + unit = TimeUnit.NANOSECONDS; + } else if (nanos < 200_000_000L) { + unit = TimeUnit.MICROSECONDS; + } else { + unit = TimeUnit.MILLISECONDS; + } + return unit; + } + private final @NonNull Duration fsTimestampResolution; private Duration minimalRacyInterval; @@ -565,7 +623,7 @@ public abstract class FS { * * @param fsTimestampResolution */ - public FileStoreAttributeCache( + public FileStoreAttributes( @NonNull Duration fsTimestampResolution) { this.fsTimestampResolution = fsTimestampResolution; this.minimalRacyInterval = Duration.ZERO; @@ -575,7 +633,7 @@ public abstract class FS { @Override public String toString() { return String.format( - "FileStoreAttributeCache[fsTimestampResolution=%,d µs, " + "FileStoreAttributes[fsTimestampResolution=%,d µs, " + "minimalRacyInterval=%,d µs]", fsTimestampResolution.toNanos() / 1000, minimalRacyInterval.toNanos() / 1000); @@ -598,17 +656,16 @@ public abstract class FS { } /** - * Whether FileStore attribute cache entries should be determined - * asynchronously + * Whether FileStore attributes should be determined asynchronously * * @param asynch - * whether FileStore attribute cache entries should be determined + * whether FileStore attributes should be determined * asynchronously. If false access to cached attributes may block * for some seconds for the first call per FileStore * @since 5.1.9 */ - public static void setAsyncfileStoreAttrCache(boolean asynch) { - FileStoreAttributeCache.setBackground(asynch); + public static void setAsyncFileStoreAttributes(boolean asynch) { + FileStoreAttributes.setBackground(asynch); } /** @@ -639,9 +696,8 @@ public abstract class FS { } /** - * Get an estimate for the filesystem timestamp resolution from a cache of - * timestamp resolution per FileStore, if not yet available it is measured - * for a probe file under the given directory. + * Get cached FileStore attributes, if not yet available measure them using + * a probe file under the given directory. * * @param dir * the directory under which the probe file will be created to @@ -649,9 +705,9 @@ public abstract class FS { * @return measured filesystem timestamp resolution * @since 5.1.9 */ - public static FileStoreAttributeCache getFileStoreAttributeCache( + public static FileStoreAttributes getFileStoreAttributes( @NonNull Path dir) { - return FileStoreAttributeCache.get(dir); + return FileStoreAttributes.get(dir); } private volatile Holder userHome;