Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OaaS/HeuristicLab.Services.Optimization.Controller/HL/HiveScenarioManager.cs @ 9227

Last change on this file since 9227 was 9227, checked in by fschoepp, 11 years ago

#1888:

  • Experiments will be saved as JSON elements within the blob store.
  • Added simple model and JSON converters.
  • Backend stores and runs experiments.
  • Updated interfaces to save/read experiments.
  • Added a binding to automatically map incoming JSON ajax requests to experiment models.
  • Added the javascript DatatypeMapper to map parameter inputs to the right html elements and vice versa.
  • Added smartwizard to generate Wizards for creating new experiments (New.cshtml).
File size: 21.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using HeuristicLab.Services.Optimization.ControllerService.Interfaces;
6using HeuristicLab.Optimization;
7using HeuristicLab.Algorithms.GeneticAlgorithm;
8using HeuristicLab.Problems.TravelingSalesman;
9using HeuristicLab;
10using System.Reflection;
11using HeuristicLab.Services.Optimization.ControllerService.Model;
12using HeuristicLab.Core;
13using System.Collections;
14using HeuristicLab.Clients.Hive;
15using System.Threading;
16using HeuristicLab.Data;
17using System.IO;
18using Microsoft.WindowsAzure;
19using Microsoft.WindowsAzure.StorageClient;
20using HeuristicLab.Services.Optimization.ControllerService.Azure;
21using System.Data;
22using HeuristicLab.Services.Optimization.ControllerService.General;
23
24namespace HeuristicLab.Services.Optimization.ControllerService {
25  public class ScenarioEntity : TableServiceEntity {
26
27    public ScenarioEntity() {
28    }
29   
30    public ScenarioEntity(string scenarioName, string scenario, string mapper) {
31      PartitionKey = "ScenarioPartition";
32      RowKey = scenarioName;
33      Scenario = scenario;
34      Mapper = mapper;
35    }   
36
37    public string Scenario { get; set; }
38
39    public string Mapper { get; set; }
40  }
41
42  public class HiveScenarioManager : IScenarioManager {
43    private static IScenarioMapper tspMapper;
44    private static object lockable;
45    private Dictionary<string, IScenarioMapper> mappers = new Dictionary<string, IScenarioMapper>();
46    private IDataAccessLayer dal = DataAccessLayerProvider.GetLayer();
47
48    public static readonly string SCENARIO_TABLE = "Scenario";
49
50    static HiveScenarioManager() {
51      lockable = new object();
52    }
53
54    public string DispatchScenario(Model.User user, Model.OptimizationScenario scenario, JobExecutionDetails details) {
55      // Experiment experiment = new Experiment();
56      // var problem = new TravelingSalesmanProblem();
57      // var algo = new GeneticAlgorithm();
58      // algo.Problem = problem;     
59     
60      IScenarioMapper mapper = GetMapper(scenario.Id);
61      IAlgorithm algo;
62      mapper.MapScenario(scenario, out algo);
63      /*if (details.Repititions > 1) {
64        BatchRun br = new BatchRun();
65        //br.Name = details.JobTitle;
66        br.Optimizer = algo;       
67        br.Repetitions = details.Repititions;
68        return SendExperimentToHive(user, br, details);
69      }
70      else {       
71       
72      }*/
73      return SendExperimentToHive(user, algo, details);
74    }
75
76    private sealed class StackEntry {
77      public HeuristicLab.Optimization.Experiment Parent { get; set; }
78      public IList<Model.Algorithm> Children { get; set; }
79    }
80
81    public bool DispatchExperiment(User user, Model.Experiment exp, JobExecutionDetails details) {
82      // TODO: Determine how to build a tree of IAlgorithm
83      // For now the experiment will be flatened for execution
84      HeuristicLab.Optimization.Experiment hiveExperiment = new HeuristicLab.Optimization.Experiment(exp.Name);
85      var stack = new Stack<StackEntry>();
86      var children = new List<Model.Algorithm>();
87      foreach (var child in exp.Algorithm) {
88        children.Add(child);       
89      }
90      stack.Push(new StackEntry() { Parent = hiveExperiment, Children = children });
91
92      while (stack.Count > 0) {
93        var entry = stack.Pop();
94        // handle current entry
95
96        // TODO: Store scenario name in entry.Child.Mapper when saving
97        foreach (var child in entry.Children) {
98          // This is a template experiment;
99          if (child.Name == null) {
100            var parent = new HeuristicLab.Optimization.Experiment(child.Name);
101            entry.Parent.Optimizers.Add(parent);
102            stack.Push(new StackEntry() { Parent = parent, Children = child.ChildAlgorithms });         
103          }
104          // This entity is mapable
105          else {           
106            IScenarioMapper mapper = GetMapper(child.Name);
107            if (mapper == null) { // TODO: We should really be able to difference Experiment/Algorithm types; this is a workaround
108              var parent = new HeuristicLab.Optimization.Experiment(child.Name);
109              entry.Parent.Optimizers.Add(parent);
110              stack.Push(new StackEntry() { Parent = parent, Children = child.ChildAlgorithms });         
111            }
112            else {
113              var optScen = new OptimizationScenario() { Id = child.Name };
114              optScen.Algorithm.Add(child);
115              IAlgorithm algo;
116              mapper.MapScenario(optScen, out algo);
117              entry.Parent.Optimizers.Add(algo);
118            }
119          } 
120        }
121      }
122      details.JobTitle = exp.Name;
123      return SendExperimentToHive(user, hiveExperiment, details) != null;
124    }
125
126    static public string AssemblyDirectory {
127      get {
128        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
129        UriBuilder uri = new UriBuilder(codeBase);
130        string path = Uri.UnescapeDataString(uri.Path);
131        return Path.GetDirectoryName(path);
132      }
133    }
134
135    public static IScenarioMapper CompileMapper(string scenarioMapper) {
136       // http://stackoverflow.com/questions/3188882/compile-and-run-dynamic-code-without-generating-exe
137      using (var csCodeProvider = new Microsoft.CSharp.CSharpCodeProvider()) {
138        var cp = new System.CodeDom.Compiler.CompilerParameters() {
139          GenerateInMemory = true
140        };
141
142        var referencedPaths = Directory.GetFiles(AssemblyDirectory, "*.dll");
143        foreach (var loadedAssembly in referencedPaths) {
144          cp.ReferencedAssemblies.Add(loadedAssembly);
145        }
146        cp.ReferencedAssemblies.Add("System.dll");
147        cp.ReferencedAssemblies.Add("System.Core.dll");
148        cp.ReferencedAssemblies.Add("System.Data.dll");
149        cp.ReferencedAssemblies.Add("System.Xml.dll");
150        cp.ReferencedAssemblies.Add("System.Xml.Linq.dll");
151
152        var res = csCodeProvider.CompileAssemblyFromSource(
153          cp,
154          scenarioMapper
155        );
156
157        foreach (var error in res.Errors) {
158          Console.WriteLine(error);
159        }
160       
161        var firstMapper = res.CompiledAssembly.GetTypes().Where(p => typeof(IScenarioMapper).IsAssignableFrom(p)).FirstOrDefault();       
162        return Activator.CreateInstance(firstMapper) as IScenarioMapper;
163      }
164    }
165
166    private IScenarioMapper GetMapper(string scenarioId) {
167      var id = scenarioId;
168      if (!mappers.ContainsKey(id)) {
169        lock (lockable) {
170          if (mappers.ContainsKey(id))
171            return mappers[id];
172         
173          var mapperString = GetMapperFromBlobStore(id);
174          if (mapperString == null) return null;
175          var mapper = CompileMapper(mapperString);
176
177          mappers[id] = mapper;
178          return mapper;
179        } // lock       
180       } // if
181      return null;
182     } 
183
184    private void MapExperiment(Model.OptimizationScenario scenario, out IAlgorithm algorithm) {     
185      IScenarioMapper mapper = GetMapper(scenario.Id);
186      mapper.MapScenario(scenario, out algorithm);     
187    }
188
189    private HiveServiceLocator ConfigureHive(Model.User user) {
190      var serviceLocator = new HiveServiceLocator();
191      serviceLocator.Username = user.Username;
192      serviceLocator.Password = user.Password;
193      serviceLocator.EndpointConfigurationName = Configuration.HiveEndpointName;
194      return serviceLocator;
195    }
196
197    private string SendExperimentToHive(Model.User user, IOptimizer exp, JobExecutionDetails details) {     
198      var job = new RefreshableJob();
199      job.IsAllowedPrivileged = true;     
200      job.Job.Name = details.JobTitle;
201      job.Job.ResourceNames = details.Group;     
202      job.RefreshAutomatically = false;
203     
204      if (details.Repititions > 1) {
205        BatchRun br = new BatchRun();
206        br.Optimizer = exp;
207        br.Repetitions = details.Repititions;
208        exp = br;
209      }
210
211      if (exp.ExecutionState != ExecutionState.Prepared) {
212        exp.Prepare();
213      }     
214      job.HiveTasks.Add(new OptimizerHiveTask(exp));
215      var service = ConfigureHive(user);
216     
217      // TODO: Fix HiveClient class to be not dependent on singleton HiveServiceLocator!!!
218      HiveServiceLocator.Instance.Username = user.Username;
219      HiveServiceLocator.Instance.Password = user.Password;
220      HiveServiceLocator.Instance.EndpointConfigurationName = Configuration.HiveEndpointName;
221      HiveClient.StartJob((ex) => {
222        Console.WriteLine(ex.StackTrace);
223      }, job, new CancellationToken());
224     
225      job.StopResultPolling();
226      return job.Id != null ? job.Id.ToString() : null;
227    }
228
229
230    public IList<Model.Job> GetJobs(User user) {
231      var serviceLocator = ConfigureHive(user);
232      var jobsLoaded = serviceLocator.CallHiveService<IEnumerable<HeuristicLab.Clients.Hive.Job>>(s => s.GetJobs());
233      IList<Model.Job> jobs = new List<Model.Job>();
234
235      foreach (var job in jobsLoaded) {
236        jobs.Add(ConvertJob(user, job));
237      }     
238      return jobs;
239    }
240
241    private Model.Job ConvertJob(User user, HeuristicLab.Clients.Hive.Job job)
242    {
243      var waitingJobs = job.JobCount - job.CalculatingCount - job.FinishedCount;
244      Model.JobState? state = null;
245      if (job.CalculatingCount > 0)
246        state = JobState.Calculating;
247      else if (job.JobCount > 0 && job.JobCount == job.FinishedCount)
248        state = JobState.Finished;
249      else
250        state = JobState.Waiting;
251
252      return new Model.Job() { Id = job.Id.ToString(), Name = job.Name, Resource = job.ResourceNames, State = state.Value, DateCreated = job.DateCreated };
253    }
254
255
256    public Model.Job GetJob(User user, string id) {
257      var serviceLocator = ConfigureHive(user);
258      var guid = Guid.Parse(id);
259      return ConvertJob(user, serviceLocator.CallHiveService<HeuristicLab.Clients.Hive.Job>(s => s.GetJob(guid)));
260    }
261
262
263    public bool DeleteJob(User user, string id) {
264      var serviceLocator = ConfigureHive(user);
265      var guid = Guid.Parse(id);     
266      serviceLocator.CallHiveService(s => s.DeleteJob(guid));
267      return true;
268    }
269
270    public IList<Model.Run> GetJobResults(User user, string id) {
271      var serviceLocator = ConfigureHive(user);
272      var guid = Guid.Parse(id);
273      var jobTasks = serviceLocator.CallHiveService<IEnumerable<HeuristicLab.Clients.Hive.LightweightTask>>(s => s.GetLightweightJobTasks(guid));
274
275      IList<Guid> taskIds = new List<Guid>();
276      foreach (var task in jobTasks) {
277        taskIds.Add(task.Id);
278      }
279
280      // TODO: Fix problems with the HiveServiceLocater singleton!!!
281      HiveServiceLocator.Instance.Username = user.Username;
282      HiveServiceLocator.Instance.Password = user.Password;
283      HiveServiceLocator.Instance.EndpointConfigurationName = Configuration.HiveEndpointName;
284      TaskDownloader downloader = new TaskDownloader(taskIds);
285      downloader.StartAsync();
286      while (!downloader.IsFinished) {       
287        Thread.Sleep(500);
288
289        if (downloader.IsFaulted) {
290          throw downloader.Exception;
291        }
292      }
293      IDictionary<Guid, HiveTask> hiveTasks = downloader.Results;
294      IList<Model.Run> runs = new List<Model.Run>();
295      foreach (var keyTask in hiveTasks.Keys) {
296        var oht = hiveTasks[keyTask] as OptimizerHiveTask;
297        if (oht != null) {
298          foreach (var run in oht.ItemTask.Item.Runs) {
299            Model.Run taskRun = new Model.Run();
300            taskRun.Id = taskRun.Name = run.Name;
301            IList<Parameter> resultValues = new List<Model.Parameter>();
302            foreach (var key in run.Results.Keys) {
303              var value = run.Results[key];             
304              Parameter result = MapHiveDataType(key, value);
305              resultValues.Add(result);
306            }
307            taskRun.Results = resultValues;
308            runs.Add(taskRun);
309          }
310        }
311      }
312      return runs;
313    }
314
315    //TODO: We might need images / +++
316   
317    private Parameter MapHiveDataType(string name, IItem item) {
318      Parameter result = new Parameter();
319      result.Type = ParameterType.String;
320      //TODO: How shall we handle dll specific datatypes?     
321      //if (item is PathTSPTour) {
322      //  var tour = item as PathTSPTour;           
323      //}
324      //else
325      if (item is IStringConvertibleValue) {
326        var value = (item as IStringConvertibleValue).GetValue();
327        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.StringValue() { Name = name, Value = value };
328      }
329      else if (item is IStringConvertibleValueTuple) {
330        var value1 = (item as IStringConvertibleValueTuple).Item1.GetValue();
331        var value2 = (item as IStringConvertibleValueTuple).Item2.GetValue();
332        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.StringValue() { Name = name, Value = "{" + value1 + ", " + value2 + "}" };
333      }           
334      else if (item is DoubleArray) {
335        var array = item as DoubleArray;
336        double[] arrayValue = new double[array.Length];
337        for (int i = 0; i < arrayValue.Length; ++i) {
338          arrayValue[i] = array[i];
339        }
340        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.DecimalVector() { Name = name, Value = arrayValue };
341      }
342      else if (item is DoubleMatrix) {
343        var matrix = item as DoubleMatrix;
344        double[][] matrixValue = new double[matrix.Rows][];
345        for (int i = 0; i < matrixValue.Length; ++i) {
346          matrixValue[i] = new double[matrix.Columns];
347          for (int j = 0; j < matrixValue[i].Length; ++j) {
348            matrixValue[i][j] = matrix[i, j];
349          }
350        }
351        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.DecimalMatrix() { Name = name, Value = matrixValue };
352      }
353      else if (item is IStringConvertibleArray) {
354        StringBuilder sb = new StringBuilder();
355        var array = item as IStringConvertibleArray;
356        if (array.Length == 0) {
357          sb.Append("[ ]");
358        }
359        else {
360          sb.Append("[");
361          for (int i = 0; i < array.Length - 1; i++) {
362            sb.Append(array.GetValue(i)).Append(", ");
363          }
364          sb.Append(array.GetValue(array.Length - 1));
365          sb.Append(" ]");
366        }
367        var value = sb.ToString();
368        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.StringValue() { Name = name, Value = value };
369      }
370      else if (item is HeuristicLab.Analysis.DataTable) {
371        var table = item as HeuristicLab.Analysis.DataTable;
372        string[] names = new string[table.Rows.Count];
373        double[][] results = new double[table.Rows.Count][];
374        for (int i = 0; i < table.Rows.Count; i++ ) {
375          var columns = table.Rows.ToList()[i];
376          names[i] = columns.Name;
377          results[i] = new double[columns.Values.Count];
378          for (int j=0; j < columns.Values.Count; j++) {
379            results[i][j] = columns.Values[j];
380          }
381        }
382        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.DecimalMatrix() { Name = name, Value = results, RowNames = names };
383      }
384      else if (item is IStringConvertibleMatrix) {
385        StringBuilder sb = new StringBuilder();
386        var matrix = item as IStringConvertibleMatrix;
387
388        if (matrix.Rows == 0 || matrix.Columns == 0) {
389          sb.Append("[ ]");
390        }
391        else {
392
393          sb.Append("[ ");
394          for (int r = 0; r < matrix.Rows; r++) {
395            sb.Append("( ");
396            for (int c = 0; c < matrix.Columns - 1; c++) {
397              matrix.GetValue(r, c);
398              sb.Append(matrix.GetValue(r, c)).Append(", ");
399            }
400            sb.Append(matrix.GetValue(r, matrix.Columns - 1)).Append(r < matrix.Rows - 1 ? " ), " : " )");
401          }
402          sb.Append(" ]");
403        }
404        var value = sb.ToString();
405        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.StringValue() { Name = name, Value = value };
406      }
407      else {
408        result.Value = new HeuristicLab.Services.Optimization.ControllerService.Model.StringValue() { Name = name, Value = "Cannot be displayed as string" };
409      }
410      // TODO: Add workaround for TSP
411      return result;
412    }
413
414    public bool AddScenario(User user, string scenarioName, string scenarioXml, string scenarioMapper) {
415      // create scenario mapper
416      var mapper = CompileMapper(scenarioMapper);
417      if (mapper == null)
418        return false;
419     
420      // insert into table & blob store
421      var scenDao = dal.ScenarioDao;
422      var blobDao = dal.BlobDao;
423     
424      Guid scenarioXmlGuid = Guid.NewGuid();
425      Guid scenarioMapperGuid = Guid.NewGuid();
426      string scenarioXmlId = scenarioName + "_" + scenarioXmlGuid.ToString();
427      string scenarioMapperId = scenarioName + "_" + scenarioMapperGuid.ToString();
428      if (!blobDao.Add(new StringEntry() { Key = scenarioXmlId, Text = scenarioXml }))
429        return false;
430      if (!blobDao.Add(new StringEntry() { Key = scenarioMapperId, Text = scenarioMapper }))
431        return false;
432      if (!scenDao.Add(new ScenarioEntity(scenarioName, scenarioXmlId, scenarioMapperId)))
433        return false;
434
435      // everything stored in the DB -> add mapper to dictionary
436      if (!mappers.ContainsKey(scenarioName)) {
437        lock (lockable) {
438          if (!mappers.ContainsKey(scenarioName))
439            mappers[scenarioName] = mapper;
440        }
441      }
442      return true;
443    }
444
445    private string GetMapperFromBlobStore(string scenarioName) {
446      var scenarioDao = dal.ScenarioDao;
447      var blobDao = dal.BlobDao;
448      var entity = scenarioDao.FindByName(scenarioName);
449      if (entity == null)
450        return null;
451
452      var mapper = blobDao.FindByKey(entity.Mapper);
453      if (mapper == null)
454        return null;
455      return mapper.Text;
456    }
457
458    public bool DeleteScenario(User user, string scenarioName) {
459      // delete from table & blob store
460      var scenarioDao = dal.ScenarioDao;
461      var blobDao = dal.BlobDao;
462
463      var entity = scenarioDao.FindByName(scenarioName);
464      if (entity == null)
465        return false;
466
467      blobDao.DeleteByKey(entity.Mapper);
468      blobDao.DeleteByKey(entity.Scenario);
469      scenarioDao.DeleteByName(scenarioName);           
470      return true;
471    }
472
473    public bool SaveExperiment(User user, Model.Experiment experiment) {
474      return dal.ExperimentDao.Add(user.Username, experiment);
475    }
476
477    public IEnumerable<string> GetExperiments(User user) {
478      return (from exp in dal.ExperimentDao.GetExperiments(user.Username)
479              select exp.Name);
480    }
481
482
483    public bool DeleteExperiment(User user, string experiment) {
484      return dal.ExperimentDao.DeleteByName(user.Username, experiment);
485    }
486
487
488    public Model.Task GetTaskData(User u, string jobId, string taskId) {
489      ConfigureHive(u);
490      HiveServiceLocator.Instance.Username = u.Username;
491      HiveServiceLocator.Instance.Password = u.Password;
492      HiveServiceLocator.Instance.EndpointConfigurationName = Configuration.HiveEndpointName;
493      TaskDownloader downloader = new TaskDownloader(new List<Guid>(){Guid.Parse(taskId)});
494      downloader.StartAsync();
495      while (!downloader.IsFinished) {
496        Thread.Sleep(250);
497        if (downloader.IsFaulted) {
498          throw downloader.Exception;
499        }
500      }
501     
502      IDictionary<Guid, HiveTask> hiveTasks = downloader.Results;
503      var task = hiveTasks[Guid.Parse(taskId)];
504      if (task == null)
505        return null;
506     
507      return new Model.Task() {
508        State = new Model.TaskState() {
509          DateCreated = task.Task.DateCreated.ToString(),
510          DateFinished = task.Task.DateFinished.ToString(),
511          ExecutionTime = task.Task.ExecutionTime.ToString(),
512          State = task.Task.State.ToString()
513        },
514        General = new Model.General() {
515          Id = task.Task.Id.ToString(),
516          LastChanged = task.Task.Modified.ToString(),
517          Name = task.ItemTask.Name
518        }
519      };
520    }
521
522    public Model.Job GetTasks(User u, string jobId) {
523      var serviceLocator = ConfigureHive(u);
524      var jobTasks = serviceLocator.CallHiveService<IEnumerable<HeuristicLab.Clients.Hive.LightweightTask>>(s => s.GetLightweightJobTasks(Guid.Parse(jobId)));
525     
526      var job = new Model.Job();
527      job.Id = jobId;
528      var tasks = new Dictionary<Guid, Model.Task>();
529      // push all elements to dictionary
530      foreach (var task in jobTasks) {
531        // TODO: Crawl children + parent and create hierarchy!
532        var children = serviceLocator.CallHiveService<IEnumerable<HeuristicLab.Clients.Hive.LightweightTask>>(s => s.GetLightweightChildTasks(Guid.Parse(jobId), true, true));
533        foreach (var child in children) {
534          tasks[child.Id] = new Model.Task() {
535            State = new Model.TaskState() {
536              DateCreated = child.DateCreated.ToString(),
537              DateFinished = child.DateFinished.ToString(),
538              ExecutionTime = child.ExecutionTime.ToString(),
539              State = child.State.ToString()
540            },
541            General = new Model.General() {
542              Id = child.Id.ToString(),
543              LastChanged = child.Modified.ToString(),
544              Name = child.ItemName
545            }
546          };
547        }
548      }
549
550      // traverse all tasks again and create tree of tasks
551      foreach (var task in jobTasks) {
552        if (task.ParentTaskId.HasValue)
553          tasks[task.Id].Children.Add(tasks[task.ParentTaskId.Value]);
554        else // its a root task
555          job.Tasks.Add(tasks[task.Id]);
556      }
557
558      return job;
559    }
560
561
562    public Model.Experiment GetExperimentByName(User user, string scenario) {
563      return dal.ExperimentDao.GetExperimentByName(user.Username, scenario);
564    }
565
566
567
568  }
569}
Note: See TracBrowser for help on using the repository browser.