/// <summary> /// Initializes a new instance of the MultiplexerWrappedStream /// class. /// </summary> /// <param name="stream">A stream to wrap.</param> /// <param name="multiplexer"> /// The multiplexer cache instance owning item. /// </param> /// <param name="container"> /// The container for the item in the multiplexer cache. /// </param> /// <param name="itemHash"> /// The hash for the item in the multiplexer cache. /// </param> public MultiplexerWrappedStream( Stream stream, ItemCacheMultiplexer multiplexer, ItemCacheContainer container, string itemHash) { this.stream = stream; this.multiplexer = multiplexer; this.container = container; this.itemHash = itemHash; }
/// <summary> /// Initializes a new instance of the CloudSubmitter class. /// </summary> /// <param name="requestIdentifier"> /// Unique identifier for this request. /// </param> /// <param name="workingDirectory"> /// Working directory the process is started in. /// </param> /// <param name="inputFiles"> /// List of input files expected by the process. /// </param> /// <param name="outputFiles"> /// List of potential output files generated by the process. /// </param> /// <param name="executable">Executable to run.</param> /// <param name="args"> /// Command line arguments to provide to the executable. /// </param> /// <param name="failureBase">Not sure what this is -- some debugging/diagnostic thing.</param> /// <param name="captureStdout">Where to (optionally) store the captured standard out.</param> /// <param name="dbgText">Debugging text for something or another.</param> public CloudSubmitter( string requestIdentifier, WorkingDirectory workingDirectory, IEnumerable <BuildObject> inputFiles, IEnumerable <BuildObject> outputFiles, string executable, string[] args, BuildObject failureBase, BuildObject captureStdout = null, string dbgText = null) { // Catch bad verb authors before they hurt themselves. Util.Assert(!executable.Contains(":")); // Hey, this looks like an absolute path! Use .getRelativePath(); it makes your output more stable. foreach (string arg in args) { // Pardon my distasteful heuristic to avoid flagging /flag:value args. Util.Assert(arg.Length < 2 || arg[1] != ':'); // Hey, this looks like an absolute path! Use .getRelativePath() to tolerate crossing machine boundaries. } // Stash away things we'll want to remember later. this.workingDirectory = workingDirectory; // Create list of input file mappings. // REVIEW: We're not running on the main thread at this point. Are below calls all thread-safe? List <BuildObjectValuePointer> inputFileMappings = new List <BuildObjectValuePointer>(); foreach (BuildObject file in inputFiles) { string fileHash = BuildEngine.theEngine.Repository.GetHash(file); Util.Assert(!string.IsNullOrEmpty(fileHash)); inputFileMappings.Add(new BuildObjectValuePointer(fileHash, file.getRelativePath())); // Ensure that the input files are in the cloud cache. // REVIEW: best way to determine this is a source file? ItemCacheContainer container; if (file is SourcePath) { container = ItemCacheContainer.Sources; } else { container = ItemCacheContainer.Objects; } ItemCacheMultiplexer multiplexedCache = BuildEngine.theEngine.ItemCache as ItemCacheMultiplexer; Util.Assert(multiplexedCache != null); multiplexedCache.SyncItemToCloud(container, fileHash); } // Prepare cloud execution request for submission. string arguments = string.Join(" ", args); CloudExecutionRequest request = new CloudExecutionRequest( BuildEngine.theEngine.CloudReportQueueName, requestIdentifier, CloudExecutionRequest.Operation.RunExecutable, executable, arguments, inputFileMappings, outputFiles); BuildEngine.theEngine.CloudExecutionQueue.SubmitRequest(request); // Wait for remote execution to finish. int requestsOutstanding; Console.WriteLine("Waiting on remote execution report for request '{0}'.", requestIdentifier); CloudExecutionReport executionReport = BuildEngine.theEngine.CloudExecutionQueue.GetReport(requestIdentifier, out requestsOutstanding); Console.WriteLine("Received remote execution report for request '{0}'. {1} others still outstanding.", requestIdentifier, requestsOutstanding); // Record what we got back. this.exitCode = executionReport.ExitCode; this.stdout = executionReport.StandardOutput; this.stderr = executionReport.StandardError; this.cpuTime = executionReport.CpuTime; // Copy output files from cloud cache back to local working dir. // REVIEW: This is just to set things up as expected for the // Scheduler's recordResult routine. Could re-architect this to // be more efficient for the remote execution case. foreach (BuildObjectValuePointer outputFileMapping in executionReport.OutputFileMappings) { BuildEngine.theEngine.CloudCache.FetchItemToFile( ItemCacheContainer.Objects, outputFileMapping.ObjectHash, workingDirectory.PathTo(outputFileMapping.RelativePath)); } }