public static OpenStreamResult ShouldBeCancelled(this OpenStreamResult result) { Assert.Equal(OpenStreamResult.ResultCode.Error, result.Code); Assert.Null(result.Stream); Assert.Contains("canceled", result.ToString()); return(result); }
private async Task <OpenStreamResult> GetFileStreamAsync(Context context, ContentHash hash) { Debug.Assert(_contentStoreByCacheName != null); // Iterate through all known stores, looking for content in each. // In most of our configurations there is just one store anyway, // and doing this means both we can callers don't have // to deal with cache roots and drive letters. foreach (KeyValuePair <string, IContentStore> entry in _contentStoreByCacheName) { IStreamStore store = entry.Value as IStreamStore; if (store != null) { OpenStreamResult result = await store.StreamContentAsync(context, hash); if (result.Code != OpenStreamResult.ResultCode.ContentNotFound) { return(result); } } } return(new OpenStreamResult(OpenStreamResult.ResultCode.ContentNotFound, $"{hash} to found")); }
private async Task StreamContentAsync(OpenStreamResult openStreamResult, IServerStreamWriter <CopyFileResponse> responseStream, DateTime startTime) { using (var stream = openStreamResult.Stream) { byte[] buffer = new byte[ContentStore.Grpc.Utils.DefaultBufferSize]; long chunks = 0; while (true) { int chunkSize = await stream.ReadAsync(buffer, 0, buffer.Length); if (chunkSize == 0) { break; } ByteString content = ByteString.CopyFrom(buffer, 0, chunkSize); CopyFileResponse reply = new CopyFileResponse() { // TODO: Check on this code Header = new ResponseHeader(startTime, openStreamResult.Succeeded, (int)openStreamResult.Code, openStreamResult.ErrorMessage, openStreamResult.Diagnostics), Content = content, Index = chunks }; await responseStream.WriteAsync(reply); chunks++; } } }
public static OpenStreamResult ShouldBeSuccess(this OpenStreamResult result) { Assert.NotNull(result); Assert.Null(result.ErrorMessage); Assert.True(result.Succeeded, $"OpenStream operation should succeed, but it failed. Error: {result.ErrorMessage}. Diagnostics: {result.Diagnostics}"); return(result); }
public virtual void OpenStreamStop(Context context, ContentHash contentHash, OpenStreamResult result) { if (context.IsEnabled) { TracerOperationFinished(context, result, $"{Name}.{OpenStreamCallName} stop {result.DurationMs}ms input=[{contentHash.ToShortString()}] result=[{result}]"); } _openStreamCallCounter.Completed(result.Duration.Ticks); }
public override void OpenStreamStop(Context context, OpenStreamResult result) { if (_eventSource.IsEnabled()) { _eventSource.OpenStreamStop(context.Id.ToString(), (int)result.Code, result.ErrorMessage); } base.OpenStreamStop(context, result); }
private async Task <ObjectResult <ContentHashListWithCacheMetadata> > UnpackBlobContentHashListAsync(Context context, BlobContentHashListWithCacheMetadata blobCacheMetadata) { Contract.Assert(blobCacheMetadata != null); if (blobCacheMetadata.ContentHashListWithDeterminism.BlobIdentifier == null) { return(new ObjectResult <ContentHashListWithCacheMetadata>( new ContentHashListWithCacheMetadata( new ContentHashListWithDeterminism(null, blobCacheMetadata.Determinism), blobCacheMetadata.GetRawExpirationTimeUtc(), blobCacheMetadata.ContentGuarantee, blobCacheMetadata.HashOfExistingContentHashList))); } BlobIdentifier blobId = blobCacheMetadata.ContentHashListWithDeterminism.BlobIdentifier; Func <ContentHash, CancellationToken, Task <ObjectResult <Stream> > > openStreamFunc = async(hash, cts) => { OpenStreamResult openStreamResult = await _blobContentSession.OpenStreamAsync(context, hash, cts); if (openStreamResult.Succeeded) { return(new ObjectResult <Stream>(openStreamResult.Stream)); } return(new ObjectResult <Stream>(openStreamResult)); }; StructResult <ContentHashListWithDeterminism> contentHashListResult = await BlobContentHashListExtensions.UnpackFromBlob( openStreamFunc, blobId); if (contentHashListResult.Succeeded) { var contentHashListWithCacheMetadata = new ContentHashListWithCacheMetadata( contentHashListResult.Data, blobCacheMetadata.GetRawExpirationTimeUtc(), blobCacheMetadata.ContentGuarantee, blobCacheMetadata.HashOfExistingContentHashList); return(new ObjectResult <ContentHashListWithCacheMetadata>(contentHashListWithCacheMetadata)); } else { return(new ObjectResult <ContentHashListWithCacheMetadata>(contentHashListResult)); } }
protected async Task OpenStreamReturnsExpectedFile( IReadOnlyContentSession session, Context context, ContentHash hash, byte[] expected) { OpenStreamResult openResult = await session.OpenStreamAsync(context, hash, Token); context.Debug($"Validating stream for content hash {hash} returned result {openResult.Code} with diagnostics {openResult} with ErrorMessage {openResult.ErrorMessage} diagnostics {openResult.Diagnostics}"); Assert.Equal <OpenStreamResult.ResultCode>(OpenStreamResult.ResultCode.Success, openResult.Code); Assert.True(openResult.Succeeded, $"OpenStream did not succeed for content hash {hash}"); Assert.NotNull(openResult.Stream); using (openResult.Stream) { var actualBytes = await openResult.Stream.GetBytes(false); actualBytes.Should().Equal(expected); } }
public async Task <ActionResult> GetContentAsync(Guid contextId, string hash, string downloadUrl) { OperationContext context = new OperationContext(new Context(contextId, _logger)); OpenStreamResult result = await _service.GetContentAsync(context, hash, downloadUrl); if (result.Succeeded) { return(File(result.Stream, MediaTypeNames.Application.Octet)); } else if (result.Code == OpenStreamResult.ResultCode.ContentNotFound) { return(NotFound()); } else { return(StatusCode(StatusCodes.Status500InternalServerError, result.ToString())); } }
public static OpenStreamResult ShouldBeNotFound(this OpenStreamResult result) { Assert.Equal(OpenStreamResult.ResultCode.ContentNotFound, result.Code); Assert.Null(result.Stream); return(result); }
public override void OpenStreamStop(Context context, ContentHash contentHash, OpenStreamResult result, Severity successSeverity) { if (_eventSource.IsEnabled()) { _eventSource.OpenStreamStop(context.TraceId, (int)result.Code, result.ErrorMessage); } base.OpenStreamStop(context, contentHash, result, successSeverity: DiagnosticLevelSeverity(result.Duration)); }
public static ClusterOperationResult FindAtomicClusterOperationStatusReplicated(RspList results) { ClusterOperationResult res = null; if (results == null) { return(res); } int timeoutCount = 0; int suspectedCount = 0; int successCount = 0; for (int i = 0; i < results.size(); i++) { Rsp rsp = (Rsp)results.elementAt(i); if (rsp.wasSuspected()) { suspectedCount++; continue; } if (!rsp.wasReceived() && !rsp.wasSuspected()) { timeoutCount++; continue; } res = rsp.Value as ClusterOperationResult; if (res.ExecutionResult == ClusterOperationResult.Result.Completed) { successCount++; } } if (suspectedCount > 0 && successCount > 0 && (suspectedCount + successCount == results.size())) { //as operation is successfull on all other nodes other than suspected node(s). return(res); } if (timeoutCount > 0 && (timeoutCount + successCount == results.size())) { if (successCount > 0) { //operation is not succeeded on some of the nodes; therefore we throw timeout exception. res.ExecutionResult = ClusterOperationResult.Result.ParitalTimeout; return(res); } else { //operation timed out on all of the node; no need to rollback. res = new OpenStreamResult(ClusterOperationResult.Result.FullTimeout, false); return(res); } } if (timeoutCount > 0 && suspectedCount > 0) { if (successCount > 0) { res.ExecutionResult = ClusterOperationResult.Result.ParitalTimeout; return(res); } else { res = new OpenStreamResult(ClusterOperationResult.Result.FullTimeout, false); return(res); } } return(res); }
/// <summary> /// Implements a copy file request. /// </summary> private async Task CopyFileAsync(CopyFileRequest request, IServerStreamWriter <CopyFileResponse> responseStream, ServerCallContext context) { try { LogRequestHandling(); // Get the content stream. Context cacheContext = new Context(new Guid(request.TraceId), _logger); HashType type = (HashType)request.HashType; ContentHash hash = request.ContentHash.ToContentHash((HashType)request.HashType); OpenStreamResult result = await GetFileStreamAsync(cacheContext, hash); using (result.Stream) { // Figure out response headers. CopyCompression compression = CopyCompression.None; Metadata headers = new Metadata(); switch (result.Code) { case OpenStreamResult.ResultCode.ContentNotFound: headers.Add("Exception", "ContentNotFound"); headers.Add("Message", $"Requested content at {hash} not found."); break; case OpenStreamResult.ResultCode.Error: Debug.Assert(result.Exception != null); headers.Add("Exception", result.Exception.GetType().Name); headers.Add("Message", result.Exception.Message); break; case OpenStreamResult.ResultCode.Success: Debug.Assert(result.Stream != null); long size = result.Stream.Length; headers.Add("FileSize", size.ToString()); if ((request.Compression == CopyCompression.Gzip) && (size > _bufferSize)) { compression = CopyCompression.Gzip; } headers.Add("Compression", compression.ToString()); headers.Add("ChunkSize", _bufferSize.ToString()); break; default: throw new NotImplementedException(); } // Send the response headers. await context.WriteResponseHeadersAsync(headers); // Send the content. if (result.Succeeded) { _logger.Debug($"Streaming file through GRPC with GZip {(compression == CopyCompression.Gzip ? "on" : "off")}"); byte[] buffer = new byte[_bufferSize]; switch (compression) { case CopyCompression.None: await StreamContentAsync(result.Stream, buffer, responseStream, context.CancellationToken); break; case CopyCompression.Gzip: await StreamContentWithCompressionAsync(result.Stream, buffer, responseStream, context.CancellationToken); break; } } } } catch (Exception) { throw; } }
/// <summary> /// Implements a copy file request. /// </summary> private async Task CopyFileAsync(CopyFileRequest request, IServerStreamWriter <CopyFileResponse> responseStream, ServerCallContext context) { OperationStarted(); // Get the content stream. Context cacheContext = new Context(new Guid(request.TraceId), Logger); ContentHash hash = request.GetContentHash(); OpenStreamResult result = await GetFileStreamAsync(cacheContext, hash); // If result is unsuccessful, then result.Stream is null, but using(null) is just a no op. using (result.Stream) { // Figure out response headers. CopyCompression compression = CopyCompression.None; Metadata headers = new Metadata(); switch (result.Code) { case OpenStreamResult.ResultCode.ContentNotFound: headers.Add("Exception", "ContentNotFound"); headers.Add("Message", $"Requested content at {hash} not found."); break; case OpenStreamResult.ResultCode.Error: Contract.Assert(result.Exception != null); headers.Add("Exception", result.Exception.GetType().Name); headers.Add("Message", result.Exception.Message); break; case OpenStreamResult.ResultCode.Success: Contract.Assert(result.Stream != null); long size = result.Stream.Length; headers.Add("FileSize", size.ToString()); if ((request.Compression == CopyCompression.Gzip) && (size > _gzipSizeBarrier)) { compression = CopyCompression.Gzip; } headers.Add("Compression", compression.ToString()); headers.Add("ChunkSize", _bufferSize.ToString()); break; default: throw new NotImplementedException($"Unknown result.Code '{result.Code}'."); } // Send the response headers. await context.WriteResponseHeadersAsync(headers); // Send the content. if (result.Succeeded) { var operationContext = new OperationContext(cacheContext, context.CancellationToken); using (var arrayHandle = _pool.Get()) { StreamContentDelegate streamContent = compression == CopyCompression.None ? (StreamContentDelegate)StreamContentAsync : StreamContentWithCompressionAsync; byte[] buffer = arrayHandle.Value; await operationContext.PerformOperationAsync( _tracer, () => streamContent(result.Stream, buffer, responseStream, context.CancellationToken), traceOperationStarted : false, // Tracing only stop messages extraEndMessage : r => $"Hash={hash.ToShortString()}, GZip={(compression == CopyCompression.Gzip ? "on" : "off")}.") .IgnoreFailure(); // The error was already logged. } } } }