Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/RefreshableJob.cs @ 6725

Last change on this file since 6725 was 6725, checked in by ascheibe, 13 years ago

#1233 more renaming for more consistency

File size: 21.8 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 HeuristicLab.Collections;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30
31namespace HeuristicLab.Clients.Hive {
32  public class RefreshableJob : IHiveItem, IDeepCloneable, IContent, IProgressReporter, IComparable<RefreshableJob> {
33    private JobResultPoller jobResultPoller;
34    private ConcurrentTaskDownloader<ItemTask> jobDownloader;
35    private static object locker = new object();
36
37    private Job job;
38    public Job Job {
39      get { return job; }
40      set {
41        if (value != job) {
42          if (value == null)
43            throw new ArgumentNullException();
44
45          if (job != null) DergisterJobEvents();
46          job = value;
47          if (job != null) {
48            RegisterJobEvents();
49            job_PropertyChanged(job, new PropertyChangedEventArgs("Id"));
50          }
51          OnJobChanged();
52          OnToStringChanged(this, EventArgs.Empty);
53        }
54      }
55    }
56
57    private ItemCollection<HiveTask> hiveJobs;
58    public ItemCollection<HiveTask> HiveJobs {
59      get { return hiveJobs; }
60      set {
61        if (hiveJobs != value) {
62          if (hiveJobs != null) DeregisterHiveJobsEvents();
63          hiveJobs = value;
64          if (hiveJobs != null) RegisterHiveJobsEvents();
65          OnHiveJobsChanged();
66        }
67      }
68    }
69
70    private ExecutionState executionState;
71    public ExecutionState ExecutionState {
72      get { return executionState; }
73      internal set {
74        if (executionState != value) {
75          executionState = value;
76          OnExecutionStateChanged();
77        }
78      }
79    }
80
81    private TimeSpan executionTime;
82    public TimeSpan ExecutionTime {
83      get { return executionTime; }
84      internal set {
85        if (executionTime != value) {
86          executionTime = value;
87          OnExecutionTimeChanged();
88        }
89      }
90    }
91
92    private bool refreshAutomatically;
93    public bool RefreshAutomatically {
94      get { return refreshAutomatically; }
95      set {
96        lock (locker) {
97          if (refreshAutomatically != value) {
98            refreshAutomatically = value;
99            OnRefreshAutomaticallyChanged();
100          }
101          if (RefreshAutomatically) {
102            if (this.HiveJobs != null && this.HiveJobs.Count > 0 && (jobResultPoller == null || !jobResultPoller.IsPolling)) {
103              StartResultPolling();
104            }
105          } else {
106            StopResultPolling();
107          }
108        }
109      }
110    }
111
112    // indicates if download button is enabled
113    private bool isDownloadable = true;
114    public bool IsDownloadable {
115      get { return isDownloadable; }
116      set {
117        if (value != isDownloadable) {
118          isDownloadable = value;
119          OnIsDownloadableChanged();
120        }
121      }
122    }
123
124    // if true, all control buttons should be enabled. otherwise disabled
125    private bool isControllable = true;
126    public bool IsControllable {
127      get { return isControllable; }
128      private set {
129        if (value != isControllable) {
130          isControllable = value;
131          OnIsControllableChanged();
132          if (this.hiveJobs != null) {
133            foreach (var hiveJob in this.hiveJobs) {
134              hiveJob.IsControllable = value;
135            }
136          }
137        }
138      }
139    }
140
141    // indicates if a user is allowed to share this experiment
142    private bool isSharable = true;
143    public bool IsSharable {
144      get { return isSharable; }
145      private set {
146        if (value != isSharable) {
147          isSharable = value;
148          OnIsSharableChanged();
149        }
150      }
151    }
152
153    // may execute jobs with privileged permissions on slaves
154    private bool isAllowedPrivileged = true;
155    public bool IsAllowedPrivileged {
156      get { return isAllowedPrivileged; }
157      set {
158        if (value != isAllowedPrivileged) {
159          isAllowedPrivileged = value;
160          OnIsAllowedPrivilegedChanged();
161        }
162      }
163    }
164
165    private bool isProgressing;
166    public bool IsProgressing {
167      get { return isProgressing; }
168      set {
169        if (isProgressing != value) {
170          isProgressing = value;
171          OnIsProgressingChanged();
172        }
173      }
174    }
175
176    private IProgress progress;
177    public IProgress Progress {
178      get { return progress; }
179      set { this.progress = value; }
180    }
181
182    private ThreadSafeLog log;
183    public ILog Log {
184      get { return log; }
185    }
186
187    public StateLogListList StateLogList {
188      get { return new StateLogListList(this.GetAllHiveJobs().Select(x => x.StateLog)); }
189    }
190
191    #region Constructors and Cloning
192    public RefreshableJob() {
193      this.refreshAutomatically = true;
194      this.Job = new Job();
195      this.log = new ThreadSafeLog(new Log());
196      this.jobDownloader = new ConcurrentTaskDownloader<ItemTask>(2, 2);
197      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
198      this.HiveJobs = new ItemCollection<HiveTask>();
199    }
200    public RefreshableJob(Job hiveExperiment) {
201      this.refreshAutomatically = true;
202      this.Job = hiveExperiment;
203      this.log = new ThreadSafeLog(new Log());
204      this.jobDownloader = new ConcurrentTaskDownloader<ItemTask>(2, 2);
205      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
206      this.HiveJobs = new ItemCollection<HiveTask>();
207    }
208    protected RefreshableJob(RefreshableJob original, Cloner cloner) {
209      cloner.RegisterClonedObject(original, this);
210      this.Job = original.Job;
211      this.IsControllable = original.IsControllable;
212      this.log = cloner.Clone(original.log);
213      this.RefreshAutomatically = false; // do not start results polling automatically
214      this.jobDownloader = new ConcurrentTaskDownloader<ItemTask>(2, 2);
215      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
216      this.HiveJobs = cloner.Clone(original.HiveJobs);
217      this.ExecutionTime = original.ExecutionTime;
218      this.ExecutionState = original.ExecutionState;
219    }
220    public IDeepCloneable Clone(Cloner cloner) {
221      return new RefreshableJob(this, cloner);
222    }
223    public object Clone() {
224      return this.Clone(new Cloner());
225    }
226    #endregion
227
228    #region JobResultPoller Events
229
230    public void StartResultPolling() {
231      if (jobResultPoller == null) {
232        jobResultPoller = new JobResultPoller(job.Id, /*ApplicationConstants.ResultPollingInterval*/new TimeSpan(0, 0, 5)); //TODO: find a better place for ApplicationConstants
233        RegisterResultPollingEvents();
234        jobResultPoller.AutoResumeOnException = true;
235      }
236
237      if (!jobResultPoller.IsPolling) {
238        jobResultPoller.Start();
239      }
240    }
241
242    public void StopResultPolling() {
243      if (jobResultPoller != null && jobResultPoller.IsPolling) {
244        jobResultPoller.Stop();
245      }
246    }
247
248    private void RegisterResultPollingEvents() {
249      jobResultPoller.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
250      jobResultPoller.JobResultsReceived += new EventHandler<EventArgs<IEnumerable<LightweightTask>>>(jobResultPoller_JobResultReceived);
251      jobResultPoller.IsPollingChanged += new EventHandler(jobResultPoller_IsPollingChanged);
252    }
253    private void DeregisterResultPollingEvents() {
254      jobResultPoller.ExceptionOccured -= new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
255      jobResultPoller.JobResultsReceived -= new EventHandler<EventArgs<IEnumerable<LightweightTask>>>(jobResultPoller_JobResultReceived);
256      jobResultPoller.IsPollingChanged -= new EventHandler(jobResultPoller_IsPollingChanged);
257    }
258    private void jobResultPoller_IsPollingChanged(object sender, EventArgs e) {
259      if (this.refreshAutomatically != jobResultPoller.IsPolling) {
260        this.refreshAutomatically = jobResultPoller.IsPolling;
261        OnRefreshAutomaticallyChanged();
262      }
263    }
264    private void jobResultPoller_JobResultReceived(object sender, EventArgs<IEnumerable<LightweightTask>> e) {
265      foreach (LightweightTask lightweightJob in e.Value) {
266        HiveTask hiveJob = GetHiveJobById(lightweightJob.Id);
267        if (hiveJob != null) {
268          // lastJobDataUpdate equals DateTime.MinValue right after it was uploaded. When the first results are polled, this value is updated
269          if (hiveJob.Task.State == TaskState.Offline && lightweightJob.State != TaskState.Finished && lightweightJob.State != TaskState.Failed && lightweightJob.State != TaskState.Aborted) {
270            hiveJob.Task.LastJobDataUpdate = lightweightJob.LastJobDataUpdate;
271          }
272
273          hiveJob.UpdateFromLightweightJob(lightweightJob);
274
275          if (!hiveJob.IsFinishedTaskDownloaded && !hiveJob.IsDownloading && hiveJob.Task.LastJobDataUpdate < lightweightJob.LastJobDataUpdate) {
276            log.LogMessage(string.Format("Downloading task {0}", lightweightJob.Id));
277            hiveJob.IsDownloading = true;
278            jobDownloader.DownloadJob(hiveJob.Task, (localJob, itemJob) => {
279              log.LogMessage(string.Format("Finished downloading task {0}", localJob.Id));
280              HiveTask localHiveJob = GetHiveJobById(localJob.Id);
281
282              if (itemJob == null) {
283                localHiveJob.IsDownloading = false;
284              }
285
286              if (itemJob == null) {
287                // something bad happened to this task. bad task, BAAAD task!
288              } else {
289                // if the task is paused, download but don't integrate into parent optimizer (to avoid Prepare)
290
291                if (localJob.State == TaskState.Paused) {
292                  localHiveJob.ItemTask = itemJob;
293                } else {
294                  if (localJob.ParentTaskId.HasValue) {
295                    HiveTask parentHiveJob = GetHiveJobById(localJob.ParentTaskId.Value);
296                    parentHiveJob.IntegrateChild(itemJob, localJob.Id);
297                  } else {
298                    localHiveJob.ItemTask = itemJob;
299                  }
300                }
301                localHiveJob.IsDownloading = false;
302                localHiveJob.Task.LastJobDataUpdate = localJob.LastJobDataUpdate;
303              }
304            });
305          }
306        }
307      }
308      GC.Collect(); // force GC, because .NET is too lazy here (deserialization takes a lot of memory)
309      if (AllJobsFinished()) {
310        this.ExecutionState = Core.ExecutionState.Stopped;
311        StopResultPolling();
312      }
313      UpdateTotalExecutionTime();
314      UpdateStatistics();
315      OnStateLogListChanged();
316    }
317
318    public HiveTask GetHiveJobById(Guid jobId) {
319      foreach (HiveTask job in this.HiveJobs) {
320        var hj = job.GetHiveTaskByTaskId(jobId);
321        if (hj != null)
322          return hj;
323      }
324      return null;
325    }
326    private void UpdateStatistics() {
327      var jobs = this.GetAllHiveJobs();
328      job.JobCount = jobs.Count();
329      job.CalculatingCount = jobs.Count(j => j.Task.State == TaskState.Calculating);
330      job.FinishedCount = jobs.Count(j => j.Task.State == TaskState.Finished);
331      OnJobStatisticsChanged();
332    }
333
334    public bool AllJobsFinished() {
335      return this.GetAllHiveJobs().All(j => (j.Task.State == TaskState.Finished
336                                                   || j.Task.State == TaskState.Aborted
337                                                   || j.Task.State == TaskState.Failed)
338                                                   && j.IsFinishedTaskDownloaded);
339    }
340
341    private void jobResultPoller_ExceptionOccured(object sender, EventArgs<Exception> e) {
342      OnExceptionOccured(e.Value);
343    }
344    private void jobDownloader_ExceptionOccured(object sender, EventArgs<Exception> e) {
345      OnExceptionOccured(e.Value);
346    }
347    public void UpdateTotalExecutionTime() {
348      this.ExecutionTime = TimeSpan.FromMilliseconds(this.GetAllHiveJobs().Sum(x => x.Task.ExecutionTime.TotalMilliseconds));
349    }
350    #endregion
351
352    #region Task Events
353    private void RegisterJobEvents() {
354      job.ToStringChanged += new EventHandler(OnToStringChanged);
355      job.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
356      job.ItemImageChanged += new EventHandler(job_ItemImageChanged);
357      job.ModifiedChanged += new EventHandler(job_ModifiedChanged);
358    }
359
360    private void DergisterJobEvents() {
361      job.ToStringChanged -= new EventHandler(OnToStringChanged);
362      job.PropertyChanged -= new PropertyChangedEventHandler(job_PropertyChanged);
363      job.ItemImageChanged -= new EventHandler(job_ItemImageChanged);
364      job.ModifiedChanged -= new EventHandler(job_ModifiedChanged);
365    }
366    #endregion
367
368    #region Event Handler
369    public event EventHandler RefreshAutomaticallyChanged;
370    private void OnRefreshAutomaticallyChanged() {
371      var handler = RefreshAutomaticallyChanged;
372      if (handler != null) handler(this, EventArgs.Empty);
373    }
374
375    public event EventHandler JobChanged;
376    private void OnJobChanged() {
377      var handler = JobChanged;
378      if (handler != null) handler(this, EventArgs.Empty);
379    }
380
381    public event EventHandler ModifiedChanged;
382    private void job_ModifiedChanged(object sender, EventArgs e) {
383      var handler = ModifiedChanged;
384      if (handler != null) handler(sender, e);
385    }
386
387    public event EventHandler ItemImageChanged;
388    private void job_ItemImageChanged(object sender, EventArgs e) {
389      var handler = ItemImageChanged;
390      if (handler != null) handler(this, e);
391    }
392
393    public event PropertyChangedEventHandler PropertyChanged;
394    private void job_PropertyChanged(object sender, PropertyChangedEventArgs e) {
395      this.IsSharable = job.Permission == Permission.Full;
396      this.IsControllable = job.Permission == Permission.Full;
397
398      var handler = PropertyChanged;
399      if (handler != null) handler(sender, e);
400    }
401
402    public event EventHandler ToStringChanged;
403    private void OnToStringChanged(object sender, EventArgs e) {
404      var handler = ToStringChanged;
405      if (handler != null) handler(this, e);
406    }
407
408    public event EventHandler IsProgressingChanged;
409    protected virtual void OnIsProgressingChanged() {
410      var handler = IsProgressingChanged;
411      if (handler != null) handler(this, EventArgs.Empty);
412    }
413
414    public event EventHandler IsDownloadableChanged;
415    private void OnIsDownloadableChanged() {
416      var handler = IsDownloadableChanged;
417      if (handler != null) handler(this, EventArgs.Empty);
418    }
419
420    public event EventHandler IsControllableChanged;
421    private void OnIsControllableChanged() {
422      var handler = IsControllableChanged;
423      if (handler != null) handler(this, EventArgs.Empty);
424    }
425
426    public event EventHandler IsSharableChanged;
427    private void OnIsSharableChanged() {
428      var handler = IsSharableChanged;
429      if (handler != null) handler(this, EventArgs.Empty);
430    }
431
432    public event EventHandler IsAllowedPrivilegedChanged;
433    private void OnIsAllowedPrivilegedChanged() {
434      var handler = IsAllowedPrivilegedChanged;
435      if (handler != null) handler(this, EventArgs.Empty);
436    }
437
438    public event EventHandler JobStatisticsChanged;
439    private void OnJobStatisticsChanged() {
440      var handler = JobStatisticsChanged;
441      if (handler != null) handler(this, EventArgs.Empty);
442    }
443
444    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
445    private void OnExceptionOccured(Exception exception) {
446      log.LogException(exception);
447      var handler = ExceptionOccured;
448      if (handler != null) handler(this, new EventArgs<Exception>(exception));
449    }
450
451    public event EventHandler StateLogListChanged;
452    private void OnStateLogListChanged() {
453      var handler = StateLogListChanged;
454      if (handler != null) handler(this, EventArgs.Empty);
455    }
456
457    public event EventHandler ExecutionTimeChanged;
458    protected virtual void OnExecutionTimeChanged() {
459      var handler = ExecutionTimeChanged;
460      if (handler != null) handler(this, EventArgs.Empty);
461    }
462
463    public event EventHandler ExecutionStateChanged;
464    protected virtual void OnExecutionStateChanged() {
465      var handler = ExecutionStateChanged;
466      if (handler != null) handler(this, EventArgs.Empty);
467    }
468    #endregion
469
470    #region HiveJobs Events
471    private void RegisterHiveJobsEvents() {
472      this.hiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsAdded);
473      this.hiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsRemoved);
474      this.hiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_CollectionReset);
475    }
476
477    private void DeregisterHiveJobsEvents() {
478      this.hiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsAdded);
479      this.hiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsRemoved);
480      this.hiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_CollectionReset);
481    }
482
483    private void hiveJobs_CollectionReset(object sender, CollectionItemsChangedEventArgs<HiveTask> e) {
484      foreach (var item in e.Items) {
485        item.StateLogChanged -= new EventHandler(item_StateLogChanged);
486      }
487      OnHiveJobsReset(e);
488    }
489
490    private void hiveJobs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<HiveTask> e) {
491      foreach (var item in e.Items) {
492        item.StateLogChanged -= new EventHandler(item_StateLogChanged);
493      }
494      OnHiveJobsRemoved(e);
495    }
496
497    private void hiveJobs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<HiveTask> e) {
498      foreach (var item in e.Items) {
499        item.StateLogChanged += new EventHandler(item_StateLogChanged);
500        item.IsControllable = this.IsControllable;
501      }
502      OnHiveJobsAdded(e);
503    }
504
505    private void item_StateLogChanged(object sender, EventArgs e) {
506      OnStateLogListChanged();
507    }
508    #endregion
509
510    public event EventHandler HiveJobsChanged;
511    protected virtual void OnHiveJobsChanged() {
512      if (jobResultPoller != null && jobResultPoller.IsPolling) {
513        jobResultPoller.Stop();
514        DeregisterResultPollingEvents();
515      }
516      if (this.HiveJobs != null && this.HiveJobs.Count > 0 && this.GetAllHiveJobs().All(x => x.Task.Id != Guid.Empty)) {
517        if (this.RefreshAutomatically)
518          StartResultPolling();
519      }
520
521      var handler = HiveJobsChanged;
522      if (handler != null) handler(this, EventArgs.Empty);
523    }
524
525    public event EventHandler Loaded;
526    public virtual void OnLoaded() {
527      this.UpdateTotalExecutionTime();
528
529      if (this.ExecutionState != ExecutionState.Stopped) {
530        this.RefreshAutomatically = true;
531      }
532
533      var handler = Loaded;
534      if (handler != null) handler(this, EventArgs.Empty);
535    }
536
537    public event EventHandler<CollectionItemsChangedEventArgs<HiveTask>> HiveJobsAdded;
538    private void OnHiveJobsAdded(CollectionItemsChangedEventArgs<HiveTask> e) {
539      var handler = HiveJobsAdded;
540      if (handler != null) handler(this, e);
541    }
542
543    public event EventHandler<CollectionItemsChangedEventArgs<HiveTask>> HiveJobsRemoved;
544    private void OnHiveJobsRemoved(CollectionItemsChangedEventArgs<HiveTask> e) {
545      var handler = HiveJobsRemoved;
546      if (handler != null) handler(this, e);
547    }
548
549    public event EventHandler<CollectionItemsChangedEventArgs<HiveTask>> HiveJobsReset;
550    private void OnHiveJobsReset(CollectionItemsChangedEventArgs<HiveTask> e) {
551      var handler = HiveJobsReset;
552      if (handler != null) handler(this, e);
553    }
554
555    public Guid Id {
556      get { return job.Id; }
557      set { job.Id = value; }
558    }
559    public bool Modified {
560      get { return job.Modified; }
561    }
562    public void Store() {
563      job.Store();
564    }
565    public string ItemDescription {
566      get { return job.ItemDescription; }
567    }
568    public Image ItemImage {
569      get { return job.ItemImage; }
570    }
571    public string ItemName {
572      get { return job.ItemName; }
573    }
574    public Version ItemVersion {
575      get { return job.ItemVersion; }
576    }
577
578    public override string ToString() {
579      return string.Format("{0} {1}", Job.DateCreated.ToString("MM.dd.yyyy HH:mm"), Job.ToString());
580    }
581
582    public bool IsFinished() {
583      return HiveJobs != null
584        && HiveJobs.All(x => x.Task.DateFinished.HasValue && x.Task.DateCreated.HasValue);
585    }
586
587    public IEnumerable<HiveTask> GetAllHiveJobs() {
588      if (hiveJobs == null) return Enumerable.Empty<HiveTask>();
589
590      var jobs = new List<HiveTask>();
591      foreach (HiveTask job in HiveJobs) {
592        jobs.AddRange(job.GetAllHiveTasks());
593      }
594      return jobs;
595    }
596
597    public int CompareTo(RefreshableJob other) {
598      return this.ToString().CompareTo(other.ToString());
599    }
600  }
601}
Note: See TracBrowser for help on using the repository browser.