#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace HeuristicLab.Services.Hive.DataAccess {
using HeuristicLab.Services.Hive.Common.DataTransfer;
using HeuristicLab.Services.Hive.DataAccess.Properties;
using DT = HeuristicLab.Services.Hive.Common.DataTransfer;
public class HiveDao : IHiveDao {
public static HiveDataContext CreateContext() {
return new HiveDataContext(Settings.Default.HeuristicLab_Hive_LinqConnectionString);
}
public HiveDao() {
}
#region Job Methods
public DT.Job GetJob(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.Jobs.SingleOrDefault(x => x.JobId == id));
}
}
public IEnumerable
GetJobs(Expression> predicate) {
using (var db = CreateContext()) {
return db.Jobs.Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddJob(DT.Job dto) {
using (var db = CreateContext()) {
var entity = Convert.ToEntity(dto);
db.Jobs.InsertOnSubmit(entity);
db.SubmitChanges();
foreach (Guid pluginId in dto.PluginsNeededIds) {
db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { JobId = entity.JobId, PluginId = pluginId });
}
db.SubmitChanges();
return entity.JobId;
}
}
public void UpdateJob(DT.Job dto) {
using (var db = CreateContext()) {
var entity = db.Jobs.FirstOrDefault(x => x.JobId == dto.Id);
if (entity == null) db.Jobs.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
// todo: update required plugins
db.SubmitChanges();
}
}
public void DeleteJob(Guid id) {
using (var db = CreateContext()) {
var entity = db.Jobs.FirstOrDefault(x => x.JobId == id);
if (entity != null) db.Jobs.DeleteOnSubmit(entity);
db.SubmitChanges(); // JobData and child jobs are deleted by db-trigger
}
}
public IEnumerable GetWaitingParentJobs(IEnumerable resourceIds, int count) {
using (var db = CreateContext()) {
var query = from ar in db.AssignedResources
where resourceIds.Contains(ar.ResourceId)
&& ar.Job.JobState == JobState.WaitingForChildJobs
&& (from child in db.Jobs
where child.ParentJobId == ar.Job.JobId
select child.JobState == JobState.Finished).All(x => x)
&& (from child in db.Jobs // avoid returning WaitForChildJobs jobs where no child-jobs exist (yet)
where child.ParentJobId == ar.Job.JobId
select child).Count() > 0
orderby ar.Job.Priority descending
select Convert.ToDto(ar.Job);
return count == 0 ? query.ToArray() : query.Take(count).ToArray();
}
}
public IEnumerable GetWaitingJobs(DT.Slave slave, int count) {
using (var db = CreateContext()) {
var resourceIds = GetParentResources(slave.Id).Select(r => r.Id);
var waitingParentJobs = GetWaitingParentJobs(resourceIds, count);
if (count > 0 && waitingParentJobs.Count() >= count) return waitingParentJobs.Take(count).ToArray();
var query = from ar in db.AssignedResources
where resourceIds.Contains(ar.ResourceId)
&& ar.Job.JobState == JobState.Waiting
&& ar.Job.CoresNeeded <= slave.FreeCores
&& ar.Job.MemoryNeeded <= slave.FreeMemory
orderby ar.Job.Priority descending
select Convert.ToDto(ar.Job);
var waitingJobs = (count == 0 ? query : query.Take(count)).ToArray();
return waitingJobs.Union(waitingParentJobs).OrderByDescending(x => x.Priority);
}
}
#endregion
#region JobData Methods
public DT.JobData GetJobData(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.JobDatas.SingleOrDefault(x => x.JobId == id));
}
}
public IEnumerable GetJobDatas(Expression> predicate) {
using (var db = CreateContext()) {
return db.JobDatas.Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddJobData(DT.JobData dto) {
using (var db = CreateContext()) {
var entity = Convert.ToEntity(dto);
db.JobDatas.InsertOnSubmit(entity);
db.SubmitChanges();
return entity.JobId;
}
}
public void UpdateJobData(DT.JobData dto) {
using (var db = CreateContext()) {
var entity = db.JobDatas.FirstOrDefault(x => x.JobId == dto.JobId);
if (entity == null) db.JobDatas.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
db.SubmitChanges();
}
}
public void DeleteJobData(Guid id) {
using (var db = CreateContext()) {
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
if (entity != null) db.JobDatas.DeleteOnSubmit(entity);
db.SubmitChanges();
}
}
#endregion
#region HiveExperiment Methods
public DT.HiveExperiment GetHiveExperiment(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.HiveExperiments.SingleOrDefault(x => x.HiveExperimentId == id));
}
}
public IEnumerable GetHiveExperiments(Expression> predicate) {
using (var db = CreateContext()) {
return db.HiveExperiments.Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddHiveExperiment(DT.HiveExperiment dto) {
using (var db = CreateContext()) {
var entity = Convert.ToEntity(dto);
db.HiveExperiments.InsertOnSubmit(entity);
db.SubmitChanges();
return entity.HiveExperimentId;
}
}
public void UpdateHiveExperiment(DT.HiveExperiment dto) {
using (var db = CreateContext()) {
var entity = db.HiveExperiments.FirstOrDefault(x => x.HiveExperimentId == dto.Id);
if (entity == null) db.HiveExperiments.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
db.SubmitChanges();
}
}
public void DeleteHiveExperiment(Guid id) {
using (var db = CreateContext()) {
var entity = db.HiveExperiments.FirstOrDefault(x => x.HiveExperimentId == id);
if (entity != null) db.HiveExperiments.DeleteOnSubmit(entity);
db.SubmitChanges();
}
}
#endregion
#region Plugin Methods
public DT.Plugin GetPlugin(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.Plugins.SingleOrDefault(x => x.PluginId == id));
}
}
public IEnumerable GetPlugins(Expression> predicate) {
using (var db = CreateContext()) {
return db.Plugins.Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddPlugin(DT.Plugin dto) {
using (var db = CreateContext()) {
var entity = Convert.ToEntity(dto);
db.Plugins.InsertOnSubmit(entity);
db.SubmitChanges();
return entity.PluginId;
}
}
public void UpdatePlugin(DT.Plugin dto) {
using (var db = CreateContext()) {
var entity = db.Plugins.FirstOrDefault(x => x.PluginId == dto.Id);
if (entity == null) db.Plugins.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
db.SubmitChanges();
}
}
public void DeletePlugin(Guid id) {
using (var db = CreateContext()) {
var entity = db.Plugins.FirstOrDefault(x => x.PluginId == id);
if (entity != null) db.Plugins.DeleteOnSubmit(entity);
db.SubmitChanges();
}
}
#endregion
#region PluginData Methods
public DT.PluginData GetPluginData(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.PluginDatas.SingleOrDefault(x => x.PluginDataId == id));
}
}
public IEnumerable GetPluginDatas(Expression> predicate) {
using (var db = CreateContext()) {
return db.PluginDatas.Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddPluginData(DT.PluginData dto) {
using (var db = CreateContext()) {
var entity = Convert.ToEntity(dto);
db.PluginDatas.InsertOnSubmit(entity);
db.SubmitChanges();
return entity.PluginDataId;
}
}
public void UpdatePluginData(DT.PluginData dto) {
using (var db = CreateContext()) {
var entity = db.PluginDatas.FirstOrDefault(x => x.PluginId == dto.PluginId);
if (entity == null) db.PluginDatas.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
db.SubmitChanges();
}
}
public void DeletePluginData(Guid id) {
using (var db = CreateContext()) {
var entity = db.PluginDatas.FirstOrDefault(x => x.PluginDataId == id); // todo: check if all the byte[] is loaded into memory here. otherwise work around to delete without loading it
if (entity != null) db.PluginDatas.DeleteOnSubmit(entity);
db.SubmitChanges();
}
}
#endregion
#region Slave Methods
public DT.Slave GetSlave(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.Resources.OfType().SingleOrDefault(x => x.ResourceId == id));
}
}
public IEnumerable GetSlaves(Expression> predicate) {
using (var db = CreateContext()) {
return db.Resources.OfType().Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddSlave(DT.Slave dto) {
using (var db = CreateContext()) {
var entity = Convert.ToEntity(dto);
db.Resources.InsertOnSubmit(entity);
db.SubmitChanges();
return entity.ResourceId;
}
}
public void UpdateSlave(DT.Slave dto) {
using (var db = CreateContext()) {
var entity = db.Resources.OfType().FirstOrDefault(x => x.ResourceId == dto.Id);
if (entity == null) db.Resources.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
db.SubmitChanges();
}
}
public void DeleteSlave(Guid id) {
using (var db = CreateContext()) {
var entity = db.Resources.OfType().FirstOrDefault(x => x.ResourceId == id);
if (entity != null) db.Resources.DeleteOnSubmit(entity);
db.SubmitChanges();
}
}
#endregion
#region SlaveGroup Methods
public DT.SlaveGroup GetSlaveGroup(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.Resources.OfType().SingleOrDefault(x => x.ResourceId == id));
}
}
public IEnumerable GetSlaveGroups(Expression> predicate) {
using (var db = CreateContext()) {
return db.Resources.OfType().Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddSlaveGroup(DT.SlaveGroup dto) {
using (var db = CreateContext()) {
if (dto.Id == Guid.Empty)
dto.Id = Guid.NewGuid();
var entity = Convert.ToEntity(dto);
db.Resources.InsertOnSubmit(entity);
db.SubmitChanges();
return entity.ResourceId;
}
}
public void UpdateSlaveGroup(DT.SlaveGroup dto) {
using (var db = CreateContext()) {
var entity = db.Resources.OfType().FirstOrDefault(x => x.ResourceId == dto.Id);
if (entity == null) db.Resources.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
db.SubmitChanges();
}
}
public void DeleteSlaveGroup(Guid id) {
using (var db = CreateContext()) {
var entity = db.Resources.OfType().FirstOrDefault(x => x.ResourceId == id);
if (entity != null) {
if (db.Resources.Where(r => r.ParentResourceId == id).Count() > 0) {
throw new DaoException("Cannot delete SlaveGroup as long as there are Slaves in the group");
}
db.Resources.DeleteOnSubmit(entity);
}
db.SubmitChanges();
}
}
#endregion
#region Resource Methods
public DT.Resource GetResource(Guid id) {
using (var db = CreateContext()) {
return Convert.ToDto(db.Resources.SingleOrDefault(x => x.ResourceId == id));
}
}
public IEnumerable GetResources(Expression> predicate) {
using (var db = CreateContext()) {
return db.Resources.Where(predicate).Select(x => Convert.ToDto(x)).ToArray();
}
}
public Guid AddResource(DT.Resource dto) {
using (var db = CreateContext()) {
var entity = Convert.ToEntity(dto);
db.Resources.InsertOnSubmit(entity);
db.SubmitChanges();
return entity.ResourceId;
}
}
public void UpdateResource(DT.Resource dto) {
using (var db = CreateContext()) {
var entity = db.Resources.FirstOrDefault(x => x.ResourceId == dto.Id);
if (entity == null) db.Resources.InsertOnSubmit(Convert.ToEntity(dto));
else Convert.ToEntity(dto, entity);
db.SubmitChanges();
}
}
public void DeleteResource(Guid id) {
using (var db = CreateContext()) {
var entity = db.Resources.FirstOrDefault(x => x.ResourceId == id);
if (entity != null) db.Resources.DeleteOnSubmit(entity);
db.SubmitChanges();
}
}
public void AssignJobToResource(Guid jobId, Guid resourceId) {
using (var db = CreateContext()) {
var job = db.Jobs.Where(x => x.JobId == jobId).Single();
job.AssignedResources.Add(new AssignedResource() { JobId = jobId, ResourceId = resourceId });
db.SubmitChanges();
}
}
public IEnumerable GetAssignedResources(Guid jobId) {
using (var db = CreateContext()) {
var job = db.Jobs.Where(x => x.JobId == jobId).Single();
return job.AssignedResources.Select(x => Convert.ToDto(x.Resource)).ToArray();
}
}
///
/// Returns all parent resources of a resource (the given resource is also added)
///
private IEnumerable GetParentResources(Guid resourceId) {
using (var db = CreateContext()) {
var resources = new List();
CollectParentResources(resources, db.Resources.Where(r => r.ResourceId == resourceId).Single());
return resources.Select(r => Convert.ToDto(r)).ToArray();
}
}
private void CollectParentResources(List resources, Resource resource) {
if (resource == null) return;
resources.Add(resource);
CollectParentResources(resources, resource.ParentResource);
}
#endregion
#region Authorization Methods
public bool IsUserAuthorizedForJobs(Guid userId, params Guid[] jobIds) {
using (var db = CreateContext()) {
var userIds = from job in db.Jobs // this needs to be fast!
where jobIds.Contains(job.JobId)
select job.UserId;
return userIds.All(x => x == userId);
}
}
#endregion
}
}