Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 5782 was 5782, checked in by ascheibe, 14 years ago

#1233

  • fixed job pause bug... again
  • general Executor improvements
File size: 7.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Collections.Generic;
24using System.Linq;
25using System.Threading;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Hive;
29using HeuristicLab.PluginInfrastructure;
30
31
32namespace HeuristicLab.Clients.Hive.SlaveCore {
33  public class Executor : MarshalByRefObject, IDisposable {
34    public Guid JobId { get; set; }
35    public IJob Job { get; set; }
36    private bool wasJobAborted = false;
37    public Core Core { get; set; }
38    private Semaphore pauseStopSem = new Semaphore(0, 1);
39
40    private Exception currentException;
41    public String CurrentException {
42      get {
43        if (currentException != null) {
44          return currentException.ToString();
45        } else {
46          return string.Empty;
47        }
48      }
49    }
50
51    public ExecutionState ExecutionState {
52      get {
53        return Job != null ? Job.ExecutionState : HeuristicLab.Core.ExecutionState.Stopped;
54      }
55    }
56
57    public TimeSpan ExecutionTime {
58      get {
59        return Job != null ? Job.ExecutionTime : new TimeSpan(0, 0, 0);
60      }
61    }
62
63    public DateTime CreationTime { get; set; }
64
65    /// <param name="serializedJob"></param>
66    /// <param name="collectChildJobs">if true, all child-jobs are downloaded and the job will be resumed.</param>
67    public void Start(byte[] serializedJob) {
68      try {
69        CreationTime = DateTime.Now;
70        Job = PersistenceUtil.Deserialize<IJob>(serializedJob);
71
72        RegisterJobEvents();
73
74        if (Job.CollectChildJobs) {
75          IEnumerable<JobData> childjobs = WcfService.Instance.GetChildJobs(JobId);
76          Job.Resume(childjobs.Select(j => PersistenceUtil.Deserialize<IJob>(j.Data)));
77        } else {
78          Job.Prepare();
79          Job.Start();
80        }
81      }
82      catch (Exception e) {
83        this.currentException = e;
84      }
85    }
86
87    public void Pause() {
88      if (Job == null) {
89        throw new InvalidStateException("Job is null");
90      }
91
92      if (Job.ExecutionState == HeuristicLab.Core.ExecutionState.Started) {
93        try {
94          Job.Pause();
95          //we need to block the pause...
96          pauseStopSem.WaitOne();
97        }
98        catch (Exception ex) {
99          SlaveClientCom.Instance.ClientCom.LogMessage("Error pausing job:" + ex.ToString());
100        }
101      }
102    }
103
104    public void Stop() {
105      if (Job == null) {
106        throw new InvalidStateException("Job is null");
107      }
108      wasJobAborted = true;
109
110      if ((ExecutionState == ExecutionState.Started) || (ExecutionState == ExecutionState.Paused)) {
111        try {
112          Job.Stop();
113          pauseStopSem.WaitOne();
114        }
115        catch (Exception ex) {
116          SlaveClientCom.Instance.ClientCom.LogMessage("Error stopping job:" + ex.ToString());
117        }
118      }
119    }
120
121    private void RegisterJobEvents() {
122      Job.JobStopped += new EventHandler(Job_JobStopped);
123      Job.JobFailed += new EventHandler(Job_JobFailed);
124      Job.NewChildJob += new EventHandler<EventArgs<IJob>>(Job_NewChildJob);
125      Job.WaitForChildJobs += new EventHandler(Job_WaitForChildJobs);
126      Job.DeleteChildJobs += new EventHandler(Job_DeleteChildJobs);
127      Job.JobPaused += new EventHandler(Job_JobPaused);
128    }
129
130    private void DeregisterJobEvents() {
131      Job.JobStopped -= new EventHandler(Job_JobStopped);
132      Job.JobFailed -= new EventHandler(Job_JobFailed);
133      Job.NewChildJob -= new EventHandler<EventArgs<IJob>>(Job_NewChildJob);
134      Job.WaitForChildJobs -= new EventHandler(Job_WaitForChildJobs);
135      Job.DeleteChildJobs -= new EventHandler(Job_DeleteChildJobs);
136      Job.JobPaused -= new EventHandler(Job_JobPaused);
137    }
138
139    private List<Guid> FindPluginsNeeded(IJob obj) {
140      List<Guid> guids = new List<Guid>();
141      foreach (IPluginDescription desc in PluginUtil.GetDeclaringPlugins(obj)) {
142      }
143      throw new NotImplementedException("FindPluginsNeeded for Job_NewChildJob");
144
145      return guids;
146    }
147
148    private void Job_NewChildJob(object sender, EventArgs<IJob> e) {
149      JobData childJobData = new JobData();
150      childJobData.Data = PersistenceUtil.Serialize(e.Value);
151
152      Job childJob = new Job();
153      childJob.CoresNeeded = 1;
154      childJob.MemoryNeeded = 0;
155      childJob.PluginsNeededIds = FindPluginsNeeded(e.Value);
156
157      //TODO: is return value needed?
158      WcfService.Instance.AddChildJob(this.JobId, childJob, childJobData);
159    }
160
161    private void Job_WaitForChildJobs(object sender, EventArgs e) {
162      // Pause the job and send it back to the hive. The server will awake it when all child-jobs are finished
163      this.Job.CollectChildJobs = true;
164
165      JobData jdata = new JobData();
166      jdata.Data = PersistenceUtil.Serialize(Job);
167      jdata.JobId = this.JobId;
168
169      Core.PauseWaitJob(jdata);
170    }
171
172    private void Job_DeleteChildJobs(object sender, EventArgs e) {
173      WcfService.Instance.DeleteChildJobs(JobId);
174    }
175
176    private void Job_JobFailed(object sender, EventArgs e) {
177      //TODO: get exception to client
178      HeuristicLab.Common.EventArgs<Exception> ex = (HeuristicLab.Common.EventArgs<Exception>)e;
179      currentException = ex.Value;
180      Core.EnqueueExecutorMessage(Core.SendFinishedJob, JobId);
181    }
182
183    private void Job_JobStopped(object sender, EventArgs e) {
184      if (wasJobAborted) {
185        pauseStopSem.Release();
186      } else {
187        //it's a clean and finished job, so send it
188        Core.EnqueueExecutorMessage(Core.SendFinishedJob, JobId);
189      }
190    }
191
192    public JobData GetFinishedJob() {
193      if (Job == null) {
194        throw new InvalidStateException("Job is null");
195      }
196
197      if (Job.ExecutionState == HeuristicLab.Core.ExecutionState.Started) {
198        try {
199          Job.Stop();
200          wasJobAborted = true;
201          pauseStopSem.WaitOne();
202        }
203        catch (Exception ex) {
204          SlaveClientCom.Instance.ClientCom.LogMessage("Error stopping job:" + ex.ToString());
205        }
206      }
207
208      return GetJob();
209    }
210
211
212    public JobData GetPausedJob() {
213      if (Job.ExecutionState != HeuristicLab.Core.ExecutionState.Paused) {
214        throw new Exception("Executor: Job has to be paused before fetching results.");
215      }
216      return GetJob();
217    }
218
219    private void Job_JobPaused(object sender, EventArgs e) {
220      pauseStopSem.Release();
221    }
222
223    private JobData GetJob() {
224      if (Job.ExecutionState == HeuristicLab.Core.ExecutionState.Started) {
225        throw new InvalidStateException("Job is still running");
226      } else {
227        JobData jdata = new JobData();
228        jdata.Data = PersistenceUtil.Serialize(Job);
229        jdata.JobId = JobId;
230        return jdata;
231      }
232    }
233
234    public Executor() {
235    }
236
237    public void Dispose() {
238      if (Job != null)
239        DeregisterJobEvents();
240      Job = null;
241    }
242  }
243}
Note: See TracBrowser for help on using the repository browser.