private async Task <Possible <T> > ExecuteCommand <T>(Command <T> command) { try { IIpcOperation ipcOperation = new IpcOperation(Command.Serialize(command), waitForServerAck: true); IIpcResult ipcResult = await m_client.Send(ipcOperation); if (!ipcResult.Succeeded) { return(new Failure <string>(ipcResult.ToString())); } T cmdResult; if (!command.TryParseResult(ipcResult.Payload, out cmdResult)) { return(new Failure <string>($"{ErrorCannotParseIpcResultMessage}: {ipcResult}")); } return(cmdResult); } catch (Exception ex) { return(new Failure <Exception>(ex).Annotate($"Executing {command.GetType().Name} command threw exception.")); } }
public void TestAddFile_AssociateDoesntNeedServer() { // this client only touches item.BlobIdentifier and returns 'Associated' var dropClient = new MockDropClient(addFileFunc: (item) => { Assert.NotNull(item.BlobIdentifier); return(Task.FromResult(AddFileResult.Associated)); }); WithSetup(dropClient, (daemon, etwListener) => { var provider = IpcFactory.GetProvider(); var connStr = provider.CreateNewConnectionString(); var contentInfo = new FileContentInfo(new ContentHash(HashType.Vso0), length: 123456); var client = new Client(provider.GetClient(connStr, new ClientConfig())); var addFileItem = new DropItemForBuildXLFile(client, filePath: "file-which-doesnt-exist.txt", fileId: "23423423:1", chunkDedup: TestChunkDedup, fileContentInfo: contentInfo); // addfile succeeds without needing BuildXL server nor the file on disk IIpcResult result = daemon.AddFileAsync(addFileItem).GetAwaiter().GetResult(); XAssert.IsTrue(result.Succeeded); // calling MaterializeFile fails because no BuildXL server is running Assert.Throws <DaemonException>(() => addFileItem.EnsureMaterialized().GetAwaiter().GetResult()); }); }
/// <nodoc/> public Response(int requestId, IIpcResult result) { Contract.Requires(result != null); RequestId = requestId; Result = result; }
/// <summary> /// The <see cref="Succeeded"/> property of the result is a conjunction of the /// corresponding properties of the arguments, and the <see cref="Payload"/> /// property of the result is a semicolon-separated concatenation of the corresponding /// properties of the arguments. /// </summary> public static IIpcResult Merge(IIpcResult lhs, IIpcResult rhs) { return(new IpcResult( MergeStatuses(lhs.ExitCode, rhs.ExitCode), lhs.Payload + Environment.NewLine + rhs.Payload, lhs.ActionDuration + rhs.ActionDuration)); }
/// <summary> /// Asynchronously serializes given <see cref="IIpcResult"/> to a stream writer. /// </summary> /// <remarks> /// Doesn't handle any exceptions. /// </remarks> public static async Task SerializeAsync(Stream stream, IIpcResult result, CancellationToken token) { await Utils.WriteByteAsync(stream, (byte)result.ExitCode, token); await Utils.WriteStringAsync(stream, result.Payload, token); await stream.FlushAsync(token); }
private void UnblockPendingRequests(IIpcResult result) { foreach (var taskSource in m_pendingRequests.Values) { taskSource.TrySetResult(result); } m_pendingRequests.Clear(); }
/// <summary> /// The <see cref="Succeeded"/> property of the result is a conjunction of the /// corresponding properties of the arguments, and the <see cref="Payload"/> /// property of the result is a semicolon-separated concatenation of the corresponding /// properties of the arguments. /// </summary> public static IIpcResult Merge(IIpcResult lhs, IIpcResult rhs) { var mergedStatus = lhs.Succeeded && rhs.Succeeded ? IpcResultStatus.Success : lhs.Succeeded && !rhs.Succeeded ? rhs.ExitCode : !lhs.Succeeded && rhs.Succeeded ? lhs.ExitCode : IpcResultStatus.GenericError; return(new IpcResult(mergedStatus, lhs.Payload + Environment.NewLine + rhs.Payload, lhs.ActionDuration + rhs.ActionDuration)); }
public void TestLazilyMaterializedSymlinkRejected() { string fileId = "142342:3"; string filePath = Path.Combine(TestOutputDirectory, nameof(TestLazilyMaterializedSymlinkRejected) + "-test.txt"); if (File.Exists(filePath)) { File.Delete(filePath); } // this client wants to read the file var dropClient = new MockDropClient(addFileFunc: (item) => { Assert.NotNull(item.BlobIdentifier); var ex = Assert.Throws <DaemonException>(() => item.EnsureMaterialized().GetAwaiter().GetResult()); // rethrowing because that's what a real IDropClient would do (then Daemon is expected to handle it) throw ex; }); WithSetup(dropClient, (daemon, etwListener, dropConfig) => { var dropName = GetDropFullName(dropConfig); var ipcProvider = IpcFactory.GetProvider(); var ipcExecutor = new LambdaIpcOperationExecutor(op => { // this mock BuildXL server materializes a regular file, which we will treat as a symlink in this test var cmd = ReceiveMaterializeFileCmdAndCheckItMatchesFileId(op.Payload, fileId); File.WriteAllText(filePath, TestFileContent); return(IpcResult.Success(cmd.RenderResult(true))); }); WithIpcServer( ipcProvider, ipcExecutor, new ServerConfig(), (moniker, mockServer) => { var client = new Client(ipcProvider.GetClient(ipcProvider.RenderConnectionString(moniker), new ClientConfig())); var addFileItem = new DropItemForBuildXLFile( symlinkTester: (file) => file == filePath ? true : false, client: client, fullDropName: dropName, filePath: filePath, fileId: fileId, fileContentInfo: TestFileContentInfo); // addfile files IIpcResult result = daemon.AddFileAsync(addFileItem).GetAwaiter().GetResult(); XAssert.IsFalse(result.Succeeded, "expected addfile to fail; instead it succeeded and returned payload: " + result.Payload); XAssert.IsTrue(result.Payload.Contains(DropItemForBuildXLFile.MaterializationResultIsSymlinkErrorPrefix)); }); }); }
/// <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> /// 1. deserializes an <see cref="IIpcOperation"/> from a given <paramref name="stream"/>; /// 2. executes the operation (via <paramref name="executor"/>); /// 3. serializes and sends back the result via <paramref name="stream"/>. /// /// If executing the operation (via <paramref name="executor"/>) fails, the <see cref="IIpcResult.ExitCode"/> /// of the result is <see cref="IpcResultStatus.ExecutionError"/> /// </summary> internal static async Task <IIpcResult> ReceiveOperationAndExecuteLocallyAsync(Stream stream, IIpcOperationExecutor executor, CancellationToken token) { IIpcOperation operation = await IpcOperation.DeserializeAsync(stream, token); IIpcResult result = await HandleExceptionsAsync(IpcResultStatus.ExecutionError, () => executor.ExecuteAsync(operation)); if (operation.ShouldWaitForServerAck) { await IpcResult.SerializeAsync(stream, result, token); } return(result); }
public void TestAddBuildXLFile_UploadCallsBuildXLServer() { string fileId = "142342:2"; string filePath = Path.Combine(TestOutputDirectory, nameof(TestAddBuildXLFile_UploadCallsBuildXLServer) + "-test.txt"); if (File.Exists(filePath)) { File.Delete(filePath); } // this client wants to read the file var dropClient = new MockDropClient(addFileFunc: (item) => { Assert.NotNull(item.BlobIdentifier); var fileInfo = item.EnsureMaterialized().GetAwaiter().GetResult(); XAssert.IsTrue(fileInfo != null && fileInfo.Exists); XAssert.AreEqual(TestFileContent, File.ReadAllText(fileInfo.FullName)); return(Task.FromResult(AddFileResult.UploadedAndAssociated)); }); WithSetup(dropClient, (daemon, etwListener, dropConfig) => { var dropName = GetDropFullName(dropConfig); var ipcProvider = IpcFactory.GetProvider(); var ipcExecutor = new LambdaIpcOperationExecutor(op => { var cmd = ReceiveMaterializeFileCmdAndCheckItMatchesFileId(op.Payload, fileId); File.WriteAllText(filePath, TestFileContent); return(IpcResult.Success(cmd.RenderResult(true))); }); WithIpcServer( ipcProvider, ipcExecutor, new ServerConfig(), (moniker, mockServer) => { var client = new Client(ipcProvider.GetClient(ipcProvider.RenderConnectionString(moniker), new ClientConfig())); var addFileItem = new DropItemForBuildXLFile(client, dropName, filePath, fileId, fileContentInfo: TestFileContentInfo); // addfile succeeds IIpcResult result = daemon.AddFileAsync(addFileItem).GetAwaiter().GetResult(); XAssert.IsTrue(result.Succeeded, result.Payload); }); }); }
private async Task <Possible <T> > ExecuteCommand <T>(Command <T> command) { IIpcOperation ipcOperation = new IpcOperation(Command.Serialize(command), waitForServerAck: true); IIpcResult ipcResult = await m_client.Send(ipcOperation); if (!ipcResult.Succeeded) { return(new Failure <string>(ipcResult.ToString())); } T cmdResult; if (!command.TryParseResult(ipcResult.Payload, out cmdResult)) { return(new Failure <string>("Cannot parse IPC result: " + ipcResult.ToString())); } return(cmdResult); }
/// <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)); }
private void AssertRpcResult(bool shouldSucceed, IIpcResult rpcResult) { Assert.NotNull(rpcResult); Assert.Equal(shouldSucceed, rpcResult.Succeeded); }