Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 15630)
@@ -144,6 +144,8 @@
         }
       } else {
-        if (item is Job)
-          HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJob((Job)item));
+        if (item is Job) {
+          var job = (Job)item;
+          HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJob(job, job.ResourceIds));
+        }
         if (item is Project)
           HiveServiceLocator.Instance.CallHiveService(s => s.UpdateProject((Project)item));
@@ -173,5 +175,5 @@
 
       if (item is Job)
-        HiveServiceLocator.Instance.CallHiveService(s => s.DeleteJob(item.Id));
+        HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJobState(item.Id, JobState.StatisticsPending));
       if (item is RefreshableJob) {
         RefreshableJob job = (RefreshableJob)item;
@@ -179,5 +181,5 @@
           job.StopResultPolling();
         }
-        HiveServiceLocator.Instance.CallHiveService(s => s.DeleteJob(item.Id));
+        HiveServiceLocator.Instance.CallHiveService(s => s.UpdateJobState(item.Id, JobState.StatisticsPending));
       }
       if (item is JobPermission) {
@@ -262,5 +264,5 @@
         // upload Job
         refreshableJob.Progress.Status = "Uploading Job...";
-        refreshableJob.Job.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddJob(refreshableJob.Job));
+        refreshableJob.Job.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddJob(refreshableJob.Job, refreshableJob.Job.ResourceIds));
         refreshableJob.Job = HiveServiceLocator.Instance.CallHiveService((s) => s.GetJob(refreshableJob.Job.Id)); // update owner and permissions
         cancellationToken.ThrowIfCancellationRequested();
@@ -284,5 +286,5 @@
         foreach (HiveTask hiveTask in refreshableJob.HiveTasks) {
           var task = TS.Task.Factory.StartNew((hj) => {
-            UploadTaskWithChildren(refreshableJob.Progress, (HiveTask)hj, null, refreshableJob.Job.ResourceIds, jobCount, totalJobCount, configFilePlugin.Id, refreshableJob.Job.Id, refreshableJob.Log, cancellationToken);
+            UploadTaskWithChildren(refreshableJob.Progress, (HiveTask)hj, null, jobCount, totalJobCount, configFilePlugin.Id, refreshableJob.Job.Id, refreshableJob.Log, cancellationToken);
           }, hiveTask);
           task.ContinueWith((x) => refreshableJob.Log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted);
@@ -329,5 +331,5 @@
     /// </summary>
     /// <param name="parentHiveTask">shall be null if its the root task</param>
-    private void UploadTaskWithChildren(IProgress progress, HiveTask hiveTask, HiveTask parentHiveTask, IEnumerable<Guid> groups, int[] taskCount, int totalJobCount, Guid configPluginId, Guid jobId, ILog log, CancellationToken cancellationToken) {
+    private void UploadTaskWithChildren(IProgress progress, HiveTask hiveTask, HiveTask parentHiveTask, int[] taskCount, int totalJobCount, Guid configPluginId, Guid jobId, ILog log, CancellationToken cancellationToken) {
       taskUploadSemaphore.WaitOne();
       bool semaphoreReleased = false;
@@ -368,5 +370,5 @@
               hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddChildTask(parentHiveTask.Task.Id, hiveTask.Task, taskData));
             } else {
-              hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddTask(hiveTask.Task, taskData, groups.ToList()));
+              hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddTask(hiveTask.Task, taskData));
             }
           }
@@ -383,5 +385,5 @@
           var task = TS.Task.Factory.StartNew((tuple) => {
             var arguments = (Tuple<HiveTask, HiveTask>)tuple;
-            UploadTaskWithChildren(progress, arguments.Item1, arguments.Item2, groups, taskCount, totalJobCount, configPluginId, jobId, log, cancellationToken);
+            UploadTaskWithChildren(progress, arguments.Item1, arguments.Item2, taskCount, totalJobCount, configPluginId, jobId, log, cancellationToken);
           }, new Tuple<HiveTask, HiveTask>(child, hiveTask));
           task.ContinueWith((x) => log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted);
@@ -390,9 +392,81 @@
         taskUploadSemaphore.Release(); semaphoreReleased = true; // the semaphore has to be release before waitall!
         TS.Task.WaitAll(tasks.ToArray());
-      }
-      finally {
+      } finally {
         if (!semaphoreReleased) taskUploadSemaphore.Release();
       }
     }
+
+
+    /// <summary>
+    /// Uploads the given task and all its child-jobs while setting the proper parentJobId values for the childs
+    /// </summary>
+    /// <param name="parentHiveTask">shall be null if its the root task</param>
+    //private void UploadTaskWithChildren_Old(IProgress progress, HiveTask hiveTask, HiveTask parentHiveTask, IEnumerable<Guid> groups, int[] taskCount, int totalJobCount, Guid configPluginId, Guid jobId, ILog log, CancellationToken cancellationToken) {
+    //  taskUploadSemaphore.WaitOne();
+    //  bool semaphoreReleased = false;
+    //  try {
+    //    cancellationToken.ThrowIfCancellationRequested();
+    //    lock (jobCountLocker) {
+    //      taskCount[0]++;
+    //    }
+    //    TaskData taskData;
+    //    List<IPluginDescription> plugins;
+
+    //    if (hiveTask.ItemTask.ComputeInParallel) {
+    //      hiveTask.Task.IsParentTask = true;
+    //      hiveTask.Task.FinishWhenChildJobsFinished = true;
+    //      taskData = hiveTask.GetAsTaskData(true, out plugins);
+    //    } else {
+    //      hiveTask.Task.IsParentTask = false;
+    //      hiveTask.Task.FinishWhenChildJobsFinished = false;
+    //      taskData = hiveTask.GetAsTaskData(false, out plugins);
+    //    }
+    //    cancellationToken.ThrowIfCancellationRequested();
+
+    //    TryAndRepeat(() => {
+    //      if (!cancellationToken.IsCancellationRequested) {
+    //        lock (pluginLocker) {
+    //          HiveServiceLocator.Instance.CallHiveService((s) => hiveTask.Task.PluginsNeededIds = PluginUtil.GetPluginDependencies(s, this.onlinePlugins, this.alreadyUploadedPlugins, plugins));
+    //        }
+    //      }
+    //    }, Settings.Default.MaxRepeatServiceCalls, "Failed to upload plugins");
+    //    cancellationToken.ThrowIfCancellationRequested();
+    //    hiveTask.Task.PluginsNeededIds.Add(configPluginId);
+    //    hiveTask.Task.JobId = jobId;
+
+    //    log.LogMessage(string.Format("Uploading task ({0} kb, {1} objects)", taskData.Data.Count() / 1024, hiveTask.ItemTask.GetObjectGraphObjects().Count()));
+    //    TryAndRepeat(() => {
+    //      if (!cancellationToken.IsCancellationRequested) {
+    //        if (parentHiveTask != null) {
+    //          hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddChildTask(parentHiveTask.Task.Id, hiveTask.Task, taskData));
+    //        } else {
+    //          hiveTask.Task.Id = HiveServiceLocator.Instance.CallHiveService((s) => s.AddTask(hiveTask.Task, taskData, groups.ToList()));
+    //        }
+    //      }
+    //    }, Settings.Default.MaxRepeatServiceCalls, "Failed to add task", log);
+    //    cancellationToken.ThrowIfCancellationRequested();
+
+    //    lock (jobCountLocker) {
+    //      progress.ProgressValue = (double)taskCount[0] / totalJobCount;
+    //      progress.Status = string.Format("Uploaded task ({0} of {1})", taskCount[0], totalJobCount);
+    //    }
+
+    //    var tasks = new List<TS.Task>();
+    //    foreach (HiveTask child in hiveTask.ChildHiveTasks) {
+    //      var task = TS.Task.Factory.StartNew((tuple) => {
+    //        var arguments = (Tuple<HiveTask, HiveTask>)tuple;
+    //        UploadTaskWithChildren_Old(progress, arguments.Item1, arguments.Item2, groups, taskCount, totalJobCount, configPluginId, jobId, log, cancellationToken);
+    //      }, new Tuple<HiveTask, HiveTask>(child, hiveTask));
+    //      task.ContinueWith((x) => log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted);
+    //      tasks.Add(task);
+    //    }
+    //    taskUploadSemaphore.Release(); semaphoreReleased = true; // the semaphore has to be release before waitall!
+    //    TS.Task.WaitAll(tasks.ToArray());
+    //  }
+    //  finally {
+    //    if (!semaphoreReleased) taskUploadSemaphore.Release();
+    //  }
+    //}
+    
     #endregion
 
Index: branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 15630)
@@ -27,4 +27,5 @@
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Plugin))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.Project))]
+    [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.AssignedJobResource))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.JobPermission))]
     [System.Runtime.Serialization.KnownTypeAttribute(typeof(HeuristicLab.Clients.Hive.PluginData))]
@@ -74,5 +75,5 @@
         
         public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
-
+        
     }
     
@@ -290,4 +291,7 @@
         private System.Guid ProjectIdField;
         
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private HeuristicLab.Clients.Hive.JobState StateField;
+        
         [System.Runtime.Serialization.DataMemberAttribute()]
         public int CalculatingCount
@@ -422,4 +426,21 @@
                     this.ProjectIdField = value;
                     this.RaisePropertyChanged("ProjectId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public HeuristicLab.Clients.Hive.JobState State
+        {
+            get
+            {
+                return this.StateField;
+            }
+            set
+            {
+                if ((this.StateField.Equals(value) != true))
+                {
+                    this.StateField = value;
+                    this.RaisePropertyChanged("State");
                 }
             }
@@ -951,4 +972,52 @@
     [System.Diagnostics.DebuggerStepThroughAttribute()]
     [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="AssignedJobResource", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    [System.SerializableAttribute()]
+    public partial class AssignedJobResource : HeuristicLab.Clients.Hive.HiveItem
+    {
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid JobIdField;
+        
+        [System.Runtime.Serialization.OptionalFieldAttribute()]
+        private System.Guid ResourceIdField;
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid JobId
+        {
+            get
+            {
+                return this.JobIdField;
+            }
+            set
+            {
+                if ((this.JobIdField.Equals(value) != true))
+                {
+                    this.JobIdField = value;
+                    this.RaisePropertyChanged("JobId");
+                }
+            }
+        }
+        
+        [System.Runtime.Serialization.DataMemberAttribute()]
+        public System.Guid ResourceId
+        {
+            get
+            {
+                return this.ResourceIdField;
+            }
+            set
+            {
+                if ((this.ResourceIdField.Equals(value) != true))
+                {
+                    this.ResourceIdField = value;
+                    this.RaisePropertyChanged("ResourceId");
+                }
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
     [System.Runtime.Serialization.DataContractAttribute(Name="JobPermission", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
     [System.SerializableAttribute()]
@@ -1772,4 +1841,19 @@
         [System.Runtime.Serialization.EnumMemberAttribute()]
         Full = 2,
+    }
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
+    [System.Runtime.Serialization.DataContractAttribute(Name="JobState", Namespace="http://schemas.datacontract.org/2004/07/HeuristicLab.Services.Hive.DataTransfer")]
+    public enum JobState : int
+    {
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        Online = 0,
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        StatisticsPending = 1,
+        
+        [System.Runtime.Serialization.EnumMemberAttribute()]
+        DeletionPending = 2,
     }
     
@@ -2260,5 +2344,5 @@
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddTask", ReplyAction="http://tempuri.org/IHiveService/AddTaskResponse")]
-        System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData, System.Collections.Generic.List<System.Guid> resourceIds);
+        System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddChildTask", ReplyAction="http://tempuri.org/IHiveService/AddChildTaskResponse")]
@@ -2302,11 +2386,14 @@
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddJob", ReplyAction="http://tempuri.org/IHiveService/AddJobResponse")]
-        System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto);
+        System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateJob", ReplyAction="http://tempuri.org/IHiveService/UpdateJobResponse")]
-        void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto);
-        
-        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/DeleteJob", ReplyAction="http://tempuri.org/IHiveService/DeleteJobResponse")]
-        void DeleteJob(System.Guid JobId);
+        void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UpdateJobState", ReplyAction="http://tempuri.org/IHiveService/UpdateJobStateResponse")]
+        void UpdateJobState(System.Guid JobId, HeuristicLab.Clients.Hive.JobState jobState);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForJob", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForJobResponse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedJobResource> GetAssignedResourcesForJob(System.Guid jobId);
         
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GrantPermission", ReplyAction="http://tempuri.org/IHiveService/GrantPermissionResponse")]
@@ -2386,4 +2473,8 @@
         System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProject(System.Guid projectId);
         
+        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectAdministration", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectAdministrationRespo" +
+            "nse")]
+        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(System.Guid projectId);
+        
         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddSlave", ReplyAction="http://tempuri.org/IHiveService/AddSlaveResponse")]
         System.Guid AddSlave(HeuristicLab.Clients.Hive.Slave slave);
@@ -2487,7 +2578,7 @@
         }
         
-        public System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData, System.Collections.Generic.List<System.Guid> resourceIds)
-        {
-            return base.Channel.AddTask(task, taskData, resourceIds);
+        public System.Guid AddTask(HeuristicLab.Clients.Hive.Task task, HeuristicLab.Clients.Hive.TaskData taskData)
+        {
+            return base.Channel.AddTask(task, taskData);
         }
         
@@ -2557,17 +2648,22 @@
         }
         
-        public System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto)
-        {
-            return base.Channel.AddJob(jobDto);
-        }
-        
-        public void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto)
-        {
-            base.Channel.UpdateJob(jobDto);
-        }
-        
-        public void DeleteJob(System.Guid JobId)
-        {
-            base.Channel.DeleteJob(JobId);
+        public System.Guid AddJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds)
+        {
+            return base.Channel.AddJob(jobDto, resourceIds);
+        }
+        
+        public void UpdateJob(HeuristicLab.Clients.Hive.Job jobDto, System.Collections.Generic.List<System.Guid> resourceIds)
+        {
+            base.Channel.UpdateJob(jobDto, resourceIds);
+        }
+        
+        public void UpdateJobState(System.Guid JobId, HeuristicLab.Clients.Hive.JobState jobState)
+        {
+            base.Channel.UpdateJobState(JobId, jobState);
+        }
+        
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedJobResource> GetAssignedResourcesForJob(System.Guid jobId)
+        {
+            return base.Channel.GetAssignedResourcesForJob(jobId);
         }
         
@@ -2697,4 +2793,9 @@
         }
         
+        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(System.Guid projectId)
+        {
+            return base.Channel.GetAssignedResourcesForProjectAdministration(projectId);
+        }
+        
         public System.Guid AddSlave(HeuristicLab.Clients.Hive.Slave slave)
         {
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/AssignedJobResourceDao.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/AssignedJobResourceDao.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/AssignedJobResourceDao.cs	(revision 15630)
@@ -159,5 +159,5 @@
       )
       SELECT COUNT(ajr.JobId)
-      FROM rbranch, AssignedJobResource ajr
+      FROM rbranch, [AssignedJobResource] ajr
       WHERE rbranch.ResourceId = ajr.ResourceId
       AND ajr.JobId = {0}
@@ -174,5 +174,5 @@
       )
       SELECT COUNT(ajr.JobId)
-      FROM rbranch, AssignedJobResource ajr, Task t
+      FROM rbranch, [AssignedJobResource] ajr, [Task] t
       WHERE rbranch.ResourceId = ajr.ResourceId
       AND ajr.JobId = t.JobId
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/JobDao.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/JobDao.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/JobDao.cs	(revision 15630)
@@ -21,4 +21,5 @@
 
 using System;
+using System.Collections.Generic;
 using System.Data.Linq;
 using System.Linq;
@@ -31,4 +32,17 @@
       return GetByIdQuery(DataContext, id);
     }
+    
+    public void DeleteByState(JobState state) {
+      DataContext.ExecuteCommand(DeleteByStateQueryString, Enum.GetName(typeof(JobState), state));
+    }
+
+    public IEnumerable<Job> GetByState(JobState state) {
+      return GetByStateQuery(DataContext, state);
+    }
+
+    public IEnumerable<Guid> GetJobIdsByState(JobState state) {
+      return GetJobIdsByStateQuery(DataContext, state);
+    }
+
 
     #region Compiled queries
@@ -38,4 +52,21 @@
          where job.JobId == jobId
          select job).SingleOrDefault());
+    private static readonly Func<DataContext, JobState, IEnumerable<Job>> GetByStateQuery =
+      CompiledQuery.Compile((DataContext db, JobState jobState) =>
+        (from job in db.GetTable<Job>()
+         where job.State == jobState
+         select job).ToList());
+    private static readonly Func<DataContext, JobState, IEnumerable<Guid>> GetJobIdsByStateQuery =
+      CompiledQuery.Compile((DataContext db, JobState jobState) =>
+        (from job in db.GetTable<Job>()
+         where job.State == jobState
+         select job.JobId).ToList());
+    #endregion
+
+    #region String queries
+    private const string DeleteByStateQueryString = @"
+      DELETE FROM [Job]
+      WHERE JobState = {0}
+    ";
     #endregion
   }
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/TaskDao.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/TaskDao.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/TaskDao.cs	(revision 15630)
@@ -54,5 +54,9 @@
       //Because there is at the moment no case where this makes sense (there don't exist parent tasks which need to be calculated), 
       //we skip this step because it's wasted runtime
-      return DataContext.ExecuteQuery<TaskPriorityInfo>(GetWaitingTasksQueryString, slave.ResourceId, Enum.GetName(typeof(TaskState), TaskState.Waiting), slave.FreeCores, slave.FreeMemory).ToList();
+      return DataContext.ExecuteQuery<TaskPriorityInfo>(GetWaitingTasksQueryString, 
+        slave.ResourceId, 
+        Enum.GetName(typeof(TaskState), TaskState.Waiting), 
+        slave.FreeCores, 
+        slave.FreeMemory).ToList();
     }
 
@@ -88,5 +92,5 @@
     /// <param name="resourceIds">list of resourceids which for which the task should be valid</param>
     /// <param name="count">maximum number of task to return</param>
-    /// <param name="finished">if true, all parent task which have FinishWhenChildJobsFinished=true are returned, otherwise only FinishWhenChildJobsFinished=false are returned</param>
+    /// <param name="finished">if true, all parent tasks which have FinishWhenChildJobsFinished=true are returned, otherwise only FinishWhenChildJobsFinished=false are returned</param>
     /// <returns></returns>
     public IEnumerable<Task> GetParentTasks(IEnumerable<Guid> resourceIds, int count, bool finished) {
@@ -129,4 +133,25 @@
     ";
     private const string GetWaitingTasksQueryString = @"
+      WITH rbranch AS (
+        SELECT ResourceId, ParentResourceId
+        FROM [Resource]
+        WHERE ResourceId = {0}
+        UNION ALL
+        SELECT r.ResourceId, r.ParentResourceId
+        FROM [Resource] r
+        JOIN rbranch rb ON rb.ParentResourceId = r.ResourceId
+      )
+      SELECT DISTINCT t.TaskId, t.JobId, t.Priority
+      FROM [Task] t, [Job] j, [AssignedJobResource] ajr, rbranch
+      WHERE NOT (t.IsParentTask = 1 AND t.FinishWhenChildJobsFinished = 1)
+      AND t.TaskState = {1}
+      AND t.CoresNeeded <= {2}
+      AND t.MemoryNeeded <= {3}
+      AND t.JobId = j.JobId
+      AND j.JobState = 'Online'
+      AND j.JobId = ajr.JobId
+      AND ajr.ResourceId = rbranch.ResourceId
+    ";
+    private const string GetWaitingTasksQueryStringOld = @"
       WITH pr AS (
         SELECT ResourceId, ParentResourceId
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Enums/JobState.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Enums/JobState.cs	(revision 15630)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/Enums/JobState.cs	(revision 15630)
@@ -0,0 +1,45 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2018 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.Services.Hive.DataAccess {
+  [Serializable]
+  public enum JobState {
+    /// <summary>
+    /// A job is online as long as he is no other state.
+    /// </summary>
+    Online,
+
+    /// <summary>
+    /// A job is in StatisticsPending if its deletion has been requested,
+    /// but the final generation of statistics hasn't been performed yet.
+    /// </summary>
+    StatisticsPending,
+
+    /// <summary>
+    /// A job is in DeletionPending if its deletion has been requested,
+    /// the final generation of statistics has already been performed,
+    /// but the eventual deletion of the job is still pending. 
+    /// </summary>
+    DeletionPending
+  };
+}
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HeuristicLab.Services.Hive.DataAccess-3.3.csproj
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HeuristicLab.Services.Hive.DataAccess-3.3.csproj	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HeuristicLab.Services.Hive.DataAccess-3.3.csproj	(revision 15630)
@@ -131,4 +131,5 @@
     <Compile Include="Daos\UserPriorityDao.cs" />
     <Compile Include="Data\TableInformation.cs" />
+    <Compile Include="Enums\JobState.cs" />
     <Compile Include="Interfaces\IGenericDao.cs" />
     <Compile Include="Enums\Command.cs" />
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml	(revision 15630)
@@ -106,4 +106,5 @@
       <Column Name="DateCreated" Type="System.DateTime" DbType="DateTime" CanBeNull="false" />
       <Column Name="ProjectId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" CanBeNull="false" />
+      <Column Name="JobState" Member="State" Type="global::HeuristicLab.Services.Hive.DataAccess.JobState" DbType="VarChar(30)" CanBeNull="false" />
       <Association Name="Job_Task" Member="Tasks" Storage="_Jobs" ThisKey="JobId" OtherKey="JobId" Type="Task" />
       <Association Name="Job_JobPermission" Member="JobPermissions" Storage="_HiveExperimentPermissions" ThisKey="JobId" OtherKey="JobId" Type="JobPermission" />
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout	(revision 15630)
@@ -39,8 +39,8 @@
       </nestedChildShapes>
     </classShape>
-    <classShape Id="e6f840cc-2968-4be1-b234-eef624ccacbb" absoluteBounds="4.125, 2.625, 2, 1.9631982421874996">
+    <classShape Id="e6f840cc-2968-4be1-b234-eef624ccacbb" absoluteBounds="4.125, 2.625, 2, 2.1554996744791666">
       <DataClassMoniker Name="/HiveDataContext/Job" />
       <nestedChildShapes>
-        <elementListCompartment Id="0c65d4e1-256a-4a91-9a57-392f25e4de7f" absoluteBounds="4.1400000000000006, 3.0850000000000009, 1.9700000000000002, 1.4031982421875" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
+        <elementListCompartment Id="0c65d4e1-256a-4a91-9a57-392f25e4de7f" absoluteBounds="4.1400000000000006, 3.0850000000000009, 1.9700000000000002, 1.5954996744791665" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
       </nestedChildShapes>
     </classShape>
@@ -155,5 +155,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(6.5 : 2.50564697265625); (3.75 : 2.50564697265625)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(6.5 : 2.50564697265625); (3.75 : 2.50564697265625)]" fixedFrom="Algorithm" fixedTo="Algorithm">
       <AssociationMoniker Name="/HiveDataContext/Task/Task_StateLog" />
       <nodes>
@@ -162,5 +162,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(6.125 : 3.37100341796875); (6.5 : 3.37100341796875)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(6.125 : 3.37100341796875); (6.5 : 3.37100341796875)]" fixedFrom="Algorithm" fixedTo="Algorithm">
       <AssociationMoniker Name="/HiveDataContext/Job/Job_Task" />
       <nodes>
@@ -169,5 +169,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(4.125 : 4.10659912109375); (3.75 : 4.10659912109375)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(4.125 : 4.20274983723958); (3.75 : 4.20274983723958)]" fixedFrom="Algorithm" fixedTo="Algorithm">
       <AssociationMoniker Name="/HiveDataContext/Job/Job_JobPermission" />
       <nodes>
@@ -279,5 +279,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(11.25 : 9.42390055338542); (10.375 : 9.42390055338542); (10.375 : 8); (4 : 8); (4 : 4.9631982421875); (5.125 : 4.9631982421875); (5.125 : 4.5881982421875)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(11.25 : 9.42390055338542); (10.375 : 9.42390055338542); (10.375 : 8); (4 : 8); (4 : 5.15549967447917); (4.80957165625 : 5.15549967447917); (4.80957165625 : 4.78049967447917)]" fixedFrom="Algorithm" fixedTo="Algorithm">
       <AssociationMoniker Name="/HiveDataContext/Project/Project_Job" />
       <nodes>
@@ -333,5 +333,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(5.656252 : 4.5881982421875); (5.656252 : 5.07535062109375); (8.875 : 5.07535062109375)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(5.498537828125 : 4.78049967447917); (5.498537828125 : 5.14024983723958); (7.41666666666667 : 5.14024983723958 : JumpStart); (7.58333333333333 : 5.14024983723958 : JumpEnd); (8.875 : 5.14024983723958)]" fixedFrom="Algorithm" fixedTo="Algorithm">
       <AssociationMoniker Name="/HiveDataContext/Job/Job_AssignedJobResource" />
       <nodes>
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs	(revision 15630)
@@ -390,5 +390,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Resource_AssignedProjectResource", Storage="_Resource", ThisKey="ResourceId", OtherKey="ResourceId", IsForeignKey=true, DeleteOnNull=true)]
+		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Resource_AssignedProjectResource", Storage="_Resource", ThisKey="ResourceId", OtherKey="ResourceId", IsForeignKey=true, DeleteRule="CASCADE")]
 		public Resource Resource
 		{
@@ -424,5 +424,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_AssignedProjectResource", Storage="_Project", ThisKey="ProjectId", OtherKey="ProjectId", IsForeignKey=true, DeleteOnNull=true)]
+		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_AssignedProjectResource", Storage="_Project", ThisKey="ProjectId", OtherKey="ProjectId", IsForeignKey=true, DeleteRule="CASCADE")]
 		public Project Project
 		{
@@ -2486,4 +2486,6 @@
 		private System.Guid _ProjectId;
 		
+		private global::HeuristicLab.Services.Hive.DataAccess.JobState _State;
+		
 		private EntitySet<Task> _Jobs;
 		
@@ -2510,4 +2512,6 @@
     partial void OnProjectIdChanging(System.Guid value);
     partial void OnProjectIdChanged();
+    partial void OnStateChanging(global::HeuristicLab.Services.Hive.DataAccess.JobState value);
+    partial void OnStateChanged();
     #endregion
 		
@@ -2641,4 +2645,24 @@
 					this.SendPropertyChanged("ProjectId");
 					this.OnProjectIdChanged();
+				}
+			}
+		}
+		
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Name="JobState", Storage="_State", DbType="VarChar(30)", CanBeNull=false)]
+		public global::HeuristicLab.Services.Hive.DataAccess.JobState State
+		{
+			get
+			{
+				return this._State;
+			}
+			set
+			{
+				if ((this._State != value))
+				{
+					this.OnStateChanging(value);
+					this.SendPropertyChanging();
+					this._State = value;
+					this.SendPropertyChanged("State");
+					this.OnStateChanged();
 				}
 			}
@@ -5809,5 +5833,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_AssignedProjectResource", Storage="_AssignedResources", ThisKey="ProjectId", OtherKey="ProjectId", DeleteRule="CASCADE")]
+		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_AssignedProjectResource", Storage="_AssignedResources", ThisKey="ProjectId", OtherKey="ProjectId")]
 		public EntitySet<AssignedProjectResource> AssignedProjectResources
 		{
@@ -5848,5 +5872,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_ProjectPermission", Storage="_ProjectPermissions", ThisKey="ProjectId", OtherKey="ProjectId", DeleteRule="CASCADE")]
+		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_ProjectPermission", Storage="_ProjectPermissions", ThisKey="ProjectId", OtherKey="ProjectId")]
 		public EntitySet<ProjectPermission> ProjectPermissions
 		{
@@ -6060,5 +6084,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_ProjectPermission", Storage="_Project", ThisKey="ProjectId", OtherKey="ProjectId", IsForeignKey=true, DeleteOnNull=true)]
+		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Project_ProjectPermission", Storage="_Project", ThisKey="ProjectId", OtherKey="ProjectId", IsForeignKey=true)]
 		public Project Project
 		{
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 15630)
@@ -111,4 +111,5 @@
   [DateCreated] DateTime NOT NULL,
   [ProjectId] UniqueIdentifier NOT NULL,
+  [JobState] VarChar(30) NOT NULL,
   CONSTRAINT [PK_dbo.Job] PRIMARY KEY ([JobId])
   )
@@ -172,43 +173,43 @@
 
 ALTER TABLE [dbo].[AssignedProjectResource]
-  ADD CONSTRAINT [Resource_AssignedProjectResource] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId])
+  ADD CONSTRAINT [Resource_AssignedProjectResource] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[AssignedProjectResource]
-  ADD CONSTRAINT [Project_AssignedProjectResource] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Project]([ProjectId])
+  ADD CONSTRAINT [Project_AssignedProjectResource] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Project]([ProjectId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[AssignedTaskResource]
-  ADD CONSTRAINT [Resource_AssignedTaskResource] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId])
+  ADD CONSTRAINT [Resource_AssignedTaskResource] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[AssignedTaskResource]
-  ADD CONSTRAINT [Task_AssignedTaskResource] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId])
+  ADD CONSTRAINT [Task_AssignedTaskResource] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[AssignedJobResource]
-  ADD CONSTRAINT [Resource_AssignedJobResource] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId])
+  ADD CONSTRAINT [Resource_AssignedJobResource] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[AssignedJobResource]
-  ADD CONSTRAINT [Job_AssignedJobResource] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId])
+  ADD CONSTRAINT [Job_AssignedJobResource] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[RequiredPlugins]
-  ADD CONSTRAINT [Plugin_RequiredPlugin] FOREIGN KEY ([PluginId]) REFERENCES [dbo].[Plugin]([PluginId])
+  ADD CONSTRAINT [Plugin_RequiredPlugin] FOREIGN KEY ([PluginId]) REFERENCES [dbo].[Plugin]([PluginId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[RequiredPlugins]
-  ADD CONSTRAINT [Task_RequiredPlugin] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId])
+  ADD CONSTRAINT [Task_RequiredPlugin] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[Resource]
-  ADD CONSTRAINT [Resource_Resource] FOREIGN KEY ([ParentResourceId]) REFERENCES [dbo].[Resource]([ResourceId])
+  ADD CONSTRAINT [Resource_Resource] FOREIGN KEY ([ParentResourceId]) REFERENCES [dbo].[Resource]([ResourceId]);
 ALTER TABLE [dbo].[Task]
-  ADD CONSTRAINT [Task_Task] FOREIGN KEY ([ParentTaskId]) REFERENCES [dbo].[Task]([TaskId])
+  ADD CONSTRAINT [Task_Task] FOREIGN KEY ([ParentTaskId]) REFERENCES [dbo].[Task]([TaskId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[Task]
-  ADD CONSTRAINT [Job_Job] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId])
+  ADD CONSTRAINT [Job_Job] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[Downtime]
-  ADD CONSTRAINT [Resource_Downtime] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId])
+  ADD CONSTRAINT [Resource_Downtime] FOREIGN KEY ([ResourceId]) REFERENCES [dbo].[Resource]([ResourceId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[Job]
-	ADD CONSTRAINT [Project_Job] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Project]([ProjectId])
+	ADD CONSTRAINT [Project_Job] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Project]([ProjectId]);
 ALTER TABLE [dbo].[TaskData]
-  ADD CONSTRAINT [Task_TaskData] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId])
+  ADD CONSTRAINT [Task_TaskData] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[PluginData]
-  ADD CONSTRAINT [Plugin_PluginData] FOREIGN KEY ([PluginId]) REFERENCES [dbo].[Plugin]([PluginId])
+  ADD CONSTRAINT [Plugin_PluginData] FOREIGN KEY ([PluginId]) REFERENCES [dbo].[Plugin]([PluginId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[StateLog]
-  ADD CONSTRAINT [Task_StateLog] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId])
+  ADD CONSTRAINT [Task_StateLog] FOREIGN KEY ([TaskId]) REFERENCES [dbo].[Task]([TaskId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[StateLog]
-  ADD CONSTRAINT [Resource_StateLog] FOREIGN KEY ([SlaveId]) REFERENCES [dbo].[Resource]([ResourceId])
+  ADD CONSTRAINT [Resource_StateLog] FOREIGN KEY ([SlaveId]) REFERENCES [dbo].[Resource]([ResourceId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[JobPermission]
-  ADD CONSTRAINT [Job_JobPermission] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId])
+  ADD CONSTRAINT [Job_JobPermission] FOREIGN KEY ([JobId]) REFERENCES [dbo].[Job]([JobId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[Project]
-  ADD CONSTRAINT [Project_Project] FOREIGN KEY ([ParentProjectId]) REFERENCES [dbo].[Project]([ProjectId])
+  ADD CONSTRAINT [Project_Project] FOREIGN KEY ([ParentProjectId]) REFERENCES [dbo].[Project]([ProjectId]) ON UPDATE CASCADE ON DELETE CASCADE;
 ALTER TABLE [dbo].[ProjectPermission]
-  ADD CONSTRAINT [Project_ProjectPermission] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Project]([ProjectId])
+  ADD CONSTRAINT [Project_ProjectPermission] FOREIGN KEY ([ProjectId]) REFERENCES [dbo].[Project]([ProjectId]) ON UPDATE CASCADE ON DELETE CASCADE;
 
 GO
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql	(revision 15630)
@@ -33,5 +33,5 @@
 ON DELETE CASCADE
 GO
-
+-- OBSOLETE (start)
 ALTER TABLE [dbo].[AssignedTaskResource]  DROP  CONSTRAINT [Task_AssignedTaskResource]
 ALTER TABLE [dbo].[AssignedTaskResource]  WITH CHECK ADD  CONSTRAINT [Task_AssignedTaskResource] FOREIGN KEY([TaskId])
@@ -46,5 +46,5 @@
 ON DELETE CASCADE
 GO
-
+-- OBSOLETE (end)
 ALTER TABLE [dbo].[AssignedJobResource]  DROP  CONSTRAINT [Job_AssignedJobResource]
 ALTER TABLE [dbo].[AssignedJobResource]  WITH CHECK ADD  CONSTRAINT [Job_AssignedJobResource] FOREIGN KEY([JobId])
@@ -118,5 +118,5 @@
 REFERENCES [dbo].[Project] ([ProjectId])
 ON UPDATE CASCADE
--- ON DELETE CASCADE
+-- ON DELETE CASCADE (no "ON DELETE CASCADE" >>> if project is deleted, jobs (actually job-belonging tasks) should be aborted, but not deleted
 GO
 
@@ -158,4 +158,6 @@
 
 
+
+-- OBSOLETE (start)
 /****** Object:  Trigger [dbo].[tr_JobDeleteCascade]    Script Date: 04/19/2011 16:31:53 ******/
 SET ANSI_NULLS ON
@@ -210,4 +212,4 @@
 END
 GO
-
-
+-- OBSOLETE (end)
+
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Converter.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Converter.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Converter.cs	(revision 15630)
@@ -121,5 +121,6 @@
         OwnerUserId = source.OwnerUserId,
         DateCreated = source.DateCreated,
-        ProjectId = source.ProjectId
+        ProjectId = source.ProjectId,
+        State = source.State.ToDto()
       };
     }
@@ -140,4 +141,5 @@
       target.DateCreated = source.DateCreated;
       target.ProjectId = source.ProjectId;
+      target.State = source.State.ToEntity();
     }
     #endregion
@@ -242,5 +244,5 @@
     #endregion
 
-    #region State
+    #region TaskState
     public static DT.TaskState ToDto(this DA.TaskState source) {
       switch (source) {
@@ -268,4 +270,24 @@
         case DT.TaskState.Waiting: return DA.TaskState.Waiting;
         default: return DA.TaskState.Failed;
+      }
+    }
+    #endregion
+
+    #region JobState
+    public static DT.JobState ToDto(this DA.JobState source) {
+      switch (source) {
+        case DA.JobState.Online: return DT.JobState.Online;
+        case DA.JobState.StatisticsPending: return DT.JobState.StatisticsPending;
+        case DA.JobState.DeletionPending: return DT.JobState.DeletionPending;
+        default: return DT.JobState.Online;
+      }
+    }
+
+    public static DA.JobState ToEntity(this DT.JobState source) {
+      switch (source) {
+        case DT.JobState.Online: return DA.JobState.Online;
+        case DT.JobState.StatisticsPending: return DA.JobState.StatisticsPending;
+        case DT.JobState.DeletionPending: return DA.JobState.DeletionPending;
+        default: return DA.JobState.Online;
       }
     }
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/DataTransfer/Job.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/DataTransfer/Job.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/DataTransfer/Job.cs	(revision 15630)
@@ -37,4 +37,6 @@
     [DataMember]
     public string OwnerUsername { get; set; }
+    [DataMember]
+    public JobState State { get; set; }
 
     /* ==== some computed statistics ==== */
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/DataTransfer/JobState.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/DataTransfer/JobState.cs	(revision 15630)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/DataTransfer/JobState.cs	(revision 15630)
@@ -0,0 +1,45 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HeuristicLab.Services.Hive.DataTransfer {
+  [Serializable]
+  public enum JobState {
+    /// <summary>
+    /// A job is online as long as he is no other state.
+    /// </summary>
+    Online,
+
+    /// <summary>
+    /// A job is in StatisticsPending if its deletion has been requested,
+    /// but the final generation of statistics hasn't been performed yet.
+    /// </summary>
+    StatisticsPending,
+
+    /// <summary>
+    /// A job is in DeletionPending if its deletion has been requested,
+    /// the final generation of statistics has already been performed,
+    /// but the eventual deletion of the job is still pending. 
+    /// </summary>
+    DeletionPending
+  };
+
+  public static class JobStateExtensions {
+    /// <summary>
+    /// This job is online
+    /// </summary>
+    public static bool IsOnline(this JobState jobState) {
+      return jobState == JobState.Online;
+    }
+
+    /// <summary>
+    /// This job is still existent, but already flagged for deletion.
+    /// Usually the flag is set by a user, not a resource or the janitor or something else.
+    /// </summary>
+    public static bool IsFlaggedForDeletion(this JobState jobState) {
+      return jobState == JobState.StatisticsPending || jobState == JobState.DeletionPending;
+    }
+  }
+}
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HeuristicLab.Services.Hive-3.3.csproj
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HeuristicLab.Services.Hive-3.3.csproj	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HeuristicLab.Services.Hive-3.3.csproj	(revision 15630)
@@ -122,4 +122,5 @@
     <Compile Include="DataTransfer\AssignedProjectResource.cs" />
     <Compile Include="DataTransfer\Command.cs" />
+    <Compile Include="DataTransfer\JobState.cs" />
     <Compile Include="DataTransfer\Project.cs" />
     <Compile Include="DataTransfer\ProjectPermission.cs" />
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 15630)
@@ -361,7 +361,9 @@
         return pm.UseTransaction(() => {
           var jobs = jobDao.GetAll()
-            .Where(x => x.OwnerUserId == currentUserId
-                     || x.JobPermissions.Count(y => y.Permission != DA.Permission.NotAllowed
-                                                 && y.GrantedUserId == currentUserId) > 0)
+            .Where(x => x.State == DA.JobState.Online
+                          && (x.OwnerUserId == currentUserId
+                            || x.JobPermissions.Count(y => y.Permission != DA.Permission.NotAllowed 
+                              && y.GrantedUserId == currentUserId) > 0)
+                          )
             .Select(x => x.ToDto())
             .ToList();
@@ -524,16 +526,30 @@
     }
 
-    public void DeleteJob(Guid jobId) {
+    public void UpdateJobState(Guid jobId, DT.JobState jobState) {
       RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
       var pm = PersistenceManager;
-      using (new PerformanceLogger("DeleteJob")) {
+      using (new PerformanceLogger("UpdateJobState")) {
         var jobDao = pm.JobDao;
         pm.UseTransaction(() => {
-          // not necessary anymore: child tasks will be deleted by db-trigger
-          // now: tasks are deleted by jobId
-          // entries in AssignedJobResource will be deleted by foreign key clause CASCADE ON DELETE
-          jobDao.Delete(jobId);
-          pm.SubmitChanges();
+          var job = jobDao.GetById(jobId);
+          if(job != null) {
+            var jobStateEntity = jobState.ToEntity();
+            // note: allow solely state changes from "Online" to "StatisticsPending"
+            // and from "StatisticsPending" to "DeletionPending"
+            if (job.State == DA.JobState.Online && jobStateEntity == DA.JobState.StatisticsPending) {
+              job.State = jobStateEntity;
+              foreach(var task in job.Tasks
+              .Where(x => x.State == DA.TaskState.Waiting 
+                || x.State == DA.TaskState.Paused 
+                || x.State == DA.TaskState.Offline)) {
+                task.State = DA.TaskState.Aborted;
+              }
+              pm.SubmitChanges();
+            } else if(job.State == DA.JobState.StatisticsPending && jobStateEntity == DA.JobState.DeletionPending) {
+              job.State = jobStateEntity;
+              pm.SubmitChanges();
+            } 
+          }
         });
       }
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/EventManager.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/EventManager.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/EventManager.cs	(revision 15630)
@@ -34,4 +34,10 @@
     public void Cleanup() {
       var pm = PersistenceManager;
+
+      pm.UseTransaction(() => {
+        FinishJobDeletion(pm);
+        pm.SubmitChanges();
+      });
+
       pm.UseTransaction(() => {
         SetTimeoutSlavesOffline(pm);
@@ -45,4 +51,13 @@
         pm.SubmitChanges();
       });
+    }
+
+    /// <summary>
+    /// Deletes all jobs which are in state "DeletionPending" (this will include all corresponding tasks).
+    /// The state "DeletionPending" is set by HiveJanitor > StatisticsGenerator
+    /// </summary>
+    private void FinishJobDeletion(IPersistenceManager pm) {
+      var jobDao = pm.JobDao;
+      jobDao.DeleteByState(JobState.DeletionPending);
     }
 
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 15630)
@@ -141,4 +141,81 @@
     /// </summary>
     private IEnumerable<MessageContainer> UpdateTasks(IPersistenceManager pm, Heartbeat heartbeat, bool isAllowedToCalculate) {
+      var taskDao = pm.TaskDao;
+      var jobDao = pm.JobDao;
+      var assignedJobResourceDao = pm.AssignedJobResourceDao;
+      var actions = new List<MessageContainer>();
+      if (heartbeat.JobProgress == null || !heartbeat.JobProgress.Any())
+        return actions;
+
+      var jobIdsWithStatisticsPending = jobDao.GetJobIdsByState(DA.JobState.StatisticsPending).ToList();
+
+      // select all tasks and statelogs with one query
+      var taskIds = heartbeat.JobProgress.Select(x => x.Key).ToList();
+      var taskInfos = pm.UseTransaction(() =>
+        (from task in taskDao.GetAll()
+          where taskIds.Contains(task.TaskId)
+          let lastStateLog = task.StateLogs.OrderByDescending(x => x.DateTime).FirstOrDefault()
+          select new {
+            TaskId = task.TaskId,
+            JobId = task.JobId,
+            State = task.State,
+            Command = task.Command,
+            SlaveId = lastStateLog != null ? lastStateLog.SlaveId : default(Guid)
+          }).ToList()
+      );
+
+      // process the jobProgresses
+      foreach (var jobProgress in heartbeat.JobProgress) {
+        var progress = jobProgress;
+        var curTask = taskInfos.SingleOrDefault(x => x.TaskId == progress.Key);
+        if (curTask == null) {
+          actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, progress.Key));
+          LogFactory.GetLogger(this.GetType().Namespace).Log("Task on slave " + heartbeat.SlaveId + " does not exist in DB: " + jobProgress.Key);
+        } else if (jobIdsWithStatisticsPending.Contains(curTask.JobId)) {
+          // parenting job of current task has been requested for deletion (indicated by job state "Statistics Pending")
+          // update task execution time
+          pm.UseTransaction(() => {
+            taskDao.UpdateExecutionTime(curTask.TaskId, progress.Value.TotalMilliseconds);
+          });
+          actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curTask.TaskId));
+          LogFactory.GetLogger(this.GetType().Namespace).Log("Abort task " + curTask.TaskId + " on slave " + heartbeat.SlaveId + ". The parenting job " + curTask.JobId + " was requested to be deleted.");
+        } else if (curTask.SlaveId == Guid.Empty || curTask.SlaveId != heartbeat.SlaveId) {
+          // assigned slave does not match heartbeat
+          actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curTask.TaskId));
+          LogFactory.GetLogger(this.GetType().Namespace).Log("The slave " + heartbeat.SlaveId + " is not supposed to calculate task: " + curTask.TaskId);
+        } else if (!isAllowedToCalculate) {
+          actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curTask.TaskId));
+          LogFactory.GetLogger(this.GetType().Namespace).Log("The slave " + heartbeat.SlaveId + " is not allowed to calculate any tasks tue to a downtime. The task is paused.");
+        } else if (assignedJobResourceDao.CheckJobGrantedForResource(curTask.JobId, heartbeat.SlaveId)) { 
+          // assigned resources ids of task do not match with slaveId (and parent resourceGroupIds); this might happen when slave is moved to different group
+          actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curTask.TaskId));
+          LogFactory.GetLogger(this.GetType().Namespace).Log("The slave " + heartbeat.SlaveId + " is not granted to calculate task: " + curTask.TaskId);
+        } else {
+          // update task execution time
+          pm.UseTransaction(() => {
+            taskDao.UpdateExecutionTime(curTask.TaskId, progress.Value.TotalMilliseconds);
+          });
+          switch (curTask.Command) {
+            case DA.Command.Stop:
+              actions.Add(new MessageContainer(MessageContainer.MessageType.StopTask, curTask.TaskId));
+              break;
+            case DA.Command.Pause:
+              actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curTask.TaskId));
+              break;
+            case DA.Command.Abort:
+              actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curTask.TaskId));
+              break;
+          }
+        }
+        
+      } 
+      return actions;
+    }
+
+    /// <summary>
+    /// Update the progress of each task
+    /// Checks if all the task sent by heartbeat are supposed to be calculated by this slave
+    /// </summary>
+    private IEnumerable<MessageContainer> UpdateTasks_Old(IPersistenceManager pm, Heartbeat heartbeat, bool isAllowedToCalculate) {
       var taskDao = pm.TaskDao;
       var assignedResourceDao = pm.AssignedTaskResourceDao;
Index: branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs
===================================================================
--- branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 15629)
+++ branches/HiveProjectManagement/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 15630)
@@ -93,5 +93,5 @@
 
     [OperationContract]
-    void DeleteJob(Guid JobId);
+    void UpdateJobState(Guid JobId, JobState jobState);
 
     [OperationContract]
