Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

  • fixed Admin Views plugin dependencies
  • use settings instead of magic numbers and strings
File size: 6.9 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 Semaphore pauseStopSem = new Semaphore(0, 1);
36    private Semaphore startJobSem = new Semaphore(0, 1);
37    private Semaphore jobStartedSem = new Semaphore(0, 1); // 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    private Exception currentException;
50    public String CurrentException {
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 (!jobStartedSem.WaitOne(TimeSpan.FromSeconds(Settings.Default.ExecutorSemTimeouts))) {
87          jobDataInvalid = true;
88          throw new TimeoutException("Timeout when starting the job. JobStarted event was not fired.");
89        }
90        jobStartedSem.Release();
91      }
92      catch (Exception e) {
93        this.currentException = e;
94        Job_JobFailed(this, new EventArgs<Exception>(e));
95      }
96    }
97
98    public void Pause() {
99      IsPausing = true;
100      // wait until job is started. if this does not happen, the Job is null an we give up
101      jobStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
102      if (job == null) {
103        currentException = new Exception("Pausing job " + this.JobId + ": Job is null");
104        return;
105      }
106
107      if (job.ExecutionState == ExecutionState.Started) {
108        try {
109          job.Pause();
110          //we need to block the pause...
111          pauseStopSem.WaitOne();
112        }
113        catch (Exception ex) {
114          currentException = new Exception("Error pausing job " + this.JobId + ": " + ex.ToString());
115        }
116      }
117    }
118
119    public void Stop() {
120      IsStopping = true;
121      // wait until job is started. if this does not happen, the Job is null an we give up
122      jobStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
123      if (job == null) {
124        currentException = new Exception("Stopping job " + this.JobId + ": Job is null");
125      }
126      wasJobAborted = true;
127
128      if ((ExecutionState == ExecutionState.Started) || (ExecutionState == ExecutionState.Paused)) {
129        try {
130          job.Stop();
131          pauseStopSem.WaitOne();
132        }
133        catch (Exception ex) {
134          currentException = new Exception("Error stopping job " + this.JobId + ": " + ex.ToString());
135        }
136      }
137    }
138
139    private void RegisterJobEvents() {
140      job.JobStopped += new EventHandler(Job_JobStopped);
141      job.JobFailed += new EventHandler(Job_JobFailed);
142      job.JobPaused += new EventHandler(Job_JobPaused);
143      job.JobStarted += new EventHandler(Job_JobStarted);
144    }
145
146    private void DeregisterJobEvents() {
147      job.JobStopped -= new EventHandler(Job_JobStopped);
148      job.JobFailed -= new EventHandler(Job_JobFailed);
149      job.JobPaused -= new EventHandler(Job_JobPaused);
150      job.JobStarted -= new EventHandler(Job_JobStarted);
151    }
152
153    #region Job Events
154    private void Job_JobFailed(object sender, EventArgs e) {
155      IsStopping = true;
156      EventArgs<Exception> ex = (EventArgs<Exception>)e;
157      currentException = ex.Value;
158
159      executorQueue.AddMessage(ExecutorMessageType.JobFailed);
160    }
161
162    private void Job_JobStopped(object sender, EventArgs e) {
163      IsStopping = true;
164      if (wasJobAborted)
165        pauseStopSem.Release();
166
167      executorQueue.AddMessage(ExecutorMessageType.JobStopped);
168    }
169
170    private void Job_JobPaused(object sender, EventArgs e) {
171      IsPausing = true;
172      pauseStopSem.Release();
173      executorQueue.AddMessage(ExecutorMessageType.JobPaused);
174    }
175
176    private void Job_JobStarted(object sender, EventArgs e) {
177      jobStartedSem.Release();
178      executorQueue.AddMessage(ExecutorMessageType.JobStarted);
179    }
180    #endregion
181
182    public JobData GetJobData() {
183      if (jobDataInvalid) return null;
184
185      if (job.ExecutionState == ExecutionState.Started) {
186        throw new InvalidStateException("Job is still running");
187      } else {
188        JobData jobData = new JobData();
189        if (job == null) {
190          //send empty job and save exception
191          jobData.Data = PersistenceUtil.Serialize(new JobData());
192          if (currentException == null) {
193            currentException = new Exception("Job with id " + this.JobId + " is null, sending empty job");
194          }
195        } else {
196          jobData.Data = PersistenceUtil.Serialize(job);
197        }
198        jobData.JobId = JobId;
199        return jobData;
200      }
201    }
202
203    public void Dispose() {
204      if (job != null)
205        DeregisterJobEvents();
206      job = null;
207    }
208  }
209}
Note: See TracBrowser for help on using the repository browser.