Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Manager/JobManager.cs @ 6381

Last change on this file since 6381 was 6381, checked in by cneumuel, 13 years ago

#1233

  • locking for childHiveJobs in OptimizerHiveJob avoid multi threaded access issues
  • added IsPrivileged to gui
  • minor changes
File size: 11.6 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.Collections.Generic;
24using System.Linq;
25using System.Threading;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28
29namespace HeuristicLab.Clients.Hive.SlaveCore {
30
31  /// <summary>
32  /// Holds a list of slave jobs and manages access to this list.
33  /// Forwards events from SlaveJob and forwards commands to SlaveJob.
34  /// </summary>
35  public class JobManager {
36    private static ReaderWriterLockSlim slaveJobsLocker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
37    private Dictionary<Guid, SlaveJob> slaveJobs;
38    private ILog log;
39    private PluginManager pluginManager;
40
41    public int JobCount {
42      get {
43        slaveJobsLocker.EnterReadLock();
44        try {
45          return slaveJobs.Count;
46        }
47        finally { slaveJobsLocker.ExitReadLock(); }
48      }
49    }
50
51    public Guid[] JobIds {
52      get {
53        slaveJobsLocker.EnterReadLock();
54        try {
55          return slaveJobs.Keys.ToArray();
56        }
57        finally { slaveJobsLocker.ExitReadLock(); }
58      }
59    }
60
61    public JobManager(PluginManager pluginCache, ILog log) {
62      this.pluginManager = pluginCache;
63      this.log = log;
64      this.slaveJobs = new Dictionary<Guid, SlaveJob>();
65    }
66
67    #region Job Control methods
68    public void StartJobAsync(Job job, JobData jobData) {
69      SlaveJob slaveJob = null;
70      slaveJobsLocker.EnterUpgradeableReadLock();
71      try {
72        if (slaveJobs.ContainsKey(job.Id)) {
73          SlaveStatusInfo.IncrementExceptionOccured();
74          throw new JobAlreadyRunningException(job.Id);
75        } else {
76          slaveJob = new SlaveJob(pluginManager, job.CoresNeeded, log);
77          AddSlaveJob(job, slaveJob);
78          SlaveStatusInfo.IncrementJobsFetched();
79        }
80      }
81      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
82
83      if (slaveJob != null) {
84        try {
85          slaveJob.StartJobAsync(job, jobData);
86        }
87        catch (Exception) {
88          RemoveSlaveJob(job.Id, slaveJob); // clean up and rethrow
89          slaveJob.DisposeAppDomain();
90          throw;
91        }
92      }
93    }
94
95    public void PauseJobAsync(Guid jobId) {
96      slaveJobsLocker.EnterUpgradeableReadLock();
97      try {
98        if (!slaveJobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);
99        SlaveJob slaveJob = slaveJobs[jobId];
100        slaveJob.PauseJob();
101      }
102      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
103    }
104
105    public void StopJobAsync(Guid jobId) {
106      slaveJobsLocker.EnterUpgradeableReadLock();
107      try {
108        if (!slaveJobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);
109        SlaveJob slaveJob = slaveJobs[jobId];
110        slaveJob.StopJob();
111      }
112      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
113    }
114
115    public void AbortJob(Guid jobId) {
116      SlaveJob slaveJob = null;
117      slaveJobsLocker.EnterUpgradeableReadLock();
118      try {
119        if (!slaveJobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);
120        slaveJob = slaveJobs[jobId];
121        if (!slaveJob.IsPrepared) throw new AppDomainNotCreatedException();
122        RemoveSlaveJob(jobId, slaveJob);
123      }
124      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
125      slaveJob.DisposeAppDomain();
126      SlaveStatusInfo.IncrementJobsAborted();
127      OnJobAborted(slaveJob);
128    }
129
130    public void PauseAllJobsAsync() {
131      slaveJobsLocker.EnterUpgradeableReadLock();
132      try {
133        foreach (var slaveJob in slaveJobs.Values) {
134          slaveJob.PauseJob();
135        }
136      }
137      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
138    }
139
140    public void StopAllJobsAsync() {
141      slaveJobsLocker.EnterUpgradeableReadLock();
142      try {
143        foreach (var slaveJob in slaveJobs.Values) {
144          slaveJob.StopJob();
145        }
146      }
147      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
148    }
149
150    public void AbortAllJobs() {
151      slaveJobsLocker.EnterUpgradeableReadLock();
152      try {
153        foreach (var slaveJob in slaveJobs.Values.ToArray()) {
154          AbortJob(slaveJob.JobId);
155        }
156      }
157      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
158    }
159    #endregion
160
161    #region Add/Remove SlaveJob
162    private void AddSlaveJob(Job job, SlaveJob slaveJob) {
163      slaveJobsLocker.EnterWriteLock();
164      try {
165        slaveJobs.Add(job.Id, slaveJob);
166        RegisterSlaveJobEvents(slaveJob);
167      }
168      finally { slaveJobsLocker.ExitWriteLock(); }
169    }
170
171    private void RemoveSlaveJob(Guid jobId, SlaveJob slaveJob) {
172      slaveJobsLocker.EnterWriteLock();
173      try {
174        slaveJobs.Remove(jobId);
175        DeregisterSlaveJobEvents(slaveJob);
176      }
177      finally { slaveJobsLocker.ExitWriteLock(); }
178    }
179    #endregion
180
181    #region SlaveJob Events
182    private void RegisterSlaveJobEvents(SlaveJob slaveJob) {
183      slaveJob.JobStarted += new EventHandler<EventArgs<Guid>>(slaveJob_JobStarted);
184      slaveJob.JobPaused += new EventHandler<EventArgs<Guid>>(slaveJob_JobPaused);
185      slaveJob.JobStopped += new EventHandler<EventArgs<Guid>>(slaveJob_JobStopped);
186      slaveJob.JobFailed += new EventHandler<EventArgs<Guid, Exception>>(slaveJob_JobFailed);
187      slaveJob.ExceptionOccured += new EventHandler<EventArgs<Guid, Exception>>(slaveJob_ExceptionOccured);
188    }
189
190    private void DeregisterSlaveJobEvents(SlaveJob slaveJob) {
191      slaveJob.JobStarted -= new EventHandler<EventArgs<Guid>>(slaveJob_JobStarted);
192      slaveJob.JobPaused -= new EventHandler<EventArgs<Guid>>(slaveJob_JobPaused);
193      slaveJob.JobStopped -= new EventHandler<EventArgs<Guid>>(slaveJob_JobStopped);
194      slaveJob.JobFailed -= new EventHandler<EventArgs<Guid, Exception>>(slaveJob_JobFailed);
195      slaveJob.ExceptionOccured -= new EventHandler<EventArgs<Guid, Exception>>(slaveJob_ExceptionOccured);
196    }
197
198    private void slaveJob_JobStarted(object sender, EventArgs<Guid> e) {
199      SlaveJob slaveJob;
200      slaveJobsLocker.EnterUpgradeableReadLock();
201      try {
202        slaveJob = slaveJobs[e.Value];
203      }
204      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
205
206      SlaveStatusInfo.IncrementJobsStarted();
207      OnJobStarted(slaveJob);
208    }
209
210    private void slaveJob_JobPaused(object sender, EventArgs<Guid> e) {
211      SlaveJob slaveJob;
212      slaveJobsLocker.EnterUpgradeableReadLock();
213      try {
214        slaveJob = slaveJobs[e.Value];
215        RemoveSlaveJob(e.Value, slaveJob);
216      }
217      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
218
219      JobData jobData = null;
220      try {
221        jobData = slaveJob.GetJobData();
222        if (jobData == null) throw new SerializationException();
223        SlaveStatusInfo.IncrementJobsFinished();
224        OnJobPaused(slaveJob, jobData);
225      }
226      catch (Exception ex) {
227        RemoveSlaveJob(e.Value, slaveJob);
228        SlaveStatusInfo.IncrementJobsFailed();
229        OnJobFailed(slaveJob, jobData, ex);
230      }
231    }
232
233    private void slaveJob_JobStopped(object sender, EventArgs<Guid> e) {
234      SlaveJob slaveJob;
235      slaveJobsLocker.EnterUpgradeableReadLock();
236      try {
237        slaveJob = slaveJobs[e.Value];
238        RemoveSlaveJob(e.Value, slaveJob);
239      }
240      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
241
242      JobData jobData = null;
243      try {
244        jobData = slaveJob.GetJobData();
245        if (jobData == null) throw new SerializationException();
246        SlaveStatusInfo.IncrementJobsFinished();
247        OnJobStopped(slaveJob, jobData);
248      }
249      catch (Exception ex) {
250        RemoveSlaveJob(e.Value, slaveJob);
251        SlaveStatusInfo.IncrementJobsFailed();
252        OnJobFailed(slaveJob, jobData, ex);
253      }
254    }
255
256    private void slaveJob_JobFailed(object sender, EventArgs<Guid, Exception> e) {
257      SlaveJob slaveJob;
258      slaveJobsLocker.EnterUpgradeableReadLock();
259      try {
260        slaveJob = slaveJobs[e.Value];
261        RemoveSlaveJob(e.Value, slaveJob);
262      }
263      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
264
265      JobData jobData = null;
266      try {
267        jobData = slaveJob.GetJobData();
268        if (jobData == null) throw new SerializationException();
269      }
270      catch { /* jobData will be null */ }
271      SlaveStatusInfo.IncrementJobsFailed();
272      OnJobFailed(slaveJob, jobData, e.Value2);
273    }
274
275    private void slaveJob_ExceptionOccured(object sender, EventArgs<Guid, Exception> e) {
276      SlaveJob slaveJob;
277      slaveJobsLocker.EnterUpgradeableReadLock();
278      try {
279        slaveJob = slaveJobs[e.Value];
280        RemoveSlaveJob(e.Value, slaveJob);
281      }
282      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
283
284      SlaveStatusInfo.IncrementExceptionOccured();
285      OnExceptionOccured(slaveJob, e.Value2);
286    }
287    #endregion
288
289    #region EventHandler
290    public event EventHandler<EventArgs<SlaveJob>> JobStarted;
291    private void OnJobStarted(SlaveJob slaveJob) {
292      var handler = JobStarted;
293      if (handler != null) handler(this, new EventArgs<SlaveJob>(slaveJob));
294    }
295
296    public event EventHandler<EventArgs<SlaveJob, JobData>> JobStopped;
297    private void OnJobStopped(SlaveJob slaveJob, JobData jobData) {
298      var handler = JobStopped;
299      if (handler != null) handler(this, new EventArgs<SlaveJob, JobData>(slaveJob, jobData));
300    }
301
302    public event EventHandler<EventArgs<SlaveJob, JobData>> JobPaused;
303    private void OnJobPaused(SlaveJob slaveJob, JobData jobData) {
304      var handler = JobPaused;
305      if (handler != null) handler(this, new EventArgs<SlaveJob, JobData>(slaveJob, jobData));
306    }
307
308    public event EventHandler<EventArgs<Tuple<SlaveJob, JobData, Exception>>> JobFailed;
309    private void OnJobFailed(SlaveJob slaveJob, JobData jobData, Exception exception) {
310      var handler = JobFailed;
311      if (handler != null) handler(this, new EventArgs<Tuple<SlaveJob, JobData, Exception>>(new Tuple<SlaveJob, JobData, Exception>(slaveJob, jobData, exception)));
312    }
313
314    public event EventHandler<EventArgs<SlaveJob, Exception>> ExceptionOccured;
315    private void OnExceptionOccured(SlaveJob slaveJob, Exception exception) {
316      var handler = ExceptionOccured;
317      if (handler != null) handler(this, new EventArgs<SlaveJob, Exception>(slaveJob, exception));
318    }
319
320    public event EventHandler<EventArgs<SlaveJob>> JobAborted;
321    private void OnJobAborted(SlaveJob slaveJob) {
322      var handler = JobAborted;
323      if (handler != null) handler(this, new EventArgs<SlaveJob>(slaveJob));
324    }
325    #endregion
326
327    public Dictionary<Guid, TimeSpan> GetExecutionTimes() {
328      slaveJobsLocker.EnterReadLock();
329      try {
330        return slaveJobs.ToDictionary(x => x.Key, x => x.Value.ExecutionTime);
331      }
332      finally { slaveJobsLocker.ExitReadLock(); }
333    }
334  }
335}
Note: See TracBrowser for help on using the repository browser.