Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveDtoDao.cs @ 9391

Last change on this file since 9391 was 9391, checked in by pfleck, 10 years ago

#2030
Separated old DTO-Dao from new Dao. DTO-Dao should be replaced completely.
Heartbeat and UpdateTaskState uses new Dao.
DataContext is now closed on ServiceOperation end.

File size: 41.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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 HiveDtoDao : IHiveDtoDao {
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 HiveDtoDao() { }
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 IEnumerable<DT.LightweightTask> GetLightweightTasks(Expression<Func<Task, bool>> predicate) {
52      List<DT.LightweightTask> tasks = new List<DT.LightweightTask>();
53
54      using (var db = CreateContext()) {
55        var tasksQuery = db.Tasks.Where(predicate).Select(task => new { task.TaskId, task.ExecutionTimeMs, task.ParentTaskId, task.StateLogs, task.State, task.Command });
56        var taskDatasQuery = db.Tasks.Where(predicate).Where(task => task.JobData != null).Select(task => new { task.TaskId, task.JobData.LastUpdate });
57
58        foreach (var task in tasksQuery) {
59          DT.LightweightTask t = new DT.LightweightTask();
60          t.Id = task.TaskId;
61          t.ExecutionTime = TimeSpan.FromMilliseconds(task.ExecutionTimeMs);
62          t.ParentTaskId = task.ParentTaskId;
63          t.StateLog = task.StateLogs == null ? new List<DT.StateLog>() : task.StateLogs.Select(x => DataTransfer.Convert.ToDto(x)).OrderBy(x => x.DateTime).ToList();
64          t.State = DataTransfer.Convert.ToDto(task.State);
65          t.Command = DataTransfer.Convert.ToDto(task.Command);
66          t.LastTaskDataUpdate = taskDatasQuery.Where(x => x.TaskId == task.TaskId).Count() > 0 ? taskDatasQuery.Select(x => x.LastUpdate).First() : DateTime.MinValue;
67          tasks.Add(t);
68        }
69      }
70      return tasks;
71    }
72
73    public IEnumerable<DT.LightweightTask> GetLightweightTasksWithoutStateLog(Expression<Func<Task, bool>> predicate) {
74      List<DT.LightweightTask> tasks = new List<DT.LightweightTask>();
75
76      using (var db = CreateContext()) {
77        var tasksQuery = db.Tasks.Where(predicate).Select(task => new { task.TaskId, task.ExecutionTimeMs, task.ParentTaskId, task.State, task.Command });
78        var taskDatasQuery = db.Tasks.Where(predicate).Where(task => task.JobData != null).Select(task => new { task.TaskId, task.JobData.LastUpdate });
79
80        foreach (var task in tasksQuery) {
81          DT.LightweightTask t = new DT.LightweightTask();
82          t.Id = task.TaskId;
83          t.ExecutionTime = TimeSpan.FromMilliseconds(task.ExecutionTimeMs);
84          t.ParentTaskId = task.ParentTaskId;
85          t.StateLog = new List<DT.StateLog>();
86          t.State = DataTransfer.Convert.ToDto(task.State);
87          t.Command = DataTransfer.Convert.ToDto(task.Command);
88          t.LastTaskDataUpdate = taskDatasQuery.Where(x => x.TaskId == task.TaskId).Count() > 0 ? taskDatasQuery.Select(x => x.LastUpdate).First() : DateTime.MinValue;
89          tasks.Add(t);
90        }
91      }
92      return tasks;
93    }
94
95    public Guid AddTask(DT.Task dto) {
96      using (var db = CreateContext()) {
97        var entity = DT.Convert.ToEntity(dto);
98        db.Tasks.InsertOnSubmit(entity);
99        db.SubmitChanges();
100        foreach (Guid pluginId in dto.PluginsNeededIds) {
101          db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
102        }
103        db.SubmitChanges();
104        return entity.TaskId;
105      }
106    }
107
108    public void UpdateTaskAndPlugins(DT.Task dto) {
109      using (var db = CreateContext()) {
110        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
111        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
112        else DT.Convert.ToEntity(dto, entity);
113        foreach (Guid pluginId in dto.PluginsNeededIds) {
114          if (db.RequiredPlugins.Count(p => p.PluginId == pluginId) == 0) {
115            db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
116          }
117        }
118        db.SubmitChanges();
119      }
120    }
121
122    public void UpdateTaskAndStateLogs(DT.Task dto) {
123      using (var db = CreateContext()) {
124        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
125        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
126        else DT.Convert.ToEntity(dto, entity);
127        db.SubmitChanges();
128      }
129    }
130
131    public void UpdateTask(DT.Task dto) {
132      using (var db = CreateContext()) {
133        db.DeferredLoadingEnabled = false;
134
135        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
136        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
137        else DT.Convert.ToEntityTaskOnly(dto, entity);
138        db.SubmitChanges();
139      }
140    }
141
142    public void DeleteTask(Guid id) {
143      using (var db = CreateContext()) {
144        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == id);
145        if (entity != null) db.Tasks.DeleteOnSubmit(entity);
146        db.SubmitChanges(); // taskData and child tasks are deleted by db-trigger
147      }
148    }
149
150    /// <summary>
151    /// returns all parent tasks which are waiting for their child tasks to finish
152    /// </summary>
153    /// <param name="resourceIds">list of resourceids which for which the task should be valid</param>
154    /// <param name="count">maximum number of task to return</param>
155    /// <param name="finished">if true, all parent task which have FinishWhenChildJobsFinished=true are returned, otherwise only FinishWhenChildJobsFinished=false are returned</param>
156    /// <returns></returns>
157    public IEnumerable<DT.Task> GetParentTasks(IEnumerable<Guid> resourceIds, int count, bool finished) {
158      using (var db = CreateContext()) {
159        var query = from ar in db.AssignedResources
160                    where resourceIds.Contains(ar.ResourceId)
161                       && ar.Task.State == TaskState.Waiting
162                       && ar.Task.IsParentTask
163                       && (finished ? ar.Task.FinishWhenChildJobsFinished : !ar.Task.FinishWhenChildJobsFinished)
164                       && (from child in db.Tasks
165                           where child.ParentTaskId == ar.Task.TaskId
166                           select child.State == TaskState.Finished
167                               || child.State == TaskState.Aborted
168                               || child.State == TaskState.Failed).All(x => x)
169                       && (from child in db.Tasks // avoid returning WaitForChildTasks task where no child-task exist (yet)
170                           where child.ParentTaskId == ar.Task.TaskId
171                           select child).Count() > 0
172                    orderby ar.Task.Priority descending, db.Random()
173                    select DT.Convert.ToDto(ar.Task);
174        return count == 0 ? query.ToArray() : query.Take(count).ToArray();
175      }
176    }
177
178    public IEnumerable<TaskInfoForScheduler> GetWaitingTasks(DT.Slave slave) {
179      using (var db = CreateContext()) {
180        var resourceIds = GetParentResources(slave.Id).Select(r => r.Id);
181        //Originally we checked here if there are parent tasks which should be calculated (with GetParentTasks(resourceIds, count, false);).
182        //Because there is at the moment no case where this makes sense (there don't exist parent tasks which need to be calculated),
183        //we skip this step because it's wasted runtime
184
185        var query = from ar in db.AssignedResources
186                    where resourceIds.Contains(ar.ResourceId)
187                       && !(ar.Task.IsParentTask && ar.Task.FinishWhenChildJobsFinished)
188                       && ar.Task.State == TaskState.Waiting
189                       && ar.Task.CoresNeeded <= slave.FreeCores
190                       && ar.Task.MemoryNeeded <= slave.FreeMemory
191                    select new TaskInfoForScheduler() { TaskId = ar.Task.TaskId, JobId = ar.Task.JobId, Priority = ar.Task.Priority };
192        var waitingTasks = query.ToArray();
193        return waitingTasks;
194      }
195    }
196
197    public DT.Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
198      using (var db = CreateContext()) {
199        db.DeferredLoadingEnabled = false;
200
201        db.StateLogs.InsertOnSubmit(new StateLog {
202          TaskId = taskId,
203          State = taskState,
204          SlaveId = slaveId,
205          UserId = userId,
206          Exception = exception,
207          DateTime = DateTime.Now
208        });
209        db.SubmitChanges();
210      }
211
212      using (var db = CreateContext()) {
213        db.DeferredLoadingEnabled = false;
214
215        var task = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
216        task.State = taskState;
217        db.SubmitChanges();
218      }
219
220      using (var db = CreateContext()) {
221        var task = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
222        return DT.Convert.ToDto(task);
223      }
224    }
225    #endregion
226
227    #region TaskData Methods
228    public DT.TaskData GetTaskData(Guid id) {
229      using (var db = CreateContext(true)) {
230        return DT.Convert.ToDto(db.TaskDatas.SingleOrDefault(x => x.TaskId == id));
231      }
232    }
233
234    public IEnumerable<DT.TaskData> GetTaskDatas(Expression<Func<TaskData, bool>> predicate) {
235      using (var db = CreateContext(true)) {
236        return db.TaskDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
237      }
238    }
239
240    public Guid AddTaskData(DT.TaskData dto) {
241      using (var db = CreateContext(true)) {
242        var entity = DT.Convert.ToEntity(dto);
243        db.TaskDatas.InsertOnSubmit(entity);
244        db.SubmitChanges();
245        return entity.TaskId;
246      }
247    }
248
249    public void UpdateTaskData(DT.TaskData dto) {
250      using (var db = CreateContext(true)) {
251        var entity = db.TaskDatas.FirstOrDefault(x => x.TaskId == dto.TaskId);
252        if (entity == null) db.TaskDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
253        else DT.Convert.ToEntity(dto, entity);
254        db.SubmitChanges();
255      }
256    }
257
258    public void DeleteTaskData(Guid id) {
259      using (var db = CreateContext()) {
260        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
261        if (entity != null) db.TaskDatas.DeleteOnSubmit(entity);
262        db.SubmitChanges();
263      }
264    }
265    #endregion
266
267    #region StateLog Methods
268    public DT.StateLog GetStateLog(Guid id) {
269      using (var db = CreateContext()) {
270        return DT.Convert.ToDto(db.StateLogs.SingleOrDefault(x => x.StateLogId == id));
271      }
272    }
273
274    public IEnumerable<DT.StateLog> GetStateLogs(Expression<Func<StateLog, bool>> predicate) {
275      using (var db = CreateContext()) {
276        return db.StateLogs.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
277      }
278    }
279
280    public Guid AddStateLog(DT.StateLog dto) {
281      using (var db = CreateContext()) {
282        var entity = DT.Convert.ToEntity(dto);
283        db.StateLogs.InsertOnSubmit(entity);
284        db.SubmitChanges();
285        return entity.StateLogId;
286      }
287    }
288
289    public void UpdateStateLog(DT.StateLog dto) {
290      using (var db = CreateContext()) {
291        var entity = db.StateLogs.FirstOrDefault(x => x.StateLogId == dto.Id);
292        if (entity == null) db.StateLogs.InsertOnSubmit(DT.Convert.ToEntity(dto));
293        else DT.Convert.ToEntity(dto, entity);
294        db.SubmitChanges();
295      }
296    }
297
298    public void DeleteStateLog(Guid id) {
299      using (var db = CreateContext()) {
300        var entity = db.StateLogs.FirstOrDefault(x => x.StateLogId == id);
301        if (entity != null) db.StateLogs.DeleteOnSubmit(entity);
302        db.SubmitChanges();
303      }
304    }
305    #endregion
306
307    #region Job Methods
308    public DT.Job GetJob(Guid id) {
309      using (var db = CreateContext()) {
310        return AddStatsToJob(db, DT.Convert.ToDto(db.Jobs.SingleOrDefault(x => x.JobId == id)));
311      }
312    }
313
314    private DT.Job AddStatsToJob(HiveDataContext db, DT.Job exp) {
315      if (exp == null)
316        return null;
317
318      var jobs = db.Tasks.Where(j => j.JobId == exp.Id);
319      exp.JobCount = jobs.Count();
320      exp.CalculatingCount = jobs.Count(j => j.State == TaskState.Calculating);
321      exp.FinishedCount = jobs.Count(j => j.State == TaskState.Finished);
322      return exp;
323    }
324
325    public IEnumerable<DT.Job> GetJobs(Expression<Func<Job, bool>> predicate) {
326      using (var db = CreateContext()) {
327        return db.Jobs.Where(predicate).Select(x => AddStatsToJob(db, DT.Convert.ToDto(x))).ToArray();
328      }
329    }
330
331    public IEnumerable<JobInfoForScheduler> GetJobInfoForScheduler(Expression<Func<Job, bool>> predicate) {
332      using (var db = CreateContext()) {
333        return db.Jobs.Where(predicate).Select(x => new JobInfoForScheduler() { Id = x.JobId, DateCreated = x.DateCreated, OwnerUserId = x.OwnerUserId }).ToArray();
334      }
335    }
336
337    public Guid AddJob(DT.Job dto) {
338      using (var db = CreateContext()) {
339        var entity = DT.Convert.ToEntity(dto);
340        db.Jobs.InsertOnSubmit(entity);
341        if (!db.UserPriorities.Any(x => x.UserId == dto.OwnerUserId))
342          EnqueueUserPriority(new DT.UserPriority { Id = dto.OwnerUserId, DateEnqueued = dto.DateCreated });
343        db.SubmitChanges();
344        return entity.JobId;
345      }
346    }
347
348    public void UpdateJob(DT.Job dto) {
349      using (var db = CreateContext()) {
350        var entity = db.Jobs.FirstOrDefault(x => x.JobId == dto.Id);
351        if (entity == null) db.Jobs.InsertOnSubmit(DT.Convert.ToEntity(dto));
352        else DT.Convert.ToEntity(dto, entity);
353        db.SubmitChanges();
354      }
355    }
356
357    public void DeleteJob(Guid id) {
358      using (var db = CreateContext()) {
359        var entity = db.Jobs.FirstOrDefault(x => x.JobId == id);
360        if (entity != null) db.Jobs.DeleteOnSubmit(entity);
361        db.SubmitChanges();
362      }
363    }
364    #endregion
365
366    #region JobPermission Methods
367    public DT.JobPermission GetJobPermission(Guid jobId, Guid grantedUserId) {
368      using (var db = CreateContext()) {
369        return DT.Convert.ToDto(db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId));
370      }
371    }
372
373    public IEnumerable<DT.JobPermission> GetJobPermissions(Expression<Func<JobPermission, bool>> predicate) {
374      using (var db = CreateContext()) {
375        return db.JobPermissions.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
376      }
377    }
378
379    public void AddJobPermission(DT.JobPermission dto) {
380      using (var db = CreateContext()) {
381        var entity = DT.Convert.ToEntity(dto);
382        db.JobPermissions.InsertOnSubmit(entity);
383        db.SubmitChanges();
384      }
385    }
386
387    public void UpdateJobPermission(DT.JobPermission dto) {
388      using (var db = CreateContext()) {
389        var entity = db.JobPermissions.FirstOrDefault(x => x.JobId == dto.JobId && x.GrantedUserId == dto.GrantedUserId);
390        if (entity == null) db.JobPermissions.InsertOnSubmit(DT.Convert.ToEntity(dto));
391        else DT.Convert.ToEntity(dto, entity);
392        db.SubmitChanges();
393      }
394    }
395
396    public void DeleteJobPermission(Guid jobId, Guid grantedUserId) {
397      using (var db = CreateContext()) {
398        var entity = db.JobPermissions.FirstOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
399        if (entity != null) db.JobPermissions.DeleteOnSubmit(entity);
400        db.SubmitChanges();
401      }
402    }
403
404    /// <summary>
405    /// Sets the permissions for a experiment. makes sure that only one permission per user exists.
406    /// </summary>
407    public void SetJobPermission(Guid jobId, Guid grantedByUserId, Guid grantedUserId, Permission permission) {
408      using (var db = CreateContext()) {
409        JobPermission jobPermission = db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
410        if (jobPermission != null) {
411          if (permission == Permission.NotAllowed) {
412            // not allowed, delete
413            db.JobPermissions.DeleteOnSubmit(jobPermission);
414          } else {
415            // update
416            jobPermission.Permission = permission;
417            jobPermission.GrantedByUserId = grantedByUserId; // update grantedByUserId, always the last "granter" is stored
418          }
419        } else {
420          // insert
421          if (permission != Permission.NotAllowed) {
422            jobPermission = new JobPermission() { JobId = jobId, GrantedByUserId = grantedByUserId, GrantedUserId = grantedUserId, Permission = permission };
423            db.JobPermissions.InsertOnSubmit(jobPermission);
424          }
425        }
426        db.SubmitChanges();
427      }
428    }
429    #endregion
430
431    #region Plugin Methods
432    public DT.Plugin GetPlugin(Guid id) {
433      using (var db = CreateContext()) {
434        return DT.Convert.ToDto(db.Plugins.SingleOrDefault(x => x.PluginId == id));
435      }
436    }
437
438    public IEnumerable<DT.Plugin> GetPlugins(Expression<Func<Plugin, bool>> predicate) {
439      using (var db = CreateContext()) {
440        return db.Plugins.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
441      }
442    }
443
444    public Guid AddPlugin(DT.Plugin dto) {
445      using (var db = CreateContext()) {
446        var entity = DT.Convert.ToEntity(dto);
447        db.Plugins.InsertOnSubmit(entity);
448        db.SubmitChanges();
449        return entity.PluginId;
450      }
451    }
452
453    public void UpdatePlugin(DT.Plugin dto) {
454      using (var db = CreateContext()) {
455        var entity = db.Plugins.FirstOrDefault(x => x.PluginId == dto.Id);
456        if (entity == null) db.Plugins.InsertOnSubmit(DT.Convert.ToEntity(dto));
457        else DT.Convert.ToEntity(dto, entity);
458        db.SubmitChanges();
459      }
460    }
461
462    public void DeletePlugin(Guid id) {
463      using (var db = CreateContext()) {
464        var entity = db.Plugins.FirstOrDefault(x => x.PluginId == id);
465        if (entity != null) db.Plugins.DeleteOnSubmit(entity);
466        db.SubmitChanges();
467      }
468    }
469    #endregion
470
471    #region PluginData Methods
472    public DT.PluginData GetPluginData(Guid id) {
473      using (var db = CreateContext()) {
474        return DT.Convert.ToDto(db.PluginDatas.SingleOrDefault(x => x.PluginDataId == id));
475      }
476    }
477
478    public IEnumerable<DT.PluginData> GetPluginDatas(Expression<Func<PluginData, bool>> predicate) {
479      using (var db = CreateContext()) {
480        return db.PluginDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
481      }
482    }
483
484    public Guid AddPluginData(DT.PluginData dto) {
485      using (var db = CreateContext()) {
486        var entity = DT.Convert.ToEntity(dto);
487        db.PluginDatas.InsertOnSubmit(entity);
488        db.SubmitChanges();
489        return entity.PluginDataId;
490      }
491    }
492
493    public void UpdatePluginData(DT.PluginData dto) {
494      using (var db = CreateContext()) {
495        var entity = db.PluginDatas.FirstOrDefault(x => x.PluginId == dto.PluginId);
496        if (entity == null) db.PluginDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
497        else DT.Convert.ToEntity(dto, entity);
498        db.SubmitChanges();
499      }
500    }
501
502    public void DeletePluginData(Guid id) {
503      using (var db = CreateContext()) {
504        var entity = db.PluginDatas.FirstOrDefault(x => x.PluginDataId == id);
505        if (entity != null) db.PluginDatas.DeleteOnSubmit(entity);
506        db.SubmitChanges();
507      }
508    }
509    #endregion
510
511    #region Slave Methods
512    public DT.Slave GetSlave(Guid id) {
513      using (var db = CreateContext()) {
514        return DT.Convert.ToDto(db.Resources.OfType<Slave>().SingleOrDefault(x => x.ResourceId == id));
515      }
516    }
517
518    public IEnumerable<DT.Slave> GetSlaves(Expression<Func<Slave, bool>> predicate) {
519      using (var db = CreateContext()) {
520        return db.Resources.OfType<Slave>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
521      }
522    }
523
524    public Guid AddSlave(DT.Slave dto) {
525      using (var db = CreateContext()) {
526        var entity = DT.Convert.ToEntity(dto);
527        db.Resources.InsertOnSubmit(entity);
528        db.SubmitChanges();
529        return entity.ResourceId;
530      }
531    }
532
533    public void UpdateSlave(DT.Slave dto) {
534      using (var db = CreateContext()) {
535        var entity = db.Resources.OfType<Slave>().FirstOrDefault(x => x.ResourceId == dto.Id);
536        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
537        else DT.Convert.ToEntity(dto, entity);
538        db.SubmitChanges();
539      }
540    }
541
542    public void DeleteSlave(Guid id) {
543      using (var db = CreateContext()) {
544        var entity = db.Resources.OfType<Slave>().FirstOrDefault(x => x.ResourceId == id);
545        if (entity != null) db.Resources.DeleteOnSubmit(entity);
546        db.SubmitChanges();
547      }
548    }
549    #endregion
550
551    #region SlaveGroup Methods
552    public DT.SlaveGroup GetSlaveGroup(Guid id) {
553      using (var db = CreateContext()) {
554        return DT.Convert.ToDto(db.Resources.OfType<SlaveGroup>().SingleOrDefault(x => x.ResourceId == id));
555      }
556    }
557
558    public IEnumerable<DT.SlaveGroup> GetSlaveGroups(Expression<Func<SlaveGroup, bool>> predicate) {
559      using (var db = CreateContext()) {
560        return db.Resources.OfType<SlaveGroup>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
561      }
562    }
563
564    public Guid AddSlaveGroup(DT.SlaveGroup dto) {
565      using (var db = CreateContext()) {
566        if (dto.Id == Guid.Empty)
567          dto.Id = Guid.NewGuid();
568        var entity = DT.Convert.ToEntity(dto);
569        db.Resources.InsertOnSubmit(entity);
570        db.SubmitChanges();
571        return entity.ResourceId;
572      }
573    }
574
575    public void UpdateSlaveGroup(DT.SlaveGroup dto) {
576      using (var db = CreateContext()) {
577        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == dto.Id);
578        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
579        else DT.Convert.ToEntity(dto, entity);
580        db.SubmitChanges();
581      }
582    }
583
584    public void DeleteSlaveGroup(Guid id) {
585      using (var db = CreateContext()) {
586        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == id);
587        if (entity != null) {
588          if (db.Resources.Where(r => r.ParentResourceId == id).Count() > 0) {
589            throw new InvalidOperationException("Cannot delete SlaveGroup as long as there are Slaves in the group");
590          }
591          db.Resources.DeleteOnSubmit(entity);
592        }
593        db.SubmitChanges();
594      }
595    }
596    #endregion
597
598    #region Resource Methods
599    public DT.Resource GetResource(Guid id) {
600      using (var db = CreateContext()) {
601        return DT.Convert.ToDto(db.Resources.SingleOrDefault(x => x.ResourceId == id));
602      }
603    }
604
605    public IEnumerable<DT.Resource> GetResources(Expression<Func<Resource, bool>> predicate) {
606      using (var db = CreateContext()) {
607        return db.Resources.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
608      }
609    }
610
611    public Guid AddResource(DT.Resource dto) {
612      using (var db = CreateContext()) {
613        var entity = DT.Convert.ToEntity(dto);
614        db.Resources.InsertOnSubmit(entity);
615        db.SubmitChanges();
616        return entity.ResourceId;
617      }
618    }
619
620    public void UpdateResource(DT.Resource dto) {
621      using (var db = CreateContext()) {
622        var entity = db.Resources.FirstOrDefault(x => x.ResourceId == dto.Id);
623        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
624        else DT.Convert.ToEntity(dto, entity);
625        db.SubmitChanges();
626      }
627    }
628
629    public void DeleteResource(Guid id) {
630      using (var db = CreateContext()) {
631        var entity = db.Resources.FirstOrDefault(x => x.ResourceId == id);
632        if (entity != null) db.Resources.DeleteOnSubmit(entity);
633        db.SubmitChanges();
634      }
635    }
636
637    public void AssignJobToResource(Guid taskId, IEnumerable<Guid> resourceIds) {
638      using (var db = CreateContext()) {
639        db.DeferredLoadingEnabled = false;
640
641        List<AssignedResource> assignedResources = new List<AssignedResource>();
642        foreach (Guid rId in resourceIds) {
643          assignedResources.Add(new AssignedResource() { TaskId = taskId, ResourceId = rId });
644        }
645        db.AssignedResources.InsertAllOnSubmit(assignedResources);
646        db.SubmitChanges();
647      }
648    }
649
650    public IEnumerable<DT.Resource> GetAssignedResources(Guid jobId) {
651      using (var db = CreateContext()) {
652        var job = db.Tasks.Where(x => x.TaskId == jobId).Single();
653        return job.AssignedResources.Select(x => DT.Convert.ToDto(x.Resource)).ToArray();
654      }
655    }
656
657    /// <summary>
658    /// Returns all parent resources of a resource (the given resource is also added)
659    /// </summary>
660    public IEnumerable<DT.Resource> GetParentResources(Guid resourceId) {
661      using (var db = CreateContext()) {
662        var resources = new List<Resource>();
663        CollectParentResources(resources, db.Resources.Where(r => r.ResourceId == resourceId).Single());
664        return resources.Select(r => DT.Convert.ToDto(r)).ToArray();
665      }
666    }
667
668    private static void CollectParentResources(ICollection<Resource> resources, Resource resource) {
669      if (resource == null) return;
670      resources.Add(resource);
671      CollectParentResources(resources, resource.ParentResource);
672    }
673
674    /// <summary>
675    /// Returns all child resources of a resource (without the given resource)
676    /// </summary>
677    public IEnumerable<DT.Resource> GetChildResources(Guid resourceId) {
678      using (var db = CreateContext()) {
679        return CollectChildResources(resourceId, db);
680      }
681    }
682
683    public IEnumerable<DT.Resource> CollectChildResources(Guid resourceId, HiveDataContext db) {
684      var childs = new List<DT.Resource>();
685      foreach (var child in db.Resources.Where(x => x.ParentResourceId == resourceId)) {
686        childs.Add(DT.Convert.ToDto(child));
687        childs.AddRange(CollectChildResources(child.ResourceId, db));
688      }
689      return childs;
690    }
691
692    public IEnumerable<DT.Task> GetJobsByResourceId(Guid resourceId) {
693      using (var db = CreateContext()) {
694        var resources = GetChildResources(resourceId).Select(x => x.Id).ToList();
695        resources.Add(resourceId);
696
697        var jobs = db.Tasks.Where(j =>
698          j.State == TaskState.Calculating &&
699          j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.HasValue &&
700          resources.Contains(j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.Value));
701        return jobs.Select(j => DT.Convert.ToDto(j)).ToArray();
702      }
703    }
704    #endregion
705
706    #region ResourcePermission Methods
707    public DT.ResourcePermission GetResourcePermission(Guid resourceId, Guid grantedUserId) {
708      using (var db = CreateContext()) {
709        return DT.Convert.ToDto(db.ResourcePermissions.SingleOrDefault(x => x.ResourceId == resourceId && x.GrantedUserId == grantedUserId));
710      }
711    }
712
713    public IEnumerable<DT.ResourcePermission> GetResourcePermissions(Expression<Func<ResourcePermission, bool>> predicate) {
714      using (var db = CreateContext()) {
715        return db.ResourcePermissions.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
716      }
717    }
718
719    public void AddResourcePermission(DT.ResourcePermission dto) {
720      using (var db = CreateContext()) {
721        var entity = db.ResourcePermissions.SingleOrDefault(x => x.ResourceId == dto.ResourceId && x.GrantedUserId == dto.GrantedUserId);
722        if (entity == null) { db.ResourcePermissions.InsertOnSubmit(DT.Convert.ToEntity(dto)); db.SubmitChanges(); }
723      }
724    }
725
726    public void UpdateResourcePermission(DT.ResourcePermission dto) {
727      using (var db = CreateContext()) {
728        var entity = db.ResourcePermissions.FirstOrDefault(x => x.ResourceId == dto.ResourceId && x.GrantedUserId == dto.GrantedUserId);
729        if (entity == null) db.ResourcePermissions.InsertOnSubmit(DT.Convert.ToEntity(dto));
730        else DT.Convert.ToEntity(dto, entity);
731        db.SubmitChanges();
732      }
733    }
734
735    public void DeleteResourcePermission(Guid resourceId, Guid grantedUserId) {
736      using (var db = CreateContext()) {
737        var entity = db.ResourcePermissions.FirstOrDefault(x => x.ResourceId == resourceId && x.GrantedUserId == grantedUserId);
738        if (entity != null) db.ResourcePermissions.DeleteOnSubmit(entity);
739        db.SubmitChanges();
740      }
741    }
742    #endregion
743
744    #region Authorization Methods
745    public Permission GetPermissionForTask(Guid taskId, Guid userId) {
746      using (var db = CreateContext()) {
747        return GetPermissionForJob(GetJobForTask(taskId), userId);
748      }
749    }
750
751    public Permission GetPermissionForJob(Guid jobId, Guid userId) {
752      using (var db = CreateContext()) {
753        Job job = db.Jobs.SingleOrDefault(x => x.JobId == jobId);
754        if (job == null) return Permission.NotAllowed;
755        if (job.OwnerUserId == userId) return Permission.Full;
756        JobPermission permission = db.JobPermissions.SingleOrDefault(p => p.JobId == jobId && p.GrantedUserId == userId);
757        return permission != null ? permission.Permission : Permission.NotAllowed;
758      }
759    }
760
761    public Guid GetJobForTask(Guid taskId) {
762      using (var db = CreateContext()) {
763        return db.Tasks.Single(j => j.TaskId == taskId).JobId;
764      }
765    }
766    #endregion
767
768    #region Lifecycle Methods
769    public DateTime GetLastCleanup() {
770      using (var db = CreateContext()) {
771        var entity = db.Lifecycles.SingleOrDefault();
772        return entity != null ? entity.LastCleanup : DateTime.MinValue;
773      }
774    }
775
776    public void SetLastCleanup(DateTime datetime) {
777      using (var db = CreateContext()) {
778        var entity = db.Lifecycles.SingleOrDefault();
779        if (entity != null) {
780          entity.LastCleanup = datetime;
781        } else {
782          entity = new Lifecycle();
783          entity.LifecycleId = 0; // always only one entry with ID:0
784          entity.LastCleanup = datetime;
785          db.Lifecycles.InsertOnSubmit(entity);
786        }
787        db.SubmitChanges();
788      }
789    }
790    #endregion
791
792    #region Downtime Methods
793    public DT.Downtime GetDowntime(Guid id) {
794      using (var db = CreateContext()) {
795        return DT.Convert.ToDto(db.Downtimes.SingleOrDefault(x => x.DowntimeId == id));
796      }
797    }
798
799    public IEnumerable<DT.Downtime> GetDowntimes(Expression<Func<Downtime, bool>> predicate) {
800      using (var db = CreateContext()) {
801        return db.Downtimes.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
802      }
803    }
804
805    public Guid AddDowntime(DT.Downtime dto) {
806      using (var db = CreateContext()) {
807        var entity = DT.Convert.ToEntity(dto);
808        db.Downtimes.InsertOnSubmit(entity);
809        db.SubmitChanges();
810        return entity.DowntimeId;
811      }
812    }
813
814    public void UpdateDowntime(DT.Downtime dto) {
815      using (var db = CreateContext()) {
816        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == dto.Id);
817        if (entity == null) db.Downtimes.InsertOnSubmit(DT.Convert.ToEntity(dto));
818        else DT.Convert.ToEntity(dto, entity);
819        db.SubmitChanges();
820      }
821    }
822
823    public void DeleteDowntime(Guid id) {
824      using (var db = CreateContext()) {
825        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == id);
826        if (entity != null) db.Downtimes.DeleteOnSubmit(entity);
827        db.SubmitChanges();
828      }
829    }
830    #endregion
831
832    #region Statistics Methods
833    public DT.Statistics GetStatistic(Guid id) {
834      using (var db = CreateContext()) {
835        return DT.Convert.ToDto(db.Statistics.SingleOrDefault(x => x.StatisticsId == id));
836      }
837    }
838
839    public IEnumerable<DT.Statistics> GetStatistics(Expression<Func<Statistics, bool>> predicate) {
840      using (var db = CreateContext()) {
841        return db.Statistics.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
842      }
843    }
844
845    public Guid AddStatistics(DT.Statistics dto) {
846      using (var db = CreateContext()) {
847        var entity = DT.Convert.ToEntity(dto);
848        db.Statistics.InsertOnSubmit(entity);
849        db.SubmitChanges();
850        foreach (var slaveStat in dto.SlaveStatistics) {
851          slaveStat.Id = entity.StatisticsId;
852          db.SlaveStatistics.InsertOnSubmit(DT.Convert.ToEntity(slaveStat));
853        }
854        if (dto.UserStatistics != null) {
855          foreach (var userStat in dto.UserStatistics) {
856            userStat.Id = entity.StatisticsId;
857            db.UserStatistics.InsertOnSubmit(DT.Convert.ToEntity(userStat));
858          }
859        }
860        db.SubmitChanges();
861        return entity.StatisticsId;
862      }
863    }
864
865    public void DeleteStatistics(Guid id) {
866      using (var db = CreateContext()) {
867        var entity = db.Statistics.FirstOrDefault(x => x.StatisticsId == id);
868        if (entity != null) db.Statistics.DeleteOnSubmit(entity);
869        db.SubmitChanges();
870      }
871    }
872
873    public Dictionary<Guid, int> GetWaitingTasksByUser() {
874      using (var db = CreateContext()) {
875        var waitingTasksByUser = from task in db.Tasks
876                                 where task.State == TaskState.Waiting
877                                 group task by task.Job.OwnerUserId into g
878                                 select new { UserId = g.Key, UsedCores = g.Count() };
879        return waitingTasksByUser.ToDictionary(x => x.UserId, x => x.UsedCores);
880      }
881    }
882
883    public Dictionary<Guid, int> GetWaitingTasksByUserForResources(List<Guid> resourceIds) {
884      using (var db = CreateContext()) {
885        var waitingTasksByUser = from task in db.Tasks
886                                 where task.State == TaskState.Waiting && task.AssignedResources.Any(x => resourceIds.Contains(x.ResourceId))
887                                 group task by task.Job.OwnerUserId into g
888                                 select new { UserId = g.Key, UsedCores = g.Count() };
889        return waitingTasksByUser.ToDictionary(x => x.UserId, x => x.UsedCores);
890      }
891    }
892
893    public Dictionary<Guid, int> GetCalculatingTasksByUser() {
894      using (var db = CreateContext()) {
895        var calculatingTasksByUser = from task in db.Tasks
896                                     where task.State == TaskState.Calculating
897                                     group task by task.Job.OwnerUserId into g
898                                     select new { UserId = g.Key, UsedCores = g.Count() };
899        return calculatingTasksByUser.ToDictionary(x => x.UserId, x => x.UsedCores);
900      }
901    }
902
903    public Dictionary<Guid, int> GetCalculatingTasksByUserForResources(List<Guid> resourceIds) {
904      using (var db = CreateContext()) {
905        var calculatingTasksByUser = from task in db.Tasks
906                                     where task.State == TaskState.Calculating && task.AssignedResources.Any(x => resourceIds.Contains(x.ResourceId))
907                                     group task by task.Job.OwnerUserId into g
908                                     select new { UserId = g.Key, UsedCores = g.Count() };
909        return calculatingTasksByUser.ToDictionary(x => x.UserId, x => x.UsedCores);
910      }
911    }
912
913    public List<DT.UserStatistics> GetUserStatistics() {
914      using (var db = CreateContext()) {
915        var userStats = new Dictionary<Guid, DT.UserStatistics>();
916
917        var usedCoresByUser = from job in db.Tasks
918                              where job.State == TaskState.Calculating
919                              group job by job.Job.OwnerUserId into g
920                              select new { UserId = g.Key, UsedCores = g.Count() };
921
922        foreach (var item in usedCoresByUser) {
923          if (!userStats.ContainsKey(item.UserId)) {
924            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
925          }
926          userStats[item.UserId].UsedCores += item.UsedCores;
927        }
928
929        var executionTimesByUser = from task in db.Tasks
930                                   group task by task.Job.OwnerUserId into g
931                                   select new { UserId = g.Key, ExecutionTime = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
932        foreach (var item in executionTimesByUser) {
933          if (!userStats.ContainsKey(item.UserId)) {
934            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
935          }
936          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
937        }
938
939        // execution times only of finished task - necessary to compute efficieny
940        var executionTimesFinishedJobs = from job in db.Tasks
941                                         where job.State == TaskState.Finished
942                                         group job by job.Job.OwnerUserId into g
943                                         select new { UserId = g.Key, ExecutionTimeFinishedJobs = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
944
945        foreach (var item in executionTimesFinishedJobs) {
946          if (!userStats.ContainsKey(item.UserId)) {
947            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
948          }
949          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
950        }
951
952        // start to end times only of finished task - necessary to compute efficiency
953        var startToEndTimesFinishedJobs = from job in db.Tasks
954                                          where job.State == TaskState.Finished
955                                          group job by job.Job.OwnerUserId into g
956                                          select new {
957                                            UserId = g.Key,
958                                            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))
959                                          };
960        foreach (var item in startToEndTimesFinishedJobs) {
961          if (!userStats.ContainsKey(item.UserId)) {
962            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
963          }
964          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
965        }
966
967        // also consider executiontimes of DeletedJobStats
968        var deletedJobsExecutionTimesByUsers = from del in db.DeletedJobStatistics
969                                               group del by del.UserId into g
970                                               select new {
971                                                 UserId = g.Key,
972                                                 ExecutionTime = TimeSpan.FromSeconds(g.Select(x => x.ExecutionTimeS).Sum()),
973                                                 ExecutionTimeFinishedJobs = TimeSpan.FromSeconds(g.Select(x => x.ExecutionTimeSFinishedJobs).Sum()),
974                                                 StartToEndTime = TimeSpan.FromSeconds(g.Select(x => x.StartToEndTimeS).Sum())
975                                               };
976        foreach (var item in deletedJobsExecutionTimesByUsers) {
977          if (!userStats.ContainsKey(item.UserId)) {
978            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
979          }
980          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
981          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
982          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
983        }
984
985        return userStats.Values.ToList();
986      }
987    }
988    #endregion
989
990    #region UserPriority Methods
991    public IEnumerable<DT.UserPriority> GetUserPriorities(Expression<Func<UserPriority, bool>> predicate) {
992      using (var db = CreateContext()) {
993        return db.UserPriorities.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
994      }
995    }
996
997    public void EnqueueUserPriority(DT.UserPriority dto) {
998      using (var db = CreateContext()) {
999        var entity = db.UserPriorities.FirstOrDefault(x => x.UserId == dto.Id);
1000        if (entity == null) db.UserPriorities.InsertOnSubmit(DT.Convert.ToEntity(dto));
1001        else DT.Convert.ToEntity(dto, entity);
1002        db.SubmitChanges();
1003      }
1004    }
1005    #endregion
1006
1007    #region Helpers
1008    private void CollectChildTasks(HiveDataContext db, Guid parentTaskId, List<Task> collection) {
1009      var tasks = db.Tasks.Where(j => j.ParentTaskId == parentTaskId);
1010      foreach (var task in tasks) {
1011        collection.Add(task);
1012        if (task.IsParentTask)
1013          CollectChildTasks(db, task.TaskId, collection);
1014      }
1015    }
1016    #endregion
1017  }
1018}
Note: See TracBrowser for help on using the repository browser.