Free cookie consent management tool by TermsFeed Policy Generator

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

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

merged with changes from Hive-3.2

File size: 27.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.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 = "A runner for a single experiment, which's algorithms are executed in the Hive.";
54    private const int resultPollingIntervalMs = 15000;
55    private const int snapshotPollingIntervalMs = 1000;
56    private const int maxSnapshotRetries = 20;
57    private object locker = new object();
58
59    private System.Timers.Timer timer;
60    private bool pausePending, stopPending;
61
62    [Storable]
63    private DateTime lastUpdateTime;
64
65    private bool isPollingResults;
66    public bool IsPollingResults {
67      get { return isPollingResults; }
68      private set {
69        if (isPollingResults != value) {
70          isPollingResults = value;
71          OnIsPollingResultsChanged();
72        }
73      }
74    }
75
76    private bool stopResultsPollingPending = false;
77
78    private IDictionary<Guid, Thread> resultPollingThreads;
79
80    /// <summary>
81    /// Mapping from JobId to an optimizer.
82    /// Stores all pending optimizers. If an optimizer is finished it is removed from this collection
83    /// </summary>
84    [Storable]
85    private IDictionary<Guid, IOptimizer> pendingOptimizersByJobId = new Dictionary<Guid, IOptimizer>();
86
87    /// <summary>
88    /// Stores a mapping from the child-optimizer to the parent optimizer.
89    /// Needed to replace a finished optimizer in the optimizer-tree.
90    /// Only pending optmizers are stored.
91    /// </summary>
92    [Storable]
93    private IDictionary<IOptimizer, IOptimizer> parentOptimizersByPendingOptimizer = new Dictionary<IOptimizer, IOptimizer>();
94
95    [Storable]
96    private JobItemList jobItems;
97    public JobItemList JobItems {
98      get { return jobItems; }
99    }
100
101
102    [Storable]
103    private string serverUrl;
104    public string ServerUrl {
105      get { return serverUrl; }
106      set {
107        if (serverUrl != value) {
108          serverUrl = value;
109          OnServerUrlChanged();
110        }
111      }
112    }
113
114    [Storable]
115    private string resourceIds;
116    public string ResourceIds {
117      get { return resourceIds; }
118      set {
119        if (resourceIds != value) {
120          resourceIds = value;
121          OnResourceIdsChanged();
122        }
123      }
124    }
125
126    [Storable]
127    private HeuristicLab.Optimization.Experiment experiment;
128    public HeuristicLab.Optimization.Experiment Experiment {
129      get { return experiment; }
130      set {
131        if (experiment != value) {
132          experiment = value;
133          OnExperimentChanged();
134        }
135      }
136    }
137
138    [Storable]
139    private ILog log;
140    public ILog Log {
141      get { return log; }
142    }
143
144    [StorableConstructor]
145    public HiveExperiment(bool deserializing)
146      : base(deserializing) {
147      this.resultPollingThreads = new Dictionary<Guid, Thread>();
148      jobItems = new JobItemList();
149    }
150
151    public HiveExperiment()
152      : base(itemName, itemDescription) {
153      this.ServerUrl = HeuristicLab.Hive.Experiment.Properties.Settings.Default.HiveServerUrl;
154      this.ResourceIds = HeuristicLab.Hive.Experiment.Properties.Settings.Default.ResourceIds;
155      this.log = new Log();
156      pausePending = stopPending = false;
157      jobItems = new JobItemList();
158      isPollingResults = false;
159      resultPollingThreads = new Dictionary<Guid, Thread>();
160      InitTimer();
161    }
162
163    public override IDeepCloneable Clone(Cloner cloner) {
164      LogMessage("I am beeing cloned");
165      HiveExperiment clone = (HiveExperiment)base.Clone(cloner);
166      clone.resourceIds = this.resourceIds;
167      clone.serverUrl = this.serverUrl;
168      clone.experiment = (HeuristicLab.Optimization.Experiment)cloner.Clone(experiment);
169      clone.executionState = this.executionState;
170      clone.executionTime = this.executionTime;
171      clone.pendingOptimizersByJobId = new Dictionary<Guid, IOptimizer>();
172
173      foreach (var pair in this.pendingOptimizersByJobId)
174        clone.pendingOptimizersByJobId[pair.Key] = (IOptimizer)cloner.Clone(pair.Value);
175
176      foreach (var pair in this.parentOptimizersByPendingOptimizer)
177        clone.parentOptimizersByPendingOptimizer[(IOptimizer)cloner.Clone(pair.Key)] = (IOptimizer)cloner.Clone(pair.Value);
178
179      clone.log = (ILog)cloner.Clone(log);
180      clone.stopPending = this.stopPending;
181      clone.pausePending = this.pausePending;
182      clone.jobItems = (JobItemList)cloner.Clone(jobItems);
183      clone.lastUpdateTime = this.lastUpdateTime;
184      clone.isPollingResults = this.isPollingResults;
185      return clone;
186    }
187
188    [StorableHook(HookType.AfterDeserialization)]
189    private void AfterDeserialization() {
190      InitTimer();
191      this.IsPollingResults = false;
192      this.stopResultsPollingPending = false;
193      LogMessage("I was deserialized.");
194    }
195
196    private void InitTimer() {
197      timer = new System.Timers.Timer(100);
198      timer.AutoReset = true;
199      timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
200    }
201
202    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
203      DateTime now = DateTime.Now;
204      ExecutionTime += now - lastUpdateTime;
205      lastUpdateTime = now;
206    }
207
208    public IEnumerable<string> ResourceGroups {
209      get {
210        if (!string.IsNullOrEmpty(resourceIds)) {
211          return resourceIds.Split(';');
212        } else {
213          return new List<string>();
214        }
215      }
216    }
217    #region IExecutable Members
218
219    [Storable]
220    private Core.ExecutionState executionState;
221    public ExecutionState ExecutionState {
222      get { return executionState; }
223      private set {
224        if (executionState != value) {
225          executionState = value;
226          OnExecutionStateChanged();
227        }
228      }
229    }
230
231    [Storable]
232    private TimeSpan executionTime;
233    public TimeSpan ExecutionTime {
234      get { return executionTime; }
235      private set {
236        if (executionTime != value) {
237          executionTime = value;
238          OnExecutionTimeChanged();
239        }
240      }
241    }
242
243    public void Pause() {
244      throw new NotSupportedException();
245    }
246
247    public void Prepare() {
248      if (experiment != null) {
249        StopResultPolling();
250        pendingOptimizersByJobId.Clear();
251        parentOptimizersByPendingOptimizer.Clear();
252        jobItems.Clear();
253        experiment.Prepare();
254        this.ExecutionState = Core.ExecutionState.Prepared;
255        OnPrepared();
256      }
257    }
258
259    public void Start() {
260      OnStarted();
261      ExecutionTime = new TimeSpan();
262      lastUpdateTime = DateTime.Now;
263      this.ExecutionState = Core.ExecutionState.Started;
264      Thread t = new Thread(() => {
265        IExecutionEngineFacade executionEngineFacade = GetExecutionEngineFacade();
266
267        pendingOptimizersByJobId = new Dictionary<Guid, IOptimizer>();
268        parentOptimizersByPendingOptimizer = GetOptimizers(true);
269        IEnumerable<string> groups = ResourceGroups;
270       
271        foreach (IOptimizer optimizer in parentOptimizersByPendingOptimizer.Keys) {
272          SerializedJob serializedJob = CreateSerializedJob(optimizer);
273          ResponseObject<JobDto> response = executionEngineFacade.AddJobWithGroupStrings(serializedJob, groups);
274          pendingOptimizersByJobId.Add(response.Obj.Id, optimizer);
275
276          JobItem jobItem = new JobItem() {
277            JobDto = response.Obj,
278            LatestSnapshot = new ResponseObject<SerializedJob>() {
279              Obj = serializedJob,
280              StatusMessage = "Initial Snapshot",
281              Success = true
282            }
283          };
284          jobItems.Add(jobItem);
285          jobItem.LogMessage("Job sent to Hive");
286
287          LogMessage("Sent job to Hive (jobId: " + response.Obj.Id + ")");
288        }
289
290        // start results polling after sending sending the jobs to the server (to avoid race conflicts at the optimizers-collection)
291        StartResultPolling();
292      });
293      t.Start();
294    }
295
296    public void Stop() {
297      this.ExecutionState = Core.ExecutionState.Stopped;
298      foreach (JobItem jobItem in jobItems) {
299        AbortJob(jobItem.JobDto.Id);
300      }
301      OnStopped();
302    }
303
304    private void CreateResultPollingThreads() {
305      foreach (JobItem jobItem in JobItems) {
306        if (!resultPollingThreads.ContainsKey(jobItem.JobDto.Id) && jobItem.JobDto.State != State.Finished) {
307          resultPollingThreads.Add(jobItem.JobDto.Id, CreateResultPollingThread(jobItem.JobDto));
308        }
309      }
310    }
311
312    public void StartResultPolling() {
313      this.stopResultsPollingPending = false;
314      this.IsPollingResults = true;
315      lock (resultPollingThreads) {
316        CreateResultPollingThreads();
317        foreach (Thread pollingThread in resultPollingThreads.Values) {
318          if (pollingThread.ThreadState != System.Threading.ThreadState.Running) {
319            pollingThread.Start();
320          }
321        }
322      }
323    }
324
325    public void StopResultPolling() {
326      this.stopResultsPollingPending = true;
327      foreach (Thread pollingThread in resultPollingThreads.Values) {
328        pollingThread.Interrupt();
329      }
330      this.stopResultsPollingPending = false;
331    }
332
333    private JobItem GetJobItemById(Guid jobId) {
334      return jobItems.Single(x => x.JobDto.Id == jobId);
335    }
336
337    /// <summary>
338    /// Returns all optimizers in the current Experiment
339    /// </summary>
340    /// <param name="flatout">if false only top level optimizers are returned, if true the optimizer-tree is flatted</param>
341    /// <returns></returns>
342    private IDictionary<IOptimizer, IOptimizer> GetOptimizers(bool flatout) {
343      if (!flatout) {
344        var optimizers = new Dictionary<IOptimizer, IOptimizer>();
345        foreach (IOptimizer opt in experiment.Optimizers) {
346          optimizers.Add(experiment, opt);
347        }
348        return optimizers;
349      } else {
350        return FlatOptimizerTree(null, experiment);
351      }
352    }
353
354    /// <summary>
355    /// Recursively iterates all IOptimizers in the optimizer-tree and returns them.
356    ///
357    /// [chn] this could be implemented more cleanly if Experiment and BatchRun would implement an interface like:
358    /// interface IParallelizable {
359    ///   IEnumerable&lt;IOptimizer&gt; GetOptimizers();
360    /// }
361    /// </summary>
362    /// <returns>a dictionary mapping from the parent optimizer to the child optimizer</returns>
363    private IDictionary<IOptimizer, IOptimizer> FlatOptimizerTree(IOptimizer parent, IOptimizer optimizer) {
364      IDictionary<IOptimizer, IOptimizer> optimizers = new Dictionary<IOptimizer, IOptimizer>();
365      if (optimizer is HeuristicLab.Optimization.Experiment) {
366        HeuristicLab.Optimization.Experiment experiment = optimizer as HeuristicLab.Optimization.Experiment;
367        foreach (IOptimizer opt in experiment.Optimizers) {
368          AddRange(optimizers, FlatOptimizerTree(experiment, opt));
369        }
370      } else if (optimizer is BatchRun) {
371        BatchRun batchRun = optimizer as BatchRun;
372        for (int i = 0; i < batchRun.Repetitions; i++) {
373          IOptimizer opt = (IOptimizer)batchRun.Algorithm.Clone();
374          AddRange(optimizers, FlatOptimizerTree(batchRun, opt));
375        }
376      } else if (optimizer is EngineAlgorithm) {
377        optimizers.Add(optimizer, parent);
378      } else {
379        Logger.Warn("Optimizer of type " + optimizers.GetType().ToString() + " unknown");
380        optimizers.Add(optimizer, parent);
381      }
382      return optimizers;
383    }
384
385    private void AddRange(IDictionary<IOptimizer, IOptimizer> optimizers, IDictionary<IOptimizer, IOptimizer> childs) {
386      foreach (KeyValuePair<IOptimizer, IOptimizer> kvp in childs) {
387        optimizers.Add(kvp);
388      }
389    }
390
391    private void ReplaceOptimizer(IOptimizer parentOptimizer, IOptimizer originalOptimizer, IOptimizer newOptimizer) {
392      lock (locker) {
393        if (parentOptimizer is HeuristicLab.Optimization.Experiment) {
394          HeuristicLab.Optimization.Experiment exp = (HeuristicLab.Optimization.Experiment)parentOptimizer;
395          int originalOptimizerIndex = exp.Optimizers.IndexOf(originalOptimizer);
396          exp.Optimizers[originalOptimizerIndex] = newOptimizer;
397        } else if (parentOptimizer is BatchRun) {
398          BatchRun batchRun = (BatchRun)parentOptimizer;
399          if (newOptimizer is IAlgorithm) {
400            batchRun.Runs.Add(new Run((IAlgorithm)newOptimizer));
401          } else {
402            throw new NotSupportedException("Only IAlgorithm types supported");
403          }
404        } else {
405          throw new NotSupportedException("Invalid parentOptimizer");
406        }
407      }
408    }
409
410    public void AbortJob(Guid jobId) {
411      IExecutionEngineFacade executionEngineFacade = GetExecutionEngineFacade();
412      Response response = executionEngineFacade.AbortJob(jobId);
413      GetJobItemById(jobId).LogMessage("Aborting Job: " + response.StatusMessage);
414    }
415
416    #endregion
417
418    private IExecutionEngineFacade GetExecutionEngineFacade() {
419      return ServiceLocator.CreateExecutionEngineFacade(ServerUrl);
420    }
421
422    private SerializedJob CreateSerializedJob(IOptimizer optimizer) {
423      IJob job = new OptimizerJob() {
424        Optimizer = optimizer
425      };
426
427      // serialize job
428      MemoryStream memStream = new MemoryStream();
429      XmlGenerator.Serialize(job, memStream);
430      byte[] jobByteArray = memStream.ToArray();
431      memStream.Dispose();
432
433      // find out which which plugins are needed for the given object
434      List<HivePluginInfoDto> pluginsNeeded = (
435        from p in GetDeclaringPlugins(optimizer.GetType())
436        select new HivePluginInfoDto() {
437          Name = p.Name,
438          Version = p.Version
439        }).ToList();
440
441      JobDto jobDto = new JobDto() {
442        CoresNeeded = 1, // [chn] how to determine real cores needed?
443        PluginsNeeded = pluginsNeeded,
444        State = State.Offline,
445        MemoryNeeded = 0,
446        UserId = Guid.Empty // [chn] set real userid here!
447      };
448
449      SerializedJob serializedJob = new SerializedJob() {
450        JobInfo = jobDto,
451        SerializedJobData = jobByteArray
452      };
453
454      return serializedJob;
455    }
456
457    private Thread CreateResultPollingThread(JobDto job) {
458      return new Thread(() => {
459        try {
460          GetJobItemById(job.Id).LogMessage("Starting job results polling");
461          IExecutionEngineFacade executionEngineFacade = GetExecutionEngineFacade();
462          IJob restoredObject = null;
463
464          do {
465            if (stopPending || !this.IsPollingResults) {
466              return;
467            }
468
469            ResponseObject<JobDto> response = executionEngineFacade.GetJobById(job.Id);
470            LogMessage("Response: " + response.StatusMessage + " (jobId: " + job.Id + ")");
471            GetJobItemById(job.Id).LogMessage("Response: " + response.StatusMessage);
472
473            UpdateJobItem(response.Obj);
474
475            if (response.Obj.State == State.Abort) {
476              // job is aborted, don't poll for results anymore
477              GetJobItemById(job.Id).LogMessage("Job successfully aborted");
478              return;
479            }
480
481            // loop while
482            // 1. the user doesn't request an abort
483            // 2. there is a problem with server communication (success==false)
484            // 3. no result for the job is available yet (response.Obj==null)
485            // 4. the result that we get from the server is a snapshot and not the final result
486            if (response.Success && response.Obj != null && response.Obj.State == State.Finished) {
487              ResponseObject<SerializedJob> jobResponse = executionEngineFacade.GetLastSerializedResult(job.Id, false, false);
488              restoredObject = XmlParser.Deserialize<IJob>(new MemoryStream(jobResponse.Obj.SerializedJobData));
489              UpdateSnapshot(jobResponse);
490            }
491
492            Thread.Sleep(resultPollingIntervalMs);
493          } while (restoredObject == null || restoredObject.ExecutionState != Core.ExecutionState.Stopped);
494
495          LogMessage("Job finished (jobId: " + job.Id + ")");
496          GetJobItemById(job.Id).LogMessage("Job finished");
497          // job retrieved... replace the existing optimizers with the finished one
498          IOptimizer originalOptimizer = pendingOptimizersByJobId[job.Id];
499          IOptimizer restoredOptimizer = ((OptimizerJob)restoredObject).Optimizer;
500         
501          ReplaceOptimizer(parentOptimizersByPendingOptimizer[originalOptimizer], originalOptimizer, restoredOptimizer);
502          pendingOptimizersByJobId.Remove(job.Id);
503          parentOptimizersByPendingOptimizer.Remove(originalOptimizer);
504
505        } catch (ThreadInterruptedException exception) {
506
507        } finally {
508          GetJobItemById(job.Id).LogMessage("ResultsPolling Thread stopped");
509          lock (resultPollingThreads) {
510            resultPollingThreads.Remove(job.Id);
511            if (resultPollingThreads.Count == 0) {
512              IsPollingResults = false;
513            }
514          }
515
516          // check if finished
517          if (pendingOptimizersByJobId.Count == 0) {
518            this.ExecutionState = Core.ExecutionState.Stopped;
519            OnStopped();
520          }
521        }
522      });
523    }
524
525    private void UpdateJobItem(JobDto jobDto) {
526      JobItem jobItem = jobItems.Single(x => x.JobDto.Id == jobDto.Id);
527      jobItem.JobDto = jobDto;
528    }
529
530    private void UpdateSnapshot(ResponseObject<SerializedJob> response) {
531      JobItem jobItem = jobItems.Single(x => x.JobDto.Id == response.Obj.JobInfo.Id);
532      jobItem.LatestSnapshot = response;
533    }
534
535    private void LogMessage(string message) {
536      // HeuristicLab.Log is not Thread-Safe, so lock on every call
537      lock (locker) {
538        log.LogMessage(message);
539      }
540    }
541
542    public void RequestSnapshot(Guid jobId) {
543      IExecutionEngineFacade executionEngineFacade = GetExecutionEngineFacade();
544      ResponseObject<SerializedJob> response;
545      int retryCount = 0;
546
547      Response snapShotResponse = executionEngineFacade.RequestSnapshot(jobId);
548      if (snapShotResponse.StatusMessage == ApplicationConstants.RESPONSE_JOB_IS_NOT_BEEING_CALCULATED) {
549        // job already finished
550        Logger.Debug("HiveEngine: Abort - GetLastResult(false)");
551        response = executionEngineFacade.GetLastSerializedResult(jobId, false, false);
552        Logger.Debug("HiveEngine: Abort - Server: " + response.StatusMessage + " success: " + response.Success);
553      } else {
554        // server sent snapshot request to client
555        // poll until snapshot is ready
556        do {
557          Thread.Sleep(snapshotPollingIntervalMs);
558          Logger.Debug("HiveEngine: Abort - GetLastResult(true)");
559          response = executionEngineFacade.GetLastSerializedResult(jobId, false, true);
560          Logger.Debug("HiveEngine: Abort - Server: " + response.StatusMessage + " success: " + response.Success);
561          retryCount++;
562          // loop while
563          // 1. problem with communication with server
564          // 2. job result not yet ready
565        } while (
566          (retryCount < maxSnapshotRetries) && (
567          !response.Success ||
568          response.StatusMessage == ApplicationConstants.RESPONSE_JOB_RESULT_NOT_YET_HERE)
569          );
570      }
571      SerializedJob jobResult = response.Obj;
572      if (jobResult != null) {
573        Logger.Debug("HiveEngine: Results-polling - Got result!");
574
575        //job = XmlParser.Deserialize<Job>(new MemoryStream(jobResult.SerializedJobData));
576
577        throw new NotImplementedException("[chn] how to create a view in 3.3 and why should i do this here? shouldnt the caller of this method receive a result and decide what to do?");
578        //ControlManager.Manager.ShowControl(job.Engine.CreateView());
579      }
580    }
581
582    #region Required Plugin Search
583    /// <summary>
584    /// Returns a list of plugins in which the type itself and all members
585    /// of the type are declared. Objectgraph is searched recursively.
586    /// </summary>
587    private IEnumerable<IPluginDescription> GetDeclaringPlugins(Type type) {
588      HashSet<Type> types = new HashSet<Type>();
589      FindTypes(type, types, "HeuristicLab.");
590      return GetDeclaringPlugins(types);
591    }
592
593    /// <summary>
594    /// Returns the plugins (including dependencies) in which the given types are declared
595    /// </summary>
596    private IEnumerable<IPluginDescription> GetDeclaringPlugins(IEnumerable<Type> types) {
597      HashSet<IPluginDescription> plugins = new HashSet<IPluginDescription>();
598      foreach (Type t in types) {
599        FindDeclaringPlugins(ApplicationManager.Manager.GetDeclaringPlugin(t), plugins);
600      }
601      return plugins;
602    }
603
604    /// <summary>
605    /// Finds the dependencies of the given plugin and adds it to the plugins hashset.
606    /// Also searches the dependencies recursively.
607    /// </summary>
608    private void FindDeclaringPlugins(IPluginDescription plugin, HashSet<IPluginDescription> plugins) {
609      if (!plugins.Contains(plugin)) {
610        plugins.Add(plugin);
611        foreach (IPluginDescription dependency in plugin.Dependencies) {
612          FindDeclaringPlugins(dependency, plugins);
613        }
614      }
615    }
616
617    /// <summary>
618    /// Recursively finds all types used in type which are in a namespace which starts with namespaceStart
619    /// Be aware that search is not performed on attributes
620    /// </summary>
621    /// <param name="type">the type to be searched</param>
622    /// <param name="types">found types will be stored there, needed in order to avoid duplicates</param>
623    /// <param name="namespaceStart">only types from namespaces which start with this will be searched and added</param>
624    private void FindTypes(Type type, HashSet<Type> types, string namespaceStart) {
625      if (!types.Contains(type) && type.Namespace.StartsWith(namespaceStart)) {
626        types.Add(type);
627
628        // constructors
629        foreach (ConstructorInfo info in type.GetConstructors()) {
630          foreach (ParameterInfo paramInfo in info.GetParameters()) {
631            FindTypes(paramInfo.ParameterType, types, namespaceStart);
632          }
633        }
634
635        // interfaces
636        foreach (Type t in type.GetInterfaces()) {
637          FindTypes(t, types, namespaceStart);
638        }
639
640        // events
641        foreach (EventInfo info in type.GetEvents()) {
642          FindTypes(info.EventHandlerType, types, namespaceStart);
643          FindTypes(info.DeclaringType, types, namespaceStart);
644        }
645
646        // properties
647        foreach (PropertyInfo info in type.GetProperties()) {
648          FindTypes(info.PropertyType, types, namespaceStart);
649        }
650
651        // fields
652        foreach (FieldInfo info in type.GetFields()) {
653          FindTypes(info.FieldType, types, namespaceStart);
654        }
655
656        // methods
657        foreach (MethodInfo info in type.GetMethods()) {
658          foreach (ParameterInfo paramInfo in info.GetParameters()) {
659            FindTypes(paramInfo.ParameterType, types, namespaceStart);
660          }
661          FindTypes(info.ReturnType, types, namespaceStart);
662        }
663      }
664    }
665    #endregion
666
667    #region Eventhandler
668
669    public event EventHandler ExecutionTimeChanged;
670    private void OnExecutionTimeChanged() {
671      EventHandler handler = ExecutionTimeChanged;
672      if (handler != null) handler(this, EventArgs.Empty);
673    }
674
675    public event EventHandler ExecutionStateChanged;
676    private void OnExecutionStateChanged() {
677      LogMessage("ExecutionState changed to " + executionState.ToString());
678      EventHandler handler = ExecutionStateChanged;
679      if (handler != null) handler(this, EventArgs.Empty);
680    }
681
682    public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
683
684    public event EventHandler Started;
685    private void OnStarted() {
686      LogMessage("Started");
687      timer.Start();
688      EventHandler handler = Started;
689      if (handler != null) handler(this, EventArgs.Empty);
690    }
691
692    public event EventHandler Stopped;
693    private void OnStopped() {
694      timer.Stop();
695      LogMessage("Stopped");
696      EventHandler handler = Stopped;
697      if (handler != null) handler(this, EventArgs.Empty);
698    }
699
700    public event EventHandler Paused;
701    private void OnPaused() {
702      timer.Stop();
703      LogMessage("Paused");
704      EventHandler handler = Paused;
705      if (handler != null) handler(this, EventArgs.Empty);
706    }
707
708    public event EventHandler Prepared;
709    protected virtual void OnPrepared() {
710      LogMessage("Prepared");
711      EventHandler handler = Prepared;
712      if (handler != null) handler(this, EventArgs.Empty);
713    }
714
715    public event EventHandler ResourceIdsChanged;
716    protected virtual void OnResourceIdsChanged() {
717      EventHandler handler = ResourceIdsChanged;
718      if (handler != null) handler(this, EventArgs.Empty);
719    }
720
721    public event EventHandler ExperimentChanged;
722    protected virtual void OnExperimentChanged() {
723      LogMessage("Experiment changed");
724      EventHandler handler = ExperimentChanged;
725      if (handler != null) handler(this, EventArgs.Empty);
726    }
727
728    public event EventHandler ServerUrlChanged;
729    protected virtual void OnServerUrlChanged() {
730      EventHandler handler = ServerUrlChanged;
731      if (handler != null) handler(this, EventArgs.Empty);
732    }
733
734    public event EventHandler IsResultsPollingChanged;
735    private void OnIsPollingResultsChanged() {
736      if (this.IsPollingResults) {
737        LogMessage("Results Polling Started");
738        timer.Start();
739      } else {
740        LogMessage("Results Polling Stopped");
741        timer.Stop();
742      }
743      EventHandler handler = IsResultsPollingChanged;
744      if (handler != null) handler(this, EventArgs.Empty);
745    }
746    #endregion
747  }
748}
Note: See TracBrowser for help on using the repository browser.