Changeset 17013 for branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs
- Timestamp:
- 06/17/19 10:40:41 (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2924_DotNetCoreMigration/HeuristicLab.PluginInfrastructure/3.3/Isolation/RunnerHost.cs
r16993 r17013 4 4 using System.Threading; 5 5 using System.Threading.Tasks; 6 using HEAL.Attic; 6 7 7 8 namespace HeuristicLab.PluginInfrastructure { … … 14 15 Starting, 15 16 Running, 16 Paused,17 Stopping,18 17 Stopped 19 18 } … … 27 26 #region Vars 28 27 protected Process process; 28 private ProtoBufSerializer serializer = new ProtoBufSerializer(); 29 29 #endregion 30 30 31 31 #region Properties 32 /// <summary> 33 /// Set this to true, if console output should be disabled. 34 /// </summary> 35 public bool QuietMode { get; set; } 36 37 32 38 /// <summary> 33 39 /// The programm, which should be used. For example 'docker'. … … 41 47 protected string Password { get; private set; } 42 48 protected string Domain { get; private set; } 49 protected IRunner Runner { get; set; } 43 50 44 /// <summary>45 /// The runner state.46 /// </summary>47 51 public RunnerState State { get; protected set; } = RunnerState.Created; 48 52 #endregion 49 53 50 54 #region Constructors 55 51 56 protected RunnerHost(string program, string startArgument, string userName, string password, string domain) { 52 57 Program = program; … … 63 68 throw new InvalidOperationException("Runner must be in state 'Created'."); 64 69 State = RunnerState.Starting; 70 Runner = runner; 65 71 process = new Process { 66 72 StartInfo = new ProcessStartInfo { … … 72 78 RedirectStandardError = true, 73 79 CreateNoWindow = false, 74 UserName = string.IsNullOrEmpty(UserName) ? null : UserName, 80 UserName = string.IsNullOrEmpty(UserName) ? null : UserName, // TODO: accounts testen: https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/local-accounts#sec-localsystem 75 81 PasswordInClearText = string.IsNullOrEmpty(Password) ? null : Password, 76 82 Domain = string.IsNullOrEmpty(Domain) ? null : Domain, … … 80 86 }; 81 87 process.Start(); 88 82 89 // registers a task for cancellation, prevents the use of polling (while-loop) 83 90 var task = RegisterCancellation(token.HasValue ? token.Value : CancellationToken.None); 84 91 85 // write config to standardinput, runner listens on this and deserializes the config 86 Runner.Serialize(runner, process.StandardInput.BaseStream); 92 // set runnerhost in runner 93 Runner r = Runner as Runner; 94 if (r != null) r.Host = this; 87 95 88 96 process.BeginOutputReadLine(); 89 97 process.BeginErrorReadLine(); 90 98 91 if (! runner.QuietMode) {99 if (!QuietMode) { 92 100 process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data); 93 101 process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data); 94 102 } 103 104 // write config to standardinput, runner listens on this and deserializes the config 105 SendMessage(new TransportRunnerMessage(Runner)); 106 95 107 State = RunnerState.Running; 96 108 if (await task) State = RunnerState.Cancelled; 97 109 else State = RunnerState.Stopped; 98 99 110 } 100 111 101 /// <summary> 102 /// Pauses the runners. The childprocess gets notified with the help of the standard input and a serialized RunnerJob. 103 /// To pause the runner, the state must be "Running". 104 /// </summary> 105 public void Pause() { 112 113 public void Send(RunnerMessage runnerMessage) { 106 114 if (State != RunnerState.Running) throw new InvalidOperationException("Runner must be in state 'Running'!"); 107 Runner.Pause(process.StandardInput.BaseStream); 108 State = RunnerState.Paused; 115 SendMessage(runnerMessage); 109 116 } 110 117 111 /// <summary> 112 /// Resumes a paused runner. The childprocess gets notified with the help of the standard input and a serialized RunnerJob. 113 /// To resume the runner, the state must be "Paused". 114 /// </summary> 115 public void Resume() { 116 if (State != RunnerState.Paused) throw new InvalidOperationException("Runner must be in state 'Paused'!"); 117 Runner.Resume(process.StandardInput.BaseStream); 118 State = RunnerState.Running; 118 // because we need to transfer the runner with a TransportRunnerMessage in the starting state and the 119 // original send method should not be available until running state 120 protected virtual void SendMessage(RunnerMessage runnerMessage) { 121 runnerMessage.SendTime = DateTime.Now; 122 byte[] bytes = serializer.Serialize(runnerMessage); 123 byte[] size = BitConverter.GetBytes(bytes.Length); 124 process.StandardInput.BaseStream.Write(size, 0, size.Length); 125 process.StandardInput.BaseStream.Flush(); 126 process.StandardInput.BaseStream.Write(bytes, 0, bytes.Length); 127 process.StandardInput.BaseStream.Flush(); 119 128 } 120 129 … … 125 134 /// When the child process gets finished without requested cancellation, the linked token gets cancelled and a result set. 126 135 /// </summary> 127 pr ivateTask<bool> RegisterCancellation(CancellationToken token) {136 protected Task<bool> RegisterCancellation(CancellationToken token) { 128 137 if (process != null && State == RunnerState.Starting) { 129 138 var cts = CancellationTokenSource.CreateLinkedTokenSource(token); … … 133 142 cts.Token.Register(() => { 134 143 if (!process.HasExited) { 135 Runner.Cancel( process.StandardInput.BaseStream);144 Runner.Cancel(); 136 145 process.WaitForExit(); 137 146 }
Note: See TracChangeset
for help on using the changeset viewer.