#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 HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Hive; using HeuristicLab.PluginInfrastructure; using HeuristicLab.Services.Hive.Common.DataTransfer; namespace HeuristicLab.Clients.Hive.Slave { public class Executor : MarshalByRefObject, IDisposable { public Guid JobId { get; set; } public IJob Job { get; set; } private bool wasJobAborted = false; public Core core { get; set; } private Exception currentException; public String CurrentException { get { if (currentException != null) { return currentException.ToString(); } else { return string.Empty; } } } public ExecutionState ExecutionState { get { return Job != null ? Job.ExecutionState : HeuristicLab.Core.ExecutionState.Stopped; } } public TimeSpan ExecutionTime { get { return Job != null ? Job.ExecutionTime : new TimeSpan(0, 0, 0); } } public DateTime CreationTime { get; set; } /// /// if true, all child-jobs are downloaded and the job will be resumed. public void Start(byte[] serializedJob) { try { CreationTime = DateTime.Now; Job = PersistenceUtil.Deserialize(serializedJob); RegisterJobEvents(); if (Job.CollectChildJobs) { IEnumerable childjobs = WcfService.Instance.GetChildJobs(JobId); Job.Resume(childjobs.Select(j => PersistenceUtil.Deserialize(j.Data))); } else { Job.Prepare(); Job.Start(); } } catch (Exception e) { this.currentException = e; } } public void StartOnlyJob() { try { Job.Start(); } catch (Exception e) { this.currentException = e; } } public void Pause() { Job.Pause(); } public void Abort() { wasJobAborted = true; if ((ExecutionState == ExecutionState.Started) || (ExecutionState == ExecutionState.Paused)) { Job.Stop(); } else { Job_JobStopped(this, EventArgs.Empty); } } private void RegisterJobEvents() { Job.JobStopped += new EventHandler(Job_JobStopped); Job.JobFailed += new EventHandler(Job_JobFailed); Job.NewChildJob += new EventHandler>(Job_NewChildJob); Job.WaitForChildJobs += new EventHandler(Job_WaitForChildJobs); Job.DeleteChildJobs += new EventHandler(Job_DeleteChildJobs); } private void DeregisterJobEvents() { Job.JobStopped -= new EventHandler(Job_JobStopped); Job.JobFailed -= new EventHandler(Job_JobFailed); Job.NewChildJob -= new EventHandler>(Job_NewChildJob); Job.WaitForChildJobs -= new EventHandler(Job_WaitForChildJobs); Job.DeleteChildJobs -= new EventHandler(Job_DeleteChildJobs); } private List FindPluginsNeeded(IJob obj) { List guids = new List(); foreach (IPluginDescription desc in PluginUtil.GetDeclaringPlugins(obj)) { } throw new NotImplementedException("FindPluginsNeeded for Job_NewChildJob"); return guids; } private void Job_NewChildJob(object sender, EventArgs e) { JobData childJobData = new JobData(); childJobData.Data = PersistenceUtil.Serialize(e.Value); Job childJob = new Job(); childJob.JobState = JobState.Offline; childJob.CoresNeeded = 1; childJob.MemoryNeeded = 0; childJob.PluginsNeededIds = FindPluginsNeeded(e.Value); //TODO: is return value needed? WcfService.Instance.AddChildJob(this.JobId, childJob, childJobData); } private void Job_WaitForChildJobs(object sender, EventArgs e) { // Pause the job and send it back to the hive. The server will awake it when all child-jobs are finished this.Job.CollectChildJobs = true; JobData jdata = new JobData(); jdata.Data = PersistenceUtil.Serialize(Job); jdata.JobId = this.JobId; core.PauseJob(jdata); } private void Job_DeleteChildJobs(object sender, EventArgs e) { WcfService.Instance.DeleteChildJobs(JobId); } private void Job_JobFailed(object sender, EventArgs e) { //TODO: get exception to client HeuristicLab.Common.EventArgs ex = (HeuristicLab.Common.EventArgs)e; currentException = ex.Value; core.SendFinishedJob(JobId); } private void Job_JobStopped(object sender, EventArgs e) { if (wasJobAborted) { core.KillAppDomain(JobId); } else { core.SendFinishedJob(JobId); } } public JobData GetFinishedJob() { if (Job == null) { throw new InvalidStateException("Job is null"); } if (Job.ExecutionState == HeuristicLab.Core.ExecutionState.Started) { try { Job.Stop(); } catch { } } if (Job.ExecutionState == HeuristicLab.Core.ExecutionState.Started) { throw new InvalidStateException("Job is still running"); } else { JobData jdata = new JobData(); jdata.Data = PersistenceUtil.Serialize(Job); jdata.JobId = JobId; return jdata; } } public Executor() { } public void Dispose() { if (Job != null) DeregisterJobEvents(); Job = null; } } }