Skip to content

Commit

Permalink
Reliability update:
Browse files Browse the repository at this point in the history
- Improved handling of IO timeouts
- Made it easier to discover and configure cache servers
- Improved reliability of GVFS.Service
- More repair options
- Many other perf and bug fixes
  • Loading branch information
sanoursa committed Aug 17, 2017
1 parent 522d018 commit 153006d
Show file tree
Hide file tree
Showing 220 changed files with 7,397 additions and 4,129 deletions.
7 changes: 6 additions & 1 deletion GVFS.sln
Expand Up @@ -22,7 +22,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GVFS", "GVFS", "{2EF2EC94-3
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GVFS.GVFlt", "GVFS\GVFS.GVFlt\GVFS.GVFlt.csproj", "{1118B427-7063-422F-83B9-5023C8EC5A7A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GVFS.GvFltWrapper", "GVFS\GVFS.GvFltWrapper\GVFS.GvFltWrapper.vcxproj", "{FB0831AE-9997-401B-B31F-3A065FDBEB20}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GvFlt", "GVFS\GVFS.GvFltWrapper\GvFlt.vcxproj", "{FB0831AE-9997-401B-B31F-3A065FDBEB20}"
ProjectSection(ProjectDependencies) = postProject
{5A6656D5-81C7-472C-9DC8-32D071CB2258} = {5A6656D5-81C7-472C-9DC8-32D071CB2258}
{374BF1E5-0B2D-4D4A-BD5E-4212299DEF09} = {374BF1E5-0B2D-4D4A-BD5E-4212299DEF09}
Expand Down Expand Up @@ -61,10 +61,15 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GVFS.Hooks", "GVFS\GVFS.Hooks\GVFS.Hooks.csproj", "{BDA91EE5-C684-4FC5-A90A-B7D677421917}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GVFS.Service", "GVFS\GVFS.Service\GVFS.Service.csproj", "{B8C1DFBA-CAFD-4F7E-A1A3-E11907B5467B}"
ProjectSection(ProjectDependencies) = postProject
{5A6656D5-81C7-472C-9DC8-32D071CB2258} = {5A6656D5-81C7-472C-9DC8-32D071CB2258}
{BDA91EE5-C684-4FC5-A90A-B7D677421917} = {BDA91EE5-C684-4FC5-A90A-B7D677421917}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GVFS.Mount", "GVFS\GVFS.Mount\GVFS.Mount.csproj", "{17498502-AEFF-4E70-90CC-1D0B56A8ADF5}"
ProjectSection(ProjectDependencies) = postProject
{5A6656D5-81C7-472C-9DC8-32D071CB2258} = {5A6656D5-81C7-472C-9DC8-32D071CB2258}
{BDA91EE5-C684-4FC5-A90A-B7D677421917} = {BDA91EE5-C684-4FC5-A90A-B7D677421917}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GVFS.ReadObjectHook", "GVFS\GVFS.ReadObjectHook\GVFS.ReadObjectHook.vcxproj", "{5A6656D5-81C7-472C-9DC8-32D071CB2258}"
Expand Down
68 changes: 47 additions & 21 deletions GVFS/FastFetch/CheckoutFetchHelper.cs
Expand Up @@ -2,10 +2,12 @@
using FastFetch.Jobs;
using GVFS.Common;
using GVFS.Common.Git;
using GVFS.Common.Http;
using GVFS.Common.Tracing;
using Microsoft.Diagnostics.Tracing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace FastFetch
Expand All @@ -18,12 +20,13 @@ public class CheckoutFetchHelper : FetchHelper
public CheckoutFetchHelper(
ITracer tracer,
Enlistment enlistment,
GitObjectsHttpRequestor objectRequestor,
int chunkSize,
int searchThreadCount,
int downloadThreadCount,
int indexThreadCount,
int checkoutThreadCount,
bool allowIndexMetadataUpdateFromWorkingTree) : base(tracer, enlistment, chunkSize, searchThreadCount, downloadThreadCount, indexThreadCount)
bool allowIndexMetadataUpdateFromWorkingTree) : base(tracer, enlistment, objectRequestor, chunkSize, searchThreadCount, downloadThreadCount, indexThreadCount)
{
this.checkoutThreadCount = checkoutThreadCount;
this.allowIndexMetadataUpdateFromWorkingTree = allowIndexMetadataUpdateFromWorkingTree;
Expand Down Expand Up @@ -51,7 +54,7 @@ public override void FastFetch(string branchOrCommit, bool isBranch)
throw new FetchException("Could not find branch {0} in info/refs from: {1}", branchOrCommit, this.Enlistment.RepoUrl);
}

commitToFetch = refs.GetTipCommitIds().Single();
commitToFetch = refs.GetTipCommitId(branchOrCommit);
}
else
{
Expand Down Expand Up @@ -98,7 +101,7 @@ public override void FastFetch(string branchOrCommit, bool isBranch)
if (isBranch)
{
// Update the refspec before setting the upstream or git will complain the remote branch doesn't exist
this.HasFailures |= !RefSpecHelpers.UpdateRefSpec(this.Tracer, this.Enlistment, branchOrCommit, refs);
this.HasFailures |= !this.UpdateRefSpec(this.Tracer, this.Enlistment, branchOrCommit, refs);

using (ITracer activity = this.Tracer.StartActivity("SetUpstream", EventLevel.Informational))
{
Expand All @@ -113,27 +116,30 @@ public override void FastFetch(string branchOrCommit, bool isBranch)
}
}

bool indexSigningIsOff = this.GetIsIndexSigningOff();
bool shouldSignIndex = !this.GetIsIndexSigningOff();

// Update the index
EventMetadata updateIndexMetadata = new EventMetadata();
updateIndexMetadata.Add("IndexSigningIsOff", indexSigningIsOff);
updateIndexMetadata.Add("IndexSigningIsOff", shouldSignIndex);
using (ITracer activity = this.Tracer.StartActivity("UpdateIndex", EventLevel.Informational, Keywords.Telemetry, updateIndexMetadata))
{
// Create the index object now so it can track the current index
Index index = indexSigningIsOff ? new Index(this.Enlistment.EnlistmentRoot, activity) : null;

GitIndexGenerator indexGen = new GitIndexGenerator(this.Tracer, this.Enlistment, !indexSigningIsOff);
indexGen.CreateFromHeadTree();
this.HasFailures = indexGen.HasFailures;

if (!indexGen.HasFailures && index != null)
Index sourceIndex = this.GetSourceIndex();
GitIndexGenerator indexGen = new GitIndexGenerator(this.Tracer, this.Enlistment, shouldSignIndex);
indexGen.CreateFromHeadTree(indexVersion: 2);
this.HasFailures |= indexGen.HasFailures;

if (!indexGen.HasFailures)
{
Index newIndex = new Index(
this.Enlistment.EnlistmentRoot,
this.Tracer,
Path.Combine(this.Enlistment.DotGitRoot, GVFSConstants.DotGit.IndexName),
readOnly: false);

// Update from disk only if the caller says it is ok via command line
// or if we updated the whole tree and know that all files are up to date
bool allowIndexMetadataUpdateFromWorkingTree = this.allowIndexMetadataUpdateFromWorkingTree || checkout.UpdatedWholeTree;

index.UpdateFileSizesAndTimes(checkout.AddedOrEditedLocalFiles, allowIndexMetadataUpdateFromWorkingTree);
newIndex.UpdateFileSizesAndTimes(checkout.AddedOrEditedLocalFiles, allowIndexMetadataUpdateFromWorkingTree, shouldSignIndex, sourceIndex);
}
}
}
Expand All @@ -146,24 +152,44 @@ public override void FastFetch(string branchOrCommit, bool isBranch)
/// </summary>
protected override void UpdateRefs(string branchOrCommit, bool isBranch, GitRefs refs)
{
UpdateRefsHelper refHelper = new UpdateRefsHelper(this.Enlistment);

if (isBranch)
{
KeyValuePair<string, string> remoteRef = refs.GetBranchRefPairs().Single();
string remoteBranch = remoteRef.Key;

string fullLocalBranchName = branchOrCommit.StartsWith("refs/heads/") ? branchOrCommit : ("refs/heads/" + branchOrCommit);
this.HasFailures |= !refHelper.UpdateRef(this.Tracer, fullLocalBranchName, remoteRef.Value);
this.HasFailures |= !refHelper.UpdateRef(this.Tracer, "HEAD", fullLocalBranchName);
string fullLocalBranchName = branchOrCommit.StartsWith(RefsHeadsGitPath) ? branchOrCommit : (RefsHeadsGitPath + branchOrCommit);
this.HasFailures |= !this.UpdateRef(this.Tracer, fullLocalBranchName, remoteRef.Value);
this.HasFailures |= !this.UpdateRef(this.Tracer, "HEAD", fullLocalBranchName);
}
else
{
this.HasFailures |= !refHelper.UpdateRef(this.Tracer, "HEAD", branchOrCommit);
this.HasFailures |= !this.UpdateRef(this.Tracer, "HEAD", branchOrCommit);
}

base.UpdateRefs(branchOrCommit, isBranch, refs);
}

private Index GetSourceIndex()
{
string indexPath = Path.Combine(this.Enlistment.DotGitRoot, GVFSConstants.DotGit.IndexName);
string backupIndexPath = Path.Combine(this.Enlistment.DotGitRoot, GVFSConstants.DotGit.IndexName + ".backup");

if (File.Exists(indexPath))
{
// Note that this moves the current index, leaving nothing behind
// This is intentional as we only need it for the purpose of updating the
// new index and leaving it behind can make updating slower.
this.Tracer.RelatedEvent(EventLevel.Informational, "CreateBackup", new EventMetadata() { { "BackupIndexName", backupIndexPath } });
File.Delete(backupIndexPath);
File.Move(indexPath, backupIndexPath);

Index output = new Index(this.Enlistment.EnlistmentRoot, this.Tracer, backupIndexPath, readOnly: true);
output.Parse();
return output;
}

return null;
}

private bool GetIsIndexSigningOff()
{
Expand Down
4 changes: 2 additions & 2 deletions GVFS/FastFetch/FastFetch.csproj
Expand Up @@ -67,13 +67,14 @@
<Compile Include="FastFetchVerb.cs" />
<Compile Include="CheckoutFetchHelper.cs" />
<Compile Include="FetchHelper.cs" />
<Compile Include="Git\BigEndianReader.cs" />
<Compile Include="Git\EndianHelper.cs" />
<Compile Include="Git\GitIndexGenerator.cs" />
<Compile Include="HashingStream.cs" />
<Compile Include="WorkingTree.cs" />
<Compile Include="GitEnlistment.cs" />
<Compile Include="Git\DiffHelper.cs" />
<Compile Include="Git\GitPackIndex.cs" />
<Compile Include="Git\RefSpecHelpers.cs" />
<Compile Include="Index.cs" />
<Compile Include="Jobs\BatchObjectDownloadJob.cs" />
<Compile Include="Jobs\CheckoutJob.cs" />
Expand All @@ -83,7 +84,6 @@
<Compile Include="Jobs\FindMissingBlobsJob.cs" />
<Compile Include="Jobs\IndexPackJob.cs" />
<Compile Include="Jobs\Job.cs" />
<Compile Include="Git\UpdateRefsHelper.cs" />
<Compile Include="PathConverter.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
38 changes: 25 additions & 13 deletions GVFS/FastFetch/FastFetchVerb.cs
@@ -1,6 +1,7 @@
using CommandLine;
using GVFS.Common;
using GVFS.Common.Git;
using GVFS.Common.Http;
using GVFS.Common.Tracing;
using Microsoft.Diagnostics.Tracing;
using System;
Expand Down Expand Up @@ -87,9 +88,9 @@ public class FastFetchVerb
"max-retries",
Required = false,
Default = 10,
HelpText = "Sets the maximum number of retries for downloading a pack")]
HelpText = "Sets the maximum number of attempts for downloading a pack")]

public int MaxRetries { get; set; }
public int MaxAttempts { get; set; }

[Option(
"git-path",
Expand Down Expand Up @@ -157,17 +158,15 @@ private int ExecuteWithExitCode()
Console.WriteLine("Cannot specify both a commit sha and a branch name.");
return ExitFailure;
}

this.CacheServerUrl = Enlistment.StripObjectsEndpointSuffix(this.CacheServerUrl);


this.SearchThreadCount = this.SearchThreadCount > 0 ? this.SearchThreadCount : Environment.ProcessorCount;
this.DownloadThreadCount = this.DownloadThreadCount > 0 ? this.DownloadThreadCount : Math.Min(Environment.ProcessorCount, MaxDefaultDownloadThreads);
this.IndexThreadCount = this.IndexThreadCount > 0 ? this.IndexThreadCount : Environment.ProcessorCount;
this.CheckoutThreadCount = this.CheckoutThreadCount > 0 ? this.CheckoutThreadCount : Environment.ProcessorCount;

this.GitBinPath = !string.IsNullOrWhiteSpace(this.GitBinPath) ? this.GitBinPath : GitProcess.GetInstalledGitBinPath();

GitEnlistment enlistment = GitEnlistment.CreateFromCurrentDirectory(this.CacheServerUrl, this.GitBinPath);
GitEnlistment enlistment = GitEnlistment.CreateFromCurrentDirectory(this.GitBinPath);
if (enlistment == null)
{
Console.WriteLine("Must be run within a git repo");
Expand Down Expand Up @@ -206,19 +205,28 @@ private int ExecuteWithExitCode()

string fastfetchLogFile = Enlistment.GetNewLogFileName(enlistment.FastFetchLogRoot, "fastfetch");
tracer.AddLogFileEventListener(fastfetchLogFile, EventLevel.Informational, Keywords.Any);

RetryConfig retryConfig = new RetryConfig(this.MaxAttempts, TimeSpan.FromMinutes(RetryConfig.FetchAndCloneTimeoutMinutes));

string error;
CacheServerInfo cacheServer;
if (!CacheServerInfo.TryDetermineCacheServer(this.CacheServerUrl, tracer, enlistment, retryConfig, out cacheServer, out error))
{
tracer.RelatedError(error);
return ExitFailure;
}

tracer.WriteStartEvent(
enlistment.EnlistmentRoot,
enlistment.RepoUrl,
enlistment.CacheServerUrl,
cacheServer.Url,
new EventMetadata
{
{ "TargetCommitish", commitish },
{ "Checkout", this.Checkout },
});

FetchHelper fetchHelper = this.GetFetchHelper(tracer, enlistment);
fetchHelper.MaxRetries = this.MaxRetries;


FetchHelper fetchHelper = this.GetFetchHelper(tracer, enlistment, cacheServer, retryConfig);
if (!FetchHelper.TryLoadPathWhitelist(tracer, this.PathWhitelist, this.PathWhitelistFile, enlistment, fetchHelper.PathWhitelist))
{
return ExitFailure;
Expand Down Expand Up @@ -254,7 +262,7 @@ private int ExecuteWithExitCode()
"Fetching",
output: Console.Out,
showSpinner: !Console.IsOutputRedirected,
suppressGvfsLogMessage: true);
gvfsLogEnlistmentRoot: null);

Console.WriteLine();
Console.WriteLine("See the full log at " + fastfetchLogFile);
Expand Down Expand Up @@ -284,13 +292,16 @@ private int ExecuteWithExitCode()
}
}

private FetchHelper GetFetchHelper(ITracer tracer, Enlistment enlistment)
private FetchHelper GetFetchHelper(ITracer tracer, Enlistment enlistment, CacheServerInfo cacheServer, RetryConfig retryConfig)
{
GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(tracer, enlistment, cacheServer, retryConfig);

if (this.Checkout)
{
return new CheckoutFetchHelper(
tracer,
enlistment,
objectRequestor,
this.ChunkSize,
this.SearchThreadCount,
this.DownloadThreadCount,
Expand All @@ -303,6 +314,7 @@ private FetchHelper GetFetchHelper(ITracer tracer, Enlistment enlistment)
return new FetchHelper(
tracer,
enlistment,
objectRequestor,
this.ChunkSize,
this.SearchThreadCount,
this.DownloadThreadCount,
Expand Down

0 comments on commit 153006d

Please sign in to comment.