/// <summary> /// Check that the fake build contents are available and correct /// </summary> /// <param name="cache">The cache to read from (uses a read-only session)</param> /// <param name="record">The full cache record that is to be used to check the cache</param> /// <returns>Success if all worked</returns> /// <remarks> /// This is tied to the FakeBuild where the set of results is /// made as the index file which we use in the strong fingerprint /// and basically describes the set of entries that should be in the CasEntries /// </remarks> public static Task CheckContentsAsync(ICache cache, FullCacheRecord record) { Contract.Requires(cache != null); Contract.Requires(record != null); return(CheckContentsAsync(cache, record.StrongFingerprint.CasElement, record.CasEntries)); }
private async Task ValidateSessionAsync(HashSet <FullCacheRecord> expectedRecords, ICache cache, string sessionId, FakeBuild.CasAccessMethod accessMethod) { if (!ImplementsTrackedSessions || DummySessionName != null) { return; } ICacheReadOnlySession readOnlySession = (await cache.CreateReadOnlySessionAsync()).Success(); // Check that the content is fine HashSet <FullCacheRecord> foundRecords = new HashSet <FullCacheRecord>(); foreach (var strongFingerprintTask in cache.EnumerateSessionStrongFingerprints(DummySessionName ?? sessionId).Success().OutOfOrderTasks()) { StrongFingerprint strongFingerprint = await strongFingerprintTask; CasEntries casEntries = (await readOnlySession.GetCacheEntryAsync(strongFingerprint)).Success(); FullCacheRecord record = new FullCacheRecord(strongFingerprint, casEntries); XAssert.IsTrue(expectedRecords.Contains(record), "Found record that was not expected!"); foundRecords.Add(record); } (await readOnlySession.CloseAsync()).Success(); await FakeBuild.CheckContentsAsync(cache, foundRecords, accessMethod); XAssert.AreEqual(expectedRecords.Count, foundRecords.Count); }
// Add a record to the session if we are recording a session private void AddSessionRecord(FullCacheRecord record) { if (SessionEntries != null) { SessionEntries.TryAdd(record.StrongFingerprint, 1); } }
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); }
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); }
public async Task NoItemFingerprint() { const string TestName = nameof(NoItemFingerprint); string testCacheId = MakeCacheId(TestName); ICache cache = await CreateCacheAsync(testCacheId); // Now for the session (which we base on the cache ID) string testSessionId = "Session1-" + testCacheId; ICacheSession session = await CreateSessionAsync(cache, testSessionId); // Note that we will be making a new fingerprint with a CasHash of NoItem // without pre-sending it as NoItem is a special case - it is nothing FullCacheRecord record = await FakeBuild.DoPipAsync(session, TestName); // We place this in and did not pin the NoItem yet or even send it around // Note that this also is doing a zero-length CasEntries var strong = new StrongFingerprint(record.StrongFingerprint.WeakFingerprint, CasHash.NoItem, new Hash(FingerprintUtilities.ZeroFingerprint), TestName); FullCacheRecordWithDeterminism oldRecord = (await session.AddOrGetAsync( strong.WeakFingerprint, strong.CasElement, strong.HashElement, CasEntries.FromCasHashes())).Success("Should work even though I did not pin CasHash.NoItem, instead it failed with {0}"); XAssert.IsNull(oldRecord.Record, "Should have been the first one like this"); var result = await session.GetCacheEntryAsync(strong).SuccessAsync(); XAssert.AreEqual(0, result.Count, "We should have gotten a zero-length CasEntries"); // We place this in and did not pin the NoItem yet or even send it around // Note that this does an array of NoItem CasEntries and use the // record.CasElement as the weak fingerprint CasHash[] empties = { CasHash.NoItem, CasHash.NoItem, CasHash.NoItem }; strong = new StrongFingerprint(new WeakFingerprintHash(strong.CasElement.ToFingerprint()), CasHash.NoItem, new Hash(FingerprintUtilities.ZeroFingerprint), TestName); oldRecord = (await session.AddOrGetAsync( strong.WeakFingerprint, CasHash.NoItem, new Hash(FingerprintUtilities.ZeroFingerprint), empties)).Success("Should work even though I did not pin CasHash.NoItem, instead it failed with {0}"); XAssert.IsNull(oldRecord.Record, "Should have been the first one like this"); result = await session.GetCacheEntryAsync(strong).SuccessAsync(); XAssert.AreEqual(empties, result, "We should have gotten the set of empties"); await CloseSessionAsync(session, testSessionId); await ShutdownCacheAsync(cache, testCacheId); }
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(); }
/// <summary> /// Execute a fake build based on this pip definition into the given cache session /// </summary> /// <param name="session">The cache session to use</param> /// <returns>The FullCacheRecord of the build operation</returns> public async Task <FullCacheRecord> BuildAsync(ICacheSession session) { Contract.Requires(session != null); FullCacheRecord record = await FakeBuild.DoPipAsync( session, pipName : PipName, pipSize : PipSize, weakIndex : WeakIndex, hashIndex : HashIndex, determinism : Determinism); if (Determinism.IsDeterministicTool) { XAssert.IsTrue(record.CasEntries.Determinism.IsDeterministicTool, "Tool was supposed to be deterministic"); } return(record); }
public async Task CacheDataPersistedReadOnlyCache() { string testName = "CacheDataPersistedReadOnly"; ICache firstInvocation = await CreateCacheAsync(testName, true); Guid originalGuid = firstInvocation.CacheGuid; ICacheSession session = (await firstInvocation.CreateSessionAsync("sessionName")).Success(); FullCacheRecord cacheRecord = await FakeBuild.DoPipAsync(session, "PipA"); (await session.CloseAsync()).Success(); await ShutdownCacheAsync(firstInvocation, testName); ICache secondInvocation = await GetExistingCacheAsync(testName, true, true); XAssert.AreEqual(originalGuid, secondInvocation.CacheGuid, "Persistent caches: GUID should not change"); XAssert.IsTrue(secondInvocation.IsReadOnly, "This should have been a read-only cache"); ICacheReadOnlySession newSession = (await secondInvocation.CreateReadOnlySessionAsync()).Success(); int fingerprintsFound = 0; foreach (var singleFingerprint in newSession.EnumerateStrongFingerprints(cacheRecord.StrongFingerprint.WeakFingerprint)) { var sfp = (await singleFingerprint).Success(); XAssert.AreEqual(cacheRecord.StrongFingerprint, sfp, "Fingerprints must match"); fingerprintsFound++; } XAssert.AreEqual(1, fingerprintsFound, "A single instance of the fingerprint should have been found after restarting the cache."); (await newSession.CloseAsync()).Success(); await ShutdownCacheAsync(secondInvocation, testName); }
public virtual async Task ReadOnlyRemoteIsNotUpdatedWhenDisconnected() { string testCacheId = "Disconnected"; ICache testCache = await InitializeCacheAsync(NewCache(testCacheId, false)).SuccessAsync(); VerticalCacheAggregator vertCache = testCache as VerticalCacheAggregator; XAssert.IsNotNull(vertCache); PoisonAllRemoteSessions(testCache); DisconnectRemoteCache(testCache); ICacheSession session = (await testCache.CreateSessionAsync()).Success(); FullCacheRecord cacheRecord = await FakeBuild.DoPipAsync(session, "TestPip"); await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync( vertCache.LocalCache, cacheRecord.StrongFingerprint.WeakFingerprint, new List <CasHash>(cacheRecord.CasEntries), CacheDeterminism.None, cacheRecord.StrongFingerprint.CasElement, vertCache.LocalCache.CacheId, 1); var remoteSession = await vertCache.RemoteCache.CreateReadOnlySessionAsync().SuccessAsync(); int fingerprintsReturned = 0; foreach (var fingerprint in remoteSession.EnumerateStrongFingerprints(cacheRecord.StrongFingerprint.WeakFingerprint)) { fingerprintsReturned++; } XAssert.AreEqual(0, fingerprintsReturned, "No fingerprints should have been found in the remote cache."); AssertSuccess(await testCache.ShutdownAsync()); }
public async Task SimpleDummySession() { const string TestName = "SimpleSession"; string testCacheId = MakeCacheId(TestName); ICache cache = await CreateCacheAsync(testCacheId); // Now for the session (which we base on the cache ID) string testSessionId = "Session1-" + testCacheId; ICacheSession session = await CreateSessionAsync(cache, testSessionId); // Do the default fake build for this test (first time, no cache hit) FullCacheRecord built = await FakeBuild.DoPipAsync(session, TestName); XAssert.AreEqual(FakeBuild.NewRecordCacheId, built.CacheId, "Should have been a new cache entry!"); // Now we see if we can get back the items we think we should await CloseSessionAsync(session, testSessionId); // We need a read only session to get the CasEntries ICacheReadOnlySession readOnlySession = (await cache.CreateReadOnlySessionAsync()).Success(); // Validate that the cache contains a dummy session and it has the one cache record it needs. HashSet <FullCacheRecord> found = new HashSet <FullCacheRecord>(); foreach (var strongFingerprintTask in cache.EnumerateSessionStrongFingerprints(MemoizationStoreAdapterCache.DummySessionName).Success().OutOfOrderTasks()) { StrongFingerprint strongFingerprint = await strongFingerprintTask; CasEntries casEntries = (await readOnlySession.GetCacheEntryAsync(strongFingerprint)).Success(); FullCacheRecord record = new FullCacheRecord(strongFingerprint, casEntries); // If it is not the record we already found... if (!found.Contains(record)) { found.Add(record); } XAssert.AreEqual(1, found.Count, "There should be only 1 unique record in the session"); XAssert.AreEqual(built.StrongFingerprint.WeakFingerprint, record.StrongFingerprint.WeakFingerprint); XAssert.AreEqual(built.StrongFingerprint.CasElement, record.StrongFingerprint.CasElement); XAssert.AreEqual(built.StrongFingerprint.HashElement, record.StrongFingerprint.HashElement); XAssert.AreEqual(built.CasEntries.Count, record.CasEntries.Count, "Did not return the same number of items"); XAssert.IsTrue(record.CasEntries.Equals(built.CasEntries), "Items returned are not the same hash and/or order order"); XAssert.AreEqual(built, record); // We can not check record.CasEntries.IsDeterministic // as the cache may have determined that they are deterministic // via cache determinism recovery. } XAssert.AreEqual(1, found.Count, "There should be 1 and only 1 record in the session!"); await readOnlySession.CloseAsync().SuccessAsync(); // Check that the cache has the items in it await FakeBuild.CheckContentsAsync(cache, built); // Now redo the "build" with a cache hit testSessionId = "Session2-" + testCacheId; session = await CreateSessionAsync(cache, testSessionId); FullCacheRecord rebuilt = await FakeBuild.DoPipAsync(session, TestName); XAssert.AreEqual(built, rebuilt, "Should have been the same build!"); // We make sure we did get it from a cache rather than a manual rebuild. XAssert.AreNotEqual(built.CacheId, rebuilt.CacheId, "Should not be the same cache ID"); await CloseSessionAsync(session, testSessionId); readOnlySession = await cache.CreateReadOnlySessionAsync().SuccessAsync(); // Now that we have done the second build via a cache hit, it should produce the // same cache record as before foreach (var strongFingerprintTask in cache.EnumerateSessionStrongFingerprints(MemoizationStoreAdapterCache.DummySessionName).Success().OutOfOrderTasks()) { StrongFingerprint strongFingerprint = await strongFingerprintTask; CasEntries casEntries = (await readOnlySession.GetCacheEntryAsync(strongFingerprint)).Success(); FullCacheRecord record = new FullCacheRecord(strongFingerprint, casEntries); XAssert.IsTrue(found.Contains(record), "Second session should produce the same cache record but did not!"); } (await readOnlySession.CloseAsync()).Success(); await ShutdownCacheAsync(cache, testCacheId); }
private Possible <FullCacheRecordWithDeterminism, Failure> AddOrGet(WeakFingerprintHash weak, CasHash casElement, BuildXL.Cache.Interfaces.Hash hashElement, CasEntries hashes) { Contract.Requires(!IsClosed); Contract.Requires(hashes.IsValid); Contract.Assert(!m_readOnly); // We check the Cas entries if we are strict if (StrictMetadataCasCoupling) { // Check that the content is valid. if (!m_pinnedToCas.ContainsKey(casElement)) { return(new UnpinnedCasEntryFailure(CacheId, casElement)); } foreach (CasHash hash in hashes) { if (!m_pinnedToCas.ContainsKey(hash)) { return(new UnpinnedCasEntryFailure(CacheId, hash)); } } } var strongFingerprints = Cache.Fingerprints.GetOrAdd(weak, (key) => new ConcurrentDictionary <StrongFingerprint, FullCacheRecord>()); var record = strongFingerprints.AddOrUpdate( new StrongFingerprint(weak, casElement, hashElement, Cache.CacheId), (strong) => new FullCacheRecord(strong, hashes), (strong, oldRecord) => { // Do no harm here - we will recheck this outside to produce the error that it was a bad attempt if (oldRecord.CasEntries.Determinism.IsSinglePhaseNonDeterministic != hashes.Determinism.IsSinglePhaseNonDeterministic) { return(oldRecord); } // We replace if we are SinglePhaseNonDeterministic *or* // if we are upgrading the determinism. if (hashes.Determinism.IsSinglePhaseNonDeterministic || (!oldRecord.CasEntries.Determinism.IsDeterministicTool && (hashes.Determinism.IsDeterministic && !hashes.Determinism.Equals(oldRecord.CasEntries.Determinism))) || HasMissingContent(oldRecord.CasEntries)) { oldRecord = new FullCacheRecord(strong, hashes); } return(oldRecord); }); if (record.CasEntries.Determinism.IsSinglePhaseNonDeterministic != hashes.Determinism.IsSinglePhaseNonDeterministic) { return(new SinglePhaseMixingFailure(CacheId)); } AddSessionRecord(record); if (record.CasEntries.Equals(hashes)) { record = null; } else { // Check if tool determinism did not make it in - that means a very bad thing happened if (hashes.Determinism.IsDeterministicTool) { return(new NotDeterministicFailure(Cache.CacheId, record, new FullCacheRecord(record.StrongFingerprint, hashes))); } } if (record == null) { return(new FullCacheRecordWithDeterminism(hashes.GetFinalDeterminism(Cache.IsAuthoritative, Cache.CacheGuid, CacheDeterminism.NeverExpires))); } else { return(new FullCacheRecordWithDeterminism(new FullCacheRecord(record.StrongFingerprint, record.CasEntries.GetModifiedCasEntriesWithDeterminism(Cache.IsAuthoritative, Cache.CacheGuid, CacheDeterminism.NeverExpires)))); } }
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))))); } } } }