Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveJobClient.cs @ 5786

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

#1233

  • implemented correct numbering of BatchRuns
  • improvements in ExperimentManager
  • fixed bug in server (jobs were scheduled multiple times)
  • added exception handling for task in slave
  • improved timeout handling of jobs (LifecycleManager)
File size: 27.3 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.Drawing;
25using System.Linq;
26using HeuristicLab.Clients.Hive.Jobs;
27using HeuristicLab.Collections;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Optimization;
31using HeuristicLab.PluginInfrastructure;
32
33namespace HeuristicLab.Clients.Hive {
34
35  [Item("Hive Job", "Represents a hive job.")]
36  public class HiveJob : NamedItem, IItemTree {
37    private static object locker = new object();
38
39    public override Image ItemImage {
40      get {
41        if (job.Id == Guid.Empty) { // not yet uploaded
42          return HeuristicLab.Common.Resources.VSImageLibrary.Event;
43        } else {
44          if (job.State == JobState.Waiting) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
45          else if (job.State == JobState.Calculating) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
46          else if (job.State == JobState.Transferring) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
47          else if (job.State == JobState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
48          else if (job.State == JobState.Aborted) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
49          else if (job.State == JobState.Failed) return HeuristicLab.Common.Resources.VSImageLibrary.Error;
50          else if (job.State == JobState.Finished) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
51          else return HeuristicLab.Common.Resources.VSImageLibrary.Event;
52        }
53      }
54    }
55
56    private Job job;
57    public Job Job {
58      get { return job; }
59      set {
60        if (job != value) {
61          job = value;
62          OnJobChanged();
63          OnToStringChanged();
64          OnItemImageChanged();
65        }
66      }
67    }
68
69    private OptimizerJob optimizerJob;
70    public OptimizerJob OptimizerJob {
71      get { return optimizerJob; }
72      private set {
73        if (optimizerJob != null && syncJobsWithOptimizers) {
74          this.childHiveJobs.Clear();
75        }
76        if (optimizerJob != value) {
77          DergisterOptimizerEvents();
78          optimizerJob = value;
79          //if (optimizerJob.ExecutionState == ExecutionState.Stopped) {
80          //  IsFinishedOptimizerDownloaded = true;
81          //}
82          RegisterOptimizerEvents();
83          OnOptimizerJobChanged();
84        }
85      }
86    }
87
88    private ItemList<HiveJob> childHiveJobs;
89    public ReadOnlyItemList<HiveJob> ChildHiveJobs {
90      get { return childHiveJobs.AsReadOnly(); }
91    }
92
93    //private bool isFinishedOptimizerDownloaded;
94    //public bool IsFinishedOptimizerDownloaded {
95    //  get { return isFinishedOptimizerDownloaded; }
96    //  set {
97    //    if (isFinishedOptimizerDownloaded != value) {
98    //      isFinishedOptimizerDownloaded = value;
99    //      OnIsFinishedOptimizerDownloadedChanged();
100    //    }
101    //  }
102    //}
103
104    private bool syncJobsWithOptimizers = true;
105
106    public HiveJob() {
107      this.Job = new Job() {
108        CoresNeeded = 1,
109        MemoryNeeded = 0
110      };
111      job.State = JobState.Offline;
112      this.childHiveJobs = new ItemList<HiveJob>();
113      syncJobsWithOptimizers = true;
114      RegisterChildHiveJobEvents();
115    }
116
117    public HiveJob(OptimizerJob optimizerJob, bool autoCreateChildHiveJobs)
118      : this() {
119      this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
120      this.OptimizerJob = optimizerJob;
121      this.syncJobsWithOptimizers = true;
122    }
123
124    public HiveJob(IOptimizer optimizer)
125      : this() {
126      this.OptimizerJob = new OptimizerJob(optimizer);
127    }
128
129    public HiveJob(Job job, JobData jobData, bool autoCreateChildHiveJobs) {
130      this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
131      this.Job = job;
132      try {
133        this.OptimizerJob = PersistenceUtil.Deserialize<OptimizerJob>(jobData.Data);
134      }
135      catch {
136        this.OptimizerJob = null;
137      }
138      this.childHiveJobs = new ItemList<HiveJob>();
139      this.syncJobsWithOptimizers = true;
140      RegisterChildHiveJobEvents();
141    }
142
143    protected HiveJob(HiveJob original, Cloner cloner)
144      : base(original, cloner) {
145      this.Job = cloner.Clone(original.job);
146      this.OptimizerJob = cloner.Clone(original.OptimizerJob);
147    }
148    public override IDeepCloneable Clone(Cloner cloner) {
149      return new HiveJob(this, cloner);
150    }
151
152    /// <summary>
153    /// if this.Optimizer is an experiment
154    ///   Uses the child-optimizers of this.HiveJob and creates HiveJob-childs
155    /// if this.Optimizer is a batchrun
156    ///   Creates a number of child-jobs according to repetitions
157    /// </summary>
158    private void UpdateChildHiveJobs() {
159      if (Job != null && syncJobsWithOptimizers) {
160        if (!OptimizerJob.ComputeInParallel) {
161          this.childHiveJobs.Clear();
162        } else {
163          if (OptimizerJob.Optimizer is Optimization.Experiment) {
164            Optimization.Experiment experiment = (Optimization.Experiment)OptimizerJob.Optimizer;
165            foreach (IOptimizer childOpt in experiment.Optimizers) {
166              this.childHiveJobs.Add(new HiveJob(childOpt));
167            }
168          } else if (OptimizerJob.Optimizer is Optimization.BatchRun) {
169            Optimization.BatchRun batchRun = OptimizerJob.OptimizerAsBatchRun;
170            if (batchRun.Optimizer != null) {
171              while (this.childHiveJobs.Count < batchRun.Repetitions) {
172                this.childHiveJobs.Add(new HiveJob(batchRun.Optimizer));
173              }
174              while (this.childHiveJobs.Count > batchRun.Repetitions) {
175                this.childHiveJobs.Remove(this.childHiveJobs.Last());
176              }
177            }
178          }
179        }
180      }
181    }
182
183    private void RegisterOptimizerEvents() {
184      if (OptimizerJob != null) {
185        if (OptimizerJob.Optimizer is Optimization.Experiment) {
186          Optimization.Experiment experiment = OptimizerJob.OptimizerAsExperiment;
187          experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
188          experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
189          experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
190          experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
191        } else if (OptimizerJob.Optimizer is Optimization.BatchRun) {
192          Optimization.BatchRun batchRun = OptimizerJob.OptimizerAsBatchRun;
193          batchRun.RepetitionsChanged += new EventHandler(batchRun_RepetitionsChanged);
194          batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
195        }
196        OptimizerJob.ComputeInParallelChanged += new EventHandler(OptimizerJob_ComputeInParallelChanged);
197        OptimizerJob.ToStringChanged += new EventHandler(OptimizerJob_ToStringChanged);
198      }
199    }
200    private void DergisterOptimizerEvents() {
201      if (OptimizerJob != null) {
202        if (OptimizerJob.Optimizer is Optimization.Experiment) {
203          Optimization.Experiment experiment = OptimizerJob.OptimizerAsExperiment;
204          experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
205          experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
206          experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
207          experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
208        } else if (OptimizerJob.Optimizer is Optimization.BatchRun) {
209          Optimization.BatchRun batchRun = OptimizerJob.OptimizerAsBatchRun;
210          batchRun.RepetitionsChanged -= new EventHandler(batchRun_RepetitionsChanged);
211          batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
212        }
213        OptimizerJob.ComputeInParallelChanged -= new EventHandler(OptimizerJob_ComputeInParallelChanged);
214        OptimizerJob.ToStringChanged -= new EventHandler(OptimizerJob_ToStringChanged);
215      }
216    }
217
218    private void RegisterChildHiveJobEvents() {
219      this.childHiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsAdded);
220      this.childHiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsRemoved);
221      this.childHiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnCollectionReset);
222    }
223    private void DeregisterChildHiveJobEvents() {
224      this.childHiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsAdded);
225      this.childHiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsRemoved);
226      this.childHiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnCollectionReset);
227    }
228
229    private void batchRun_OptimizerChanged(object sender, EventArgs e) {
230      if (syncJobsWithOptimizers) {
231        UpdateChildHiveJobs();
232      }
233    }
234
235    private void batchRun_RepetitionsChanged(object sender, EventArgs e) {
236      if (syncJobsWithOptimizers) {
237        UpdateChildHiveJobs();
238      }
239    }
240
241    private void OptimizerJob_ToStringChanged(object sender, EventArgs e) {
242      this.OnToStringChanged();
243    }
244
245    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
246      if (syncJobsWithOptimizers && this.OptimizerJob.ComputeInParallel) {
247        foreach (var item in e.Items) {
248          if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
249            this.childHiveJobs.Add(new HiveJob(item.Value));
250          }
251        }
252      }
253    }
254    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
255      if (syncJobsWithOptimizers && this.OptimizerJob.ComputeInParallel) {
256        foreach (var item in e.OldItems) {
257          this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
258        }
259        foreach (var item in e.Items) {
260          if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
261            this.childHiveJobs.Add(new HiveJob(item.Value));
262          }
263        }
264      }
265    }
266    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
267      if (syncJobsWithOptimizers && this.OptimizerJob.ComputeInParallel) {
268        foreach (var item in e.Items) {
269          this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
270        }
271      }
272    }
273    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
274      if (syncJobsWithOptimizers && this.OptimizerJob.ComputeInParallel) {
275        foreach (var item in e.Items) {
276          this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
277        }
278      }
279    }
280
281    private void OptimizerJob_ComputeInParallelChanged(object sender, EventArgs e) {
282      if (OptimizerJob != null && syncJobsWithOptimizers) {
283        this.UpdateChildHiveJobs();
284      }
285    }
286
287    public void AddChildHiveJob(HiveJob hiveJob) {
288      this.childHiveJobs.Add(hiveJob);
289      syncJobsWithOptimizers = false;
290      if (this.OptimizerJob != null && hiveJob.OptimizerJob != null) {
291        if (this.OptimizerJob.Optimizer is Optimization.Experiment) {
292          if (!this.OptimizerJob.OptimizerAsExperiment.Optimizers.Contains(hiveJob.OptimizerJob.Optimizer)) {
293            UpdateOptimizerInExperiment(this.OptimizerJob.OptimizerAsExperiment, hiveJob.OptimizerJob);
294          }
295        } else if (this.OptimizerJob.Optimizer is Optimization.BatchRun) {
296          UpdateOptimizerInBatchRun(this.OptimizerJob.OptimizerAsBatchRun, hiveJob.OptimizerJob);
297        }
298      }
299      syncJobsWithOptimizers = true;
300    }
301
302    /// <summary>
303    /// if this.Optimizer is Experiment
304    ///   replace the child-optimizer in the experiment
305    /// if this.Optimizer is BatchRun
306    ///   add the runs from the optimizerJob to the batchrun and replace the Optimizer
307    /// </summary>
308    public void UpdateChildOptimizer(OptimizerJob optimizerJob, Guid childJobId) {
309      syncJobsWithOptimizers = false; // don't sync with optimizers during this method
310      bool childIsFinishedOptimizerDownloaded = false;
311
312      if (this.OptimizerJob != null && this.OptimizerJob.Optimizer != null) {
313        if (this.OptimizerJob.Optimizer is Optimization.Experiment) {
314          UpdateOptimizerInExperiment(this.OptimizerJob.OptimizerAsExperiment, optimizerJob);
315          childIsFinishedOptimizerDownloaded = true;
316        } else if (this.OptimizerJob.Optimizer is Optimization.BatchRun) {
317          UpdateOptimizerInBatchRun(this.OptimizerJob.OptimizerAsBatchRun, optimizerJob);
318          if (this.OptimizerJob.OptimizerAsBatchRun.Repetitions == this.OptimizerJob.Optimizer.Runs.Count) {
319            childIsFinishedOptimizerDownloaded = true;
320          }
321        } else {
322          childIsFinishedOptimizerDownloaded = optimizerJob.Optimizer.ExecutionState == ExecutionState.Stopped;
323        }
324      }
325
326      HiveJob child = this.ChildHiveJobs.Single(j => j.Job.Id == childJobId);
327      if (!optimizerJob.ComputeInParallel) {
328        child.syncJobsWithOptimizers = false;
329        child.OptimizerJob = optimizerJob;
330        child.syncJobsWithOptimizers = true;
331      }
332      if (childIsFinishedOptimizerDownloaded) {
333        //child.IsFinishedOptimizerDownloaded = true; // todo: clean up with childIsFinishedOptimizerDownloaded
334      }
335      syncJobsWithOptimizers = true;
336    }
337
338    /// <summary>
339    /// Adds the runs from the optimizerJob to the batchrun and replaces the Optimizer
340    /// Sideeffect: the optimizerJob.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
341    /// </summary>
342    private void UpdateOptimizerInBatchRun(BatchRun batchRun, OptimizerJob optimizerJob) {
343      if (batchRun.Optimizer == null) {
344        batchRun.Optimizer = (IOptimizer)optimizerJob.Optimizer; // only set the first optimizer as Optimizer. if every time the Optimizer would be set, the runs would be cleared each time
345      }
346      foreach (IRun run in optimizerJob.Optimizer.Runs) {
347        if (!batchRun.Runs.Contains(run)) {
348          run.Name = GetNewRunName(run, batchRun.Runs);
349          batchRun.Runs.Add(run);
350        }
351      }
352    }
353
354    /// <summary>
355    /// Parses the run numbers out of runs and renames the run to the next number
356    /// </summary>
357    private static string GetNewRunName(IRun run, RunCollection runs) {
358      int idx = run.Name.IndexOf("Run ") + 4;
359
360      if (idx == -1 || runs.Count == 0)
361        return run.Name;
362
363      int maxRunNumber = int.MinValue;
364      foreach (IRun r in runs) {
365        int number = GetRunNumber(r.Name);
366        maxRunNumber = Math.Max(maxRunNumber, number);
367      }
368
369      return run.Name.Substring(0, idx) + (maxRunNumber + 1).ToString();
370    }
371
372    /// <summary>
373    /// Parses the number of a Run out of its name. Example "Genetic Algorithm Run 3" -> 3
374    /// </summary>
375    private static int GetRunNumber(string runName) {
376      int idx = runName.IndexOf("Run ") + 4;
377      if (idx == -1) {
378        return 0;
379      } else {
380        return int.Parse(runName.Substring(idx, runName.Length - idx));
381      }
382    }
383
384    /// <summary>
385    /// replace the child-optimizer in the experiment
386    /// Sideeffect: the optimizerJob.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
387    /// </summary>
388    private void UpdateOptimizerInExperiment(Optimization.Experiment experiment, OptimizerJob optimizerJob) {
389      if (optimizerJob.IndexInParentOptimizerList < 0)
390        throw new IndexOutOfRangeException("IndexInParentOptimizerList must be equal or greater than zero! The Job is invalid and the optimizer-tree cannot be reassembled.");
391
392      while (experiment.Optimizers.Count < optimizerJob.IndexInParentOptimizerList) {
393        experiment.Optimizers.Add(new UserDefinedAlgorithm("Placeholder")); // add dummy-entries to Optimizers so that its possible to insert the optimizerJob at the correct position
394      }
395      if (experiment.Optimizers.Count < optimizerJob.IndexInParentOptimizerList + 1) {
396        experiment.Optimizers.Add(optimizerJob.Optimizer);
397      } else {
398        // if ComputeInParallel==true, don't replace the optimizer (except it is still a Placeholder)
399        // this is because Jobs with ComputeInParallel get submitted to hive with their child-optimizers deleted
400        if (!optimizerJob.ComputeInParallel || experiment.Optimizers[optimizerJob.IndexInParentOptimizerList].Name == "Placeholder") {
401          experiment.Optimizers[optimizerJob.IndexInParentOptimizerList] = optimizerJob.Optimizer;
402        }
403      }
404    }
405
406    /// <summary>
407    /// Sets the IndexInParentOptimizerList property of the OptimizerJob
408    /// according to the position in the OptimizerList of the parentHiveJob.Job
409    /// Recursively updates all the child-jobs as well
410    /// </summary>
411    internal void SetIndexInParentOptimizerList(HiveJob parentHiveJob) {
412      if (parentHiveJob != null) {
413        if (parentHiveJob.OptimizerJob.Optimizer is Optimization.Experiment) {
414          this.OptimizerJob.IndexInParentOptimizerList = parentHiveJob.OptimizerJob.OptimizerAsExperiment.Optimizers.IndexOf(this.OptimizerJob.Optimizer);
415        } else if (parentHiveJob.OptimizerJob.Optimizer is Optimization.BatchRun) {
416          this.OptimizerJob.IndexInParentOptimizerList = 0;
417        } else {
418          throw new NotSupportedException("Only Experiment and BatchRuns are supported");
419        }
420      }
421      foreach (HiveJob child in childHiveJobs) {
422        child.SetIndexInParentOptimizerList(this);
423      }
424    }
425
426    public override string ToString() {
427      if (optimizerJob != null) {
428        return optimizerJob.ToString();
429      } else {
430        return base.ToString();
431      }
432    }
433
434    public void UpdateFromLightweightJob(LightweightJob lightweightJob) {
435      if (lightweightJob != null) {
436        job.Id = lightweightJob.Id;
437        job.ParentJobId = lightweightJob.ParentJobId;
438        job.ExecutionTime = lightweightJob.ExecutionTime;
439        job.State = lightweightJob.State;
440        job.StateLog = new List<StateLog>(lightweightJob.StateLog);
441        job.Command = lightweightJob.Command;
442        job.LastJobDataUpdate = lightweightJob.LastJobDataUpdate;
443       
444        OnJobStateChanged();
445        OnToStringChanged();
446        OnItemImageChanged();
447      }
448    }
449
450    /// <summary>
451    /// Creates a JobData object containing the Job and the IJob-Object as byte[]
452    /// </summary>
453    /// <param name="withoutChildOptimizers">
454    ///   if true the Child-Optimizers will not be serialized (if the job contains an Experiment)
455    /// </param>
456    public JobData GetAsJobData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
457      plugins = new List<IPluginDescription>();
458      if (this.optimizerJob == null || this.optimizerJob.Optimizer == null)
459        return null;
460
461      IEnumerable<Type> usedTypes;
462      byte[] jobByteArray;
463      if (withoutChildOptimizers && this.OptimizerJob.Optimizer is Optimization.Experiment) {
464        OptimizerJob clonedJob = (OptimizerJob)this.OptimizerJob.Clone(); // use a cloned job, so that the childHiveJob don't get confused
465        clonedJob.OptimizerAsExperiment.Optimizers.Clear();
466        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
467      } else if (withoutChildOptimizers && this.OptimizerJob.Optimizer is Optimization.BatchRun) {
468        OptimizerJob clonedJob = (OptimizerJob)this.OptimizerJob.Clone();
469        clonedJob.OptimizerAsBatchRun.Optimizer = null;
470        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
471      } else if (this.OptimizerJob.Optimizer is IAlgorithm) {
472        ((IAlgorithm)this.OptimizerJob.Optimizer).StoreAlgorithmInEachRun = false; // avoid storing the algorithm in runs to reduce size
473        jobByteArray = PersistenceUtil.Serialize(this.OptimizerJob, out usedTypes);
474      } else {
475        jobByteArray = PersistenceUtil.Serialize(this.OptimizerJob, out usedTypes);
476      }
477
478      JobData jobData = new JobData() {
479        JobId = job.Id,
480        Data = jobByteArray
481      };
482
483      CollectDeclaringPlugins(plugins, usedTypes);
484
485      return jobData;
486    }
487
488    private void CollectDeclaringPlugins(List<IPluginDescription> plugins, IEnumerable<Type> usedTypes) {
489      foreach (Type type in usedTypes) {
490        var plugin = ApplicationManager.Manager.GetDeclaringPlugin(type);
491        if (plugin != null && !plugins.Contains(plugin)) {
492          plugins.Add(plugin);
493          CollectPluginDependencies(plugins, plugin);
494        }
495      }
496    }
497
498    private void CollectPluginDependencies(List<IPluginDescription> plugins, IPluginDescription plugin) {
499      if (plugin == null) return;
500      foreach (var dependency in plugin.Dependencies) {
501        if (!plugins.Contains(dependency)) {
502          plugins.Add(dependency);
503          CollectPluginDependencies(plugins, dependency);
504        }
505      }
506    }
507
508    #region Events
509    public event EventHandler JobChanged;
510    private void OnJobChanged() {
511      LogMessage("JobChanged");
512      EventHandler handler = JobChanged;
513      if (handler != null) handler(this, EventArgs.Empty);
514    }
515
516    public event EventHandler JobStateChanged;
517    private void OnJobStateChanged() {
518      LogMessage("JobStateChanged (State: " + this.Job.State + ", ExecutionTime: " + this.Job.ExecutionTime.ToString() + ")");
519      EventHandler handler = JobStateChanged;
520      if (handler != null) handler(this, EventArgs.Empty);
521    }
522
523    public event EventHandler OptimizerJobChanged;
524    private void OnOptimizerJobChanged() {
525      OptimizerJob_ComputeInParallelChanged(this, EventArgs.Empty);
526      var handler = JobChanged;
527      if (handler != null) handler(this, EventArgs.Empty);
528    }
529
530    public event EventHandler IsFinishedOptimizerDownloadedChanged;
531    private void OnIsFinishedOptimizerDownloadedChanged() {
532      var handler = IsFinishedOptimizerDownloadedChanged;
533      if (handler != null) handler(this, EventArgs.Empty);
534    }
535    #endregion
536
537    public void LogMessage(string message) {
538      lock (locker) {
539        if (optimizerJob != null) {
540          optimizerJob.Log.LogMessage(message);
541        }
542      }
543    }
544
545    /// <summary>
546    /// Returns a list of HiveJobs including this and all its child-jobs recursively
547    /// </summary>
548    public IEnumerable<HiveJob> GetAllHiveJobs() {
549      List<HiveJob> jobs = new List<HiveJob>();
550      jobs.Add(this);
551      foreach (HiveJob child in this.ChildHiveJobs) {
552        jobs.AddRange(child.GetAllHiveJobs());
553      }
554      return jobs;
555    }
556
557    public HiveJob GetParentByJobId(Guid jobId) {
558      if (this.ChildHiveJobs.SingleOrDefault(j => j.job.Id == jobId) != null)
559        return this;
560      foreach (HiveJob child in this.childHiveJobs) {
561        HiveJob result = child.GetParentByJobId(jobId);
562        if (result != null)
563          return result;
564      }
565      return null;
566    }
567
568
569    public HiveJob GetChildByOptimizerJob(OptimizerJob optimizerJob) {
570      foreach (var child in ChildHiveJobs) {
571        if (child.OptimizerJob == optimizerJob)
572          return child;
573      }
574      return null;
575    }
576
577
578    public HiveJob GetChildByOptimizer(IOptimizer optimizer) {
579      foreach (var child in ChildHiveJobs) {
580        if (child.OptimizerJob.Optimizer == optimizer)
581          return child;
582      }
583      return null;
584    }
585
586    /// <summary>
587    /// Searches for an HiveJob object with the correct jobId recursively
588    /// </summary>
589    public HiveJob GetHiveJobByJobId(Guid jobId) {
590      if (this.Job.Id == jobId) {
591        return this;
592      } else {
593        foreach (HiveJob child in this.ChildHiveJobs) {
594          HiveJob result = child.GetHiveJobByJobId(jobId);
595          if (result != null)
596            return result;
597        }
598      }
599      return null;
600    }
601
602
603    public void RemoveByJobId(Guid jobId) {
604      IEnumerable<HiveJob> jobs = ChildHiveJobs.Where(j => j.Job.Id == jobId).ToList(); // if Guid.Empty needs to be removed, there could be more than one with this jobId
605      foreach (HiveJob j in jobs) {
606        this.childHiveJobs.Remove(j);
607      }
608      foreach (HiveJob child in ChildHiveJobs) {
609        child.RemoveByJobId(jobId);
610      }
611    }
612
613    public IEnumerable<IItemTree> GetChildItems() {
614      return this.childHiveJobs;
615    }
616
617    #region INotifyObservableCollectionItemsChanged<IItemTree> Members
618
619    public event CollectionItemsChangedEventHandler<IItemTree> CollectionReset;
620    private void OnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
621      var handler = CollectionReset;
622      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
623    }
624
625    public event CollectionItemsChangedEventHandler<IItemTree> ItemsAdded;
626    private void OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
627      var handler = ItemsAdded;
628      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
629    }
630
631    public event CollectionItemsChangedEventHandler<IItemTree> ItemsRemoved;
632    private void OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
633      var handler = ItemsRemoved;
634      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
635    }
636
637    private static CollectionItemsChangedEventArgs<IItemTree> ToCollectionItemsChangedEventArgs(CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
638      return new CollectionItemsChangedEventArgs<IItemTree>(e.Items.Select(x => x.Value), e.OldItems == null ? null : e.OldItems.Select(x => x.Value));
639    }
640    #endregion
641
642    public void Pause() {
643      ServiceLocator.Instance.CallHiveService(s => s.PauseJob(this.job.Id));
644    }
645
646    public void Stop() {
647      ServiceLocator.Instance.CallHiveService(s => s.StopJob(this.job.Id));
648    }
649
650    public void Restart() {
651      ServiceLocator.Instance.CallHiveService(s => s.RestartJob(this.job.Id));
652    }
653  }
654}
Note: See TracBrowser for help on using the repository browser.