source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveJob.cs @ 6006

Last change on this file since 6006 was 6006, checked in by cneumuel, 9 years ago

#1233

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