/// <summary> /// Run the requested executable and produce a report of the results. /// </summary> /// <param name="executionRequest">The execution request.</param> /// <returns>A report of the results.</returns> private CloudExecutionReport RunAnExecutable(CloudExecutionRequest executionRequest) { // REVIEW: How/whether to use this. BuildObject diagnosticsBase = new BuildObject(Path.Combine("nuobj", "diagnostics", "process")); // Prep working directory with input files and output dirs. // TODO: The below will throw cache exceptions if something // isn't there (they should all be though). Need to catch // these and fail the execution request when this happens. WorkingDirectory workingDirectory = new WorkingDirectory(this.virtualIronRoot); foreach (BuildObjectValuePointer inputFile in executionRequest.InputFileMappings) { // REVIEW: How to determine cache container here. ItemCacheContainer container = ItemCacheContainer.Sources; if (this.multiplexedItemCache.GetItemSize(container, inputFile.ObjectHash) == -1) { container = ItemCacheContainer.Objects; } // TODO: Move path/directory manipulation code into // WorkingDirectory and/or ItemCache. string inputFilePath = workingDirectory.PathTo(inputFile.RelativePath); Directory.CreateDirectory(Path.GetDirectoryName(inputFilePath)); // REVIEW: Still neeeded? this.multiplexedItemCache.FetchItemToFile( container, inputFile.ObjectHash, inputFilePath); } foreach (BuildObject outputFile in executionRequest.OutputFiles) { workingDirectory.CreateDirectoryFor(outputFile); } // Run executable. ProcessInvoker pinv = new ProcessInvoker( workingDirectory, executionRequest.Executable, new string[] { executionRequest.Arguments }, diagnosticsBase, null, // This is captureStdout. TODO: Should cleanup how this is used in ProcessInvoker. null); // This is dbgText. REVIEW: How/whether to use this. // When ProcessInvoker's constructor returns, the process has // finished running. Console.WriteLine("Request {0} completed in {1} seconds.", executionRequest.Identifier, pinv.CpuTime); // Store output files in the (cloud) item cache, and create a // list of the mappings. List <BuildObjectValuePointer> outputFileMappings = new List <BuildObjectValuePointer>(); foreach (BuildObject outFile in executionRequest.OutputFiles) { if (File.Exists(workingDirectory.PathTo(outFile))) { string fileHash = Util.hashFilesystemPath(workingDirectory.PathTo(outFile)); Util.Assert(!string.IsNullOrEmpty(fileHash)); // Note we explicitly write to the cloud cache here. this.cloudCache.StoreItemFromFile(ItemCacheContainer.Objects, fileHash, workingDirectory.PathTo(outFile)); outputFileMappings.Add(new BuildObjectValuePointer(fileHash, outFile.getRelativePath())); } } // Collect the results into a report. CloudExecutionReport report = new CloudExecutionReport( executionRequest.Identifier, CloudExecutionReport.StatusCode.Completed, pinv.ExitCode, pinv.GetStdout(), pinv.GetStderr(), pinv.CpuTime, outputFileMappings); return(report); }