From 81d64c9135b99ce85bbf7ebdce4f7ea5b7b77d35 Mon Sep 17 00:00:00 2001 From: Nasser Grainawi Date: Fri, 23 Feb 2024 09:34:37 -0800 Subject: Cache refreshed loose ref dirs in SnapshottingRefDirectory Update SnapshottingRefDirectory to have a cache of dirs refreshed for loose refs. This should help improve performance when 'after_open' setting is used for 'trustLooseRefStat' as duplicate refreshes are avoided when a snapshot of the ref database is used in a request scope. Change-Id: I8f66e7cee572e477d29abe2d9db69e97bca3ee4c Signed-off-by: Nasser Grainawi Co-authored-by: Martin Fick Co-authored-by: Kaushik Lingarkar --- .../storage/file/SnapshottingRefDirectory.java | 28 ++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'org.eclipse.jgit/src') diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java index 46607f60d9..1dc5776e06 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/SnapshottingRefDirectory.java @@ -16,15 +16,21 @@ import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.revwalk.RevWalk; +import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Snapshotting write-through cache of a {@link RefDirectory}. *

* This is intended to be short-term write-through snapshot based cache used in - * a request scope to avoid re-reading packed-refs on each read. A future - * improvement could also snapshot loose refs. + * a request scope to avoid re-reading packed-refs on each read and to avoid + * refreshing paths to a loose ref that has already been refreshed. *

* Only use this class when concurrent writes from other requests (not using the * same instance of SnapshottingRefDirectory) generally need not be visible to @@ -34,6 +40,7 @@ import java.util.List; */ class SnapshottingRefDirectory extends RefDirectory { final RefDirectory refDb; + private final Set refreshedLooseRefDirs = ConcurrentHashMap.newKeySet(); private volatile boolean isValid; @@ -66,6 +73,22 @@ class SnapshottingRefDirectory extends RefDirectory { return packedRefs.get(); } + @Override + void refreshPathToLooseRef(Path refPath) { + for (int i = 1; i < refPath.getNameCount(); i++) { + File dir = fileFor(refPath.subpath(0, i).toString()); + if (!refreshedLooseRefDirs.contains(dir)) { + try (InputStream stream = Files.newInputStream(dir.toPath())) { + // open the dir to refresh attributes (on some NFS clients) + } catch (IOException e) { + break; // loose ref may not exist + } finally { + refreshedLooseRefDirs.add(dir); + } + } + } + } + @Override void delete(RefDirectoryUpdate update) throws IOException { refreshSnapshot(); @@ -107,6 +130,7 @@ class SnapshottingRefDirectory extends RefDirectory { } synchronized void invalidateSnapshot() { + refreshedLooseRefDirs.clear(); isValid = false; } -- cgit v1.2.3