Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

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