Exemple #1
0
 Result <MachineLocation[]> IDistributedContentCopierHost.GetDesignatedLocations(ContentHash hash)
 {
     return(_contentLocationStore.GetDesignatedLocations(hash));
 }
Exemple #2
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="PutResult" /> class.
 /// </summary>
 public PutResult(ResultBase other, ContentHash contentHash, string message = null)
     : base(other, message)
 {
     ContentHash = contentHash;
 }
        /// <inheritdoc />
        public async Task <FileExistenceResult> CheckFileExistsAsync(Context context, ContentHash contentHash)
        {
            if (InnerContentStore is IStreamStore innerStreamStore)
            {
                return(await innerStreamStore.CheckFileExistsAsync(context, contentHash));
            }

            return(new FileExistenceResult(FileExistenceResult.ResultCode.Error, $"{InnerContentStore} does not implement {nameof(IStreamStore)} in {nameof(DistributedContentStore<T>)}."));
        }
 /// <nodoc />
 protected abstract Task <OpenStreamResult> OpenStreamCoreAsync(
     OperationContext operationContext,
     ContentHash contentHash,
     UrgencyHint urgencyHint,
     Counter retryCounter);
Exemple #5
0
 /// <inheritdoc />
 protected override Task <PutResult> PutStreamCoreAsync(OperationContext operationContext, ContentHash contentHash, Stream stream, UrgencyHint urgencyHint, Counter retryCounter)
 {
     return(_innerSession.PutStreamAsync(operationContext, contentHash, stream, operationContext.Token, urgencyHint));
 }
Exemple #6
0
        /// <inheritdoc />
        protected override async Task <PlaceFileResult> PlaceFileCoreAsync(OperationContext operationContext, ContentHash contentHash, AbsolutePath path, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
        {
            if (replacementMode != FileReplacementMode.ReplaceExisting && _fileSystem.FileExists(path))
            {
                if (replacementMode == FileReplacementMode.SkipIfExists)
                {
                    return(new PlaceFileResult(PlaceFileResult.ResultCode.NotPlacedAlreadyExists));
                }
                else if (replacementMode == FileReplacementMode.FailIfExists)
                {
                    return(new PlaceFileResult(
                               PlaceFileResult.ResultCode.Error,
                               $"File exists at destination {path} with FailIfExists specified"));
                }
            }

            var virtualPath = _contentManager.ToVirtualPath(path);

            if (virtualPath == null)
            {
                return(await _innerSession.PlaceFileAsync(operationContext, contentHash, path, accessMode, replacementMode, realizationMode, operationContext.Token, urgencyHint));
            }

            _contentManager.Tree.AddFileNode(virtualPath, new VfsFilePlacementData(contentHash, realizationMode, accessMode));
            return(new PlaceFileResult(GetPlaceResultCode(realizationMode, accessMode), fileSize: -1 /* Unknown */));
        }
Exemple #7
0
        private Task <ProactiveCopyResult> RequestProactiveCopyIfNeededAsync(OperationContext context, ContentHash hash)
        {
            if (!_pendingProactivePuts.Add(hash))
            {
                return(Task.FromResult(ProactiveCopyResult.CopyNotRequiredResult));
            }

            return(context.PerformOperationAsync(
                       Tracer,
                       traceErrorsOnly: true,
                       operation: async() =>
            {
                try
                {
                    var hashArray = _buildIdHash != null
                            ? new[] { hash, _buildIdHash.Value }
                            : new[] { hash };

                    // First check in local location store, then global if failed.
                    var getLocationsResult = await ContentLocationStore.GetBulkAsync(context, hashArray, context.Token, UrgencyHint.Nominal, GetBulkOrigin.Local);
                    if (getLocationsResult.Succeeded && getLocationsResult.ContentHashesInfo[0].Locations.Count > Settings.ProactiveCopyLocationsThreshold)
                    {
                        _counters[Counters.GetLocationsSatisfiedFromLocal].Increment();
                        return ProactiveCopyResult.CopyNotRequiredResult;
                    }
                    else
                    {
                        getLocationsResult += await ContentLocationStore.GetBulkAsync(context, hashArray, context.Token, UrgencyHint.Nominal, GetBulkOrigin.Global).ThrowIfFailure();
                        _counters[Counters.GetLocationsSatisfiedFromRemote].Increment();
                    }

                    if (getLocationsResult.ContentHashesInfo[0].Locations.Count > Settings.ProactiveCopyLocationsThreshold)
                    {
                        return ProactiveCopyResult.CopyNotRequiredResult;
                    }

                    IReadOnlyList <MachineLocation> buildRingMachines;

                    // Get random machine inside build ring
                    Task <BoolResult> insideRingCopyTask;
                    if (_buildIdHash != null)
                    {
                        buildRingMachines = getLocationsResult.ContentHashesInfo[getLocationsResult.ContentHashesInfo.Count - 1].Locations;
                        var candidates = buildRingMachines.Where(m => !m.Equals(LocalCacheRootMachineLocation)).ToArray();
                        if (candidates.Length > 0)
                        {
                            var candidate = candidates[ThreadSafeRandom.Generator.Next(0, candidates.Length)];
                            Tracer.Info(context, $"{nameof(RequestProactiveCopyIfNeededAsync)}: Copying {hash.ToShortString()} to machine '{candidate}' in build ring (of {candidates.Length} machines).");
                            insideRingCopyTask = DistributedCopier.RequestCopyFileAsync(context, hash, candidate);
                        }
                        else
                        {
                            insideRingCopyTask = Task.FromResult(new BoolResult("Could not find any machines belonging to the build ring."));
                        }
                    }
                    else
                    {
                        insideRingCopyTask = Task.FromResult(new BoolResult("BuildId was not specified, so machines in the build ring cannot be found."));
                        buildRingMachines = new[] { LocalCacheRootMachineLocation };
                    }

                    Task <BoolResult> outsideRingCopyTask;
                    var getLocationResult = ContentLocationStore.GetRandomMachineLocation(except: buildRingMachines);
                    if (getLocationResult.Succeeded)
                    {
                        var candidate = getLocationResult.Value;
                        Tracer.Info(context, $"{nameof(RequestProactiveCopyIfNeededAsync)}: Copying {hash.ToShortString()} to machine '{candidate}' outside build ring.");
                        outsideRingCopyTask = DistributedCopier.RequestCopyFileAsync(context, hash, candidate);
                    }
                    else
                    {
                        outsideRingCopyTask = Task.FromResult(new BoolResult(getLocationResult));
                    }

                    return new ProactiveCopyResult(await insideRingCopyTask, await outsideRingCopyTask);
                }
                finally
                {
                    _pendingProactivePuts.Remove(hash);
                }
            }));
        }
Exemple #8
0
 protected override void CorruptContent(TestFileSystemContentStoreInternal store, ContentHash contentHash)
 {
     store.CorruptContent(contentHash);
 }
        public static ReplicaRank GetReplicaRank(
            ContentHash hash,
            ContentLocationEntry entry,
            MachineId localMachineId,
            LocalLocationStoreConfiguration configuration,
            DateTime now)
        {
            var locationsCount = entry.Locations.Count;

            var desiredReplicaCount = configuration.DesiredReplicaRetention;

            if (desiredReplicaCount == 0 ||
                locationsCount == 0) // It is possible for the entry to have 0 locations.
                                     // For instance, the database has 1 location but the machine is in the bad state
            {
                return(ReplicaRank.None);
            }

            if (locationsCount <= desiredReplicaCount
                // If using throttled eviction, we might need to upgrade the rank to Protected
                // so don't return here
                && configuration.ThrottledEvictionInterval == TimeSpan.Zero)
            {
                return(ReplicaRank.Important);
            }

            // Making sure that probabilistically, some locations are considered important for the current machine.
            long contentHashCode = unchecked ((uint)HashCodeHelper.Combine(hash[0] | hash[1] << 8, hash[1]));

            var importantRangeStart = contentHashCode % locationsCount;

            // Getting an index of a current location in the location list
            int currentMachineLocationIndex = entry.Locations.GetMachineIdIndex(localMachineId);

            if (currentMachineLocationIndex == -1)
            {
                // This is used for testing only. The machine Id should be part of the machines.
                // But in tests it is useful to control the behavior of this method and in some cases to guarantee that some replica won't be important.
                return(ReplicaRank.None);
            }

            // In case of important range wrapping around end of location list to start of location list
            // we need to compute a positive offset from the range start to see if the replica exists in the range
            // i.e. range start = 5, location count = 7, and desired location count = 3
            // important range contains [5, 6 and 0] since it overflows the end of the list
            var offset = currentMachineLocationIndex - importantRangeStart;

            if (offset < 0)
            {
                offset += locationsCount;
            }

            var lastImportantReplicaOffset = Math.Min(desiredReplicaCount, locationsCount) - 1;

            if (offset >= desiredReplicaCount)
            {
                return(ReplicaRank.None);
            }

            if (offset != lastImportantReplicaOffset)
            {
                // All but last important replica are always Protected
                return(ReplicaRank.Protected);
            }

            if (configuration.ThrottledEvictionInterval == TimeSpan.Zero)
            {
                // Throttled eviction is disabled. Just mark the replica as important
                // since its in the important range
                return(ReplicaRank.Important);
            }

            // How throttled eviction works:
            // 1. Compute which machines consider the content important
            // This is done by computing a hash code from the content hash modulo location count to
            // generate a start index into the list replicas.
            // For instance,
            // given locations: [4, 11, 22, 35, 73, 89]
            // locationCount = 6,
            // if contentHashCode % locationCount = 2 and DesiredReplicaCount = 3
            // then the machines considering content important are [22, 35, 73]
            // 2. All but last important replica must be consider Protected (i.e. 22, 35 have rank Protected)
            // 3. Compute if last replica is protected.
            // This is based of to time ranges or buckets of duration ThrottledEvictionInterval
            // For instance,
            // if ThrottleInterval = 20 minutes
            // 10:00AM-10:20AM -> (timeBucketIndex = 23045230) % DesiredReplicaCount = 2 = evictableOffset
            // 10:20AM-10:40AM -> (timeBucketIndex = 23045231) % DesiredReplicaCount = 0 = evictableOffset
            // 10:40AM-11:00AM -> (timeBucketIndex = 23045232) % DesiredReplicaCount = 1 = evictableOffset
            // 11:00AM-11:20AM -> (timeBucketIndex = 23045233) % DesiredReplicaCount = 2 = evictableOffset
            // So for times 10:00AM-10:20AM and 11:00AM-11:20AM the last important replica is evictable
            var timeBucketIndex = now.Ticks / configuration.ThrottledEvictionInterval.Ticks;

            // NOTE: We add contentHashCode to timeBucketIndex so that not all Protected content is considered evictable
            // at the same time
            var evictableOffset = (contentHashCode + timeBucketIndex) % desiredReplicaCount;

            if (evictableOffset == offset)
            {
                return(ReplicaRank.Important);
            }
            else
            {
                // The replica is not currently evictable. Mark it as protected which will give it the minimum effective age
                // so that it is only evicted as a last resort
                return(ReplicaRank.Protected);
            }
        }
 /// <nodoc />
 public static Task <EvictResult> EvictAsync(
     this ContentStoreInternalTracer tracer, OperationContext context, ContentHash contentHash, Func <Task <EvictResult> > func)
 {
     return(EvictCall.RunAsync(tracer, context, contentHash, func));
 }
 public override string ToString()
 {
     return($"[ContentHash={ContentHash.ToShortString()} Size={Size} LocationCount={Locations?.Count}]");
 }
 public ContentHashWithSizeAndLocations(ContentHash contentHash, long size = -1)
 {
     ContentHash = contentHash;
     Size        = size;
 }
Exemple #13
0
        private async Task <ProactiveCopyResult> ProactiveCopyIfNeededAsync(OperationContext operationContext, ContentHash hash)
        {
            var sessionResult = await ProactiveCopySession.Value;

            if (sessionResult)
            {
                return(await sessionResult.Value.ProactiveCopyIfNeededAsync(
                           operationContext,
                           hash,
                           tryBuildRing : false,
                           reason : ProactiveCopyReason.Replication));
            }

            return(new ProactiveCopyResult(sessionResult, "Failed to retrieve session for proactive copies."));
        }
Exemple #14
0
        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.AssertNotNull(result.Exception);
                    headers.Add("Exception", result.Exception.GetType().Name);
                    headers.Add("Message", result.Exception.Message);
                    break;

                case OpenStreamResult.ResultCode.Success:
                    Contract.AssertNotNull(result.Stream);
                    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.
                    }
                }
            }
        }
Exemple #15
0
        /// <summary>
        /// Deserializes an <see cref="IPipFingerprintEntryData"/> of the appropriate concrete type (or null if the type is unknown).
        /// <see cref="PipFingerprintEntry"/> is a tagged polymorphic container (see <see cref="Kind"/>),
        /// and this operation unwraps it. The returned instance contains all relevant data for the entry.
        /// </summary>
        public IPipFingerprintEntryData Deserialize(CacheQueryData cacheQueryData = null)
        {
            if (Kind == PipFingerprintEntryKind.Unknown)
            {
                return(null);
            }

            if (m_deserializedEntryData != null)
            {
                return(m_deserializedEntryData);
            }

            try
            {
                InputBuffer buffer = new InputBuffer(DataBlob);
                CompactBinaryReader <InputBuffer> reader = new CompactBinaryReader <InputBuffer>(buffer);
                IPipFingerprintEntryData          deserialized;

                switch (Kind)
                {
                case PipFingerprintEntryKind.DescriptorV1:
                    deserialized = Deserialize <PipCacheDescriptor> .From(reader);

                    break;

                case PipFingerprintEntryKind.DescriptorV2:
                    deserialized = Deserialize <PipCacheDescriptorV2Metadata> .From(reader);

                    break;

                case PipFingerprintEntryKind.GraphDescriptor:
                    deserialized = Deserialize <PipGraphCacheDescriptor> .From(reader);

                    break;

                case PipFingerprintEntryKind.FileDownload:
                    deserialized = Deserialize <FileDownloadDescriptor> .From(reader);

                    break;

                case PipFingerprintEntryKind.PackageDownload:
                    deserialized = Deserialize <PackageDownloadDescriptor> .From(reader);

                    break;

                case PipFingerprintEntryKind.GraphInputDescriptor:
                    deserialized = Deserialize <PipGraphInputDescriptor> .From(reader);

                    break;

                default:
                    throw Contract.AssertFailure("Unhandled PipFingerprintEntryKind");
                }

                Interlocked.CompareExchange(ref m_deserializedEntryData, deserialized, comparand: null);
                return(Volatile.Read(ref m_deserializedEntryData));
            }
            catch (Exception exception)
            {
                if (IsCorrupted)
                {
                    OutputBuffer valueBuffer = new OutputBuffer(1024);
                    CompactBinaryWriter <OutputBuffer> writer = new CompactBinaryWriter <OutputBuffer>(valueBuffer);
                    Serialize.To(writer, this);

                    // Include in the log the hash of this instance so that we can trace it in the cache log, and obtain the file in the CAS.
                    ContentHash valueHash = ContentHashingUtilities.HashBytes(
                        valueBuffer.Data.Array,
                        valueBuffer.Data.Offset,
                        valueBuffer.Data.Count);

                    const string Unspecified     = "<Unspecified>";
                    string       actualEntryBlob = Unspecified;
                    string       actualEntryHash = Unspecified;

                    if (cacheQueryData != null && cacheQueryData.ContentCache != null)
                    {
                        var maybeActualContent = cacheQueryData.ContentCache.TryLoadContent(
                            cacheQueryData.MetadataHash,
                            failOnNonSeekableStream: true,
                            byteLimit: 20 * 1024 * 1024).Result;

                        if (maybeActualContent.Succeeded && maybeActualContent.Result != null)
                        {
                            actualEntryBlob = ToByteArrayString(maybeActualContent.Result);
                            actualEntryHash = ContentHashingUtilities.HashBytes(maybeActualContent.Result).ToString();
                        }
                    }

                    Logger.Log.DeserializingCorruptedPipFingerprintEntry(
                        Events.StaticContext,
                        kind: Kind.ToString(),
                        weakFingerprint: cacheQueryData?.WeakContentFingerprint.ToString() ?? Unspecified,
                        pathSetHash: cacheQueryData?.PathSetHash.ToString() ?? Unspecified,
                        strongFingerprint: cacheQueryData?.StrongContentFingerprint.ToString() ?? Unspecified,
                        expectedHash: cacheQueryData?.MetadataHash.ToString() ?? Unspecified, // expected metadata hash
                        hash: valueHash.ToString(),                                           // re-computed hash
                        blob: ToDataBlobString(),                                             // blob of data carried by pip fingerprint entry
                        actualHash: actualEntryHash,                                          // actual pip fingerprint entry hash
                        actualEntryBlob: actualEntryBlob);                                    // actual pip fingerprint entry blob

                    throw new BuildXLException("Deserializing corrupted pip fingerprint entry", exception, ExceptionRootCause.CorruptedCache);
                }

                // We don't expect this to happen so rethrow the exception.
                throw;
            }
        }
Exemple #16
0
 /// <nodoc />
 public DownloadIncrementalState(DownloadData downloadData, ContentHash contentHash)
 {
     m_downloadData = downloadData;
     ContentHash    = contentHash;
 }
 /// <inheritdoc />
 public PathBase GeneratePath(ContentHash contentHash, byte[] contentLocationIdContent) => null;
Exemple #18
0
 /// <inheritdoc />
 protected override Task <PutResult> PutFileCoreAsync(OperationContext operationContext, ContentHash contentHash, AbsolutePath path, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
 {
     return(_innerSession.PutFileAsync(operationContext, contentHash, path, realizationMode, operationContext.Token, urgencyHint));
 }
 public override AbsolutePath GeneratePath(ContentHash contentHash, byte[] contentLocationIdContent)
 {
     LastContentLocation = contentLocationIdContent;
     return(_root);
 }
Exemple #20
0
 /// <inheritdoc />
 protected override Task <PinResult> PinCoreAsync(OperationContext operationContext, ContentHash contentHash, UrgencyHint urgencyHint, Counter retryCounter)
 {
     return(_innerSession.PinAsync(operationContext, contentHash, operationContext.Token, urgencyHint));
 }
Exemple #21
0
 public PutResult(bool succeeded, ContentHash contentHash, string errorMessage, string diagnostics = null)
     : base(succeeded, errorMessage, diagnostics)
 {
     ContentHash = contentHash;
 }
        /// <summary>
        /// Records a <see cref="ContentHash" /> for the given file handle. This hash mapping will be persisted to disk if the
        /// table is saved with <see cref="SaveAsync" />. The given file handle should be opened with at most Read sharing
        /// (having the handle should ensure the file is not being written).
        /// This returns a <see cref="VersionedFileIdentityAndContentInfo"/>:
        /// - The identity has the kind <see cref="VersionedFileIdentity.IdentityKind.StrongUsn"/> if a USN-based identity was successfully established;
        ///   the identity may have kind <see cref="VersionedFileIdentity.IdentityKind.Anonymous"/> if such an identity was unavailable.
        /// - Regardless, the contained <see cref="FileContentInfo"/> contains the actual length of the stream corresponding to <paramref name="hash"/>.
        /// </summary>
        /// <remarks>
        /// An overload taking a file path is intentionally not provided. This should be called after hashing or writing a file,
        /// but before closing the handle. This way, there is no race between establishing the file's hash, some unrelated writer,
        /// and recording its file version (e.g., USN) to hash mapping.
        /// Note that this results in a small amount of I/O (e.g., on Windows, a file open and USN query), but never hashes the file or reads its contents.
        /// The <paramref name="strict"/> corresponds to the <c>flush</c> parameter of <see cref="VersionedFileIdentity.TryEstablishStrong"/>
        /// </remarks>
        public VersionedFileIdentity RecordContentHash(
            string path,
            SafeFileHandle handle,
            ContentHash hash,
            long length,
            bool?strict = default)
        {
            Contract.Requires(handle != null);
            Contract.Requires(!string.IsNullOrWhiteSpace(path));

            using (Counters.StartStopwatch(FileContentTableCounters.RecordContentHashDuration))
            {
                // TODO: The contract below looks very nice but breaks tons of UT
                // Fix the tests and enable the contract.
                // Contract.Requires(FileContentInfo.IsValidLength(length, hash));
                // Here we write a new change journal record for this file to get a 'strong' identity. This means that the USN -> hash table
                // only ever contains USNs whose records have the 'close' reason set. Recording USNs without that
                // reason set would not be correct; it would be possible that multiple separate changes (e.g. writes)
                // were represented with the same USN, and so intermediate USNs do not necessarily correspond to exactly
                // one snapshot of a file. See http://msdn.microsoft.com/en-us/library/windows/desktop/aa363803(v=vs.85).aspx
                Possible <VersionedFileIdentity, Failure <VersionedFileIdentity.IdentityUnavailabilityReason> > possibleVersionedIdentity =
                    TryEstablishStrongIdentity(handle, flush: strict == true);

                if (!possibleVersionedIdentity.Succeeded)
                {
                    if (Interlocked.CompareExchange(ref m_changeJournalWarningLogged, 1, 0) == 0)
                    {
                        Tracing.Logger.Log.StorageFileContentTableIgnoringFileSinceVersionedFileIdentityIsNotSupported(
                            Events.StaticContext,
                            path,
                            possibleVersionedIdentity.Failure.DescribeIncludingInnerFailures());
                    }

                    return(VersionedFileIdentity.Anonymous);
                }

                VersionedFileIdentity identity = possibleVersionedIdentity.Result;

                var newEntry = new Entry(identity.Usn, hash, length, EntryTimeToLive);

                // We allow concurrent update attempts with different observed USNs.
                // This is useful and relevant for two reasons:
                // - Querying a 'strong' identity (TryEstablishStrongIdentity) generates a new CLOSE record every time.
                // - Creating hardlinks generates 'hardlink change' records.
                // So, concurrently creating and recording (or even just recording) different links is possible, and
                // keeping the last stored entry (rather than highest-USN entry) can introduce false positives.
                var fileIdAndVolumeId = new FileIdAndVolumeId(identity.VolumeSerialNumber, identity.FileId);

                m_entries.AddOrUpdate(
                    new FileIdAndVolumeId(identity.VolumeSerialNumber, identity.FileId),
                    newEntry,
                    updateValueFactory: (key, existingEntry) =>
                {
                    if (existingEntry.Usn > newEntry.Usn)
                    {
                        return(existingEntry);
                    }

                    if (newEntry.Hash == existingEntry.Hash)
                    {
                        Counters.IncrementCounter(FileContentTableCounters.NumUsnMismatch);
                        Tracing.Logger.Log.StorageUsnMismatchButContentMatch(
                            Events.StaticContext,
                            path,
                            existingEntry.Usn.Value,
                            newEntry.Usn.Value,
                            existingEntry.Hash.ToHex());
                    }
                    else
                    {
                        // Stale USN.
                        Counters.IncrementCounter(FileContentTableCounters.NumContentMismatch);
                    }

                    return(newEntry);
                });

                Tracing.Logger.Log.StorageRecordNewKnownUsn(
                    Events.StaticContext,
                    path,
                    identity.FileId.High,
                    identity.FileId.Low,
                    identity.VolumeSerialNumber,
                    identity.Usn.Value,
                    hash.ToHex());

                return(identity);
            }
        }
Exemple #23
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="PutResult"/> class.
 /// </summary>
 public PutResult(ContentHash contentHash, string errorMessage, string diagnostics = null)
     : base(errorMessage, diagnostics)
 {
     ContentHash = contentHash;
 }
 /// <inheritdoc />
 public Task <DeleteResult> DeleteAsync(Context context, ContentHash contentHash)
 {
     throw new NotImplementedException();
 }
Exemple #25
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="PutResult" /> class.
 /// </summary>
 public PutResult(Exception exception, ContentHash contentHash, string message = null)
     : base(exception, message)
 {
     ContentHash = contentHash;
 }
Exemple #26
0
 /// <nodoc />
 protected abstract Task <PinResult> PinCoreAsync(
     OperationContext operatonContext,
     ContentHash contentHash,
     UrgencyHint urgencyHint,
     Counter retryCounter);
 internal static string GetRedisKey(ContentHash hash)
 {
     // Use the string representation short hash used in other parts of the system (db and event stream) as the redis key
     return(new ShortHash(hash).ToString());
 }