Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Clients.Hive.Slave/3.3/Executor.cs @ 10262

Last change on this file since 10262 was 9456, checked in by swagner, 12 years ago

Updated copyright year and added some missing license headers (#1889)

File size: 7.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 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 task.
32  /// </summary>
33  public class Executor : MarshalByRefObject, IDisposable {
34    private bool wasTaskAborted = false;
35    private AutoResetEvent pauseStopSem = new AutoResetEvent(false);
36    private AutoResetEvent startTaskSem = new AutoResetEvent(false); // block start method call
37    private AutoResetEvent taskStartedSem = new AutoResetEvent(false); // make pause or stop wait until start is finished
38    private ExecutorQueue executorQueue;
39    private bool taskDataInvalid = false; // if true, the jobdata is not sent when the task is failed
40    private ITask task;
41    private DateTime creationTime;
42
43    public Guid TaskId { 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 task != null ? task.ExecutionState : HeuristicLab.Core.ExecutionState.Stopped; }
66    }
67
68    public TimeSpan ExecutionTime {
69      get { return task != null ? task.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        task = PersistenceUtil.Deserialize<ITask>(serializedJob);
82
83        RegisterJobEvents();
84
85        task.Start();
86        if (!startTaskSem.WaitOne(Settings.Default.ExecutorSemTimeouts)) {
87          taskDataInvalid = true;
88          throw new TimeoutException("Timeout when starting the task. TaskStarted event was not fired.");
89        }
90      }
91      catch (Exception e) {
92        this.CurrentException = e;
93        taskDataInvalid = true;
94        Task_TaskFailed(this, new EventArgs<Exception>(e));
95      } finally {
96        taskStartedSem.Set();
97      }
98    }
99
100    public void Pause() {
101      IsPausing = true;
102      // wait until task is started. if this does not happen, the Task is null an we give up
103      taskStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
104      if (task == null) {
105        CurrentException = new Exception("Pausing task " + this.TaskId + ": Task is null");
106        executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
107        return;
108      }
109
110      if (task.ExecutionState == ExecutionState.Started) {
111        try {
112          task.Pause();
113          //we need to block the pause...
114          pauseStopSem.WaitOne();
115        }
116        catch (Exception ex) {
117          CurrentException = new Exception("Error pausing task " + this.TaskId + ": " + ex.ToString());
118          executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
119        }
120      }
121    }
122
123    public void Stop() {
124      IsStopping = true;
125      // wait until task is started. if this does not happen, the Task is null an we give up
126      taskStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
127      if (task == null) {
128        CurrentException = new Exception("Stopping task " + this.TaskId + ": Task is null");
129        executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
130      }
131      wasTaskAborted = true;
132
133      if ((ExecutionState == ExecutionState.Started) || (ExecutionState == ExecutionState.Paused)) {
134        try {
135          task.Stop();
136          pauseStopSem.WaitOne();
137        }
138        catch (Exception ex) {
139          CurrentException = new Exception("Error stopping task " + this.TaskId + ": " + ex.ToString());
140          executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
141        }
142      }
143    }
144
145    private void RegisterJobEvents() {
146      task.TaskStopped += new EventHandler(Task_TaskStopped);
147      task.TaskFailed += new EventHandler(Task_TaskFailed);
148      task.TaskPaused += new EventHandler(Task_TaskPaused);
149      task.TaskStarted += new EventHandler(Task_TaskStarted);
150    }
151
152    private void DeregisterJobEvents() {
153      task.TaskStopped -= new EventHandler(Task_TaskStopped);
154      task.TaskFailed -= new EventHandler(Task_TaskFailed);
155      task.TaskPaused -= new EventHandler(Task_TaskPaused);
156      task.TaskStarted -= new EventHandler(Task_TaskStarted);
157    }
158
159    #region Task Events
160    private void Task_TaskFailed(object sender, EventArgs e) {
161      IsStopping = true;
162      EventArgs<Exception> ex = (EventArgs<Exception>)e;
163      CurrentException = ex.Value;
164      executorQueue.AddMessage(ExecutorMessageType.TaskFailed);
165    }
166
167    private void Task_TaskStopped(object sender, EventArgs e) {
168      IsStopping = true;
169      if (wasTaskAborted) {
170        pauseStopSem.Set();
171      }
172      executorQueue.AddMessage(ExecutorMessageType.TaskStopped);
173    }
174
175    private void Task_TaskPaused(object sender, EventArgs e) {
176      IsPausing = true;
177      pauseStopSem.Set();
178      executorQueue.AddMessage(ExecutorMessageType.TaskPaused);
179    }
180
181    private void Task_TaskStarted(object sender, EventArgs e) {
182      startTaskSem.Set();
183      executorQueue.AddMessage(ExecutorMessageType.TaskStarted);
184    }
185    #endregion
186
187    public TaskData GetTaskData() {
188      if (taskDataInvalid) return null;
189
190      if (task != null && task.ExecutionState == ExecutionState.Started) {
191        throw new InvalidStateException("Task is still running");
192      } else {
193        TaskData taskData = new TaskData();
194        if (task == null) {
195          //send empty task and save exception
196          taskData.Data = PersistenceUtil.Serialize(new TaskData());
197          if (CurrentException == null) {
198            CurrentException = new Exception("Task with id " + this.TaskId + " is null, sending empty task");
199          }
200        } else {
201          taskData.Data = PersistenceUtil.Serialize(task);
202        }
203        taskData.TaskId = TaskId;
204        return taskData;
205      }
206    }
207
208    public void Dispose() {
209      if (task != null)
210        DeregisterJobEvents();
211      task = null;
212    }
213  }
214}
Note: See TracBrowser for help on using the repository browser.