Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/HiveDao.cs @ 6426

Last change on this file since 6426 was 6419, checked in by cneumuel, 13 years ago

#1233

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