Index: /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs
===================================================================
--- /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 9396)
+++ /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 9397)
@@ -31,52 +31,77 @@
 
     #region Task Methods
-    public Task GetTaskById(Guid id) {
-      return GetTaskByIdQuery(Db, id).SingleOrDefault();
-    }
-
-    private static Func<HiveDataContext, Guid, IQueryable<Task>> GetTaskByIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid id) =>
+    public Task GetTaskById(Guid taskId) {
+      return GetTaskByIdQuery(Db, taskId).SingleOrDefault();
+    }
+
+    private static Func<HiveDataContext, Guid, IQueryable<Task>> GetTaskByIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid taskId) =>
       from t in db.Tasks
-      where t.TaskId == id
+      where t.TaskId == taskId
       select t
     );
 
-    public void UpdateTaskAndPlugins(Task task) {       /*
-      foreach (var pluginId in task.RequiredPlugins.Select(p => p.PluginId)) {
-        if (db.RequiredPlugins.Count(p => p.PluginId == pluginId) == 0) {
-          db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = task.TaskId, PluginId = pluginId });
-        }
-      }
-      db.SubmitChanges();                                   */
-    }
-
-    public void UpdateTask(Task task) {
-      Db.SubmitChanges();
-    }
-
-    public IQueryable<TaskInfoForScheduler> GetWaitingTasks(Slave slave) {
-      var parentResources = GetParentResources(slave.ResourceId);
-      var resourceIds = parentResources.Select(x => x.ResourceId);
+    public Tuple<Task, Guid?> GetTaskByIdAndLastStateLogSlaveId(Guid taskId) {
+      return GetTaskByIdAndLastStateLogSlaveIdQuery(Db, taskId).SingleOrDefault();
+    }
+
+    private static Func<HiveDataContext, Guid, IQueryable<Tuple<Task, Guid?>>> GetTaskByIdAndLastStateLogSlaveIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid taskId) =>
+       from t in db.Tasks
+       join sl in db.StateLogs on t.TaskId equals sl.TaskId
+       where t.TaskId == taskId
+       orderby sl.DateTime descending
+       group sl by t into logs
+       select new Tuple<Task, Guid?>(logs.Key, logs.First().SlaveId)
+    );
+
+    private const string GetWaitingTasksQueryString = @"
+      WITH pr AS (
+        SELECT ResourceId, ParentResourceId
+        FROM [Resource]
+        WHERE ResourceId = {0}
+        UNION ALL
+        SELECT r.ResourceId, r.ParentResourceId
+        FROM [Resource] r JOIN pr ON r.ResourceId = pr.ParentResourceId
+      )
+      SELECT DISTINCT t.TaskId, t.JobId, t.Priority
+      FROM pr JOIN AssignedResources ar ON ar.ResourceId = pr.ResourceId
+          JOIN Task t ON t.TaskId = ar.TaskId
+      WHERE NOT (t.IsParentTask = 1 AND t.FinishWhenChildJobsFinished = 1)
+          AND t.TaskState = {1}
+          AND t.CoresNeeded <= {2}
+          AND t.MemoryNeeded <= {3}
+    ";
+
+    public IEnumerable<TaskInfoForScheduler> GetWaitingTasks(Slave slave) {
       //Originally we checked here if there are parent tasks which should be calculated (with GetParentTasks(resourceIds, count, false);).
       //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 from ar in Db.AssignedResources
-             where resourceIds.Contains(ar.ResourceId)
-                 && !(ar.Task.IsParentTask && ar.Task.FinishWhenChildJobsFinished)
-                 && ar.Task.State == TaskState.Waiting
-                 && ar.Task.CoresNeeded <= slave.FreeCores
-                 && ar.Task.MemoryNeeded <= slave.FreeMemory
-             select new TaskInfoForScheduler() { TaskId = ar.Task.TaskId, JobId = ar.Task.JobId, Priority = ar.Task.Priority };
-    }
-
-    /*private static Func<HiveDataContext, Guid, Slave, IQueryable<TaskInfoForScheduler>> GetWaitingTasksQuery = CompiledQuery.Compile((HiveDataContext db, Guid id, Slave slave) =>
-      from ar in db.AssignedResources
-      where ar.ResourceId == id
-          && !(ar.Task.IsParentTask && ar.Task.FinishWhenChildJobsFinished)
-          && ar.Task.State == TaskState.Waiting
-          && ar.Task.CoresNeeded <= slave.FreeCores
-          && ar.Task.MemoryNeeded <= slave.FreeMemory
-      select new TaskInfoForScheduler() { TaskId = ar.Task.TaskId, JobId = ar.Task.JobId, Priority = ar.Task.Priority }
-    );*/
+      return Db.ExecuteQuery<TaskInfoForScheduler>(GetWaitingTasksQueryString, slave.ResourceId, Enum.GetName(typeof(TaskState), TaskState.Waiting), slave.FreeCores, slave.FreeMemory);
+    }
+
+    public IQueryable<DT.LightweightTask> GetLightweightTasks(Guid jobId) {
+      return GetLightweightTasksQuery(Db, jobId);
+    }
+
+    private static Func<HiveDataContext, Guid, IQueryable<DT.LightweightTask>> GetLightweightTasksQuery = CompiledQuery.Compile((HiveDataContext db, Guid jobId) =>
+        from task in db.Tasks
+        where task.JobId == jobId
+        select new DT.LightweightTask {
+          Id = task.TaskId,
+          ExecutionTime = TimeSpan.FromMilliseconds(task.ExecutionTimeMs),
+          ParentTaskId = task.ParentTaskId,
+          StateLog = task.StateLogs.Select(sl => ConvertStateLog(sl)).ToList(),
+          State = ConvertTaskState(task.State),
+          Command = ConvertCommand(task.Command),
+          LastTaskDataUpdate = task.JobData.LastUpdate
+        }
+    );
+
+    static Func<StateLog, DT.StateLog> ConvertStateLog = sl => DT.Convert.ToDto(sl);
+    static Func<TaskState, DT.TaskState> ConvertTaskState = ts => DT.Convert.ToDto(ts);
+    static Func<Command?, DT.Command?> ConvertCommand = c => DT.Convert.ToDto(c);
+
+    public void UpdateTask(Task task) {
+      Db.SubmitChanges();
+    }
 
     public Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
@@ -97,4 +122,22 @@
       return task;
     }
+
+    private const string TaskIsAllowedToBeCalculatedBySlaveQueryString = @"
+      WITH pr AS (
+        SELECT ResourceId, ParentResourceId
+        FROM [Resource]
+        WHERE ResourceId = {0}
+        UNION ALL
+        SELECT r.ResourceId, r.ParentResourceId
+        FROM [Resource] r JOIN pr ON r.ResourceId = pr.ParentResourceId
+      )
+      SELECT COUNT(ar.TaskId)
+      FROM pr JOIN AssignedResources ar ON pr.ResourceId = ar.ResourceId
+      WHERE ar.TaskId = {1}
+    ";
+
+    public bool TaskIsAllowedToBeCalculatedBySlave(Guid taskId, Guid slaveId) {
+      return Db.ExecuteQuery<int>(TaskIsAllowedToBeCalculatedBySlaveQueryString, slaveId, taskId).First() > 0;
+    }
     #endregion
 
@@ -155,4 +198,27 @@
       Db.SubmitChanges();
     }
+
+    private const string DowntimeQueryString = @"
+      WITH pr AS (
+        SELECT ResourceId, ParentResourceId
+        FROM [Resource]
+        WHERE ResourceId = {0}
+        UNION ALL
+        SELECT r.ResourceId, r.ParentResourceId
+        FROM [Resource] r JOIN pr ON r.ResourceId = pr.ParentResourceId
+      )
+      SELECT COUNT(dt.DowntimeId)
+      FROM pr JOIN [Downtime] dt ON pr.ResourceId = dt.ResourceId
+      WHERE {1} BETWEEN dt.StartDate AND dt.EndDate
+        AND dt.DowntimeType = {2}
+      ";
+
+    public bool SlaveHasToShutdownComputer(Guid slaveId) {
+      return Db.ExecuteQuery<int>(DowntimeQueryString, slaveId, DateTime.Now, DowntimeType.Shutdown).First() > 0;
+    }
+
+    public bool SlaveIsAllowedToCalculate(Guid slaveId) {
+      return Db.ExecuteQuery<int>(DowntimeQueryString, slaveId, DateTime.Now, DowntimeType.Offline).First() == 0;
+    }
     #endregion
 
@@ -162,39 +228,4 @@
 
     #region Resource Methods
-    public IQueryable<Guid> GetAssignedResourcesIds(Guid taskId) {
-      return GetAssignedResourcesIdQuery(Db, taskId);
-    }
-
-    private static Func<HiveDataContext, Guid, IQueryable<Guid>> GetAssignedResourcesIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid taskId) =>
-      from ar in db.AssignedResources
-      where ar.TaskId == taskId
-      select ar.ResourceId
-    );
-
-    public IEnumerable<Resource> GetParentResources(Guid resourceId) {
-      var child = Db.Resources.Single(r => r.ResourceId == resourceId);
-
-      yield return child;
-      while (child.ParentResource != null) {
-        child = child.ParentResource;
-        yield return child;
-      }
-    }
-
-    public IEnumerable<Guid> GetParentResourcesIDs(Guid resourceId) {
-      var child = Db.Resources.Single(r => r.ResourceId == resourceId);
-
-      yield return resourceId;
-      while (child.ParentResource != null) {
-        child = child.ParentResource;
-        yield return child.ResourceId;
-      }
-    }
-
-    private static void CollectParentResources(ICollection<Resource> resources, Resource resource) {
-      if (resource == null) return;
-      resources.Add(resource);
-      CollectParentResources(resources, resource.ParentResource);
-    }
     #endregion
 
@@ -212,21 +243,4 @@
 
     #region Downtime Methods
-    public IQueryable<int> GetNumberOfDowntimesFromParentResourcesAtCurrentTime(Guid resourceId, DowntimeType type) {
-      var ids = GetParentResourcesIDs(resourceId).ToArray();
-
-      return from r in Db.Resources
-             where ids.Contains(r.ResourceId)
-             select (from d in Db.Downtimes
-                     where d.ResourceId == r.ResourceId && d.DowntimeType == type && (DateTime.Now >= d.StartDate) && (DateTime.Now <= d.EndDate)
-                     select d).Count();
-    }
-
-    /*private static Func<HiveDataContext, Guid, DowntimeType, int> GetNumberOfDowntimesAtCurrentTimeQuery =
-      CompiledQuery.Compile((HiveDataContext db, Guid ids, DowntimeType type) =>
-        (from d in db.Downtimes
-         where d.ResourceId == ids && d.DowntimeType == type && (DateTime.Now >= d.StartDate) && (DateTime.Now <= d.EndDate)
-         select d).Count()
-    );*/
-
     #endregion
 
Index: /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs
===================================================================
--- /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 9396)
+++ /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 9397)
@@ -132,5 +132,5 @@
 
       return trans.UseTransaction(() => {
-        return dtoDao.GetLightweightTasks(task => task.JobId == jobId).ToArray();
+        return dao.GetLightweightTasks(jobId).ToArray();
       }, false, true);
     }
@@ -217,5 +217,5 @@
         }
 
-        //dtoDao.UpdateTaskAndPluginsDA(task); no idea why this is needed
+        //dao.UpdateTaskAndPlugins(task); no idea why this is needed
         return DT.Convert.ToDto(task);
       });
Index: /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs
===================================================================
--- /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs	(revision 9396)
+++ /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs	(revision 9397)
@@ -29,7 +29,9 @@
   public interface IHiveDao {
     #region Task Methods
-    Task GetTaskById(Guid id);
+    Task GetTaskById(Guid task);
+    Tuple<Task, Guid?> GetTaskByIdAndLastStateLogSlaveId(Guid taskId);
 
-    IQueryable<TaskInfoForScheduler> GetWaitingTasks(Slave slave);
+    IEnumerable<TaskInfoForScheduler> GetWaitingTasks(Slave slave);
+    IQueryable<DT.LightweightTask> GetLightweightTasks(Guid jobId);
 
     void UpdateTask(Task task);
@@ -37,4 +39,5 @@
     Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception);
 
+    bool TaskIsAllowedToBeCalculatedBySlave(Guid taskId, Guid slaveId);
     #endregion
 
@@ -68,4 +71,7 @@
 
     void UpdateSlave(Slave slave);
+
+    bool SlaveHasToShutdownComputer(Guid slaveId);
+    bool SlaveIsAllowedToCalculate(Guid slaveId);
     #endregion
 
@@ -75,7 +81,5 @@
 
     #region Resource Methods
-    IQueryable<Guid> GetAssignedResourcesIds(Guid taskId);
-    IEnumerable<Resource> GetParentResources(Guid resourceId);
-    IEnumerable<Guid> GetParentResourcesIDs(Guid resourceId);
+
     #endregion
 
@@ -93,5 +97,4 @@
 
     #region Downtime Methods
-    IQueryable<int> GetNumberOfDowntimesFromParentResourcesAtCurrentTime(Guid resourceId, DowntimeType type);
     #endregion
 
Index: /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs
===================================================================
--- /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 9396)
+++ /branches/HivePerformance/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 9397)
@@ -51,26 +51,27 @@
       trans.UseTransaction(() => {
         slave = dao.GetSlaveById(heartbeat.SlaveId);
+      });
+      if (slave == null) {
+        actions.Add(new MessageContainer(MessageContainer.MessageType.SayHello));
+      } else {
+        if (heartbeat.HbInterval != slave.HbInterval) {
+          actions.Add(new MessageContainer(MessageContainer.MessageType.NewHBInterval));
+        }
+        if (dao.SlaveHasToShutdownComputer(slave.ResourceId)) {
+          actions.Add(new MessageContainer(MessageContainer.MessageType.ShutdownComputer));
+        }
 
-        if (slave == null) {
-          actions.Add(new MessageContainer(MessageContainer.MessageType.SayHello));
-        } else {
-          if (heartbeat.HbInterval != slave.HbInterval) {
-            actions.Add(new MessageContainer(MessageContainer.MessageType.NewHBInterval));
-          }
-          if (ShutdownSlaveComputer(slave.ResourceId)) {
-            actions.Add(new MessageContainer(MessageContainer.MessageType.ShutdownComputer));
-          }
+        // update slave data
+        slave.FreeCores = heartbeat.FreeCores;
+        slave.FreeMemory = heartbeat.FreeMemory;
+        slave.CpuUtilization = heartbeat.CpuUtilization;
+        slave.IsAllowedToCalculate = dao.SlaveIsAllowedToCalculate(slave.ResourceId);
+        slave.SlaveState = (heartbeat.JobProgress != null && heartbeat.JobProgress.Count > 0) ? SlaveState.Calculating : SlaveState.Idle;
+        slave.LastHeartbeat = DateTime.Now;
 
-          // update slave data
-          slave.FreeCores = heartbeat.FreeCores;
-          slave.FreeMemory = heartbeat.FreeMemory;
-          slave.CpuUtilization = heartbeat.CpuUtilization;
-          slave.IsAllowedToCalculate = SlaveIsAllowedToCalculate(slave.ResourceId);
-          slave.SlaveState = (heartbeat.JobProgress != null && heartbeat.JobProgress.Count > 0) ? SlaveState.Calculating : SlaveState.Idle;
-          slave.LastHeartbeat = DateTime.Now;
-
+        trans.UseTransaction(() => {
           dao.UpdateSlave(slave);
-        }
-      });
+        });
+      }
 
       if (slave != null) {
@@ -136,60 +137,47 @@
         // process the jobProgresses
         foreach (var jobProgress in heartbeat.JobProgress) {
+          Tuple<Task, Guid?> taskWithLastStateLogSlaveId = null;
           trans.UseTransaction(() => {
-            var curTask = dao.GetTaskById(jobProgress.Key);
-            if (curTask == null) {
-              // task does not exist in db
-              actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, jobProgress.Key));
-              LogFactory.GetLogger(this.GetType().Namespace).Log("Task on slave " + heartbeat.SlaveId + " does not exist in DB: " + jobProgress.Key);
+            taskWithLastStateLogSlaveId = dao.GetTaskByIdAndLastStateLogSlaveId(jobProgress.Key);
+          });
+          var curTask = taskWithLastStateLogSlaveId != null ? taskWithLastStateLogSlaveId.Item1 : null;
+          if (curTask == null) {
+            // task does not exist in db
+            actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, jobProgress.Key));
+            LogFactory.GetLogger(this.GetType().Namespace).Log("Task on slave " + heartbeat.SlaveId + " does not exist in DB: " + jobProgress.Key);
+          } else {
+            var slaveId = taskWithLastStateLogSlaveId.Item2;
+            if (slaveId == Guid.Empty || 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);
+            } else if (!dao.TaskIsAllowedToBeCalculatedBySlave(curTask.TaskId, 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));
             } else {
-              var currentStateLog = curTask.StateLogs.Last();
-              if (currentStateLog.SlaveId == Guid.Empty || currentStateLog.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);
-              } else if (!TaskIsAllowedToBeCalculatedBySlave(heartbeat.SlaveId, curTask)) {
-                // 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));
-              } else {
-                // save task execution time
-                curTask.ExecutionTimeMs = jobProgress.Value.TotalMilliseconds;
-                curTask.LastHeartbeat = DateTime.Now;
+              // save task execution time
+              curTask.ExecutionTimeMs = jobProgress.Value.TotalMilliseconds;
+              curTask.LastHeartbeat = DateTime.Now;
 
-                switch (curTask.Command) {
-                  case Command.Stop:
-                    actions.Add(new MessageContainer(MessageContainer.MessageType.StopTask, curTask.TaskId));
-                    break;
-                  case Command.Pause:
-                    actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curTask.TaskId));
-                    break;
-                  case Command.Abort:
-                    actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curTask.TaskId));
-                    break;
-                }
+              switch (curTask.Command) {
+                case Command.Stop:
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.StopTask, curTask.TaskId));
+                  break;
+                case Command.Pause:
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curTask.TaskId));
+                  break;
+                case Command.Abort:
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curTask.TaskId));
+                  break;
+              }
+              trans.UseTransaction(() => {
                 dao.UpdateTask(curTask);
-              }
+              });
             }
-          });
+          }
         }
       }
       return actions;
     }
-
-    private bool TaskIsAllowedToBeCalculatedBySlave(Guid slaveId, Task curTask) {
-      var assignedResourceIds = dao.GetAssignedResourcesIds(curTask.TaskId);
-      var slaveResourceIds = dao.GetParentResourcesIDs(slaveId).ToArray();
-      return assignedResourceIds.Any(r => slaveResourceIds.Contains(r));
-    }
-
-    private bool SlaveIsAllowedToCalculate(Guid slaveId) {
-      var downtimes = dao.GetNumberOfDowntimesFromParentResourcesAtCurrentTime(slaveId, DowntimeType.Offline);
-      // the slave may only calculate if there is no downtime right now. this needs to be checked for every parent resource also
-      return downtimes.All(x => x == 0);
-    }
-
-    private bool ShutdownSlaveComputer(Guid slaveId) {
-      var downtimes = dao.GetNumberOfDowntimesFromParentResourcesAtCurrentTime(slaveId, DowntimeType.Shutdown);
-      return downtimes.Any(x => x != 0);
-    }
   }
 }
