Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

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