source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HiveJobs/HiveJob.cs @ 6479

Last change on this file since 6479 was 6479, checked in by cneumuel, 8 years ago

#1233

  • finished experiment sharing
  • added role for executing privileged jobs
  • refreshing experiments in experimentManager does not delete already downloaded jobs
  • moved some properties from HiveExperiment into RefreshableHiveExperiment
File size: 18.4 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.ComponentModel;
25using System.Drawing;
26using System.Linq;
27using System.Threading;
28using HeuristicLab.Collections;
29using HeuristicLab.Common;
30using HeuristicLab.Core;
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<HiveJob> {
39    protected static object locker = new object();
40    protected ReaderWriterLockSlim childHiveJobsLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
41
42    public override Image ItemImage {
43      get {
44        if (job.Id == Guid.Empty) { // not yet uploaded
45          return HeuristicLab.Common.Resources.VSImageLibrary.Event;
46        } else {
47          if (job.State == JobState.Waiting) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
48          else if (job.State == JobState.Calculating) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
49          else if (job.State == JobState.Transferring) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
50          else if (job.State == JobState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
51          else if (job.State == JobState.Aborted) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
52          else if (job.State == JobState.Failed) return HeuristicLab.Common.Resources.VSImageLibrary.Error;
53          else if (job.State == JobState.Finished) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
54          else return HeuristicLab.Common.Resources.VSImageLibrary.Event;
55        }
56      }
57    }
58
59    [Storable]
60    protected Job job;
61    public Job Job {
62      get { return job; }
63      set {
64        if (job != value) {
65          DeregisterJobEvents();
66          job = value;
67          RegisterJobEvents();
68          IsFinishedJobDownloaded = false;
69          OnJobChanged();
70          OnToStringChanged();
71          OnItemImageChanged();
72        }
73
74      }
75    }
76
77    [Storable]
78    protected ItemJob itemJob;
79    public ItemJob ItemJob {
80      get { return itemJob; }
81      set {
82        if (itemJob != null && syncJobsWithOptimizers) {
83          this.childHiveJobs.Clear();
84        }
85        if (itemJob != value) {
86          DergisterItemJobEvents();
87          itemJob = value;
88          RegisterItemJobEvents();
89          OnItemJobChanged();
90          IsFinishedJobDownloaded = true;
91        }
92      }
93    }
94
95    // job downloaded since last status change
96    [Storable]
97    private bool isFinishedJobDownloaded = false;
98    public bool IsFinishedJobDownloaded {
99      get { return isFinishedJobDownloaded; }
100      set {
101        if (value != isFinishedJobDownloaded) {
102          this.isFinishedJobDownloaded = value;
103          OnIsFinishedJobDownloadedChanged();
104        }
105      }
106    }
107
108    public bool IsDownloading { get; set; }
109
110    // if true, all control buttons should be enabled. otherwise disabled
111    private bool isControllable = true;
112    public bool IsControllable {
113      get { return isControllable; }
114      set {
115        if (value != isControllable) {
116          isControllable = value;
117          OnIsControllableChanged();
118          childHiveJobsLock.EnterReadLock();
119          try {
120            foreach (var hiveJob in childHiveJobs) {
121              hiveJob.IsControllable = value;
122            }
123          }
124          finally {
125            childHiveJobsLock.ExitReadLock();
126          }
127        }
128      }
129    }
130
131    [Storable]
132    protected ItemList<HiveJob> childHiveJobs;
133    public virtual ReadOnlyItemList<HiveJob> ChildHiveJobs {
134      get {
135        childHiveJobsLock.EnterReadLock();
136        try {
137          return childHiveJobs.AsReadOnly();
138        }
139        finally { childHiveJobsLock.ExitReadLock(); }
140      }
141    }
142
143    [Storable]
144    protected bool syncJobsWithOptimizers = true;
145
146    public StateLogList StateLog {
147      get { return new StateLogList(this.job.StateLog); }
148    }
149
150    public StateLogListList ChildStateLogList {
151      get { return new StateLogListList(this.childHiveJobs.Select(x => x.StateLog)); }
152    }
153
154    #region Constructors and Cloning
155    public HiveJob() {
156      this.Job = new Job() { CoresNeeded = 1, MemoryNeeded = 0 };
157      job.State = JobState.Offline;
158      this.childHiveJobs = new ItemList<HiveJob>();
159      syncJobsWithOptimizers = true;
160      RegisterChildHiveJobEvents();
161    }
162
163    public HiveJob(ItemJob itemJob, bool autoCreateChildHiveJobs)
164      : this() {
165      this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
166      this.ItemJob = itemJob;
167      this.syncJobsWithOptimizers = true;
168    }
169
170    public HiveJob(Job job, JobData jobData, bool autoCreateChildHiveJobs) {
171      this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
172      this.Job = job;
173      try {
174        this.ItemJob = PersistenceUtil.Deserialize<ItemJob>(jobData.Data);
175      }
176      catch {
177        this.ItemJob = null;
178      }
179      this.childHiveJobs = new ItemList<HiveJob>();
180      this.syncJobsWithOptimizers = true;
181      RegisterChildHiveJobEvents();
182    }
183
184    protected HiveJob(HiveJob original, Cloner cloner)
185      : base(original, cloner) {
186      this.Job = cloner.Clone(original.job);
187      this.ItemJob = cloner.Clone(original.ItemJob);
188      original.childHiveJobsLock.EnterReadLock();
189      try {
190        this.childHiveJobs = cloner.Clone(original.childHiveJobs);
191      }
192      finally { original.childHiveJobsLock.ExitReadLock(); }
193      this.syncJobsWithOptimizers = original.syncJobsWithOptimizers;
194      this.isFinishedJobDownloaded = original.isFinishedJobDownloaded;
195    }
196    public override IDeepCloneable Clone(Cloner cloner) {
197      return new HiveJob(this, cloner);
198    }
199    #endregion
200
201    protected virtual void UpdateChildHiveJobs() { }
202
203    protected virtual void RegisterItemJobEvents() {
204      if (ItemJob != null) {
205        ItemJob.ComputeInParallelChanged += new EventHandler(ItemJob_ComputeInParallelChanged);
206        ItemJob.ToStringChanged += new EventHandler(ItemJob_ToStringChanged);
207      }
208    }
209    protected virtual void DergisterItemJobEvents() {
210      if (ItemJob != null) {
211        ItemJob.ComputeInParallelChanged -= new EventHandler(ItemJob_ComputeInParallelChanged);
212        ItemJob.ToStringChanged -= new EventHandler(ItemJob_ToStringChanged);
213      }
214    }
215
216    protected virtual void RegisterChildHiveJobEvents() {
217      this.childHiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsAdded);
218      this.childHiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsRemoved);
219      this.childHiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnCollectionReset);
220    }
221    protected virtual void DeregisterChildHiveJobEvents() {
222      this.childHiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsAdded);
223      this.childHiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsRemoved);
224      this.childHiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnCollectionReset);
225    }
226
227    protected virtual void ItemJob_ToStringChanged(object sender, EventArgs e) {
228      this.OnToStringChanged();
229    }
230
231    protected virtual void ItemJob_ComputeInParallelChanged(object sender, EventArgs e) {
232      if (ItemJob != null && syncJobsWithOptimizers) {
233        this.UpdateChildHiveJobs();
234      }
235    }
236
237    public virtual void AddChildHiveJob(HiveJob hiveJob) {
238      childHiveJobsLock.EnterWriteLock();
239      try {
240        this.childHiveJobs.Add(hiveJob);
241      }
242      finally { childHiveJobsLock.ExitWriteLock(); }
243    }
244
245    public override string ToString() {
246      if (itemJob != null && itemJob.Item != null) {
247        return itemJob.ToString();
248      } else {
249        return Job.Id.ToString();
250      }
251    }
252
253    public virtual void UpdateFromLightweightJob(LightweightJob lightweightJob) {
254      if (lightweightJob != null) {
255        job.Id = lightweightJob.Id;
256        job.ParentJobId = lightweightJob.ParentJobId;
257        job.ExecutionTime = lightweightJob.ExecutionTime;
258        job.State = lightweightJob.State;
259        job.StateLog = new List<StateLog>(lightweightJob.StateLog);
260        job.Command = lightweightJob.Command;
261
262        OnJobStateChanged();
263        OnToStringChanged();
264        OnItemImageChanged();
265        OnStateLogChanged();
266      }
267    }
268
269    /// <summary>
270    /// Creates a JobData object containing the Job and the IJob-Object as byte[]
271    /// </summary>
272    /// <param name="withoutChildOptimizers">
273    ///   if true the Child-Optimizers will not be serialized (if the job contains an Experiment)
274    /// </param>
275    public virtual JobData GetAsJobData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
276      plugins = new List<IPluginDescription>();
277      if (this.itemJob == null)
278        return null;
279
280      IEnumerable<Type> usedTypes;
281      byte[] jobByteArray = PersistenceUtil.Serialize(this.ItemJob, out usedTypes);
282      JobData jobData = new JobData() { JobId = job.Id, Data = jobByteArray };
283      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
284      return jobData;
285    }
286
287    #region Event Handler
288    public event EventHandler JobChanged;
289    private void OnJobChanged() {
290      EventHandler handler = JobChanged;
291      if (handler != null) handler(this, EventArgs.Empty);
292    }
293
294    public event EventHandler JobStateChanged;
295    private void OnJobStateChanged() {
296      EventHandler handler = JobStateChanged;
297      if (handler != null) handler(this, EventArgs.Empty);
298    }
299
300    public event EventHandler ItemJobChanged;
301    private void OnItemJobChanged() {
302      ItemJob_ComputeInParallelChanged(this, EventArgs.Empty);
303      var handler = ItemJobChanged;
304      if (handler != null) handler(this, EventArgs.Empty);
305    }
306
307    public event EventHandler IsFinishedJobDownloadedChanged;
308    private void OnIsFinishedJobDownloadedChanged() {
309      var handler = IsFinishedJobDownloadedChanged;
310      if (handler != null) handler(this, EventArgs.Empty);
311    }
312
313    public event EventHandler StateLogChanged;
314    private void OnStateLogChanged() {
315      var handler = StateLogChanged;
316      if (handler != null) handler(this, EventArgs.Empty);
317    }
318
319    public event EventHandler IsControllableChanged;
320    private void OnIsControllableChanged() {
321      var handler = IsControllableChanged;
322      if (handler != null) handler(this, EventArgs.Empty);
323    }
324
325    private void RegisterJobEvents() {
326      if (job != null)
327        job.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
328    }
329
330    private void DeregisterJobEvents() {
331      if (job != null)
332        job.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
333    }
334
335    private void job_PropertyChanged(object sender, PropertyChangedEventArgs e) {
336      if (e.PropertyName == "State") {
337        IsFinishedJobDownloaded = false;
338      }
339    }
340    #endregion
341
342    /// <summary>
343    /// Returns a list of HiveJobs including this and all its child-jobs recursively
344    /// </summary>
345    public IEnumerable<HiveJob> GetAllHiveJobs() {
346      childHiveJobsLock.EnterReadLock();
347      try {
348        var jobs = new List<HiveJob>();
349        jobs.Add(this);
350        foreach (HiveJob child in this.childHiveJobs) {
351          jobs.AddRange(child.GetAllHiveJobs());
352        }
353        return jobs;
354      }
355      finally { childHiveJobsLock.ExitReadLock(); }
356    }
357
358    public HiveJob GetParentByJobId(Guid jobId) {
359      childHiveJobsLock.EnterReadLock();
360      try {
361        if (this.ChildHiveJobs.SingleOrDefault(j => j.job.Id == jobId) != null)
362          return this;
363        foreach (HiveJob child in this.childHiveJobs) {
364          HiveJob result = child.GetParentByJobId(jobId);
365          if (result != null)
366            return result;
367        }
368        return null;
369      }
370      finally { childHiveJobsLock.ExitWriteLock(); }
371    }
372
373    /// <summary>
374    /// Searches for an HiveJob object with the correct jobId recursively
375    /// </summary>
376    public HiveJob GetHiveJobByJobId(Guid jobId) {
377      if (this.Job.Id == jobId) {
378        return this;
379      } else {
380        childHiveJobsLock.EnterReadLock();
381        try {
382          foreach (HiveJob child in this.childHiveJobs) {
383            HiveJob result = child.GetHiveJobByJobId(jobId);
384            if (result != null)
385              return result;
386          }
387        }
388        finally { childHiveJobsLock.ExitReadLock(); }
389      }
390      return null;
391    }
392
393    public void RemoveByJobId(Guid jobId) {
394      childHiveJobsLock.EnterWriteLock();
395      try {
396        IEnumerable<HiveJob> jobs = childHiveJobs.Where(j => j.Job.Id == jobId).ToList();
397        foreach (HiveJob j in jobs) {
398          this.childHiveJobs.Remove(j);
399        }
400        foreach (HiveJob child in childHiveJobs) {
401          child.RemoveByJobId(jobId);
402        }
403      }
404      finally { childHiveJobsLock.ExitWriteLock(); }
405    }
406
407    public IEnumerable<IItemTree<HiveJob>> GetChildItems() {
408      return this.ChildHiveJobs;
409    }
410
411    #region INotifyObservableCollectionItemsChanged<IItemTree> Members
412
413    public event CollectionItemsChangedEventHandler<IItemTree<HiveJob>> CollectionReset;
414    private void OnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
415      foreach (var item in e.Items) {
416        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
417      }
418      var handler = CollectionReset;
419      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
420    }
421
422    public event CollectionItemsChangedEventHandler<IItemTree<HiveJob>> ItemsAdded;
423    private void OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
424      foreach (var item in e.Items) {
425        item.Value.StateLogChanged += new EventHandler(ChildHiveJob_StateLogChanged);
426        item.Value.IsControllable = this.IsControllable;
427      }
428      var handler = ItemsAdded;
429      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
430    }
431
432    public event CollectionItemsChangedEventHandler<IItemTree<HiveJob>> ItemsRemoved;
433    private void OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
434      foreach (var item in e.Items) {
435        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
436      }
437      var handler = ItemsRemoved;
438      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
439    }
440
441    private static CollectionItemsChangedEventArgs<IItemTree<HiveJob>> ToCollectionItemsChangedEventArgs(CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
442      return new CollectionItemsChangedEventArgs<IItemTree<HiveJob>>(e.Items.Select(x => x.Value), e.OldItems == null ? null : e.OldItems.Select(x => x.Value));
443    }
444
445    private void ChildHiveJob_StateLogChanged(object sender, EventArgs e) {
446      OnStateLogChanged();
447    }
448    #endregion
449
450    public void Pause() {
451      if (this.Job.IsParentJob) {
452        childHiveJobsLock.EnterReadLock();
453        try {
454          foreach (var child in childHiveJobs) {
455            ServiceLocator.Instance.CallHiveService(s => s.PauseJob(child.job.Id));
456          }
457        }
458        finally { childHiveJobsLock.ExitReadLock(); }
459      } else {
460        ServiceLocator.Instance.CallHiveService(s => s.PauseJob(this.job.Id));
461      }
462    }
463
464    public void Stop() {
465      if (this.Job.IsParentJob) {
466        childHiveJobsLock.EnterReadLock();
467        try {
468          foreach (var child in childHiveJobs) {
469            ServiceLocator.Instance.CallHiveService(s => s.StopJob(child.job.Id));
470          }
471        }
472        finally { childHiveJobsLock.ExitReadLock(); }
473      } else {
474        ServiceLocator.Instance.CallHiveService(s => s.StopJob(this.job.Id));
475      }
476    }
477
478    public void Restart() {
479      ServiceLocator.Instance.CallHiveService(service => {
480        JobData jobData = new JobData();
481        jobData.JobId = this.job.Id;
482        jobData.Data = PersistenceUtil.Serialize(this.itemJob);
483        service.UpdateJobData(this.Job, jobData);
484        service.RestartJob(this.job.Id);
485        Job job = service.GetJob(this.job.Id);
486        this.job.LastJobDataUpdate = job.LastJobDataUpdate;
487      });
488    }
489
490    public ICollection<IItemTreeNodeAction<HiveJob>> Actions {
491      get {
492        return new List<IItemTreeNodeAction<HiveJob>>();
493      }
494    }
495
496    public virtual void IntegrateChild(ItemJob job, Guid childJobId) { }
497
498    /// <summary>
499    /// Delete ItemJob
500    /// </summary>
501    public virtual void ClearData() {
502      this.ItemJob.Item = null;
503    }
504  }
505
506  [Item("Hive Job", "Represents a hive job.")]
507  [StorableClass]
508  public class HiveJob<T> : HiveJob where T : ItemJob {
509
510    public new T ItemJob {
511      get { return (T)base.ItemJob; }
512      internal set { base.ItemJob = value; }
513    }
514
515    #region Constructors and Cloning
516    public HiveJob() : base() { }
517    public HiveJob(T itemJob) : base(itemJob, true) { }
518    protected HiveJob(HiveJob original, Cloner cloner)
519      : base(original, cloner) {
520    }
521    public override IDeepCloneable Clone(Cloner cloner) {
522      return new HiveJob<T>(this, cloner);
523    }
524    #endregion
525  }
526}
Note: See TracBrowser for help on using the repository browser.