using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.ServiceModel;
using HeuristicLab.Services.Hive.Common;
using HeuristicLab.Services.Hive.Common.DataTransfer;
using HeuristicLab.Services.Hive.Common.ServiceContracts;
namespace HeuristicLab.Services.Hive {
///
/// Implementation of the Hive service (interface ).
/// We need 'IgnoreExtensionDataObject' Attribute for the slave to work.
///
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IgnoreExtensionDataObject = true)]
public class HiveService : IHiveService {
private DataAccess.IHiveDao dao {
get { return ServiceLocator.Instance.HiveDao; }
}
private HeuristicLab.Services.Hive.DataAccess.TransactionManager trans {
get { return ServiceLocator.Instance.TransactionManager; }
}
private IAuthorizationManager auth {
get { return ServiceLocator.Instance.AuthorizationManager; }
}
private ILifecycleManager lifecycleManager {
get { return ServiceLocator.Instance.LifecycleManager; }
}
private HeartbeatManager heartbeatManager {
get { return ServiceLocator.Instance.HeartbeatManager; }
}
#region Job Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Guid AddJob(Job job, JobData jobData, IEnumerable resourceIds) {
return trans.UseTransaction(() => {
job.Id = dao.AddJob(job);
jobData.JobId = job.Id;
jobData.LastUpdate = DateTime.Now;
if (resourceIds != null) {
foreach (Guid slaveGroupId in resourceIds) {
dao.AssignJobToResource(job.Id, slaveGroupId);
}
} else {
// todo: use default group
}
dao.AddJobData(jobData);
dao.UpdateJobState(job.Id, JobState.Waiting, null, auth.UserId, null);
return jobData.JobId;
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Guid AddChildJob(Guid parentJobId, Job job, JobData jobData) {
return trans.UseTransaction(() => {
job.ParentJobId = parentJobId;
return AddJob(job, jobData, dao.GetAssignedResources(parentJobId).Select(x => x.Id));
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public Job GetJob(Guid jobId) {
return dao.GetJob(jobId);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public IEnumerable GetJobs() {
return dao.GetJobs(x => true);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public IEnumerable GetLightweightJobs(IEnumerable jobIds) {
return dao.GetJobs(x => jobIds.Contains(x.JobId)).Select(x => new LightweightJob(x)).ToArray();
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public IEnumerable GetLightweightChildJobs(Guid? parentJobId, bool recursive, bool includeParent) {
return GetChildJobs(parentJobId, recursive, includeParent).Select(x => new LightweightJob(x)).ToArray();
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public JobData GetJobData(Guid jobId) {
return dao.GetJobData(jobId);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void UpdateJob(Job job) {
trans.UseTransaction(() => {
dao.UpdateJob(job);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void UpdateJobData(Job job, JobData jobData) {
trans.UseTransaction(() => {
jobData.LastUpdate = DateTime.Now;
dao.UpdateJob(job);
dao.UpdateJobData(jobData);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void DeleteJob(Guid jobId) {
trans.UseTransaction(() => {
dao.DeleteJob(jobId);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void DeleteChildJobs(Guid parentJobId) {
trans.UseTransaction(() => {
var jobs = GetChildJobs(parentJobId, true, false);
foreach (var job in jobs) {
dao.DeleteJob(job.Id);
dao.DeleteJobData(job.Id);
};
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public Job UpdateJobState(Guid jobId, JobState jobState, Guid? slaveId, Guid? userId, string exception) {
return trans.UseTransaction(() => {
Job job = dao.UpdateJobState(jobId, jobState, slaveId, userId, exception);
if (job.Command.HasValue && job.Command.Value == Command.Pause && job.State == JobState.Paused) {
job.Command = null;
} else if (job.Command.HasValue && job.Command.Value == Command.Abort && job.State == JobState.Aborted) {
job.Command = null;
} else if (job.Command.HasValue && job.Command.Value == Command.Stop && job.State == JobState.Aborted) {
job.Command = null;
}
dao.UpdateJob(job);
return job;
});
}
#endregion
#region Job Control Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void StopJob(Guid jobId) {
trans.UseTransaction(() => {
//dao.UpdateJobState(jobId, JobState.Aborted, null, auth.UserId, string.Empty);
var job = dao.GetJob(jobId);
job.Command = Command.Stop;
dao.UpdateJob(job);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void PauseJob(Guid jobId) {
trans.UseTransaction(() => {
//dao.UpdateJobState(jobId, JobState.Paused, null, auth.UserId, string.Empty);
var job = dao.GetJob(jobId);
job.Command = Command.Pause;
dao.UpdateJob(job);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void RestartJob(Guid jobId) {
trans.UseTransaction(() => {
Job job = dao.UpdateJobState(jobId, JobState.Waiting, null, auth.UserId, string.Empty);
job.Command = null;
dao.UpdateJob(job);
});
}
#endregion
#region HiveExperiment Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public HiveExperiment GetHiveExperiment(Guid id) {
return dao.GetHiveExperiments(x =>
x.HiveExperimentId == id
&& (x.OwnerUserId == auth.UserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == auth.UserId) > 0)
).FirstOrDefault();
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public IEnumerable GetHiveExperiments() {
return dao.GetHiveExperiments(x => x.OwnerUserId == auth.UserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == auth.UserId) > 0);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
public IEnumerable GetAllHiveExperiments() {
return dao.GetHiveExperiments(x => true);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Guid AddHiveExperiment(HiveExperiment hiveExperimentDto) {
return trans.UseTransaction(() => {
hiveExperimentDto.OwnerUserId = auth.UserId;
hiveExperimentDto.DateCreated = DateTime.Now;
return dao.AddHiveExperiment(hiveExperimentDto);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void UpdateHiveExperiment(HiveExperiment hiveExperimentDto) {
trans.UseTransaction(() => {
dao.UpdateHiveExperiment(hiveExperimentDto);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void DeleteHiveExperiment(Guid hiveExperimentId) {
trans.UseTransaction(() => {
HiveExperiment he = dao.GetHiveExperiment(hiveExperimentId);
dao.DeleteHiveExperiment(hiveExperimentId); // child jobs will be deleted by db-trigger
});
}
#endregion
#region Login Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void Hello(Slave slaveInfo) {
trans.UseTransaction(() => {
var slave = dao.GetSlave(slaveInfo.Id);
if (slave == null) {
dao.AddSlave(slaveInfo);
} else {
dao.UpdateSlave(slaveInfo);
}
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public void GoodBye(Guid slaveId) {
trans.UseTransaction(() => {
var slave = dao.GetSlave(slaveId);
if (slave != null) {
slave.SlaveState = SlaveState.Offline;
dao.UpdateSlave(slave);
}
});
}
#endregion
#region Heartbeat Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public List Heartbeat(Heartbeat heartbeat) {
TriggerLifecycle(false);
return trans.UseTransaction(() => heartbeatManager.ProcessHeartbeat(heartbeat));
}
#endregion
#region Plugin Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Guid AddPlugin(Plugin plugin, List pluginDatas) {
return trans.UseTransaction(() => {
plugin.UserId = auth.UserId;
plugin.DateCreated = DateTime.Now;
Guid pluginId = dao.AddPlugin(plugin);
foreach (PluginData pluginData in pluginDatas) {
pluginData.PluginId = pluginId;
dao.AddPluginData(pluginData);
}
return pluginId;
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public IEnumerable GetPlugins() {
return dao.GetPlugins(x => x.IsLocal == false);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
public IEnumerable GetPluginDatas(List pluginIds) {
List pluginDatas = new List();
return trans.UseTransaction(() => {
foreach (Guid guid in pluginIds) {
List pluginData = dao.GetPluginDatas(x => x.PluginId == guid).ToList();
if (pluginData != null) {
pluginDatas.AddRange(pluginData);
} else {
//ignore ?
}
}
return pluginDatas;
});
}
#endregion
#region Slave Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Guid AddSlave(Slave slave) {
return trans.UseTransaction(() => dao.AddSlave(slave));
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Guid AddSlaveGroup(SlaveGroup slaveGroup) {
return trans.UseTransaction(() => dao.AddSlaveGroup(slaveGroup));
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Slave GetSlave(Guid slaveId) {
return dao.GetSlave(slaveId);
}
public SlaveGroup GetSlaveGroup(Guid slaveGroupId) {
return dao.GetSlaveGroup(slaveGroupId);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public IEnumerable GetSlaves() {
return dao.GetSlaves(x => true);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public IEnumerable GetSlaveGroups() {
return dao.GetSlaveGroups(x => true);
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void UpdateSlave(Slave slave) {
trans.UseTransaction(() => {
dao.UpdateSlave(slave);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void UpdateSlaveGroup(SlaveGroup slaveGroup) {
trans.UseTransaction(() => {
dao.UpdateSlaveGroup(slaveGroup);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void DeleteSlave(Guid slaveId) {
trans.UseTransaction(() => {
dao.DeleteSlave(slaveId);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void DeleteSlaveGroup(Guid slaveGroupId) {
trans.UseTransaction(() => {
dao.DeleteSlaveGroup(slaveGroupId);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
trans.UseTransaction(() => {
var resource = dao.GetResource(resourceId);
resource.ParentResourceId = slaveGroupId;
dao.UpdateResource(resource);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
trans.UseTransaction(() => {
var resource = dao.GetResource(resourceId);
resource.ParentResourceId = null;
dao.UpdateResource(resource);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
public Guid GetResourceId(string resourceName) {
return trans.UseTransaction(() => {
var resource = dao.GetResources(x => x.Name == resourceName).FirstOrDefault();
if (resource != null) {
return resource.Id;
} else {
return Guid.Empty;
}
});
}
public void TriggerLifecycle(bool force) {
trans.UseTransaction(() => {
DateTime lastCleanup = dao.GetLastCleanup();
if (force || DateTime.Now - lastCleanup > TimeSpan.FromSeconds(59)) {
dao.SetLastCleanup(DateTime.Now);
lifecycleManager.Cleanup();
}
});
}
#endregion
#region Helper Methods
private IEnumerable GetChildJobs(Guid? parentJobId, bool recursive, bool includeParent) {
var jobs = new List(dao.GetJobs(x => parentJobId == null ? !x.ParentJobId.HasValue : x.ParentJobId.Value == parentJobId));
if (recursive) {
var childs = new List();
foreach (var job in jobs) {
childs.AddRange(GetChildJobs(job.Id, recursive, false));
}
jobs.AddRange(childs);
}
if (includeParent) jobs.Add(GetJob(parentJobId.Value));
return jobs;
}
#endregion
#region Appointment Methods
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
public Guid AddAppointment(Appointment appointment) {
return trans.UseTransaction(() => dao.AddAppointment(appointment));
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
public void DeleteAppointment(Guid appointmentId) {
trans.UseTransaction(() => {
dao.DeleteAppointment(appointmentId);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
public void UpdateAppointment(Appointment appointment) {
trans.UseTransaction(() => {
dao.UpdateAppointment(appointment);
});
}
[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
public IEnumerable GetScheduleForResource(Guid resourceId) {
return trans.UseTransaction(() => dao.GetAppointments(x => x.ResourceId == resourceId));
}
#endregion
}
}