Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs @ 6996

Last change on this file since 6996 was 6983, checked in by ascheibe, 13 years ago

#1672

  • added the Hive Services and Slave projects
  • added missing svn ignores
File size: 32.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Linq.Expressions;
26using DT = HeuristicLab.Services.Hive.DataTransfer;
27
28namespace HeuristicLab.Services.Hive.DataAccess {
29  public class HiveDao : IHiveDao {
30    public static HiveDataContext CreateContext(bool longRunning = false) {
31      var context = new HiveDataContext(Settings.Default.HeuristicLab_Hive_LinqConnectionString);
32      if (longRunning) context.CommandTimeout = (int)Settings.Default.LongRunningDatabaseCommandTimeout.TotalSeconds;
33      return context;
34    }
35
36    public HiveDao() { }
37
38    #region Task Methods
39    public DT.Task GetTask(Guid id) {
40      using (var db = CreateContext()) {
41        return DT.Convert.ToDto(db.Tasks.SingleOrDefault(x => x.TaskId == id));
42      }
43    }
44
45    public IEnumerable<DT.Task> GetTasks(Expression<Func<Task, bool>> predicate) {
46      using (var db = CreateContext()) {
47        return db.Tasks.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
48      }
49    }
50
51    public Guid AddTask(DT.Task dto) {
52      using (var db = CreateContext()) {
53        var entity = DT.Convert.ToEntity(dto);
54        db.Tasks.InsertOnSubmit(entity);
55        db.SubmitChanges();
56        foreach (Guid pluginId in dto.PluginsNeededIds) {
57          db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
58        }
59        db.SubmitChanges();
60        return entity.TaskId;
61      }
62    }
63
64    public void UpdateTask(DT.Task dto) {
65      using (var db = CreateContext()) {
66        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
67        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
68        else DT.Convert.ToEntity(dto, entity);
69        foreach (Guid pluginId in dto.PluginsNeededIds) {
70          if (db.RequiredPlugins.Count(p => p.PluginId == pluginId) == 0) {
71            db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
72          }
73        }
74        db.SubmitChanges();
75      }
76    }
77
78    public void DeleteTask(Guid id) {
79      using (var db = CreateContext()) {
80        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == id);
81        if (entity != null) db.Tasks.DeleteOnSubmit(entity);
82        db.SubmitChanges(); // taskData and child tasks are deleted by db-trigger
83      }
84    }
85
86    /// <summary>
87    /// returns all parent tasks which are waiting for their child tasks to finish
88    /// </summary>
89    /// <param name="resourceIds">list of resourceids which for which the task should be valid</param>
90    /// <param name="count">maximum number of task to return</param>
91    /// <param name="finished">if true, all parent task which have FinishWhenChildJobsFinished=true are returned, otherwise only FinishWhenChildJobsFinished=false are returned</param>
92    /// <returns></returns>
93    public IEnumerable<DT.Task> GetParentTasks(IEnumerable<Guid> resourceIds, int count, bool finished) {
94      using (var db = CreateContext()) {
95        var query = from ar in db.AssignedResources
96                    where resourceIds.Contains(ar.ResourceId)
97                       && ar.Task.State == TaskState.Waiting
98                       && ar.Task.IsParentTask
99                       && (finished ? ar.Task.FinishWhenChildJobsFinished : !ar.Task.FinishWhenChildJobsFinished)
100                       && (from child in db.Tasks
101                           where child.ParentTaskId == ar.Task.TaskId
102                           select child.State == TaskState.Finished
103                               || child.State == TaskState.Aborted
104                               || child.State == TaskState.Failed).All(x => x)
105                       && (from child in db.Tasks // avoid returning WaitForChildTasks task where no child-task exist (yet)
106                           where child.ParentTaskId == ar.Task.TaskId
107                           select child).Count() > 0
108                    orderby ar.Task.Priority descending, db.Random()
109                    select DT.Convert.ToDto(ar.Task);
110        return count == 0 ? query.ToArray() : query.Take(count).ToArray();
111      }
112    }
113
114    public IEnumerable<DT.Task> GetWaitingTasks(DT.Slave slave, int count) {
115      using (var db = CreateContext()) {
116        var resourceIds = GetParentResources(slave.Id).Select(r => r.Id);
117        var waitingParentJobs = GetParentTasks(resourceIds, count, false);
118        if (count > 0 && waitingParentJobs.Count() >= count) return waitingParentJobs.Take(count).ToArray();
119
120        var query = from ar in db.AssignedResources
121                    where resourceIds.Contains(ar.ResourceId)
122                       && !(ar.Task.IsParentTask && ar.Task.FinishWhenChildJobsFinished)
123                       && ar.Task.State == TaskState.Waiting
124                       && ar.Task.CoresNeeded <= slave.FreeCores
125                       && ar.Task.MemoryNeeded <= slave.FreeMemory
126                    orderby ar.Task.Priority descending, db.Random() // take random task to avoid the race condition that occurs when this method is called concurrently (the same task would be returned)
127                    select DT.Convert.ToDto(ar.Task);
128        var waitingTasks = (count == 0 ? query : query.Take(count)).ToArray();
129        return waitingTasks.Union(waitingParentJobs).OrderByDescending(x => x.Priority);
130      }
131    }
132
133    public DT.Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
134      using (var db = CreateContext()) {
135        var job = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
136        job.State = taskState;
137        db.StateLogs.InsertOnSubmit(new StateLog {
138          TaskId = taskId,
139          State = taskState,
140          SlaveId = slaveId,
141          UserId = userId,
142          Exception = exception,
143          DateTime = DateTime.Now
144        });
145        db.SubmitChanges();
146        job = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
147        return DT.Convert.ToDto(job);
148      }
149    }
150    #endregion
151
152    #region TaskData Methods
153    public DT.TaskData GetTaskData(Guid id) {
154      using (var db = CreateContext(true)) {
155        return DT.Convert.ToDto(db.TaskDatas.SingleOrDefault(x => x.TaskId == id));
156      }
157    }
158
159    public IEnumerable<DT.TaskData> GetTaskDatas(Expression<Func<TaskData, bool>> predicate) {
160      using (var db = CreateContext(true)) {
161        return db.TaskDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
162      }
163    }
164
165    public Guid AddTaskData(DT.TaskData dto) {
166      using (var db = CreateContext(true)) {
167        var entity = DT.Convert.ToEntity(dto);
168        db.TaskDatas.InsertOnSubmit(entity);
169        db.SubmitChanges();
170        return entity.TaskId;
171      }
172    }
173
174    public void UpdateTaskData(DT.TaskData dto) {
175      using (var db = CreateContext(true)) {
176        var entity = db.TaskDatas.FirstOrDefault(x => x.TaskId == dto.TaskId);
177        if (entity == null) db.TaskDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
178        else DT.Convert.ToEntity(dto, entity);
179        db.SubmitChanges();
180      }
181    }
182
183    public void DeleteTaskData(Guid id) {
184      using (var db = CreateContext()) {
185        var entity = db.TaskDatas.FirstOrDefault(x => x.TaskId == id); // check if all the byte[] is loaded into memory here. otherwise work around to delete without loading it
186        if (entity != null) db.TaskDatas.DeleteOnSubmit(entity);
187        db.SubmitChanges();
188      }
189    }
190    #endregion
191
192    #region StateLog Methods
193    public DT.StateLog GetStateLog(Guid id) {
194      using (var db = CreateContext()) {
195        return DT.Convert.ToDto(db.StateLogs.SingleOrDefault(x => x.StateLogId == id));
196      }
197    }
198
199    public IEnumerable<DT.StateLog> GetStateLogs(Expression<Func<StateLog, bool>> predicate) {
200      using (var db = CreateContext()) {
201        return db.StateLogs.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
202      }
203    }
204
205    public Guid AddStateLog(DT.StateLog dto) {
206      using (var db = CreateContext()) {
207        var entity = DT.Convert.ToEntity(dto);
208        db.StateLogs.InsertOnSubmit(entity);
209        db.SubmitChanges();
210        return entity.StateLogId;
211      }
212    }
213
214    public void UpdateStateLog(DT.StateLog dto) {
215      using (var db = CreateContext()) {
216        var entity = db.StateLogs.FirstOrDefault(x => x.StateLogId == dto.Id);
217        if (entity == null) db.StateLogs.InsertOnSubmit(DT.Convert.ToEntity(dto));
218        else DT.Convert.ToEntity(dto, entity);
219        db.SubmitChanges();
220      }
221    }
222
223    public void DeleteStateLog(Guid id) {
224      using (var db = CreateContext()) {
225        var entity = db.StateLogs.FirstOrDefault(x => x.StateLogId == id);
226        if (entity != null) db.StateLogs.DeleteOnSubmit(entity);
227        db.SubmitChanges();
228      }
229    }
230    #endregion
231
232    #region Job Methods
233    public DT.Job GetJob(Guid id) {
234      using (var db = CreateContext()) {
235        return AddStatsToJob(db, DT.Convert.ToDto(db.Jobs.SingleOrDefault(x => x.JobId == id)));
236      }
237    }
238
239    private DT.Job AddStatsToJob(HiveDataContext db, DT.Job exp) {
240      if (exp == null)
241        return null;
242
243      var jobs = db.Tasks.Where(j => j.JobId == exp.Id);
244      exp.JobCount = jobs.Count();
245      exp.CalculatingCount = jobs.Count(j => j.State == TaskState.Calculating);
246      exp.FinishedCount = jobs.Count(j => j.State == TaskState.Finished);
247      return exp;
248    }
249
250    public IEnumerable<DT.Job> GetJobs(Expression<Func<Job, bool>> predicate) {
251      using (var db = CreateContext()) {
252        return db.Jobs.Where(predicate).Select(x => AddStatsToJob(db, DT.Convert.ToDto(x))).ToArray();
253      }
254    }
255
256    public Guid AddJob(DT.Job dto) {
257      using (var db = CreateContext()) {
258        var entity = DT.Convert.ToEntity(dto);
259        db.Jobs.InsertOnSubmit(entity);
260        db.SubmitChanges();
261        return entity.JobId;
262      }
263    }
264
265    public void UpdateJob(DT.Job dto) {
266      using (var db = CreateContext()) {
267        var entity = db.Jobs.FirstOrDefault(x => x.JobId == dto.Id);
268        if (entity == null) db.Jobs.InsertOnSubmit(DT.Convert.ToEntity(dto));
269        else DT.Convert.ToEntity(dto, entity);
270        db.SubmitChanges();
271      }
272    }
273
274    public void DeleteJob(Guid id) {
275      using (var db = CreateContext()) {
276        var entity = db.Jobs.FirstOrDefault(x => x.JobId == id);
277        if (entity != null) db.Jobs.DeleteOnSubmit(entity);
278        db.SubmitChanges();
279      }
280    }
281    #endregion
282
283    #region JobPermission Methods
284    public DT.JobPermission GetJobPermission(Guid jobId, Guid grantedUserId) {
285      using (var db = CreateContext()) {
286        return DT.Convert.ToDto(db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId));
287      }
288    }
289
290    public IEnumerable<DT.JobPermission> GetJobPermissions(Expression<Func<JobPermission, bool>> predicate) {
291      using (var db = CreateContext()) {
292        return db.JobPermissions.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
293      }
294    }
295
296    public void AddJobPermission(DT.JobPermission dto) {
297      using (var db = CreateContext()) {
298        var entity = DT.Convert.ToEntity(dto);
299        db.JobPermissions.InsertOnSubmit(entity);
300        db.SubmitChanges();
301      }
302    }
303
304    public void UpdateJobPermission(DT.JobPermission dto) {
305      using (var db = CreateContext()) {
306        var entity = db.JobPermissions.FirstOrDefault(x => x.JobId == dto.JobId && x.GrantedUserId == dto.GrantedUserId);
307        if (entity == null) db.JobPermissions.InsertOnSubmit(DT.Convert.ToEntity(dto));
308        else DT.Convert.ToEntity(dto, entity);
309        db.SubmitChanges();
310      }
311    }
312
313    public void DeleteJobPermission(Guid jobId, Guid grantedUserId) {
314      using (var db = CreateContext()) {
315        var entity = db.JobPermissions.FirstOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
316        if (entity != null) db.JobPermissions.DeleteOnSubmit(entity);
317        db.SubmitChanges();
318      }
319    }
320
321    /// <summary>
322    /// Sets the permissions for a experiment. makes sure that only one permission per user exists.
323    /// </summary>
324    public void SetJobPermission(Guid jobId, Guid grantedByUserId, Guid grantedUserId, Permission permission) {
325      using (var db = CreateContext()) {
326        JobPermission jobPermission = db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
327        if (jobPermission != null) {
328          if (permission == Permission.NotAllowed) {
329            // not allowed, delete
330            db.JobPermissions.DeleteOnSubmit(jobPermission);
331          } else {
332            // update
333            jobPermission.Permission = permission;
334            jobPermission.GrantedByUserId = grantedByUserId; // update grantedByUserId, always the last "granter" is stored
335          }
336        } else {
337          // insert
338          if (permission != Permission.NotAllowed) {
339            jobPermission = new JobPermission() { JobId = jobId, GrantedByUserId = grantedByUserId, GrantedUserId = grantedUserId, Permission = permission };
340            db.JobPermissions.InsertOnSubmit(jobPermission);
341          }
342        }
343        db.SubmitChanges();
344      }
345    }
346    #endregion
347
348    #region Plugin Methods
349    public DT.Plugin GetPlugin(Guid id) {
350      using (var db = CreateContext()) {
351        return DT.Convert.ToDto(db.Plugins.SingleOrDefault(x => x.PluginId == id));
352      }
353    }
354
355    public IEnumerable<DT.Plugin> GetPlugins(Expression<Func<Plugin, bool>> predicate) {
356      using (var db = CreateContext()) {
357        return db.Plugins.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
358      }
359    }
360
361    public Guid AddPlugin(DT.Plugin dto) {
362      using (var db = CreateContext()) {
363        var entity = DT.Convert.ToEntity(dto);
364        db.Plugins.InsertOnSubmit(entity);
365        db.SubmitChanges();
366        return entity.PluginId;
367      }
368    }
369
370    public void UpdatePlugin(DT.Plugin dto) {
371      using (var db = CreateContext()) {
372        var entity = db.Plugins.FirstOrDefault(x => x.PluginId == dto.Id);
373        if (entity == null) db.Plugins.InsertOnSubmit(DT.Convert.ToEntity(dto));
374        else DT.Convert.ToEntity(dto, entity);
375        db.SubmitChanges();
376      }
377    }
378
379    public void DeletePlugin(Guid id) {
380      using (var db = CreateContext()) {
381        var entity = db.Plugins.FirstOrDefault(x => x.PluginId == id);
382        if (entity != null) db.Plugins.DeleteOnSubmit(entity);
383        db.SubmitChanges();
384      }
385    }
386    #endregion
387
388    #region PluginData Methods
389    public DT.PluginData GetPluginData(Guid id) {
390      using (var db = CreateContext()) {
391        return DT.Convert.ToDto(db.PluginDatas.SingleOrDefault(x => x.PluginDataId == id));
392      }
393    }
394
395    public IEnumerable<DT.PluginData> GetPluginDatas(Expression<Func<PluginData, bool>> predicate) {
396      using (var db = CreateContext()) {
397        return db.PluginDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
398      }
399    }
400
401    public Guid AddPluginData(DT.PluginData dto) {
402      using (var db = CreateContext()) {
403        var entity = DT.Convert.ToEntity(dto);
404        db.PluginDatas.InsertOnSubmit(entity);
405        db.SubmitChanges();
406        return entity.PluginDataId;
407      }
408    }
409
410    public void UpdatePluginData(DT.PluginData dto) {
411      using (var db = CreateContext()) {
412        var entity = db.PluginDatas.FirstOrDefault(x => x.PluginId == dto.PluginId);
413        if (entity == null) db.PluginDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
414        else DT.Convert.ToEntity(dto, entity);
415        db.SubmitChanges();
416      }
417    }
418
419    public void DeletePluginData(Guid id) {
420      using (var db = CreateContext()) {
421        var entity = db.PluginDatas.FirstOrDefault(x => x.PluginDataId == id);
422        if (entity != null) db.PluginDatas.DeleteOnSubmit(entity);
423        db.SubmitChanges();
424      }
425    }
426    #endregion
427
428    #region Slave Methods
429    public DT.Slave GetSlave(Guid id) {
430      using (var db = CreateContext()) {
431        return DT.Convert.ToDto(db.Resources.OfType<Slave>().SingleOrDefault(x => x.ResourceId == id));
432      }
433    }
434
435    public IEnumerable<DT.Slave> GetSlaves(Expression<Func<Slave, bool>> predicate) {
436      using (var db = CreateContext()) {
437        return db.Resources.OfType<Slave>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
438      }
439    }
440
441    public Guid AddSlave(DT.Slave dto) {
442      using (var db = CreateContext()) {
443        var entity = DT.Convert.ToEntity(dto);
444        db.Resources.InsertOnSubmit(entity);
445        db.SubmitChanges();
446        return entity.ResourceId;
447      }
448    }
449
450    public void UpdateSlave(DT.Slave dto) {
451      using (var db = CreateContext()) {
452        var entity = db.Resources.OfType<Slave>().FirstOrDefault(x => x.ResourceId == dto.Id);
453        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
454        else DT.Convert.ToEntity(dto, entity);
455        db.SubmitChanges();
456      }
457    }
458
459    public void DeleteSlave(Guid id) {
460      using (var db = CreateContext()) {
461        var entity = db.Resources.OfType<Slave>().FirstOrDefault(x => x.ResourceId == id);
462        if (entity != null) db.Resources.DeleteOnSubmit(entity);
463        db.SubmitChanges();
464      }
465    }
466    #endregion
467
468    #region SlaveGroup Methods
469    public DT.SlaveGroup GetSlaveGroup(Guid id) {
470      using (var db = CreateContext()) {
471        return DT.Convert.ToDto(db.Resources.OfType<SlaveGroup>().SingleOrDefault(x => x.ResourceId == id));
472      }
473    }
474
475    public IEnumerable<DT.SlaveGroup> GetSlaveGroups(Expression<Func<SlaveGroup, bool>> predicate) {
476      using (var db = CreateContext()) {
477        return db.Resources.OfType<SlaveGroup>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
478      }
479    }
480
481    public Guid AddSlaveGroup(DT.SlaveGroup dto) {
482      using (var db = CreateContext()) {
483        if (dto.Id == Guid.Empty)
484          dto.Id = Guid.NewGuid();
485        var entity = DT.Convert.ToEntity(dto);
486        db.Resources.InsertOnSubmit(entity);
487        db.SubmitChanges();
488        return entity.ResourceId;
489      }
490    }
491
492    public void UpdateSlaveGroup(DT.SlaveGroup dto) {
493      using (var db = CreateContext()) {
494        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == dto.Id);
495        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
496        else DT.Convert.ToEntity(dto, entity);
497        db.SubmitChanges();
498      }
499    }
500
501    public void DeleteSlaveGroup(Guid id) {
502      using (var db = CreateContext()) {
503        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == id);
504        if (entity != null) {
505          if (db.Resources.Where(r => r.ParentResourceId == id).Count() > 0) {
506            throw new InvalidOperationException("Cannot delete SlaveGroup as long as there are Slaves in the group");
507          }
508          db.Resources.DeleteOnSubmit(entity);
509        }
510        db.SubmitChanges();
511      }
512    }
513    #endregion
514
515    #region Resource Methods
516    public DT.Resource GetResource(Guid id) {
517      using (var db = CreateContext()) {
518        return DT.Convert.ToDto(db.Resources.SingleOrDefault(x => x.ResourceId == id));
519      }
520    }
521
522    public IEnumerable<DT.Resource> GetResources(Expression<Func<Resource, bool>> predicate) {
523      using (var db = CreateContext()) {
524        return db.Resources.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
525      }
526    }
527
528    public Guid AddResource(DT.Resource dto) {
529      using (var db = CreateContext()) {
530        var entity = DT.Convert.ToEntity(dto);
531        db.Resources.InsertOnSubmit(entity);
532        db.SubmitChanges();
533        return entity.ResourceId;
534      }
535    }
536
537    public void UpdateResource(DT.Resource dto) {
538      using (var db = CreateContext()) {
539        var entity = db.Resources.FirstOrDefault(x => x.ResourceId == dto.Id);
540        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
541        else DT.Convert.ToEntity(dto, entity);
542        db.SubmitChanges();
543      }
544    }
545
546    public void DeleteResource(Guid id) {
547      using (var db = CreateContext()) {
548        var entity = db.Resources.FirstOrDefault(x => x.ResourceId == id);
549        if (entity != null) db.Resources.DeleteOnSubmit(entity);
550        db.SubmitChanges();
551      }
552    }
553
554    public void AssignJobToResource(Guid jobId, Guid resourceId) {
555      using (var db = CreateContext()) {
556        var job = db.Tasks.Where(x => x.TaskId == jobId).Single();
557        job.AssignedResources.Add(new AssignedResource() { TaskId = jobId, ResourceId = resourceId });
558        db.SubmitChanges();
559      }
560    }
561
562    public IEnumerable<DT.Resource> GetAssignedResources(Guid jobId) {
563      using (var db = CreateContext()) {
564        var job = db.Tasks.Where(x => x.TaskId == jobId).Single();
565        return job.AssignedResources.Select(x => DT.Convert.ToDto(x.Resource)).ToArray();
566      }
567    }
568
569    /// <summary>
570    /// Returns all parent resources of a resource (the given resource is also added)
571    /// </summary>
572    public IEnumerable<DT.Resource> GetParentResources(Guid resourceId) {
573      using (var db = CreateContext()) {
574        var resources = new List<Resource>();
575        CollectParentResources(resources, db.Resources.Where(r => r.ResourceId == resourceId).Single());
576        return resources.Select(r => DT.Convert.ToDto(r)).ToArray();
577      }
578    }
579
580    private void CollectParentResources(List<Resource> resources, Resource resource) {
581      if (resource == null) return;
582      resources.Add(resource);
583      CollectParentResources(resources, resource.ParentResource);
584    }
585
586    /// <summary>
587    /// Returns all child resources of a resource (without the given resource)
588    /// </summary>
589    public IEnumerable<DT.Resource> GetChildResources(Guid resourceId) {
590      using (var db = CreateContext()) {
591        var childs = new List<DT.Resource>();
592        foreach (var child in db.Resources.Where(x => x.ParentResourceId == resourceId)) {
593          childs.Add(DT.Convert.ToDto(child));
594          childs.AddRange(GetChildResources(child.ResourceId));
595        }
596        return childs;
597      }
598    }
599
600    public IEnumerable<DT.Task> GetJobsByResourceId(Guid resourceId) {
601      using (var db = CreateContext()) {
602        var resources = GetChildResources(resourceId).Select(x => x.Id).ToList();
603        resources.Add(resourceId);
604
605        var jobs = db.Tasks.Where(j =>
606          j.State == TaskState.Calculating &&
607          j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.HasValue &&
608          resources.Contains(j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.Value));
609        return jobs.Select(j => DT.Convert.ToDto(j)).ToArray();
610      }
611    }
612    #endregion
613
614    #region Authorization Methods
615    public Permission GetPermissionForTask(Guid taskId, Guid userId) {
616      using (var db = CreateContext()) {
617        return GetPermissionForJob(GetJobForTask(taskId), userId);
618      }
619    }
620
621    public Permission GetPermissionForJob(Guid jobId, Guid userId) {
622      using (var db = CreateContext()) {
623        Job job = db.Jobs.SingleOrDefault(x => x.JobId == jobId);
624        if (job == null) return Permission.NotAllowed;
625        if (job.OwnerUserId == userId) return Permission.Full;
626        JobPermission permission = db.JobPermissions.SingleOrDefault(p => p.JobId == jobId && p.GrantedUserId == userId);
627        return permission != null ? permission.Permission : Permission.NotAllowed;
628      }
629    }
630
631    public Guid GetJobForTask(Guid taskId) {
632      using (var db = CreateContext()) {
633        return db.Tasks.Single(j => j.TaskId == taskId).JobId;
634      }
635    }
636    #endregion
637
638    #region Lifecycle Methods
639    public DateTime GetLastCleanup() {
640      using (var db = CreateContext()) {
641        var entity = db.Lifecycles.SingleOrDefault();
642        return entity != null ? entity.LastCleanup : DateTime.MinValue;
643      }
644    }
645
646    public void SetLastCleanup(DateTime datetime) {
647      using (var db = CreateContext()) {
648        var entity = db.Lifecycles.SingleOrDefault();
649        if (entity != null) {
650          entity.LastCleanup = datetime;
651        } else {
652          entity = new Lifecycle();
653          entity.LifecycleId = 0; // always only one entry with ID:0
654          entity.LastCleanup = datetime;
655          db.Lifecycles.InsertOnSubmit(entity);
656        }
657        db.SubmitChanges();
658      }
659    }
660    #endregion
661
662    #region Downtime Methods
663    public DT.Downtime GetDowntime(Guid id) {
664      using (var db = CreateContext()) {
665        return DT.Convert.ToDto(db.Downtimes.SingleOrDefault(x => x.DowntimeId == id));
666      }
667    }
668
669    public IEnumerable<DT.Downtime> GetDowntimes(Expression<Func<Downtime, bool>> predicate) {
670      using (var db = CreateContext()) {
671        return db.Downtimes.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
672      }
673    }
674
675    public Guid AddDowntime(DT.Downtime dto) {
676      using (var db = CreateContext()) {
677        var entity = DT.Convert.ToEntity(dto);
678        db.Downtimes.InsertOnSubmit(entity);
679        db.SubmitChanges();
680        return entity.DowntimeId;
681      }
682    }
683
684    public void UpdateDowntime(DT.Downtime dto) {
685      using (var db = CreateContext()) {
686        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == dto.Id);
687        if (entity == null) db.Downtimes.InsertOnSubmit(DT.Convert.ToEntity(dto));
688        else DT.Convert.ToEntity(dto, entity);
689        db.SubmitChanges();
690      }
691    }
692
693    public void DeleteDowntime(Guid id) {
694      using (var db = CreateContext()) {
695        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == id);
696        if (entity != null) db.Downtimes.DeleteOnSubmit(entity);
697        db.SubmitChanges();
698      }
699    }
700    #endregion
701
702    #region Statistics Methods
703    public DT.Statistics GetStatistic(Guid id) {
704      using (var db = CreateContext()) {
705        return DT.Convert.ToDto(db.Statistics.SingleOrDefault(x => x.StatisticsId == id));
706      }
707    }
708
709    public IEnumerable<DT.Statistics> GetStatistics(Expression<Func<Statistics, bool>> predicate) {
710      using (var db = CreateContext()) {
711        return db.Statistics.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
712      }
713    }
714
715    public Guid AddStatistics(DT.Statistics dto) {
716      using (var db = CreateContext()) {
717        var entity = DT.Convert.ToEntity(dto);
718        db.Statistics.InsertOnSubmit(entity);
719        db.SubmitChanges();
720        foreach (var slaveStat in dto.SlaveStatistics) {
721          slaveStat.Id = entity.StatisticsId;
722          db.SlaveStatistics.InsertOnSubmit(DT.Convert.ToEntity(slaveStat));
723        }
724        if (dto.UserStatistics != null) {
725          foreach (var userStat in dto.UserStatistics) {
726            userStat.Id = entity.StatisticsId;
727            db.UserStatistics.InsertOnSubmit(DT.Convert.ToEntity(userStat));
728          }
729        }
730        db.SubmitChanges();
731        return entity.StatisticsId;
732      }
733    }
734
735    public void DeleteStatistics(Guid id) {
736      using (var db = CreateContext()) {
737        var entity = db.Statistics.FirstOrDefault(x => x.StatisticsId == id);
738        if (entity != null) db.Statistics.DeleteOnSubmit(entity);
739        db.SubmitChanges();
740      }
741    }
742
743    public List<DT.UserStatistics> GetUserStatistics() {
744      using (var db = CreateContext()) {
745        var userStats = new Dictionary<Guid, DT.UserStatistics>();
746
747        var usedCoresByUser = from job in db.Tasks
748                              where job.State == TaskState.Calculating
749                              group job by job.Job.OwnerUserId into g
750                              select new { UserId = g.Key, UsedCores = g.Count() };
751
752        foreach (var item in usedCoresByUser) {
753          if (!userStats.ContainsKey(item.UserId)) {
754            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
755          }
756          userStats[item.UserId].UsedCores += item.UsedCores;
757        }
758
759        var executionTimesByUser = from task in db.Tasks
760                                   group task by task.Job.OwnerUserId into g
761                                   select new { UserId = g.Key, ExecutionTime = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
762        foreach (var item in executionTimesByUser) {
763          if (!userStats.ContainsKey(item.UserId)) {
764            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
765          }
766          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
767        }
768
769        // execution times only of finished task - necessary to compute efficieny
770        var executionTimesFinishedJobs = from job in db.Tasks
771                                         where job.State == TaskState.Finished
772                                         group job by job.Job.OwnerUserId into g
773                                         select new { UserId = g.Key, ExecutionTimeFinishedJobs = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
774
775        foreach (var item in executionTimesFinishedJobs) {
776          if (!userStats.ContainsKey(item.UserId)) {
777            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
778          }
779          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
780        }
781
782        // start to end times only of finished task - necessary to compute efficiency
783        var startToEndTimesFinishedJobs = from job in db.Tasks
784                                          where job.State == TaskState.Finished
785                                          group job by job.Job.OwnerUserId into g
786                                          select new {
787                                            UserId = g.Key,
788                                            StartToEndTime = new TimeSpan(g.Select(x => x.StateLogs.OrderByDescending(sl => sl.DateTime).First().DateTime - x.StateLogs.OrderBy(sl => sl.DateTime).First().DateTime).Sum(ts => ts.Ticks))
789                                          };
790        foreach (var item in startToEndTimesFinishedJobs) {
791          if (!userStats.ContainsKey(item.UserId)) {
792            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
793          }
794          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
795        }
796
797        // also consider executiontimes of DeletedJobStats
798        var deletedJobsExecutionTimesByUsers = from del in db.DeletedJobStatistics
799                                               group del by del.UserId into g
800                                               select new {
801                                                 UserId = g.Key,
802                                                 ExecutionTime = TimeSpan.FromSeconds(g.Select(x => x.ExecutionTimeS).Sum()),
803                                                 ExecutionTimeFinishedJobs = TimeSpan.FromSeconds(g.Select(x => x.ExecutionTimeSFinishedJobs).Sum()),
804                                                 StartToEndTime = TimeSpan.FromSeconds(g.Select(x => x.StartToEndTimeS).Sum())
805                                               };
806        foreach (var item in deletedJobsExecutionTimesByUsers) {
807          if (!userStats.ContainsKey(item.UserId)) {
808            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
809          }
810          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
811          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
812          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
813        }
814
815        return userStats.Values.ToList();
816      }
817    }
818    #endregion
819
820    #region Helpers
821    private void CollectChildTasks(HiveDataContext db, Guid parentTaskId, List<Task> collection) {
822      var tasks = db.Tasks.Where(j => j.ParentTaskId == parentTaskId);
823      foreach (var task in tasks) {
824        collection.Add(task);
825        if (task.IsParentTask)
826          CollectChildTasks(db, task.TaskId, collection);
827      }
828    }
829    #endregion
830  }
831}
Note: See TracBrowser for help on using the repository browser.