private DownloadAndSaveObjectResult TryDownloadAndSaveObject( string objectId, CancellationToken cancellationToken, RequestSource requestSource, bool retryOnFailure) { if (objectId == GVFSConstants.AllZeroSha) { return(DownloadAndSaveObjectResult.Error); } DateTime negativeCacheRequestTime; if (this.objectNegativeCache.TryGetValue(objectId, out negativeCacheRequestTime)) { if (negativeCacheRequestTime > DateTime.Now.Subtract(NegativeCacheTTL)) { return(DownloadAndSaveObjectResult.ObjectNotOnServer); } this.objectNegativeCache.TryRemove(objectId, out negativeCacheRequestTime); } // To reduce allocations, reuse the same buffer when writing objects in this batch byte[] bufToCopyWith = new byte[StreamUtil.DefaultCopyBufferSize]; RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .InvocationResult output = this.GitObjectRequestor.TryDownloadLooseObject( objectId, retryOnFailure, cancellationToken, requestSource.ToString(), onSuccess: (tryCount, response) => { // If the request is from git.exe (i.e. NamedPipeMessage) then we should assume that if there is an // object on disk it's corrupt somehow (which is why git is asking for it) this.WriteLooseObject( response.Stream, objectId, overwriteExistingObject: requestSource == RequestSource.NamedPipeMessage, bufToCopyWith: bufToCopyWith); return(new RetryWrapper <GitObjectsHttpRequestor.GitObjectTaskResult> .CallbackResult(new GitObjectsHttpRequestor.GitObjectTaskResult(true))); }); if (output.Result != null) { if (output.Succeeded && output.Result.Success) { return(DownloadAndSaveObjectResult.Success); } if (output.Result.HttpStatusCodeResult == HttpStatusCode.NotFound) { this.objectNegativeCache.AddOrUpdate(objectId, DateTime.Now, (unused1, unused2) => DateTime.Now); return(DownloadAndSaveObjectResult.ObjectNotOnServer); } } return(DownloadAndSaveObjectResult.Error); }