Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

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