Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs @ 6756

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

#1233 adapted Administrator UI to be more like OKB

File size: 32.9 KB
RevLine 
[5156]1#region License Information
2/* HeuristicLab
[6367]3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[5156]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;
[4598]23using System.Collections.Generic;
24using System.Linq;
25using System.Linq.Expressions;
[6717]26using DT = HeuristicLab.Services.Hive.DataTransfer;
[4598]27
28namespace HeuristicLab.Services.Hive.DataAccess {
29  public class HiveDao : IHiveDao {
[6419]30    public static HiveDataContext CreateContext(bool longRunning = false) {
31      var context = new HiveDataContext(Settings.Default.HeuristicLab_Hive_LinqConnectionString);
[6457]32      if (longRunning) context.CommandTimeout = (int)Settings.Default.LongRunningDatabaseCommandTimeout.TotalSeconds;
[6419]33      return context;
[4649]34    }
[4598]35
[5786]36    public HiveDao() { }
[4598]37
[6743]38    #region Task Methods
39    public DT.Task GetTask(Guid id) {
[4649]40      using (var db = CreateContext()) {
[6721]41        return DT.Convert.ToDto(db.Tasks.SingleOrDefault(x => x.TaskId == id));
[4649]42      }
[4598]43    }
44
[6743]45    public IEnumerable<DT.Task> GetTasks(Expression<Func<Task, bool>> predicate) {
[4649]46      using (var db = CreateContext()) {
[6721]47        return db.Tasks.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[4649]48      }
[4598]49    }
50
[6743]51    public Guid AddTask(DT.Task dto) {
[4649]52      using (var db = CreateContext()) {
[6717]53        var entity = DT.Convert.ToEntity(dto);
[6721]54        db.Tasks.InsertOnSubmit(entity);
[4649]55        db.SubmitChanges();
[5402]56        foreach (Guid pluginId in dto.PluginsNeededIds) {
[6721]57          db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
[5402]58        }
59        db.SubmitChanges();
[6721]60        return entity.TaskId;
[4649]61      }
[4598]62    }
63
[6743]64    public void UpdateTask(DT.Task dto) {
[4649]65      using (var db = CreateContext()) {
[6721]66        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
67        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
[6717]68        else DT.Convert.ToEntity(dto, entity);
[6367]69        foreach (Guid pluginId in dto.PluginsNeededIds) {
70          if (db.RequiredPlugins.Count(p => p.PluginId == pluginId) == 0) {
[6721]71            db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
[6419]72          }
[6367]73        }
[4649]74        db.SubmitChanges();
75      }
[4598]76    }
77
[6743]78    public void DeleteTask(Guid id) {
[4649]79      using (var db = CreateContext()) {
[6721]80        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == id);
81        if (entity != null) db.Tasks.DeleteOnSubmit(entity);
[6743]82        db.SubmitChanges(); // taskData and child tasks are deleted by db-trigger
[4649]83      }
[4598]84    }
[4615]85
[5526]86    /// <summary>
[6743]87    /// returns all parent tasks which are waiting for their child tasks to finish
[5526]88    /// </summary>
[6743]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>
[5526]92    /// <returns></returns>
[6743]93    public IEnumerable<DT.Task> GetParentTasks(IEnumerable<Guid> resourceIds, int count, bool finished) {
[4649]94      using (var db = CreateContext()) {
95        var query = from ar in db.AssignedResources
[5404]96                    where resourceIds.Contains(ar.ResourceId)
[6721]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)
[6743]105                       && (from child in db.Tasks // avoid returning WaitForChildTasks task where no child-task exist (yet)
[6721]106                           where child.ParentTaskId == ar.Task.TaskId
[5404]107                           select child).Count() > 0
[6721]108                    orderby ar.Task.Priority descending, db.Random()
109                    select DT.Convert.ToDto(ar.Task);
[5404]110        return count == 0 ? query.ToArray() : query.Take(count).ToArray();
[4649]111      }
[4615]112    }
[4629]113
[6743]114    public IEnumerable<DT.Task> GetWaitingTasks(DT.Slave slave, int count) {
[4649]115      using (var db = CreateContext()) {
[5404]116        var resourceIds = GetParentResources(slave.Id).Select(r => r.Id);
[6743]117        var waitingParentJobs = GetParentTasks(resourceIds, count, false);
[5404]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)
[6721]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
[6743]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)
[6721]127                    select DT.Convert.ToDto(ar.Task);
[6743]128        var waitingTasks = (count == 0 ? query : query.Take(count)).ToArray();
129        return waitingTasks.Union(waitingParentJobs).OrderByDescending(x => x.Priority);
[4649]130      }
[4629]131    }
[5636]132
[6743]133    public DT.Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
[5636]134      using (var db = CreateContext()) {
[6743]135        var job = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
136        job.State = taskState;
[5636]137        db.StateLogs.InsertOnSubmit(new StateLog {
[6743]138          TaskId = taskId,
139          State = taskState,
[5636]140          SlaveId = slaveId,
141          UserId = userId,
142          Exception = exception,
143          DateTime = DateTime.Now
144        });
145        db.SubmitChanges();
[6743]146        job = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
[6717]147        return DT.Convert.ToDto(job);
[5636]148      }
149    }
[4598]150    #endregion
151
[6725]152    #region TaskData Methods
[6743]153    public DT.TaskData GetTaskData(Guid id) {
[6419]154      using (var db = CreateContext(true)) {
[6721]155        return DT.Convert.ToDto(db.TaskDatas.SingleOrDefault(x => x.TaskId == id));
[4649]156      }
[4598]157    }
158
[6743]159    public IEnumerable<DT.TaskData> GetTaskDatas(Expression<Func<TaskData, bool>> predicate) {
[6419]160      using (var db = CreateContext(true)) {
[6721]161        return db.TaskDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[4649]162      }
[4598]163    }
164
[6743]165    public Guid AddTaskData(DT.TaskData dto) {
[6419]166      using (var db = CreateContext(true)) {
[6717]167        var entity = DT.Convert.ToEntity(dto);
[6721]168        db.TaskDatas.InsertOnSubmit(entity);
[4649]169        db.SubmitChanges();
[6721]170        return entity.TaskId;
[4649]171      }
[4598]172    }
173
[6743]174    public void UpdateTaskData(DT.TaskData dto) {
[6419]175      using (var db = CreateContext(true)) {
[6721]176        var entity = db.TaskDatas.FirstOrDefault(x => x.TaskId == dto.TaskId);
177        if (entity == null) db.TaskDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
[6717]178        else DT.Convert.ToEntity(dto, entity);
[4649]179        db.SubmitChanges();
180      }
[4598]181    }
182
[6743]183    public void DeleteTaskData(Guid id) {
[4649]184      using (var db = CreateContext()) {
[6721]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);
[4649]187        db.SubmitChanges();
188      }
[4598]189    }
190    #endregion
191
[5526]192    #region StateLog Methods
193    public DT.StateLog GetStateLog(Guid id) {
194      using (var db = CreateContext()) {
[6717]195        return DT.Convert.ToDto(db.StateLogs.SingleOrDefault(x => x.StateLogId == id));
[5526]196      }
197    }
198
199    public IEnumerable<DT.StateLog> GetStateLogs(Expression<Func<StateLog, bool>> predicate) {
200      using (var db = CreateContext()) {
[6717]201        return db.StateLogs.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[5526]202      }
203    }
204
205    public Guid AddStateLog(DT.StateLog dto) {
206      using (var db = CreateContext()) {
[6717]207        var entity = DT.Convert.ToEntity(dto);
[5526]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);
[6717]217        if (entity == null) db.StateLogs.InsertOnSubmit(DT.Convert.ToEntity(dto));
218        else DT.Convert.ToEntity(dto, entity);
[5526]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
[6725]232    #region Job Methods
[6743]233    public DT.Job GetJob(Guid id) {
[4649]234      using (var db = CreateContext()) {
[6756]235        return AddStatsToJob(db, DT.Convert.ToDto(db.Jobs.SingleOrDefault(x => x.JobId == id)));
[4649]236      }
[4598]237    }
238
[6756]239    private DT.Job AddStatsToJob(HiveDataContext db, DT.Job exp) {
[6006]240      if (exp == null)
241        return null;
242
[6723]243      var jobs = db.Tasks.Where(j => j.JobId == exp.Id);
[6006]244      exp.JobCount = jobs.Count();
[6721]245      exp.CalculatingCount = jobs.Count(j => j.State == TaskState.Calculating);
246      exp.FinishedCount = jobs.Count(j => j.State == TaskState.Finished);
[5955]247      return exp;
248    }
249
[6743]250    public IEnumerable<DT.Job> GetJobs(Expression<Func<Job, bool>> predicate) {
[4649]251      using (var db = CreateContext()) {
[6756]252        return db.Jobs.Where(predicate).Select(x => AddStatsToJob(db, DT.Convert.ToDto(x))).ToArray();
[4649]253      }
[4598]254    }
255
[6743]256    public Guid AddJob(DT.Job dto) {
[4649]257      using (var db = CreateContext()) {
[6717]258        var entity = DT.Convert.ToEntity(dto);
[6723]259        db.Jobs.InsertOnSubmit(entity);
[4649]260        db.SubmitChanges();
[6723]261        return entity.JobId;
[4649]262      }
[4598]263    }
264
[6743]265    public void UpdateJob(DT.Job dto) {
[4649]266      using (var db = CreateContext()) {
[6723]267        var entity = db.Jobs.FirstOrDefault(x => x.JobId == dto.Id);
268        if (entity == null) db.Jobs.InsertOnSubmit(DT.Convert.ToEntity(dto));
[6717]269        else DT.Convert.ToEntity(dto, entity);
[4649]270        db.SubmitChanges();
271      }
[4598]272    }
273
[6743]274    public void DeleteJob(Guid id) {
[4649]275      using (var db = CreateContext()) {
[6723]276        var entity = db.Jobs.FirstOrDefault(x => x.JobId == id);
277        if (entity != null) db.Jobs.DeleteOnSubmit(entity);
[4649]278        db.SubmitChanges();
279      }
[4598]280    }
281    #endregion
282
[6723]283    #region JobPermission Methods
[6743]284    public DT.JobPermission GetJobPermission(Guid jobId, Guid grantedUserId) {
[5511]285      using (var db = CreateContext()) {
[6743]286        return DT.Convert.ToDto(db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId));
[5511]287      }
288    }
289
[6743]290    public IEnumerable<DT.JobPermission> GetJobPermissions(Expression<Func<JobPermission, bool>> predicate) {
[5511]291      using (var db = CreateContext()) {
[6723]292        return db.JobPermissions.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[5511]293      }
294    }
295
[6743]296    public void AddJobPermission(DT.JobPermission dto) {
[5511]297      using (var db = CreateContext()) {
[6717]298        var entity = DT.Convert.ToEntity(dto);
[6723]299        db.JobPermissions.InsertOnSubmit(entity);
[5511]300        db.SubmitChanges();
301      }
302    }
303
[6743]304    public void UpdateJobPermission(DT.JobPermission dto) {
[5511]305      using (var db = CreateContext()) {
[6723]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));
[6717]308        else DT.Convert.ToEntity(dto, entity);
[5511]309        db.SubmitChanges();
310      }
311    }
312
[6743]313    public void DeleteJobPermission(Guid jobId, Guid grantedUserId) {
[5511]314      using (var db = CreateContext()) {
[6743]315        var entity = db.JobPermissions.FirstOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
[6723]316        if (entity != null) db.JobPermissions.DeleteOnSubmit(entity);
[5511]317        db.SubmitChanges();
318      }
319    }
[6457]320
321    /// <summary>
322    /// Sets the permissions for a experiment. makes sure that only one permission per user exists.
323    /// </summary>
[6743]324    public void SetJobPermission(Guid jobId, Guid grantedByUserId, Guid grantedUserId, Permission permission) {
[6457]325      using (var db = CreateContext()) {
[6743]326        JobPermission jobPermission = db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
327        if (jobPermission != null) {
[6457]328          if (permission == Permission.NotAllowed) {
329            // not allowed, delete
[6743]330            db.JobPermissions.DeleteOnSubmit(jobPermission);
[6457]331          } else {
332            // update
[6743]333            jobPermission.Permission = permission;
334            jobPermission.GrantedByUserId = grantedByUserId; // update grantedByUserId, always the last "granter" is stored
[6457]335          }
336        } else {
337          // insert
338          if (permission != Permission.NotAllowed) {
[6743]339            jobPermission = new JobPermission() { JobId = jobId, GrantedByUserId = grantedByUserId, GrantedUserId = grantedUserId, Permission = permission };
340            db.JobPermissions.InsertOnSubmit(jobPermission);
[6457]341          }
342        }
343        db.SubmitChanges();
344      }
345    }
[5511]346    #endregion
347
[4905]348    #region Plugin Methods
349    public DT.Plugin GetPlugin(Guid id) {
350      using (var db = CreateContext()) {
[6717]351        return DT.Convert.ToDto(db.Plugins.SingleOrDefault(x => x.PluginId == id));
[4905]352      }
353    }
354
355    public IEnumerable<DT.Plugin> GetPlugins(Expression<Func<Plugin, bool>> predicate) {
356      using (var db = CreateContext()) {
[6717]357        return db.Plugins.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[4905]358      }
359    }
360
361    public Guid AddPlugin(DT.Plugin dto) {
362      using (var db = CreateContext()) {
[6717]363        var entity = DT.Convert.ToEntity(dto);
[4905]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);
[6717]373        if (entity == null) db.Plugins.InsertOnSubmit(DT.Convert.ToEntity(dto));
374        else DT.Convert.ToEntity(dto, entity);
[4905]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()) {
[6717]391        return DT.Convert.ToDto(db.PluginDatas.SingleOrDefault(x => x.PluginDataId == id));
[4905]392      }
393    }
394
395    public IEnumerable<DT.PluginData> GetPluginDatas(Expression<Func<PluginData, bool>> predicate) {
396      using (var db = CreateContext()) {
[6717]397        return db.PluginDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[4905]398      }
399    }
400
401    public Guid AddPluginData(DT.PluginData dto) {
402      using (var db = CreateContext()) {
[6717]403        var entity = DT.Convert.ToEntity(dto);
[4905]404        db.PluginDatas.InsertOnSubmit(entity);
405        db.SubmitChanges();
[5402]406        return entity.PluginDataId;
[4905]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);
[6717]413        if (entity == null) db.PluginDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
414        else DT.Convert.ToEntity(dto, entity);
[4905]415        db.SubmitChanges();
416      }
417    }
418
419    public void DeletePluginData(Guid id) {
420      using (var db = CreateContext()) {
[6369]421        var entity = db.PluginDatas.FirstOrDefault(x => x.PluginDataId == id);
[4905]422        if (entity != null) db.PluginDatas.DeleteOnSubmit(entity);
423        db.SubmitChanges();
424      }
425    }
426    #endregion
427
[4598]428    #region Slave Methods
429    public DT.Slave GetSlave(Guid id) {
[4649]430      using (var db = CreateContext()) {
[6717]431        return DT.Convert.ToDto(db.Resources.OfType<Slave>().SingleOrDefault(x => x.ResourceId == id));
[4649]432      }
[4598]433    }
434
435    public IEnumerable<DT.Slave> GetSlaves(Expression<Func<Slave, bool>> predicate) {
[4649]436      using (var db = CreateContext()) {
[6717]437        return db.Resources.OfType<Slave>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[4649]438      }
[4598]439    }
440
441    public Guid AddSlave(DT.Slave dto) {
[4649]442      using (var db = CreateContext()) {
[6717]443        var entity = DT.Convert.ToEntity(dto);
[4649]444        db.Resources.InsertOnSubmit(entity);
445        db.SubmitChanges();
446        return entity.ResourceId;
447      }
[4598]448    }
449
450    public void UpdateSlave(DT.Slave dto) {
[4649]451      using (var db = CreateContext()) {
452        var entity = db.Resources.OfType<Slave>().FirstOrDefault(x => x.ResourceId == dto.Id);
[6717]453        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
454        else DT.Convert.ToEntity(dto, entity);
[4649]455        db.SubmitChanges();
456      }
[4598]457    }
458
459    public void DeleteSlave(Guid id) {
[4649]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      }
[4598]465    }
466    #endregion
467
468    #region SlaveGroup Methods
469    public DT.SlaveGroup GetSlaveGroup(Guid id) {
[4649]470      using (var db = CreateContext()) {
[6717]471        return DT.Convert.ToDto(db.Resources.OfType<SlaveGroup>().SingleOrDefault(x => x.ResourceId == id));
[4649]472      }
[4598]473    }
474
475    public IEnumerable<DT.SlaveGroup> GetSlaveGroups(Expression<Func<SlaveGroup, bool>> predicate) {
[4649]476      using (var db = CreateContext()) {
[6717]477        return db.Resources.OfType<SlaveGroup>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[4649]478      }
[4598]479    }
480
481    public Guid AddSlaveGroup(DT.SlaveGroup dto) {
[4649]482      using (var db = CreateContext()) {
[5375]483        if (dto.Id == Guid.Empty)
484          dto.Id = Guid.NewGuid();
[6717]485        var entity = DT.Convert.ToEntity(dto);
[4649]486        db.Resources.InsertOnSubmit(entity);
487        db.SubmitChanges();
488        return entity.ResourceId;
489      }
[4598]490    }
491
492    public void UpdateSlaveGroup(DT.SlaveGroup dto) {
[4649]493      using (var db = CreateContext()) {
494        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == dto.Id);
[6717]495        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
496        else DT.Convert.ToEntity(dto, entity);
[4649]497        db.SubmitChanges();
498      }
[4598]499    }
500
501    public void DeleteSlaveGroup(Guid id) {
[4649]502      using (var db = CreateContext()) {
503        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == id);
[5404]504        if (entity != null) {
505          if (db.Resources.Where(r => r.ParentResourceId == id).Count() > 0) {
[6431]506            throw new InvalidOperationException("Cannot delete SlaveGroup as long as there are Slaves in the group");
[5404]507          }
508          db.Resources.DeleteOnSubmit(entity);
509        }
[4649]510        db.SubmitChanges();
511      }
[4598]512    }
513    #endregion
514
515    #region Resource Methods
516    public DT.Resource GetResource(Guid id) {
[4649]517      using (var db = CreateContext()) {
[6717]518        return DT.Convert.ToDto(db.Resources.SingleOrDefault(x => x.ResourceId == id));
[4649]519      }
[4598]520    }
521
522    public IEnumerable<DT.Resource> GetResources(Expression<Func<Resource, bool>> predicate) {
[4649]523      using (var db = CreateContext()) {
[6717]524        return db.Resources.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[4649]525      }
[4598]526    }
527
528    public Guid AddResource(DT.Resource dto) {
[4649]529      using (var db = CreateContext()) {
[6717]530        var entity = DT.Convert.ToEntity(dto);
[4649]531        db.Resources.InsertOnSubmit(entity);
532        db.SubmitChanges();
533        return entity.ResourceId;
534      }
[4598]535    }
536
537    public void UpdateResource(DT.Resource dto) {
[4649]538      using (var db = CreateContext()) {
539        var entity = db.Resources.FirstOrDefault(x => x.ResourceId == dto.Id);
[6717]540        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
541        else DT.Convert.ToEntity(dto, entity);
[4649]542        db.SubmitChanges();
543      }
[4598]544    }
545
546    public void DeleteResource(Guid id) {
[4649]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      }
[4598]552    }
[5155]553
554    public void AssignJobToResource(Guid jobId, Guid resourceId) {
555      using (var db = CreateContext()) {
[6721]556        var job = db.Tasks.Where(x => x.TaskId == jobId).Single();
557        job.AssignedResources.Add(new AssignedResource() { TaskId = jobId, ResourceId = resourceId });
[5155]558        db.SubmitChanges();
559      }
560    }
561
562    public IEnumerable<DT.Resource> GetAssignedResources(Guid jobId) {
563      using (var db = CreateContext()) {
[6721]564        var job = db.Tasks.Where(x => x.TaskId == jobId).Single();
[6717]565        return job.AssignedResources.Select(x => DT.Convert.ToDto(x.Resource)).ToArray();
[5155]566      }
567    }
[5404]568
569    /// <summary>
570    /// Returns all parent resources of a resource (the given resource is also added)
571    /// </summary>
[6110]572    public IEnumerable<DT.Resource> GetParentResources(Guid resourceId) {
[5404]573      using (var db = CreateContext()) {
574        var resources = new List<Resource>();
575        CollectParentResources(resources, db.Resources.Where(r => r.ResourceId == resourceId).Single());
[6717]576        return resources.Select(r => DT.Convert.ToDto(r)).ToArray();
[5404]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    }
[6267]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)) {
[6717]593          childs.Add(DT.Convert.ToDto(child));
[6267]594          childs.AddRange(GetChildResources(child.ResourceId));
595        }
596        return childs;
597      }
598    }
599
[6721]600    public IEnumerable<DT.Task> GetJobsByResourceId(Guid resourceId) {
[6267]601      using (var db = CreateContext()) {
602        var resources = GetChildResources(resourceId).Select(x => x.Id).ToList();
603        resources.Add(resourceId);
604
[6721]605        var jobs = db.Tasks.Where(j =>
606          j.State == TaskState.Calculating &&
[6267]607          j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.HasValue &&
608          resources.Contains(j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.Value));
[6717]609        return jobs.Select(j => DT.Convert.ToDto(j)).ToArray();
[6267]610      }
611    }
[4598]612    #endregion
613
614    #region Authorization Methods
[6743]615    public Permission GetPermissionForTask(Guid taskId, Guid userId) {
[4649]616      using (var db = CreateContext()) {
[6743]617        return GetPermissionForJob(GetJobForTask(taskId), userId);
[4649]618      }
[4598]619    }
[5511]620
[6743]621    public Permission GetPermissionForJob(Guid jobId, Guid userId) {
[5511]622      using (var db = CreateContext()) {
[6743]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);
[5511]627        return permission != null ? permission.Permission : Permission.NotAllowed;
628      }
629    }
630
[6743]631    public Guid GetJobForTask(Guid taskId) {
[5511]632      using (var db = CreateContext()) {
[6743]633        return db.Tasks.Single(j => j.TaskId == taskId).JobId;
[5511]634      }
635    }
[4598]636    #endregion
[5526]637
[5593]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
[5633]661
[6452]662    #region Downtime Methods
663    public DT.Downtime GetDowntime(Guid id) {
[5633]664      using (var db = CreateContext()) {
[6717]665        return DT.Convert.ToDto(db.Downtimes.SingleOrDefault(x => x.DowntimeId == id));
[5633]666      }
667    }
668
[6452]669    public IEnumerable<DT.Downtime> GetDowntimes(Expression<Func<Downtime, bool>> predicate) {
[5633]670      using (var db = CreateContext()) {
[6717]671        return db.Downtimes.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[5633]672      }
673    }
674
[6452]675    public Guid AddDowntime(DT.Downtime dto) {
[5633]676      using (var db = CreateContext()) {
[6717]677        var entity = DT.Convert.ToEntity(dto);
[6452]678        db.Downtimes.InsertOnSubmit(entity);
[5633]679        db.SubmitChanges();
[6452]680        return entity.DowntimeId;
[5633]681      }
682    }
683
[6452]684    public void UpdateDowntime(DT.Downtime dto) {
[5633]685      using (var db = CreateContext()) {
[6452]686        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == dto.Id);
[6717]687        if (entity == null) db.Downtimes.InsertOnSubmit(DT.Convert.ToEntity(dto));
688        else DT.Convert.ToEntity(dto, entity);
[5633]689        db.SubmitChanges();
690      }
691    }
692
[6452]693    public void DeleteDowntime(Guid id) {
[5633]694      using (var db = CreateContext()) {
[6452]695        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == id);
696        if (entity != null) db.Downtimes.DeleteOnSubmit(entity);
[5633]697        db.SubmitChanges();
698      }
699    }
700    #endregion
[5955]701
[6229]702    #region Statistics Methods
703    public DT.Statistics GetStatistic(Guid id) {
704      using (var db = CreateContext()) {
[6717]705        return DT.Convert.ToDto(db.Statistics.SingleOrDefault(x => x.StatisticsId == id));
[6229]706      }
707    }
708
709    public IEnumerable<DT.Statistics> GetStatistics(Expression<Func<Statistics, bool>> predicate) {
710      using (var db = CreateContext()) {
[6717]711        return db.Statistics.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
[6229]712      }
713    }
714
715    public Guid AddStatistics(DT.Statistics dto) {
716      using (var db = CreateContext()) {
[6717]717        var entity = DT.Convert.ToEntity(dto);
[6229]718        db.Statistics.InsertOnSubmit(entity);
719        db.SubmitChanges();
720        foreach (var slaveStat in dto.SlaveStatistics) {
721          slaveStat.Id = entity.StatisticsId;
[6717]722          db.SlaveStatistics.InsertOnSubmit(DT.Convert.ToEntity(slaveStat));
[6229]723        }
724        foreach (var userStat in dto.UserStatistics) {
725          userStat.Id = entity.StatisticsId;
[6717]726          db.UserStatistics.InsertOnSubmit(DT.Convert.ToEntity(userStat));
[6229]727        }
728        db.SubmitChanges();
729        return entity.StatisticsId;
730      }
731    }
732
733    public void DeleteStatistics(Guid id) {
734      using (var db = CreateContext()) {
735        var entity = db.Statistics.FirstOrDefault(x => x.StatisticsId == id);
736        if (entity != null) db.Statistics.DeleteOnSubmit(entity);
737        db.SubmitChanges();
738      }
739    }
740
741    public List<DT.UserStatistics> GetUserStatistics() {
742      using (var db = CreateContext()) {
[6267]743        var userStats = new Dictionary<Guid, DT.UserStatistics>();
744
[6721]745        var usedCoresByUser = from job in db.Tasks
746                              where job.State == TaskState.Calculating
[6723]747                              group job by job.Job.OwnerUserId into g
[6267]748                              select new { UserId = g.Key, UsedCores = g.Count() };
749
750        foreach (var item in usedCoresByUser) {
751          if (!userStats.ContainsKey(item.UserId)) {
752            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
753          }
754          userStats[item.UserId].UsedCores += item.UsedCores;
755        }
756
[6721]757        var executionTimesByUser = from job in db.Tasks
[6723]758                                   group job by job.Job.OwnerUserId into g
[6267]759                                   select new { UserId = g.Key, ExecutionTime = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
[6229]760        foreach (var item in executionTimesByUser) {
[6267]761          if (!userStats.ContainsKey(item.UserId)) {
762            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
763          }
764          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
[6229]765        }
766
[6743]767        // execution times only of finished task - necessary to compute efficieny
[6721]768        var executionTimesFinishedJobs = from job in db.Tasks
769                                         where job.State == TaskState.Finished
[6723]770                                         group job by job.Job.OwnerUserId into g
[6267]771                                         select new { UserId = g.Key, ExecutionTimeFinishedJobs = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
[6229]772
[6267]773        foreach (var item in executionTimesFinishedJobs) {
774          if (!userStats.ContainsKey(item.UserId)) {
775            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
776          }
777          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
778        }
779
[6743]780        // start to end times only of finished task - necessary to compute efficiency
[6721]781        var startToEndTimesFinishedJobs = from job in db.Tasks
782                                          where job.State == TaskState.Finished
[6723]783                                          group job by job.Job.OwnerUserId into g
[6267]784                                          select new {
785                                            UserId = g.Key,
[6431]786                                            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))
[6267]787                                          };
788        foreach (var item in startToEndTimesFinishedJobs) {
789          if (!userStats.ContainsKey(item.UserId)) {
790            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
791          }
792          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
793        }
794
795        // also consider executiontimes of DeletedJobStats
796        var deletedJobsExecutionTimesByUsers = from del in db.DeletedJobStatistics
797                                               group del by del.UserId into g
798                                               select new {
799                                                 UserId = g.Key,
800                                                 ExecutionTime = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()),
801                                                 ExecutionTimeFinishedJobs = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMsFinishedJobs).Sum()),
802                                                 StartToEndTime = TimeSpan.FromMilliseconds(g.Select(x => x.StartToEndTimeMs).Sum())
803                                               };
804        foreach (var item in deletedJobsExecutionTimesByUsers) {
805          if (!userStats.ContainsKey(item.UserId)) {
806            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
807          }
808          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
809          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
810          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
811        }
812
813        return userStats.Values.ToList();
[6229]814      }
815    }
816    #endregion
817
[5955]818    #region Helpers
[6743]819    private void CollectChildTasks(HiveDataContext db, Guid parentTaskId, List<Task> collection) {
820      var tasks = db.Tasks.Where(j => j.ParentTaskId == parentTaskId);
821      foreach (var task in tasks) {
822        collection.Add(task);
823        if (task.IsParentTask)
824          CollectChildTasks(db, task.TaskId, collection);
[5955]825      }
826    }
827    #endregion
[6267]828  }
[4598]829}
Note: See TracBrowser for help on using the repository browser.