Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Core.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Core.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Core.cs	(revision 5786)
@@ -57,5 +57,5 @@
     private int coreThreadId;
 
-    private ISlaveCommunication ClientCom;
+    private ISlaveCommunication clientCom;
     private ServiceHost slaveComm;
 
@@ -84,6 +84,6 @@
         slaveComm.Open();
 
-        ClientCom = SlaveClientCom.Instance.ClientCom;
-        ClientCom.LogMessage("Hive Slave started");
+        clientCom = SlaveClientCom.Instance.ClientCom;
+        clientCom.LogMessage("Hive Slave started");
 
         ConfigManager manager = ConfigManager.Instance;
@@ -139,9 +139,9 @@
 
     void WcfService_ExceptionOccured(object sender, EventArgs<Exception> e) {
-      ClientCom.LogMessage("Connection to server interruped with exception: " + e.Value.Message);
+      clientCom.LogMessage("Connection to server interruped with exception: " + e.Value.Message);
     }
 
     void WcfService_Connected(object sender, EventArgs e) {
-      ClientCom.LogMessage("Connected successfully to Hive server");
+      clientCom.LogMessage("Connected successfully to Hive server");
     }
 
@@ -151,5 +151,5 @@
     /// <param name="container">The Container, containing the message</param>
     private void DetermineAction(MessageContainer container) {
-      ClientCom.LogMessage("Message: " + container.Message.ToString() + " for job: " + container.JobId);
+      clientCom.LogMessage("Message: " + container.Message.ToString() + " for job: " + container.JobId);
 
       if (container is ExecutorMessageContainer<Guid>) {
@@ -159,6 +159,10 @@
         switch (container.Message) {
           case MessageContainer.MessageType.CalculateJob:
-            Task.Factory.StartNew(() => {
-              Job job = wcfService.GetJob(container.JobId);
+            clientCom.LogMessage("Task.StartNew[0]: jobId: " + container.JobId);
+            Task.Factory.StartNew((jobIdObj) => {
+              Guid jobId = (Guid)jobIdObj;
+              clientCom.LogMessage("Task.StartNew[1]: jobId: " + jobId);
+              Job job = wcfService.GetJob(jobId);
+              if (job == null) throw new JobNotFoundException(jobId);
               lock (engines) {
                 if (!jobs.ContainsKey(job.Id)) {
@@ -167,7 +171,12 @@
               }
               JobData jobData = wcfService.GetJobData(job.Id);
+              if (job == null) throw new JobDataNotFoundException(jobId);
               job = wcfService.UpdateJobState(job.Id, JobState.Calculating, null);
               StartJobInAppDomain(job, jobData);
-            });
+            }, container.JobId)
+            .ContinueWith((t) => {
+              // handle exception of task
+              clientCom.LogMessage(t.Exception.ToString());
+            }, TaskContinuationOptions.OnlyOnFaulted);
             break;
           case MessageContainer.MessageType.ShutdownSlave:
@@ -203,5 +212,5 @@
         }
       } else {
-        ClientCom.LogMessage("Unknown MessageContainer: " + container);
+        clientCom.LogMessage("Unknown MessageContainer: " + container);
       }
     }
@@ -217,10 +226,10 @@
 
         try {
-          ClientCom.LogMessage("Sending the paused job with id: " + job.Id);
+          clientCom.LogMessage("Sending the paused job with id: " + job.Id);
           wcfService.UpdateJobData(job, sJob, ConfigManager.Instance.GetClientInfo().Id, JobState.Paused);
           SlaveStatusInfo.JobsProcessed++;    //TODO: count or not count, thats the question
         }
         catch (Exception e) {
-          ClientCom.LogMessage("Transmitting to server failed. Storing the paused job with id: " + job.Id + " to hdd (" + e.ToString() + ")");
+          clientCom.LogMessage("Transmitting to server failed. Storing the paused job with id: " + job.Id + " to hdd (" + e.ToString() + ")");
         }
         finally {
@@ -240,10 +249,10 @@
 
         try {
-          ClientCom.LogMessage("Sending the stoppped job with id: " + job.Id);
+          clientCom.LogMessage("Sending the stoppped job with id: " + job.Id);
           wcfService.UpdateJobData(job, sJob, ConfigManager.Instance.GetClientInfo().Id, JobState.Paused);
           SlaveStatusInfo.JobsProcessed++;    //TODO: count or not count, thats the question
         }
         catch (Exception e) {
-          ClientCom.LogMessage("Transmitting to server failed. Storing the paused job with id: " + job.Id + " to hdd (" + e.ToString() + ")");
+          clientCom.LogMessage("Transmitting to server failed. Storing the paused job with id: " + job.Id + " to hdd (" + e.ToString() + ")");
         }
         finally {
@@ -266,5 +275,5 @@
       }
 
-      ClientCom.LogMessage("Aborted all jobs!");
+      clientCom.LogMessage("Aborted all jobs!");
     }
 
@@ -273,5 +282,5 @@
     /// </summary>
     private void DoPauseAll() {
-      ClientCom.LogMessage("Pause all received");
+      clientCom.LogMessage("Pause all received");
 
       //copy guids because there will be removed items from 'Jobs'
@@ -290,5 +299,5 @@
     /// </summary>
     private void DoStopAll() {
-      ClientCom.LogMessage("Stop all received");
+      clientCom.LogMessage("Stop all received");
 
       //copy guids because there will be removed items from 'Jobs'
@@ -316,15 +325,15 @@
     /// </summary>
     private void ShutdownCore() {
-      ClientCom.LogMessage("Shutdown Signal received");
-      ClientCom.LogMessage("Stopping heartbeat");
+      clientCom.LogMessage("Shutdown Signal received");
+      clientCom.LogMessage("Stopping heartbeat");
       heartbeatManager.StopHeartBeat();
       abortRequested = true;
-      ClientCom.LogMessage("Logging out");
+      clientCom.LogMessage("Logging out");
 
 
       lock (engines) {
-        ClientCom.LogMessage("engines locked");
+        clientCom.LogMessage("engines locked");
         foreach (KeyValuePair<Guid, AppDomain> kvp in appDomains) {
-          ClientCom.LogMessage("Shutting down Appdomain for " + kvp.Key);
+          clientCom.LogMessage("Shutting down Appdomain for " + kvp.Key);
           appDomains[kvp.Key].UnhandledException -= new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
           AppDomain.Unload(kvp.Value);
@@ -332,5 +341,5 @@
       }
       WcfService.Instance.Disconnect();
-      ClientCom.Shutdown();
+      clientCom.Shutdown();
       SlaveClientCom.Close();
 
@@ -344,7 +353,7 @@
     /// </summary>  
     private void DoStartSlave() {
-      ClientCom.LogMessage("Restart received");
+      clientCom.LogMessage("Restart received");
       StartHeartbeats();
-      ClientCom.LogMessage("Restart done");
+      clientCom.LogMessage("Restart done");
     }
 
@@ -355,10 +364,10 @@
     //TODO: do we need an AbortSleep?
     private void Sleep() {
-      ClientCom.LogMessage("Sleep received");
+      clientCom.LogMessage("Sleep received");
       heartbeatManager.StopHeartBeat();
       heartbeatManager = null;
       DoStopAll();
       WcfService.Instance.Disconnect();
-      ClientCom.LogMessage("Sleep done");
+      clientCom.LogMessage("Sleep done");
     }
 
@@ -371,5 +380,5 @@
     public void PauseWaitJob(JobData data) {
       if (!Jobs.ContainsKey(data.JobId)) {
-        ClientCom.LogMessage("Can't find job with id " + data.JobId);
+        clientCom.LogMessage("Can't find job with id " + data.JobId);
       } else {
         Job job = Jobs[data.JobId];
@@ -388,11 +397,11 @@
     public void SendFinishedJob(Guid jobId) {
       try {
-        ClientCom.LogMessage("Getting the finished job with id: " + jobId);
+        clientCom.LogMessage("Getting the finished job with id: " + jobId);
         if (!engines.ContainsKey(jobId)) {
-          ClientCom.LogMessage("Engine doesn't exist");
+          clientCom.LogMessage("Engine doesn't exist");
           return;
         }
         if (!jobs.ContainsKey(jobId)) {
-          ClientCom.LogMessage("Job doesn't exist");
+          clientCom.LogMessage("Job doesn't exist");
           return;
         }
@@ -405,10 +414,10 @@
 
         try {
-          ClientCom.LogMessage("Sending the finished job with id: " + jobId);
+          clientCom.LogMessage("Sending the finished job with id: " + jobId);
           wcfService.UpdateJobData(cJob, sJob, ConfigManager.Instance.GetClientInfo().Id, JobState.Finished);
           SlaveStatusInfo.JobsProcessed++;
         }
         catch (Exception e) {
-          ClientCom.LogMessage("Transmitting to server failed. Storing the finished job with id: " + jobId + " to hdd (" + e.ToString() + ")");
+          clientCom.LogMessage("Transmitting to server failed. Storing the finished job with id: " + jobId + " to hdd (" + e.ToString() + ")");
         }
         finally {
@@ -428,5 +437,5 @@
     /// <param name="e"></param>
     private void StartJobInAppDomain(Job myJob, JobData jobData) {
-      ClientCom.LogMessage("Received new job with id " + myJob.Id);
+      clientCom.LogMessage("Received new job with id " + myJob.Id);
       String pluginDir = Path.Combine(PluginCache.Instance.PluginTempBaseDir, myJob.Id.ToString());
       bool pluginsPrepared = false;
@@ -435,9 +444,9 @@
       try {
         PluginCache.Instance.PreparePlugins(myJob, out configFileName);
-        ClientCom.LogMessage("Plugins fetched for job " + myJob.Id);
+        clientCom.LogMessage("Plugins fetched for job " + myJob.Id);
         pluginsPrepared = true;
       }
       catch (Exception exception) {
-        ClientCom.LogMessage(string.Format("Copying plugins for job {0} failed: {1}", myJob.Id, exception));
+        clientCom.LogMessage(string.Format("Copying plugins for job {0} failed: {1}", myJob.Id, exception));
       }
 
@@ -448,19 +457,19 @@
           lock (engines) {
             appDomains.Add(myJob.Id, appDomain);
-            ClientCom.LogMessage("Creating AppDomain");
+            clientCom.LogMessage("Creating AppDomain");
             Executor engine = (Executor)appDomain.CreateInstanceAndUnwrap(typeof(Executor).Assembly.GetName().Name, typeof(Executor).FullName);
-            ClientCom.LogMessage("Created AppDomain");
+            clientCom.LogMessage("Created AppDomain");
             engine.JobId = myJob.Id;
             engine.Core = this;
-            ClientCom.LogMessage("Starting Engine for job " + myJob.Id);
+            clientCom.LogMessage("Starting Engine for job " + myJob.Id);
             engines.Add(myJob.Id, engine);
             engine.Start(jobData.Data);
             SlaveStatusInfo.JobsFetched++;
-            ClientCom.LogMessage("Increment FetchedJobs to:" + SlaveStatusInfo.JobsFetched);
+            clientCom.LogMessage("Increment FetchedJobs to:" + SlaveStatusInfo.JobsFetched);
           }
         }
         catch (Exception exception) {
-          ClientCom.LogMessage("Creating the Appdomain and loading the job failed for job " + myJob.Id);
-          ClientCom.LogMessage("Error thrown is: " + exception.ToString());
+          clientCom.LogMessage("Creating the Appdomain and loading the job failed for job " + myJob.Id);
+          clientCom.LogMessage("Error thrown is: " + exception.ToString());
           KillAppDomain(myJob.Id);
         }
@@ -471,5 +480,5 @@
     public event EventHandler<EventArgs<Exception>> ExceptionOccured;
     private void OnExceptionOccured(Exception e) {
-      ClientCom.LogMessage("Error: " + e.ToString());
+      clientCom.LogMessage("Error: " + e.ToString());
       var handler = ExceptionOccured;
       if (handler != null) handler(this, new EventArgs<Exception>(e));
@@ -477,5 +486,5 @@
 
     private void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
-      ClientCom.LogMessage("Exception in AppDomain: " + e.ExceptionObject.ToString());
+      clientCom.LogMessage("Exception in AppDomain: " + e.ExceptionObject.ToString());
       KillAppDomain(new Guid(e.ExceptionObject.ToString()));
     }
@@ -508,5 +517,5 @@
       }
 
-      ClientCom.LogMessage("Shutting down Appdomain for Job " + id);
+      clientCom.LogMessage("Shutting down Appdomain for Job " + id);
       lock (engines) {
         try {
@@ -526,5 +535,5 @@
               }
               catch (CannotUnloadAppDomainException) {
-                ClientCom.LogMessage("Could not unload AppDomain, will try again in 1 sec.");
+                clientCom.LogMessage("Could not unload AppDomain, will try again in 1 sec.");
                 Thread.Sleep(1000);
                 repeat--;
@@ -542,5 +551,5 @@
         }
         catch (Exception ex) {
-          ClientCom.LogMessage("Exception when unloading the appdomain: " + ex.ToString());
+          clientCom.LogMessage("Exception when unloading the appdomain: " + ex.ToString());
         }
       }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/InvalidStateException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/InvalidStateException.cs	(revision 5786)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/InvalidStateException.cs	(revision 5786)
@@ -0,0 +1,35 @@
+﻿#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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  [global::System.Serializable]
+  public class InvalidStateException : Exception {
+    public InvalidStateException() { }
+    public InvalidStateException(string message) : base(message) { }
+    public InvalidStateException(string message, Exception inner) : base(message, inner) { }
+    protected InvalidStateException(
+    System.Runtime.Serialization.SerializationInfo info,
+    System.Runtime.Serialization.StreamingContext context)
+      : base(info, context) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/JobNotDataFoundException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/JobNotDataFoundException.cs	(revision 5786)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/JobNotDataFoundException.cs	(revision 5786)
@@ -0,0 +1,7 @@
+﻿using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class JobDataNotFoundException : Exception {
+    public JobDataNotFoundException(Guid jobId) : base(string.Format("Job with Id {0} was not found.", jobId)) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/JobNotFoundException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/JobNotFoundException.cs	(revision 5786)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Exceptions/JobNotFoundException.cs	(revision 5786)
@@ -0,0 +1,7 @@
+﻿using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class JobNotFoundException : Exception {
+    public JobNotFoundException(Guid jobId) : base (string.Format("Job with Id {0} was not found.", jobId)) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeuristicLab.Clients.Hive.Slave-3.4.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeuristicLab.Clients.Hive.Slave-3.4.csproj	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeuristicLab.Clients.Hive.Slave-3.4.csproj	(revision 5786)
@@ -98,4 +98,6 @@
   <ItemGroup>
     <Compile Include="ConfigManager.cs" />
+    <Compile Include="Exceptions\JobNotFoundException.cs" />
+    <Compile Include="Exceptions\JobNotDataFoundException.cs" />
     <Compile Include="SlaveClientCom.cs" />
     <Compile Include="Core.cs" />
@@ -103,5 +105,5 @@
     <Compile Include="Executor.cs" />
     <Compile Include="HeartbeatManager.cs" />
-    <Compile Include="InvalidStateException.cs" />
+    <Compile Include="Exceptions\InvalidStateException.cs" />
     <Compile Include="JobStatus.cs" />
     <Compile Include="MessageQueue.cs" />
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/InvalidStateException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/InvalidStateException.cs	(revision 5782)
+++ 	(revision )
@@ -1,35 +1,0 @@
-﻿#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 <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  [global::System.Serializable]
-  public class InvalidStateException : Exception {
-    public InvalidStateException() { }
-    public InvalidStateException(string message) : base(message) { }
-    public InvalidStateException(string message, Exception inner) : base(message, inner) { }
-    protected InvalidStateException(
-    System.Runtime.Serialization.SerializationInfo info,
-    System.Runtime.Serialization.StreamingContext context)
-      : base(info, context) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveExperimentClient.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveExperimentClient.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveExperimentClient.cs	(revision 5786)
@@ -22,17 +22,16 @@
 using System;
 using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
 using System.Linq;
 using System.Threading;
 using HeuristicLab.Clients.Hive.Jobs;
+using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Optimization;
+using HeuristicLab.PluginInfrastructure;
 
 namespace HeuristicLab.Clients.Hive {
-  using System.Configuration;
-  using System.IO;
-  using HeuristicLab.Collections;
-  using HeuristicLab.PluginInfrastructure;
-
   /// <summary>
   /// An experiment which contains multiple batch runs of algorithms.
@@ -378,5 +377,5 @@
 
     #region HiveJob Events
-    void HiveJob_JobStateChanged(object sender, EventArgs e) {
+    private void HiveJob_JobStateChanged(object sender, EventArgs e) {
       if (HiveJob != null) {
         rootJobId = HiveJob.Job.Id;
@@ -520,20 +519,25 @@
         HiveJob hj = hiveJob.GetHiveJobByJobId(lightweightJob.Id);
         if (hj != null) {
+          DateTime lastJobDataUpdate = hj.Job.LastJobDataUpdate;
           hj.UpdateFromLightweightJob(lightweightJob);
-          if ((hj.Job.State == JobState.Aborted ||
-               hj.Job.State == JobState.Failed ||
-               hj.Job.State == JobState.Finished) &&
-              !hj.IsFinishedOptimizerDownloaded) {
+
+          // lastJobDataUpdate equals DateTime.MinValue right after it was uploaded. When the first results are polled, this value is updated
+          if (lastJobDataUpdate != DateTime.MinValue && lastJobDataUpdate < hj.Job.LastJobDataUpdate) {
             LogMessage(hj.Job.Id, "Downloading optimizer for job");
             OptimizerJob optimizerJob = LoadOptimizerJob(hj.Job.Id);
             if (optimizerJob == null) {
               // something bad happened to this job. set to finished to allow the rest beeing downloaded
-              hj.IsFinishedOptimizerDownloaded = true;
+              //hj.IsFinishedOptimizerDownloaded = true;
             } else {
-              if (lightweightJob.ParentJobId.HasValue) {
-                HiveJob parentHiveJob = HiveJob.GetHiveJobByJobId(lightweightJob.ParentJobId.Value);
-                parentHiveJob.UpdateChildOptimizer(optimizerJob, hj.Job.Id);
+              // if the job is paused, download but don't integrate into parent optimizer (to avoid Prepare)
+              if (hj.Job.State == JobState.Paused) {
+                
               } else {
-                this.HiveJob.IsFinishedOptimizerDownloaded = true;
+                if (lightweightJob.ParentJobId.HasValue) {
+                  HiveJob parentHiveJob = HiveJob.GetHiveJobByJobId(lightweightJob.ParentJobId.Value);
+                  parentHiveJob.UpdateChildOptimizer(optimizerJob, hj.Job.Id);
+                } else {
+                  //this.HiveJob.IsFinishedOptimizerDownloaded = true;
+                }
               }
             }
@@ -550,5 +554,8 @@
 
     private bool AllJobsFinished() {
-      return HiveJob.GetAllHiveJobs().All(hj => hj.IsFinishedOptimizerDownloaded);
+      //return HiveJob.GetAllHiveJobs().All(hj => hj.IsFinishedOptimizerDownloaded);
+      return HiveJob.GetAllHiveJobs().All(j => j.Job.State == JobState.Finished
+                                            || j.Job.State == JobState.Aborted
+                                            || j.Job.State == JobState.Failed);
     }
 
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveJobClient.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveJobClient.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/HiveJobClient.cs	(revision 5786)
@@ -77,7 +77,7 @@
           DergisterOptimizerEvents();
           optimizerJob = value;
-          if (optimizerJob.ExecutionState == ExecutionState.Stopped) {
-            IsFinishedOptimizerDownloaded = true;
-          }
+          //if (optimizerJob.ExecutionState == ExecutionState.Stopped) {
+          //  IsFinishedOptimizerDownloaded = true;
+          //}
           RegisterOptimizerEvents();
           OnOptimizerJobChanged();
@@ -91,14 +91,14 @@
     }
 
-    private bool isFinishedOptimizerDownloaded;
-    public bool IsFinishedOptimizerDownloaded {
-      get { return isFinishedOptimizerDownloaded; }
-      set {
-        if (isFinishedOptimizerDownloaded != value) {
-          isFinishedOptimizerDownloaded = value;
-          OnIsFinishedOptimizerDownloadedChanged();
-        }
-      }
-    }
+    //private bool isFinishedOptimizerDownloaded;
+    //public bool IsFinishedOptimizerDownloaded {
+    //  get { return isFinishedOptimizerDownloaded; }
+    //  set {
+    //    if (isFinishedOptimizerDownloaded != value) {
+    //      isFinishedOptimizerDownloaded = value;
+    //      OnIsFinishedOptimizerDownloadedChanged();
+    //    }
+    //  }
+    //}
 
     private bool syncJobsWithOptimizers = true;
@@ -331,5 +331,5 @@
       }
       if (childIsFinishedOptimizerDownloaded) {
-        child.IsFinishedOptimizerDownloaded = true;
+        //child.IsFinishedOptimizerDownloaded = true; // todo: clean up with childIsFinishedOptimizerDownloaded
       }
       syncJobsWithOptimizers = true;
@@ -345,6 +345,38 @@
       }
       foreach (IRun run in optimizerJob.Optimizer.Runs) {
-        if (!batchRun.Runs.Contains(run))
+        if (!batchRun.Runs.Contains(run)) {
+          run.Name = GetNewRunName(run, batchRun.Runs);
           batchRun.Runs.Add(run);
+        }
+      }
+    }
+
+    /// <summary>
+    /// Parses the run numbers out of runs and renames the run to the next number
+    /// </summary>
+    private static string GetNewRunName(IRun run, RunCollection runs) {
+      int idx = run.Name.IndexOf("Run ") + 4;
+
+      if (idx == -1 || runs.Count == 0)
+        return run.Name;
+
+      int maxRunNumber = int.MinValue;
+      foreach (IRun r in runs) {
+        int number = GetRunNumber(r.Name);
+        maxRunNumber = Math.Max(maxRunNumber, number);
+      }
+
+      return run.Name.Substring(0, idx) + (maxRunNumber + 1).ToString();
+    }
+
+    /// <summary>
+    /// Parses the number of a Run out of its name. Example "Genetic Algorithm Run 3" -> 3
+    /// </summary>
+    private static int GetRunNumber(string runName) {
+      int idx = runName.IndexOf("Run ") + 4;
+      if (idx == -1) {
+        return 0;
+      } else {
+        return int.Parse(runName.Substring(idx, runName.Length - idx));
       }
     }
@@ -403,9 +435,11 @@
       if (lightweightJob != null) {
         job.Id = lightweightJob.Id;
-        job.Id = lightweightJob.Id;
+        job.ParentJobId = lightweightJob.ParentJobId;
         job.ExecutionTime = lightweightJob.ExecutionTime;
         job.State = lightweightJob.State;
         job.StateLog = new List<StateLog>(lightweightJob.StateLog);
-        // what about parentJob
+        job.Command = lightweightJob.Command;
+        job.LastJobDataUpdate = lightweightJob.LastJobDataUpdate;
+        
         OnJobStateChanged();
         OnToStringChanged();
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveServiceClient.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveServiceClient.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveServiceClient.cs	(revision 5786)
@@ -94,4 +94,7 @@
         
         [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.DateTime LastJobDataUpdateField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
         private System.Nullable<System.Guid> ParentJobIdField;
         
@@ -132,4 +135,21 @@
                     this.ExecutionTimeField = value;
                     this.RaisePropertyChanged("ExecutionTime");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.DateTime LastJobDataUpdate
+        {
+            get
+            {
+                return this.LastJobDataUpdateField;
+            }
+            set
+            {
+                if ((this.LastJobDataUpdateField.Equals(value) != true))
+                {
+                    this.LastJobDataUpdateField = value;
+                    this.RaisePropertyChanged("LastJobDataUpdate");
                 }
             }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/LightweightJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/LightweightJob.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/LightweightJob.cs	(revision 5786)
@@ -43,4 +43,5 @@
       this.State = job.State;
       this.Command = job.Command;
+      this.LastJobDataUpdate = job.LastJobDataUpdate;
     }
 
@@ -52,4 +53,5 @@
       this.State = original.State;
       this.Command = original.Command;
+      this.LastJobDataUpdate = original.LastJobDataUpdate;
     }
     public override IDeepCloneable Clone(Cloner cloner) {
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/ApplicationConstants.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/ApplicationConstants.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/ApplicationConstants.cs	(revision 5786)
@@ -33,10 +33,14 @@
     public static System.Transactions.IsolationLevel IsolationLevelScope = System.Transactions.IsolationLevel.ReadUncommitted;
 
-    public static int HeartbeatTimeout = 120; // value in seconds
+    public static TimeSpan SlaveHeartbeatTimeout = TimeSpan.FromMinutes(1);
+
+    public static TimeSpan CalculatingJobHeartbeatTimeout = TimeSpan.FromMinutes(1);
+
+    public static TimeSpan TransferringJobHeartbeatTimeout = TimeSpan.FromMinutes(5);
 
     /// <summary>
     /// Interval in which the HL.HiveExperiment will poll results from server
     /// </summary>
-    public static TimeSpan ResultPollingInterval = new TimeSpan(0, 0, 5);
+    public static TimeSpan ResultPollingInterval = TimeSpan.FromSeconds(5);
 
     /// <summary>
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/LightweightJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/LightweightJob.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/DataTransfer/LightweightJob.cs	(revision 5786)
@@ -39,4 +39,6 @@
     [DataMember]
     public Command? Command { get; set; }
+    [DataMember]
+    public DateTime LastJobDataUpdate { get; set; }
 
     public StateLog CurrentStateLog { get { return StateLog.LastOrDefault(); } }
@@ -55,4 +57,5 @@
       this.State = job.State;
       this.Command = job.Command;
+      this.LastJobDataUpdate = job.LastJobDataUpdate;
     }
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/Convert.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/Convert.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/Convert.cs	(revision 5786)
@@ -43,5 +43,6 @@
         IsParentJob = source.IsParentJob,
         FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished,
-        Command = source.Command
+        Command = source.Command,
+        LastJobDataUpdate = source.JobData.LastUpdate
       };
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/HiveDao.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/HiveDao.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/HiveDao.cs	(revision 5786)
@@ -35,6 +35,5 @@
     }
 
-    public HiveDao() {
-    }
+    public HiveDao() { }
 
     #region Job Methods
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/DaoTests.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/DaoTests.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/DaoTests.cs	(revision 5786)
@@ -32,4 +32,8 @@
       job1.Command = Command.Pause;
 
+      DT.JobData jobData1 = new DT.JobData();
+      jobData1.Data = new byte[] { 0, 1, 2, 3, 4, 5 };
+      jobData1.LastUpdate = DateTime.Now;
+
       DT.Plugin plugin1 = new DT.Plugin();
       plugin1.Name = "Tests.MyPlugin";
@@ -51,4 +55,6 @@
 
       job1.Id = dao.AddJob(job1);
+      jobData1.JobId = job1.Id;
+      dao.AddJobData(jobData1);
 
       DT.Job job1loaded = dao.GetJob(job1.Id);
@@ -60,4 +66,5 @@
       Assert.AreEqual(job1.StateLog.Count, job1loaded.StateLog.Count);
       Assert.AreEqual(job1.Command, job1loaded.Command);
+      Assert.IsTrue(Math.Abs((job1loaded.LastJobDataUpdate - jobData1.LastUpdate).TotalSeconds) < 1);
       for (int i = 0; i < job1.StateLog.Count; i++) {
         Assert.AreEqual(job1.Id, job1loaded.StateLog[i].JobId);
@@ -88,7 +95,13 @@
       }
 
+      DT.JobData jobData1Loaded = dao.GetJobData(job1.Id);
+      Assert.AreEqual(jobData1.JobId, jobData1Loaded.JobId);
+      Assert.IsTrue(Math.Abs((jobData1.LastUpdate - jobData1Loaded.LastUpdate).TotalSeconds) < 1);
+      Assert.IsTrue(jobData1.Data.SequenceEqual(jobData1Loaded.Data));
+      
       dao.DeleteJob(job1.Id);
 
       Assert.AreEqual(null, dao.GetJob(job1.Id));
+      Assert.AreEqual(null, dao.GetJobData(job1.Id));
     }
 
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs	(revision 5786)
@@ -52,6 +52,10 @@
 
     private void AssignJob(Slave slave, Job job) {
-      dao.UpdateJobState(job.Id, JobState.Transferring, slave.Id, null, null);
+      job = dao.UpdateJobState(job.Id, JobState.Transferring, slave.Id, null, null);
       dao.UpdateSlave(slave);
+
+      // from now on the job has some time to send the next heartbeat (ApplicationConstants.TransferringJobHeartbeatTimeout)
+      job.LastHeartbeat = DateTime.Now;
+      dao.UpdateJob(job);
     }
 
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs	(revision 5786)
@@ -25,5 +25,6 @@
       log.Log("LifecycleManager.Cleanup()");
       SetTimeoutSlavesOffline();
-      FinishParentJobs();
+      SetTimeoutJobsWaiting();
+      FinishParentJobs();      
     }
 
@@ -34,5 +35,5 @@
       var slaves = dao.GetSlaves(x => x.SlaveState != SlaveState.Offline);
       foreach (Slave slave in slaves) {
-        if (!slave.LastHeartbeat.HasValue || (DateTime.Now - slave.LastHeartbeat.Value).TotalSeconds > ApplicationConstants.HeartbeatTimeout) {
+        if (!slave.LastHeartbeat.HasValue || (DateTime.Now - slave.LastHeartbeat.Value) > ApplicationConstants.SlaveHeartbeatTimeout) {
           slave.SlaveState = SlaveState.Offline;
           SetJobsWaiting(slave.Id);
@@ -55,5 +56,5 @@
       var jobs = dao.GetJobs(x => x.State == JobState.Calculating).Where(x => x.StateLog.Last().SlaveId == slaveId);
       foreach (var j in jobs) {
-        Job job = dao.UpdateJobState(j.Id, JobState.Waiting, slaveId, null, "Slave timed out");
+        Job job = dao.UpdateJobState(j.Id, JobState.Waiting, slaveId, null, "Slave timed out.");
         job.Command = null;
         dao.UpdateJob(job);
@@ -61,4 +62,16 @@
     }
 
+    /// <summary>
+    /// Looks for jobs which have not sent heartbeats for some time and reschedules them for calculation
+    /// </summary>
+    private void SetTimeoutJobsWaiting() {
+      var jobs = dao.GetJobs(x => (x.State == JobState.Calculating && (DateTime.Now - x.LastHeartbeat) > ApplicationConstants.CalculatingJobHeartbeatTimeout) 
+                               || (x.State == JobState.Transferring && (DateTime.Now - x.LastHeartbeat) > ApplicationConstants.TransferringJobHeartbeatTimeout));
+      foreach (var j in jobs) {
+        Job job = dao.UpdateJobState(j.Id, JobState.Waiting, null, null, "Slave timed out.");
+        job.Command = null;
+        dao.UpdateJob(job);
+      }
+    }
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/MergeConfigs.cmd
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/MergeConfigs.cmd	(revision 5782)
+++ branches/HeuristicLab.Hive-3.4/sources/MergeConfigs.cmd	(revision 5786)
@@ -1,5 +1,4 @@
 copy "%SolutionDir%HeuristicLab.Hive 3.4.dll.config" "%TargetDir%"
 
-%SolutionDir%ConfigMerger "%SolutionDir%HeuristicLab.Services.Hive\3.4\app.config" "%TargetDir%HeuristicLab.Hive 3.4.dll.config"
 %SolutionDir%ConfigMerger "%SolutionDir%HeuristicLab.Services.Hive.DataAccess\3.4\app.config" "%TargetDir%HeuristicLab.Hive 3.4.dll.config"
 %SolutionDir%ConfigMerger "%SolutionDir%HeuristicLab.Clients.Hive\3.4\app.config" "%TargetDir%HeuristicLab.Hive 3.4.dll.config"
