#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.ComponentModel;
using System.Drawing;
using System.Linq;
using HeuristicLab.Collections;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Hive;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.PluginInfrastructure;
namespace HeuristicLab.Clients.Hive {
[Item("Hive Job", "Represents a hive job.")]
[StorableClass]
public class HiveJob : NamedItem, IItemTree {
protected static object locker = new object();
public override Image ItemImage {
get {
if (job.Id == Guid.Empty) { // not yet uploaded
return HeuristicLab.Common.Resources.VSImageLibrary.Event;
} else {
if (job.State == JobState.Waiting) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
else if (job.State == JobState.Calculating) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
else if (job.State == JobState.Transferring) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
else if (job.State == JobState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
else if (job.State == JobState.Aborted) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
else if (job.State == JobState.Failed) return HeuristicLab.Common.Resources.VSImageLibrary.Error;
else if (job.State == JobState.Finished) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
else return HeuristicLab.Common.Resources.VSImageLibrary.Event;
}
}
}
[Storable]
protected Job job;
public Job Job {
get { return job; }
set {
if (job != value) {
DeregisterJobEvents();
job = value;
RegisterJobEvents();
IsFinishedJobDownloaded = false;
OnJobChanged();
OnToStringChanged();
OnItemImageChanged();
}
}
}
[Storable]
protected ItemJob itemJob;
public ItemJob ItemJob {
get { return itemJob; }
internal set {
if (itemJob != null && syncJobsWithOptimizers) {
this.childHiveJobs.Clear();
}
if (itemJob != value) {
DergisterItemJobEvents();
itemJob = value;
RegisterItemJobEvents();
OnJobItemChanged();
IsFinishedJobDownloaded = true;
}
}
}
// job downloaded since last status change
[Storable]
private bool isFinishedJobDownloaded = false;
public bool IsFinishedJobDownloaded {
get { return isFinishedJobDownloaded; }
set {
if (value != isFinishedJobDownloaded) {
this.isFinishedJobDownloaded = value;
OnIsFinishedJobDownloadedChanged();
}
}
}
public bool IsDownloading { get; set; }
[Storable]
protected ItemList childHiveJobs;
public virtual ReadOnlyItemList ChildHiveJobs {
get { return childHiveJobs.AsReadOnly(); }
}
[Storable]
protected bool syncJobsWithOptimizers = true;
#region Constructors and Cloning
public HiveJob() {
this.Job = new Job() {
CoresNeeded = 1,
MemoryNeeded = 0
};
job.State = JobState.Offline;
this.childHiveJobs = new ItemList();
syncJobsWithOptimizers = true;
RegisterChildHiveJobEvents();
}
public HiveJob(ItemJob itemJob, bool autoCreateChildHiveJobs)
: this() {
this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
this.ItemJob = itemJob;
this.syncJobsWithOptimizers = true;
}
public HiveJob(Job job, JobData jobData, bool autoCreateChildHiveJobs) {
this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
this.Job = job;
try {
this.ItemJob = PersistenceUtil.Deserialize(jobData.Data);
}
catch {
this.ItemJob = null;
}
this.childHiveJobs = new ItemList();
this.syncJobsWithOptimizers = true;
RegisterChildHiveJobEvents();
}
protected HiveJob(HiveJob original, Cloner cloner)
: base(original, cloner) {
this.Job = cloner.Clone(original.job);
this.ItemJob = cloner.Clone(original.ItemJob);
this.childHiveJobs = cloner.Clone(original.childHiveJobs);
this.syncJobsWithOptimizers = original.syncJobsWithOptimizers;
this.isFinishedJobDownloaded = original.isFinishedJobDownloaded;
}
public override IDeepCloneable Clone(Cloner cloner) {
return new HiveJob(this, cloner);
}
#endregion
protected virtual void UpdateChildHiveJobs() { }
protected virtual void RegisterItemJobEvents() {
if (ItemJob != null) {
ItemJob.ComputeInParallelChanged += new EventHandler(JobItem_ComputeInParallelChanged);
ItemJob.ToStringChanged += new EventHandler(JobItem_ToStringChanged);
}
}
protected virtual void DergisterItemJobEvents() {
if (ItemJob != null) {
ItemJob.ComputeInParallelChanged -= new EventHandler(JobItem_ComputeInParallelChanged);
ItemJob.ToStringChanged -= new EventHandler(JobItem_ToStringChanged);
}
}
protected virtual void RegisterChildHiveJobEvents() {
this.childHiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler>(OnItemsAdded);
this.childHiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler>(OnItemsRemoved);
this.childHiveJobs.CollectionReset += new CollectionItemsChangedEventHandler>(OnCollectionReset);
}
protected virtual void DeregisterChildHiveJobEvents() {
this.childHiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler>(OnItemsAdded);
this.childHiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler>(OnItemsRemoved);
this.childHiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler>(OnCollectionReset);
}
protected virtual void JobItem_ToStringChanged(object sender, EventArgs e) {
this.OnToStringChanged();
}
protected virtual void JobItem_ComputeInParallelChanged(object sender, EventArgs e) {
if (ItemJob != null && syncJobsWithOptimizers) {
this.UpdateChildHiveJobs();
}
}
public virtual void AddChildHiveJob(HiveJob hiveJob) {
this.childHiveJobs.Add(hiveJob);
}
public override string ToString() {
if (itemJob != null) {
return itemJob.ToString();
} else {
return base.ToString();
}
}
public virtual void UpdateFromLightweightJob(LightweightJob lightweightJob) {
if (lightweightJob != null) {
job.Id = lightweightJob.Id;
job.ParentJobId = lightweightJob.ParentJobId;
job.ExecutionTime = lightweightJob.ExecutionTime;
job.State = lightweightJob.State;
job.StateLog = new List(lightweightJob.StateLog);
job.Command = lightweightJob.Command;
OnJobStateChanged();
OnToStringChanged();
OnItemImageChanged();
}
}
///
/// Creates a JobData object containing the Job and the IJob-Object as byte[]
///
///
/// if true the Child-Optimizers will not be serialized (if the job contains an Experiment)
///
public virtual JobData GetAsJobData(bool withoutChildOptimizers, out List plugins) {
plugins = new List();
if (this.itemJob == null)
return null;
IEnumerable usedTypes;
byte[] jobByteArray = PersistenceUtil.Serialize(this.ItemJob, out usedTypes);
JobData jobData = new JobData() {
JobId = job.Id,
Data = jobByteArray
};
PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
return jobData;
}
#region Events
public event EventHandler JobChanged;
private void OnJobChanged() {
EventHandler handler = JobChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
public event EventHandler JobStateChanged;
private void OnJobStateChanged() {
EventHandler handler = JobStateChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
public event EventHandler JobItemChanged;
private void OnJobItemChanged() {
JobItem_ComputeInParallelChanged(this, EventArgs.Empty);
var handler = JobItemChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
public event EventHandler IsFinishedJobDownloadedChanged;
private void OnIsFinishedJobDownloadedChanged() {
var handler = IsFinishedJobDownloadedChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
private void RegisterJobEvents() {
if (job != null)
job.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
}
private void DeregisterJobEvents() {
if (job != null)
job.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(job_PropertyChanged);
}
private void job_PropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "State") {
IsFinishedJobDownloaded = false;
}
}
#endregion
///
/// Returns a list of HiveJobs including this and all its child-jobs recursively
///
public IEnumerable GetAllHiveJobs() {
var jobs = new List();
jobs.Add(this);
foreach (HiveJob child in this.ChildHiveJobs) {
jobs.AddRange(child.GetAllHiveJobs());
}
return jobs;
}
public HiveJob GetParentByJobId(Guid jobId) {
if (this.ChildHiveJobs.SingleOrDefault(j => j.job.Id == jobId) != null)
return this;
foreach (HiveJob child in this.childHiveJobs) {
HiveJob result = child.GetParentByJobId(jobId);
if (result != null)
return result;
}
return null;
}
///
/// Searches for an HiveJob object with the correct jobId recursively
///
public HiveJob GetHiveJobByJobId(Guid jobId) {
if (this.Job.Id == jobId) {
return this;
} else {
foreach (HiveJob child in this.ChildHiveJobs) {
HiveJob result = child.GetHiveJobByJobId(jobId);
if (result != null)
return result;
}
}
return null;
}
public void RemoveByJobId(Guid jobId) {
IEnumerable jobs = ChildHiveJobs.Where(j => j.Job.Id == jobId).ToList(); // if Guid.Empty needs to be removed, there could be more than one with this jobId
foreach (HiveJob j in jobs) {
this.childHiveJobs.Remove(j);
}
foreach (HiveJob child in ChildHiveJobs) {
child.RemoveByJobId(jobId);
}
}
public IEnumerable> GetChildItems() {
return this.childHiveJobs;
}
#region INotifyObservableCollectionItemsChanged Members
public event CollectionItemsChangedEventHandler> CollectionReset;
private void OnCollectionReset(object sender, CollectionItemsChangedEventArgs> e) {
var handler = CollectionReset;
if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
}
public event CollectionItemsChangedEventHandler> ItemsAdded;
private void OnItemsAdded(object sender, CollectionItemsChangedEventArgs> e) {
var handler = ItemsAdded;
if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
}
public event CollectionItemsChangedEventHandler> ItemsRemoved;
private void OnItemsRemoved(object sender, CollectionItemsChangedEventArgs> e) {
var handler = ItemsRemoved;
if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
}
private static CollectionItemsChangedEventArgs> ToCollectionItemsChangedEventArgs(CollectionItemsChangedEventArgs> e) {
return new CollectionItemsChangedEventArgs>(e.Items.Select(x => x.Value), e.OldItems == null ? null : e.OldItems.Select(x => x.Value));
}
#endregion
public void Pause() {
if (this.Job.IsParentJob) {
foreach (var child in ChildHiveJobs) {
ServiceLocator.Instance.CallHiveService(s => s.PauseJob(child.job.Id));
}
} else {
ServiceLocator.Instance.CallHiveService(s => s.PauseJob(this.job.Id));
}
}
public void Stop() {
if (this.Job.IsParentJob) {
foreach (var child in ChildHiveJobs) {
ServiceLocator.Instance.CallHiveService(s => s.StopJob(child.job.Id));
}
} else {
ServiceLocator.Instance.CallHiveService(s => s.StopJob(this.job.Id));
}
}
public void Restart() {
ServiceLocator.Instance.CallHiveService(service => {
JobData jobData = new JobData();
jobData.JobId = this.job.Id;
jobData.Data = PersistenceUtil.Serialize(this.itemJob);
service.UpdateJobData(this.Job, jobData);
service.RestartJob(this.job.Id);
Job job = service.GetJob(this.job.Id);
this.job.LastJobDataUpdate = job.LastJobDataUpdate;
});
}
public ICollection> Actions {
get {
return new List>();
}
}
public virtual void IntegrateChild(ItemJob job, Guid childJobId) { }
}
[Item("Hive Job", "Represents a hive job.")]
[StorableClass]
public class HiveJob : HiveJob where T : ItemJob {
public new T ItemJob {
get { return (T)base.ItemJob; }
internal set { base.ItemJob = value; }
}
#region Constructors and Cloning
public HiveJob() : base() { }
public HiveJob(T itemJob) : base(itemJob, true) { }
protected HiveJob(HiveJob original, Cloner cloner)
: base(original, cloner) {
}
public override IDeepCloneable Clone(Cloner cloner) {
return new HiveJob(this, cloner);
}
#endregion
}
}