internal static Command InternalDeserialize(BinaryReader reader) { string dropName = reader.ReadString(); int entryCount = reader.ReadInt32(); BuildManifestEntry[] buildManifestEntries = Enumerable .Range(0, entryCount) .Select(i => BuildManifestEntry.Deserialize(reader)) .ToArray(); return(new RegisterFilesForBuildManifestCommand(dropName, buildManifestEntries)); }
/// <inheritdoc /> public override bool TryParseResult(string result, out BuildManifestEntry[] commandResult) { try { using (var stream = new MemoryStream(Convert.FromBase64String(result))) using (var reader = new BinaryReader(stream)) { var length = reader.ReadInt32(); commandResult = Enumerable.Range(0, length).Select(_ => BuildManifestEntry.Deserialize(reader)).ToArray(); return(true); } } catch { #pragma warning disable ERP022 // Unobserved exception in generic exception handler commandResult = new BuildManifestEntry[0]; return(false); #pragma warning restore ERP022 // Unobserved exception in generic exception handler } }
/// <summary> /// Returns an invalid <see cref="Tracing.BuildManifestEntry"/> when file read or hash computation fails. /// Else returns a valid <see cref="Tracing.BuildManifestEntry"/> on success. /// </summary> private async Task <Tracing.BuildManifestEntry> ExecuteRecordBuildManifestHashWithXlgAsync(string dropName, BuildManifestEntry buildManifestEntry) { await Task.Yield(); // Yield to ensure hashing happens asynchronously // (1) Attempt hash read from in-memory store if (m_inMemoryBuildManifestStore.TryGetValue(buildManifestEntry.Hash, out var buildManifestHash)) { return(new Tracing.BuildManifestEntry(dropName, buildManifestEntry.RelativePath, buildManifestEntry.Hash, buildManifestHash)); } // (2) Attempt hash read from cache if (TryGetBuildManifestHashesAsync(buildManifestEntry.Hash, out var buildManifestHashes)) { m_inMemoryBuildManifestStore.TryAdd(buildManifestEntry.Hash, buildManifestHashes); return(new Tracing.BuildManifestEntry(dropName, buildManifestEntry.RelativePath, buildManifestEntry.Hash, buildManifestHashes)); } // (3) Attempt to compute hash for locally existing file (Materializes non-existing files) using (ManifestCounters.StartStopwatch(BuildManifestCounters.InternalComputeHashLocallyDuration)) { ManifestCounters.IncrementCounter(BuildManifestCounters.InternalComputeHashLocallyCount); var computeHashResult = await ComputeBuildManifestHashFromCacheAsync(buildManifestEntry, requestedTypes : ContentHashingUtilities.BuildManifestHashTypes); if (computeHashResult.Succeeded) { m_inMemoryBuildManifestStore.TryAdd(buildManifestEntry.Hash, computeHashResult.Result); StoreBuildManifestHashes(buildManifestEntry.Hash, computeHashResult.Result); return(new Tracing.BuildManifestEntry(dropName, buildManifestEntry.RelativePath, buildManifestEntry.Hash, computeHashResult.Result)); } Tracing.Logger.Log.ErrorApiServerGetBuildManifestHashFromLocalFileFailed(m_loggingContext, buildManifestEntry.Hash.Serialize(), computeHashResult.Failure.DescribeIncludingInnerFailures()); } ManifestCounters.IncrementCounter(BuildManifestCounters.TotalHashFileFailures); return(new Tracing.BuildManifestEntry(dropName, buildManifestEntry.RelativePath, buildManifestEntry.Hash, new[] { new ContentHash(HashType.Unknown) })); }
/// <summary> /// Compute the hashes for file stored in Cache. Required for Build Manifest generation. /// </summary> private async Task <Possible <IReadOnlyList <ContentHash> > > ComputeBuildManifestHashFromCacheAsync(BuildManifestEntry buildManifestEntry, IList <HashType> requestedTypes) { // Ensure that the file is materialized. MaterializeFileCommand materializeCommand = new MaterializeFileCommand(buildManifestEntry.Artifact, buildManifestEntry.FullFilePath); IIpcResult materializeResult = await ExecuteMaterializeFileAsync(materializeCommand); if (!materializeResult.Succeeded) { return(new Failure <string>($"Unable to materialize file: '{buildManifestEntry.FullFilePath}' with hash: '{buildManifestEntry.Hash.Serialize()}'. Failure: {materializeResult.Payload}")); } return(await TryGetBuildManifestHashFromLocalFileAsync(buildManifestEntry.FullFilePath, buildManifestEntry.Hash, requestedTypes)); }
/// <summary> /// Returns the BuildManifestEntry when hash read/computation fails. Else returns null. /// </summary> private async Task <BuildManifestEntry> ExecuteRecordBuildManifestHashAsync(string dropName, BuildManifestEntry buildManifestEntry) { await Task.Yield(); // Yield to ensure hashing happens asynchronously // (1) Attempt hash read from in-memory store if (m_inMemoryBuildManifestStore.TryGetValue(buildManifestEntry.Hash, out var buildManifestHash)) { RecordFileForBuildManifestInXLG(dropName, buildManifestEntry.RelativePath, buildManifestEntry.Hash, buildManifestHash); return(null); } // (2) Attempt hash read from cache ContentHash?hashFromCache = await TryGetBuildManifestHashAsync(buildManifestEntry.Hash); if (hashFromCache.HasValue) { m_inMemoryBuildManifestStore.TryAdd(buildManifestEntry.Hash, hashFromCache.Value); RecordFileForBuildManifestInXLG(dropName, buildManifestEntry.RelativePath, buildManifestEntry.Hash, hashFromCache.Value); return(null); } // (3) Attempt to compute hash for locally existing file (Materializes non-existing files) var computeHashResult = await ComputeBuildManifestHashFromCacheAsync(buildManifestEntry); if (computeHashResult.Succeeded) { m_inMemoryBuildManifestStore.TryAdd(buildManifestEntry.Hash, computeHashResult.Result); RecordFileForBuildManifestInXLG(dropName, buildManifestEntry.RelativePath, buildManifestEntry.Hash, computeHashResult.Result); await StoreBuildManifestHashAsync(buildManifestEntry.Hash, computeHashResult.Result); return(null); } Tracing.Logger.Log.ErrorApiServerGetBuildManifestHashFromCacheFailed(m_loggingContext, buildManifestEntry.Hash.Serialize(), computeHashResult.Failure.DescribeIncludingInnerFailures()); return(buildManifestEntry); }
/// <summary> /// Compute the SHA-256 hash for file stored in Cache. Required for Build Manifets generation. /// </summary> private async Task <Possible <ContentHash> > ComputeBuildManifestHashFromCacheAsync(BuildManifestEntry buildManifestEntry) { if (!File.Exists(buildManifestEntry.FullFilePath)) { // Ensure file is materialized locally if (!AbsolutePath.TryCreate(m_context.PathTable, buildManifestEntry.FullFilePath, out AbsolutePath path)) { return(new Failure <string>($"Invalid absolute path: '{buildManifestEntry.FullFilePath}'")); } MaterializeFileCommand materializeCommand = new MaterializeFileCommand(FileArtifact.CreateOutputFile(path), buildManifestEntry.FullFilePath); IIpcResult materializeResult = await ExecuteMaterializeFileAsync(materializeCommand); if (!materializeResult.Succeeded) { return(new Failure <string>($"Unable to materialize file: '{buildManifestEntry.FullFilePath}' with hash: '{buildManifestEntry.Hash.Serialize()}'. Failure: {materializeResult.Payload}")); } } return(await TryGetBuildManifestHashFromLocalFileAsync(buildManifestEntry.FullFilePath)); }