Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Executor.cs @ 6464

Last change on this file since 6464 was 6464, checked in by ascheibe, 12 years ago

#1233

  • some Admin UI bugfixes

Slave:

  • fixed bug when Pause is called immediately after Calculate
  • send exceptions when something goes wrong in Pause or Stop
File size: 7.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Threading;
24using HeuristicLab.Clients.Hive.SlaveCore.Properties;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Hive;
28
29namespace HeuristicLab.Clients.Hive.SlaveCore {
30  /// <summary>
31  /// The executor runs in the appdomain and handles the execution of an Hive job.
32  /// </summary>
33  public class Executor : MarshalByRefObject, IDisposable {
34    private bool wasJobAborted = false;
35    private AutoResetEvent pauseStopSem = new AutoResetEvent(false);
36    private AutoResetEvent startJobSem = new AutoResetEvent(false); // block start method call
37    private AutoResetEvent jobStartedSem = new AutoResetEvent(false); // make pause or stop wait until start is finished
38    private ExecutorQueue executorQueue;
39    private bool jobDataInvalid = false; // if true, the jobdata is not sent when the job is failed
40    private IJob job;
41    private DateTime creationTime;
42
43    public Guid JobId { get; set; }
44    public int CoresNeeded { get; set; }
45    public int MemoryNeeded { get; set; }
46    public bool IsStopping { get; set; }
47    public bool IsPausing { get; set; }
48
49    public Exception CurrentException;
50    public String CurrentExceptionStr {
51      get {
52        if (CurrentException != null) {
53          return CurrentException.ToString();
54        } else {
55          return string.Empty;
56        }
57      }
58    }
59
60    public ExecutorQueue ExecutorCommandQueue {
61      get { return executorQueue; }
62    }
63
64    private ExecutionState ExecutionState {
65      get { return job != null ? job.ExecutionState : HeuristicLab.Core.ExecutionState.Stopped; }
66    }
67
68    public TimeSpan ExecutionTime {
69      get { return job != null ? job.ExecutionTime : new TimeSpan(0, 0, 0); }
70    }
71
72    public Executor() {
73      IsStopping = false;
74      IsPausing = false;
75      executorQueue = new ExecutorQueue();
76    }
77
78    public void Start(byte[] serializedJob) {
79      try {
80        creationTime = DateTime.Now;
81        job = PersistenceUtil.Deserialize<IJob>(serializedJob);
82
83        RegisterJobEvents();
84
85        job.Start();
86        if (!startJobSem.WaitOne(Settings.Default.ExecutorSemTimeouts)) {
87          jobDataInvalid = true;
88          throw new TimeoutException("Timeout when starting the job. JobStarted event was not fired.");
89        }
90      }
91      catch (Exception e) {
92        this.CurrentException = e;
93        Job_JobFailed(this, new EventArgs<Exception>(e));
94      }
95      finally {
96        jobStartedSem.Set();
97      }
98    }
99
100    public void Pause() {
101      IsPausing = true;
102      // wait until job is started. if this does not happen, the Job is null an we give up
103      jobStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
104      if (job == null) {
105        CurrentException = new Exception("Pausing job " + this.JobId + ": Job is null");
106        executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
107        return;
108      }
109
110      if (job.ExecutionState == ExecutionState.Started) {
111        try {
112          job.Pause();
113          //we need to block the pause...
114          pauseStopSem.WaitOne();
115        }
116        catch (Exception ex) {
117          CurrentException = new Exception("Error pausing job " + this.JobId + ": " + ex.ToString());
118          executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
119        }
120      }
121    }
122
123    public void Stop() {
124      IsStopping = true;
125      // wait until job is started. if this does not happen, the Job is null an we give up
126      jobStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
127      if (job == null) {
128        CurrentException = new Exception("Stopping job " + this.JobId + ": Job is null");
129        executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
130      }
131      wasJobAborted = true;
132
133      if ((ExecutionState == ExecutionState.Started) || (ExecutionState == ExecutionState.Paused)) {
134        try {
135          job.Stop();
136          pauseStopSem.WaitOne();
137        }
138        catch (Exception ex) {
139          CurrentException = new Exception("Error stopping job " + this.JobId + ": " + ex.ToString());
140          executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
141        }
142      }
143    }
144
145    private void RegisterJobEvents() {
146      job.JobStopped += new EventHandler(Job_JobStopped);
147      job.JobFailed += new EventHandler(Job_JobFailed);
148      job.JobPaused += new EventHandler(Job_JobPaused);
149      job.JobStarted += new EventHandler(Job_JobStarted);
150    }
151
152    private void DeregisterJobEvents() {
153      job.JobStopped -= new EventHandler(Job_JobStopped);
154      job.JobFailed -= new EventHandler(Job_JobFailed);
155      job.JobPaused -= new EventHandler(Job_JobPaused);
156      job.JobStarted -= new EventHandler(Job_JobStarted);
157    }
158
159    #region Job Events
160    private void Job_JobFailed(object sender, EventArgs e) {
161      IsStopping = true;
162      EventArgs<Exception> ex = (EventArgs<Exception>)e;
163      CurrentException = ex.Value;
164      executorQueue.AddMessage(ExecutorMessageType.JobFailed);
165    }
166
167    private void Job_JobStopped(object sender, EventArgs e) {
168      IsStopping = true;
169      if (wasJobAborted) {
170        pauseStopSem.Set();
171      }
172      executorQueue.AddMessage(ExecutorMessageType.JobStopped);
173    }
174
175    private void Job_JobPaused(object sender, EventArgs e) {
176      IsPausing = true;
177      pauseStopSem.Set();
178      executorQueue.AddMessage(ExecutorMessageType.JobPaused);
179    }
180
181    private void Job_JobStarted(object sender, EventArgs e) {
182      startJobSem.Set();
183      executorQueue.AddMessage(ExecutorMessageType.JobStarted);
184    }
185    #endregion
186
187    public JobData GetJobData() {
188      if (jobDataInvalid) return null;
189
190      if (job.ExecutionState == ExecutionState.Started) {
191        throw new InvalidStateException("Job is still running");
192      } else {
193        JobData jobData = new JobData();
194        if (job == null) {
195          //send empty job and save exception
196          jobData.Data = PersistenceUtil.Serialize(new JobData());
197          if (CurrentException == null) {
198            CurrentException = new Exception("Job with id " + this.JobId + " is null, sending empty job");
199          }
200        } else {
201          jobData.Data = PersistenceUtil.Serialize(job);
202        }
203        jobData.JobId = JobId;
204        return jobData;
205      }
206    }
207
208    public void Dispose() {
209      if (job != null)
210        DeregisterJobEvents();
211      job = null;
212    }
213  }
214}
Note: See TracBrowser for help on using the repository browser.