Beispiel #1
0
        public void ContentHashListWithDeterminismProperty()
        {
            var contentHashListWithDeterminism = new ContentHashListWithDeterminism(
                ContentHashList.Random(), CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires));

            Assert.Equal(contentHashListWithDeterminism, new GetContentHashListResult(contentHashListWithDeterminism).ContentHashListWithDeterminism);
        }
Beispiel #2
0
        public void ViaCacheRoundtrip()
        {
            var guid        = CacheDeterminism.NewCacheGuid();
            var determinism = CacheDeterminism.ViaCache(guid, DateTime.MaxValue);

            Assert.Equal(guid, determinism.EffectiveGuid);
        }
Beispiel #3
0
        /// <nodoc />
        public static ContentHashListWithDeterminism FromGrpc(this ContentHashListWithDeterminismData input)
        {
            ContentHashList  contentHashList = input.ContentHashList.FromGrpc();
            CacheDeterminism determinism     = FromGrpc(input.CacheDeterminism);

            return(new ContentHashListWithDeterminism(contentHashList, determinism));
        }
Beispiel #4
0
 /// <nodoc />
 public MemCache(CacheId cacheId, bool strictMetadataCasCoupling, bool isauthoritative)
 {
     m_cacheGuid                 = CacheDeterminism.NewCacheGuid();
     m_cacheId                   = cacheId;
     IsAuthoritative             = isauthoritative;
     m_strictMetadataCasCoupling = strictMetadataCasCoupling;
 }
Beispiel #5
0
        /// <summary>
        ///     Load value from the filesystem.
        /// </summary>
        public static Guid Load(IAbsFileSystem fileSystem, AbsolutePath filePath)
        {
            Guid guid;

            try
            {
                // First try reading the GUID file
                guid = Read(fileSystem, filePath);
            }
            catch (Exception e) when(e is CacheException || e is IOException)
            {
                // If that fails, we likely need to create a Guid
                guid = CacheDeterminism.NewCacheGuid();
                try
                {
                    fileSystem.CreateDirectory(filePath.Parent);

                    // Write the Guid file
                    fileSystem.WriteAllBytes(filePath, Encoding.UTF8.GetBytes(guid.ToString(SerializationFormat)));
                }
                catch (Exception ex) when(ex is IOException)
                {
                    // If we failed to write the Guid file we may have just missed getting the guid in the first place,
                    // so let us try to read it again.  This failure we let go all the way out.
                    guid = Read(fileSystem, filePath);
                }
            }

            return(guid);
        }
Beispiel #6
0
        private static CacheDeterminism ReadDeterminism(byte[] determinismBytes, byte[] oldDeterminismBytes)
        {
            var determinism        = CacheDeterminism.Deserialize(determinismBytes);
            var oldDeterminismGuid = new Guid(oldDeterminismBytes);

            // If the old guid was ToolDeterministic, we need to keep it that way.
            if (oldDeterminismGuid == CacheDeterminism.Tool.Guid)
            {
                return(CacheDeterminism.Tool);
            }

            // If the old guid was SinglePhaseNonDeterministic, we need to keep it that way.
            if (oldDeterminismGuid == CacheDeterminism.SinglePhaseNonDeterministic.Guid)
            {
                return(CacheDeterminism.SinglePhaseNonDeterministic);
            }

            // The newer code always sets the old "Determinism" column to the same determinism guid when it writes a new value,
            // so if we read here that the determinism from the old column is different from
            // the new "SerializedDeterminism" column's guid then the ContentHashList in this row was inserted by the
            // old code and the new column's Determinism value is no longer valid. In that case, we return None.
            return(oldDeterminismGuid == determinism.EffectiveGuid
                ? determinism
                : CacheDeterminism.None);
        }
Beispiel #7
0
        public void EqualsFalseContentHashListMismatch()
        {
            var determinism = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires);
            var v1          = new GetContentHashListResult(new ContentHashListWithDeterminism(ContentHashList.Random(), determinism));
            var v2          = new GetContentHashListResult(new ContentHashListWithDeterminism(ContentHashList.Random(), determinism));

            Assert.False(v1.Equals(v2));
        }
Beispiel #8
0
        public void NewCacheGuidCreatesNonSpecialValue()
        {
            var guid = CacheDeterminism.NewCacheGuid();

            Assert.NotEqual(CacheDeterminism.None.EffectiveGuid, guid);
            Assert.NotEqual(CacheDeterminism.Tool.EffectiveGuid, guid);
            Assert.NotEqual(CacheDeterminism.SinglePhaseNonDeterministic.EffectiveGuid, guid);
        }
Beispiel #9
0
 /// <nodoc />
 public static CacheDeterminismData ToGrpc(this CacheDeterminism determinism)
 {
     return(new CacheDeterminismData
     {
         ExpirationUtc = determinism.ExpirationUtc.Ticks,
         Guid = determinism.Guid.ToByteArray().ToByteString()
     });
 }
Beispiel #10
0
        public void GetHashCodeNotSameWhenNotEqual()
        {
            var v1 = new GetContentHashListResult(new ContentHashListWithDeterminism(
                                                      ContentHashList.Random(), CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires)));
            var v2 = new GetContentHashListResult(new ContentHashListWithDeterminism(
                                                      ContentHashList.Random(), CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires)));

            Assert.NotEqual(v1.GetHashCode(), v2.GetHashCode());
        }
Beispiel #11
0
        public void EqualsFalseDeterminismMismatch()
        {
            var v1 = new AddOrGetContentHashListResult(
                new ContentHashListWithDeterminism(null, CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.MaxValue)));
            var v2 = new AddOrGetContentHashListResult(
                new ContentHashListWithDeterminism(null, CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.MaxValue)));

            Assert.False(v1.Equals(v2));
        }
        public async Task Roundtrip()
        {
            var fileName = $"{Guid.NewGuid()}.json";

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var sessionId        = 42;
                var serializedConfig = "Foo";
                var pat = Guid.NewGuid().ToString();

                var numOperations = 3;
                var operations    = Enumerable.Range(0, numOperations)
                                    .Select(_ => generateRandomOperation())
                                    .ToList();

                var sessionInfo = new HibernatedCacheSessionInfo(sessionId, serializedConfig, pat, operations);
                var sessions1   = new HibernatedSessions <HibernatedCacheSessionInfo>(new List <HibernatedCacheSessionInfo> {
                    sessionInfo
                });
                await sessions1.WriteAsync(FileSystem, directory.Path, fileName);

                FileSystem.HibernatedSessionsExists(directory.Path, fileName).Should().BeTrue();

                var fileSize = FileSystem.GetFileSize(directory.Path / fileName);
                fileSize.Should().BeGreaterThan(0);

                var sessions2 = await FileSystem.ReadHibernatedSessionsAsync <HibernatedCacheSessionInfo>(directory.Path, fileName);

                sessions2.Sessions.Count.Should().Be(1);
                sessions2.Sessions[0].Id.Should().Be(sessionId);
                sessions2.Sessions[0].SerializedSessionConfiguration.Should().Be(serializedConfig);
                sessions2.Sessions[0].Pat.Should().Be(pat);
                sessions2.Sessions[0].PendingPublishingOperations.Should().BeEquivalentTo(operations);

                await FileSystem.DeleteHibernatedSessions(directory.Path, fileName);

                PublishingOperation generateRandomOperation()
                {
                    var amountOfHashes  = 3;
                    var hashes          = Enumerable.Range(0, amountOfHashes).Select(_ => ContentHash.Random()).ToArray();
                    var contentHashList = new ContentHashList(hashes);
                    var determinism     = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.UtcNow.AddMilliseconds(ThreadSafeRandom.Generator.Next()));
                    var contentHashListWithDeterminism = new ContentHashListWithDeterminism(contentHashList, determinism);

                    var fingerprint       = new Fingerprint(ContentHash.Random().ToByteArray());
                    var selector          = new Selector(ContentHash.Random());
                    var strongFingerprint = new StrongFingerprint(fingerprint, selector);

                    return(new PublishingOperation
                    {
                        ContentHashListWithDeterminism = contentHashListWithDeterminism,
                        StrongFingerprint = strongFingerprint
                    });
                }
            }
        }
Beispiel #13
0
        private ICache CreateBackendCache(AbsolutePath rootPath)
        {
            var configuration      = ContentStoreConfiguration.CreateWithMaxSizeQuotaMB(1);
            var configurationModel = new ConfigurationModel(configuration);

            return(new OneLevelCache(
                       () => new FileSystemContentStore(FileSystem, SystemClock.Instance, rootPath, configurationModel),
                       () => new MemoryMemoizationStore(Logger),
                       CacheDeterminism.NewCacheGuid()));
        }
Beispiel #14
0
        public virtual async Task NonDeterministicContentRespectsDisconnect()
        {
            string testCacheId = "Disconnected";
            ICache testCache   = await InitializeCacheAsync(NewCache(testCacheId, false)).SuccessAsync();

            VerticalCacheAggregator vertCache = testCache as VerticalCacheAggregator;

            XAssert.IsNotNull(vertCache);

            ICacheSession aggregatorSession = (await testCache.CreateSessionAsync()).Success();
            ICacheSession localSession      = (await vertCache.LocalCache.CreateSessionAsync()).Success();
            ICacheSession remoteSession     = (await vertCache.RemoteCache.CreateSessionAsync()).Success();

            VerticalCacheAggregatorSession vertSession = aggregatorSession as VerticalCacheAggregatorSession;

            XAssert.IsNotNull(vertSession);

            CallbackCacheSessionWrapper wrappedSession = vertSession.RemoteSession as CallbackCacheSessionWrapper;

            XAssert.IsNotNull(wrappedSession);
            PoisonSession(wrappedSession);

            CacheDeterminism determinismSource = CacheDeterminism.None;

            const string PipName = "TestPip";

            // Populate the remote cache with one set of outputs.
            FullCacheRecord remoteCacheRecord = await FakeBuild.DoNonDeterministicPipAsync(remoteSession, PipName);

            // And the local cache with a set forced to be unique.
            FullCacheRecord localCacheRecord = await FakeBuild.DoNonDeterministicPipAsync(localSession, PipName, generateVerifiablePip: true);

            PoisonAllRemoteSessions(testCache);
            DisconnectRemoteCache(testCache);

            // Now query each cache, and verify only the remote content is in each.
            // Make sure the content is in each cache. (Placing the aggregator cache first will cause backfill of the local cache)
            foreach (var currentCache in new Tuple <ICache, CacheDeterminism, string, int>[]
            {
                new Tuple <ICache, CacheDeterminism, string, int>(testCache, CacheDeterminism.None, vertCache.LocalCache.CacheId, 1),
                new Tuple <ICache, CacheDeterminism, string, int>(vertCache.LocalCache, CacheDeterminism.None, vertCache.LocalCache.CacheId, 1)
            })
            {
                await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync(
                    currentCache.Item1,
                    localCacheRecord.StrongFingerprint.WeakFingerprint,
                    new List <CasHash>(localCacheRecord.CasEntries),
                    currentCache.Item2,
                    localCacheRecord.StrongFingerprint.CasElement,
                    currentCache.Item3,
                    currentCache.Item4);
            }

            XAssert.IsTrue((await testCache.ShutdownAsync()).Succeeded);
        }
        /// <inheritdoc />
        public async Task <Possible <CacheEntryPublishResult, Failure> > TryPublishCacheEntryAsync(
            WeakContentFingerprint weakFingerprint,
            ContentHash pathSetHash,
            StrongContentFingerprint strongFingerprint,
            CacheEntry entry,
            CacheEntryPublishMode publishMode = CacheEntryPublishMode.CreateNew,
            PublishCacheEntryOptions options  = default)
        {
            // We can request semantics appropriate for CreateNewOrReplaceExisting via CacheDeterminism.SinglePhaseNonDeterministic
            // Note that conflict-rejections / failures may still occur.
            CacheDeterminism determinism = publishMode == CacheEntryPublishMode.CreateNewOrReplaceExisting
                ? CacheDeterminism.SinglePhaseNonDeterministic
                : default(CacheDeterminism);

            // N.B. this includes the metadata hash.
            CasEntries adaptedHashes = new CasEntries(
                entry.ToArray(h => new CasHash(new global::BuildXL.Cache.Interfaces.Hash(h))),
                determinism);

            Possible <FullCacheRecordWithDeterminism, Failure> maybePublished = await PerformFingerprintCacheOperationAsync(
                () => m_cache.AddOrGetAsync(
                    weak: new WeakFingerprintHash(new Hash(weakFingerprint.Hash)),
                    casElement: new CasHash(new Hash(pathSetHash)),
                    hashElement: new Hash(strongFingerprint.Hash),
                    hashes: adaptedHashes,
                    urgencyHint: options.ShouldPublishAssociatedContent ? UrgencyHint.RegisterAssociatedContent : UrgencyHint.SkipRegisterContent),
                nameof(TryPublishCacheEntryAsync));

            if (maybePublished.Succeeded)
            {
                if (maybePublished.Result.Record == null)
                {
                    // Happy path: Entry accepted without an alternative.
                    return(CacheEntryPublishResult.CreatePublishedResult());
                }
                else
                {
                    // Less happy path: The underlying store has an alternative entry that we need to use instead.
                    Possible <CacheEntry, Failure> maybeConvertedConflictingEntry = TryConvertCasEntriesToCacheEntry(maybePublished.Result.Record.CasEntries, maybePublished.Result.Record.CacheId);
                    if (maybeConvertedConflictingEntry.Succeeded)
                    {
                        return(CacheEntryPublishResult.CreateConflictResult(maybeConvertedConflictingEntry.Result));
                    }
                    else
                    {
                        return(maybeConvertedConflictingEntry.Failure.Annotate(
                                   "The cache returned a conflicting entry (rejecting the proposed entry), but the conflicting entry is invalid."));
                    }
                }
            }
            else
            {
                return(maybePublished.Failure);
            }
        }
Beispiel #16
0
        protected override ICache CreateCache(DisposableDirectory testDirectory)
        {
            var rootPath           = testDirectory.Path;
            var configuration      = ContentStoreConfiguration.CreateWithMaxSizeQuotaMB(1);
            var configurationModel = new ConfigurationModel(configuration);

            return(new OneLevelCache(
                       () => new FileSystemContentStore(FileSystem, SystemClock.Instance, rootPath, configurationModel),
                       () => new MemoryMemoizationStore(Logger),
                       CacheDeterminism.NewCacheGuid()));
        }
Beispiel #17
0
        public void EqualsTrueNotReferenceEqualContentHashList()
        {
            var contentHashList = ContentHashList.Random();
            var determinism     = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires);
            var contentHashListWithDeterminism1 = new ContentHashListWithDeterminism(contentHashList, determinism);
            var contentHashListWithDeterminism2 = new ContentHashListWithDeterminism(contentHashList, determinism);
            var v1 = new GetContentHashListResult(contentHashListWithDeterminism1);
            var v2 = new GetContentHashListResult(contentHashListWithDeterminism2);

            Assert.True(v1.Equals(v2));
        }
        private ICache CreateBlockingPublishingCache(AbsolutePath path)
        {
            var configuration      = ContentStoreConfiguration.CreateWithMaxSizeQuotaMB(1);
            var configurationModel = new ConfigurationModel(configuration);
            var contentStore       = new FileSystemContentStore(FileSystem, SystemClock.Instance, path, configurationModel);
            var localCache         = new OneLevelCache(
                () => contentStore,
                () => new MemoryMemoizationStore(Logger),
                CacheDeterminism.NewCacheGuid());

            return(new PublishingCacheToContentStore(new PublishingCache <OneLevelCache>(localCache, new BlockingPublishingStore(), Guid.NewGuid())));
        }
Beispiel #19
0
        private async Task AddToEmptyCacheAsync(bool contentIsDeterministic)
        {
            string testCacheId = "Disconnected";
            ICache testCache   = await InitializeCacheAsync(NewCache(testCacheId, false)).SuccessAsync();

            VerticalCacheAggregator vertCache = testCache as VerticalCacheAggregator;

            XAssert.IsNotNull(vertCache);

            CacheDeterminism localDeterminism = CacheDeterminism.None;

            if (contentIsDeterministic)
            {
                localDeterminism = CacheDeterminism.Tool;
            }

            CacheDeterminism initialDeterminism = contentIsDeterministic ? CacheDeterminism.Tool : CacheDeterminism.None;

            ICacheSession session = (await testCache.CreateSessionAsync()).Success();

            VerticalCacheAggregatorSession vertSession = session as VerticalCacheAggregatorSession;

            XAssert.IsNotNull(vertSession);

            CallbackCacheSessionWrapper wrappedSession = vertSession.RemoteSession as CallbackCacheSessionWrapper;

            XAssert.IsNotNull(wrappedSession);
            PoisonSession(wrappedSession);
            DisconnectRemoteCache(testCache);

            FullCacheRecord cacheRecord = await FakeBuild.DoPipAsync(session, "TestPip", determinism: initialDeterminism);

            await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync(
                vertCache.LocalCache,
                cacheRecord.StrongFingerprint.WeakFingerprint,
                new List <CasHash>(cacheRecord.CasEntries),
                localDeterminism,
                cacheRecord.StrongFingerprint.CasElement,
                vertCache.LocalCache.CacheId,
                1);

            await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync(
                vertCache.RemoteCache,
                cacheRecord.StrongFingerprint.WeakFingerprint,
                new List <CasHash>(cacheRecord.CasEntries),
                localDeterminism,
                cacheRecord.StrongFingerprint.CasElement,
                vertCache.RemoteCache.CacheId,
                0);

            XAssert.IsTrue((await testCache.ShutdownAsync()).Succeeded);
        }
Beispiel #20
0
        protected static IEnumerable <object[]> BuildDeterminismMatrix()
        {
            for (int i = -1; i < determinisms.Length; i++)
            {
                int localIndex = Math.Max(0, i);
                CacheDeterminism startDeterminismLocal  = determinisms[localIndex];
                CacheDeterminism startDeterminismRemote = determinisms[Math.Max(localIndex, 1)];
                CacheDeterminism endDetermismLocal      = startDeterminismLocal.IsDeterministicTool || startDeterminismRemote.IsDeterministicTool ? CacheDeterminism.Tool : CacheDeterminism.ViaCache(RemoteReferenceGuild, CacheDeterminism.NeverExpires);
                CacheDeterminism endDeterminismRemote   = startDeterminismRemote;

                yield return(new object[] { BackingStoreTestClass.Self, BackingStoreTestClass.Self, startDeterminismLocal, startDeterminismRemote, endDetermismLocal, endDeterminismRemote });
            }
        }
Beispiel #21
0
        /// <inheritdoc />
        public ContentHashListWithDeterminism AsContentHashList(RedisValue value)
        {
            const int partCount = 5;
            var       parts     = value.ToString().Split(new[] { RedisValueSeparator }, partCount, StringSplitOptions.None);

            Contract.Assert(parts.Length == partCount);
            var determinism = CacheDeterminism.Deserialize(HexUtilities.HexToBytes(parts[0]));
            var payload     = parts[3] == RedisValueExistsSemaphore?HexUtilities.HexToBytes(parts[4]) : null;

            var hashList = parts[1] == RedisValueExistsSemaphore?ContentHashList.Deserialize(parts[2], payload) : null;

            return(new ContentHashListWithDeterminism(hashList, determinism));
        }
Beispiel #22
0
        /// <summary>
        /// Simple constructor of a fake pip definition.
        /// </summary>
        /// <param name="pipName">Require pip name (used as data too)</param>
        /// <param name="pipSize">Number of outputs</param>
        /// <param name="weakIndex">Output index used to produce the weak fingerprint</param>
        /// <param name="hashIndex">Output index used to produce the hash</param>
        /// <param name="determinism">The determinism to claim for new records</param>
        public PipDefinition(string pipName, int pipSize = 3, int weakIndex = 1, int hashIndex = 0, CacheDeterminism determinism = default(CacheDeterminism))
        {
            Contract.Requires(pipName != null);
            Contract.Requires(pipSize > 0);
            Contract.Requires(weakIndex >= 0 && weakIndex < pipSize);
            Contract.Requires(hashIndex >= 0 && hashIndex < pipSize);

            PipName     = pipName;
            PipSize     = pipSize;
            WeakIndex   = weakIndex;
            HashIndex   = hashIndex;
            Determinism = determinism;
        }
Beispiel #23
0
        public async Task DisconnectMostRemoteCacheAddNewReconnect()
        {
            string cacheId   = "MutlipleCacheRemote";
            ICache testCache = await InitializeCacheAsync(NewCache(cacheId, true, false, true)).SuccessAsync();

            VerticalCacheAggregator lowerVert = testCache as VerticalCacheAggregator;

            XAssert.IsNotNull(lowerVert);

            CallbackCacheWrapper callbackCache = lowerVert.RemoteCache as CallbackCacheWrapper;

            XAssert.IsNotNull(callbackCache);

            VerticalCacheAggregator upperVert = callbackCache.WrappedCache as VerticalCacheAggregator;

            XAssert.IsNotNull(upperVert);

            ICacheSession session = await testCache.CreateSessionAsync().SuccessAsync();

            VerticalAggregatorDisconnectTests.DisconnectCache(upperVert.RemoteCache);

            FullCacheRecord cacheRecord = await FakeBuild.DoPipAsync(session, "Test Pip");

            VerticalAggregatorDisconnectTests.ConnectCache(upperVert.RemoteCache);

            // Now query each cache, and verify only the remote content is in each.
            var aggregatorStats   = new Dictionary <string, double>();
            var remoteDeterminism = CacheDeterminism.ViaCache(upperVert.RemoteCache.CacheGuid, CacheDeterminism.NeverExpires);

            foreach (var currentCache in new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >[]
            {
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(testCache, remoteDeterminism, lowerVert.LocalCache.CacheId, 3, aggregatorStats),
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(lowerVert.LocalCache, remoteDeterminism, lowerVert.LocalCache.CacheId, 1, null),
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(upperVert.LocalCache, remoteDeterminism, upperVert.LocalCache.CacheId, 1, null),
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(upperVert.RemoteCache, remoteDeterminism, upperVert.RemoteCache.CacheId, 1, null)
            })
            {
                await ValidateItemsInCacheAsync(
                    currentCache.Item1,
                    cacheRecord.StrongFingerprint.WeakFingerprint,
                    new List <CasHash>(cacheRecord.CasEntries),
                    currentCache.Item2,
                    cacheRecord.StrongFingerprint.CasElement,
                    currentCache.Item3,
                    currentCache.Item4);
            }

            await testCache.ShutdownAsync().SuccessAsync();
        }
Beispiel #24
0
        public Task AddOrGetContentHashListPassThrough()
        {
            var context           = new Context(Logger);
            var strongFingerprint = StrongFingerprint.Random();
            var contentHashListWithDeterminism = new ContentHashListWithDeterminism(
                ContentHashList.Random(),
                CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires));

            return(RunMockSessionTestAsync(context, session =>
            {
                session.AddOrGetContentHashListAsync(context, strongFingerprint, contentHashListWithDeterminism, Token, NonDefaultUrgencyHint).ConfigureAwait(false).GetAwaiter().GetResult().ShouldBeSuccess();
                Assert.True(_mockMemoizationSession.AddOrGetContentHashListAsyncParams.Contains(new Tuple <StrongFingerprint, ContentHashListWithDeterminism>(strongFingerprint, contentHashListWithDeterminism)));
                return Task.FromResult(0);
            }));
        }
        /// <inheritdoc />
        protected async Task <AddOrGetContentHashListResult> AddOrGetContentHashListAsync(
            Context context,
            StrongFingerprint strongFingerprint,
            ContentHashListWithDeterminism contentHashListWithDeterminism,
            ContentAvailabilityGuarantee guarantee)
        {
            try
            {
                DateTime expirationUtc = FingerprintTracker.GenerateNewExpiration();
                var      valueToAdd    = new ContentHashListWithCacheMetadata(
                    contentHashListWithDeterminism, expirationUtc, guarantee);

                Tracer.Debug(
                    context,
                    $"Adding contentHashList=[{valueToAdd.ContentHashListWithDeterminism.ContentHashList}] determinism=[{valueToAdd.ContentHashListWithDeterminism.Determinism}] to VSTS with contentAvailabilityGuarantee=[{valueToAdd.ContentGuarantee}] and expirationUtc=[{expirationUtc}]");

                var contentHashListResponseObject = await ContentHashListAdapter.AddContentHashListAsync(context, CacheNamespace, strongFingerprint, valueToAdd).ConfigureAwait(false);

                if (!contentHashListResponseObject.Succeeded)
                {
                    return(new AddOrGetContentHashListResult(contentHashListResponseObject));
                }

                var contentHashListResponse   = contentHashListResponseObject.Data;
                var inconsistencyErrorMessage = CheckForResponseInconsistency(contentHashListResponse);
                if (inconsistencyErrorMessage != null)
                {
                    return(new AddOrGetContentHashListResult(inconsistencyErrorMessage));
                }

                ContentHashList contentHashListToReturn = UnpackContentHashListAfterAdd(
                    contentHashListWithDeterminism.ContentHashList, contentHashListResponse);

                CacheDeterminism determinismToReturn = UnpackDeterminism(contentHashListResponse, CacheId);
                if (guarantee == ContentAvailabilityGuarantee.AllContentBackedByCache && !determinismToReturn.IsDeterministic)
                {
                    return(new AddOrGetContentHashListResult(
                               "Inconsistent BuildCache service response. Unbacked values should never override backed values."));
                }

                FingerprintTracker.Track(strongFingerprint, contentHashListResponse.GetRawExpirationTimeUtc());
                return(new AddOrGetContentHashListResult(new ContentHashListWithDeterminism(contentHashListToReturn, determinismToReturn)));
            }
            catch (Exception e)
            {
                return(new AddOrGetContentHashListResult(e));
            }
        }
Beispiel #26
0
 public override Task FetchingContentFromLocalCacheUpdatesLocalCacheForDeterministicContentPopulatedRemote(
     BackingStoreTestClass localTestClass,
     BackingStoreTestClass remoteTestClass,
     CacheDeterminism initialDeterminismLocal,
     CacheDeterminism initialDeterminismRemote,
     CacheDeterminism finalDeterminismLocal,
     CacheDeterminism finalDeterminismRemote)
 {
     return(base.FetchingContentFromLocalCacheUpdatesLocalCacheForDeterministicContentPopulatedRemote(
                localTestClass,
                remoteTestClass,
                initialDeterminismLocal,
                initialDeterminismRemote,
                finalDeterminismLocal,
                finalDeterminismRemote));
 }
Beispiel #27
0
        public Task AddExpiredDeterminism()
        {
            var strongFingerprint = StrongFingerprint.Random();
            var expirationUtc     = DateTime.UtcNow - TimeSpan.FromDays(7);
            var guid        = CacheDeterminism.NewCacheGuid();
            var determinism = CacheDeterminism.ViaCache(guid, expirationUtc);
            var contentHashListWithDeterminism = new ContentHashListWithDeterminism(ContentHashList.Random(), determinism);

            return(RunTest((context, contentLocationDatabase) =>
            {
                contentLocationDatabase.AddOrGetContentHashList(
                    context, strongFingerprint, contentHashListWithDeterminism).ShouldBeSuccess();
                var result = contentLocationDatabase.GetContentHashList(context, strongFingerprint);
                Assert.Equal(CacheDeterminism.None.EffectiveGuid, result.ContentHashListWithDeterminism.Determinism.EffectiveGuid);
            }));
        }
Beispiel #28
0
        /// <summary>
        /// This will do a build into the session with a given name
        /// and output count.
        /// </summary>
        /// <param name="session">The cache session to work with</param>
        /// <param name="pipName">Some text that acts as a base element in the output</param>
        /// <param name="pipSize">Number of elements in the output.  Must be enough to cover the variants</param>
        /// <param name="accessMethod">Method (File or stream) for how files are materialized from the cache</param>
        /// <param name="determinism">Determinism to provide for new build records</param>
        /// <param name="generateVerifiablePip">Indicates that the pip generated should be verfiiable by CheckContentAsync</param>
        /// <returns>The FullCacheRecord of the build</returns>
        /// <remarks>
        /// This will do a "fake build" including a cache lookup via weak fingerprints
        /// and then return either the existing FullCacheRecord or add the build as a new
        /// one.  A new FullCacheRecord will have the StrongFingerprint.CacheId set to NewRecordCacheId.
        ///
        /// The outputs of this pip will be unique for each call, but have the same strong fingerprint.
        ///
        /// The WeakFingerprint and input hash element are derived from the pipName.
        /// </remarks>
        public static Task <FullCacheRecord> DoNonDeterministicPipAsync(
            ICacheSession session,
            string pipName,
            bool generateVerifiablePip = false,
            int pipSize = DefaultFakeBuildSize,
            CacheDeterminism determinism = default(CacheDeterminism),
            CasAccessMethod accessMethod = CasAccessMethod.Stream)
        {
            Contract.Requires(session != null);
            Contract.Requires(pipName != null);
            Contract.Requires(pipSize > 0);

            FakeStrongFingerprint fakePrint = FakeStrongFingerprint.Create(pipName, generateVerifiablePip, pipSize);

            return(DoPipAsyncImpl(session, fakePrint.WeakFingerprint, fakePrint.HashElement, fakePrint.FakeBuild, determinism, accessMethod));
        }
        /// <summary>
        ///     Determine the Determinism to return.
        /// </summary>
        protected static CacheDeterminism UnpackDeterminism(ContentHashListWithCacheMetadata cacheMetadata, Guid cacheId)
        {
            Contract.Assert(cacheMetadata != null);

            if (cacheMetadata.ContentHashListWithDeterminism.Determinism.Guid == CacheDeterminism.Tool.Guid)
            {
                // Value is Tool-deterministic
                return(CacheDeterminism.Tool);
            }

            var expirationUtc = cacheMetadata.GetEffectiveExpirationTimeUtc();

            return(expirationUtc == null
                ? CacheDeterminism.None                                     // Value is unbacked in VSTS
                : CacheDeterminism.ViaCache(cacheId, expirationUtc.Value)); // Value is backed in VSTS
        }
Beispiel #30
0
 public override Task AddingFpReplacedWithExistingRORemote(
     BackingStoreTestClass localTestClass,
     BackingStoreTestClass remoteTestClass,
     CacheDeterminism initialDeterminismLocal,
     CacheDeterminism initialDeterminsimRemote,
     CacheDeterminism finalDeterminismLocal,
     CacheDeterminism finalDeterminismRemote)
 {
     return(base.AddingFpReplacedWithExistingRORemote(
                localTestClass,
                remoteTestClass,
                initialDeterminismLocal,
                initialDeterminsimRemote,
                finalDeterminismLocal,
                finalDeterminismRemote));
 }