Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 5718 was 5718, checked in by cneumuel, 14 years ago

#1233

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