source: branches/PersistenceOverhaul/HeuristicLab.Clients.Hive/3.3/HiveTasks/HiveTask.cs @ 13386

Last change on this file since 13386 was 13386, checked in by ascheibe, 4 years ago

#2520

  • fixed duplicate guids
  • adapted/added unit tests for new persistence
File size: 19.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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 Task", "Represents a hive task.")]
37  [StorableClass("967DC1A1-7B0C-4D8B-AF9F-710B1FD676DF")]
38  public class HiveTask : NamedItem, IItemTree<HiveTask>, IDisposable {
39    protected static object locker = new object();
40    protected ReaderWriterLockSlim childHiveTasksLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
41    protected ReaderWriterLockSlim itemTaskLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
42
43    public static new Image StaticItemImage {
44      get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; }
45    }
46    public override Image ItemImage {
47      get {
48        if (task.Id == Guid.Empty) { // not yet uploaded
49          return HeuristicLab.Common.Resources.VSImageLibrary.Event;
50        } else {
51          if (task.State == TaskState.Waiting) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
52          else if (task.State == TaskState.Calculating) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
53          else if (task.State == TaskState.Transferring) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
54          else if (task.State == TaskState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
55          else if (task.State == TaskState.Aborted) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
56          else if (task.State == TaskState.Failed) return HeuristicLab.Common.Resources.VSImageLibrary.Error;
57          else if (task.State == TaskState.Finished) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
58          else return base.ItemImage;
59        }
60      }
61    }
62
63    [Storable]
64    protected Task task;
65    public Task Task {
66      get { return task; }
67      set {
68        if (task != value) {
69          DeregisterTaskEvents();
70          task = value;
71          RegisterTaskEvents();
72          IsFinishedTaskDownloaded = false;
73          OnTaskChanged();
74          OnToStringChanged();
75          OnItemImageChanged();
76        }
77      }
78    }
79
80    [Storable]
81    protected ItemTask itemTask;
82    public ItemTask ItemTask {
83      get { return itemTask; }
84      set {
85        if (itemTask != null && syncTasksWithOptimizers) {
86          childHiveTasksLock.EnterWriteLock();
87          try {
88            childHiveTasks.Clear();
89          }
90          finally { childHiveTasksLock.ExitWriteLock(); }
91        }
92        if (itemTask != value) {
93          itemTaskLock.EnterWriteLock();
94          try {
95            DeregisterItemTaskEvents();
96            itemTask = value;
97            RegisterItemTaskEvents();
98          }
99          finally { itemTaskLock.ExitWriteLock(); }
100          OnItemTaskChanged();
101          IsFinishedTaskDownloaded = true;
102        }
103
104      }
105    }
106
107    // task downloaded since last status change
108    [Storable]
109    private bool isFinishedTaskDownloaded = false;
110    public bool IsFinishedTaskDownloaded {
111      get { return isFinishedTaskDownloaded; }
112      set {
113        if (value != isFinishedTaskDownloaded) {
114          this.isFinishedTaskDownloaded = value;
115          OnIsFinishedJobDownloadedChanged();
116        }
117      }
118    }
119
120    public bool IsDownloading { get; set; }
121
122    // if true, all control buttons should be enabled. otherwise disabled
123    private bool isControllable = true;
124    public bool IsControllable {
125      get { return isControllable; }
126      set {
127        if (value != isControllable) {
128          isControllable = value;
129          OnIsControllableChanged();
130          childHiveTasksLock.EnterReadLock();
131          try {
132            foreach (var hiveJob in childHiveTasks) {
133              hiveJob.IsControllable = value;
134            }
135          }
136          finally {
137            childHiveTasksLock.ExitReadLock();
138          }
139        }
140      }
141    }
142
143    [Storable]
144    protected ItemList<HiveTask> childHiveTasks;
145    public virtual ReadOnlyItemList<HiveTask> ChildHiveTasks {
146      get {
147        childHiveTasksLock.EnterReadLock();
148        try {
149          return childHiveTasks.AsReadOnly();
150        }
151        finally { childHiveTasksLock.ExitReadLock(); }
152      }
153    }
154
155    [Storable]
156    protected bool syncTasksWithOptimizers = true;
157
158    public StateLogList StateLog {
159      get {
160        var list = new StateLogList(this.task.StateLog);
161        list.ForEach(s => { s.TaskName = itemTask.Name; });
162        return list;
163      }
164    }
165
166    public StateLogListList ChildStateLogList {
167      get { return new StateLogListList(this.childHiveTasks.Select(x => x.StateLog)); }
168    }
169
170    #region Constructors and Cloning
171    [StorableConstructor]
172    protected HiveTask(bool deserializing) { }
173
174    public HiveTask()
175      : base() {
176      Name = "Hive Task";
177      this.Task = new Task() { CoresNeeded = 1, MemoryNeeded = 128 };
178      task.State = TaskState.Offline;
179      this.childHiveTasks = new ItemList<HiveTask>();
180      syncTasksWithOptimizers = true;
181      RegisterChildHiveTasksEvents();
182    }
183
184    public HiveTask(ItemTask itemTask, bool autoCreateChildHiveTasks)
185      : this() {
186      this.syncTasksWithOptimizers = autoCreateChildHiveTasks;
187      this.ItemTask = itemTask;
188      this.syncTasksWithOptimizers = true;
189    }
190
191    public HiveTask(Task task, TaskData taskData, bool autoCreateChildHiveTasks) {
192      this.syncTasksWithOptimizers = autoCreateChildHiveTasks;
193      this.Task = task;
194      try {
195        this.ItemTask = PersistenceUtil.Deserialize<ItemTask>(taskData.Data);
196      }
197      catch {
198        this.ItemTask = null;
199      }
200      this.childHiveTasks = new ItemList<HiveTask>();
201      this.syncTasksWithOptimizers = true;
202      RegisterChildHiveTasksEvents();
203    }
204
205    protected HiveTask(HiveTask original, Cloner cloner)
206      : base(original, cloner) {
207      this.Task = cloner.Clone(original.task);
208      this.ItemTask = cloner.Clone(original.ItemTask);
209      original.childHiveTasksLock.EnterReadLock();
210      try {
211        this.childHiveTasks = cloner.Clone(original.childHiveTasks);
212      }
213      finally { original.childHiveTasksLock.ExitReadLock(); }
214      this.syncTasksWithOptimizers = original.syncTasksWithOptimizers;
215      this.isFinishedTaskDownloaded = original.isFinishedTaskDownloaded;
216    }
217    public override IDeepCloneable Clone(Cloner cloner) {
218      return new HiveTask(this, cloner);
219    }
220    #endregion
221
222    protected virtual void UpdateChildHiveTasks() { }
223
224    protected virtual void RegisterItemTaskEvents() {
225      if (ItemTask != null) {
226        ItemTask.ComputeInParallelChanged += new EventHandler(ItemJob_ComputeInParallelChanged);
227        ItemTask.ToStringChanged += new EventHandler(ItemJob_ToStringChanged);
228      }
229    }
230    protected virtual void DeregisterItemTaskEvents() {
231      if (ItemTask != null) {
232        ItemTask.ComputeInParallelChanged -= new EventHandler(ItemJob_ComputeInParallelChanged);
233        ItemTask.ToStringChanged -= new EventHandler(ItemJob_ToStringChanged);
234      }
235    }
236
237    protected virtual void RegisterChildHiveTasksEvents() {
238      this.childHiveTasks.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsAdded);
239      this.childHiveTasks.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsRemoved);
240      this.childHiveTasks.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnCollectionReset);
241    }
242    protected virtual void DeregisterChildHiveTasksEvents() {
243      this.childHiveTasks.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsAdded);
244      this.childHiveTasks.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsRemoved);
245      this.childHiveTasks.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnCollectionReset);
246    }
247
248    protected virtual void ItemJob_ToStringChanged(object sender, EventArgs e) {
249      this.OnToStringChanged();
250    }
251
252    protected virtual void ItemJob_ComputeInParallelChanged(object sender, EventArgs e) {
253      if (ItemTask != null && syncTasksWithOptimizers) {
254        this.UpdateChildHiveTasks();
255      }
256    }
257
258    public virtual void AddChildHiveTask(HiveTask hiveTask) {
259      childHiveTasksLock.EnterWriteLock();
260      try {
261        this.childHiveTasks.Add(hiveTask);
262      }
263      finally { childHiveTasksLock.ExitWriteLock(); }
264    }
265
266    public override string ToString() {
267      if (itemTask != null && itemTask.Item != null) {
268        return itemTask.ToString();
269      } else {
270        return Task.Id.ToString();
271      }
272    }
273
274    public virtual void UpdateFromLightweightJob(LightweightTask lightweightJob) {
275      if (lightweightJob != null) {
276        task.Id = lightweightJob.Id;
277        task.ParentTaskId = lightweightJob.ParentTaskId;
278        task.ExecutionTime = lightweightJob.ExecutionTime;
279        task.State = lightweightJob.State;
280        task.StateLog = new List<StateLog>(lightweightJob.StateLog);
281        task.Command = lightweightJob.Command;
282
283        OnTaskStateChanged();
284        OnToStringChanged();
285        OnItemImageChanged();
286        OnStateLogChanged();
287      }
288    }
289
290    /// <summary>
291    /// Creates a TaskData object containing the Task and the IJob-Object as byte[]
292    /// </summary>
293    /// <param name="withoutChildOptimizers">
294    ///   if true the Child-Optimizers will not be serialized (if the task contains an Experiment)
295    /// </param>
296    public virtual TaskData GetAsTaskData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
297      if (ItemTask == null) {
298        plugins = new List<IPluginDescription>();
299        return null;
300      }
301
302      IEnumerable<Type> usedTypes;
303      byte[] taskByteArray = PersistenceUtil.Serialize(ItemTask, out usedTypes);
304      TaskData taskData = new TaskData() { TaskId = task.Id, Data = taskByteArray };
305      plugins = PluginUtil.GetPluginsForTask(usedTypes, ItemTask);
306      return taskData;
307    }
308
309    #region Event Handler
310    public event EventHandler TaskChanged;
311    private void OnTaskChanged() {
312      EventHandler handler = TaskChanged;
313      if (handler != null) handler(this, EventArgs.Empty);
314    }
315
316    public event EventHandler TaskStateChanged;
317    private void OnTaskStateChanged() {
318      EventHandler handler = TaskStateChanged;
319      if (handler != null) handler(this, EventArgs.Empty);
320    }
321
322    public event EventHandler ItemTaskChanged;
323    private void OnItemTaskChanged() {
324      ItemJob_ComputeInParallelChanged(this, EventArgs.Empty);
325      var handler = ItemTaskChanged;
326      if (handler != null) handler(this, EventArgs.Empty);
327    }
328
329    public event EventHandler IsFinishedJobDownloadedChanged;
330    private void OnIsFinishedJobDownloadedChanged() {
331      var handler = IsFinishedJobDownloadedChanged;
332      if (handler != null) handler(this, EventArgs.Empty);
333    }
334
335    public event EventHandler StateLogChanged;
336    private void OnStateLogChanged() {
337      var handler = StateLogChanged;
338      if (handler != null) handler(this, EventArgs.Empty);
339    }
340
341    public event EventHandler IsControllableChanged;
342    private void OnIsControllableChanged() {
343      var handler = IsControllableChanged;
344      if (handler != null) handler(this, EventArgs.Empty);
345    }
346
347    private void RegisterTaskEvents() {
348      if (task != null)
349        task.PropertyChanged += new PropertyChangedEventHandler(task_PropertyChanged);
350    }
351
352    private void DeregisterTaskEvents() {
353      if (task != null)
354        task.PropertyChanged += new PropertyChangedEventHandler(task_PropertyChanged);
355    }
356
357    private void task_PropertyChanged(object sender, PropertyChangedEventArgs e) {
358      if (e.PropertyName == "State") {
359        IsFinishedTaskDownloaded = false;
360      }
361      if (e.PropertyName == "Priority" && Task != null) {
362        foreach (var task in childHiveTasks) {
363          task.Task.Priority = Task.Priority;
364        }
365      }
366    }
367    #endregion
368
369    /// <summary>
370    /// Returns a list of HiveTasks including this and all its child-jobs recursively
371    /// </summary>
372    public IEnumerable<HiveTask> GetAllHiveTasks() {
373      childHiveTasksLock.EnterReadLock();
374      try {
375        var tasks = new List<HiveTask>();
376        tasks.Add(this);
377        foreach (HiveTask child in this.childHiveTasks) {
378          tasks.AddRange(child.GetAllHiveTasks());
379        }
380        return tasks;
381      }
382      finally { childHiveTasksLock.ExitReadLock(); }
383    }
384
385    public HiveTask GetParentByJobId(Guid taskId) {
386      childHiveTasksLock.EnterReadLock();
387      try {
388        if (this.ChildHiveTasks.SingleOrDefault(j => j.task.Id == taskId) != null)
389          return this;
390        foreach (HiveTask child in this.childHiveTasks) {
391          HiveTask result = child.GetParentByJobId(taskId);
392          if (result != null)
393            return result;
394        }
395        return null;
396      }
397      finally { childHiveTasksLock.ExitWriteLock(); }
398    }
399
400    /// <summary>
401    /// Searches for an HiveTask object with the correct taskId recursively
402    /// </summary>
403    public HiveTask GetHiveTaskByTaskId(Guid jobId) {
404      if (this.Task.Id == jobId) {
405        return this;
406      } else {
407        childHiveTasksLock.EnterReadLock();
408        try {
409          foreach (HiveTask child in this.childHiveTasks) {
410            HiveTask result = child.GetHiveTaskByTaskId(jobId);
411            if (result != null)
412              return result;
413          }
414        }
415        finally { childHiveTasksLock.ExitReadLock(); }
416      }
417      return null;
418    }
419
420    public void RemoveByTaskId(Guid taskId) {
421      childHiveTasksLock.EnterWriteLock();
422      try {
423        IEnumerable<HiveTask> tasks = childHiveTasks.Where(j => j.Task.Id == taskId).ToList();
424        foreach (HiveTask t in tasks) {
425          this.childHiveTasks.Remove(t);
426        }
427        foreach (HiveTask child in childHiveTasks) {
428          child.RemoveByTaskId(taskId);
429        }
430      }
431      finally { childHiveTasksLock.ExitWriteLock(); }
432    }
433
434    public IEnumerable<IItemTree<HiveTask>> GetChildItems() {
435      return this.ChildHiveTasks;
436    }
437
438    #region INotifyObservableCollectionItemsChanged<IItemTree> Members
439
440    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> CollectionReset;
441    private void OnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
442      foreach (var item in e.Items) {
443        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
444      }
445      var handler = CollectionReset;
446      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
447    }
448
449    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> ItemsAdded;
450    private void OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
451      foreach (var item in e.Items) {
452        item.Value.StateLogChanged += new EventHandler(ChildHiveJob_StateLogChanged);
453        item.Value.IsControllable = this.IsControllable;
454      }
455      var handler = ItemsAdded;
456      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
457    }
458
459    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> ItemsRemoved;
460    private void OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
461      foreach (var item in e.Items) {
462        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
463      }
464      var handler = ItemsRemoved;
465      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
466    }
467
468    private static CollectionItemsChangedEventArgs<IItemTree<HiveTask>> ToCollectionItemsChangedEventArgs(CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
469      return new CollectionItemsChangedEventArgs<IItemTree<HiveTask>>(e.Items.Select(x => x.Value), e.OldItems == null ? null : e.OldItems.Select(x => x.Value));
470    }
471
472    private void ChildHiveJob_StateLogChanged(object sender, EventArgs e) {
473      OnStateLogChanged();
474    }
475    #endregion
476
477    public void Pause() {
478      if (this.Task.IsParentTask) {
479        childHiveTasksLock.EnterReadLock();
480        try {
481          foreach (var child in childHiveTasks) {
482            HiveServiceLocator.Instance.CallHiveService(s => s.PauseTask(child.task.Id));
483          }
484        }
485        finally { childHiveTasksLock.ExitReadLock(); }
486      } else {
487        HiveServiceLocator.Instance.CallHiveService(s => s.PauseTask(this.task.Id));
488      }
489    }
490
491    public void Stop() {
492      if (this.Task.IsParentTask) {
493        childHiveTasksLock.EnterReadLock();
494        try {
495          foreach (var child in childHiveTasks) {
496            HiveServiceLocator.Instance.CallHiveService(s => s.StopTask(child.task.Id));
497          }
498        }
499        finally { childHiveTasksLock.ExitReadLock(); }
500      } else {
501        HiveServiceLocator.Instance.CallHiveService(s => s.StopTask(this.task.Id));
502      }
503    }
504
505    public void Restart() {
506      HiveServiceLocator.Instance.CallHiveService(service => {
507        TaskData taskData = new TaskData();
508        taskData.TaskId = this.task.Id;
509        taskData.Data = PersistenceUtil.Serialize(this.itemTask);
510        service.UpdateTaskData(this.Task, taskData);
511        service.RestartTask(this.task.Id);
512        Task task = service.GetTask(this.task.Id);
513        this.task.LastTaskDataUpdate = task.LastTaskDataUpdate;
514      });
515    }
516
517    public ICollection<IItemTreeNodeAction<HiveTask>> Actions {
518      get {
519        return new List<IItemTreeNodeAction<HiveTask>>();
520      }
521    }
522
523    public virtual void IntegrateChild(ItemTask task, Guid childTaskId) { }
524
525    /// <summary>
526    /// Delete ItemTask
527    /// </summary>
528    public virtual void ClearData() {
529      this.ItemTask.Item = null;
530    }
531
532    public void Dispose() {
533      DeregisterChildHiveTasksEvents();
534      DeregisterTaskEvents();
535      DeregisterItemTaskEvents();
536      childHiveTasksLock.Dispose();
537      itemTaskLock.Dispose();
538      ClearData();
539    }
540  }
541
542  [Item("Hive Task", "Represents a hive task.")]
543  [StorableClass("04AD6AF8-8248-48FB-AF3A-403A2D22F725")]
544  public class HiveTask<T> : HiveTask where T : ItemTask {
545
546    public new T ItemTask {
547      get { return (T)base.ItemTask; }
548      set { base.ItemTask = value; }
549    }
550
551    #region Constructors and Cloning
552    public HiveTask() : base() { }
553    [StorableConstructor]
554    protected HiveTask(bool deserializing) { }
555    public HiveTask(T itemTask) : base(itemTask, true) { }
556    protected HiveTask(HiveTask<T> original, Cloner cloner)
557      : base(original, cloner) {
558    }
559    public override IDeepCloneable Clone(Cloner cloner) {
560      return new HiveTask<T>(this, cloner);
561    }
562    #endregion
563  }
564}
Note: See TracBrowser for help on using the repository browser.