public static BuildResultCode BuildSlave(BuilderOptions options) { // Mount build path ((FileSystemProvider)VirtualFileSystem.ApplicationData).ChangeBasePath(options.BuildDirectory); PrepareDatabases(options); try { VirtualFileSystem.CreateDirectory("/data/"); VirtualFileSystem.CreateDirectory("/data/db/"); } catch (Exception) { throw new OptionException("Invalid Build database path", "database"); } // Open WCF channel with master builder var namedPipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { SendTimeout = TimeSpan.FromSeconds(300.0) }; var processBuilderRemote = ChannelFactory<IProcessBuilderRemote>.CreateChannel(namedPipeBinding, new EndpointAddress(options.SlavePipe)); try { RegisterRemoteLogger(processBuilderRemote); // Create scheduler var scheduler = new Scheduler(); var status = ResultStatus.NotProcessed; // Schedule command string buildPath = options.BuildDirectory; Logger logger = options.Logger; MicroThread microthread = scheduler.Add(async () => { // Deserialize command and parameters Command command = processBuilderRemote.GetCommandToExecute(); BuildParameterCollection parameters = processBuilderRemote.GetBuildParameters(); // Run command var inputHashes = new DictionaryStore<InputVersionKey, ObjectId>(VirtualFileSystem.OpenStream("/data/db/InputHashes", VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite)); var builderContext = new BuilderContext(buildPath, inputHashes, parameters, 0, null); var commandContext = new RemoteCommandContext(processBuilderRemote, command, builderContext, logger); command.PreCommand(commandContext); status = await command.DoCommand(commandContext); command.PostCommand(commandContext, status); // Returns result to master builder processBuilderRemote.RegisterResult(commandContext.ResultEntry); }); while (true) { scheduler.Run(); // Exit loop if no more micro threads lock (scheduler.MicroThreads) { if (!scheduler.MicroThreads.Any()) break; } Thread.Sleep(0); } // Rethrow any exception that happened in microthread if (microthread.Exception != null) { options.Logger.Fatal(microthread.Exception.ToString()); return BuildResultCode.BuildError; } if (status == ResultStatus.Successful || status == ResultStatus.NotTriggeredWasSuccessful) return BuildResultCode.Successful; return BuildResultCode.BuildError; } finally { // Close WCF channel // ReSharper disable SuspiciousTypeConversion.Global ((IClientChannel)processBuilderRemote).Close(); // ReSharper restore SuspiciousTypeConversion.Global } }
public static BuildResultCode BuildSlave(BuilderOptions options) { // Mount build path ((FileSystemProvider)VirtualFileSystem.ApplicationData).ChangeBasePath(options.BuildDirectory); PrepareDatabases(options); try { VirtualFileSystem.CreateDirectory("/data/"); VirtualFileSystem.CreateDirectory("/data/db/"); } catch (Exception) { throw new OptionException("Invalid Build database path", "database"); } // Open WCF channel with master builder var namedPipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { SendTimeout = TimeSpan.FromSeconds(300.0) }; var processBuilderRemote = ChannelFactory <IProcessBuilderRemote> .CreateChannel(namedPipeBinding, new EndpointAddress(options.SlavePipe)); try { RegisterRemoteLogger(processBuilderRemote); // Create scheduler var scheduler = new Scheduler(); var status = ResultStatus.NotProcessed; // Schedule command string buildPath = options.BuildDirectory; Logger logger = options.Logger; MicroThread microthread = scheduler.Add(async() => { // Deserialize command and parameters Command command = processBuilderRemote.GetCommandToExecute(); BuildParameterCollection parameters = processBuilderRemote.GetBuildParameters(); // Run command var inputHashes = new DictionaryStore <InputVersionKey, ObjectId>(VirtualFileSystem.OpenStream("/data/db/InputHashes", VirtualFileMode.OpenOrCreate, VirtualFileAccess.ReadWrite, VirtualFileShare.ReadWrite)); var builderContext = new BuilderContext(buildPath, inputHashes, parameters, 0, null); var commandContext = new RemoteCommandContext(processBuilderRemote, command, builderContext, logger); command.PreCommand(commandContext); status = await command.DoCommand(commandContext); command.PostCommand(commandContext, status); // Returns result to master builder processBuilderRemote.RegisterResult(commandContext.ResultEntry); }); while (true) { scheduler.Run(); // Exit loop if no more micro threads lock (scheduler.MicroThreads) { if (!scheduler.MicroThreads.Any()) { break; } } Thread.Sleep(0); } // Rethrow any exception that happened in microthread if (microthread.Exception != null) { options.Logger.Fatal(microthread.Exception.ToString()); return(BuildResultCode.BuildError); } if (status == ResultStatus.Successful || status == ResultStatus.NotTriggeredWasSuccessful) { return(BuildResultCode.Successful); } return(BuildResultCode.BuildError); } finally { // Close WCF channel // ReSharper disable SuspiciousTypeConversion.Global ((IClientChannel)processBuilderRemote).Close(); // ReSharper restore SuspiciousTypeConversion.Global } }