Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HiveService.cs @ 6369

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

#1233

  • added consideration of appointments in heartbeats
  • code cleanup
File size: 18.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.ServiceModel;
5using HeuristicLab.Services.Hive.Common;
6using HeuristicLab.Services.Hive.Common.DataTransfer;
7using HeuristicLab.Services.Hive.Common.ServiceContracts;
8
9namespace HeuristicLab.Services.Hive {
10
11  /// <summary>
12  /// Implementation of the Hive service (interface <see cref="IHiveService"/>).
13  /// We need 'IgnoreExtensionDataObject' Attribute for the slave to work.
14  /// </summary>
15  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IgnoreExtensionDataObject = true)]
16  public class HiveService : IHiveService {
17    private DataAccess.IHiveDao dao {
18      get { return ServiceLocator.Instance.HiveDao; }
19    }
20    private HeuristicLab.Services.Hive.DataAccess.TransactionManager trans {
21      get { return ServiceLocator.Instance.TransactionManager; }
22    }
23    private IAuthenticationManager authen {
24      get { return ServiceLocator.Instance.AuthenticationManager; }
25    }
26    private IAuthorizationManager author {
27      get { return ServiceLocator.Instance.AuthorizationManager; }
28    }
29    private ILifecycleManager lifecycleManager {
30      get { return ServiceLocator.Instance.LifecycleManager; }
31    }
32    private HeartbeatManager heartbeatManager {
33      get { return ServiceLocator.Instance.HeartbeatManager; }
34    }
35
36    #region Job Methods
37    public Guid AddJob(Job job, JobData jobData, IEnumerable<Guid> resourceIds) {
38      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
39      return trans.UseTransaction(() => {
40        job.Id = dao.AddJob(job);
41        jobData.JobId = job.Id;
42        jobData.LastUpdate = DateTime.Now;
43        foreach (Guid slaveGroupId in resourceIds) {
44          dao.AssignJobToResource(job.Id, slaveGroupId);
45        }
46        dao.AddJobData(jobData);
47        dao.UpdateJobState(job.Id, JobState.Waiting, null, author.UserId, null);
48        return jobData.JobId;
49      });
50    }
51
52    public Guid AddChildJob(Guid parentJobId, Job job, JobData jobData) {
53      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
54      return trans.UseTransaction(() => {
55        job.ParentJobId = parentJobId;
56        return AddJob(job, jobData, dao.GetAssignedResources(parentJobId).Select(x => x.Id));
57      });
58    }
59
60    public Job GetJob(Guid jobId) {
61      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
62      return dao.GetJob(jobId);
63    }
64
65    public IEnumerable<Job> GetJobs() {
66      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
67      return dao.GetJobs(x => true);
68    }
69
70    public IEnumerable<LightweightJob> GetLightweightJobs(IEnumerable<Guid> jobIds) {
71      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
72      return dao.GetJobs(x => jobIds.Contains(x.JobId)).Select(x => new LightweightJob(x)).ToArray();
73    }
74
75    public IEnumerable<LightweightJob> GetLightweightChildJobs(Guid? parentJobId, bool recursive, bool includeParent) {
76      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
77      return GetChildJobs(parentJobId, recursive, includeParent).Select(x => new LightweightJob(x)).ToArray();
78    }
79
80    public IEnumerable<LightweightJob> GetLightweightExperimentJobs(Guid experimentId) {
81      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
82      return dao.GetJobs(x => x.HiveExperimentId == experimentId).Select(x => new LightweightJob(x)).ToArray();
83    }
84
85    public JobData GetJobData(Guid jobId) {
86      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
87      return dao.GetJobData(jobId);
88    }
89
90    public void UpdateJob(Job job) {
91      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
92      trans.UseTransaction(() => {
93        dao.UpdateJob(job);
94      });
95    }
96
97    public void UpdateJobData(Job job, JobData jobData) {
98      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
99      trans.UseTransaction(() => {
100        jobData.LastUpdate = DateTime.Now;
101        dao.UpdateJob(job);
102        dao.UpdateJobData(jobData);
103      });
104    }
105
106    public void DeleteJob(Guid jobId) {
107      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
108      trans.UseTransaction(() => {
109        dao.DeleteJob(jobId);
110      });
111    }
112
113    public void DeleteChildJobs(Guid parentJobId) {
114      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
115      trans.UseTransaction(() => {
116        var jobs = GetChildJobs(parentJobId, true, false);
117        foreach (var job in jobs) {
118          dao.DeleteJob(job.Id);
119          dao.DeleteJobData(job.Id);
120        };
121      });
122    }
123
124    public Job UpdateJobState(Guid jobId, JobState jobState, Guid? slaveId, Guid? userId, string exception) {
125      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
126      return trans.UseTransaction(() => {
127        Job job = dao.UpdateJobState(jobId, jobState, slaveId, userId, exception);
128
129        if (job.Command.HasValue && job.Command.Value == Command.Pause && job.State == JobState.Paused) {
130          job.Command = null;
131        } else if (job.Command.HasValue && job.Command.Value == Command.Abort && job.State == JobState.Aborted) {
132          job.Command = null;
133        } else if (job.Command.HasValue && job.Command.Value == Command.Stop && job.State == JobState.Aborted) {
134          job.Command = null;
135        } else if (jobState == JobState.Paused && !job.Command.HasValue) {
136          // slave paused and uploaded the job (no user-command) -> set waiting.
137          job = dao.UpdateJobState(jobId, JobState.Waiting, slaveId, userId, exception);
138        }
139
140        dao.UpdateJob(job);
141        return job;
142      });
143    }
144    #endregion
145
146    #region Job Control Methods
147    public void StopJob(Guid jobId) {
148      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
149      trans.UseTransaction(() => {
150        var job = dao.GetJob(jobId);
151        if (job.State == JobState.Calculating || job.State == JobState.Transferring) {
152          job.Command = Command.Stop;
153          dao.UpdateJob(job);
154        } else {
155          if (job.State != JobState.Aborted && job.State != JobState.Finished && job.State != JobState.Failed) {
156            job = UpdateJobState(jobId, JobState.Aborted, null, null, string.Empty);
157          }
158        }
159      });
160    }
161
162    public void PauseJob(Guid jobId) {
163      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
164      trans.UseTransaction(() => {
165        var job = dao.GetJob(jobId);
166        if (job.State == JobState.Calculating || job.State == JobState.Transferring) {
167          job.Command = Command.Pause;
168          dao.UpdateJob(job);
169        } else {
170          job = UpdateJobState(jobId, JobState.Paused, null, null, string.Empty);
171        }
172      });
173    }
174
175    public void RestartJob(Guid jobId) {
176      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
177      trans.UseTransaction(() => {
178        Job job = dao.UpdateJobState(jobId, JobState.Waiting, null, author.UserId, string.Empty);
179        job.Command = null;
180        dao.UpdateJob(job);
181      });
182    }
183    #endregion
184
185    #region HiveExperiment Methods
186    public HiveExperiment GetHiveExperiment(Guid id) {
187      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
188      return dao.GetHiveExperiments(x =>
189        x.HiveExperimentId == id
190        && (x.OwnerUserId == author.UserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == author.UserId) > 0)
191      ).FirstOrDefault();
192    }
193
194    public IEnumerable<HiveExperiment> GetHiveExperiments() {
195      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
196      return dao.GetHiveExperiments(x => x.OwnerUserId == author.UserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == author.UserId) > 0);
197    }
198
199    public IEnumerable<HiveExperiment> GetAllHiveExperiments() {
200      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
201      return dao.GetHiveExperiments(x => true);
202    }
203
204    public Guid AddHiveExperiment(HiveExperiment hiveExperimentDto) {
205      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
206      return trans.UseTransaction(() => {
207        hiveExperimentDto.OwnerUserId = author.UserId;
208        hiveExperimentDto.DateCreated = DateTime.Now;
209        return dao.AddHiveExperiment(hiveExperimentDto);
210      });
211    }
212
213    public void UpdateHiveExperiment(HiveExperiment hiveExperimentDto) {
214      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
215      trans.UseTransaction(() => {
216        dao.UpdateHiveExperiment(hiveExperimentDto);
217      });
218    }
219
220    public void DeleteHiveExperiment(Guid hiveExperimentId) {
221      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
222      trans.UseTransaction(() => {
223        HiveExperiment he = dao.GetHiveExperiment(hiveExperimentId);
224        dao.DeleteHiveExperiment(hiveExperimentId); // child jobs will be deleted by db-trigger
225      });
226    }
227    #endregion
228
229    #region Login Methods
230    public void Hello(Slave slaveInfo) {
231      authen.AuthenticateForAnyRole(HiveRoles.Slave);
232      trans.UseTransaction(() => {
233        var slave = dao.GetSlave(slaveInfo.Id);
234
235        if (slave == null) {
236          dao.AddSlave(slaveInfo);
237        } else {
238          var dbSlave = dao.GetSlave(slaveInfo.Id);
239
240          dbSlave.Name = slaveInfo.Name;
241          dbSlave.Description = slaveInfo.Description;
242
243          dbSlave.Cores = slaveInfo.Cores;
244          dbSlave.CpuArchitecture = slaveInfo.CpuArchitecture;
245          dbSlave.CpuSpeed = slaveInfo.CpuSpeed;
246          dbSlave.FreeCores = slaveInfo.FreeCores;
247          dbSlave.FreeMemory = slaveInfo.FreeMemory;
248          dbSlave.Memory = slaveInfo.Memory;
249          dbSlave.OperatingSystem = slaveInfo.OperatingSystem;
250
251          dbSlave.LastHeartbeat = DateTime.Now;
252          dbSlave.SlaveState = SlaveState.Idle;
253
254          // don't update those properties: dbSlave.IsAllowedToCalculate, dbSlave.ParentResourceId
255
256          dao.UpdateSlave(dbSlave);
257        }
258      });
259    }
260
261    public void GoodBye(Guid slaveId) {
262      authen.AuthenticateForAnyRole(HiveRoles.Slave);
263      trans.UseTransaction(() => {
264        var slave = dao.GetSlave(slaveId);
265        if (slave != null) {
266          slave.SlaveState = SlaveState.Offline;
267          dao.UpdateSlave(slave);
268        }
269      });
270    }
271    #endregion
272
273    #region Heartbeat Methods
274    public List<MessageContainer> Heartbeat(Heartbeat heartbeat) {
275      authen.AuthenticateForAnyRole(HiveRoles.Slave);
276      TriggerLifecycle(false);
277      return trans.UseTransaction(() => heartbeatManager.ProcessHeartbeat(heartbeat));
278    }
279    #endregion
280
281    #region Plugin Methods
282    public Guid AddPlugin(Plugin plugin, List<PluginData> pluginDatas) {
283      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
284      return trans.UseTransaction(() => {
285        plugin.UserId = author.UserId;
286        plugin.DateCreated = DateTime.Now;
287        if (!plugin.IsLocal) {
288          var existing = dao.GetPlugins(x => x.Name == plugin.Name && x.Version == plugin.Version.ToString() && !x.IsLocal);
289          if (existing.Count() > 0) {
290            // a plugin with the same name and version already exists.
291            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(existing.Single().Id));
292          }
293        }
294        Guid pluginId = dao.AddPlugin(plugin);
295        foreach (PluginData pluginData in pluginDatas) {
296          pluginData.PluginId = pluginId;
297          dao.AddPluginData(pluginData);
298        }
299        return pluginId;
300      });
301    }
302
303    public Plugin GetPlugin(Guid pluginId) {
304      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
305      return dao.GetPlugin(pluginId);
306    }
307
308    public IEnumerable<Plugin> GetPlugins() {
309      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
310      return dao.GetPlugins(x => x.IsLocal == false);
311    }
312
313    public IEnumerable<PluginData> GetPluginDatas(List<Guid> pluginIds) {
314      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
315      List<PluginData> pluginDatas = new List<PluginData>();
316
317      return trans.UseTransaction(() => {
318        foreach (Guid guid in pluginIds) {
319          pluginDatas.AddRange(dao.GetPluginDatas(x => x.PluginId == guid).ToList());
320        }
321        return pluginDatas;
322      });
323    }
324
325    #endregion
326
327    #region Slave Methods
328    public Guid AddSlave(Slave slave) {
329      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
330      return trans.UseTransaction(() => dao.AddSlave(slave));
331    }
332
333    public Guid AddSlaveGroup(SlaveGroup slaveGroup) {
334      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
335      return trans.UseTransaction(() => dao.AddSlaveGroup(slaveGroup));
336    }
337
338    public Slave GetSlave(Guid slaveId) {
339      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
340      return dao.GetSlave(slaveId);
341    }
342
343    public SlaveGroup GetSlaveGroup(Guid slaveGroupId) {
344      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
345      return dao.GetSlaveGroup(slaveGroupId);
346    }
347
348    public IEnumerable<Slave> GetSlaves() {
349      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
350      return dao.GetSlaves(x => true);
351    }
352
353    public IEnumerable<SlaveGroup> GetSlaveGroups() {
354      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
355      return dao.GetSlaveGroups(x => true);
356    }
357
358    public void UpdateSlave(Slave slave) {
359      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
360      trans.UseTransaction(() => {
361        dao.UpdateSlave(slave);
362      });
363    }
364
365    public void UpdateSlaveGroup(SlaveGroup slaveGroup) {
366      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
367      trans.UseTransaction(() => {
368        dao.UpdateSlaveGroup(slaveGroup);
369      });
370    }
371
372    public void DeleteSlave(Guid slaveId) {
373      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
374      trans.UseTransaction(() => {
375        dao.DeleteSlave(slaveId);
376      });
377    }
378
379    public void DeleteSlaveGroup(Guid slaveGroupId) {
380      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
381      trans.UseTransaction(() => {
382        dao.DeleteSlaveGroup(slaveGroupId);
383      });
384    }
385
386    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
387      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
388      trans.UseTransaction(() => {
389        var resource = dao.GetResource(resourceId);
390        resource.ParentResourceId = slaveGroupId;
391        dao.UpdateResource(resource);
392      });
393    }
394
395    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
396      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
397      trans.UseTransaction(() => {
398        var resource = dao.GetResource(resourceId);
399        resource.ParentResourceId = null;
400        dao.UpdateResource(resource);
401      });
402    }
403
404    public Guid GetResourceId(string resourceName) {
405      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
406      return trans.UseTransaction(() => {
407        var resource = dao.GetResources(x => x.Name == resourceName).FirstOrDefault();
408        if (resource != null) {
409          return resource.Id;
410        } else {
411          return Guid.Empty;
412        }
413      });
414    }
415
416    public void TriggerLifecycle(bool force) {
417      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
418      trans.UseTransaction(() => {
419        DateTime lastCleanup = dao.GetLastCleanup();
420        if (force || DateTime.Now - lastCleanup > TimeSpan.FromSeconds(59)) {
421          dao.SetLastCleanup(DateTime.Now);
422          lifecycleManager.Cleanup();
423        }
424      }, true);
425    }
426    #endregion
427
428    #region Helper Methods
429    private IEnumerable<Job> GetChildJobs(Guid? parentJobId, bool recursive, bool includeParent) {
430      var jobs = new List<Job>(dao.GetJobs(x => parentJobId == null ? !x.ParentJobId.HasValue : x.ParentJobId.Value == parentJobId));
431
432      if (recursive) {
433        var childs = new List<Job>();
434        foreach (var job in jobs) {
435          childs.AddRange(GetChildJobs(job.Id, recursive, false));
436        }
437        jobs.AddRange(childs);
438      }
439
440      if (includeParent) jobs.Add(GetJob(parentJobId.Value));
441      return jobs;
442    }
443    #endregion
444
445    #region Appointment Methods
446    public Guid AddAppointment(Appointment appointment) {
447      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
448      return trans.UseTransaction(() => dao.AddAppointment(appointment));
449    }
450
451    public void DeleteAppointment(Guid appointmentId) {
452      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
453      trans.UseTransaction(() => {
454        dao.DeleteAppointment(appointmentId);
455      });
456    }
457
458    public void UpdateAppointment(Appointment appointment) {
459      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
460      trans.UseTransaction(() => {
461        dao.UpdateAppointment(appointment);
462      });
463    }
464
465    public IEnumerable<Appointment> GetScheduleForResource(Guid resourceId) {
466      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
467      return trans.UseTransaction(() => dao.GetAppointments(x => x.ResourceId == resourceId));
468    }
469
470    public IEnumerable<Job> GetJobsByResourceId(Guid resourceId) {
471      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
472      return trans.UseTransaction(() => dao.GetJobsByResourceId(resourceId));
473    }
474    #endregion
475  }
476}
Note: See TracBrowser for help on using the repository browser.