source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/RefreshableHiveExperiment.cs @ 6478

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

#1233

  • minor improvements
  • binaries
  • stats
File size: 15.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.Common;
28using HeuristicLab.Core;
29
30namespace HeuristicLab.Clients.Hive {
31  public class RefreshableHiveExperiment : IHiveItem, IDeepCloneable, IContent, IProgressReporter {
32    private JobResultPoller jobResultPoller;
33    private ConcurrentJobDownloader<ItemJob> jobDownloader;
34    private static object locker = new object();
35
36    private HiveExperiment hiveExperiment;
37    public HiveExperiment HiveExperiment {
38      get { return hiveExperiment; }
39      set {
40        if (value != hiveExperiment) {
41          if (value == null)
42            throw new ArgumentNullException();
43
44          if (hiveExperiment != null) DergisterHiveExperimentEvents();
45          hiveExperiment = value;
46          if (hiveExperiment != null) RegisterHiveExperimentEvents();
47          OnHiveExperimentChanged();
48        }
49      }
50    }
51
52    private bool refreshAutomatically;
53    public bool RefreshAutomatically {
54      get { return refreshAutomatically; }
55      set {
56        lock (locker) {
57          if (refreshAutomatically != value) {
58            refreshAutomatically = value;
59            OnRefreshAutomaticallyChanged();
60          }
61          if (RefreshAutomatically) {
62            if (hiveExperiment.HiveJobs != null && hiveExperiment.HiveJobs.Count > 0 && (jobResultPoller == null || !jobResultPoller.IsPolling)) {
63              StartResultPolling();
64            }
65          } else {
66            StopResultPolling();
67          }
68        }
69      }
70    }
71
72    // if true, all control buttons should be enabled. otherwise disabled (used for HiveEngine)
73    private bool isControllable = true;
74    public bool IsControllable {
75      get { return isControllable; }
76      set {
77        if (value != isControllable) {
78          isControllable = value;
79          OnIsControllableChanged();
80        }
81      }
82    }
83
84    private ThreadSafeLog log;
85    public ILog Log {
86      get { return log; }
87    }
88
89    #region Constructors and Cloning
90    public RefreshableHiveExperiment() {
91      this.refreshAutomatically = true;
92      this.HiveExperiment = new HiveExperiment();
93      this.log = new ThreadSafeLog(new Log());
94      this.jobDownloader = new ConcurrentJobDownloader<ItemJob>(2, 2);
95      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
96    }
97    public RefreshableHiveExperiment(HiveExperiment hiveExperiment) {
98      this.refreshAutomatically = true;
99      this.HiveExperiment = hiveExperiment;
100      this.log = new ThreadSafeLog(new Log());
101      this.jobDownloader = new ConcurrentJobDownloader<ItemJob>(2, 2);
102      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
103    }
104    protected RefreshableHiveExperiment(RefreshableHiveExperiment original, Cloner cloner) {
105      cloner.RegisterClonedObject(original, this);
106      this.HiveExperiment = original.HiveExperiment;
107      this.IsControllable = original.IsControllable;
108      this.log = cloner.Clone(original.log);
109      this.RefreshAutomatically = false; // do not start results polling automatically
110      this.jobDownloader = new ConcurrentJobDownloader<ItemJob>(2, 2);
111      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
112    }
113    public IDeepCloneable Clone(Cloner cloner) {
114      return new RefreshableHiveExperiment(this, cloner);
115    }
116    public object Clone() {
117      return this.Clone(new Cloner());
118    }
119    #endregion
120
121    private void hiveExperiment_HiveJobsChanged(object sender, EventArgs e) {
122      if (jobResultPoller != null && jobResultPoller.IsPolling) {
123        jobResultPoller.Stop();
124        DeregisterResultPollingEvents();
125      }
126      if (hiveExperiment.HiveJobs != null && hiveExperiment.HiveJobs.Count > 0 && hiveExperiment.GetAllHiveJobs().All(x => x.Job.Id != Guid.Empty)) {
127        if (this.RefreshAutomatically)
128          StartResultPolling();
129      }
130    }
131
132    #region JobResultPoller Events
133
134    public void StartResultPolling() {
135      if (jobResultPoller == null) {
136        jobResultPoller = new JobResultPoller(hiveExperiment.Id, /*ApplicationConstants.ResultPollingInterval*/new TimeSpan(0, 0, 5)); //TODO: find a better place for ApplicationConstants
137        RegisterResultPollingEvents();
138        jobResultPoller.AutoResumeOnException = true;
139      }
140
141      if (!jobResultPoller.IsPolling) {
142        jobResultPoller.Start();
143      }
144    }
145
146    public void StopResultPolling() {
147      if (jobResultPoller != null && jobResultPoller.IsPolling) {
148        jobResultPoller.Stop();
149      }
150    }
151
152    private void RegisterResultPollingEvents() {
153      jobResultPoller.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
154      jobResultPoller.JobResultsReceived += new EventHandler<EventArgs<IEnumerable<LightweightJob>>>(jobResultPoller_JobResultReceived);
155      jobResultPoller.IsPollingChanged += new EventHandler(jobResultPoller_IsPollingChanged);
156    }
157    private void DeregisterResultPollingEvents() {
158      jobResultPoller.ExceptionOccured -= new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
159      jobResultPoller.JobResultsReceived -= new EventHandler<EventArgs<IEnumerable<LightweightJob>>>(jobResultPoller_JobResultReceived);
160      jobResultPoller.IsPollingChanged -= new EventHandler(jobResultPoller_IsPollingChanged);
161    }
162    private void jobResultPoller_IsPollingChanged(object sender, EventArgs e) {
163      if (this.refreshAutomatically != jobResultPoller.IsPolling) {
164        this.refreshAutomatically = jobResultPoller.IsPolling;
165        OnRefreshAutomaticallyChanged();
166      }
167    }
168    private void jobResultPoller_JobResultReceived(object sender, EventArgs<IEnumerable<LightweightJob>> e) {
169      foreach (LightweightJob lightweightJob in e.Value) {
170        HiveJob hiveJob = GetHiveJobById(lightweightJob.Id);
171        if (hiveJob != null) {
172          // lastJobDataUpdate equals DateTime.MinValue right after it was uploaded. When the first results are polled, this value is updated
173          if (hiveJob.Job.State == JobState.Offline && lightweightJob.State != JobState.Finished && lightweightJob.State != JobState.Failed && lightweightJob.State != JobState.Aborted) {
174            hiveJob.Job.LastJobDataUpdate = lightweightJob.LastJobDataUpdate;
175          }
176
177          hiveJob.UpdateFromLightweightJob(lightweightJob);
178
179          if (!hiveJob.IsFinishedJobDownloaded && !hiveJob.IsDownloading && hiveJob.Job.LastJobDataUpdate < lightweightJob.LastJobDataUpdate) {
180            log.LogMessage(string.Format("Downloading job {0}", lightweightJob.Id));
181            hiveJob.IsDownloading = true;
182            jobDownloader.DownloadJob(hiveJob.Job, (localJob, itemJob) => {
183              log.LogMessage(string.Format("Finished downloading job {0}", localJob.Id));
184              HiveJob localHiveJob = GetHiveJobById(localJob.Id);
185
186              if (itemJob == null) {
187                localHiveJob.IsDownloading = false;
188              }
189
190              if (itemJob == null) {
191                // something bad happened to this job. bad job, BAAAD job!
192              } else {
193                // if the job is paused, download but don't integrate into parent optimizer (to avoid Prepare)
194
195                if (localJob.State == JobState.Paused) {
196                  localHiveJob.ItemJob = itemJob;
197                } else {
198                  if (localJob.ParentJobId.HasValue) {
199                    HiveJob parentHiveJob = GetHiveJobById(localJob.ParentJobId.Value);
200                    parentHiveJob.IntegrateChild(itemJob, localJob.Id);
201                  } else {
202                    localHiveJob.ItemJob = itemJob;
203                  }
204                }
205                localHiveJob.IsDownloading = false;
206                localHiveJob.Job.LastJobDataUpdate = localJob.LastJobDataUpdate;
207              }
208            });
209          }
210        }
211      }
212      GC.Collect(); // force GC, because .NET is too lazy here (deserialization takes a lot of memory)
213      if (AllJobsFinished()) {
214        hiveExperiment.ExecutionState = Core.ExecutionState.Stopped;
215        StopResultPolling();
216      }
217      UpdateTotalExecutionTime();
218      UpdateStatistics();
219      OnStateLogListChanged();
220    }
221
222    public HiveJob GetHiveJobById(Guid jobId) {
223      foreach (HiveJob job in hiveExperiment.HiveJobs) {
224        var hj = job.GetHiveJobByJobId(jobId);
225        if (hj != null)
226          return hj;
227      }
228      return null;
229    }
230    private void UpdateStatistics() {
231      var jobs = hiveExperiment.GetAllHiveJobs();
232      hiveExperiment.JobCount = jobs.Count();
233      hiveExperiment.CalculatingCount = jobs.Count(j => j.Job.State == JobState.Calculating);
234      hiveExperiment.FinishedCount = jobs.Count(j => j.Job.State == JobState.Finished);
235      OnJobStatisticsChanged();
236    }
237
238    public bool AllJobsFinished() {
239      return hiveExperiment.GetAllHiveJobs().All(j => (j.Job.State == JobState.Finished
240                                                   || j.Job.State == JobState.Aborted
241                                                   || j.Job.State == JobState.Failed)
242                                                   && j.IsFinishedJobDownloaded);
243    }
244
245    private void jobResultPoller_ExceptionOccured(object sender, EventArgs<Exception> e) {
246      OnExceptionOccured(e.Value);
247    }
248    private void jobDownloader_ExceptionOccured(object sender, EventArgs<Exception> e) {
249      OnExceptionOccured(e.Value);
250    }
251    public void UpdateTotalExecutionTime() {
252      hiveExperiment.ExecutionTime = TimeSpan.FromMilliseconds(hiveExperiment.GetAllHiveJobs().Sum(x => x.Job.ExecutionTime.TotalMilliseconds));
253    }
254    #endregion
255
256    #region HiveExperiment Events
257    private void RegisterHiveExperimentEvents() {
258      hiveExperiment.HiveJobsChanged += new EventHandler(hiveExperiment_HiveJobsChanged);
259      hiveExperiment.ToStringChanged += new EventHandler(hiveExperiment_ToStringChanged);
260      hiveExperiment.PropertyChanged += new PropertyChangedEventHandler(hiveExperiment_PropertyChanged);
261      hiveExperiment.ItemImageChanged += new EventHandler(hiveExperiment_ItemImageChanged);
262      hiveExperiment.ModifiedChanged += new EventHandler(hiveExperiment_ModifiedChanged);
263      hiveExperiment.IsProgressingChanged += new EventHandler(hiveExperiment_IsProgressingChanged);
264      hiveExperiment.Loaded += new EventHandler(hiveExperiment_Loaded);
265    }
266
267    private void DergisterHiveExperimentEvents() {
268      hiveExperiment.HiveJobsChanged -= new EventHandler(hiveExperiment_HiveJobsChanged);
269      hiveExperiment.ToStringChanged -= new EventHandler(hiveExperiment_ToStringChanged);
270      hiveExperiment.PropertyChanged -= new PropertyChangedEventHandler(hiveExperiment_PropertyChanged);
271      hiveExperiment.ItemImageChanged -= new EventHandler(hiveExperiment_ItemImageChanged);
272      hiveExperiment.ModifiedChanged -= new EventHandler(hiveExperiment_ModifiedChanged);
273      hiveExperiment.IsProgressingChanged -= new EventHandler(hiveExperiment_IsProgressingChanged);
274      hiveExperiment.Loaded -= new EventHandler(hiveExperiment_Loaded);
275    }
276
277    private void hiveExperiment_Loaded(object sender, EventArgs e) {
278      this.UpdateTotalExecutionTime();
279
280      if (hiveExperiment.ExecutionState != ExecutionState.Stopped) {
281        this.RefreshAutomatically = true;
282      }
283    }
284    #endregion
285
286    #region Event Handler
287    public event EventHandler RefreshAutomaticallyChanged;
288    private void OnRefreshAutomaticallyChanged() {
289      var handler = RefreshAutomaticallyChanged;
290      if (handler != null) handler(this, EventArgs.Empty);
291    }
292
293    public event EventHandler HiveExperimentChanged;
294    private void OnHiveExperimentChanged() {
295      var handler = HiveExperimentChanged;
296      if (handler != null) handler(this, EventArgs.Empty);
297    }
298
299    public event EventHandler ModifiedChanged;
300    private void hiveExperiment_ModifiedChanged(object sender, EventArgs e) {
301      var handler = ModifiedChanged;
302      if (handler != null) handler(sender, e);
303    }
304
305    public event EventHandler ItemImageChanged;
306    private void hiveExperiment_ItemImageChanged(object sender, EventArgs e) {
307      var handler = ItemImageChanged;
308      if (handler != null) handler(this, e);
309    }
310
311    public event PropertyChangedEventHandler PropertyChanged;
312    private void hiveExperiment_PropertyChanged(object sender, PropertyChangedEventArgs e) {
313      var handler = PropertyChanged;
314      if (handler != null) handler(sender, e);
315    }
316
317    public event EventHandler ToStringChanged;
318    private void hiveExperiment_ToStringChanged(object sender, EventArgs e) {
319      var handler = ToStringChanged;
320      if (handler != null) handler(this, e);
321    }
322
323    public event EventHandler IsProgressingChanged;
324    private void hiveExperiment_IsProgressingChanged(object sender, EventArgs e) {
325      var handler = IsProgressingChanged;
326      if (handler != null) handler(sender, e);
327    }
328
329    public event EventHandler IsControllableChanged;
330    private void OnIsControllableChanged() {
331      var handler = IsControllableChanged;
332      if (handler != null) handler(this, EventArgs.Empty);
333    }
334
335    public event EventHandler JobStatisticsChanged;
336    private void OnJobStatisticsChanged() {
337      var handler = JobStatisticsChanged;
338      if (handler != null) handler(this, EventArgs.Empty);
339    }
340
341    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
342    private void OnExceptionOccured(Exception exception) {
343      log.LogException(exception);
344      var handler = ExceptionOccured;
345      if (handler != null) handler(this, new EventArgs<Exception>(exception));
346    }
347
348    public event EventHandler StateLogListChanged;
349    private void OnStateLogListChanged() {
350      var handler = StateLogListChanged;
351      if (handler != null) handler(this, EventArgs.Empty);
352    }
353    #endregion
354
355    public Guid Id {
356      get { return hiveExperiment.Id; }
357      set { hiveExperiment.Id = value; }
358    }
359    public bool Modified {
360      get { return hiveExperiment.Modified; }
361    }
362    public void Store() {
363      hiveExperiment.Store();
364    }
365    public string ItemDescription {
366      get { return hiveExperiment.ItemDescription; }
367    }
368    public Image ItemImage {
369      get { return hiveExperiment.ItemImage; }
370    }
371    public string ItemName {
372      get { return hiveExperiment.ItemName; }
373    }
374    public Version ItemVersion {
375      get { return hiveExperiment.ItemVersion; }
376    }
377   
378    #region IProgressReporter Members
379    public IProgress Progress {
380      get { return HiveExperiment.Progress; }
381    }
382
383    public bool IsProgressing {
384      get { return HiveExperiment.IsProgressing; }
385    }
386    #endregion
387
388    public override string ToString() {
389      return string.Format("{0} {1}", HiveExperiment.DateCreated.ToString("MM.dd.yyyy HH:mm"), HiveExperiment.ToString());
390    }
391  }
392}
Note: See TracBrowser for help on using the repository browser.