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

Last change on this file since 9365 was 9365, checked in by fschoepp, 9 years ago

#1888:

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