Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 6200 was 6200, checked in by cneumuel, 13 years ago

#1233

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