source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveExperiment.cs @ 6006

Last change on this file since 6006 was 6006, checked in by cneumuel, 9 years ago

#1233

  • changed relationship between Job and HiveExperiment. There is no more HiveExperiment.RootJobId, instead there is Job.HiveExperimentId.
  • One HiveExperiment can now have multiple Experiments.
  • TreeView supports multiple root nodes
  • HiveEngine creates a HiveExperiment for each set of jobs, so jobs cannot be without an parent experiment anymore (no more loose jobs)
  • updated ExperimentManager binaries
File size: 12.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Linq;
26using HeuristicLab.Clients.Hive.Jobs;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Optimization;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31
32namespace HeuristicLab.Clients.Hive {
33  [StorableClass]
34  public partial class HiveExperiment : IDeepCloneable, IContent, IProgressReporter {
35    private JobResultPoller jobResultPoller;
36
37    [Storable]
38    private bool useLocalPlugins;
39    public bool UseLocalPlugins {
40      get { return useLocalPlugins; }
41      set { useLocalPlugins = value; }
42    }
43
44    [Storable]
45    private ExecutionState executionState;
46    public ExecutionState ExecutionState {
47      get { return executionState; }
48      internal set {
49        if (executionState != value) {
50          executionState = value;
51          OnExecutionStateChanged();
52        }
53      }
54    }
55
56    [Storable]
57    private TimeSpan executionTime;
58    public TimeSpan ExecutionTime {
59      get { return executionTime; }
60      internal set {
61        if (executionTime != value) {
62          executionTime = value;
63          OnExecutionTimeChanged();
64        }
65      }
66    }
67
68    [Storable]
69    private ItemCollection<HiveJob> hiveJobs;
70    public ItemCollection<HiveJob> HiveJobs {
71      get { return hiveJobs; }
72      set {
73        DeregisterHiveJobsEvents();
74        if (hiveJobs != value) {
75          hiveJobs = value;
76          RegisterHiveJobsEvents();
77          OnHiveJobsChanged();
78        }
79      }
80    }
81
82    [Storable]
83    private bool isProgressing;
84    public bool IsProgressing {
85      get { return isProgressing; }
86      set {
87        if (isProgressing != value) {
88          isProgressing = value;
89          OnIsProgressingChanged();
90        }
91      }
92    }
93
94    /** include jobs when refreshing **/
95    [Storable]
96    private bool includeJobs;
97    public bool IncludeJobs {
98      get { return includeJobs; }
99      set { includeJobs = value; }
100    }
101
102    [Storable]
103    private bool refreshAutomatically;
104    public bool RefreshAutomatically {
105      get { return refreshAutomatically; }
106      set {
107        if (refreshAutomatically != value) {
108          refreshAutomatically = value;
109          OnRefreshAutomaticallyChanged();
110          if (RefreshAutomatically) {
111            StartResultPolling();
112          } else {
113            StopResultPolling();
114          }
115        }
116      }
117    }
118
119    [Storable]
120    private IProgress progress;
121    public IProgress Progress {
122      get { return progress; }
123      set { this.progress = value; }
124    }
125
126    #region Constructors and Cloning
127    public HiveExperiment() {
128      this.ResourceNames = "HEAL";
129      this.includeJobs = true;
130      this.refreshAutomatically = true;
131    }
132
133    protected HiveExperiment(HiveExperiment original, Cloner cloner) {
134      cloner.RegisterClonedObject(original, this);
135      this.OwnerUserId = original.OwnerUserId;
136      this.DateCreated = original.DateCreated;
137      this.ResourceNames = original.ResourceNames;
138      this.LastAccessed = original.LastAccessed;
139      this.Name = original.Name;
140      this.Description = original.Description;
141      this.Id = original.Id;
142
143      this.UseLocalPlugins = original.UseLocalPlugins;
144      this.ExecutionTime = original.ExecutionTime;
145    }
146    public override IDeepCloneable Clone(Cloner cloner) {
147      return new HiveExperiment(this, cloner);
148    }
149    #endregion
150
151    public override string ToString() {
152      return Name;
153    }
154
155    #region Events
156    public event EventHandler ExecutionTimeChanged;
157    private void OnExecutionTimeChanged() {
158      EventHandler handler = ExecutionTimeChanged;
159      if (handler != null) handler(this, EventArgs.Empty);
160    }
161
162    public event EventHandler ExecutionStateChanged;
163    private void OnExecutionStateChanged() {
164      EventHandler handler = ExecutionStateChanged;
165      if (handler != null) handler(this, EventArgs.Empty);
166    }
167
168    public event EventHandler HiveJobsChanged;
169    private void OnHiveJobsChanged() {
170      if (jobResultPoller != null && jobResultPoller.IsPolling) {
171        jobResultPoller.Stop();
172        DeregisterResultPollingEvents();
173      }
174      if (HiveJobs != null && HiveJobs.Count > 0 && GetAllHiveJobs().All(x => x.Job.Id != Guid.Empty)) {
175        if (this.RefreshAutomatically)
176          StartResultPolling();
177      }
178      EventHandler handler = HiveJobsChanged;
179      if (handler != null) handler(this, EventArgs.Empty);
180    }
181
182    public event EventHandler IsProgressingChanged;
183    private void OnIsProgressingChanged() {
184      EventHandler handler = IsProgressingChanged;
185      if (handler != null) handler(this, EventArgs.Empty);
186    }
187
188    public event EventHandler RefreshAutomaticallyChanged;
189    private void OnRefreshAutomaticallyChanged() {
190      EventHandler handler = RefreshAutomaticallyChanged;
191      if (handler != null) handler(this, EventArgs.Empty);
192    }
193    #endregion
194
195    private void RegisterHiveJobsEvents() {
196      //if (HiveJobs != null) {
197      //  HiveJobs.JobStateChanged += new EventHandler(HiveJob_JobStateChanged);
198      //}
199    }
200
201    private void DeregisterHiveJobsEvents() {
202      //if (HiveJobs != null) {
203      //  HiveJobs.JobStateChanged -= new EventHandler(HiveJob_JobStateChanged);
204      //}
205    }
206
207    private void HiveJob_JobStateChanged(object sender, EventArgs e) {
208      //if (this.HiveJobs != null) {
209      //  this.RootJobId = HiveJobs.Job.Id;
210      //}
211    }
212
213    public Experiment GetExperiment(int idx) {
214      if (this.HiveJobs != null) {
215        var hj = HiveJobs.ElementAtOrDefault(idx);
216        if (hj != null)
217          return hj.OptimizerJob.OptimizerAsExperiment;
218      }
219      return null;
220    }
221
222    public void AddExperiment(Experiment experiment) {
223      if (this.HiveJobs == null)
224        this.HiveJobs = new ItemCollection<HiveJob>();
225      this.HiveJobs.Add(new HiveJob(experiment));
226    }
227
228    public void SetExperiment(Experiment experiment) {
229      if (this.HiveJobs == null)
230        this.HiveJobs = new ItemCollection<HiveJob>();
231      else
232        this.HiveJobs.Clear();
233      this.HiveJobs.Add(new HiveJob(experiment));
234    }
235
236    protected override void OnPropertyChanged(PropertyChangedEventArgs e) {
237      base.OnPropertyChanged(e);
238      if (e.PropertyName == "Name") {
239        OnToStringChanged();
240      }
241    }
242
243    #region JobResultPoller Events
244
245    public void StartResultPolling() {
246      if (jobResultPoller == null) {
247        jobResultPoller = new JobResultPoller(HiveJobs, /*ApplicationConstants.ResultPollingInterval*/new TimeSpan(0, 0, 5)); //TODO: find a better place for ApplicationConstants
248        RegisterResultPollingEvents();
249      }
250
251      if (!jobResultPoller.IsPolling) {
252        jobResultPoller.Start();
253      }
254    }
255
256    public void StopResultPolling() {
257      if (jobResultPoller != null && jobResultPoller.IsPolling) {
258        jobResultPoller.Stop();
259      }
260    }
261
262    private void RegisterResultPollingEvents() {
263      jobResultPoller.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
264      jobResultPoller.JobResultsReceived += new EventHandler<EventArgs<IEnumerable<LightweightJob>>>(jobResultPoller_JobResultReceived);
265      jobResultPoller.IsPollingChanged += new EventHandler(jobResultPoller_IsPollingChanged);
266    }
267    private void DeregisterResultPollingEvents() {
268      jobResultPoller.ExceptionOccured -= new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
269      jobResultPoller.JobResultsReceived -= new EventHandler<EventArgs<IEnumerable<LightweightJob>>>(jobResultPoller_JobResultReceived);
270      jobResultPoller.IsPollingChanged -= new EventHandler(jobResultPoller_IsPollingChanged);
271    }
272    private void jobResultPoller_IsPollingChanged(object sender, EventArgs e) {
273      this.refreshAutomatically = jobResultPoller.IsPolling;
274      OnRefreshAutomaticallyChanged();
275    }
276    private void jobResultPoller_JobResultReceived(object sender, EventArgs<IEnumerable<LightweightJob>> e) {
277      foreach (LightweightJob lightweightJob in e.Value) {
278        HiveJob hj = GetHiveJobById(lightweightJob.Id);
279        if (hj != null) {
280          DateTime lastJobDataUpdate = hj.Job.LastJobDataUpdate;
281          hj.UpdateFromLightweightJob(lightweightJob);
282
283          // lastJobDataUpdate equals DateTime.MinValue right after it was uploaded. When the first results are polled, this value is updated
284          if (lastJobDataUpdate != DateTime.MinValue && lastJobDataUpdate < hj.Job.LastJobDataUpdate) {
285            OptimizerJob optimizerJob = ExperimentManagerClient.LoadOptimizerJob(hj.Job.Id);
286            if (optimizerJob == null) {
287              // something bad happened to this job. bad job, BAAAD job!
288            } else {
289              // if the job is paused, download but don't integrate into parent optimizer (to avoid Prepare)
290              if (hj.Job.State == JobState.Paused) {
291                hj.OptimizerJob = optimizerJob;
292              } else {
293                if (lightweightJob.ParentJobId.HasValue) {
294                  HiveJob parentHiveJob = GetHiveJobById(lightweightJob.ParentJobId.Value);
295                  parentHiveJob.UpdateChildOptimizer(optimizerJob, hj.Job.Id);
296                }
297              }
298            }
299          }
300        }
301      }
302      GC.Collect(); // force GC, because .NET is too lazy here (deserialization takes a lot of memory)
303      if (AllJobsFinished()) {
304        this.ExecutionState = Core.ExecutionState.Stopped;
305        StopResultPolling();
306        //OnStopped();
307      }
308      UpdateTotalExecutionTime();
309      UpdateStats();
310    }
311
312    public HiveJob GetHiveJobById(Guid jobId) {
313      foreach (HiveJob job in HiveJobs) {
314        HiveJob hj = job.GetHiveJobByJobId(jobId);
315        if (hj != null)
316          return hj;
317      }
318      return null;
319    }
320
321    private void UpdateStats() {
322      var jobs = GetAllHiveJobs();
323      this.JobCount = jobs.Count();
324      this.CalculatingCount = jobs.Count(j => j.Job.State == JobState.Calculating);
325      this.FinishedCount = jobs.Count(j => j.Job.State == JobState.Finished);
326    }
327
328    public IEnumerable<HiveJob> GetAllHiveJobs() {
329      var jobs = new List<HiveJob>();
330      foreach (HiveJob job in HiveJobs) {
331        jobs.AddRange(job.GetAllHiveJobs());
332      }
333      return jobs;
334    }
335
336    public bool AllJobsFinished() {
337      return GetAllHiveJobs().All(j => j.Job.State == JobState.Finished
338                                            || j.Job.State == JobState.Aborted
339                                            || j.Job.State == JobState.Failed);
340    }
341
342    private void jobResultPoller_ExceptionOccured(object sender, EventArgs<Exception> e) {
343      //OnExceptionOccured(e.Value);
344    }
345
346    public void UpdateTotalExecutionTime() {
347      this.ExecutionTime = TimeSpan.FromMilliseconds(GetAllHiveJobs().Sum(x => x.Job.ExecutionTime.HasValue ? x.Job.ExecutionTime.Value.TotalMilliseconds : 0));
348    }
349    #endregion
350
351    protected override void RaisePropertyChanged(string propertyName) {
352      if (!(propertyName == "ExecutionTime")
353        && !(propertyName == "JobCount")
354        && !(propertyName == "CalculatingCount")
355        && !(propertyName == "FinishedCount")) {
356        base.RaisePropertyChanged(propertyName);
357      }
358    }
359
360    public bool IsFinished() {
361      return HiveJobs != null
362        && HiveJobs.All(x => x.Job.DateFinished.HasValue && x.Job.DateCreated.HasValue);
363    }
364  }
365}
Note: See TracBrowser for help on using the repository browser.