Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,42 @@ private void SavePrefetchArgs(string targetCommit, bool hydrate)
}
}

/// <summary>
/// Updates the noop prefetch cache after a successful prefetch that was
/// handled externally (e.g. offloaded to the mount process). This mirrors
/// the logic in <see cref="SavePrefetchArgs"/> but is callable without a
/// BlobPrefetcher instance.
/// </summary>
public static void UpdateNoopCache(
FileBasedDictionary<string, string> prefetchCache,
int maxCacheSize,
string commitId,
List<string> files,
List<string> folders,
bool hydrate)
{
if (prefetchCache == null || maxCacheSize <= 0)
{
return;
}

string cacheKey = ComputeCacheKey(files, folders, hydrate);

Dictionary<string, string> allEntries = prefetchCache.GetAllKeysAndValues();
if (allEntries.Count >= maxCacheSize && !allEntries.ContainsKey(cacheKey))
{
using (Dictionary<string, string>.Enumerator enumerator = allEntries.GetEnumerator())
{
if (enumerator.MoveNext())
{
prefetchCache.RemoveAndFlush(enumerator.Current.Key);
}
}
}

prefetchCache.SetValueAndFlush(cacheKey, commitId);
}

internal static string ComputeCacheKey(List<string> files, List<string> folders, bool hydrate)
{
List<string> sortedFiles = new List<string>(files);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ public void PrefetchBlobsMountedReportsStats()
public void PrefetchBlobsUnmountedFallsBackToDirectAuth()
{
// Unmount, then blob prefetch should fall back to direct auth
// and still succeed.
// and still succeed. Use a file not prefetched by earlier tests
// so the noop cache doesn't short-circuit.
this.Enlistment.UnmountGVFS();

try
{
string output = this.Enlistment.Prefetch($"--files {Path.Combine("GVFS", "GVFS", "Program.cs")}");
string output = this.Enlistment.Prefetch($"--files {Path.Combine("GVFS", "GVFS.Common", "GVFSEnlistment.cs")}");
output.ShouldContain("Matched blobs:");
output.ShouldContain("Downloaded:");
}
Expand All @@ -69,12 +70,14 @@ public void PrefetchBlobsMountedWithFolders()
public void PrefetchBlobsMountedAfterRemount()
{
// After unmount + remount, blob prefetch should work via
// the mount process again.
// the mount process again. Since this file was already
// prefetched in Order(1), the noop cache correctly detects
// there's nothing new to download.
this.Enlistment.UnmountGVFS();
this.Enlistment.MountGVFS();

string output = this.Enlistment.Prefetch($"--files {Path.Combine("GVFS", "GVFS", "Program.cs")}");
output.ShouldContain("Matched blobs:");
output.ShouldContain("Nothing new to prefetch.");
Comment thread
tyrielv marked this conversation as resolved.
}
}
}
3 changes: 2 additions & 1 deletion GVFS/GVFS.Mount/InProcessMount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,8 @@ private void HandlePrefetchBlobsRequest(NamedPipeMessages.Message message, Named
objectRequestor,
request.Files,
request.Folders,
lastPrefetchArgs,
prefetchCache: null,
maxCacheSize: 0,
chunkSize: 4000,
searchThreadCount: maxThreads,
downloadThreadCount: downloadThreads,
Expand Down
12 changes: 10 additions & 2 deletions GVFS/GVFS/CommandLine/PrefetchVerb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,15 @@ protected override void Execute(GVFSEnlistment enlistment)
cacheServerFromConfig,
out objectRequestor,
out resolvedCacheServer);
this.PrefetchBlobs(tracer, enlistment, headCommitId, filesList, foldersList, lastPrefetchArgs, objectRequestor, resolvedCacheServer);
this.PrefetchBlobs(tracer, enlistment, headCommitId, filesList, foldersList, prefetchCache, prefetchCacheSize, objectRequestor, resolvedCacheServer);
}
else
{
// Mount handled download — now hydrate locally
// Mount handled download — hydrate locally, then update noop
// cache. Cache update is after hydration so a hydration failure
// doesn't suppress the retry on the next run.
this.HydrateMatchingFiles(tracer, enlistment, filesList, foldersList);
BlobPrefetcher.UpdateNoopCache(prefetchCache, prefetchCacheSize, headCommitId, filesList, foldersList, this.HydrateFiles);
}
}
else if (!this.TryPrefetchBlobsViaMountProcess(tracer, enlistment, filesList, foldersList, headCommitId))
Expand All @@ -251,6 +254,11 @@ protected override void Execute(GVFSEnlistment enlistment)
out resolvedCacheServer);
this.PrefetchBlobs(tracer, enlistment, headCommitId, filesList, foldersList, prefetchCache, prefetchCacheSize, objectRequestor, resolvedCacheServer);
}
else
{
// Mount handled download — update noop cache so repeat runs are skipped
BlobPrefetcher.UpdateNoopCache(prefetchCache, prefetchCacheSize, headCommitId, filesList, foldersList, hydrate: false);
Comment thread
tyrielv marked this conversation as resolved.
}
}
}
catch (VerbAbortedException)
Expand Down
Loading