Example #1
0
 public AcceptableEntry(PipFingerprintEntry entry)
 {
     Contract.Requires(entry != null);
     Entry = entry;
 }
Example #2
0
        /// <summary>
        /// Attempts to store a fingerprint entry; this is a compare-exchange operation, in which <paramref name="previousEntry"/>
        /// must match what is currently stored (or must be <c>null</c> if no entry is currently stored).
        /// This operation will fail if the previous entry doesn't match, or if the store could not normally proceed.
        /// </summary>
        public async Task <Possible <CacheEntryPublishResult, Failure> > TryStoreFingerprintEntryAsync(
            ContentFingerprint fingerprint,
            PipFingerprintEntry entry,
            PipFingerprintEntry previousEntry = null,
            bool replaceExisting          = true,
            CacheQueryData cacheQueryData = null)
        {
            Contract.Assume(entry != null);
            Analysis.IgnoreArgument(previousEntry); // See class remarks; replace semantics are broken.

            // We have in hand a PipFingerprintEntry which the underlyign m_twoPhaseStore does not understand.
            // We will serialize it and store it to the CAS, and that CAS hash will be the stored entry's MetadataHash.
            // See symmetric deserialization in TryGetFingerprintEntryAsync.
            Possible <ContentHash, Failure> maybeStored = await m_contentCache.TrySerializeAndStoreContent(entry);

            if (!maybeStored.Succeeded)
            {
                return(maybeStored.Failure.Annotate("Failed to store cache-entry metadata to the CAS"));
            }

            ContentHash metadataHash = maybeStored.Result;

            // The metadata (single-phase entry) is stored, so now we can construct an entry that references it.
            // From now on, 'twoPhaseEntry' will mean 'the entry we are actually storing in the two-phase store'.
            // Meanwhile, like any implementation, we assume that the referenced content (e.g. output files)
            // were stored by the caller already.
            ContentHash[] twoPhaseReferencedHashes = entry.OutputContentHashes.Select(b => b.ToContentHash()).Where(hash => !hash.IsSpecialValue()).ToArray();
            CacheEntry    twoPhaseEntry            = new CacheEntry(metadataHash, null, ArrayView <ContentHash> .FromArray(twoPhaseReferencedHashes));

            StrongContentFingerprint dummyFingerprint = ComputeDummyStrongFingerprint(
                m_pathTable,
                fingerprint);

            var weakFingerprint = new WeakContentFingerprint(fingerprint.Hash);

            Possible <CacheEntryPublishResult, Failure> maybePublished = await m_twoPhaseStore.TryPublishCacheEntryAsync(
                weakFingerprint : weakFingerprint,
                pathSetHash : s_dummyPathSetHash,
                strongFingerprint : dummyFingerprint,
                entry : twoPhaseEntry,
                mode : replaceExisting?CacheEntryPublishMode.CreateNewOrReplaceExisting : CacheEntryPublishMode.CreateNew);

            if (cacheQueryData != null)
            {
                cacheQueryData.WeakContentFingerprint   = weakFingerprint;
                cacheQueryData.PathSetHash              = s_dummyPathSetHash;
                cacheQueryData.StrongContentFingerprint = dummyFingerprint;
                cacheQueryData.ContentCache             = m_contentCache;
            }

            if (maybePublished.Succeeded)
            {
                if (maybePublished.Result.Status == CacheEntryPublishStatus.Published ||
                    (!replaceExisting && maybePublished.Result.Status == CacheEntryPublishStatus.RejectedDueToConflictingEntry))
                {
                    return(maybePublished.Result);
                }
                else
                {
                    // ISinglePhaseFingerprintStore represents conflicts as failures.
                    return(new Failure <string>(
                               "Failed to publish a cache entry; the underlying two-phase store indicated an entry conflict (maybe it does not allow replacement of existing entries)."));
                }
            }
            else
            {
                return(maybePublished.Failure);
            }
        }