/// <summary> /// Executes <see cref="MaterializeFileCommand"/>. First check that <see cref="MaterializeFileCommand.File"/> /// and <see cref="MaterializeFileCommand.FullFilePath"/> match, then delegates to <see cref="FileContentManager.TryMaterializeFileAsync"/>. /// </summary> private async Task <IIpcResult> ExecuteMaterializeFileAsync(MaterializeFileCommand cmd) { Contract.Requires(cmd != null); // for extra safety, check that provided file path and file id match AbsolutePath filePath; bool isValidPath = AbsolutePath.TryCreate(m_context.PathTable, cmd.FullFilePath, out filePath); if (!isValidPath || !cmd.File.Path.Equals(filePath)) { return(new IpcResult( IpcResultStatus.ExecutionError, "file path ids differ; file = " + cmd.File.Path.ToString(m_context.PathTable) + ", file path = " + cmd.FullFilePath)); } var result = await m_fileContentManager.TryMaterializeFileAsync(cmd.File); bool succeeded = result == ArtifactMaterializationResult.Succeeded; string absoluteFilePath = cmd.File.Path.ToString(m_context.PathTable); // if file materialization failed, log an error here immediately, so that this errors gets picked up as the root cause // (i.e., the "ErrorBucket") instead of whatever fallout ends up happening (e.g., IPC pip fails) if (!succeeded) { Tracing.Logger.Log.ErrorApiServerMaterializeFileFailed(m_loggingContext, absoluteFilePath, result.ToString()); } else { Tracing.Logger.Log.ApiServerMaterializeFileSucceeded(m_loggingContext, absoluteFilePath); } return(IpcResult.Success(cmd.RenderResult(succeeded))); }
/// <summary> /// Compute the SHA-256 hash for file stored in Cache. Required for Build Manifets generation. /// </summary> /// <remarks> /// Returns null when unable to find content in cache. /// </remarks> private async Task <Possible <ContentHash> > ComputeBuildManifestHashFromCacheAsync(RegisterFileForBuildManifestCommand cmd) { // Ensure file is materialized locally MaterializeFileCommand materializeCommand = new MaterializeFileCommand(cmd.File, cmd.FullFilePath); var materializeResult = await ExecuteMaterializeFileAsync(materializeCommand); if (!materializeResult.Succeeded) { return(new Failure <string>("Unable to materialize file = " + cmd.File.Path.ToString(m_context.PathTable) + " with hash: " + cmd.Hash.Serialize())); } // Open content stream for locally available file var loadFileContentResult = await m_engineCache.ArtifactContentCache.TryOpenContentStreamAsync(cmd.Hash); if (loadFileContentResult.Succeeded) { using (var streamWithLength = loadFileContentResult.Result) { try { return(await ContentHashingUtilities.HashContentStreamAsync(streamWithLength, ContentHashingUtilities.BuildManifestHashType)); } catch (BuildXLException ex) { return(new Failure <string>(ex.Message)); } } } return(new Failure <string>(loadFileContentResult.Failure.DescribeIncludingInnerFailures())); }
/// <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> /// Executes <see cref="MaterializeFileCommand"/>. First check that <see cref="MaterializeFileCommand.File"/> /// and <see cref="MaterializeFileCommand.FullFilePath"/> match, then delegates to <see cref="FileContentManager.TryMaterializeFileAsync(FileArtifact)"/>. /// If provided <see cref="MaterializeFileCommand.File"/> is not valid, no checks are done, and the call is delegated /// to <see cref="FileContentManager.TryMaterializeSealedFileAsync(AbsolutePath)"/> /// </summary> private async Task <IIpcResult> ExecuteMaterializeFileAsync(MaterializeFileCommand cmd) { Contract.Requires(cmd != null); // If the FileArtifact was provided, for extra safety, check that provided file path and file id match AbsolutePath filePath; bool isValidPath = AbsolutePath.TryCreate(m_context.PathTable, cmd.FullFilePath, out filePath); if (cmd.File.IsValid && (!isValidPath || !cmd.File.Path.Equals(filePath))) { return(new IpcResult( IpcResultStatus.ExecutionError, "file path ids differ; file = " + cmd.File.Path.ToString(m_context.PathTable) + ", file path = " + cmd.FullFilePath)); } // If only path was provided, check that it's a valid path. else if (!cmd.File.IsValid && !filePath.IsValid) { return(new IpcResult( IpcResultStatus.ExecutionError, $"failed to create AbsolutePath from '{cmd.FullFilePath}'")); } var result = cmd.File.IsValid ? await m_fileContentManager.TryMaterializeFileAsync(cmd.File) // If file artifact is unknown, try materializing using only the file path. // This method has lower chance of success, since it depends on FileContentManager's // ability to infer FileArtifact associated with this path. : await m_fileContentManager.TryMaterializeSealedFileAsync(filePath); bool succeeded = result == ArtifactMaterializationResult.Succeeded; string absoluteFilePath = cmd.File.Path.ToString(m_context.PathTable); // if file materialization failed, log an error here immediately, so that this errors gets picked up as the root cause // (i.e., the "ErrorBucket") instead of whatever fallout ends up happening (e.g., IPC pip fails) if (!succeeded) { // For sealed files, materialization might not have succeeded because a path is not known to BXL. // In such a case, do not log an error, and let the caller deal with the failure. if (cmd.File.IsValid) { Tracing.Logger.Log.ErrorApiServerMaterializeFileFailed(m_loggingContext, absoluteFilePath, cmd.File.IsValid, result.ToString()); } } else { Tracing.Logger.Log.ApiServerMaterializeFileSucceeded(m_loggingContext, absoluteFilePath); } return(IpcResult.Success(cmd.RenderResult(succeeded))); }
/// <summary> /// Executes <see cref="MaterializeFileCommand"/>. First check that <see cref="MaterializeFileCommand.File"/> /// and <see cref="MaterializeFileCommand.FullFilePath"/> match, then delegates to <see cref="FileContentManager.TryMaterializeFile"/>. /// </summary> private async Task <IIpcResult> ExecuteMaterializeFile(MaterializeFileCommand cmd) { Contract.Requires(cmd != null); // for extra safety, check that provided file path and file id match AbsolutePath filePath; bool isValidPath = AbsolutePath.TryCreate(m_context.PathTable, cmd.FullFilePath, out filePath); if (!isValidPath || !cmd.File.Path.Equals(filePath)) { return(new IpcResult( IpcResultStatus.ExecutionError, "file path ids differ; file = " + cmd.File.Path.ToString(m_context.PathTable) + ", file path = " + cmd.FullFilePath)); } bool succeeded = await m_fileContentManager.TryMaterializeFile(cmd.File); Tracing.Logger.Log.ApiServerMaterializeFileExecuted(m_loggingContext, cmd.File.Path.ToString(m_context.PathTable), succeeded); return(IpcResult.Success(cmd.RenderResult(succeeded))); }
/// <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)); }