Ejemplo n.º 1
0
 /// <inheritdoc />
 protected override Task <IEnumerable <Task <Indexed <PlaceFileResult> > > > PlaceFileCoreAsync(OperationContext operationContext, IReadOnlyList <ContentHashWithPath> hashesWithPaths, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
 => Task.FromResult(hashesWithPaths.Select((hash, i) => Task.FromResult(new PlaceFileResult(PlaceFileResult.ResultCode.NotPlacedContentNotFound).WithIndex(i))));
Ejemplo n.º 2
0
        public async Task <Possible <FullCacheRecordWithDeterminism, Failure> > AddOrGetAsync(WeakFingerprintHash weak, CasHash casElement, Hash hashElement, CasEntries hashes, UrgencyHint urgencyHint, Guid activityId)
        {
            Contract.Requires(!IsClosed);
            Contract.Requires(hashes.IsValid);
            Contract.Assert(!IsReadOnly);

            using (var counter = m_counters.AddOrGetCounter())
            {
                using (var eventing = new AddOrGetActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(weak, casElement, hashElement, hashes, urgencyHint);

                    counter.SetEntriesCount(hashes.Count);  // The size of what we are adding (effectively)

                    // We check the Cas entries if we are strict
                    if (StrictMetadataCasCoupling)
                    {
                        // Check that the content is valid.
                        if (!m_pinnedToCas.ContainsKey(casElement))
                        {
                            counter.Failed();
                            return(eventing.StopFailure(new UnpinnedCasEntryFailure(CacheId, casElement)));
                        }

                        foreach (CasHash hash in hashes)
                        {
                            if (!m_pinnedToCas.ContainsKey(hash))
                            {
                                counter.Failed();
                                return(eventing.StopFailure(new UnpinnedCasEntryFailure(CacheId, hash)));
                            }
                        }
                    }

                    StrongFingerprint strong = new StrongFingerprint(weak, casElement, hashElement, CacheId);

                    // Assume we accepted the Add and there is nothing to return
                    FullCacheRecord result = null;

                    string strongFingerprintName = m_cache.GetStrongFingerprintFilename(strong);

                    try
                    {
                        using (FileStream file = await m_cache.ContendedOpenStreamAsync(strongFingerprintName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                        {
                            // The compiler thinks that it is not assigned down below at the end
                            // even though it would be set by the writeEntries being true in that case
                            CasEntries oldCasEntries = hashes;

                            // Assume we will write our new enties to the file.
                            bool writeEntries = true;

                            // If there is some data in the file already, we need to try to read it.
                            if (file.Length > 0)
                            {
                                var possibleOldCasEntries = await m_cache.ReadCacheEntryAsync(file);

                                // Only if it was formatted correctly do we continue to check if
                                // we should replace it.
                                if (possibleOldCasEntries.Succeeded)
                                {
                                    oldCasEntries = possibleOldCasEntries.Result;
                                    writeEntries  = false;

                                    // We can only replace if both or neither is SinglePhaseNonDeterministic
                                    if (oldCasEntries.Determinism.IsSinglePhaseNonDeterministic != hashes.Determinism.IsSinglePhaseNonDeterministic)
                                    {
                                        counter.Failed();
                                        return(eventing.StopFailure(new SinglePhaseMixingFailure(CacheId)));
                                    }

                                    // Should we replace?
                                    if (hashes.Determinism.IsSinglePhaseNonDeterministic ||
                                        (!oldCasEntries.Determinism.IsDeterministicTool &&
                                         (hashes.Determinism.IsDeterministic && !oldCasEntries.Determinism.Equals(hashes.Determinism))))
                                    {
                                        // We are replacing due to determinism
                                        counter.Det();
                                        writeEntries = true;
                                    }
                                    else if (HasMissingContent(oldCasEntries))
                                    {
                                        counter.Repair();
                                        writeEntries = true;
                                    }
                                    else if (oldCasEntries.Determinism.IsDeterministicTool && hashes.Determinism.IsDeterministicTool && !oldCasEntries.Equals(hashes))
                                    {
                                        // We have a non-deterministic tool!
                                        counter.Failed();
                                        return(eventing.StopFailure(new NotDeterministicFailure(CacheId, new FullCacheRecord(strong, oldCasEntries), new FullCacheRecord(strong, hashes))));
                                    }
                                }
                            }

                            // Are we going to write the entries?
                            if (writeEntries)
                            {
                                // We are writing so the old entries don't count
                                oldCasEntries = hashes;

                                // Write from the front
                                file.SetLength(0);
                                await m_cache.WriteCacheEntryAsync(file, hashes);
                            }
                            else
                            {
                                counter.Dup();
                            }

                            // If what is in the cache is different than what we are
                            // asking to add, build a FullCacheRecord to return what
                            // is in the cache.
                            if (!oldCasEntries.Equals(hashes))
                            {
                                counter.Get();
                                result = new FullCacheRecord(strong, oldCasEntries);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        counter.Failed();
                        return(eventing.StopFailure(new StrongFingerprintAccessFailure(m_cache.CacheId, strong, e)));
                    }

                    AddSessionRecord(strong);

                    if (result != null)
                    {
                        return
                            (eventing.Returns(
                                 new FullCacheRecordWithDeterminism(
                                     new FullCacheRecord(
                                         result.StrongFingerprint,
                                         result.CasEntries.GetModifiedCasEntriesWithDeterminism(
                                             m_cache.IsAuthoritative,
                                             m_cache.CacheGuid,
                                             CacheDeterminism.NeverExpires)))));
                    }
                    else
                    {
                        return(eventing.Returns(new FullCacheRecordWithDeterminism(hashes.GetFinalDeterminism(m_cache.IsAuthoritative, m_cache.CacheGuid, DateTime.UtcNow.Add(m_cache.TimeToLive)))));
                    }
                }
            }
        }
 /// <inheritdoc />
 public Task <GetContentHashListResult> GetContentHashListAsync(
     Context context, StrongFingerprint strongFingerprint, CancellationToken cts, UrgencyHint urgencyHint)
 {
     return(_memoizationReadOnlySession.GetContentHashListAsync(context, strongFingerprint, cts, urgencyHint));
 }
Ejemplo n.º 4
0
        public async Task <Possible <string, Failure>[]> PinToCasAsync(CasEntries casEntries, UrgencyHint urgencyHint, Guid activityId)
        {
            Contract.Requires(!IsClosed);
            Contract.Requires(casEntries.IsValid);

            using (var eventing = new PinToCasMultipleActivity(BasicFilesystemCache.EventSource, activityId, this))
            {
                eventing.Start(casEntries, urgencyHint);

                // First, initiate all of the operations
                var taskValues = new Task <Possible <string, Failure> > [casEntries.Count];
                for (int i = 0; i < casEntries.Count; i++)
                {
                    taskValues[i] = PinToCasAsync(casEntries[i], urgencyHint, activityId);
                }

                // Now await them all (since they can run in parallel
                var results = new Possible <string, Failure> [casEntries.Count];
                for (int i = 0; i < casEntries.Count; i++)
                {
                    results[i] = await taskValues[i];
                }

                // All return results are actually traced via the per-hash call of PinToCas
                return(eventing.Returns(results));
            }
        }
Ejemplo n.º 5
0
        public async Task <Possible <CasHash, Failure> > AddToCasAsync(Stream filestream, CasHash?hash, UrgencyHint urgencyHint, Guid activityId)
        {
            Contract.Requires(!IsClosed);
            Contract.Requires(filestream != null);

            Contract.Assert(!IsReadOnly);

            // We have this interesting issue - we are not sure if the stream is rewindable
            // and the target CAS may not be local so we will end up streaming this to
            // a temporary file just to pass it up.  (Implementation detail)
            using (var counter = m_counters.AddToCasCounterStream())
            {
                using (var eventing = new AddToCasStreamActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(filestream, urgencyHint);

                    Possible <CasHash, Failure> result;

                    string tmpFile = await m_cache.CreateTempFile();

                    // Since these are longer operations that are synchronous, we wrap them
                    // into a task for potential parallelism
                    try
                    {
                        CasHash casHash = await HashStreamToFileAsync(filestream, tmpFile);

                        try
                        {
                            counter.ContentSize(new FileInfo(tmpFile).Length);

                            if (!await m_cache.AddToCasAsync(tmpFile, casHash))
                            {
                                counter.DuplicatedContent();
                            }

                            // Pin it and return the hash
                            m_pinnedToCas.TryAdd(casHash, 0);

                            result = casHash;
                        }
                        catch (Exception e)
                        {
                            counter.Failed();
                            result = new AddToCasFailure(CacheId, casHash, "<stream>", e);
                        }
                    }
                    catch (Exception e)
                    {
                        counter.Failed();
                        result = new HashFailure(CacheId, "<stream>", e);
                    }
                    finally
                    {
                        try
                        {
                            File.Delete(tmpFile);
                        }
#pragma warning disable ERP022 // TODO: This should really handle specific errors
                        catch
                        {
                            // Ignore the failure - it is likely caused by
                            // a semantic breaking tool such as most virus scanners
                            // or disk indexers.  The file was a local teporary file
                            // in the temp directory
                        }
#pragma warning restore ERP022 // Unobserved exception in generic exception handler
                    }

                    return(eventing.Returns(result));
                }
            }
        }
        protected override async Task <IEnumerable <Task <Indexed <PinResult> > > > PinCoreAsync(OperationContext context, IReadOnlyList <ContentHash> contentHashes, UrgencyHint urgencyHint, Counter retryCounter, Counter fileCounter)
        {
            try
            {
                var endDateTime = DateTime.UtcNow + TimeToKeepContent;

                return(await Workflows.RunWithFallback(
                           contentHashes,
                           hashes => CheckInMemoryCaches(hashes, endDateTime),
                           hashes => UpdateBlobStoreAsync(context, hashes, endDateTime),
                           result => result.Succeeded));
            }
            catch (Exception ex)
            {
                context.TracingContext.Warning($"Exception when querying pins against the VSTS services {ex}");
                return(contentHashes.Select((_, index) => Task.FromResult(new PinResult(ex).WithIndex(index))));
            }
        }
Ejemplo n.º 7
0
        public IEnumerable <Task <Possible <StrongFingerprint, Failure> > > EnumerateStrongFingerprints(WeakFingerprintHash weak, UrgencyHint urgencyHint, Guid activityId)
        {
            Contract.Requires(!IsClosed);

            using (var counter = m_counters.EnumerateStrongFingerprintsCounter())
            {
                using (var eventing = new EnumerateStrongFingerprintsActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(weak, urgencyHint);

                    // It's possible the cache could encounter an IO error when attempting to enumerate the fingerprints.
                    // This shouldn't be a fatal error. we just want to catch and record it, then continue on.
                    // Due to the use of yield a foreach loop can't be used here while still handling the error,
                    // so the enumation must be done manually.
                    using (var enumerator = m_cache.EnumerateStrongFingerprints(weak).GetEnumerator())
                    {
                        while (true)
                        {
                            StrongFingerprint strong = null;
                            try
                            {
                                if (!enumerator.MoveNext())
                                {
                                    break;
                                }

                                strong = enumerator.Current;
                            }
                            catch (IOException ex)
                            {
                                eventing.StopFailure(new StrongFingerprintEnumerationFailure(m_cache.CacheId, weak, ex));
                                yield break;
                            }
                            catch (UnauthorizedAccessException ex)
                            {
                                eventing.StopFailure(new StrongFingerprintEnumerationFailure(m_cache.CacheId, weak, ex));
                                yield break;
                            }

                            counter.YieldReturn();
                            yield return(Task.FromResult(new Possible <StrongFingerprint, Failure>(strong)));
                        }
                    }

                    eventing.Stop();
                }
            }
        }
Ejemplo n.º 8
0
 /// <inheritdoc />
 public Task <GetContentHashListResult> GetContentHashListAsync(Context context, StrongFingerprint strongFingerprint, CancellationToken cts, UrgencyHint urgencyHint = UrgencyHint.Nominal)
 {
     return(PerformOperationAsync(
                context,
                cts,
                (ctx, client) => client.GetContentHashListAsync(ctx, strongFingerprint),
                counter: _memoizationCounters[MemoizationStoreCounters.GetContentHashList],
                retryCounter: _memoizationCounters[MemoizationStoreCounters.GetContentHashListRetries]));
 }
        /// <inheritdoc />
        public Task <GetContentHashListResult> GetContentHashListAsync(Context context, StrongFingerprint strongFingerprint, CancellationToken cts, UrgencyHint urgencyHint)
        {
            return(WithOperationContext(
                       context,
                       cts,
                       operationContext => operationContext.PerformOperationAsync(
                           DistributedTracer,
                           operation: async() =>
            {
                GetContentHashListResult innerResult = null;

                // Get the value from the metadata cache or load the current inner value into it (and then return it)
                var existing = await MetadataCache.GetOrAddContentHashListAsync(
                    context,
                    strongFingerprint,
                    async fingerprint =>
                {
                    innerResult = await _innerCacheSession.GetContentHashListAsync(context, fingerprint, cts, urgencyHint);
                    return innerResult;
                });

                // Check to see if we need to need to read through to the inner value.
                if (_readThroughMode == ReadThroughMode.ReadThrough &&
                    existing.Succeeded &&
                    !(existing.ContentHashListWithDeterminism.Determinism.IsDeterministic &&
                      existing.ContentHashListWithDeterminism.Determinism.Guid == _innerCacheId))
                {
                    // Read through to the inner cache because the metadata cache's value is not guaranteed to be backed.
                    if (innerResult == null)
                    {
                        // We did not already query the inner cache as part of the original query, so do that now.
                        innerResult = await _innerCacheSession.GetContentHashListAsync(
                            context,
                            strongFingerprint,
                            cts,
                            urgencyHint);
                    }

                    if (innerResult != null && innerResult.Succeeded &&
                        innerResult.ContentHashListWithDeterminism.Determinism.IsDeterministic)
                    {
                        // If the inner cache's value is now backed, clear the value from the metadata cache so that the
                        // next read will load the backed value into the metadata cache (preventing the need for future read-throughs).
                        await MetadataCache.DeleteFingerprintAsync(context, strongFingerprint).IgnoreFailure();
                    }

                    return innerResult;
                }
                else
                {
                    // Return the existing value in the metadata cache, or any error.
                    return existing;
                }
            },
                           traceOperationStarted: true,
                           extraStartMessage: $"StrongFingerprint=({strongFingerprint})",
                           extraEndMessage: result => $"StrongFingerprint=({strongFingerprint}) {result.ContentHashListWithDeterminism.ToTraceString()}")));
        }
Ejemplo n.º 10
0
 /// <inheritdoc />
 public System.Collections.Generic.IAsyncEnumerable <GetSelectorResult> GetSelectors(Context context, Fingerprint weakFingerprint, CancellationToken cts, UrgencyHint urgencyHint = UrgencyHint.Nominal)
 {
     _memoizationCounters[MemoizationStoreCounters.GetSelectorsCalls].Increment();
     return(this.GetSelectorsAsAsyncEnumerable(context, weakFingerprint, cts, urgencyHint));
 }
Ejemplo n.º 11
0
 /// <inheritdoc />
 public Task <BoolResult> IncorporateStrongFingerprintsAsync(Context context, IEnumerable <Task <StrongFingerprint> > strongFingerprints, CancellationToken cts, UrgencyHint urgencyHint = UrgencyHint.Nominal)
 {
     return(PerformOperationAsync(
                context,
                cts,
                (ctx, client) => client.IncorporateStrongFingerprintsAsync(ctx, strongFingerprints),
                counter: _memoizationCounters[MemoizationStoreCounters.IncorporateStrongFingerprints],
                retryCounter: _memoizationCounters[MemoizationStoreCounters.IncorporateStrongFingerprintsRetries]));
 }
Ejemplo n.º 12
0
        /// <inheritdoc />
        protected override async Task <PutResult> PutStreamCoreAsync(OperationContext context, HashType hashType, Stream stream, UrgencyHint urgencyHint, Counter retryCounter)
        {
            if (!hashType.IsValidDedup())
            {
                return(new PutResult(
                           new ContentHash(hashType),
                           $"DedupStore client requires a HashType that supports dedup. Given hash type: {hashType}"));
            }

            try
            {
                var tempFile = TempDirectory.CreateRandomFileName().Path;
                using (Stream writer = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
                {
                    await stream.CopyToAsync(writer);
                }

                // Cast is necessary because ContentSessionBase implements IContentSession explicitly
                return(await(this as IContentSession).PutFileAsync(context, hashType, new AbsolutePath(tempFile), FileRealizationMode.None, context.Token, urgencyHint));
            }
            catch (Exception e)
            {
                return(new PutResult(e, new ContentHash(hashType)));
            }
        }
Ejemplo n.º 13
0
 /// <inheritdoc />
 protected override Task <PutResult> PutStreamCoreAsync(OperationContext operationContext, HashType hashType, Stream stream, UrgencyHint urgencyHint, Counter retryCounter)
 => Task.FromResult(new PutResult(new BoolResult(ErrorMessage)));
Ejemplo n.º 14
0
 /// <inheritdoc />
 protected override Task <PutResult> PutFileCoreAsync(OperationContext operationContext, ContentHash contentHash, AbsolutePath path, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
 => Task.FromResult(new PutResult(contentHash, ErrorMessage));
Ejemplo n.º 15
0
        /// <inheritdoc />
        public Task <BoolResult> TrimBulkAsync(Context context, IReadOnlyList <ContentHashAndLocations> contentHashToLocationMap, CancellationToken cts, UrgencyHint urgencyHint)
        {
            if (_redisContentLocationStore == null)
            {
                return(BoolResult.SuccessTask);
            }

            return(_redisContentLocationStore.TrimBulkAsync(context, contentHashToLocationMap, cts, urgencyHint));
        }
 /// <inheritdoc />
 public Task <OpenStreamResult> OpenStreamAsync(Context context, ContentHash contentHash, CancellationToken cts, UrgencyHint urgencyHint)
 {
     return(_innerCacheSession.OpenStreamAsync(context, contentHash, cts, urgencyHint));
 }
        /// <inheritdoc />
        protected override async Task <OpenStreamResult> OpenStreamCoreAsync(
            OperationContext context, ContentHash contentHash, UrgencyHint urgencyHint, Counter retryCounter)
        {
            if (contentHash.HashType != RequiredHashType)
            {
                return(new OpenStreamResult(
                           $"BuildCache client requires HashType '{RequiredHashType}'. Cannot take HashType '{contentHash.HashType}'."));
            }

            string tempFile = null;

            try
            {
                if (ImplicitPin == ImplicitPin.PutAndGet)
                {
                    var pinResult = await PinAsync(context, contentHash, context.Token, urgencyHint).ConfigureAwait(false);

                    if (!pinResult.Succeeded)
                    {
                        if (pinResult.Code == PinResult.ResultCode.ContentNotFound)
                        {
                            return(new OpenStreamResult(null));
                        }

                        return(new OpenStreamResult(pinResult));
                    }
                }

                tempFile = TempDirectory.CreateRandomFileName().Path;
                var possibleLength =
                    await PlaceFileInternalAsync(context, contentHash, tempFile, FileMode.Create).ConfigureAwait(false);

                if (possibleLength.HasValue)
                {
                    return(new OpenStreamResult(new FileStream(
                                                    tempFile,
                                                    FileMode.Open,
                                                    FileAccess.Read,
                                                    FileShare.Read | FileShare.Delete,
                                                    StreamBufferSize,
                                                    FileOptions.DeleteOnClose)));
                }

                return(new OpenStreamResult(null));
            }
            catch (Exception e)
            {
                return(new OpenStreamResult(e));
            }
            finally
            {
                if (tempFile != null)
                {
                    try
                    {
                        File.Delete(tempFile);
                    }
                    catch (Exception e)
                    {
                        Tracer.Warning(context, $"Error deleting temporary file at {tempFile}: {e}");
                    }
                }
            }
        }
 /// <inheritdoc />
 public Task <PlaceFileResult> PlaceFileAsync(Context context, ContentHash contentHash, AbsolutePath path, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, CancellationToken cts, UrgencyHint urgencyHint)
 {
     return(_innerCacheSession.PlaceFileAsync(context, contentHash, path, accessMode, replacementMode, realizationMode, cts, urgencyHint));
 }
 /// <inheritdoc />
 protected override Task <IEnumerable <Task <Indexed <PlaceFileResult> > > > PlaceFileCoreAsync(OperationContext context, IReadOnlyList <ContentHashWithPath> hashesWithPaths, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
 => throw new NotImplementedException();
 /// <inheritdoc />
 public Task <IEnumerable <Task <Indexed <PlaceFileResult> > > > PlaceFileAsync(Context context, IReadOnlyList <ContentHashWithPath> hashesWithPaths, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, CancellationToken cts, UrgencyHint urgencyHint = UrgencyHint.Nominal)
 {
     return(_innerCacheSession.PlaceFileAsync(context, hashesWithPaths, accessMode, replacementMode, realizationMode, cts, urgencyHint));
 }
Ejemplo n.º 21
0
        public async Task <Possible <CasEntries, Failure> > GetCacheEntryAsync(StrongFingerprint strong, UrgencyHint urgencyHint, Guid activityId)
        {
            Contract.Requires(!IsClosed);
            Contract.Requires(strong != null);

            using (var counter = m_counters.GetCacheEntryCounter())
            {
                using (var eventing = new GetCacheEntryActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(strong, urgencyHint);

                    var result = await m_cache.ReadCacheEntryAsync(strong);

                    if (result.Succeeded)
                    {
                        AddSessionRecord(strong);
                        counter.CacheHit();
                        result = result.Result.GetModifiedCasEntriesWithDeterminism(m_cache.IsAuthoritative, m_cache.CacheGuid, DateTime.UtcNow.Add(m_cache.TimeToLive));
                    }

                    return(eventing.Returns(result));
                }
            }
        }
Ejemplo n.º 22
0
        /// <inheritdoc />
        public Task <GetBulkLocationsResult> GetBulkAsync(Context context, IReadOnlyList <ContentHash> contentHashes, CancellationToken cts, UrgencyHint urgencyHint, GetBulkOrigin origin)
        {
            var operationContext = new OperationContext(context, cts);

            if (!_configuration.HasReadMode(ContentLocationMode.Redis) || (origin == GetBulkOrigin.Local && _configuration.HasReadMode(ContentLocationMode.LocalLocationStore)))
            {
                return(_localLocationStore.GetBulkAsync(operationContext, contentHashes, origin));
            }

            Contract.Assert(_redisContentLocationStore != null, "Read or Write mode should support ContentLocationMode.Redis.");
            return(_redisContentLocationStore.GetBulkAsync(context, contentHashes, cts, urgencyHint, origin));
        }
Ejemplo n.º 23
0
        public async Task <Possible <ValidateContentStatus, Failure> > ValidateContentAsync(CasHash hash, UrgencyHint urgencyHint, Guid activityId)
        {
            Contract.Requires(!IsClosed);

            using (var counter = m_counters.ValidateSessionCounter())
            {
                using (var eventing = new ValidateContentActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(hash, urgencyHint);

                    if (CasHash.NoItem.Equals(hash))
                    {
                        return(eventing.Returns(counter.Ok()));
                    }

                    string path = m_cache.ToPath(hash);

                    try
                    {
                        // We don't use ProduceStream as this operation does not pin or cause pinning
                        // and we want to have FileShare.Delete in case we need to delete this entry
                        // due to it being corrupt.  This way there is no race as to which file is
                        // being deleted - it will be the one that was just determined to be corrupt.
                        using (Stream fileData = await m_cache.ContendedOpenStreamAsync(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, useAsync: true, handlePendingDelete: true))
                        {
                            // Size of the file
                            counter.FileSize(fileData.Length);

                            CasHash contentHash = new CasHash(await ContentHashingUtilities.HashContentStreamAsync(fileData));
                            if (contentHash.Equals(hash))
                            {
                                return(eventing.Returns(counter.Ok()));
                            }

                            // Remove it from pinned as it is being removed
                            int junk;
                            m_pinnedToCas.TryRemove(hash, out junk);

                            // Now, we try to remediate - This is a simple delete attempt with any error
                            // saying that we could not delete it
                            try
                            {
                                File.Delete(path);
                                eventing.Write(CacheActivity.CriticalDataOptions, new { RemovedCorruptedEntry = path });

                                return(eventing.Returns(counter.Remediated()));
                            }
                            catch (Exception e)
                            {
                                // Could not delete it (for what ever reason)
                                eventing.Write(CacheActivity.CriticalDataOptions, new { FailedToRemovedCorruptedEntry = path, Reason = e.Message });

                                // The file failed to be deleted, so we need to say that it is still there
                                return(eventing.Returns(counter.Invalid()));
                            }
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        // Not found (either type) is the same as Remediated
                        return(eventing.Returns(counter.Remediated()));
                    }
                    catch (DirectoryNotFoundException)
                    {
                        // Not found (either type) is the same as Remediated
                        return(eventing.Returns(counter.Remediated()));
                    }
                    catch (Exception e)
                    {
                        // Other errors are reported as a failure to produce a stream of the data
                        return(eventing.Returns(new ProduceStreamFailure(CacheId, hash, e)));
                    }
                }
            }
        }
Ejemplo n.º 24
0
        /// <inheritdoc />
        public Task <BoolResult> TouchBulkAsync(Context context, IReadOnlyList <ContentHashWithSize> contentHashes, CancellationToken cts, UrgencyHint urgencyHint)
        {
            var operationContext = new OperationContext(context, cts);

            return(MultiExecuteAsync(
                       executeLegacyStore: () => _redisContentLocationStore.TouchBulkAsync(context, contentHashes, cts, urgencyHint),
                       executeLocalLocationStore: () => _localLocationStore.TouchBulkAsync(operationContext, contentHashes.SelectList(c => c.Hash))));
        }
Ejemplo n.º 25
0
        public async Task <Possible <CasHash, Failure> > AddToCasAsync(
            string filename,
            FileState fileState,
            CasHash?hash,
            UrgencyHint urgencyHint,
            Guid activityId)
        {
            Contract.Requires(!IsClosed);
            Contract.Requires(filename != null);
            Contract.Assert(!IsReadOnly);

            using (var counter = m_counters.AddToCasCounterFile())
            {
                using (var eventing = new AddToCasFilenameActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(filename, fileState, urgencyHint);

                    Possible <CasHash, Failure> result;

                    // First we need to do the hash of the file
                    // We do this "in place" since the CAS may be
                    // on "slow" storage and this is local
                    try
                    {
                        // We keep the file open during this such that others can't modify it
                        // until the add-to-cas has completed.  It also happens to be needed
                        // in order to compute the hash.
                        using (var fileData = await m_cache.ContendedOpenStreamAsync(filename, FileMode.Open, FileAccess.Read, FileShare.Read, handlePendingDelete: false))
                        {
                            counter.ContentSize(fileData.Length);

                            CasHash casHash = new CasHash(await ContentHashingUtilities.HashContentStreamAsync(fileData));

                            try
                            {
                                if (!await m_cache.AddToCasAsync(filename, casHash))
                                {
                                    counter.DuplicatedContent();
                                }

                                // Pin it and return the hash
                                m_pinnedToCas.TryAdd(casHash, 0);
                                result = casHash;
                            }
                            catch (Exception e)
                            {
                                counter.Failed();
                                result = new AddToCasFailure(CacheId, casHash, filename, e);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        counter.Failed();
                        result = new HashFailure(CacheId, filename, e);
                    }

                    return(eventing.Returns(result));
                }
            }
        }
Ejemplo n.º 26
0
 /// <inheritdoc />
 public Task <ObjectResult <IList <ContentHashWithLastAccessTimeAndReplicaCount> > > TrimOrGetLastAccessTimeAsync(Context context, IList <Tuple <ContentHashWithLastAccessTimeAndReplicaCount, bool> > contentHashesWithInfo, CancellationToken cts, UrgencyHint urgencyHint)
 {
     Contract.Assert(_redisContentLocationStore != null, "Read or Write mode should support ContentLocationMode.Redis.");
     return(_redisContentLocationStore.TrimOrGetLastAccessTimeAsync(context, contentHashesWithInfo, cts, urgencyHint));
 }
 /// <inheritdoc />
 public IAsyncEnumerable <GetSelectorResult> GetSelectors(Context context, Fingerprint weakFingerprint, CancellationToken cts, UrgencyHint urgencyHint = UrgencyHint.Nominal)
 {
     return(this.GetSelectorsAsAsyncEnumerable(context, weakFingerprint, cts, urgencyHint));
 }
Ejemplo n.º 28
0
 /// <inheritdoc />
 public Task <BoolResult> UpdateBulkAsync(Context context, IReadOnlyList <ContentHashWithSizeAndLocations> contentHashesWithSizeAndLocations, CancellationToken cts, UrgencyHint urgencyHint, LocationStoreOption locationStoreOption)
 {
     Contract.Assert(_redisContentLocationStore != null, "Read or Write mode should support ContentLocationMode.Redis.");
     return(_redisContentLocationStore.UpdateBulkAsync(context, contentHashesWithSizeAndLocations, cts, urgencyHint, locationStoreOption));
 }
 /// <inheritdoc />
 public Task <PinResult> PinAsync(Context context, ContentHash contentHash, CancellationToken cts, UrgencyHint urgencyHint)
 {
     return(_contentReadOnlySession.PinAsync(context, contentHash, cts, urgencyHint));
 }
Ejemplo n.º 30
0
 /// <inheritdoc />
 protected override Task <PlaceFileResult> PlaceFileCoreAsync(OperationContext operationContext, ContentHash contentHash, AbsolutePath path, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
 => Task.FromResult(new PlaceFileResult(PlaceFileResult.ResultCode.NotPlacedContentNotFound));