Esempio n. 1
0
        private async Task <CasHash> AddPathSet(ICacheSession session, params string[] thePaths)
        {
            var pathTable = new PathTable();

            ObservedPathEntry[] paths = new ObservedPathEntry[thePaths.Length];
            for (int i = 0; i < thePaths.Length; i++)
            {
                AbsolutePath absPath = AbsolutePath.Create(pathTable, thePaths[i]);
                paths[i] = new ObservedPathEntry(absPath, false, false, false, null, false);
            }

            var emptyObservedAccessFileNames = SortedReadOnlyArray <StringId, CaseInsensitiveStringIdComparer> .FromSortedArrayUnsafe(
                ReadOnlyArray <StringId> .Empty,
                new CaseInsensitiveStringIdComparer(pathTable.StringTable));

            ObservedPathSet pathSet = new ObservedPathSet(
                SortedReadOnlyArray <ObservedPathEntry, ObservedPathEntryExpandedPathComparer> .FromSortedArrayUnsafe(
                    ReadOnlyArray <ObservedPathEntry> .FromWithoutCopy(paths),
                    new ObservedPathEntryExpandedPathComparer(pathTable.ExpandedPathComparer)),
                emptyObservedAccessFileNames,
                null);

            using (var pathSetBuffer = new MemoryStream())
            {
                using (var writer = new BuildXLWriter(stream: pathSetBuffer, debug: false, leaveOpen: true, logStats: false))
                {
                    pathSet.Serialize(pathTable, writer, preserveCasing: false);
                }

                pathSetBuffer.Seek(0, SeekOrigin.Begin);

                // Must await such that the dispose of the MemoryStream is only after the write completes
                return(await session.AddToCasAsync(pathSetBuffer).SuccessAsync());
            }
        }
Esempio n. 2
0
        public ProcessStrongFingerprintComputationData(BinaryLogReader.EventReader reader)
        {
            PathSetHash = reader.ReadContentHash();
            var maybePathSet = ObservedPathSet.TryDeserialize(reader.PathTable, reader, pathReader: r => r.ReadAbsolutePath(), stringReader: r => ((BinaryLogReader.EventReader)r).ReadDynamicStringId());

            Contract.Assert(maybePathSet.Succeeded);
            PathSet = maybePathSet.Result;
            PriorStrongFingerprints = reader.ReadReadOnlyList(r => r.ReadStrongFingerprint());
            Succeeded = reader.ReadBoolean();

            if (Succeeded)
            {
                IsStrongFingerprintHit    = reader.ReadBoolean();
                ObservedInputs            = reader.ReadReadOnlyArray(r => ObservedInput.Deserialize(r));
                ComputedStrongFingerprint = reader.ReadStrongFingerprint();
                IsNewlyPublishedAugmentedWeakFingerprint = reader.ReadBoolean();
                AugmentedWeakFingerprint = reader.ReadNullableStruct(r => r.ReadWeakFingerprint());
            }
            else
            {
                IsStrongFingerprintHit    = false;
                ObservedInputs            = default;
                ComputedStrongFingerprint = default;
                IsNewlyPublishedAugmentedWeakFingerprint = false;
                AugmentedWeakFingerprint = default;
            }
        }
        public static void AssertPathSetContainsDuplicates(ObservedPathSet pathSet)
        {
            bool foundDuplicate = false;

            for (int i = 1; i < pathSet.Paths.Length; i++)
            {
                int cmp = pathSet.Paths.Comparer.Compare(pathSet.Paths[i], pathSet.Paths[i - 1]);
                XAssert.IsTrue(
                    cmp >= 0,
                    "Path set must contain unique items in a sorted order");

                foundDuplicate |= cmp == 0;
            }

            for (int i = 1; i < pathSet.ObservedAccessedFileNames.Length; i++)
            {
                int cmp = pathSet.ObservedAccessedFileNames.Comparer.Compare(pathSet.ObservedAccessedFileNames[i], pathSet.ObservedAccessedFileNames[i - 1]);
                XAssert.IsTrue(
                    cmp >= 0,
                    "Observed accessed file names must contain unique items in a sorted order");

                foundDuplicate |= cmp == 0;
            }

            XAssert.IsTrue(foundDuplicate, "Expected at least one duplicate");
        }
Esempio n. 4
0
 /// <summary>
 /// Stores path set for pip for use during two phase lookup
 /// </summary>
 public virtual Task <Possible <ContentHash> > TryStorePathSetAsync(ObservedPathSet pathSet)
 {
     return(this.TrySerializedAndStorePathSetAsync(pathSet, (pathSetHash, pathSetBuffer) =>
     {
         return TryStorePathSetContentAsync(pathSetHash, pathSetBuffer);
     }));
 }
Esempio n. 5
0
 /// <summary>
 /// Stores path set for pip for use during two phase lookup
 /// </summary>
 public virtual Task <Possible <ContentHash> > TryStorePathSetAsync(ObservedPathSet pathSet, bool preservePathCasing)
 {
     return(TrySerializedAndStorePathSetAsync(pathSet, (pathSetHash, pathSetBuffer) =>
     {
         return TryStorePathSetContentAsync(pathSetHash, pathSetBuffer);
     }, preservePathCasing));
 }
Esempio n. 6
0
 /// <summary>
 /// Serializes a path set.
 /// </summary>
 public async Task <ContentHash> SerializePathSetAsync(ObservedPathSet pathSet, bool preservePathCasing)
 {
     using (var pathSetBuffer = new MemoryStream())
     {
         return(await SerializePathSetAsync(pathSet, pathSetBuffer, preservePathCasing));
     }
 }
Esempio n. 7
0
 /// <summary>
 /// Serializes a path set.
 /// </summary>
 public async Task <ContentHash> SerializePathSet(ObservedPathSet pathSet)
 {
     using (var pathSetBuffer = new MemoryStream())
     {
         return(await SerializePathSet(pathSet, pathSetBuffer));
     }
 }
Esempio n. 8
0
        /// <summary>
        /// Gets the deserialized path set given its content hash
        /// </summary>
        public virtual async Task <Possible <ObservedPathSet> > TryRetrievePathSetAsync(
            OperationContext operationContext,

            // TODO: Do we need this fingerprint given that the path set hash is provided by this interface in the first place
            WeakContentFingerprint weakFingerprint,
            ContentHash pathSetHash)
        {
            using (operationContext.StartOperation(PipExecutorCounter.TryLoadPathSetFromContentCacheDuration))
            {
                Possible <Stream> maybePathSetStream = await TryLoadAndOpenPathSetStreamAsync(pathSetHash);

                if (!maybePathSetStream.Succeeded)
                {
                    return(maybePathSetStream.Failure);
                }

                using (operationContext.StartOperation(PipExecutorCounter.TryLoadPathSetFromContentCacheDeserializeDuration))
                    using (var pathSetReader = new BuildXLReader(debug: false, stream: maybePathSetStream.Result, leaveOpen: false))
                    {
                        var maybeDeserialized = ObservedPathSet.TryDeserialize(PathTable, pathSetReader, m_pathExpander);
                        if (!maybeDeserialized.Succeeded)
                        {
                            return(maybeDeserialized.Failure);
                        }

                        return(maybeDeserialized.Result);
                    }
            }
        }
Esempio n. 9
0
 public static void AssertPathSetDoesNotContainDuplicates(ObservedPathSet pathSet)
 {
     for (int i = 1; i < pathSet.Paths.Length; i++)
     {
         XAssert.IsTrue(
             pathSet.Paths.Comparer.Compare(pathSet.Paths[i], pathSet.Paths[i - 1]) > 0,
             "Path set must contain unique items in a sorted order");
     }
 }
Esempio n. 10
0
 private static void AssertPathSetEquals(PathTable pathTable1, ObservedPathSet pathSet1, PathTable pathTable2, ObservedPathSet pathSet2)
 {
     Assert.Equal(pathSet1.Paths.Length, pathSet2.Paths.Length);
     for (int i = 0; i < pathSet1.Paths.Length; i++)
     {
         Assert.Equal(
             pathSet1.Paths[i].Path.ToString(pathTable1).ToUpperInvariant(),
             pathSet2.Paths[i].Path.ToString(pathTable2).ToUpperInvariant());
     }
 }
Esempio n. 11
0
        public static void AssertPathSetsEquivalent(ObservedPathSet a, ObservedPathSet b)
        {
            List <AbsolutePath> aList = RemoveDuplicates(a);
            List <AbsolutePath> bList = RemoveDuplicates(b);

            XAssert.AreEqual(aList.Count, bList.Count);
            for (int i = 0; i < aList.Count; i++)
            {
                XAssert.AreEqual(aList[i], bList[i]);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Clones the current strong fingerprint computation replacing the path set and observed inputs.
        /// Internal use only for converting data to refer to different graph data structures.
        /// </summary>
        internal ProcessStrongFingerprintComputationData UnsafeOverride(
            ObservedPathSet pathSet,
            ReadOnlyArray <ObservedInput> observedInputs)
        {
            var data = this;

            // a new PathSet might have a hash than is different from the one recorded in PathSetHash
            data.PathSet        = pathSet;
            data.ObservedInputs = observedInputs;
            return(data);
        }
Esempio n. 13
0
        /// <nodoc />
        public static Xldb.ObservedPathSet ToObservedPathSet(this ObservedPathSet pathSet, PathTable pathTable)
        {
            var observedPathSet = new Xldb.ObservedPathSet();

            observedPathSet.Paths.AddRange(pathSet.Paths.Select(pathEntry => pathEntry.ToObservedPathEntry(pathTable)));
            observedPathSet.ObservedAccessedFileNames.AddRange(
                pathSet.ObservedAccessedFileNames.Select(
                    observedAccessedFileName => new Xldb.StringId()
            {
                Value = observedAccessedFileName.Value
            }));
            observedPathSet.UnsafeOptions = pathSet.UnsafeOptions.ToUnsafeOptions();

            return(observedPathSet);
        }
Esempio n. 14
0
        /// <nodoc />
        public ProcessStrongFingerprintComputationData(
            ContentHash pathSetHash,
            List <StrongContentFingerprint> priorStrongFingerprints,
            ObservedPathSet pathSet)
        {
            PathSetHash             = pathSetHash;
            PathSet                 = pathSet;
            PriorStrongFingerprints = priorStrongFingerprints;

            // Initial defaults
            Succeeded = false;
            IsStrongFingerprintHit    = false;
            ObservedInputs            = default(ReadOnlyArray <ObservedInput>);
            ComputedStrongFingerprint = default(StrongContentFingerprint);
        }
Esempio n. 15
0
        public static List <AbsolutePath> RemoveDuplicates(ObservedPathSet pathSet)
        {
            var paths = new List <AbsolutePath>();

            for (int i = 0; i < pathSet.Paths.Length; i++)
            {
                while (i + 1 < pathSet.Paths.Length && pathSet.Paths[i + 1].Path == pathSet.Paths[i].Path)
                {
                    i++;
                }

                paths.Add(pathSet.Paths[i].Path);
            }

            return(paths);
        }
Esempio n. 16
0
        /// <nodoc />
        public ProcessStrongFingerprintComputationData(
            ContentHash pathSetHash,
            List <StrongContentFingerprint> priorStrongFingerprints,
            ObservedPathSet pathSet)
        {
            PathSetHash             = pathSetHash;
            PathSet                 = pathSet;
            PriorStrongFingerprints = priorStrongFingerprints;

            // Initial defaults
            Succeeded = false;
            IsStrongFingerprintHit    = false;
            ObservedInputs            = default;
            ComputedStrongFingerprint = default;
            IsNewlyPublishedAugmentedWeakFingerprint = false;
            AugmentedWeakFingerprint = default;
        }
Esempio n. 17
0
        /// <summary>
        /// Serializes a path set to the given buffer.
        /// </summary>
        protected async Task <ContentHash> SerializePathSet(ObservedPathSet pathSet, MemoryStream pathSetBuffer, ContentHash?pathSetHash = null)
        {
            using (var writer = new BuildXLWriter(stream: pathSetBuffer, debug: false, leaveOpen: true, logStats: false))
            {
                pathSet.Serialize(PathTable, writer, m_pathExpander);

                if (pathSetHash == null)
                {
                    pathSetBuffer.Position = 0;
                    pathSetHash            = await ContentHashingUtilities.HashContentStreamAsync(pathSetBuffer);
                }

                pathSetBuffer.Position = 0;

                return(pathSetHash.Value);
            }
        }
Esempio n. 18
0
        private ProcessStrongFingerprintComputationData Convert(ProcessStrongFingerprintComputationData computation)
        {
            if (AreGraphsSame)
            {
                return(computation);
            }

            var pathSet = new ObservedPathSet(
                SortedReadOnlyArray <ObservedPathEntry, ObservedPathEntryExpandedPathComparer> .FromSortedArrayUnsafe(
                    Convert(computation.PathEntries, this, (i, me) => me.Convert(i)),
                    new ObservedPathEntryExpandedPathComparer(OldModel.PathTable.ExpandedPathComparer)),
                computation.PathSet.ObservedAccessedFileNames,
                computation.PathSet.UnsafeOptions);

            return(computation.UnsafeOverride(
                       pathSet,
                       Convert(computation.ObservedInputs, this, (i, me) => me.Convert(i))));
        }
        public void ProjectPathSet()
        {
            var pathTable = new PathTable();

            AbsolutePath firstPath  = AbsolutePath.Create(pathTable, X("/X/bar"));
            AbsolutePath secondPath = AbsolutePath.Create(pathTable, X("/X/foo"));

            var p = CreateResult(
                pathTable,
                ObservedInput.CreateFileContentRead(firstPath, ContentHashingUtilities.EmptyHash),
                ObservedInput.CreateFileContentRead(secondPath, ContentHashingUtilities.EmptyHash));

            ObservedPathSet projected = p.GetPathSet(unsafeOptions: null);

            ObservedPathSetTestUtilities.AssertPathSetsEquivalent(
                projected,
                ObservedPathSetTestUtilities.CreatePathSet(pathTable, firstPath, secondPath));
        }
Esempio n. 20
0
        public async Task TokenizedPathSet()
        {
            var pathTable = new PathTable();

            var pathExpanderA = new MountPathExpander(pathTable);

            AddMount(pathExpanderA, pathTable, AbsolutePath.Create(pathTable, X("/x/users/AUser")), "UserProfile", isSystem: true);
            AddMount(pathExpanderA, pathTable, AbsolutePath.Create(pathTable, X("/x/windows")), "Windows", isSystem: true);
            AddMount(pathExpanderA, pathTable, AbsolutePath.Create(pathTable, X("/x/test")), "TestRoot", isSystem: false);

            var pathSetA = ObservedPathSetTestUtilities.CreatePathSet(
                pathTable,
                X("/x/abc"),
                X("/x/users/AUser/def"),
                X("/x/windows"),
                X("/x/test/abc"));

            ObservedPathSet roundtripA = SerializeRoundTripAndAssertEquivalent(pathTable, pathSetA);

            XAssert.AreEqual(4, roundtripA.Paths.Length);

            ContentHash pathSetHashA = await pathSetA.ToContentHash(pathTable, pathExpanderA);

            var pathExpanderB = new MountPathExpander(pathTable);

            AddMount(pathExpanderB, pathTable, AbsolutePath.Create(pathTable, X("/y/users/BUser")), "UserProfile", isSystem: true);
            AddMount(pathExpanderB, pathTable, AbsolutePath.Create(pathTable, X("/y/windows")), "Windows", isSystem: true);
            AddMount(pathExpanderB, pathTable, AbsolutePath.Create(pathTable, X("/y/abc/test")), "TestRoot", isSystem: false);

            var pathSetB = ObservedPathSetTestUtilities.CreatePathSet(
                pathTable,
                X("/x/abc"),
                X("/y/users/BUser/def"),
                X("/y/windows"),
                X("/y/abc/test/abc"));

            ObservedPathSet roundtripB = SerializeRoundTripAndAssertEquivalent(pathTable, pathSetB);

            XAssert.AreEqual(4, roundtripB.Paths.Length);

            ContentHash pathSetHashB = await pathSetB.ToContentHash(pathTable, pathExpanderB);

            AssertTrue(pathSetHashA == pathSetHashB);
        }
Esempio n. 21
0
        private static void AssertCompressedSizeExpected(PathTable pathTable, ObservedPathSet pathSet, params string[] uncompressedStrings)
        {
            long compressedSize = GetSizeOfSerializedContent(writer => pathSet.Serialize(pathTable, writer));

            int numberOfUniquePaths = ObservedPathSetTestUtilities.RemoveDuplicates(pathSet).Count;

            // This is correct assuming the following:
            // - Each string can be represented with a one byte length prefix, and a one byte reuse-count.
            // - The number of strings can be represented in one byte.
            // - Each character takes one byte when UTF8 encoded.
            long expectedCompressedSize =
                GetSizeOfSerializedContent(writer => pathSet.UnsafeOptions.Serialize(writer)) +
                1 +                         // The number of observed accesses file names (0)
                1 +                         // String count
                (3 * numberOfUniquePaths) + // Length isSearchPath, isDirectoryPath, and reuse
                uncompressedStrings.Sum(s => s.Length);

            XAssert.AreEqual(expectedCompressedSize, compressedSize, "Wrong size for compressed path-set");
        }
Esempio n. 22
0
        /// <summary>
        /// Stores content for the given path set using the given store function
        /// </summary>
        protected async Task <Possible <ContentHash> > TrySerializedAndStorePathSetAsync(
            ObservedPathSet pathSet,
            Func <ContentHash, MemoryStream, Task <Possible <Unit> > > storeAsync,
            ContentHash?pathSetHash = null)
        {
            using (var pathSetBuffer = new MemoryStream())
            {
                var hash = await SerializePathSet(pathSet, pathSetBuffer, pathSetHash);

                var maybeStored = await storeAsync(hash, pathSetBuffer);

                if (!maybeStored.Succeeded)
                {
                    return(maybeStored.Failure);
                }

                return(hash);
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Creates a strong fingerprint computation for process execution
        /// </summary>
        public static ProcessStrongFingerprintComputationData CreateForExecution(
            ContentHash pathSetHash,
            ObservedPathSet pathSet,
            ReadOnlyArray <ObservedInput> observedInputs,
            StrongContentFingerprint strongFingerprint)
        {
            var data = default(ProcessStrongFingerprintComputationData);

            data.PathSetHash             = pathSetHash;
            data.PathSet                 = pathSet;
            data.PriorStrongFingerprints = CollectionUtilities.EmptyArray <StrongContentFingerprint>();

            // Initial defaults
            data.Succeeded = true;
            data.IsStrongFingerprintHit    = false;
            data.ObservedInputs            = observedInputs;
            data.ComputedStrongFingerprint = strongFingerprint;
            return(data);
        }
        public static void AssertPathSetsEquivalent(ObservedPathSet a, ObservedPathSet b)
        {
            List <AbsolutePath> aPaths = RemoveDuplicates(a.Paths);
            List <AbsolutePath> bPaths = RemoveDuplicates(b.Paths);

            XAssert.AreEqual(aPaths.Count, bPaths.Count);
            for (int i = 0; i < aPaths.Count; i++)
            {
                XAssert.AreEqual(aPaths[i], bPaths[i]);
            }

            List <StringId> aFileNames = RemoveDuplicates(a.ObservedAccessedFileNames);
            List <StringId> bFileNames = RemoveDuplicates(b.ObservedAccessedFileNames);

            XAssert.AreEqual(aFileNames.Count, bFileNames.Count);
            for (int i = 0; i < aFileNames.Count; i++)
            {
                XAssert.IsTrue(a.ObservedAccessedFileNames.Comparer.Compare(aFileNames[i], bFileNames[i]) == 0);
            }
        }
Esempio n. 25
0
        private static ObservedPathSet SerializeRoundTripAndAssertEquivalent(PathTable pathTable, ObservedPathSet original, PathExpander pathExpander = null)
        {
            using (var mem = new MemoryStream())
            {
                using (var writer = new BuildXLWriter(stream: mem, debug: true, leaveOpen: true, logStats: true))
                {
                    original.Serialize(pathTable, writer, pathExpander);
                }

                mem.Position = 0;

                ObservedPathSet roundtrip;
                using (var reader = new BuildXLReader(stream: mem, debug: true, leaveOpen: true))
                {
                    var maybeRoundtrip = ObservedPathSet.TryDeserialize(pathTable, reader, pathExpander);
                    XAssert.IsTrue(maybeRoundtrip.Succeeded, "Failed to deserialize a path set unexpectedly");
                    roundtrip = maybeRoundtrip.Result;
                }

                ObservedPathSetTestUtilities.AssertPathSetsEquivalent(original, roundtrip);
                return(roundtrip);
            }
        }
        /// <summary>
        /// Check the input list against the regex
        /// </summary>
        /// <param name="weak">The weak fingerprint (for logging on failure)</param>
        /// <param name="casElement">The CasElement of the strong fingerprint</param>
        /// <param name="hashElement">The hashElement of the strong fingerprint (for logging on failure)</param>
        /// <param name="urgencyHint">Pass-through</param>
        /// <param name="activityId">Pass-through activityId</param>
        /// <returns>false if the check was not performed, true if the checks were performed, failure if the regex checks failed</returns>
        /// <remarks>
        /// This will attempt to validate the CAS stored input list against the regex rules
        /// </remarks>
        private async Task <Possible <bool, Failure> > CheckInputList(WeakFingerprintHash weak, CasHash casElement, Hash hashElement, UrgencyHint urgencyHint, Guid activityId)
        {
            // If we either have no CasHash item or we have no regex to check, just return false
            // (that we did nothing)
            if (casElement.Equals(CasHash.NoItem) || ((Cache.MustIncludeRegex == null) && (Cache.MustNotIncludeRegex == null)))
            {
                return(false);
            }

            // mustInclude start out false if we need to check for mustInclude
            // Once we get a mustInclude match we no longer need to check.
            // If we have no mustInclude regex, we set it to true such that
            // we don't bother checking it
            bool mustInclude = Cache.MustIncludeRegex == null;

            // This is just to make a faster check for the MustNotinclude
            // case.  If we have the regex then we must check each entry
            // but in many cases we don't have the regex so let this be a quick out.
            bool checkMustNot = Cache.MustNotIncludeRegex != null;

            // Try to get the observed inputs from the CasHash given
            var possibleStream = await GetStreamAsync(casElement, urgencyHint, activityId);

            if (!possibleStream.Succeeded)
            {
                // If we could not get a stream to the CasEntery in the fingerprint.
                return(new InputListFilterFailure(Cache.CacheId, weak, casElement, hashElement, "Failed to get stream of CasElement"));
            }

            // Deserialize the contents of the path set.
            using (possibleStream.Result)
            {
                PathTable     pathTable    = new PathTable();
                BuildXLReader reader       = new BuildXLReader(false, possibleStream.Result, true);
                var           maybePathSet = ObservedPathSet.TryDeserialize(pathTable, reader);
                if (maybePathSet.Succeeded)
                {
                    // Deserialization was successful
                    foreach (ObservedPathEntry entry in maybePathSet.Result.Paths)
                    {
                        string filepath = entry.Path.ToString(pathTable);

                        // Have we seen a must-have entry yet?  If not check if this is one
                        // that way once we found one we want we stop checking this regex
                        if (!mustInclude)
                        {
                            mustInclude = Cache.MustIncludeRegex.IsMatch(filepath);
                        }

                        // Now, if we are looking for a must not include, we just check for that
                        // and if it matches we fail
                        if (checkMustNot)
                        {
                            if (Cache.MustNotIncludeRegex.IsMatch(filepath))
                            {
                                return(new InputListFilterFailure(Cache.CacheId, weak, casElement, hashElement, string.Format(CultureInfo.InvariantCulture, "Failed due to a MustNotInclude file: {0}", filepath)));
                            }
                        }
                    }
                }
                else
                {
                    return(new InputListFilterFailure(Cache.CacheId, weak, casElement, hashElement, "Failed to deserialize observed inputs"));
                }
            }

            if (!mustInclude)
            {
                return(new InputListFilterFailure(Cache.CacheId, weak, casElement, hashElement, "Failed due to not including at least one MustInclude file"));
            }

            return(true);
        }
Esempio n. 27
0
        /// <summary>
        /// Takes a strong fingerprint and returns the deserialized contents of
        /// the input assertion list file that corresponds to it
        /// </summary>
        /// <param name="sfp">The strong fingerprint to get the input assertion
        /// list file contents for</param>
        /// <param name="cacheErrors">Any cache errors that are found will be
        /// added to this collection</param>
        /// <returns>Deserialized contents of the input assertion list file
        /// corresponding to the specified strong fingerprint</returns>
        private async Task <string> GetInputAssertionListFileContentsAsync(StrongFingerprint sfp, ConcurrentDictionary <CacheError, int> cacheErrors)
        {
            // Check for the NoItem
            if (sfp.CasElement.Equals(CasHash.NoItem))
            {
                return(string.Empty);
            }

            // Pin the input assertion list file
            Possible <string, Failure> possibleString = await m_readOnlySession.PinToCasAsync(sfp.CasElement).ConfigureAwait(false);

            if (!possibleString.Succeeded)
            {
                return(string.Empty);
            }

            // Get the stream for the input assertion list file
            Possible <Stream, Failure> possibleStream = await m_readOnlySession.GetStreamAsync(sfp.CasElement).ConfigureAwait(false);

            if (!possibleStream.Succeeded)
            {
                cacheErrors.TryAdd(
                    new CacheError(
                        CacheErrorType.CasHashError,
                        "The input assertion list for SFP " + sfp.ToString() + " was not found in CAS"), 0);
                return(string.Empty);
            }

            // Read the stream contents while hashing
            return(await Task.Run(() =>
            {
                using (var hasher = ContentHashingUtilities.HashInfo.CreateContentHasher())
                {
                    using (var hashingStream = hasher.CreateReadHashingStream(possibleStream.Result))
                    {
                        using (var reader = new BuildXLReader(false, hashingStream, false))
                        {
                            var maybePathSet = ObservedPathSet.TryDeserialize(s_pathTable, reader);

                            // Check if deserialization was successful
                            if (!maybePathSet.Succeeded)
                            {
                                // Deserialization failed
                                cacheErrors.TryAdd(
                                    new CacheError(
                                        CacheErrorType.CasHashError,
                                        "The input assertion list for SFP " + sfp.ToString() + " could not be deserialized"), 0);
                                return string.Empty;
                            }

                            CasHash newCasHash = new CasHash(hashingStream.GetContentHash());

                            // Check if the hashes match
                            if (!sfp.CasElement.Equals(newCasHash))
                            {
                                cacheErrors.TryAdd(
                                    new CacheError(
                                        CacheErrorType.CasHashError,
                                        "The input assertion list for SFP " + sfp.ToString() + " has been altered in the CAS"), 0);
                                return string.Empty;
                            }

                            // Deserialization was successful and file was unaltered
                            StringBuilder fileContents = new StringBuilder();
                            foreach (ObservedPathEntry entry in maybePathSet.Result.Paths)
                            {
                                fileContents.Append(entry.Path.ToString(s_pathTable)).Append(Environment.NewLine);
                            }

                            return fileContents.ToString();
                        }
                    }
                }
            }).ConfigureAwait(false));
        }
        /// <summary>
        /// Deserialize result from reader
        /// </summary>
        public ExecutionResult Deserialize(BuildXLReader reader, uint workerId)
        {
            int minAbsolutePathValue = reader.ReadInt32();

            Contract.Assert(
                minAbsolutePathValue == m_maxSerializableAbsolutePathIndex,
                "When deserializing for distribution, the minimum absolute path value must match the serialized minimum absolute path value");

            var result           = (PipResultStatus)reader.ReadByte();
            var converged        = reader.ReadBoolean();
            var numberOfWarnings = reader.ReadInt32Compact();
            var weakFingerprint  = reader.ReadNullableStruct(r => r.ReadWeakFingerprint());
            ProcessPipExecutionPerformance performanceInformation;

            if (reader.ReadBoolean())
            {
                performanceInformation = ProcessPipExecutionPerformance.Deserialize(reader);

                // TODO: It looks like this is the wrong class for WorkerId, because the serialized object has always WorkerId == 0.
                performanceInformation.WorkerId = workerId;
            }
            else
            {
                performanceInformation = null;
            }

            var outputContent = ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .FromWithoutCopy(ReadOutputContent(reader));

            var directoryOutputs = ReadOnlyArray <(DirectoryArtifact, ReadOnlyArray <FileArtifact>)> .FromWithoutCopy(ReadDirectoryOutputs(reader));

            var mustBeConsideredPerpetuallyDirty       = reader.ReadBoolean();
            var dynamicallyObservedFiles               = reader.ReadReadOnlyArray(ReadAbsolutePath);
            var dynamicallyProbedFiles                 = reader.ReadReadOnlyArray(ReadAbsolutePath);
            var dynamicallyObservedEnumerations        = reader.ReadReadOnlyArray(ReadAbsolutePath);
            var allowedUndeclaredSourceReads           = reader.ReadReadOnlySet(ReadAbsolutePath);
            var absentPathProbesUnderOutputDirectories = reader.ReadReadOnlySet(ReadAbsolutePath);

            ReportedFileAccess[] fileAccessViolationsNotWhitelisted;
            ReportedFileAccess[] whitelistedFileAccessViolations;
            ReportedProcess[]    reportedProcesses;
            ReadReportedProcessesAndFileAccesses(reader, out fileAccessViolationsNotWhitelisted, out whitelistedFileAccessViolations, out reportedProcesses, readPath: m_readPath);

            var twoPhaseCachingInfo = ReadTwoPhaseCachingInfo(reader);
            var cacheDescriptor     = ReadPipCacheDescriptor(reader);

            if (cacheDescriptor != null)
            {
                cacheDescriptor.OutputContentReplicasMiniBloomFilter = reader.ReadUInt32();
            }

            ObservedPathSet?pathSet = null;

            if (reader.ReadBoolean())
            {
                var maybePathSet = ObservedPathSet.TryDeserialize(m_executionContext.PathTable, reader, pathReader: ReadAbsolutePath);
                pathSet = maybePathSet.Succeeded
                    ? (ObservedPathSet?)maybePathSet.Result
                    : null;
            }

            CacheLookupPerfInfo cacheLookupCounters = null;

            if (reader.ReadBoolean())
            {
                cacheLookupCounters = CacheLookupPerfInfo.Deserialize(reader);
            }

            if (!result.IndicatesNoOutput())
            {
                // Successful result needs to be changed to not materialized because
                // the process outputs are not materialized on the local machine.
                result = PipResultStatus.NotMaterialized;
            }

            var pipProperties  = ReadPipProperties(reader);
            var hasUserRetries = reader.ReadBoolean();

            var processExecutionResult = ExecutionResult.CreateSealed(
                result,
                numberOfWarnings,
                outputContent,
                directoryOutputs,
                performanceInformation,
                weakFingerprint,
                fileAccessViolationsNotWhitelisted,
                whitelistedFileAccessViolations,
                mustBeConsideredPerpetuallyDirty,
                dynamicallyObservedFiles,
                dynamicallyProbedFiles,
                dynamicallyObservedEnumerations,
                allowedUndeclaredSourceReads,
                absentPathProbesUnderOutputDirectories,
                twoPhaseCachingInfo,
                cacheDescriptor,
                converged,
                pathSet,
                cacheLookupCounters,
                pipProperties,
                hasUserRetries);

            return(processExecutionResult);
        }