Beispiel #1
0
 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);
 }
Beispiel #2
0
        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++;
                }
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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));
            }
        }
Beispiel #8
0
        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);
            }
        }
Beispiel #9
0
        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()));
            }
        }
Beispiel #10
0
 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));
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        /// <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;
            }
        }
Beispiel #14
0
        /// <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.
                    }
                }
            }
        }