public async Task <PlaceFileResult> CreateTempAndPutAsync( OperationContext context, ContentHash contentHash, IContentSession contentSession) { using (var disposableFile = new DisposableFile(context, _fileSystem, AbsolutePath.CreateRandomFileName(_rootPath / "temp"))) { PlaceFileResult placeTempFileResult = await PlaceFileAsync(context, contentHash, disposableFile.Path, FileAccessMode.ReadOnly, FileReplacementMode.FailIfExists, FileRealizationMode.HardLink, context.Token); if (!placeTempFileResult.Succeeded) { return(placeTempFileResult); } PutResult putFileResult = await contentSession.PutFileAsync(context, contentHash, disposableFile.Path, FileRealizationMode.Any, context.Token); if (!putFileResult) { return(new PlaceFileResult(putFileResult)); } else { return(new PlaceFileResult(PlaceFileResult.ResultCode.PlacedWithCopy, putFileResult.ContentSize)); } } }
public virtual async Task <PushFileResult> PushFileAsync(OperationContext context, ContentHash hash, Stream stream, MachineLocation targetMachine, CopyOptions options) { var tempFile = AbsolutePath.CreateRandomFileName(WorkingDirectory); using (var file = File.OpenWrite(tempFile.Path)) { await stream.CopyToAsync(file); } var result = await PushHandlersByLocation[targetMachine].HandlePushFileAsync(context, hash, tempFile, CancellationToken.None); File.Delete(tempFile.Path); return(result ? PushFileResult.PushSucceeded(result.ContentSize) : new PushFileResult(result)); }
/// <summary> /// Handles a request to copy content to this machine. /// </summary> public async Task HandlePushFileAsync(IAsyncStreamReader <PushFileRequest> requestStream, IServerStreamWriter <PushFileResponse> responseStream, ServerCallContext callContext) { OperationStarted(); var startTime = DateTime.UtcNow; var pushRequest = PushRequest.FromMetadata(callContext.RequestHeaders); var hash = pushRequest.Hash; var cacheContext = new Context(pushRequest.TraceId, Logger); var token = callContext.CancellationToken; var store = _contentStoreByCacheName.Values.OfType <IPushFileHandler>().FirstOrDefault(); if (store == null) { Tracer.Debug(cacheContext, $"{nameof(HandlePushFileAsync)}: Copy of {hash.ToShortString()} skipped because no stores implement {nameof(IPushFileHandler)}."); await callContext.WriteResponseHeadersAsync(PushResponse.DontCopy.Metadata); return; } if (store.HasContentLocally(cacheContext, hash)) { Tracer.Debug(cacheContext, $"{nameof(HandlePushFileAsync)}: Copy of {hash.ToShortString()} skipped because content is already local."); await callContext.WriteResponseHeadersAsync(PushResponse.DontCopy.Metadata); return; } if (!_ongoingPushes.Add(hash)) { Tracer.Debug(cacheContext, $"{nameof(HandlePushFileAsync)}: Copy of {hash.ToShortString()} skipped because another request to push it is already being handled."); await callContext.WriteResponseHeadersAsync(PushResponse.DontCopy.Metadata); return; } try { await callContext.WriteResponseHeadersAsync(PushResponse.Copy.Metadata); var tempFilePath = AbsolutePath.CreateRandomFileName(_tempDirectory); using (var tempFile = File.OpenWrite(tempFilePath.Path)) { while (await requestStream.MoveNext()) { if (token.IsCancellationRequested) { return; } var request = requestStream.Current; var bytes = request.Content.ToByteArray(); await tempFile.WriteAsync(bytes, 0, bytes.Length); } } var result = await store.HandlePushFileAsync(cacheContext, hash, tempFilePath, token); File.Delete(tempFilePath.Path); var response = result ? new PushFileResponse { Header = ResponseHeader.Success(startTime) } : new PushFileResponse { Header = ResponseHeader.Failure(startTime, result.ErrorMessage) }; await responseStream.WriteAsync(response); } finally { _ongoingPushes.Remove(hash); } }