source: trunk/sources/HeuristicLab.Clients.Hive/3.3/HiveTasks/HiveTask.cs @ 8939

Last change on this file since 8939 was 8939, checked in by ascheibe, 9 years ago

#1950

  • added more aggressive locking so that the views don't read run collections that get modified in the meantime
  • start downloading of tasks after the job has been uploaded completely
  • fixed exceptions that got thrown when waiting for the threads that upload the tasks
File size: 19.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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]
38  public class HiveTask : NamedItem, IItemTree<HiveTask> {
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          DeregisterJobEvents();
70          task = value;
71          RegisterJobEvents();
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            DergisterItemTaskEvents();
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      this.Task = new Task() { CoresNeeded = 1, MemoryNeeded = 128 };
176      task.State = TaskState.Offline;
177      this.childHiveTasks = new ItemList<HiveTask>();
178      syncTasksWithOptimizers = true;
179      RegisterChildHiveJobEvents();
180    }
181
182    public HiveTask(ItemTask itemJob, bool autoCreateChildHiveJobs)
183      : this() {
184      this.syncTasksWithOptimizers = autoCreateChildHiveJobs;
185      this.ItemTask = itemJob;
186      this.syncTasksWithOptimizers = true;
187    }
188
189    public HiveTask(Task job, TaskData taskData, bool autoCreateChildHiveTasks) {
190      this.syncTasksWithOptimizers = autoCreateChildHiveTasks;
191      this.Task = job;
192      try {
193        this.ItemTask = PersistenceUtil.Deserialize<ItemTask>(taskData.Data);
194      }
195      catch {
196        this.ItemTask = null;
197      }
198      this.childHiveTasks = new ItemList<HiveTask>();
199      this.syncTasksWithOptimizers = true;
200      RegisterChildHiveJobEvents();
201    }
202
203    protected HiveTask(HiveTask original, Cloner cloner)
204      : base(original, cloner) {
205      this.Task = cloner.Clone(original.task);
206      this.ItemTask = cloner.Clone(original.ItemTask);
207      original.childHiveTasksLock.EnterReadLock();
208      try {
209        this.childHiveTasks = cloner.Clone(original.childHiveTasks);
210      }
211      finally { original.childHiveTasksLock.ExitReadLock(); }
212      this.syncTasksWithOptimizers = original.syncTasksWithOptimizers;
213      this.isFinishedTaskDownloaded = original.isFinishedTaskDownloaded;
214    }
215    public override IDeepCloneable Clone(Cloner cloner) {
216      return new HiveTask(this, cloner);
217    }
218    #endregion
219
220    protected virtual void UpdateChildHiveTasks() { }
221
222    protected virtual void RegisterItemTaskEvents() {
223      if (ItemTask != null) {
224        ItemTask.ComputeInParallelChanged += new EventHandler(ItemJob_ComputeInParallelChanged);
225        ItemTask.ToStringChanged += new EventHandler(ItemJob_ToStringChanged);
226      }
227    }
228    protected virtual void DergisterItemTaskEvents() {
229      if (ItemTask != null) {
230        ItemTask.ComputeInParallelChanged -= new EventHandler(ItemJob_ComputeInParallelChanged);
231        ItemTask.ToStringChanged -= new EventHandler(ItemJob_ToStringChanged);
232      }
233    }
234
235    protected virtual void RegisterChildHiveJobEvents() {
236      this.childHiveTasks.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsAdded);
237      this.childHiveTasks.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsRemoved);
238      this.childHiveTasks.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnCollectionReset);
239    }
240    protected virtual void DeregisterChildHiveJobEvents() {
241      this.childHiveTasks.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsAdded);
242      this.childHiveTasks.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsRemoved);
243      this.childHiveTasks.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnCollectionReset);
244    }
245
246    protected virtual void ItemJob_ToStringChanged(object sender, EventArgs e) {
247      this.OnToStringChanged();
248    }
249
250    protected virtual void ItemJob_ComputeInParallelChanged(object sender, EventArgs e) {
251      if (ItemTask != null && syncTasksWithOptimizers) {
252        this.UpdateChildHiveTasks();
253      }
254    }
255
256    public virtual void AddChildHiveTask(HiveTask hiveTask) {
257      childHiveTasksLock.EnterWriteLock();
258      try {
259        this.childHiveTasks.Add(hiveTask);
260      }
261      finally { childHiveTasksLock.ExitWriteLock(); }
262    }
263
264    public override string ToString() {
265      if (itemTask != null && itemTask.Item != null) {
266        return itemTask.ToString();
267      } else {
268        return Task.Id.ToString();
269      }
270    }
271
272    public virtual void UpdateFromLightweightJob(LightweightTask lightweightJob) {
273      if (lightweightJob != null) {
274        task.Id = lightweightJob.Id;
275        task.ParentTaskId = lightweightJob.ParentTaskId;
276        task.ExecutionTime = lightweightJob.ExecutionTime;
277        task.State = lightweightJob.State;
278        task.StateLog = new List<StateLog>(lightweightJob.StateLog);
279        task.Command = lightweightJob.Command;
280
281        OnTaskStateChanged();
282        OnToStringChanged();
283        OnItemImageChanged();
284        OnStateLogChanged();
285      }
286    }
287
288    /// <summary>
289    /// Creates a TaskData object containing the Task and the IJob-Object as byte[]
290    /// </summary>
291    /// <param name="withoutChildOptimizers">
292    ///   if true the Child-Optimizers will not be serialized (if the task contains an Experiment)
293    /// </param>
294    public virtual TaskData GetAsTaskData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
295      plugins = new List<IPluginDescription>();
296      if (this.itemTask == null)
297        return null;
298
299      IEnumerable<Type> usedTypes;
300      byte[] taskByteArray = PersistenceUtil.Serialize(this.ItemTask, out usedTypes);
301      TaskData taskData = new TaskData() { TaskId = task.Id, Data = taskByteArray };
302      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
303      return taskData;
304    }
305
306    #region Event Handler
307    public event EventHandler TaskChanged;
308    private void OnTaskChanged() {
309      EventHandler handler = TaskChanged;
310      if (handler != null) handler(this, EventArgs.Empty);
311    }
312
313    public event EventHandler TaskStateChanged;
314    private void OnTaskStateChanged() {
315      EventHandler handler = TaskStateChanged;
316      if (handler != null) handler(this, EventArgs.Empty);
317    }
318
319    public event EventHandler ItemTaskChanged;
320    private void OnItemTaskChanged() {
321      ItemJob_ComputeInParallelChanged(this, EventArgs.Empty);
322      var handler = ItemTaskChanged;
323      if (handler != null) handler(this, EventArgs.Empty);
324    }
325
326    public event EventHandler IsFinishedJobDownloadedChanged;
327    private void OnIsFinishedJobDownloadedChanged() {
328      var handler = IsFinishedJobDownloadedChanged;
329      if (handler != null) handler(this, EventArgs.Empty);
330    }
331
332    public event EventHandler StateLogChanged;
333    private void OnStateLogChanged() {
334      var handler = StateLogChanged;
335      if (handler != null) handler(this, EventArgs.Empty);
336    }
337
338    public event EventHandler IsControllableChanged;
339    private void OnIsControllableChanged() {
340      var handler = IsControllableChanged;
341      if (handler != null) handler(this, EventArgs.Empty);
342    }
343
344    private void RegisterJobEvents() {
345      if (task != null)
346        task.PropertyChanged += new PropertyChangedEventHandler(task_PropertyChanged);
347    }
348
349    private void DeregisterJobEvents() {
350      if (task != null)
351        task.PropertyChanged += new PropertyChangedEventHandler(task_PropertyChanged);
352    }
353
354    private void task_PropertyChanged(object sender, PropertyChangedEventArgs e) {
355      if (e.PropertyName == "State") {
356        IsFinishedTaskDownloaded = false;
357      }
358      if (e.PropertyName == "Priority" && Task != null) {
359        foreach (var task in childHiveTasks) {
360          task.Task.Priority = Task.Priority;
361        }
362      }
363    }
364    #endregion
365
366    /// <summary>
367    /// Returns a list of HiveTasks including this and all its child-jobs recursively
368    /// </summary>
369    public IEnumerable<HiveTask> GetAllHiveTasks() {
370      childHiveTasksLock.EnterReadLock();
371      try {
372        var tasks = new List<HiveTask>();
373        tasks.Add(this);
374        foreach (HiveTask child in this.childHiveTasks) {
375          tasks.AddRange(child.GetAllHiveTasks());
376        }
377        return tasks;
378      }
379      finally { childHiveTasksLock.ExitReadLock(); }
380    }
381
382    public HiveTask GetParentByJobId(Guid taskId) {
383      childHiveTasksLock.EnterReadLock();
384      try {
385        if (this.ChildHiveTasks.SingleOrDefault(j => j.task.Id == taskId) != null)
386          return this;
387        foreach (HiveTask child in this.childHiveTasks) {
388          HiveTask result = child.GetParentByJobId(taskId);
389          if (result != null)
390            return result;
391        }
392        return null;
393      }
394      finally { childHiveTasksLock.ExitWriteLock(); }
395    }
396
397    /// <summary>
398    /// Searches for an HiveTask object with the correct taskId recursively
399    /// </summary>
400    public HiveTask GetHiveTaskByTaskId(Guid jobId) {
401      if (this.Task.Id == jobId) {
402        return this;
403      } else {
404        childHiveTasksLock.EnterReadLock();
405        try {
406          foreach (HiveTask child in this.childHiveTasks) {
407            HiveTask result = child.GetHiveTaskByTaskId(jobId);
408            if (result != null)
409              return result;
410          }
411        }
412        finally { childHiveTasksLock.ExitReadLock(); }
413      }
414      return null;
415    }
416
417    public void RemoveByTaskId(Guid taskId) {
418      childHiveTasksLock.EnterWriteLock();
419      try {
420        IEnumerable<HiveTask> tasks = childHiveTasks.Where(j => j.Task.Id == taskId).ToList();
421        foreach (HiveTask t in tasks) {
422          this.childHiveTasks.Remove(t);
423        }
424        foreach (HiveTask child in childHiveTasks) {
425          child.RemoveByTaskId(taskId);
426        }
427      }
428      finally { childHiveTasksLock.ExitWriteLock(); }
429    }
430
431    public IEnumerable<IItemTree<HiveTask>> GetChildItems() {
432      return this.ChildHiveTasks;
433    }
434
435    #region INotifyObservableCollectionItemsChanged<IItemTree> Members
436
437    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> CollectionReset;
438    private void OnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
439      foreach (var item in e.Items) {
440        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
441      }
442      var handler = CollectionReset;
443      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
444    }
445
446    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> ItemsAdded;
447    private void OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
448      foreach (var item in e.Items) {
449        item.Value.StateLogChanged += new EventHandler(ChildHiveJob_StateLogChanged);
450        item.Value.IsControllable = this.IsControllable;
451      }
452      var handler = ItemsAdded;
453      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
454    }
455
456    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> ItemsRemoved;
457    private void OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
458      foreach (var item in e.Items) {
459        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
460      }
461      var handler = ItemsRemoved;
462      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
463    }
464
465    private static CollectionItemsChangedEventArgs<IItemTree<HiveTask>> ToCollectionItemsChangedEventArgs(CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
466      return new CollectionItemsChangedEventArgs<IItemTree<HiveTask>>(e.Items.Select(x => x.Value), e.OldItems == null ? null : e.OldItems.Select(x => x.Value));
467    }
468
469    private void ChildHiveJob_StateLogChanged(object sender, EventArgs e) {
470      OnStateLogChanged();
471    }
472    #endregion
473
474    public void Pause() {
475      if (this.Task.IsParentTask) {
476        childHiveTasksLock.EnterReadLock();
477        try {
478          foreach (var child in childHiveTasks) {
479            HiveServiceLocator.Instance.CallHiveService(s => s.PauseTask(child.task.Id));
480          }
481        }
482        finally { childHiveTasksLock.ExitReadLock(); }
483      } else {
484        HiveServiceLocator.Instance.CallHiveService(s => s.PauseTask(this.task.Id));
485      }
486    }
487
488    public void Stop() {
489      if (this.Task.IsParentTask) {
490        childHiveTasksLock.EnterReadLock();
491        try {
492          foreach (var child in childHiveTasks) {
493            HiveServiceLocator.Instance.CallHiveService(s => s.StopTask(child.task.Id));
494          }
495        }
496        finally { childHiveTasksLock.ExitReadLock(); }
497      } else {
498        HiveServiceLocator.Instance.CallHiveService(s => s.StopTask(this.task.Id));
499      }
500    }
501
502    public void Restart() {
503      HiveServiceLocator.Instance.CallHiveService(service => {
504        TaskData taskData = new TaskData();
505        taskData.TaskId = this.task.Id;
506        taskData.Data = PersistenceUtil.Serialize(this.itemTask);
507        service.UpdateTaskData(this.Task, taskData);
508        service.RestartTask(this.task.Id);
509        Task task = service.GetTask(this.task.Id);
510        this.task.LastTaskDataUpdate = task.LastTaskDataUpdate;
511      });
512    }
513
514    public ICollection<IItemTreeNodeAction<HiveTask>> Actions {
515      get {
516        return new List<IItemTreeNodeAction<HiveTask>>();
517      }
518    }
519
520    public virtual void IntegrateChild(ItemTask task, Guid childTaskId) { }
521
522    /// <summary>
523    /// Delete ItemTask
524    /// </summary>
525    public virtual void ClearData() {
526      this.ItemTask.Item = null;
527    }
528  }
529
530  [Item("Hive Task", "Represents a hive task.")]
531  [StorableClass]
532  public class HiveTask<T> : HiveTask where T : ItemTask {
533
534    public new T ItemTask {
535      get { return (T)base.ItemTask; }
536      internal set { base.ItemTask = value; }
537    }
538
539    #region Constructors and Cloning
540    public HiveTask() : base() { }
541    [StorableConstructor]
542    protected HiveTask(bool deserializing) { }
543    public HiveTask(T itemJob) : base(itemJob, true) { }
544    protected HiveTask(HiveTask<T> original, Cloner cloner)
545      : base(original, cloner) {
546    }
547    public override IDeepCloneable Clone(Cloner cloner) {
548      return new HiveTask<T>(this, cloner);
549    }
550    #endregion
551  }
552}
Note: See TracBrowser for help on using the repository browser.