Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3.3-HiveMigration/sources/HeuristicLab.Hive/HeuristicLab.Hive.Experiment/3.3/HiveExperiment.cs @ 4119

Last change on this file since 4119 was 4119, checked in by cneumuel, 14 years ago

HiveExperiment is now able to send IOptimizers of an Experiment and receive the calculated result (#1115)

File size: 14.0 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.Linq;
24using HeuristicLab.Common;
25using HeuristicLab.Core;
26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
27using HeuristicLab.Optimization;
28using System.Drawing;
29using HeuristicLab.Collections;
30using System.Collections.Generic;
31using HeuristicLab.Hive.Contracts.BusinessObjects;
32using System.IO;
33using HeuristicLab.Persistence.Default.Xml;
34using HeuristicLab.PluginInfrastructure;
35using System.Reflection;
36using HeuristicLab.Hive.Contracts.Interfaces;
37using HeuristicLab.Hive.Contracts;
38using System.Threading;
39using HeuristicLab.Tracing;
40using HeuristicLab.Hive.JobBase;
41using System.Diagnostics;
42using System.Collections;
43
44namespace HeuristicLab.Hive.Experiment {
45  /// <summary>
46  /// An experiment which contains multiple batch runs of algorithms.
47  /// </summary>
48  [Item(itemName, itemDescription)]
49  [Creatable("Testing & Analysis")]
50  [StorableClass]
51  public class HiveExperiment : NamedItem, IExecutable {
52    private const string itemName = "Hive Experiment";
53    private const string itemDescription = "An experiment which contains multiple batch runs of algorithms which are executed in the Hive.";
54    private const int resultPollingIntervalMs = 10000;
55
56    private const int maxSnapshotRetries = 20;
57
58    [Storable]
59    private IDictionary<Guid, IOptimizer> sentOptimizers = null;
60
61    private object locker = new object();
62    private DateTime startTime;
63
64    [Storable]
65    private string serverUrl;
66    public string ServerUrl {
67      get { return serverUrl; }
68      set { serverUrl = value; OnServerUrlChanged(); }
69    }
70
71    [Storable]
72    private string resourceIds;
73    public string ResourceIds {
74      get { return resourceIds; }
75      set { resourceIds = value; OnResourceIdsChanged(); }
76    }
77
78    [Storable]
79    private HeuristicLab.Optimization.Experiment experiment;
80    public HeuristicLab.Optimization.Experiment Experiment {
81      get { return experiment; }
82      set { experiment = value; OnExperimentChanged(); }
83    }
84
85    [StorableConstructor]
86    public HiveExperiment(bool deserializing)
87      : base(deserializing) {
88    }
89
90    public HiveExperiment()
91      : base(itemName, itemDescription) {
92      this.ServerUrl = HeuristicLab.Hive.Experiment.Properties.Settings.Default.HiveServerUrl;
93      this.ResourceIds = HeuristicLab.Hive.Experiment.Properties.Settings.Default.ResourceIds;
94    }
95
96    public override IDeepCloneable Clone(Cloner cloner) {
97      HiveExperiment clone = (HiveExperiment)base.Clone(cloner);
98      clone.resourceIds = this.resourceIds;
99      clone.serverUrl = this.serverUrl;
100      clone.experiment = (HeuristicLab.Optimization.Experiment)cloner.Clone(experiment);
101      clone.executionState = this.executionState;
102      clone.executionTime = this.executionTime;
103      clone.sentOptimizers = new Dictionary<Guid, IOptimizer>();
104      foreach (var pair in this.sentOptimizers)
105        clone.sentOptimizers[pair.Key] = (IOptimizer)cloner.Clone(pair.Value);
106      return clone;
107    }
108
109    public IEnumerable<string> ResourceGroups {
110      get {
111        if (!string.IsNullOrEmpty(resourceIds)) {
112          return resourceIds.Split(';');
113        } else {
114          return new List<string>();
115        }
116      }
117    }
118    #region IExecutable Members
119
120    [Storable]
121    private Core.ExecutionState executionState;
122    public ExecutionState ExecutionState {
123      get { return executionState; }
124      private set {
125        if (executionState != value) {
126          executionState = value;
127          OnExecutionStateChanged();
128        }
129      }
130    }
131
132    [Storable]
133    private TimeSpan executionTime;
134    public TimeSpan ExecutionTime {
135      get { return executionTime; }
136      private set {
137        executionTime = value;
138        OnExecutionTimeChanged();
139      }
140    }
141
142    public void Pause() {
143      throw new NotSupportedException();
144    }
145
146    public void Prepare() {
147      // [chn] needed?
148      if (experiment != null) {
149        experiment.Prepare();
150        OnPrepared();
151      }
152    }
153
154    public void Start() {
155      this.startTime = DateTime.Now;
156      this.ExecutionState = Core.ExecutionState.Started;
157      IExecutionEngineFacade executionEngineFacade = ServiceLocator.CreateExecutionEngineFacade(ServerUrl);
158
159      sentOptimizers = new Dictionary<Guid, IOptimizer>();
160      IEnumerable<string> groups = ResourceGroups;
161
162      foreach (IOptimizer optimizer in Experiment.Optimizers) {
163        SerializedJob serializedJob = CreateSerializedJob(optimizer);
164        ResponseObject<JobDto> response = executionEngineFacade.AddJobWithGroupStrings(serializedJob, groups);
165        sentOptimizers.Add(response.Obj.Id, optimizer);
166        StartResultPollingThread(response.Obj);
167      }
168    }
169
170    public void Stop() {
171      // todo
172    }
173
174    private bool abortRequested;
175
176    #endregion
177
178    private SerializedJob CreateSerializedJob(IOptimizer optimizer) {
179      IJob job = new OptimizerJob() {
180        Optimizer = optimizer
181      };
182
183      // serialize job
184      MemoryStream memStream = new MemoryStream();
185      XmlGenerator.Serialize(job, memStream);
186      byte[] jobByteArray = memStream.ToArray();
187      memStream.Dispose();
188
189      // find out which which plugins are needed for the given object
190      List<HivePluginInfoDto> pluginsNeeded = (
191        from p in GetDeclaringPlugins(optimizer.GetType())
192        select new HivePluginInfoDto() {
193          Name = p.Name,
194          Version = p.Version
195        }).ToList();
196
197      JobDto jobDto = new JobDto() {
198        CoresNeeded = 1, // [chn] how to determine real cores needed?
199        PluginsNeeded = pluginsNeeded,
200        State = State.Offline,
201        MemoryNeeded = 0,
202        UserId = Guid.Empty // [chn] set real userid here!
203      };
204
205      SerializedJob serializedJob = new SerializedJob() {
206        JobInfo = jobDto,
207        SerializedJobData = jobByteArray
208      };
209
210      return serializedJob;
211    }
212
213    private void StartResultPollingThread(JobDto job) {
214      Thread t = new Thread(() => {
215        IExecutionEngineFacade executionEngineFacade = ServiceLocator.CreateExecutionEngineFacade(ServerUrl);
216        IJob restoredObject = null;
217
218        do {
219          Thread.Sleep(resultPollingIntervalMs);
220          lock (locker) {
221            if (abortRequested) return;
222
223            ResponseObject<SerializedJob> response = executionEngineFacade.GetLastSerializedResult(job.Id, false, false);
224
225            // loop while
226            // 1. the user doesn't request an abort
227            // 2. there is a problem with server communication (success==false)
228            // 3. no result for the job is available yet (response.Obj==null)
229            // 4. the result that we get from the server is a snapshot and not the final result
230            if (response.Success && response.Obj != null && response.StatusMessage != ApplicationConstants.RESPONSE_JOB_RESULT_NOT_YET_HERE) {
231
232              // [chn] todo: deserialization into interface is not possible! how to find out correct static type?
233              restoredObject = XmlParser.Deserialize<IJob>(new MemoryStream(response.Obj.SerializedJobData));
234            }
235          }
236        } while (restoredObject == null || restoredObject.ExecutionState != Core.ExecutionState.Stopped);
237
238        // job retrieved... replace the existing optimizers with the finished one
239        IOptimizer originalOptimizer = sentOptimizers[job.Id];
240        IOptimizer restoredOptimizer = ((OptimizerJob)restoredObject).Optimizer;
241
242        int originalOptimizerIndex = experiment.Optimizers.IndexOf(originalOptimizer);
243        experiment.Optimizers[originalOptimizerIndex] = restoredOptimizer;
244        sentOptimizers.Remove(job.Id);
245
246        if (sentOptimizers.Count == 0) {
247          // finished
248          this.ExecutionState = Core.ExecutionState.Stopped;
249          OnStopped();
250        }
251      });
252
253      Logger.Debug("HiveEngine: Starting results-polling thread");
254      t.Start();
255    }
256
257
258    #region Required Plugin Search
259    /// <summary>
260    /// Returns a list of plugins in which the type itself and all members
261    /// of the type are declared. Objectgraph is searched recursively.
262    /// </summary>
263    private IEnumerable<IPluginDescription> GetDeclaringPlugins(Type type) {
264      HashSet<Type> types = new HashSet<Type>();
265      FindTypes(type, types, "HeuristicLab.");
266      return GetDeclaringPlugins(types);
267    }
268
269    /// <summary>
270    /// Returns the plugins (including dependencies) in which the given types are declared
271    /// </summary>
272    private IEnumerable<IPluginDescription> GetDeclaringPlugins(IEnumerable<Type> types) {
273      HashSet<IPluginDescription> plugins = new HashSet<IPluginDescription>();
274      foreach (Type t in types) {
275        FindDeclaringPlugins(ApplicationManager.Manager.GetDeclaringPlugin(t), plugins);
276      }
277      return plugins;
278    }
279
280    /// <summary>
281    /// Finds the dependencies of the given plugin and adds it to the plugins hashset.
282    /// Also searches the dependencies recursively.
283    /// </summary>
284    private void FindDeclaringPlugins(IPluginDescription plugin, HashSet<IPluginDescription> plugins) {
285      if (!plugins.Contains(plugin)) {
286        plugins.Add(plugin);
287        foreach (IPluginDescription dependency in plugin.Dependencies) {
288          FindDeclaringPlugins(dependency, plugins);
289        }
290      }
291    }
292
293    /// <summary>
294    /// Recursively finds all types used in type which are in a namespace which starts with namespaceStart
295    /// Be aware that search is not performed on attributes
296    /// </summary>
297    /// <param name="type">the type to be searched</param>
298    /// <param name="types">found types will be stored there, needed in order to avoid duplicates</param>
299    /// <param name="namespaceStart">only types from namespaces which start with this will be searched and added</param>
300    private void FindTypes(Type type, HashSet<Type> types, string namespaceStart) {
301      if (!types.Contains(type) && type.Namespace.StartsWith(namespaceStart)) {
302        types.Add(type);
303
304        // constructors
305        foreach (ConstructorInfo info in type.GetConstructors()) {
306          foreach (ParameterInfo paramInfo in info.GetParameters()) {
307            FindTypes(paramInfo.ParameterType, types, namespaceStart);
308          }
309        }
310
311        // interfaces
312        foreach (Type t in type.GetInterfaces()) {
313          FindTypes(t, types, namespaceStart);
314        }
315
316        // events
317        foreach (EventInfo info in type.GetEvents()) {
318          FindTypes(info.EventHandlerType, types, namespaceStart);
319          FindTypes(info.DeclaringType, types, namespaceStart);
320        }
321
322        // properties
323        foreach (PropertyInfo info in type.GetProperties()) {
324          FindTypes(info.PropertyType, types, namespaceStart);
325        }
326
327        // fields
328        foreach (FieldInfo info in type.GetFields()) {
329          FindTypes(info.FieldType, types, namespaceStart);
330        }
331
332        // methods
333        foreach (MethodInfo info in type.GetMethods()) {
334          foreach (ParameterInfo paramInfo in info.GetParameters()) {
335            FindTypes(paramInfo.ParameterType, types, namespaceStart);
336          }
337          FindTypes(info.ReturnType, types, namespaceStart);
338        }
339      }
340    }
341    #endregion
342
343    #region Eventhandler
344
345    public event EventHandler ExecutionTimeChanged;
346    private void OnExecutionTimeChanged() {
347      EventHandler handler = ExecutionTimeChanged;
348      if (handler != null) handler(this, EventArgs.Empty);
349    }
350
351    public event EventHandler ExecutionStateChanged;
352    private void OnExecutionStateChanged() {
353      EventHandler handler = ExecutionStateChanged;
354      if (handler != null) handler(this, EventArgs.Empty);
355    }
356
357    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
358
359    public event EventHandler Started;
360    private void OnStarted() {
361      EventHandler handler = Started;
362      if (handler != null) handler(this, EventArgs.Empty);
363    }
364
365    public event EventHandler Stopped;
366    private void OnStopped() {
367      EventHandler handler = Stopped;
368      if (handler != null) handler(this, EventArgs.Empty);
369    }
370
371    public event EventHandler Paused;
372    private void OnPaused() {
373      EventHandler handler = Paused;
374      if (handler != null) handler(this, EventArgs.Empty);
375    }
376
377    public event EventHandler Prepared;
378    protected virtual void OnPrepared() {
379      EventHandler handler = Prepared;
380      if (handler != null) handler(this, EventArgs.Empty);
381    }
382
383    public event EventHandler ResourceIdsChanged;
384    protected virtual void OnResourceIdsChanged() {
385      EventHandler handler = ResourceIdsChanged;
386      if (handler != null) handler(this, EventArgs.Empty);
387    }
388
389    public event EventHandler ExperimentChanged;
390    protected virtual void OnExperimentChanged() {
391      EventHandler handler = ExperimentChanged;
392      if (handler != null) handler(this, EventArgs.Empty);
393    }
394
395    public event EventHandler ServerUrlChanged;
396    protected virtual void OnServerUrlChanged() {
397      EventHandler handler = ServerUrlChanged;
398      if (handler != null) handler(this, EventArgs.Empty);
399    }
400
401
402    #endregion
403  }
404}
Note: See TracBrowser for help on using the repository browser.