Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 6451 was 6431, checked in by cneumuel, 14 years ago

#1233

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