Ejemplo n.º 1
0
        /// <inheritdoc />
        public async Task <PinResult> PinAsync(Context context, ContentHash contentHash)
        {
            StructResult <int> sessionResult = await _sessionState.GetIdAsync();

            if (!sessionResult.Succeeded)
            {
                return(new PinResult(sessionResult));
            }

            int sessionId = sessionResult.Data;

            DateTime    startTime = DateTime.UtcNow;
            PinResponse response  = await RunClientActionAndThrowIfFailedAsync(
                context,
                async() => await _client.PinAsync(
                    new PinRequest
            {
                HashType    = (int)contentHash.HashType,
                ContentHash = contentHash.ToByteString(),
                Header      = new RequestHeader(context.Id, sessionId)
            }));

            long ticksWaited = response.Header.ServerReceiptTimeUtcTicks - startTime.Ticks;

            _tracer.TrackClientWaitForServerTicks(ticksWaited);

            await ResetOnUnknownSessionAsync(context, response.Header, sessionId);

            return(UnpackPinResult(response.Header));
        }
Ejemplo n.º 2
0
        private async Task SendHeartbeatAsync(Context context)
        {
            StructResult <int> sessionResult = await _sessionState.GetIdAsync();

            if (!sessionResult.Succeeded)
            {
                // We do not even attempt to send a heartbeat if we can't get a session ID.
                return;
            }

            int sessionId = sessionResult.Data;

            try
            {
                HeartbeatResponse response = await _client.HeartbeatAsync(new HeartbeatRequest { Header = new RequestHeader(context.Id, sessionId) });

                // Check for null header here as a workaround to a known service bug, which returns null headers on successful heartbeats.
                if (response?.Header != null && !response.Header.Succeeded)
                {
                    _tracer.Warning(
                        context,
                        $"Heartbeat failed: ErrorMessage=[{response.Header.ErrorMessage}] Diagnostics=[{response.Header.Diagnostics}]");

                    // Nor do we attempt to reset a session ID based on a failed heartbeat.
                }
            }
            catch (Exception ex)
            {
                string message = (ex is RpcException rpcEx) && (rpcEx.Status.StatusCode == StatusCode.Unavailable)
                    ? "Heartbeat failed to detect running service."
                    : $"Heartbeat failed: [{ex}]";
                _tracer.Debug(context, message);
            }
        }
Ejemplo n.º 3
0
        public void RemoveFromTrackerStop(Context context, StructResult <long> result)
        {
            if (context.IsEnabled)
            {
                TracerOperationFinished(context, result, $"{Name}.{_removeFromTrackerName} stop {result.DurationMs}ms result=[{result}]");
            }

            _removeFromTrackerCallCounter.Completed(result.Duration.Ticks);
        }
Ejemplo n.º 4
0
        /// <inheritdoc />
        public async Task <BoolResult> ShutdownAsync(Context context)
        {
            ShutdownStarted = true;
            try
            {
                _heartbeatTimer?.Dispose();

                if (_sessionState == null)
                {
                    // _sessionState is null if initialization has failed.
                    return(BoolResult.Success);
                }

                StructResult <int> sessionResult = await _sessionState.GetIdAsync();

                if (!sessionResult.Succeeded)
                {
                    return(new BoolResult(sessionResult));
                }

                int sessionId = sessionResult.Data;

                if (_serviceUnavailable)
                {
                    context.Debug("Skipping session shutdown because service is unavailable.");
                }
                else
                {
                    try
                    {
                        await _client.ShutdownSessionAsync(new ShutdownRequest { Header = new RequestHeader(context.Id, sessionId) });
                    }
                    catch (RpcException e)
                    {
                        context.Error($"Failed to shut down session with error: {e}");
                    }
                }

                await _channel.ShutdownAsync();

                ShutdownCompleted = true;
                return(BoolResult.Success);
            }
            catch (Exception ex)
            {
                // Catching all exceptions, even ClientCanRetryExceptions, because the teardown steps aren't idempotent.
                // In the worst case, the shutdown call comes while the service is offline, the service never receives it,
                // and then the service times out the session 10 minutes later (by default).
                ShutdownCompleted = true;
                return(new BoolResult(ex));
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Remove local location from the content tracker.
        /// </summary>
        public async Task <StructResult <long> > RemoveFromTrackerAsync(Context context)
        {
            if (_enableRepairHandling && InnerContentStore is ILocalContentStore localStore)
            {
                var result = await _contentLocationStore.InvalidateLocalMachineAsync(context, localStore, CancellationToken.None);

                if (!result)
                {
                    return(new StructResult <long>(result));
                }
            }

            // New logic doesn't have the content removed count
            return(StructResult.Create((long)0));
        }
        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));
            }
        }
Ejemplo n.º 7
0
        /// <inheritdoc />
        public async Task <PutResult> PutFileAsync(
            Context context,
            HashType hashType,
            AbsolutePath path,
            FileRealizationMode realizationMode)
        {
            StructResult <int> sessionResult = await _sessionState.GetIdAsync();

            if (!sessionResult.Succeeded)
            {
                return(new PutResult(sessionResult, new ContentHash(hashType)));
            }

            int sessionId = sessionResult.Data;

            return(await PutFileAsync(context, hashType, path, realizationMode, sessionId));
        }
Ejemplo n.º 8
0
        private async Task <IEnumerable <Task <Indexed <PinResult> > > > PinBatchAsync(Context context, int baseIndex, IReadOnlyList <ContentHash> chunk)
        {
            StructResult <int> sessionResult = await _sessionState.GetIdAsync();

            if (!sessionResult.Succeeded)
            {
                PinResult pinResult = new PinResult(sessionResult);
                return(chunk.Select((ContentHash h) => pinResult).AsIndexed().AsTasks());
            }

            int sessionId = sessionResult.Data;

            var pinResults     = new List <Indexed <PinResult> >();
            var bulkPinRequest = new PinBulkRequest {
                Header = new RequestHeader(context.Id, sessionId)
            };

            foreach (var contentHash in chunk)
            {
                bulkPinRequest.Hashes.Add(
                    new ContentHashAndHashTypeData {
                    HashType = (int)contentHash.HashType, ContentHash = contentHash.ToByteString()
                });
            }

            DateTime        startTime = DateTime.UtcNow;
            PinBulkResponse underlyingBulkPinResponse = await RunClientActionAndThrowIfFailedAsync(
                context,
                async() => await _client.PinBulkAsync(bulkPinRequest));

            long ticksWaited = underlyingBulkPinResponse.Header.Values.First().ServerReceiptTimeUtcTicks - startTime.Ticks;

            _tracer.TrackClientWaitForServerTicks(ticksWaited);

            foreach (var response in underlyingBulkPinResponse.Header)
            {
                await ResetOnUnknownSessionAsync(context, response.Value, sessionId);

                pinResults.Add(UnpackPinResult(response.Value).WithIndex(response.Key + baseIndex));
            }

            _tracer.LogPinResults(context, pinResults.Select(r => chunk[r.Index - baseIndex]).ToList(), pinResults.Select(r => r.Item).ToList());

            return(pinResults.AsTasks());
        }
Ejemplo n.º 9
0
        /// <inheritdoc />
        public IAsyncEnumerable <StructResult <StrongFingerprint> > EnumerateStrongFingerprints(Context context)
        {
            context.Debug($"{nameof(SQLiteMemoizationStore)}.{nameof(EnumerateStrongFingerprints)}({context.Id})");
            return(AsyncEnumerable.CreateEnumerable(
                       () =>
            {
                const long pageLimit = 100;
                long offset = 0;
                IEnumerator <StrongFingerprint> strongFingerprints = null;
                StructResult <StrongFingerprint> error = null;
                return AsyncEnumerable.CreateEnumerator(
                    async cancellationToken =>
                {
                    try
                    {
                        if (error != null)
                        {
                            return false;
                        }

                        if (strongFingerprints == null || !strongFingerprints.MoveNext())
                        {
                            // ReSharper disable once GenericEnumeratorNotDisposed
                            strongFingerprints = (await EnumerateStrongFingerprintsAsync(pageLimit, offset)).GetEnumerator();
                            if (!strongFingerprints.MoveNext())
                            {
                                return false;
                            }
                        }

                        offset++;
                        return true;
                    }
                    catch (Exception e)
                    {
                        error = new StructResult <StrongFingerprint>(e);
                        return true;
                    }
                },
                    () => error ?? new StructResult <StrongFingerprint>(strongFingerprints.Current),
                    () => { strongFingerprints?.Dispose(); });
            }));
        }
Ejemplo n.º 10
0
        /// <inheritdoc />
        public async Task <PlaceFileResult> PlaceFileAsync(
            Context context,
            ContentHash contentHash,
            AbsolutePath path,
            FileAccessMode accessMode,
            FileReplacementMode replacementMode,
            FileRealizationMode realizationMode)
        {
            StructResult <int> sessionResult = await _sessionState.GetIdAsync();

            if (!sessionResult.Succeeded)
            {
                return(new PlaceFileResult(sessionResult));
            }

            int sessionId = sessionResult.Data;

            return(await PlaceFileAsync(context, contentHash, path, accessMode, replacementMode, realizationMode, sessionId));
        }
        /// <inheritdoc />
        public async Task <ObjectResult <ContentHashListWithCacheMetadata> > AddContentHashListAsync(
            Context context,
            string cacheNamespace,
            StrongFingerprint strongFingerprint,
            ContentHashListWithCacheMetadata valueToAdd)
        {
            try
            {
                Func <System.IO.Stream, System.Threading.CancellationToken, Task <StructResult <ContentHash> > > putStreamFunc =
                    async(stream, cts) =>
                {
                    PutResult putResult = await _blobContentSession.PutStreamAsync(context, HashType.Vso0, stream, cts);

                    if (putResult.Succeeded)
                    {
                        return(new StructResult <ContentHash>(putResult.ContentHash));
                    }

                    return(new StructResult <ContentHash>(putResult));
                };

                StructResult <ContentHash> blobIdOfContentHashListResult =
                    await BlobContentHashListExtensions.PackInBlob(
                        putStreamFunc,
                        valueToAdd.ContentHashListWithDeterminism);

                if (!blobIdOfContentHashListResult.Succeeded)
                {
                    return(new ObjectResult <ContentHashListWithCacheMetadata>(blobIdOfContentHashListResult));
                }

                var blobContentHashListWithDeterminism =
                    new BlobContentHashListWithDeterminism(
                        valueToAdd.ContentHashListWithDeterminism.Determinism.EffectiveGuid,
                        BlobIdentifierToContentHashExtensions.ToBlobIdentifier(blobIdOfContentHashListResult.Data));

                var blobContentHashListWithCacheMetadata = new BlobContentHashListWithCacheMetadata(
                    blobContentHashListWithDeterminism,
                    valueToAdd.GetRawExpirationTimeUtc(),
                    valueToAdd.ContentGuarantee,
                    valueToAdd.HashOfExistingContentHashList);

                BlobContentHashListResponse addResult = await ArtifactHttpClientErrorDetectionStrategy.ExecuteWithTimeoutAsync(
                    context,
                    "AddContentHashList",
                    innerCts => _buildCacheHttpClient.AddContentHashListAsync(
                        cacheNamespace,
                        strongFingerprint,
                        blobContentHashListWithCacheMetadata),
                    CancellationToken.None).ConfigureAwait(false);

                DownloadUriCache.Instance.BulkAddDownloadUris(addResult.BlobDownloadUris);

                // add succeeded but returned an empty contenthashlistwith cache metadata. correct this.
                if (addResult.ContentHashListWithCacheMetadata == null)
                {
                    return
                        (new ObjectResult <ContentHashListWithCacheMetadata>(
                             new ContentHashListWithCacheMetadata(
                                 new ContentHashListWithDeterminism(null, blobContentHashListWithCacheMetadata.Determinism),
                                 blobContentHashListWithCacheMetadata.GetRawExpirationTimeUtc(),
                                 blobContentHashListWithCacheMetadata.ContentGuarantee)));
                }
                else
                {
                    return(await UnpackBlobContentHashListAsync(context, addResult.ContentHashListWithCacheMetadata));
                }
            }
            catch (Exception ex)
            {
                return(new ObjectResult <ContentHashListWithCacheMetadata>(ex));
            }
        }
Ejemplo n.º 12
0
        private async Task <IEnumerable <StructResult <StrongFingerprint> > > EnumerateStrongFingerprintsAsync(OperationContext context)
        {
            var result = await Database.EnumerateStrongFingerprintsAsync(context);

            return(result.Select(r => StructResult.FromResult(r)));
        }