Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Convert.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Convert.cs	(revision 12753)
+++ 	(revision )
@@ -1,571 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Collections.Generic;
-using System.Data.Linq;
-using System.Linq;
-using DB = HeuristicLab.Services.Hive.DataAccess;
-using DT = HeuristicLab.Services.Hive.DataTransfer;
-
-namespace HeuristicLab.Services.Hive.DataTransfer {
-  public static class Convert {
-    #region Task
-    public static DT.Task ToDto(DB.Task source) {
-      if (source == null) return null;
-      return new DT.Task {
-        Id = source.TaskId,
-        CoresNeeded = source.CoresNeeded,
-        ExecutionTime = TimeSpan.FromMilliseconds(source.ExecutionTimeMs),
-        MemoryNeeded = source.MemoryNeeded,
-        ParentTaskId = source.ParentTaskId,
-        Priority = source.Priority,
-        PluginsNeededIds = (source.RequiredPlugins == null ? new List<Guid>() : source.RequiredPlugins.Select(x => x.PluginId).ToList()),
-        LastHeartbeat = source.LastHeartbeat,
-        State = Convert.ToDto(source.State),
-        StateLog = (source.StateLogs == null ? new List<DT.StateLog>() : source.StateLogs.Select(x => Convert.ToDto(x)).OrderBy(x => x.DateTime).ToList()),
-        IsParentTask = source.IsParentTask,
-        FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished,
-        Command = Convert.ToDto(source.Command),
-        LastTaskDataUpdate = (source.JobData == null ? DateTime.MinValue : source.JobData.LastUpdate),
-        JobId = source.JobId,
-        IsPrivileged = source.IsPrivileged
-      };
-    }
-
-    public static DB.Task ToEntity(DT.Task source) {
-      if (source == null) return null;
-      var entity = new DB.Task(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.Task source, DB.Task target) {
-      if ((source != null) && (target != null)) {
-        target.TaskId = source.Id;
-        target.CoresNeeded = source.CoresNeeded;
-        target.ExecutionTimeMs = source.ExecutionTime.TotalMilliseconds;
-        target.MemoryNeeded = source.MemoryNeeded;
-        target.ParentTaskId = source.ParentTaskId;
-        target.Priority = source.Priority;
-        target.LastHeartbeat = source.LastHeartbeat;
-        target.State = Convert.ToEntity(source.State);
-        foreach (DT.StateLog sl in source.StateLog.Where(x => x.Id == Guid.Empty)) {
-          target.StateLogs.Add(Convert.ToEntity(sl));
-        }
-        target.IsParentTask = source.IsParentTask;
-        target.FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished;
-        target.Command = Convert.ToEntity(source.Command);
-        // RequiredPlugins are added by Dao
-        target.JobId = source.JobId;
-        target.IsPrivileged = source.IsPrivileged;
-      }
-    }
-
-    public static void ToEntityTaskOnly(DT.Task source, DB.Task target) {
-      if ((source != null) && (target != null)) {
-        target.TaskId = source.Id;
-        target.CoresNeeded = source.CoresNeeded;
-        target.ExecutionTimeMs = source.ExecutionTime.TotalMilliseconds;
-        target.MemoryNeeded = source.MemoryNeeded;
-        target.ParentTaskId = source.ParentTaskId;
-        target.Priority = source.Priority;
-        target.LastHeartbeat = source.LastHeartbeat;
-        target.State = Convert.ToEntity(source.State);
-        target.IsParentTask = source.IsParentTask;
-        target.FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished;
-        target.Command = Convert.ToEntity(source.Command);
-        // RequiredPlugins are added by Dao
-        target.JobId = source.JobId;
-        target.IsPrivileged = source.IsPrivileged;
-      }
-    }
-    #endregion
-
-    #region TaskData
-    public static DT.TaskData ToDto(DB.TaskData source) {
-      if (source == null) return null;
-      return new DT.TaskData { TaskId = source.TaskId, Data = source.Data, LastUpdate = source.LastUpdate };
-    }
-    public static DB.TaskData ToEntity(DT.TaskData source) {
-      if (source == null) return null;
-      var entity = new DB.TaskData(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.TaskData source, DB.TaskData target) {
-      if ((source != null) && (target != null)) {
-        target.TaskId = source.TaskId;
-        target.Data = source.Data;
-        target.LastUpdate = source.LastUpdate;
-      }
-    }
-    #endregion
-
-    #region StateLog
-    public static DT.StateLog ToDto(DB.StateLog source) {
-      if (source == null) return null;
-      return new DT.StateLog { Id = source.StateLogId, DateTime = source.DateTime, Exception = source.Exception, TaskId = source.TaskId, SlaveId = source.SlaveId, State = Convert.ToDto(source.State), UserId = source.UserId };
-    }
-    public static DB.StateLog ToEntity(DT.StateLog source) {
-      if (source == null) return null;
-      var entity = new DB.StateLog(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.StateLog source, DB.StateLog target) {
-      if ((source != null) && (target != null)) {
-        target.StateLogId = source.Id; target.DateTime = source.DateTime; target.Exception = source.Exception; target.TaskId = source.TaskId; target.SlaveId = source.SlaveId; target.State = Convert.ToEntity(source.State); target.UserId = source.UserId;
-      }
-    }
-    #endregion
-
-    #region Downtimes
-    public static DT.Downtime ToDto(DB.Downtime source) {
-      if (source == null) return null;
-      return new DT.Downtime { Id = source.DowntimeId, AllDayEvent = source.AllDayEvent, EndDate = source.EndDate, Recurring = source.Recurring, RecurringId = source.RecurringId, ResourceId = source.ResourceId, StartDate = source.StartDate, DowntimeType = source.DowntimeType };
-    }
-    public static DB.Downtime ToEntity(DT.Downtime source) {
-      if (source == null) return null;
-      var entity = new DB.Downtime(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.Downtime source, DB.Downtime target) {
-      if ((source != null) && (target != null)) {
-        target.DowntimeId = source.Id; target.AllDayEvent = source.AllDayEvent; target.EndDate = source.EndDate; target.Recurring = source.Recurring; target.RecurringId = source.RecurringId; target.ResourceId = source.ResourceId; target.StartDate = source.StartDate; target.DowntimeType = source.DowntimeType;
-      }
-    }
-    #endregion
-
-    #region Job
-    public static DT.Job ToDto(DB.Job source) {
-      if (source == null) return null;
-      return new DT.Job { Id = source.JobId, Description = source.Description, Name = source.Name, OwnerUserId = source.OwnerUserId, DateCreated = source.DateCreated, ResourceNames = source.ResourceIds };
-    }
-    public static DB.Job ToEntity(DT.Job source) {
-      if (source == null) return null;
-      var entity = new DB.Job(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.Job source, DB.Job target) {
-      if ((source != null) && (target != null)) {
-        target.JobId = source.Id; target.Description = source.Description; target.Name = source.Name; target.OwnerUserId = source.OwnerUserId; target.DateCreated = source.DateCreated; target.ResourceIds = source.ResourceNames;
-      }
-    }
-    #endregion
-
-    #region JobPermission
-    public static DT.JobPermission ToDto(DB.JobPermission source) {
-      if (source == null) return null;
-      return new DT.JobPermission { JobId = source.JobId, GrantedUserId = source.GrantedUserId, GrantedByUserId = source.GrantedByUserId, Permission = Convert.ToDto(source.Permission) };
-    }
-    public static DB.JobPermission ToEntity(DT.JobPermission source) {
-      if (source == null) return null;
-      var entity = new DB.JobPermission(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.JobPermission source, DB.JobPermission target) {
-      if ((source != null) && (target != null)) {
-        target.JobId = source.JobId; target.GrantedUserId = source.GrantedUserId; target.GrantedByUserId = source.GrantedByUserId; target.Permission = Convert.ToEntity(source.Permission);
-      }
-    }
-    #endregion
-
-    #region Plugin
-    public static DT.Plugin ToDto(DB.Plugin source) {
-      if (source == null) return null;
-      return new DT.Plugin { Id = source.PluginId, Name = source.Name, Version = new Version(source.Version), UserId = source.UserId, DateCreated = source.DateCreated, Hash = source.Hash };
-    }
-    public static DB.Plugin ToEntity(DT.Plugin source) {
-      if (source == null) return null;
-      var entity = new DB.Plugin(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.Plugin source, DB.Plugin target) {
-      if ((source != null) && (target != null)) {
-        target.PluginId = source.Id; target.Name = source.Name; target.Version = source.Version.ToString(); target.UserId = source.UserId; target.DateCreated = source.DateCreated; target.Hash = source.Hash;
-      }
-    }
-    #endregion
-
-    #region PluginData
-    public static DT.PluginData ToDto(DB.PluginData source) {
-      if (source == null) return null;
-      return new DT.PluginData { Id = source.PluginDataId, PluginId = source.PluginId, Data = source.Data.ToArray(), FileName = source.FileName };
-    }
-    public static DB.PluginData ToEntity(DT.PluginData source) {
-      if (source == null) return null;
-      var entity = new DB.PluginData(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.PluginData source, DB.PluginData target) {
-      if ((source != null) && (target != null)) {
-        target.PluginDataId = source.Id;
-        target.PluginId = source.PluginId;
-        target.Data = source.Data;
-        target.FileName = source.FileName;
-      }
-    }
-    #endregion
-
-    #region Resource
-    public static DT.Resource ToDto(DB.Resource source) {
-      if (source == null) return null;
-      return new DT.Resource { Id = source.ResourceId, Name = source.Name, ParentResourceId = source.ParentResourceId, HbInterval = source.HbInterval, OwnerUserId = source.OwnerUserId };
-    }
-    public static DB.Resource ToEntity(DT.Resource source) {
-      if (source == null) return null;
-      var entity = new DB.Resource(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.Resource source, DB.Resource target) {
-      if ((source != null) && (target != null)) {
-        target.ResourceId = source.Id; target.Name = source.Name; target.ParentResourceId = source.ParentResourceId; target.HbInterval = source.HbInterval; target.OwnerUserId = source.OwnerUserId;
-      }
-    }
-    #endregion
-
-    #region SlaveGroup
-    public static DT.SlaveGroup ToDto(DB.SlaveGroup source) {
-      if (source == null) return null;
-      return new DT.SlaveGroup { Id = source.ResourceId, Name = source.Name, ParentResourceId = source.ParentResourceId, HbInterval = source.HbInterval, OwnerUserId = source.OwnerUserId };
-    }
-    public static DB.SlaveGroup ToEntity(DT.SlaveGroup source) {
-      if (source == null) return null;
-      var entity = new DB.SlaveGroup(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.SlaveGroup source, DB.SlaveGroup target) {
-      if ((source != null) && (target != null)) {
-        target.ResourceId = source.Id; target.Name = source.Name; target.ParentResourceId = source.ParentResourceId; target.HbInterval = source.HbInterval; target.OwnerUserId = source.OwnerUserId;
-      }
-    }
-    #endregion
-
-    #region Slave
-    public static DT.Slave ToDto(DB.Slave source) {
-      if (source == null) return null;
-      return new DT.Slave {
-        Id = source.ResourceId,
-        ParentResourceId = source.ParentResourceId,
-        Cores = source.Cores,
-        CpuSpeed = source.CpuSpeed,
-        FreeCores = source.FreeCores,
-        FreeMemory = source.FreeMemory,
-        IsAllowedToCalculate = source.IsAllowedToCalculate,
-        Memory = source.Memory,
-        Name = source.Name,
-        SlaveState = Convert.ToDto(source.SlaveState),
-        CpuArchitecture = Convert.ToDto(source.CpuArchitecture),
-        OperatingSystem = source.OperatingSystem,
-        LastHeartbeat = source.LastHeartbeat,
-        CpuUtilization = source.CpuUtilization,
-        HbInterval = source.HbInterval,
-        IsDisposable = source.IsDisposable,
-        OwnerUserId = source.OwnerUserId
-      };
-    }
-    public static DB.Slave ToEntity(DT.Slave source) {
-      if (source == null) return null;
-      var entity = new DB.Slave(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.Slave source, DB.Slave target) {
-      if ((source != null) && (target != null)) {
-        target.ResourceId = source.Id;
-        target.ParentResourceId = source.ParentResourceId;
-        target.Cores = source.Cores;
-        target.CpuSpeed = source.CpuSpeed;
-        target.FreeCores = source.FreeCores;
-        target.FreeMemory = source.FreeMemory;
-        target.IsAllowedToCalculate = source.IsAllowedToCalculate;
-        target.Memory = source.Memory;
-        target.Name = source.Name;
-        target.SlaveState = Convert.ToEntity(source.SlaveState);
-        target.CpuArchitecture = Convert.ToEntity(source.CpuArchitecture);
-        target.OperatingSystem = source.OperatingSystem;
-        target.LastHeartbeat = source.LastHeartbeat;
-        target.CpuUtilization = source.CpuUtilization;
-        target.HbInterval = source.HbInterval;
-        target.IsDisposable = source.IsDisposable;
-        target.OwnerUserId = source.OwnerUserId;
-      }
-    }
-    #endregion
-
-    #region ResourcePermission
-    public static DT.ResourcePermission ToDto(DB.ResourcePermission source) {
-      if (source == null) return null;
-      return new DT.ResourcePermission { ResourceId = source.ResourceId, GrantedUserId = source.GrantedUserId, GrantedByUserId = source.GrantedByUserId };
-    }
-    public static DB.ResourcePermission ToEntity(DT.ResourcePermission source) {
-      if (source == null) return null;
-      var entity = new DB.ResourcePermission(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.ResourcePermission source, DB.ResourcePermission target) {
-      if ((source != null) && (target != null)) {
-        target.ResourceId = source.ResourceId; target.GrantedUserId = source.GrantedUserId; target.GrantedByUserId = source.GrantedByUserId;
-      }
-    }
-    #endregion
-
-    #region SlaveStatistics
-    public static DT.SlaveStatistics ToDto(DB.SlaveStatistics source) {
-      if (source == null) return null;
-      return new DT.SlaveStatistics {
-        Id = source.StatisticsId,
-        SlaveId = source.SlaveId,
-        Cores = source.Cores,
-        CpuUtilization = source.CpuUtilization,
-        FreeCores = source.FreeCores,
-        FreeMemory = source.FreeMemory,
-        Memory = source.Memory
-      };
-    }
-    public static DB.SlaveStatistics ToEntity(DT.SlaveStatistics source) {
-      if (source == null) return null;
-      var entity = new DB.SlaveStatistics(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.SlaveStatistics source, DB.SlaveStatistics target) {
-      if ((source != null) && (target != null)) {
-        target.StatisticsId = source.Id;
-        target.SlaveId = source.SlaveId;
-        target.Cores = source.Cores;
-        target.CpuUtilization = source.CpuUtilization;
-        target.FreeCores = source.FreeCores;
-        target.FreeMemory = source.FreeMemory;
-        target.Memory = source.Memory;
-      }
-    }
-    #endregion
-
-    #region Statistics
-    public static DT.Statistics ToDto(DB.Statistics source) {
-      if (source == null) return null;
-      return new DT.Statistics {
-        Id = source.StatisticsId,
-        TimeStamp = source.Timestamp,
-        SlaveStatistics = source.SlaveStatistics.Select(x => Convert.ToDto(x)).ToArray(),
-        UserStatistics = source.UserStatistics.Select(x => Convert.ToDto(x)).ToArray()
-      };
-    }
-    public static DB.Statistics ToEntity(DT.Statistics source) {
-      if (source == null) return null;
-      var entity = new DB.Statistics(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.Statistics source, DB.Statistics target) {
-      if ((source != null) && (target != null)) {
-        target.StatisticsId = source.Id;
-        target.Timestamp = source.TimeStamp;
-
-      }
-    }
-    #endregion
-
-    #region UserStatistics
-    public static DT.UserStatistics ToDto(DB.UserStatistics source) {
-      if (source == null) return null;
-      return new DT.UserStatistics {
-        Id = source.StatisticsId,
-        UserId = source.UserId,
-        UsedCores = source.UsedCores,
-        ExecutionTime = TimeSpan.FromMilliseconds(source.ExecutionTimeMs),
-        ExecutionTimeFinishedJobs = TimeSpan.FromMilliseconds(source.ExecutionTimeMsFinishedJobs),
-        StartToEndTime = TimeSpan.FromMilliseconds(source.StartToEndTimeMs)
-      };
-    }
-    public static DB.UserStatistics ToEntity(DT.UserStatistics source) {
-      if (source == null) return null;
-      var entity = new DB.UserStatistics(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.UserStatistics source, DB.UserStatistics target) {
-      if ((source != null) && (target != null)) {
-        target.StatisticsId = source.Id;
-        target.UserId = source.UserId;
-        target.UsedCores = source.UsedCores;
-        target.ExecutionTimeMs = source.ExecutionTime.TotalMilliseconds;
-        target.ExecutionTimeMsFinishedJobs = source.ExecutionTimeFinishedJobs.TotalMilliseconds;
-        target.StartToEndTimeMs = source.StartToEndTime.TotalMilliseconds;
-      }
-    }
-    #endregion
-
-    #region TaskData
-    public static DT.TaskState ToDto(DB.TaskState source) {
-      if (source == DB.TaskState.Aborted) {
-        return TaskState.Aborted;
-      } else if (source == DB.TaskState.Calculating) {
-        return TaskState.Calculating;
-      } else if (source == DB.TaskState.Failed) {
-        return TaskState.Failed;
-      } else if (source == DB.TaskState.Finished) {
-        return TaskState.Finished;
-      } else if (source == DB.TaskState.Offline) {
-        return TaskState.Offline;
-      } else if (source == DB.TaskState.Paused) {
-        return TaskState.Paused;
-      } else if (source == DB.TaskState.Transferring) {
-        return TaskState.Transferring;
-      } else if (source == DB.TaskState.Waiting) {
-        return TaskState.Waiting;
-      } else
-        return TaskState.Failed;
-    }
-
-    public static DB.TaskState ToEntity(DT.TaskState source) {
-      if (source == DT.TaskState.Aborted) {
-        return DB.TaskState.Aborted;
-      } else if (source == DT.TaskState.Calculating) {
-        return DB.TaskState.Calculating;
-      } else if (source == DT.TaskState.Failed) {
-        return DB.TaskState.Failed;
-      } else if (source == DT.TaskState.Finished) {
-        return DB.TaskState.Finished;
-      } else if (source == DT.TaskState.Offline) {
-        return DB.TaskState.Offline;
-      } else if (source == DT.TaskState.Paused) {
-        return DB.TaskState.Paused;
-      } else if (source == DT.TaskState.Transferring) {
-        return DB.TaskState.Transferring;
-      } else if (source == DT.TaskState.Waiting) {
-        return DB.TaskState.Waiting;
-      } else
-        return DB.TaskState.Failed;
-    }
-    #endregion
-
-    #region Permission
-    public static DT.Permission ToDto(DB.Permission source) {
-      if (source == DB.Permission.Full) {
-        return Permission.Full;
-      } else if (source == DB.Permission.NotAllowed) {
-        return Permission.NotAllowed;
-      } else if (source == DB.Permission.Read) {
-        return Permission.Read;
-      } else
-        return Permission.NotAllowed;
-    }
-
-    public static DB.Permission ToEntity(DT.Permission source) {
-      if (source == DT.Permission.Full) {
-        return DB.Permission.Full;
-      } else if (source == DT.Permission.NotAllowed) {
-        return DB.Permission.NotAllowed;
-      } else if (source == DT.Permission.Read) {
-        return DB.Permission.Read;
-      } else
-        return DB.Permission.NotAllowed;
-    }
-    #endregion
-
-    #region Command
-    public static DT.Command? ToDto(DB.Command? source) {
-      if (source.HasValue) {
-        if (source.Value == DB.Command.Abort) {
-          return Command.Abort;
-        } else if (source.Value == DB.Command.Pause) {
-          return Command.Pause;
-        } else if (source.Value == DB.Command.Stop) {
-          return Command.Stop;
-        } else
-          return Command.Pause;
-      }
-      return null;
-    }
-
-    public static DB.Command? ToEntity(DT.Command? source) {
-      if (source.HasValue) {
-        if (source == DT.Command.Abort) {
-          return DB.Command.Abort;
-        } else if (source == DT.Command.Pause) {
-          return DB.Command.Pause;
-        } else if (source == DT.Command.Stop) {
-          return DB.Command.Stop;
-        } else
-          return DB.Command.Pause;
-      } else
-        return null;
-    }
-    #endregion
-
-    #region CpuArchiteture
-    public static DT.CpuArchitecture ToDto(DB.CpuArchitecture source) {
-      if (source == DB.CpuArchitecture.x64) {
-        return CpuArchitecture.x64;
-      } else if (source == DB.CpuArchitecture.x86) {
-        return CpuArchitecture.x86;
-      } else
-        return CpuArchitecture.x86;
-    }
-
-    public static DB.CpuArchitecture ToEntity(DT.CpuArchitecture source) {
-      if (source == DT.CpuArchitecture.x64) {
-        return DB.CpuArchitecture.x64;
-      } else if (source == DT.CpuArchitecture.x86) {
-        return DB.CpuArchitecture.x86;
-      } else
-        return DB.CpuArchitecture.x86;
-    }
-    #endregion
-
-    #region SlaveState
-    public static DT.SlaveState ToDto(DB.SlaveState source) {
-      if (source == DB.SlaveState.Calculating) {
-        return SlaveState.Calculating;
-      } else if (source == DB.SlaveState.Idle) {
-        return SlaveState.Idle;
-      } else if (source == DB.SlaveState.Offline) {
-        return SlaveState.Offline;
-      } else
-        return SlaveState.Offline;
-    }
-
-    public static DB.SlaveState ToEntity(DT.SlaveState source) {
-      if (source == DT.SlaveState.Calculating) {
-        return DB.SlaveState.Calculating;
-      } else if (source == DT.SlaveState.Idle) {
-        return DB.SlaveState.Idle;
-      } else if (source == DT.SlaveState.Offline) {
-        return DB.SlaveState.Offline;
-      } else
-        return DB.SlaveState.Offline;
-    }
-    #endregion
-
-    #region UserPriority
-    public static DT.UserPriority ToDto(DB.UserPriority source) {
-      if (source == null) return null;
-      return new DT.UserPriority() { Id = source.UserId, DateEnqueued = source.DateEnqueued };
-    }
-    public static DB.UserPriority ToEntity(DT.UserPriority source) {
-      if (source == null) return null;
-      var entity = new DB.UserPriority(); ToEntity(source, entity);
-      return entity;
-    }
-    public static void ToEntity(DT.UserPriority source, DB.UserPriority target) {
-      if ((source != null) && (target != null)) {
-        target.UserId = source.Id;
-        target.DateEnqueued = source.DateEnqueued;
-      }
-    }
-    #endregion
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Converter.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Converter.cs	(revision 12878)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Converter.cs	(revision 12878)
@@ -0,0 +1,528 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using System.Linq;
+using DA = HeuristicLab.Services.Hive.DataAccess;
+using DT = HeuristicLab.Services.Hive.DataTransfer;
+
+namespace HeuristicLab.Services.Hive {
+  public static class Converter {
+
+    #region Task
+    public static DT.Task ToDto(this DA.Task source) {
+      if (source == null) return null;
+      return new DT.Task {
+        Id = source.TaskId,
+        State = source.State.ToDto(),
+        ExecutionTime = TimeSpan.FromMilliseconds(source.ExecutionTimeMs),
+        LastHeartbeat = source.LastHeartbeat,
+        ParentTaskId = source.ParentTaskId,
+        Priority = source.Priority,
+        CoresNeeded = source.CoresNeeded,
+        MemoryNeeded = source.MemoryNeeded,
+        IsParentTask = source.IsParentTask,
+        FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished,
+        Command = source.Command.ToDto(),
+        JobId = source.JobId,
+        IsPrivileged = source.IsPrivileged,
+        PluginsNeededIds = source.RequiredPlugins.Select(x => x.PluginId).ToList(),
+        StateLog = source.StateLogs.Select(x => x.ToDto()).OrderBy(x => x.DateTime).ToList(),
+        LastTaskDataUpdate = source.JobData == null ? DateTime.MinValue : source.JobData.LastUpdate
+      };
+    }
+
+    public static DA.Task ToEntity(this DT.Task source) {
+      if (source == null) return null;
+      var result = new DA.Task();
+      source.CopyToEntity(result);
+      return result;
+    }
+
+    public static void CopyToEntity(this DT.Task source, DA.Task target) {
+      if ((source == null) || (target == null)) return;
+      target.TaskId = source.Id;
+      target.State = source.State.ToEntity();
+      target.ExecutionTimeMs = source.ExecutionTime.TotalMilliseconds;
+      target.LastHeartbeat = source.LastHeartbeat;
+      target.ParentTaskId = source.ParentTaskId;
+      target.Priority = source.Priority;
+      target.CoresNeeded = source.CoresNeeded;
+      target.MemoryNeeded = source.MemoryNeeded;
+      target.IsParentTask = source.IsParentTask;
+      target.FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished;
+      target.Command = source.Command.ToEntity();
+      target.JobId = source.JobId;
+      target.IsPrivileged = source.IsPrivileged;
+      var ids = target.RequiredPlugins.Select(x => x.PluginId);
+      target.RequiredPlugins.AddRange(source.PluginsNeededIds
+        .Where(x => !ids.Contains(x))
+        .Select(x => new DA.RequiredPlugin {
+          PluginId = x
+        })
+      );
+      target.StateLogs.AddRange(source.StateLog
+        .Where(x => x.Id == Guid.Empty)
+        .Select(x => x.ToEntity())
+      );
+      // result.JobData missing
+      // result.AssignedResources missing
+    }
+    #endregion
+
+    #region TaskData
+    public static DT.TaskData ToDto(this DA.TaskData source) {
+      if (source == null) return null;
+      return new DT.TaskData {
+        TaskId = source.TaskId,
+        Data = source.Data,
+        LastUpdate = source.LastUpdate
+      };
+    }
+
+    public static DA.TaskData ToEntity(this DT.TaskData source) {
+      if (source == null) return null;
+      var result = new DA.TaskData();
+      source.CopyToEntity(result);
+      return result;
+    }
+
+    public static void CopyToEntity(this DT.TaskData source, DA.TaskData target) {
+      if ((source == null) || (target == null)) return;
+      target.TaskId = source.TaskId;
+      target.Data = source.Data;
+      target.LastUpdate = source.LastUpdate;
+    }
+    #endregion
+
+    #region Job
+    public static DT.Job ToDto(this DA.Job source) {
+      return new DT.Job {
+        Id = source.JobId,
+        Description = source.Description,
+        Name = source.Name,
+        OwnerUserId = source.OwnerUserId,
+        DateCreated = source.DateCreated,
+        ResourceNames = source.ResourceIds
+      };
+    }
+
+    public static DA.Job ToEntity(this DT.Job source) {
+      if (source == null) return null;
+      var result = new DA.Job();
+      source.CopyToEntity(result);
+      return result;
+    }
+
+    public static void CopyToEntity(this DT.Job source, DA.Job target) {
+      if ((source == null) || (target == null)) return;
+      target.JobId = source.Id;
+      target.Description = source.Description;
+      target.Name = source.Name;
+      target.OwnerUserId = source.OwnerUserId;
+      target.DateCreated = source.DateCreated;
+      target.ResourceIds = source.ResourceNames;
+    }
+    #endregion
+
+    #region JobPermission
+    public static DT.JobPermission ToDto(this DA.JobPermission source) {
+      if (source == null) return null;
+      return new DT.JobPermission {
+        JobId = source.JobId,
+        GrantedUserId = source.GrantedUserId,
+        GrantedByUserId = source.GrantedByUserId,
+        Permission = source.Permission.ToDto()
+      };
+    }
+
+    public static DA.JobPermission ToEntity(this DT.JobPermission source) {
+      if (source == null) return null;
+      var result = new DA.JobPermission();
+      source.CopyToEntity(result);
+      return result;
+    }
+
+    public static void CopyToEntity(this DT.JobPermission source, DA.JobPermission target) {
+      if ((source == null) || (target == null)) return;
+      target.JobId = source.JobId;
+      target.GrantedUserId = source.GrantedUserId;
+      target.GrantedByUserId = source.GrantedByUserId;
+      target.Permission = source.Permission.ToEntity();
+    }
+    #endregion
+
+    #region Slave
+    public static DT.Slave ToDto(this DA.Slave source) {
+      if (source == null) return null;
+      return new DT.Slave {
+        Id = source.ResourceId,
+        ParentResourceId = source.ParentResourceId,
+        Cores = source.Cores,
+        CpuSpeed = source.CpuSpeed,
+        FreeCores = source.FreeCores,
+        FreeMemory = source.FreeMemory,
+        IsAllowedToCalculate = source.IsAllowedToCalculate,
+        Memory = source.Memory,
+        Name = source.Name,
+        SlaveState = source.SlaveState.ToDto(),
+        CpuArchitecture = source.CpuArchitecture.ToDto(),
+        OperatingSystem = source.OperatingSystem,
+        LastHeartbeat = source.LastHeartbeat,
+        CpuUtilization = source.CpuUtilization,
+        HbInterval = source.HbInterval,
+        IsDisposable = source.IsDisposable,
+        OwnerUserId = source.OwnerUserId
+      };
+    }
+    public static DA.Slave ToEntity(this DT.Slave source) {
+      if (source == null) return null;
+      var result = new DA.Slave();
+      source.CopyToEntity(result);
+      return result;
+    }
+    public static void CopyToEntity(this DT.Slave source, DA.Slave target) {
+      if ((source == null) || (target == null)) return;
+      target.ResourceId = source.Id;
+      target.ParentResourceId = source.ParentResourceId;
+      target.Cores = source.Cores;
+      target.CpuSpeed = source.CpuSpeed;
+      target.FreeCores = source.FreeCores;
+      target.FreeMemory = source.FreeMemory;
+      target.IsAllowedToCalculate = source.IsAllowedToCalculate;
+      target.Memory = source.Memory;
+      target.Name = source.Name;
+      target.SlaveState = source.SlaveState.ToEntity();
+      target.CpuArchitecture = source.CpuArchitecture.ToEntity();
+      target.OperatingSystem = source.OperatingSystem;
+      target.LastHeartbeat = source.LastHeartbeat;
+      target.CpuUtilization = source.CpuUtilization;
+      target.HbInterval = source.HbInterval;
+      target.IsDisposable = source.IsDisposable;
+      target.OwnerUserId = source.OwnerUserId;
+    }
+    #endregion
+
+    #region State
+    public static DT.TaskState ToDto(this DA.TaskState source) {
+      switch (source) {
+        case DA.TaskState.Aborted: return DT.TaskState.Aborted;
+        case DA.TaskState.Calculating: return DT.TaskState.Calculating;
+        case DA.TaskState.Failed: return DT.TaskState.Failed;
+        case DA.TaskState.Finished: return DT.TaskState.Finished;
+        case DA.TaskState.Offline: return DT.TaskState.Offline;
+        case DA.TaskState.Paused: return DT.TaskState.Paused;
+        case DA.TaskState.Transferring: return DT.TaskState.Transferring;
+        case DA.TaskState.Waiting: return DT.TaskState.Waiting;
+        default: return DT.TaskState.Failed;
+      }
+    }
+
+    public static DA.TaskState ToEntity(this DT.TaskState source) {
+      switch (source) {
+        case DT.TaskState.Aborted: return DA.TaskState.Aborted;
+        case DT.TaskState.Calculating: return DA.TaskState.Calculating;
+        case DT.TaskState.Failed: return DA.TaskState.Failed;
+        case DT.TaskState.Finished: return DA.TaskState.Finished;
+        case DT.TaskState.Offline: return DA.TaskState.Offline;
+        case DT.TaskState.Paused: return DA.TaskState.Paused;
+        case DT.TaskState.Transferring: return DA.TaskState.Transferring;
+        case DT.TaskState.Waiting: return DA.TaskState.Waiting;
+        default: return DA.TaskState.Failed;
+      }
+    }
+    #endregion
+
+    #region StateLogs
+    public static DT.StateLog ToDto(this DA.StateLog source) {
+      return new DT.StateLog {
+        Id = source.StateLogId,
+        State = source.State.ToDto(),
+        DateTime = source.DateTime,
+        TaskId = source.TaskId,
+        UserId = source.UserId,
+        SlaveId = source.SlaveId,
+        Exception = source.Exception
+      };
+    }
+
+    public static DA.StateLog ToEntity(this DT.StateLog source) {
+      return new DA.StateLog {
+        StateLogId = source.Id,
+        State = source.State.ToEntity(),
+        DateTime = source.DateTime,
+        TaskId = source.TaskId,
+        UserId = source.UserId,
+        SlaveId = source.SlaveId,
+        Exception = source.Exception
+      };
+    }
+    #endregion
+
+    #region Plugin
+    public static DT.Plugin ToDto(this DA.Plugin source) {
+      if (source == null) return null;
+      return new DT.Plugin {
+        Id = source.PluginId,
+        Name = source.Name,
+        Version = new Version(source.Version),
+        UserId = source.UserId,
+        DateCreated = source.DateCreated,
+        Hash = source.Hash
+      };
+    }
+    public static DA.Plugin ToEntity(this DT.Plugin source) {
+      if (source == null) return null;
+      var result = new DA.Plugin();
+      source.CopyToEntity(result);
+      return result;
+    }
+    public static void CopyToEntity(this DT.Plugin source, DA.Plugin target) {
+      if ((source == null) || (target == null)) return;
+      target.PluginId = source.Id;
+      target.Name = source.Name;
+      target.Version = source.Version.ToString();
+      target.UserId = source.UserId;
+      target.DateCreated = source.DateCreated;
+      target.Hash = source.Hash;
+    }
+    #endregion
+
+    #region PluginData
+    public static DT.PluginData ToDto(this DA.PluginData source) {
+      if (source == null) return null;
+      return new DT.PluginData {
+        Id = source.PluginDataId,
+        PluginId = source.PluginId,
+        Data = source.Data.ToArray(),
+        FileName = source.FileName
+      };
+    }
+
+    public static DA.PluginData ToEntity(this DT.PluginData source) {
+      if (source == null) return null;
+      var result = new DA.PluginData();
+      source.CopyToEntity(result);
+      return result;
+    }
+
+    public static void CopyToEntity(this DT.PluginData source, DA.PluginData target) {
+      if ((source == null) || (target == null)) return;
+      target.PluginDataId = source.Id;
+      target.PluginId = source.PluginId;
+      target.Data = source.Data;
+      target.FileName = source.FileName;
+    }
+    #endregion
+
+    #region ResourcePermission
+    public static DT.ResourcePermission ToDto(this DA.ResourcePermission source) {
+      if (source == null) return null;
+      return new DT.ResourcePermission {
+        ResourceId = source.ResourceId,
+        GrantedUserId = source.GrantedUserId,
+        GrantedByUserId = source.GrantedByUserId
+      };
+    }
+    public static DA.ResourcePermission ToEntity(this DT.ResourcePermission source) {
+      if (source == null) return null;
+      var result = new DA.ResourcePermission();
+      source.CopyToEntity(result);
+      return result;
+    }
+    public static void CopyToEntity(this DT.ResourcePermission source, DA.ResourcePermission target) {
+      if ((source == null) || (target == null)) return;
+      target.ResourceId = source.ResourceId;
+      target.GrantedUserId = source.GrantedUserId;
+      target.GrantedByUserId = source.GrantedByUserId;
+    }
+    #endregion
+
+    #region SlaveGroup
+    public static DT.SlaveGroup ToDto(this DA.SlaveGroup source) {
+      if (source == null) return null;
+      return new DT.SlaveGroup {
+        Id = source.ResourceId,
+        Name = source.Name,
+        ParentResourceId = source.ParentResourceId,
+        HbInterval = source.HbInterval,
+        OwnerUserId = source.OwnerUserId
+      };
+    }
+
+    public static DA.SlaveGroup ToEntity(this DT.SlaveGroup source) {
+      if (source == null) return null;
+      var result = new DA.SlaveGroup();
+      source.CopyToEntity(result);
+      return result;
+    }
+
+    public static void CopyToEntity(this DT.SlaveGroup source, DA.SlaveGroup target) {
+      if ((source == null) || (target == null)) return;
+      target.ResourceId = source.Id;
+      target.Name = source.Name;
+      target.ParentResourceId = source.ParentResourceId;
+      target.HbInterval = source.HbInterval;
+      target.OwnerUserId = source.OwnerUserId;
+    }
+    #endregion
+
+    #region Downtimes
+    public static DT.Downtime ToDto(this DA.Downtime source) {
+      if (source == null) return null;
+      return new DT.Downtime {
+        Id = source.DowntimeId,
+        AllDayEvent = source.AllDayEvent,
+        EndDate = source.EndDate,
+        Recurring = source.Recurring,
+        RecurringId = source.RecurringId,
+        ResourceId = source.ResourceId,
+        StartDate = source.StartDate,
+        DowntimeType = source.DowntimeType
+      };
+    }
+    public static DA.Downtime ToEntity(this DT.Downtime source) {
+      if (source == null) return null;
+      var result = new DA.Downtime();
+      source.CopyToEntity(result);
+      return result;
+    }
+    public static void CopyToEntity(this DT.Downtime source, DA.Downtime target) {
+      if ((source == null) || (target == null)) return;
+      target.DowntimeId = source.Id;
+      target.AllDayEvent = source.AllDayEvent;
+      target.EndDate = source.EndDate;
+      target.Recurring = source.Recurring;
+      target.RecurringId = source.RecurringId;
+      target.ResourceId = source.ResourceId;
+      target.StartDate = source.StartDate;
+      target.DowntimeType = source.DowntimeType;
+    }
+    #endregion
+
+
+    #region Command
+    public static DT.Command? ToDto(this DA.Command? source) {
+      if (source.HasValue) {
+        switch (source) {
+          case DA.Command.Abort: return DT.Command.Abort;
+          case DA.Command.Pause: return DT.Command.Pause;
+          case DA.Command.Stop: return DT.Command.Stop;
+          default: return DT.Command.Pause;
+        }
+      }
+      return null;
+    }
+
+    public static DA.Command? ToEntity(this DT.Command? source) {
+      if (source.HasValue) {
+        switch (source) {
+          case DT.Command.Abort: return DA.Command.Abort;
+          case DT.Command.Pause: return DA.Command.Pause;
+          case DT.Command.Stop: return DA.Command.Stop;
+          default: return DA.Command.Pause;
+        }
+      }
+      return null;
+    }
+    #endregion
+
+    #region Permission
+    public static DT.Permission ToDto(this DA.Permission source) {
+      switch (source) {
+        case DA.Permission.Full: return DT.Permission.Full;
+        case DA.Permission.NotAllowed: return DT.Permission.NotAllowed;
+        case DA.Permission.Read: return DT.Permission.Read;
+        default: return DT.Permission.NotAllowed;
+      }
+    }
+
+    public static DA.Permission ToEntity(this DT.Permission source) {
+      switch (source) {
+        case DT.Permission.Full: return DA.Permission.Full;
+        case DT.Permission.NotAllowed: return DA.Permission.NotAllowed;
+        case DT.Permission.Read: return DA.Permission.Read;
+        default: return DA.Permission.NotAllowed;
+      }
+    }
+    #endregion
+
+    #region CpuArchiteture
+    public static DT.CpuArchitecture ToDto(this DA.CpuArchitecture source) {
+      switch (source) {
+        case DA.CpuArchitecture.x64: return DT.CpuArchitecture.x64;
+        case DA.CpuArchitecture.x86: return DT.CpuArchitecture.x86;
+        default: return DT.CpuArchitecture.x86;
+      }
+    }
+
+    public static DA.CpuArchitecture ToEntity(this DT.CpuArchitecture source) {
+      switch (source) {
+        case DT.CpuArchitecture.x64: return DA.CpuArchitecture.x64;
+        case DT.CpuArchitecture.x86: return DA.CpuArchitecture.x86;
+        default: return DA.CpuArchitecture.x86;
+      }
+    }
+    #endregion
+
+    #region SlaveState
+    public static DT.SlaveState ToDto(this DA.SlaveState source) {
+      switch (source) {
+        case DA.SlaveState.Calculating: return DT.SlaveState.Calculating;
+        case DA.SlaveState.Idle: return DT.SlaveState.Idle;
+        case DA.SlaveState.Offline: return DT.SlaveState.Offline;
+        default: return DT.SlaveState.Offline;
+      }
+    }
+
+    public static DA.SlaveState ToEntity(this DT.SlaveState source) {
+      switch (source) {
+        case DT.SlaveState.Calculating: return DA.SlaveState.Calculating;
+        case DT.SlaveState.Idle: return DA.SlaveState.Idle;
+        case DT.SlaveState.Offline: return DA.SlaveState.Offline;
+        default: return DA.SlaveState.Offline;
+      }
+    }
+    #endregion
+
+    #region UserPriority
+    public static DT.UserPriority ToDto(this DA.UserPriority source) {
+      if (source == null) return null;
+      return new DT.UserPriority() {
+        Id = source.UserId,
+        DateEnqueued = source.DateEnqueued
+      };
+    }
+    public static DA.UserPriority ToEntity(this DT.UserPriority source) {
+      if (source == null) return null;
+      var result = new DA.UserPriority();
+      source.CopyToEntity(result);
+      return result;
+    }
+    public static void CopyToEntity(this DT.UserPriority source, DA.UserPriority target) {
+      if ((source == null) || (target == null)) return;
+      target.UserId = source.Id;
+      target.DateEnqueued = source.DateEnqueued;
+    }
+    #endregion
+
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/SlaveStatistics.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/SlaveStatistics.cs	(revision 12753)
+++ 	(revision )
@@ -1,42 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Runtime.Serialization;
-
-namespace HeuristicLab.Services.Hive.DataTransfer {
-  [DataContract]
-  [Serializable]
-  public class SlaveStatistics : HiveItem {
-    [DataMember]
-    public Guid SlaveId { get; set; }
-    [DataMember]
-    public int Cores { get; set; }
-    [DataMember]
-    public int FreeCores { get; set; }
-    [DataMember]
-    public int Memory { get; set; }
-    [DataMember]
-    public int FreeMemory { get; set; }
-    [DataMember]
-    public double CpuUtilization { get; set; }
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/Statistics.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/Statistics.cs	(revision 12753)
+++ 	(revision )
@@ -1,39 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-
-namespace HeuristicLab.Services.Hive.DataTransfer {
-  [DataContract]
-  [Serializable]
-  public class Statistics : HiveItem {
-    [DataMember]
-    public DateTime TimeStamp { get; set; }
-    [DataMember]
-    public IEnumerable<UserStatistics> UserStatistics { get; set; }
-    [DataMember]
-    public IEnumerable<SlaveStatistics> SlaveStatistics { get; set; }
-
-    public Statistics() { }
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/UserStatistics.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/UserStatistics.cs	(revision 12753)
+++ 	(revision )
@@ -1,40 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Runtime.Serialization;
-
-namespace HeuristicLab.Services.Hive.DataTransfer {
-  [DataContract]
-  [Serializable]
-  public class UserStatistics : HiveItem {
-    [DataMember]
-    public Guid UserId { get; set; }
-    [DataMember]
-    public int UsedCores { get; set; }
-    [DataMember]
-    public TimeSpan ExecutionTime { get; set; }
-    [DataMember]
-    public TimeSpan ExecutionTimeFinishedJobs { get; set; }
-    [DataMember]
-    public TimeSpan StartToEndTime { get; set; }
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/HeuristicLab.Services.Hive-3.3.csproj
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/HeuristicLab.Services.Hive-3.3.csproj	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/HeuristicLab.Services.Hive-3.3.csproj	(revision 12878)
@@ -118,5 +118,5 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="Convert.cs" />
+    <Compile Include="Converter.cs" />
     <Compile Include="DataTransfer\Command.cs" />
     <Compile Include="DataTransfer\UserPriority.cs" />
@@ -139,19 +139,14 @@
     <Compile Include="DataTransfer\SlaveGroup.cs" />
     <Compile Include="DataTransfer\SlaveState.cs" />
-    <Compile Include="DataTransfer\SlaveStatistics.cs" />
     <Compile Include="DataTransfer\StateLog.cs" />
-    <Compile Include="DataTransfer\Statistics.cs" />
-    <Compile Include="DataTransfer\UserStatistics.cs" />
-    <Compile Include="OptimizedHiveDao.cs" />
-    <Compile Include="HiveDao.cs" />
+    <Compile Include="HiveStatisticsGenerator.cs" />
+    <Compile Include="Interfaces\IStatisticsGenerator.cs" />
     <Compile Include="HiveJanitor.cs" />
     <Compile Include="HiveOperationContext.cs" />
-    <Compile Include="Interfaces\IOptimizedHiveDao.cs" />
-    <Compile Include="Interfaces\IHiveDao.cs" />
     <Compile Include="Interfaces\ITaskScheduler.cs" />
+    <Compile Include="PerformanceLogger.cs" />
     <Compile Include="Scheduler\TaskInfoForScheduler.cs" />
     <Compile Include="Scheduler\JobInfoForScheduler.cs" />
     <Compile Include="Scheduler\RoundRobinTaskScheduler.cs" />
-    <Compile Include="Settings.cs" />
     <None Include="app.config" />
     <None Include="Plugin.cs.frame" />
@@ -182,4 +177,8 @@
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Services.Access.DataAccess\3.3\HeuristicLab.Services.Access.DataAccess-3.3.csproj">
+      <Project>{0F652437-998A-4EAB-8BF1-444B5FE8CE97}</Project>
+      <Name>HeuristicLab.Services.Access.DataAccess-3.3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Services.Access\3.3\HeuristicLab.Services.Access-3.3.csproj">
       <Project>{9FAC0B23-2730-452A-9BA0-D7CA1746C541}</Project>
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 12753)
+++ 	(revision )
@@ -1,996 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Collections.Generic;
-using System.Data.Linq;
-using System.Linq;
-using System.Linq.Expressions;
-using DT = HeuristicLab.Services.Hive.DataTransfer;
-
-namespace HeuristicLab.Services.Hive.DataAccess {
-  public class HiveDao : IHiveDao {
-    public static HiveDataContext CreateContext(bool longRunning = false) {
-      var context = new HiveDataContext(Settings.Default.HeuristicLab_Hive_LinqConnectionString);
-      if (longRunning) context.CommandTimeout = (int)Settings.Default.LongRunningDatabaseCommandTimeout.TotalSeconds;
-      return context;
-    }
-
-    #region Task Methods
-    public DT.Task GetTask(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.Tasks.SingleOrDefault(x => x.TaskId == id));
-      }
-    }
-
-    public IEnumerable<DT.Task> GetTasks(Expression<Func<Task, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Tasks.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public IEnumerable<DT.LightweightTask> GetLightweightTasks(Expression<Func<Task, bool>> predicate) {
-      List<DT.LightweightTask> tasks = new List<DT.LightweightTask>();
-
-      using (var db = CreateContext()) {
-        var tasksQuery = db.Tasks.Where(predicate).Select(task => new { task.TaskId, task.ExecutionTimeMs, task.ParentTaskId, task.StateLogs, task.State, task.Command });
-        var taskDatasQuery = db.Tasks.Where(predicate).Where(task => task.JobData != null).Select(task => new { task.TaskId, task.JobData.LastUpdate });
-
-        foreach (var task in tasksQuery) {
-          DT.LightweightTask t = new DT.LightweightTask();
-          t.Id = task.TaskId;
-          t.ExecutionTime = TimeSpan.FromMilliseconds(task.ExecutionTimeMs);
-          t.ParentTaskId = task.ParentTaskId;
-          t.StateLog = task.StateLogs == null ? new List<DT.StateLog>() : task.StateLogs.Select(x => DataTransfer.Convert.ToDto(x)).OrderBy(x => x.DateTime).ToList();
-          t.State = DataTransfer.Convert.ToDto(task.State);
-          t.Command = DataTransfer.Convert.ToDto(task.Command);
-          t.LastTaskDataUpdate = taskDatasQuery.Where(x => x.TaskId == task.TaskId).Count() > 0 ? taskDatasQuery.Select(x => x.LastUpdate).First() : DateTime.MinValue;
-          tasks.Add(t);
-        }
-      }
-      return tasks;
-    }
-
-    public IEnumerable<DT.LightweightTask> GetLightweightTasksWithoutStateLog(Expression<Func<Task, bool>> predicate) {
-      List<DT.LightweightTask> tasks = new List<DT.LightweightTask>();
-
-      using (var db = CreateContext()) {
-        var tasksQuery = db.Tasks.Where(predicate).Select(task => new { task.TaskId, task.ExecutionTimeMs, task.ParentTaskId, task.State, task.Command });
-        var taskDatasQuery = db.Tasks.Where(predicate).Where(task => task.JobData != null).Select(task => new { task.TaskId, task.JobData.LastUpdate });
-
-        foreach (var task in tasksQuery) {
-          DT.LightweightTask t = new DT.LightweightTask();
-          t.Id = task.TaskId;
-          t.ExecutionTime = TimeSpan.FromMilliseconds(task.ExecutionTimeMs);
-          t.ParentTaskId = task.ParentTaskId;
-          t.StateLog = new List<DT.StateLog>();
-          t.State = DataTransfer.Convert.ToDto(task.State);
-          t.Command = DataTransfer.Convert.ToDto(task.Command);
-          t.LastTaskDataUpdate = taskDatasQuery.Where(x => x.TaskId == task.TaskId).Count() > 0 ? taskDatasQuery.Select(x => x.LastUpdate).First() : DateTime.MinValue;
-          tasks.Add(t);
-        }
-      }
-      return tasks;
-    }
-
-    public Guid AddTask(DT.Task dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.Tasks.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        foreach (Guid pluginId in dto.PluginsNeededIds) {
-          db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
-        }
-        db.SubmitChanges();
-        return entity.TaskId;
-      }
-    }
-
-    public void UpdateTaskAndPlugins(DT.Task dto) {
-      using (var db = CreateContext()) {
-        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
-        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        foreach (Guid pluginId in dto.PluginsNeededIds) {
-          if (db.RequiredPlugins.Count(p => p.PluginId == pluginId) == 0) {
-            db.RequiredPlugins.InsertOnSubmit(new RequiredPlugin() { TaskId = entity.TaskId, PluginId = pluginId });
-          }
-        }
-        db.SubmitChanges();
-      }
-    }
-
-    public void UpdateTaskAndStateLogs(DT.Task dto) {
-      using (var db = CreateContext()) {
-        DataLoadOptions dlo = new DataLoadOptions();
-        dlo.LoadWith<Task>(x => x.StateLogs);
-        db.LoadOptions = dlo;
-
-        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
-        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void UpdateTask(DT.Task dto) {
-      using (var db = CreateContext()) {
-        db.DeferredLoadingEnabled = false;
-
-        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
-        if (entity == null) db.Tasks.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntityTaskOnly(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteTask(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Tasks.FirstOrDefault(x => x.TaskId == id);
-        if (entity != null) db.Tasks.DeleteOnSubmit(entity);
-        db.SubmitChanges(); // taskData and child tasks are deleted by db-trigger
-      }
-    }
-
-    /// <summary>
-    /// returns all parent tasks which are waiting for their child tasks to finish
-    /// </summary>
-    /// <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>
-    /// <returns></returns>
-    public IEnumerable<DT.Task> GetParentTasks(IEnumerable<Guid> resourceIds, int count, bool finished) {
-      using (var db = CreateContext()) {
-        var query = from ar in db.AssignedResources
-                    where resourceIds.Contains(ar.ResourceId)
-                       && ar.Task.State == TaskState.Waiting
-                       && ar.Task.IsParentTask
-                       && (finished ? ar.Task.FinishWhenChildJobsFinished : !ar.Task.FinishWhenChildJobsFinished)
-                       && (from child in db.Tasks
-                           where child.ParentTaskId == ar.Task.TaskId
-                           select child.State == TaskState.Finished
-                               || child.State == TaskState.Aborted
-                               || child.State == TaskState.Failed).All(x => x)
-                       && (from child in db.Tasks // avoid returning WaitForChildTasks task where no child-task exist (yet)
-                           where child.ParentTaskId == ar.Task.TaskId
-                           select child).Count() > 0
-                    orderby ar.Task.Priority descending, db.Random()
-                    select DT.Convert.ToDto(ar.Task);
-        return count == 0 ? query.ToArray() : query.Take(count).ToArray();
-      }
-    }
-
-    public IEnumerable<TaskInfoForScheduler> GetWaitingTasks(DT.Slave slave) {
-      using (var db = CreateContext()) {
-        var resourceIds = GetParentResources(slave.Id).Select(r => r.Id);
-        //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
-
-        var query = 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 };
-        var waitingTasks = query.ToArray();
-        return waitingTasks;
-      }
-    }
-
-    public DT.Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
-      using (var db = CreateContext()) {
-        db.DeferredLoadingEnabled = false;
-
-        db.StateLogs.InsertOnSubmit(new StateLog {
-          TaskId = taskId,
-          State = taskState,
-          SlaveId = slaveId,
-          UserId = userId,
-          Exception = exception,
-          DateTime = DateTime.Now
-        });
-
-        var task = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
-        task.State = taskState;
-        db.SubmitChanges();
-      }
-
-      using (var db = CreateContext()) {
-        var task = db.Tasks.SingleOrDefault(x => x.TaskId == taskId);
-        return DT.Convert.ToDto(task);
-      }
-    }
-    #endregion
-
-    #region TaskData Methods
-    public DT.TaskData GetTaskData(Guid id) {
-      using (var db = CreateContext(true)) {
-        return DT.Convert.ToDto(db.TaskDatas.SingleOrDefault(x => x.TaskId == id));
-      }
-    }
-
-    public IEnumerable<DT.TaskData> GetTaskDatas(Expression<Func<TaskData, bool>> predicate) {
-      using (var db = CreateContext(true)) {
-        return db.TaskDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddTaskData(DT.TaskData dto) {
-      using (var db = CreateContext(true)) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.TaskDatas.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.TaskId;
-      }
-    }
-
-    public void UpdateTaskData(DT.TaskData dto) {
-      using (var db = CreateContext(true)) {
-        var entity = db.TaskDatas.FirstOrDefault(x => x.TaskId == dto.TaskId);
-        if (entity == null) db.TaskDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteTaskData(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.TaskDatas.FirstOrDefault(x => x.TaskId == id); // check if all the byte[] is loaded into memory here. otherwise work around to delete without loading it
-        if (entity != null) db.TaskDatas.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region StateLog Methods
-    public DT.StateLog GetStateLog(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.StateLogs.SingleOrDefault(x => x.StateLogId == id));
-      }
-    }
-
-    public IEnumerable<DT.StateLog> GetStateLogs(Expression<Func<StateLog, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.StateLogs.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddStateLog(DT.StateLog dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.StateLogs.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.StateLogId;
-      }
-    }
-
-    public void UpdateStateLog(DT.StateLog dto) {
-      using (var db = CreateContext()) {
-        var entity = db.StateLogs.FirstOrDefault(x => x.StateLogId == dto.Id);
-        if (entity == null) db.StateLogs.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteStateLog(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.StateLogs.FirstOrDefault(x => x.StateLogId == id);
-        if (entity != null) db.StateLogs.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Job Methods
-    public DT.Job GetJob(Guid id) {
-      using (var db = CreateContext()) {
-        return AddStatsToJob(db, DT.Convert.ToDto(db.Jobs.SingleOrDefault(x => x.JobId == id)));
-      }
-    }
-
-    private DT.Job AddStatsToJob(HiveDataContext db, DT.Job exp) {
-      if (exp == null)
-        return null;
-
-      var jobs = db.Tasks.Where(j => j.JobId == exp.Id);
-      exp.JobCount = jobs.Count();
-      exp.CalculatingCount = jobs.Count(j => j.State == TaskState.Calculating);
-      exp.FinishedCount = jobs.Count(j => j.State == TaskState.Finished || j.State == TaskState.Aborted || j.State == TaskState.Failed);
-      return exp;
-    }
-
-    public IEnumerable<DT.Job> GetJobs(Expression<Func<Job, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Jobs.Where(predicate).Select(x => AddStatsToJob(db, DT.Convert.ToDto(x))).ToArray();
-      }
-    }
-
-    public IEnumerable<JobInfoForScheduler> GetJobInfoForScheduler(Expression<Func<Job, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Jobs.Where(predicate).Select(x => new JobInfoForScheduler() { Id = x.JobId, DateCreated = x.DateCreated, OwnerUserId = x.OwnerUserId }).ToArray();
-      }
-    }
-
-    public Guid AddJob(DT.Job dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.Jobs.InsertOnSubmit(entity);
-        if (!db.UserPriorities.Any(x => x.UserId == dto.OwnerUserId))
-          EnqueueUserPriority(new DT.UserPriority { Id = dto.OwnerUserId, DateEnqueued = dto.DateCreated });
-        db.SubmitChanges();
-        return entity.JobId;
-      }
-    }
-
-    public void UpdateJob(DT.Job dto) {
-      using (var db = CreateContext()) {
-        var entity = db.Jobs.FirstOrDefault(x => x.JobId == dto.Id);
-        if (entity == null) db.Jobs.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteJob(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Jobs.FirstOrDefault(x => x.JobId == id);
-        if (entity != null) db.Jobs.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region JobPermission Methods
-    public DT.JobPermission GetJobPermission(Guid jobId, Guid grantedUserId) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId));
-      }
-    }
-
-    public IEnumerable<DT.JobPermission> GetJobPermissions(Expression<Func<JobPermission, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.JobPermissions.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public void AddJobPermission(DT.JobPermission dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.JobPermissions.InsertOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void UpdateJobPermission(DT.JobPermission dto) {
-      using (var db = CreateContext()) {
-        var entity = db.JobPermissions.FirstOrDefault(x => x.JobId == dto.JobId && x.GrantedUserId == dto.GrantedUserId);
-        if (entity == null) db.JobPermissions.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteJobPermission(Guid jobId, Guid grantedUserId) {
-      using (var db = CreateContext()) {
-        var entity = db.JobPermissions.FirstOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
-        if (entity != null) db.JobPermissions.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-
-    /// <summary>
-    /// Sets the permissions for a experiment. makes sure that only one permission per user exists.
-    /// </summary>
-    public void SetJobPermission(Guid jobId, Guid grantedByUserId, Guid grantedUserId, Permission permission) {
-      using (var db = CreateContext()) {
-        JobPermission jobPermission = db.JobPermissions.SingleOrDefault(x => x.JobId == jobId && x.GrantedUserId == grantedUserId);
-        if (jobPermission != null) {
-          if (permission == Permission.NotAllowed) {
-            // not allowed, delete
-            db.JobPermissions.DeleteOnSubmit(jobPermission);
-          } else {
-            // update
-            jobPermission.Permission = permission;
-            jobPermission.GrantedByUserId = grantedByUserId; // update grantedByUserId, always the last "granter" is stored
-          }
-        } else {
-          // insert
-          if (permission != Permission.NotAllowed) {
-            jobPermission = new JobPermission() { JobId = jobId, GrantedByUserId = grantedByUserId, GrantedUserId = grantedUserId, Permission = permission };
-            db.JobPermissions.InsertOnSubmit(jobPermission);
-          }
-        }
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Plugin Methods
-    public DT.Plugin GetPlugin(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.Plugins.SingleOrDefault(x => x.PluginId == id));
-      }
-    }
-
-    public IEnumerable<DT.Plugin> GetPlugins(Expression<Func<Plugin, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Plugins.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddPlugin(DT.Plugin dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.Plugins.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.PluginId;
-      }
-    }
-
-    public void UpdatePlugin(DT.Plugin dto) {
-      using (var db = CreateContext()) {
-        var entity = db.Plugins.FirstOrDefault(x => x.PluginId == dto.Id);
-        if (entity == null) db.Plugins.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeletePlugin(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Plugins.FirstOrDefault(x => x.PluginId == id);
-        if (entity != null) db.Plugins.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region PluginData Methods
-    public DT.PluginData GetPluginData(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.PluginDatas.SingleOrDefault(x => x.PluginDataId == id));
-      }
-    }
-
-    public IEnumerable<DT.PluginData> GetPluginDatas(Expression<Func<PluginData, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.PluginDatas.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddPluginData(DT.PluginData dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.PluginDatas.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.PluginDataId;
-      }
-    }
-
-    public void UpdatePluginData(DT.PluginData dto) {
-      using (var db = CreateContext()) {
-        var entity = db.PluginDatas.FirstOrDefault(x => x.PluginId == dto.PluginId);
-        if (entity == null) db.PluginDatas.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeletePluginData(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.PluginDatas.FirstOrDefault(x => x.PluginDataId == id);
-        if (entity != null) db.PluginDatas.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Slave Methods
-    public DT.Slave GetSlave(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.Resources.OfType<Slave>().SingleOrDefault(x => x.ResourceId == id));
-      }
-    }
-
-    public IEnumerable<DT.Slave> GetSlaves(Expression<Func<Slave, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Resources.OfType<Slave>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddSlave(DT.Slave dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.Resources.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.ResourceId;
-      }
-    }
-
-    public void UpdateSlave(DT.Slave dto) {
-      using (var db = CreateContext()) {
-        var entity = db.Resources.OfType<Slave>().FirstOrDefault(x => x.ResourceId == dto.Id);
-        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteSlave(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Resources.OfType<Slave>().FirstOrDefault(x => x.ResourceId == id);
-        if (entity != null) db.Resources.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region SlaveGroup Methods
-    public DT.SlaveGroup GetSlaveGroup(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.Resources.OfType<SlaveGroup>().SingleOrDefault(x => x.ResourceId == id));
-      }
-    }
-
-    public IEnumerable<DT.SlaveGroup> GetSlaveGroups(Expression<Func<SlaveGroup, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Resources.OfType<SlaveGroup>().Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddSlaveGroup(DT.SlaveGroup dto) {
-      using (var db = CreateContext()) {
-        if (dto.Id == Guid.Empty)
-          dto.Id = Guid.NewGuid();
-        var entity = DT.Convert.ToEntity(dto);
-        db.Resources.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.ResourceId;
-      }
-    }
-
-    public void UpdateSlaveGroup(DT.SlaveGroup dto) {
-      using (var db = CreateContext()) {
-        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == dto.Id);
-        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteSlaveGroup(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Resources.OfType<SlaveGroup>().FirstOrDefault(x => x.ResourceId == id);
-        if (entity != null) {
-          if (db.Resources.Where(r => r.ParentResourceId == id).Count() > 0) {
-            throw new InvalidOperationException("Cannot delete SlaveGroup as long as there are Slaves in the group");
-          }
-          db.Resources.DeleteOnSubmit(entity);
-        }
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Resource Methods
-    public DT.Resource GetResource(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.Resources.SingleOrDefault(x => x.ResourceId == id));
-      }
-    }
-
-    public IEnumerable<DT.Resource> GetResources(Expression<Func<Resource, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Resources.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddResource(DT.Resource dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.Resources.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.ResourceId;
-      }
-    }
-
-    public void UpdateResource(DT.Resource dto) {
-      using (var db = CreateContext()) {
-        var entity = db.Resources.FirstOrDefault(x => x.ResourceId == dto.Id);
-        if (entity == null) db.Resources.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteResource(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Resources.FirstOrDefault(x => x.ResourceId == id);
-        if (entity != null) db.Resources.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void AssignJobToResource(Guid taskId, IEnumerable<Guid> resourceIds) {
-      using (var db = CreateContext()) {
-        db.DeferredLoadingEnabled = false;
-
-        List<AssignedResource> assignedResources = new List<AssignedResource>();
-        foreach (Guid rId in resourceIds) {
-          assignedResources.Add(new AssignedResource() { TaskId = taskId, ResourceId = rId });
-        }
-        db.AssignedResources.InsertAllOnSubmit(assignedResources);
-        db.SubmitChanges();
-      }
-    }
-
-    public IEnumerable<DT.Resource> GetAssignedResources(Guid jobId) {
-      using (var db = CreateContext()) {
-        var job = db.Tasks.Where(x => x.TaskId == jobId).Single();
-        return job.AssignedResources.Select(x => DT.Convert.ToDto(x.Resource)).ToArray();
-      }
-    }
-
-    /// <summary>
-    /// Returns all parent resources of a resource (the given resource is also added)
-    /// </summary>
-    public IEnumerable<DT.Resource> GetParentResources(Guid resourceId) {
-      using (var db = CreateContext()) {
-        var resources = new List<Resource>();
-        CollectParentResources(resources, db.Resources.Where(r => r.ResourceId == resourceId).Single());
-        return resources.Select(r => DT.Convert.ToDto(r)).ToArray();
-      }
-    }
-
-    private static void CollectParentResources(ICollection<Resource> resources, Resource resource) {
-      if (resource == null) return;
-      resources.Add(resource);
-      CollectParentResources(resources, resource.ParentResource);
-    }
-
-    /// <summary>
-    /// Returns all child resources of a resource (without the given resource)
-    /// </summary>
-    public IEnumerable<DT.Resource> GetChildResources(Guid resourceId) {
-      using (var db = CreateContext()) {
-        return CollectChildResources(resourceId, db);
-      }
-    }
-
-    public IEnumerable<DT.Resource> CollectChildResources(Guid resourceId, HiveDataContext db) {
-      var childs = new List<DT.Resource>();
-      foreach (var child in db.Resources.Where(x => x.ParentResourceId == resourceId)) {
-        childs.Add(DT.Convert.ToDto(child));
-        childs.AddRange(CollectChildResources(child.ResourceId, db));
-      }
-      return childs;
-    }
-
-    public IEnumerable<DT.Task> GetJobsByResourceId(Guid resourceId) {
-      using (var db = CreateContext()) {
-        var resources = GetChildResources(resourceId).Select(x => x.Id).ToList();
-        resources.Add(resourceId);
-
-        var jobs = db.Tasks.Where(j =>
-          j.State == TaskState.Calculating &&
-          j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.HasValue &&
-          resources.Contains(j.StateLogs.OrderByDescending(x => x.DateTime).First().SlaveId.Value));
-        return jobs.Select(j => DT.Convert.ToDto(j)).ToArray();
-      }
-    }
-    #endregion
-
-    #region ResourcePermission Methods
-    public DT.ResourcePermission GetResourcePermission(Guid resourceId, Guid grantedUserId) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.ResourcePermissions.SingleOrDefault(x => x.ResourceId == resourceId && x.GrantedUserId == grantedUserId));
-      }
-    }
-
-    public IEnumerable<DT.ResourcePermission> GetResourcePermissions(Expression<Func<ResourcePermission, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.ResourcePermissions.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public void AddResourcePermission(DT.ResourcePermission dto) {
-      using (var db = CreateContext()) {
-        var entity = db.ResourcePermissions.SingleOrDefault(x => x.ResourceId == dto.ResourceId && x.GrantedUserId == dto.GrantedUserId);
-        if (entity == null) { db.ResourcePermissions.InsertOnSubmit(DT.Convert.ToEntity(dto)); db.SubmitChanges(); }
-      }
-    }
-
-    public void UpdateResourcePermission(DT.ResourcePermission dto) {
-      using (var db = CreateContext()) {
-        var entity = db.ResourcePermissions.FirstOrDefault(x => x.ResourceId == dto.ResourceId && x.GrantedUserId == dto.GrantedUserId);
-        if (entity == null) db.ResourcePermissions.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteResourcePermission(Guid resourceId, Guid grantedUserId) {
-      using (var db = CreateContext()) {
-        var entity = db.ResourcePermissions.FirstOrDefault(x => x.ResourceId == resourceId && x.GrantedUserId == grantedUserId);
-        if (entity != null) db.ResourcePermissions.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Authorization Methods
-    public Permission GetPermissionForTask(Guid taskId, Guid userId) {
-      using (var db = CreateContext()) {
-        return GetPermissionForJob(GetJobForTask(taskId), userId);
-      }
-    }
-
-    public Permission GetPermissionForJob(Guid jobId, Guid userId) {
-      using (var db = CreateContext()) {
-        Job job = db.Jobs.SingleOrDefault(x => x.JobId == jobId);
-        if (job == null) return Permission.NotAllowed;
-        if (job.OwnerUserId == userId) return Permission.Full;
-        JobPermission permission = db.JobPermissions.SingleOrDefault(p => p.JobId == jobId && p.GrantedUserId == userId);
-        return permission != null ? permission.Permission : Permission.NotAllowed;
-      }
-    }
-
-    public Guid GetJobForTask(Guid taskId) {
-      using (var db = CreateContext()) {
-        return db.Tasks.Single(j => j.TaskId == taskId).JobId;
-      }
-    }
-    #endregion
-
-    #region Lifecycle Methods
-    public DateTime GetLastCleanup() {
-      using (var db = CreateContext()) {
-        var entity = db.Lifecycles.SingleOrDefault();
-        return entity != null ? entity.LastCleanup : DateTime.MinValue;
-      }
-    }
-
-    public void SetLastCleanup(DateTime datetime) {
-      using (var db = CreateContext()) {
-        var entity = db.Lifecycles.SingleOrDefault();
-        if (entity != null) {
-          entity.LastCleanup = datetime;
-        } else {
-          entity = new Lifecycle();
-          entity.LifecycleId = 0; // always only one entry with ID:0
-          entity.LastCleanup = datetime;
-          db.Lifecycles.InsertOnSubmit(entity);
-        }
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Downtime Methods
-    public DT.Downtime GetDowntime(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.Downtimes.SingleOrDefault(x => x.DowntimeId == id));
-      }
-    }
-
-    public IEnumerable<DT.Downtime> GetDowntimes(Expression<Func<Downtime, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Downtimes.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddDowntime(DT.Downtime dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.Downtimes.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        return entity.DowntimeId;
-      }
-    }
-
-    public void UpdateDowntime(DT.Downtime dto) {
-      using (var db = CreateContext()) {
-        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == dto.Id);
-        if (entity == null) db.Downtimes.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public void DeleteDowntime(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Downtimes.FirstOrDefault(x => x.DowntimeId == id);
-        if (entity != null) db.Downtimes.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Statistics Methods
-    public DT.Statistics GetStatistic(Guid id) {
-      using (var db = CreateContext()) {
-        return DT.Convert.ToDto(db.Statistics.SingleOrDefault(x => x.StatisticsId == id));
-      }
-    }
-
-    public IEnumerable<DT.Statistics> GetStatistics(Expression<Func<Statistics, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.Statistics.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public Guid AddStatistics(DT.Statistics dto) {
-      using (var db = CreateContext()) {
-        var entity = DT.Convert.ToEntity(dto);
-        db.Statistics.InsertOnSubmit(entity);
-        db.SubmitChanges();
-        foreach (var slaveStat in dto.SlaveStatistics) {
-          slaveStat.Id = entity.StatisticsId;
-          db.SlaveStatistics.InsertOnSubmit(DT.Convert.ToEntity(slaveStat));
-        }
-        if (dto.UserStatistics != null) {
-          foreach (var userStat in dto.UserStatistics) {
-            userStat.Id = entity.StatisticsId;
-            db.UserStatistics.InsertOnSubmit(DT.Convert.ToEntity(userStat));
-          }
-        }
-        db.SubmitChanges();
-        return entity.StatisticsId;
-      }
-    }
-
-    public void DeleteStatistics(Guid id) {
-      using (var db = CreateContext()) {
-        var entity = db.Statistics.FirstOrDefault(x => x.StatisticsId == id);
-        if (entity != null) db.Statistics.DeleteOnSubmit(entity);
-        db.SubmitChanges();
-      }
-    }
-
-    public Dictionary<Guid, int> GetWaitingTasksByUserForResources(List<Guid> resourceIds) {
-      using (var db = CreateContext()) {
-        var waitingTasksByUser = from task in db.Tasks
-                                 where task.State == TaskState.Waiting && task.AssignedResources.Any(x => resourceIds.Contains(x.ResourceId))
-                                 group task by task.Job.OwnerUserId into g
-                                 select new { UserId = g.Key, UsedCores = g.Count() };
-        return waitingTasksByUser.ToDictionary(x => x.UserId, x => x.UsedCores);
-      }
-    }
-
-    public Dictionary<Guid, int> GetCalculatingTasksByUserForResources(List<Guid> resourceIds) {
-      using (var db = CreateContext()) {
-        var calculatingTasksByUser = from task in db.Tasks
-                                     where task.State == TaskState.Calculating && task.AssignedResources.Any(x => resourceIds.Contains(x.ResourceId))
-                                     group task by task.Job.OwnerUserId into g
-                                     select new { UserId = g.Key, UsedCores = g.Count() };
-        return calculatingTasksByUser.ToDictionary(x => x.UserId, x => x.UsedCores);
-      }
-    }
-
-    public List<DT.UserStatistics> GetUserStatistics() {
-      using (var db = CreateContext()) {
-        var userStats = new Dictionary<Guid, DT.UserStatistics>();
-
-        var usedCoresByUser = from job in db.Tasks
-                              where job.State == TaskState.Calculating
-                              group job by job.Job.OwnerUserId into g
-                              select new { UserId = g.Key, UsedCores = g.Count() };
-
-        foreach (var item in usedCoresByUser) {
-          if (!userStats.ContainsKey(item.UserId)) {
-            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
-          }
-          userStats[item.UserId].UsedCores += item.UsedCores;
-        }
-
-        var executionTimesByUser = from task in db.Tasks
-                                   group task by task.Job.OwnerUserId into g
-                                   select new { UserId = g.Key, ExecutionTime = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
-        foreach (var item in executionTimesByUser) {
-          if (!userStats.ContainsKey(item.UserId)) {
-            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
-          }
-          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
-        }
-
-        // execution times only of finished task - necessary to compute efficieny
-        var executionTimesFinishedJobs = from job in db.Tasks
-                                         where job.State == TaskState.Finished
-                                         group job by job.Job.OwnerUserId into g
-                                         select new { UserId = g.Key, ExecutionTimeFinishedJobs = TimeSpan.FromMilliseconds(g.Select(x => x.ExecutionTimeMs).Sum()) };
-
-        foreach (var item in executionTimesFinishedJobs) {
-          if (!userStats.ContainsKey(item.UserId)) {
-            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
-          }
-          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
-        }
-
-        // start to end times only of finished task - necessary to compute efficiency
-        var startToEndTimesFinishedJobs = from job in db.Tasks
-                                          where job.State == TaskState.Finished
-                                          group job by job.Job.OwnerUserId into g
-                                          select new {
-                                            UserId = g.Key,
-                                            StartToEndTime = new TimeSpan(g.Select(x => x.StateLogs.OrderByDescending(sl => sl.DateTime).First().DateTime - x.StateLogs.OrderBy(sl => sl.DateTime).First().DateTime).Sum(ts => ts.Ticks))
-                                          };
-        foreach (var item in startToEndTimesFinishedJobs) {
-          if (!userStats.ContainsKey(item.UserId)) {
-            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
-          }
-          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
-        }
-
-        // also consider executiontimes of DeletedJobStats 
-        var deletedJobsExecutionTimesByUsers = from del in db.DeletedJobStatistics
-                                               group del by del.UserId into g
-                                               select new {
-                                                 UserId = g.Key,
-                                                 ExecutionTime = TimeSpan.FromSeconds(g.Select(x => x.ExecutionTimeS).Sum()),
-                                                 ExecutionTimeFinishedJobs = TimeSpan.FromSeconds(g.Select(x => x.ExecutionTimeSFinishedJobs).Sum()),
-                                                 StartToEndTime = TimeSpan.FromSeconds(g.Select(x => x.StartToEndTimeS).Sum())
-                                               };
-        foreach (var item in deletedJobsExecutionTimesByUsers) {
-          if (!userStats.ContainsKey(item.UserId)) {
-            userStats.Add(item.UserId, new DT.UserStatistics() { UserId = item.UserId });
-          }
-          userStats[item.UserId].ExecutionTime += item.ExecutionTime;
-          userStats[item.UserId].ExecutionTimeFinishedJobs += item.ExecutionTimeFinishedJobs;
-          userStats[item.UserId].StartToEndTime += item.StartToEndTime;
-        }
-
-        return userStats.Values.ToList();
-      }
-    }
-    #endregion
-
-    #region UserPriority Methods
-    public IEnumerable<DT.UserPriority> GetUserPriorities(Expression<Func<UserPriority, bool>> predicate) {
-      using (var db = CreateContext()) {
-        return db.UserPriorities.Where(predicate).Select(x => DT.Convert.ToDto(x)).ToArray();
-      }
-    }
-
-    public void EnqueueUserPriority(DT.UserPriority dto) {
-      using (var db = CreateContext()) {
-        var entity = db.UserPriorities.FirstOrDefault(x => x.UserId == dto.Id);
-        if (entity == null) db.UserPriorities.InsertOnSubmit(DT.Convert.ToEntity(dto));
-        else DT.Convert.ToEntity(dto, entity);
-        db.SubmitChanges();
-      }
-    }
-    #endregion
-
-    #region Helpers
-    private void CollectChildTasks(HiveDataContext db, Guid parentTaskId, List<Task> collection) {
-      var tasks = db.Tasks.Where(j => j.ParentTaskId == parentTaskId);
-      foreach (var task in tasks) {
-        collection.Add(task);
-        if (task.IsParentTask)
-          CollectChildTasks(db, task.TaskId, collection);
-      }
-    }
-    #endregion
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveJanitor.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/HiveJanitor.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/HiveJanitor.cs	(revision 12878)
@@ -23,56 +23,81 @@
 using System.Threading;
 using HeuristicLab.Services.Hive.DataAccess;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
 
 namespace HeuristicLab.Services.Hive {
   public class HiveJanitor {
     private bool stop;
-    private AutoResetEvent waitHandle;
+    private AutoResetEvent cleanupWaitHandle;
+    private AutoResetEvent generateStatisticsWaitHandle;
 
-    private DataAccess.ITransactionManager trans {
-      get { return ServiceLocator.Instance.TransactionManager; }
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
     }
-
-    private IEventManager eventManager {
+    private IEventManager EventManager {
       get { return ServiceLocator.Instance.EventManager; }
     }
 
-    private IHiveDao dao {
-      get { return ServiceLocator.Instance.HiveDao; }
+    private IStatisticsGenerator StatisticsGenerator {
+      get { return ServiceLocator.Instance.StatisticsGenerator; }
     }
 
     public HiveJanitor() {
       stop = false;
-      waitHandle = new AutoResetEvent(true);
+      cleanupWaitHandle = new AutoResetEvent(false);
+      generateStatisticsWaitHandle = new AutoResetEvent(false);
     }
 
     public void StopJanitor() {
       stop = true;
-      waitHandle.Set();
+      cleanupWaitHandle.Set();
+      generateStatisticsWaitHandle.Set();
     }
 
-    public void Run() {
+    public void RunCleanup() {
+      var pm = PersistenceManager;
       while (!stop) {
         try {
-          LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log("HiveJanitor: starting cleanup");
+          LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log("HiveJanitor: starting cleanup.");
           bool cleanup = false;
-          trans.UseTransaction(() => {
-            DateTime lastCleanup = dao.GetLastCleanup();
-            if (DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
-              dao.SetLastCleanup(DateTime.Now);
+
+          var lifecycleDao = pm.LifecycleDao;
+          pm.UseTransaction(() => {
+            var lifecycle = lifecycleDao.GetLastLifecycle();
+            if (lifecycle == null
+                || DateTime.Now - lifecycle.LastCleanup > Properties.Settings.Default.CleanupInterval) {
+              lifecycleDao.UpdateLifecycle();
               cleanup = true;
             }
+            pm.SubmitChanges();
           }, true);
 
           if (cleanup) {
-            eventManager.Cleanup();
+            EventManager.Cleanup();
           }
-          LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log("HiveJanitor: cleanup finished");
+          LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log("HiveJanitor: cleanup finished.");
         }
         catch (Exception e) {
           LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log(string.Format("HiveJanitor: The following exception occured: {0}", e.ToString()));
         }
-        waitHandle.WaitOne(HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval);
+        cleanupWaitHandle.WaitOne(Properties.Settings.Default.CleanupInterval);
       }
-      waitHandle.Close();
+      cleanupWaitHandle.Close();
+    }
+
+    public void RunGenerateStatistics() {
+      while (!stop) {
+        try {
+          LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log("HiveJanitor: starting generate statistics.");
+          StatisticsGenerator.GenerateStatistics();
+          LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log("HiveJanitor: generate statistics finished.");
+        }
+        catch (Exception e) {
+          LogFactory.GetLogger(typeof(HiveJanitor).Namespace).Log(string.Format("HiveJanitor: The following exception occured: {0}", e));
+        }
+
+        generateStatisticsWaitHandle.WaitOne(Properties.Settings.Default.GenerateStatisticsInterval);
+      }
+
+      generateStatisticsWaitHandle.Close();
     }
   }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 12878)
@@ -23,13 +23,15 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Security;
 using System.ServiceModel;
+using HeuristicLab.Services.Access;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
 using HeuristicLab.Services.Hive.DataTransfer;
+using HeuristicLab.Services.Hive.Manager;
 using HeuristicLab.Services.Hive.ServiceContracts;
 using DA = HeuristicLab.Services.Hive.DataAccess;
 using DT = HeuristicLab.Services.Hive.DataTransfer;
 
-
 namespace HeuristicLab.Services.Hive {
-
   /// <summary>
   /// Implementation of the Hive service (interface <see cref="IHiveService"/>).
@@ -39,197 +41,192 @@
   [HiveOperationContextBehavior]
   public class HiveService : IHiveService {
-    private IHiveDao dao {
-      get { return ServiceLocator.Instance.HiveDao; }
-    }
-    private IOptimizedHiveDao optimizedDao {
-      get { return ServiceLocator.Instance.OptimizedHiveDao; }
-    }
-    private Access.IRoleVerifier authen {
+    private static readonly DA.TaskState[] CompletedStates = { DA.TaskState.Finished, DA.TaskState.Aborted, DA.TaskState.Failed };
+
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    private IUserManager UserManager {
+      get { return ServiceLocator.Instance.UserManager; }
+    }
+
+    private IRoleVerifier RoleVerifier {
       get { return ServiceLocator.Instance.RoleVerifier; }
     }
-    private IAuthorizationManager author {
+
+    private IAuthorizationManager AuthorizationManager {
       get { return ServiceLocator.Instance.AuthorizationManager; }
     }
-    private DataAccess.ITransactionManager trans {
-      get { return ServiceLocator.Instance.TransactionManager; }
-    }
-    private IEventManager eventManager {
+    private IEventManager EventManager {
       get { return ServiceLocator.Instance.EventManager; }
     }
-    private Access.IUserManager userManager {
-      get { return ServiceLocator.Instance.UserManager; }
-    }
-    private HeartbeatManager heartbeatManager {
+    private HeartbeatManager HeartbeatManager {
       get { return ServiceLocator.Instance.HeartbeatManager; }
     }
 
     #region Task Methods
-    public Guid AddTask(Task task, TaskData taskData, IEnumerable<Guid> resourceIds) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        var t = DT.Convert.ToEntity(task);
-        t.RequiredPlugins.AddRange(task.PluginsNeededIds.Select(pluginId => new DA.RequiredPlugin { Task = t, PluginId = pluginId }));
-
-        t.JobData = DT.Convert.ToEntity(taskData);
-        t.JobData.LastUpdate = DateTime.Now;
-
-        optimizedDao.AddTask(t);
-
-        dao.AssignJobToResource(t.TaskId, resourceIds);
-
-        optimizedDao.UpdateTaskState(t.TaskId, DA.TaskState.Waiting, null, userManager.CurrentUserId, null);
-
-        return t.TaskId;
-      }, false, true);
-    }
-
-    public Guid AddChildTask(Guid parentTaskId, Task task, TaskData taskData) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+    public Guid AddTask(DT.Task task, DT.TaskData taskData, IEnumerable<Guid> resourceIds) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddTask")) {
+        var taskDao = pm.TaskDao;
+        var stateLogDao = pm.StateLogDao;
+        var newTask = task.ToEntity();
+        newTask.JobData = taskData.ToEntity();
+        newTask.JobData.LastUpdate = DateTime.Now;
+        newTask.AssignedResources.AddRange(resourceIds.Select(
+          x => new DA.AssignedResource {
+            ResourceId = x
+          }));
+        newTask.State = DA.TaskState.Waiting;
+        return pm.UseTransaction(() => {
+          taskDao.Save(newTask);
+          pm.SubmitChanges();
+          stateLogDao.Save(new DA.StateLog {
+            State = DA.TaskState.Waiting,
+            DateTime = DateTime.Now,
+            TaskId = newTask.TaskId,
+            UserId = UserManager.CurrentUserId,
+            SlaveId = null,
+            Exception = null
+          });
+          pm.SubmitChanges();
+          return newTask.TaskId;
+        }, false, true);
+      }
+    }
+
+    public Guid AddChildTask(Guid parentTaskId, DT.Task task, DT.TaskData taskData) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      IEnumerable<Guid> resourceIds;
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddChildTask")) {
+        var assignedResourceDao = pm.AssignedResourceDao;
+        resourceIds = pm.UseTransaction(() => {
+          return assignedResourceDao.GetByTaskId(parentTaskId)
+            .Select(x => x.ResourceId)
+            .ToList();
+        });
+      }
       task.ParentTaskId = parentTaskId;
-      return AddTask(task, taskData, optimizedDao.GetAssignedResourceIds(parentTaskId).ToList());
-    }
-
-    public Task GetTask(Guid taskId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskId, Permission.Read);
-
-      return trans.UseTransaction(() => {
-        return DT.Convert.ToDto(optimizedDao.GetTaskById(taskId));
-      }, false, false);
-    }
-
-    public IEnumerable<Task> GetTasks() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        var tasks = dao.GetTasks(x => true);
-        foreach (var task in tasks)
-          author.AuthorizeForTask(task.Id, Permission.Read);
-        return tasks;
-      });
-    }
-
-    public IEnumerable<LightweightTask> GetLightweightTasks(IEnumerable<Guid> taskIds) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-
-      return trans.UseTransaction(() => {
-        var tasks = dao.GetTasks(x => taskIds.Contains(x.TaskId)).Select(x => new LightweightTask(x)).ToArray();
-        foreach (var task in tasks)
-          author.AuthorizeForTask(task.Id, Permission.Read);
-        return tasks;
-      }, false, false);
-    }
-
-    public IEnumerable<LightweightTask> GetLightweightChildTasks(Guid? parentTaskId, bool recursive, bool includeParent) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-
-      return trans.UseTransaction(() => {
-        var tasks = GetChildTasks(parentTaskId, recursive, includeParent).Select(x => new LightweightTask(x)).ToArray();
-        foreach (var task in tasks)
-          author.AuthorizeForTask(task.Id, Permission.Read);
-        return tasks;
-      }, false, false);
-    }
-
-    public IEnumerable<LightweightTask> GetLightweightJobTasks(Guid jobId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForJob(jobId, Permission.Read);
-
-      return trans.UseTransaction(() => {
-        return optimizedDao.GetLightweightTasks(jobId).ToArray();
-      }, false, true);
-    }
-
-    public IEnumerable<LightweightTask> GetLightweightJobTasksWithoutStateLog(Guid jobId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForJob(jobId, Permission.Read);
-
-      return trans.UseTransaction(() => {
-        return dao.GetLightweightTasksWithoutStateLog(task => task.JobId == jobId).ToArray();
-      }, false, false);
-    }
-
-    public TaskData GetTaskData(Guid taskId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskId, Permission.Read);
-
-      return trans.UseTransaction(() => {
-        return dao.GetTaskData(taskId);
-      });
-    }
-
-    public void UpdateTask(Task taskDto) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskDto.Id, Permission.Full);
-
-      trans.UseTransaction(() => {
-        var task = optimizedDao.GetTaskByDto(taskDto);
-        optimizedDao.UpdateTask(task);
-      });
-    }
-
-    public void UpdateTaskData(Task task, TaskData taskData) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(task.Id, Permission.Full);
-
-      trans.UseTransaction(() => {
-        var t = optimizedDao.GetTaskByDto(task);
-        optimizedDao.UpdateTask(t);
-      });
-
-      trans.UseTransaction(() => {
-        var data = optimizedDao.GetTaskDataByDto(taskData);
-        data.LastUpdate = DateTime.Now;
-        optimizedDao.UpdateTaskData(data);
-      });
-    }
-
-    public void DeleteTask(Guid taskId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskId, Permission.Full);
-      trans.UseTransaction(() => {
-        dao.DeleteTask(taskId);
-      });
-    }
-
-    public void DeleteChildTasks(Guid parentTaskId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(parentTaskId, Permission.Full);
-      trans.UseTransaction(() => {
-        var tasks = GetChildTasks(parentTaskId, true, false);
-        foreach (var task in tasks) {
-          dao.DeleteTask(task.Id);
-          dao.DeleteTaskData(task.Id);
-        };
-      });
-    }
-
-    public Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskId, Permission.Full);
-
-      return trans.UseTransaction(() => {
-        var task = optimizedDao.UpdateTaskState(taskId, DT.Convert.ToEntity(taskState), slaveId, userId, exception);
-
-        if (task.Command.HasValue && task.Command.Value == DA.Command.Pause && task.State == DA.TaskState.Paused) {
-          task.Command = null;
-        } else if (task.Command.HasValue && task.Command.Value == DA.Command.Abort && task.State == DA.TaskState.Aborted) {
-          task.Command = null;
-        } else if (task.Command.HasValue && task.Command.Value == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
-          task.Command = null;
-        } else if (taskState == TaskState.Paused && !task.Command.HasValue) {
-          // slave paused and uploaded the task (no user-command) -> set waiting.
-          task = optimizedDao.UpdateTaskState(taskId, DA.TaskState.Waiting, slaveId, userId, exception);
-        }
-
-        return DT.Convert.ToDto(task);
-      });
-    }
-
-    public IEnumerable<Task> GetTasksByResourceId(Guid resourceId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      var tasks = trans.UseTransaction(() => dao.GetJobsByResourceId(resourceId));
-      foreach (var task in tasks)
-        author.AuthorizeForTask(task.Id, Permission.Read);
-      return tasks;
+      return AddTask(task, taskData, resourceIds);
+    }
+
+    public DT.Task GetTask(Guid taskId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetTask")) {
+        var taskDao = pm.TaskDao;
+        return pm.UseTransaction(() => {
+          var task = taskDao.GetById(taskId);
+          return task.ToDto();
+        });
+      }
+    }
+
+    public IEnumerable<DT.LightweightTask> GetLightweightJobTasks(Guid jobId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetLightweightJobTasks")) {
+        var taskDao = pm.TaskDao;
+        return pm.UseTransaction(() => {
+          return taskDao.GetByJobId(jobId)
+            .ToList()
+            .Select(x => new DT.LightweightTask {
+              Id = x.TaskId,
+              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
+              ParentTaskId = x.ParentTaskId,
+              StateLog = x.StateLogs.OrderBy(y => y.DateTime)
+                                    .Select(z => z.ToDto())
+                                    .ToList(),
+              State = x.State.ToDto(),
+              Command = x.Command.ToDto(),
+              LastTaskDataUpdate = x.JobData.LastUpdate
+            })
+            .ToList();
+        }, false, true);
+      }
+    }
+
+    public IEnumerable<DT.LightweightTask> GetLightweightJobTasksWithoutStateLog(Guid jobId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(jobId, Permission.Read);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetLightweightJobTasksWithoutStateLog")) {
+        var taskDao = pm.TaskDao;
+        return pm.UseTransaction(() => {
+          return taskDao.GetByJobId(jobId)
+            .ToList()
+            .Select(x => new DT.LightweightTask {
+              Id = x.TaskId,
+              ExecutionTime = TimeSpan.FromMilliseconds(x.ExecutionTimeMs),
+              ParentTaskId = x.ParentTaskId,
+              StateLog = new List<DT.StateLog>(),
+              State = x.State.ToDto(),
+              Command = x.Command.ToDto(),
+              LastTaskDataUpdate = x.JobData.LastUpdate
+            })
+            .ToList();
+        }, false, true);
+      }
+    }
+
+    public DT.TaskData GetTaskData(Guid taskId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskId, Permission.Read);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetTaskData")) {
+        var taskDataDao = pm.TaskDataDao;
+        return pm.UseTransaction(() => taskDataDao.GetById(taskId).ToDto());
+      }
+    }
+
+    public void UpdateTask(DT.Task taskDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("UpdateTask")) {
+        var taskDao = pm.TaskDao;
+        pm.UseTransaction(() => {
+          var task = taskDao.GetById(taskDto.Id);
+          taskDto.CopyToEntity(task);
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public void UpdateTaskData(DT.Task taskDto, DT.TaskData taskDataDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskDto.Id, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("UpdateTaskData")) {
+        var taskDao = pm.TaskDao;
+        var taskDataDao = pm.TaskDataDao;
+        pm.UseTransaction(() => {
+          var task = taskDao.GetById(taskDto.Id);
+          var taskData = taskDataDao.GetById(taskDataDto.TaskId);
+          taskDto.CopyToEntity(task);
+          taskDataDto.CopyToEntity(taskData);
+          taskData.LastUpdate = DateTime.Now;
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public DT.Task UpdateTaskState(Guid taskId, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("UpdateTaskState")) {
+        var taskDao = pm.TaskDao;
+        return pm.UseTransaction(() => {
+          var task = taskDao.GetById(taskId);
+          UpdateTaskState(pm, task, taskState, slaveId, userId, exception);
+          pm.SubmitChanges();
+          return task.ToDto();
+        });
+      }
     }
     #endregion
@@ -237,212 +234,303 @@
     #region Task Control Methods
     public void StopTask(Guid taskId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskId, Permission.Full);
-      trans.UseTransaction(() => {
-        var task = dao.GetTask(taskId);
-        if (task.State == TaskState.Calculating || task.State == TaskState.Transferring) {
-          task.Command = Command.Stop;
-          dao.UpdateTask(task);
-        } else {
-          if (task.State != TaskState.Aborted && task.State != TaskState.Finished && task.State != TaskState.Failed) {
-            task = UpdateTaskState(taskId, TaskState.Aborted, null, null, string.Empty);
-          }
-        }
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("StopTask")) {
+        var taskDao = pm.TaskDao;
+        pm.UseTransaction(() => {
+          var task = taskDao.GetById(taskId);
+          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
+            task.Command = DA.Command.Stop;
+          } else if (task.State != DA.TaskState.Aborted
+                     && task.State != DA.TaskState.Finished
+                     && task.State != DA.TaskState.Failed) {
+            UpdateTaskState(pm, task, DT.TaskState.Aborted, null, null, string.Empty);
+          }
+          pm.SubmitChanges();
+        });
+      }
     }
 
     public void PauseTask(Guid taskId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskId, Permission.Full);
-      trans.UseTransaction(() => {
-        var job = dao.GetTask(taskId);
-        if (job.State == TaskState.Calculating || job.State == TaskState.Transferring) {
-          job.Command = Command.Pause;
-          dao.UpdateTask(job);
-        } else {
-          job = UpdateTaskState(taskId, TaskState.Paused, null, null, string.Empty);
-        }
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("PauseTask")) {
+        var taskDao = pm.TaskDao;
+        pm.UseTransaction(() => {
+          var task = taskDao.GetById(taskId);
+          if (task.State == DA.TaskState.Calculating || task.State == DA.TaskState.Transferring) {
+            task.Command = DA.Command.Pause;
+          }
+          UpdateTaskState(pm, task, DT.TaskState.Paused, null, null, string.Empty);
+          pm.SubmitChanges();
+        });
+      }
     }
 
     public void RestartTask(Guid taskId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      author.AuthorizeForTask(taskId, Permission.Full);
-      trans.UseTransaction(() => {
-        Task task = dao.UpdateTaskState(taskId, DA.TaskState.Waiting, null, userManager.CurrentUserId, string.Empty);
-        task.Command = null;
-        dao.UpdateTask(task);
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      AuthorizationManager.AuthorizeForTask(taskId, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("RestartTask")) {
+        var taskDao = pm.TaskDao;
+        pm.UseTransaction(() => {
+          var task = taskDao.GetById(taskId);
+          task.Command = null;
+          UpdateTaskState(pm, task, DT.TaskState.Waiting, null, UserManager.CurrentUserId, string.Empty);
+          pm.SubmitChanges();
+        });
+      }
     }
     #endregion
 
     #region Job Methods
-    public Job GetJob(Guid id) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForJob(id, Permission.Read);
-      return trans.UseTransaction(() => {
-        var job = dao.GetJobs(x =>
-              x.JobId == id
-              && (x.OwnerUserId == userManager.CurrentUserId || x.JobPermissions.Count(hep => hep.Permission != DA.Permission.NotAllowed && hep.GrantedUserId == userManager.CurrentUserId) > 0)
-            ).FirstOrDefault();
-        if (job != null) {
-          job.Permission = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
-          job.OwnerUsername = userManager.GetUserById(job.OwnerUserId).UserName;
-        }
-        return job;
-      });
-    }
-
-    public IEnumerable<Job> GetJobs() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        var jobs = dao.GetJobs(x => x.OwnerUserId == userManager.CurrentUserId || x.JobPermissions.Count(hep => hep.Permission != DA.Permission.NotAllowed && hep.GrantedUserId == userManager.CurrentUserId) > 0);
-        foreach (var job in jobs) {
-          author.AuthorizeForJob(job.Id, Permission.Read);
-          job.Permission = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
-          job.OwnerUsername = userManager.GetUserById(job.OwnerUserId).UserName;
-        }
-        return jobs;
-      });
-    }
-
-    public IEnumerable<Job> GetAllJobs() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      return trans.UseTransaction(() => {
-        var jobs = dao.GetJobs(x => true);
-        foreach (var job in jobs) { // no authorization here, since this method is admin-only! (admin is allowed to read all task)
-          job.Permission = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
-          job.OwnerUsername = userManager.GetUserById(job.OwnerUserId).UserName;
-        }
-        return jobs;
-      });
-    }
-
-    public Guid AddJob(Job jobDto) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        jobDto.OwnerUserId = userManager.CurrentUserId;
-        jobDto.DateCreated = DateTime.Now;
-        return dao.AddJob(jobDto);
-      });
-    }
-
-    public void UpdateJob(Job jobDto) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForJob(jobDto.Id, Permission.Full);
-      trans.UseTransaction(() => {
-        dao.UpdateJob(jobDto);
-      });
+    public DT.Job GetJob(Guid id) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(id, DT.Permission.Read);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetJob")) {
+        var jobDao = pm.JobDao;
+        var jobPermissionDao = pm.JobPermissionDao;
+        var taskDao = pm.TaskDao;
+        var currentUserId = UserManager.CurrentUserId;
+        return pm.UseTransaction(() => {
+          var job = jobDao.GetById(id).ToDto();
+          if (job != null) {
+            var statistics = taskDao.GetByJobId(job.Id)
+              .GroupBy(x => x.JobId)
+              .Select(x => new {
+                TotalCount = x.Count(),
+                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
+                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
+              }).FirstOrDefault();
+            if (statistics != null) {
+              job.JobCount = statistics.TotalCount;
+              job.CalculatingCount = statistics.CalculatingCount;
+              job.FinishedCount = statistics.FinishedCount;
+            }
+            job.OwnerUsername = UserManager.GetUserById(job.OwnerUserId).UserName;
+            if (currentUserId == job.OwnerUserId) {
+              job.Permission = Permission.Full;
+            } else {
+              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
+              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
+            }
+          }
+          return job;
+        });
+      }
+    }
+
+    public IEnumerable<DT.Job> GetJobs() {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetJobs")) {
+        var jobDao = pm.JobDao;
+        var jobPermissionDao = pm.JobPermissionDao;
+        var taskDao = pm.TaskDao;
+        var currentUserId = UserManager.CurrentUserId;
+        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)
+            .Select(x => x.ToDto())
+            .ToList();
+          var statistics = taskDao.GetAll()
+              .GroupBy(x => x.JobId)
+              .Select(x => new {
+                x.Key,
+                TotalCount = x.Count(),
+                CalculatingCount = x.Count(y => y.State == DA.TaskState.Calculating),
+                FinishedCount = x.Count(y => CompletedStates.Contains(y.State))
+              })
+              .ToList();
+          foreach (var job in jobs) {
+            var statistic = statistics.FirstOrDefault(x => x.Key == job.Id);
+            if (statistic != null) {
+              job.JobCount = statistic.TotalCount;
+              job.CalculatingCount = statistic.CalculatingCount;
+              job.FinishedCount = statistic.FinishedCount;
+            }
+            job.OwnerUsername = UserManager.GetUserById(job.OwnerUserId).UserName;
+            if (currentUserId == job.OwnerUserId) {
+              job.Permission = Permission.Full;
+            } else {
+              var jobPermission = jobPermissionDao.GetByJobAndUserId(job.Id, currentUserId);
+              job.Permission = jobPermission == null ? Permission.NotAllowed : jobPermission.Permission.ToDto();
+            }
+          }
+          return jobs;
+        });
+      }
+    }
+
+    public Guid AddJob(DT.Job jobDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddJob")) {
+        var jobDao = pm.JobDao;
+        var userPriorityDao = pm.UserPriorityDao;
+        return pm.UseTransaction(() => {
+          jobDto.OwnerUserId = UserManager.CurrentUserId;
+          jobDto.DateCreated = DateTime.Now;
+          var job = jobDao.Save(jobDto.ToEntity());
+          if (userPriorityDao.GetById(jobDto.OwnerUserId) == null) {
+            userPriorityDao.Save(new DA.UserPriority {
+              UserId = jobDto.OwnerUserId,
+              DateEnqueued = jobDto.DateCreated
+            });
+          }
+          pm.SubmitChanges();
+          return job.JobId;
+        });
+      }
+    }
+
+    public void UpdateJob(DT.Job jobDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(jobDto.Id, DT.Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("UpdateJob")) {
+        bool exists = true;
+        var jobDao = pm.JobDao;
+        pm.UseTransaction(() => {
+          var job = jobDao.GetById(jobDto.Id);
+          if (job == null) {
+            exists = false;
+            job = new DA.Job();
+          }
+          jobDto.CopyToEntity(job);
+          if (!exists) {
+            jobDao.Save(job);
+          }
+          pm.SubmitChanges();
+        });
+      }
     }
 
     public void DeleteJob(Guid jobId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForJob(jobId, Permission.Full);
-      trans.UseTransaction(() => {
-        dao.DeleteJob(jobId); // child task will be deleted by db-trigger
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(jobId, DT.Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("DeleteJob")) {
+        var jobDao = pm.JobDao;
+        pm.UseTransaction(() => {
+          // child task will be deleted by db-trigger
+          jobDao.Delete(jobId);
+          pm.SubmitChanges();
+        });
+      }
     }
     #endregion
 
     #region JobPermission Methods
-    public void GrantPermission(Guid jobId, Guid grantedUserId, Permission permission) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      trans.UseTransaction(() => {
-        Job job = dao.GetJob(jobId);
-        if (job == null) throw new FaultException<FaultReason>(new FaultReason("Could not find task with id " + jobId));
-        Permission perm = DT.Convert.ToDto(dao.GetPermissionForJob(job.Id, userManager.CurrentUserId));
-        if (perm != Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permissions for this experiment"));
-        dao.SetJobPermission(jobId, userManager.CurrentUserId, grantedUserId, DT.Convert.ToEntity(permission));
-      });
+    public void GrantPermission(Guid jobId, Guid grantedUserId, DT.Permission permission) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GrantPermission")) {
+        var jobPermissionDao = pm.JobPermissionDao;
+        var currentUserId = UserManager.CurrentUserId;
+        pm.UseTransaction(() => {
+          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, permission.ToEntity());
+          pm.SubmitChanges();
+        });
+      }
     }
 
     public void RevokePermission(Guid jobId, Guid grantedUserId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      trans.UseTransaction(() => {
-        Job job = dao.GetJob(jobId);
-        if (job == null) throw new FaultException<FaultReason>(new FaultReason("Could not find task with id " + jobId));
-        DA.Permission perm = dao.GetPermissionForJob(job.Id, userManager.CurrentUserId);
-        if (perm != DA.Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permissions for this experiment"));
-        dao.SetJobPermission(jobId, userManager.CurrentUserId, grantedUserId, DA.Permission.NotAllowed);
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("RevokePermission")) {
+        var jobPermissionDao = pm.JobPermissionDao;
+        var currentUserId = UserManager.CurrentUserId;
+        pm.UseTransaction(() => {
+          jobPermissionDao.SetJobPermission(jobId, currentUserId, grantedUserId, DA.Permission.NotAllowed);
+          pm.SubmitChanges();
+        });
+      }
     }
 
     public IEnumerable<JobPermission> GetJobPermissions(Guid jobId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        DA.Permission currentUserPermission = dao.GetPermissionForJob(jobId, userManager.CurrentUserId);
-        if (currentUserPermission != DA.Permission.Full) throw new FaultException<FaultReason>(new FaultReason("Not allowed to list permissions for this experiment"));
-        return dao.GetJobPermissions(x => x.JobId == jobId);
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForJob(jobId, Permission.Full);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetJobPermissions")) {
+        var jobPermissionDao = pm.JobPermissionDao;
+        return pm.UseTransaction(() => jobPermissionDao.GetByJobId(jobId)
+          .Select(x => x.ToDto())
+          .ToList()
+        );
+      }
     }
 
     public bool IsAllowedPrivileged() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return authen.IsInRole(HiveRoles.IsAllowedPrivileged);
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      return RoleVerifier.IsInRole(HiveRoles.IsAllowedPrivileged);
     }
     #endregion
 
     #region Login Methods
-    public void Hello(Slave slaveInfo) {
-      authen.AuthenticateForAnyRole(HiveRoles.Slave);
-      if (userManager.CurrentUser.UserName != "hiveslave")
-        slaveInfo.OwnerUserId = userManager.CurrentUserId;
-
-      trans.UseTransaction(() => {
-        var slave = dao.GetSlave(slaveInfo.Id);
-
-        if (slave == null) {
-          dao.AddSlave(slaveInfo);
-        } else {
-          slave.Name = slaveInfo.Name;
-          slave.Description = slaveInfo.Description;
-          slave.OwnerUserId = slaveInfo.OwnerUserId;
-
-          slave.Cores = slaveInfo.Cores;
-          slave.CpuArchitecture = slaveInfo.CpuArchitecture;
-          slave.CpuSpeed = slaveInfo.CpuSpeed;
-          slave.FreeCores = slaveInfo.FreeCores;
-          slave.FreeMemory = slaveInfo.FreeMemory;
-          slave.Memory = slaveInfo.Memory;
-          slave.OperatingSystem = slaveInfo.OperatingSystem;
-
-          slave.LastHeartbeat = DateTime.Now;
-          slave.SlaveState = SlaveState.Idle;
-
-          // don't update those properties: dbSlave.IsAllowedToCalculate, dbSlave.ParentResourceId 
-
-          dao.UpdateSlave(slave);
-        }
-      });
+    public void Hello(DT.Slave slaveInfo) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
+      if (UserManager.CurrentUser.UserName != "hiveslave") {
+        slaveInfo.OwnerUserId = UserManager.CurrentUserId;
+      }
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("Hello")) {
+        var slaveDao = pm.SlaveDao;
+        pm.UseTransaction(() => {
+          var slave = slaveDao.GetById(slaveInfo.Id);
+          if (slave == null) {
+            slaveDao.Save(slaveInfo.ToEntity());
+          } else {
+            bool oldIsAllowedToCalculate = slave.IsAllowedToCalculate;
+            Guid? oldParentResourceId = slave.ParentResourceId;
+            slaveInfo.CopyToEntity(slave);
+            slave.IsAllowedToCalculate = oldIsAllowedToCalculate;
+            slave.ParentResourceId = oldParentResourceId;
+            slave.LastHeartbeat = DateTime.Now;
+            slave.SlaveState = DA.SlaveState.Idle;
+          }
+          pm.SubmitChanges();
+        });
+      }
     }
 
     public void GoodBye(Guid slaveId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Slave);
-      trans.UseTransaction(() => {
-        var slave = dao.GetSlave(slaveId);
-        if (slave != null) {
-          slave.SlaveState = SlaveState.Offline;
-          dao.UpdateSlave(slave);
-        }
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GoodBye")) {
+        var slaveDao = pm.SlaveDao;
+        pm.UseTransaction(() => {
+          var slave = slaveDao.GetById(slaveId);
+          if (slave != null) {
+            slave.SlaveState = DA.SlaveState.Offline;
+            pm.SubmitChanges();
+          }
+        });
+      }
     }
     #endregion
 
     #region Heartbeat Methods
-    public List<MessageContainer> Heartbeat(Heartbeat heartbeat) {
-      authen.AuthenticateForAnyRole(HiveRoles.Slave);
-
+    public List<MessageContainer> Heartbeat(DT.Heartbeat heartbeat) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
       List<MessageContainer> result = new List<MessageContainer>();
       try {
-        result = heartbeatManager.ProcessHeartbeat(heartbeat);
+        using (new PerformanceLogger("ProcessHeartbeat")) {
+          result = HeartbeatManager.ProcessHeartbeat(heartbeat);
+        }
       }
       catch (Exception ex) {
-        DA.LogFactory.GetLogger(this.GetType().Namespace).Log("Exception processing Heartbeat: " + ex.ToString());
-      }
-
+        DA.LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("Exception processing Heartbeat: {0}", ex));
+      }
       if (HeuristicLab.Services.Hive.Properties.Settings.Default.TriggerEventManagerInHeartbeat) {
         TriggerEventManager(false);
       }
-
       return result;
     }
@@ -450,64 +538,61 @@
 
     #region Plugin Methods
-    public Guid AddPlugin(Plugin plugin, List<PluginData> pluginDatas) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        plugin.UserId = userManager.CurrentUserId;
+    public DT.Plugin GetPlugin(Guid pluginId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetPlugin")) {
+        var pluginDao = pm.PluginDao;
+        return pm.UseTransaction(() => pluginDao.GetById(pluginId).ToDto());
+      }
+    }
+
+    public Guid AddPlugin(DT.Plugin plugin, List<DT.PluginData> pluginData) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddPlugin")) {
+        var pluginDao = pm.PluginDao;
+        plugin.UserId = UserManager.CurrentUserId;
         plugin.DateCreated = DateTime.Now;
-
-        var existing = dao.GetPlugins(x => x.Hash != null).Where(x => x.Hash.SequenceEqual(plugin.Hash));
-        if (existing.Count() > 0) {
-          // a plugin already exists.
-          throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(existing.Single().Id));
-        }
-
-        Guid pluginId = dao.AddPlugin(plugin);
-        foreach (PluginData pluginData in pluginDatas) {
-          pluginData.PluginId = pluginId;
-          dao.AddPluginData(pluginData);
-        }
-        return pluginId;
-      });
-    }
-
-    public Plugin GetPlugin(Guid pluginId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      return trans.UseTransaction(() => {
-        return DT.Convert.ToDto(optimizedDao.GetPluginById(pluginId));
-      });
-    }
-
-    public Plugin GetPluginByHash(byte[] hash) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      return trans.UseTransaction(() => {
-        return dao.GetPlugins(x => x.Hash == hash).FirstOrDefault();
-      });
-    }
-
-    // note: this is a possible security problem, since a client is able to download all plugins, which may contain proprietary code (which can be disassembled)
-    //       change so that only with GetPluginByHash it is possible to download plugins
-    public IEnumerable<Plugin> GetPlugins() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      return trans.UseTransaction(() => {
-        return dao.GetPlugins(x => x.Hash != null);
-      });
-    }
-
-    public IEnumerable<PluginData> GetPluginDatas(List<Guid> pluginIds) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      var pluginDatas = new List<PluginData>();
-      return trans.UseTransaction(() => {
-        foreach (Guid guid in pluginIds) {
-          pluginDatas.AddRange(dao.GetPluginDatas(x => x.PluginId == guid).ToList());
-        }
-        return pluginDatas;
-      });
-    }
-
-    public void DeletePlugin(Guid pluginId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
-      trans.UseTransaction(() => {
-        dao.DeletePlugin(pluginId);
-      });
+        return pm.UseTransaction(() => {
+          var pluginEntity = pluginDao.GetByHash(plugin.Hash).SingleOrDefault();
+          if (pluginEntity != null) {
+            throw new FaultException<PluginAlreadyExistsFault>(new PluginAlreadyExistsFault(pluginEntity.PluginId));
+          }
+          pluginEntity = plugin.ToEntity();
+          foreach (var data in pluginData) {
+            data.PluginId = default(Guid); // real id will be assigned from linq2sql
+            pluginEntity.PluginData.Add(data.ToEntity());
+          }
+          pluginDao.Save(pluginEntity);
+          pm.SubmitChanges();
+          return pluginEntity.PluginId;
+        });
+      }
+    }
+
+    public IEnumerable<DT.Plugin> GetPlugins() {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetPlugins")) {
+        var pluginDao = pm.PluginDao;
+        return pm.UseTransaction(() => pluginDao.GetAll()
+          .Where(x => x.Hash != null)
+          .Select(x => x.ToDto())
+          .ToList()
+        );
+      }
+    }
+
+    public IEnumerable<DT.PluginData> GetPluginDatas(List<Guid> pluginIds) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetPluginDatas")) {
+        var pluginDataDao = pm.PluginDataDao;
+        return pm.UseTransaction(() => pluginDataDao.GetAll()
+            .Where(x => pluginIds.Contains(x.PluginId))
+            .Select(x => x.ToDto())
+            .ToList()
+        );
+      }
     }
     #endregion
@@ -515,167 +600,268 @@
     #region ResourcePermission Methods
     public void GrantResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      trans.UseTransaction(() => {
-        Resource resource = dao.GetResource(resourceId);
-        if (resource == null) throw new FaultException<FaultReason>(new FaultReason("Could not find resource with id " + resourceId));
-        if (resource.OwnerUserId != userManager.CurrentUserId && !authen.IsInRole(HiveRoles.Administrator)) throw new FaultException<FaultReason>(new FaultReason("Not allowed to grant permission for this resource"));
-        foreach (Guid id in grantedUserIds)
-          dao.AddResourcePermission(new ResourcePermission { ResourceId = resourceId, GrantedByUserId = userManager.CurrentUserId, GrantedUserId = id });
-      });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GrantResourcePermissions")) {
+        pm.UseTransaction(() => {
+          var resource = AuthorizeForResource(pm, resourceId);
+          var resourcePermissions = resource.ResourcePermissions.ToList();
+          foreach (var id in grantedUserIds) {
+            if (resourcePermissions.All(x => x.GrantedUserId != id)) {
+              resource.ResourcePermissions.Add(new DA.ResourcePermission {
+                GrantedUserId = id,
+                GrantedByUserId = UserManager.CurrentUserId
+              });
+            }
+          }
+          pm.SubmitChanges();
+        });
+      }
     }
 
     public void RevokeResourcePermissions(Guid resourceId, Guid[] grantedUserIds) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      trans.UseTransaction(() => {
-        Resource resource = dao.GetResource(resourceId);
-        if (resource == null) throw new FaultException<FaultReason>(new FaultReason("Could not find resource with id " + resourceId));
-        if (resource.OwnerUserId != userManager.CurrentUserId && !authen.IsInRole(HiveRoles.Administrator)) throw new FaultException<FaultReason>(new FaultReason("Not allowed to revoke permission for this resource"));
-        foreach (Guid id in grantedUserIds)
-          dao.DeleteResourcePermission(resourceId, id);
-      });
-    }
-
-    public IEnumerable<ResourcePermission> GetResourcePermissions(Guid resourceId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        Resource resource = dao.GetResource(resourceId);
-        if (resource == null) throw new FaultException<FaultReason>(new FaultReason("Could not find resource with id " + resourceId));
-        return dao.GetResourcePermissions(x => x.ResourceId == resourceId);
-      });
-    }
-    #endregion
-
-    #region Resource Methods
-    public IEnumerable<Resource> GetChildResources(Guid resourceId) {
-      return trans.UseTransaction(() => { return dao.GetChildResources(resourceId); });
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("RevokeResourcePermissions")) {
+        var resourcePermissionDao = pm.ResourcePermissionDao;
+        pm.UseTransaction(() => {
+          AuthorizeForResource(pm, resourceId);
+          resourcePermissionDao.DeleteByResourceAndGrantedUserId(resourceId, grantedUserIds);
+        });
+      }
+    }
+
+    public IEnumerable<DT.ResourcePermission> GetResourcePermissions(Guid resourceId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetResourcePermissions")) {
+        var resourcePermissionDao = pm.ResourcePermissionDao;
+        return pm.UseTransaction(() => resourcePermissionDao.GetByResourceId(resourceId)
+          .Select(x => x.ToDto())
+          .ToList()
+        );
+      }
     }
     #endregion
 
     #region Slave Methods
+    public Guid AddSlave(DT.Slave slaveDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddSlave")) {
+        var slaveDao = pm.SlaveDao;
+        return pm.UseTransaction(() => {
+          var slave = slaveDao.Save(slaveDto.ToEntity());
+          pm.SubmitChanges();
+          return slave.ResourceId;
+        });
+      }
+    }
+
+    public Guid AddSlaveGroup(DT.SlaveGroup slaveGroupDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddSlaveGroup")) {
+        var slaveGroupDao = pm.SlaveGroupDao;
+        return pm.UseTransaction(() => {
+          if (slaveGroupDto.Id == Guid.Empty) {
+            slaveGroupDto.Id = Guid.NewGuid();
+          }
+          var slaveGroup = slaveGroupDao.Save(slaveGroupDto.ToEntity());
+          pm.SubmitChanges();
+          return slaveGroup.ResourceId;
+        });
+      }
+    }
+
+    public DT.Slave GetSlave(Guid slaveId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetSlave")) {
+        var slaveDao = pm.SlaveDao;
+        return pm.UseTransaction(() => slaveDao.GetById(slaveId).ToDto());
+      }
+    }
+
+    public IEnumerable<DT.Slave> GetSlaves() {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetSlaves")) {
+        var slaveDao = pm.SlaveDao;
+        var resourcePermissionDao = pm.ResourcePermissionDao;
+        var currentUserId = UserManager.CurrentUserId;
+        return pm.UseTransaction(() => {
+          var resourcePermissions = resourcePermissionDao.GetAll();
+          return slaveDao.GetAll()
+            .Where(x => isAdministrator
+              || x.OwnerUserId == null
+              || x.OwnerUserId == currentUserId
+              || UserManager.VerifyUser(currentUserId, resourcePermissions
+                  .Where(y => y.ResourceId == x.ResourceId)
+                  .Select(z => z.GrantedUserId)
+                  .ToList())
+              )
+            .Select(x => x.ToDto())
+            .ToList();
+        });
+      }
+    }
+
+    public IEnumerable<DT.SlaveGroup> GetSlaveGroups() {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      bool isAdministrator = RoleVerifier.IsInRole(HiveRoles.Administrator);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetSlaveGroups")) {
+        var slaveGroupDao = pm.SlaveGroupDao;
+        var resourcePermissionDao = pm.ResourcePermissionDao;
+        var currentUserId = UserManager.CurrentUserId;
+        return pm.UseTransaction(() => {
+          var resourcePermissions = resourcePermissionDao.GetAll();
+          return slaveGroupDao.GetAll()
+            .Where(x => isAdministrator
+              || x.OwnerUserId == null
+              || x.OwnerUserId == currentUserId
+              || UserManager.VerifyUser(currentUserId, resourcePermissions
+                  .Where(y => y.ResourceId == x.ResourceId)
+                  .Select(z => z.GrantedUserId)
+                  .ToList())
+              )
+            .Select(x => x.ToDto())
+            .ToList();
+        });
+      }
+    }
+
+    public void UpdateSlave(DT.Slave slaveDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("UpdateSlave")) {
+        var slaveDao = pm.SlaveDao;
+        pm.UseTransaction(() => {
+          var slave = slaveDao.GetById(slaveDto.Id);
+          if (slave != null) {
+            slaveDto.CopyToEntity(slave);
+          } else {
+            slaveDao.Save(slaveDto.ToEntity());
+          }
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public void UpdateSlaveGroup(DT.SlaveGroup slaveGroupDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("UpdateSlaveGroup")) {
+        var slaveGroupDao = pm.SlaveGroupDao;
+        pm.UseTransaction(() => {
+          var slaveGroup = slaveGroupDao.GetById(slaveGroupDto.Id);
+          if (slaveGroup != null) {
+            slaveGroupDto.CopyToEntity(slaveGroup);
+          } else {
+            slaveGroupDao.Save(slaveGroupDto.ToEntity());
+          }
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public void DeleteSlave(Guid slaveId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForResourceAdministration(slaveId);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("DeleteSlave")) {
+        var slaveDao = pm.SlaveDao;
+        pm.UseTransaction(() => {
+          slaveDao.Delete(slaveId);
+        });
+      }
+    }
+
+    public void DeleteSlaveGroup(Guid slaveGroupId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForResourceAdministration(slaveGroupId);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("DeleteSlaveGroup")) {
+        var slaveGroupDao = pm.SlaveGroupDao;
+        pm.UseTransaction(() => {
+          slaveGroupDao.Delete(slaveGroupId);
+        });
+      }
+    }
+
+    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddResourceToGroup")) {
+        var resourceDao = pm.ResourceDao;
+        pm.UseTransaction(() => {
+          var resource = resourceDao.GetById(resourceId);
+          resource.ParentResourceId = slaveGroupId;
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("RemoveResourceFromGroup")) {
+        var resourceDao = pm.ResourceDao;
+        pm.UseTransaction(() => {
+          var resource = resourceDao.GetById(resourceId);
+          resource.ParentResourceId = null;
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public Guid GetResourceId(string resourceName) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetResourceId")) {
+        var resourceDao = pm.ResourceDao;
+        return pm.UseTransaction(() => {
+          var resource = resourceDao.GetByName(resourceName);
+          return resource != null ? resource.ResourceId : Guid.Empty;
+        });
+      }
+    }
+
+    public void TriggerEventManager(bool force) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator);
+      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
+      bool cleanup;
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("TriggerEventManager")) {
+        cleanup = false;
+        var lifecycleDao = pm.LifecycleDao;
+        pm.UseTransaction(() => {
+          var lastLifecycle = lifecycleDao.GetLastLifecycle();
+          DateTime lastCleanup = lastLifecycle != null ? lastLifecycle.LastCleanup : DateTime.MinValue;
+          if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
+            lifecycleDao.UpdateLifecycle();
+            cleanup = true;
+            pm.SubmitChanges();
+          }
+        }, true);
+      }
+      if (cleanup) {
+        EventManager.Cleanup();
+      }
+    }
+
     public int GetNewHeartbeatInterval(Guid slaveId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Slave);
-
-      Slave s = trans.UseTransaction(() => { return dao.GetSlave(slaveId); });
-      if (s != null) {
-        return s.HbInterval;
-      } else {
-        return -1;
-      }
-    }
-
-    public Guid AddSlave(Slave slave) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      return trans.UseTransaction(() => dao.AddSlave(slave));
-    }
-
-    public Guid AddSlaveGroup(SlaveGroup slaveGroup) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => dao.AddSlaveGroup(slaveGroup));
-    }
-
-    public Slave GetSlave(Guid slaveId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      return trans.UseTransaction(() => { return dao.GetSlave(slaveId); });
-    }
-
-    public SlaveGroup GetSlaveGroup(Guid slaveGroupId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      return trans.UseTransaction(() => { return dao.GetSlaveGroup(slaveGroupId); });
-    }
-
-    public IEnumerable<Slave> GetSlaves() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        return dao.GetSlaves(x => true).Where(x => x.OwnerUserId == null
-                                           || x.OwnerUserId == userManager.CurrentUserId
-                                           || userManager.VerifyUser(userManager.CurrentUserId, GetResourcePermissions(x.Id).Select(y => y.GrantedUserId).ToList())
-                                           || authen.IsInRole(HiveRoles.Administrator)).ToArray();
-      });
-    }
-
-    public IEnumerable<SlaveGroup> GetSlaveGroups() {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        return dao.GetSlaveGroups(x => true).Where(x => x.OwnerUserId == null
-                                                || x.OwnerUserId == userManager.CurrentUserId
-                                                || userManager.VerifyUser(userManager.CurrentUserId, GetResourcePermissions(x.Id).Select(y => y.GrantedUserId).ToList())
-                                                || authen.IsInRole(HiveRoles.Administrator)).ToArray();
-      });
-    }
-
-    public void UpdateSlave(Slave slave) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      trans.UseTransaction(() => {
-        dao.UpdateSlave(slave);
-      });
-    }
-
-    public void UpdateSlaveGroup(SlaveGroup slaveGroup) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      trans.UseTransaction(() => {
-        dao.UpdateSlaveGroup(slaveGroup);
-      });
-    }
-
-    public void DeleteSlave(Guid slaveId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForResourceAdministration(slaveId);
-      trans.UseTransaction(() => {
-        dao.DeleteSlave(slaveId);
-      });
-    }
-
-    public void DeleteSlaveGroup(Guid slaveGroupId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForResourceAdministration(slaveGroupId);
-      trans.UseTransaction(() => {
-        dao.DeleteSlaveGroup(slaveGroupId);
-      });
-    }
-
-    public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      trans.UseTransaction(() => {
-        var resource = dao.GetResource(resourceId);
-        resource.ParentResourceId = slaveGroupId;
-        dao.UpdateResource(resource);
-      });
-    }
-
-    public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator);
-      trans.UseTransaction(() => {
-        var resource = dao.GetResource(resourceId);
-        resource.ParentResourceId = null;
-        dao.UpdateResource(resource);
-      });
-    }
-
-    public Guid GetResourceId(string resourceName) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => {
-        var resource = dao.GetResources(x => x.Name == resourceName).FirstOrDefault();
-        if (resource != null) {
-          return resource.Id;
-        } else {
-          return Guid.Empty;
-        }
-      });
-    }
-
-    public void TriggerEventManager(bool force) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Slave);
-      // use a serializable transaction here to ensure not two threads execute this simultaniously (mutex-lock would not work since IIS may use multiple AppDomains)
-      bool cleanup = false;
-      trans.UseTransaction(() => {
-        DateTime lastCleanup = dao.GetLastCleanup();
-        if (force || DateTime.Now - lastCleanup > HeuristicLab.Services.Hive.Properties.Settings.Default.CleanupInterval) {
-          dao.SetLastCleanup(DateTime.Now);
-          cleanup = true;
-        }
-      }, true);
-
-      if (cleanup) {
-        eventManager.Cleanup();
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Slave);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetNewHeartbeatInterval")) {
+        var slaveDao = pm.SlaveDao;
+        return pm.UseTransaction(() => {
+          var slave = slaveDao.GetById(slaveId);
+          if (slave != null) {
+            return slave.HbInterval;
+          }
+          return -1;
+        });
       }
     }
@@ -683,30 +869,58 @@
 
     #region Downtime Methods
-    public Guid AddDowntime(Downtime downtime) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForResourceAdministration(downtime.ResourceId);
-      return trans.UseTransaction(() => dao.AddDowntime(downtime));
+    public Guid AddDowntime(DT.Downtime downtimeDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("AddDowntime")) {
+        var downtimeDao = pm.DowntimeDao;
+        return pm.UseTransaction(() => {
+          var downtime = downtimeDao.Save(downtimeDto.ToEntity());
+          pm.SubmitChanges();
+          return downtime.ResourceId;
+        });
+      }
     }
 
     public void DeleteDowntime(Guid downtimeId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      // TODO: pass resource id
-      // author.AuthorizeForResource(resourceId);
-      trans.UseTransaction(() => {
-        dao.DeleteDowntime(downtimeId);
-      });
-    }
-
-    public void UpdateDowntime(Downtime downtime) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      author.AuthorizeForResourceAdministration(downtime.ResourceId);
-      trans.UseTransaction(() => {
-        dao.UpdateDowntime(downtime);
-      });
-    }
-
-    public IEnumerable<Downtime> GetDowntimesForResource(Guid resourceId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      return trans.UseTransaction(() => dao.GetDowntimes(x => x.ResourceId == resourceId));
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("DeleteDowntime")) {
+        var downtimeDao = pm.DowntimeDao;
+        pm.UseTransaction(() => {
+          downtimeDao.Delete(downtimeId);
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public void UpdateDowntime(DT.Downtime downtimeDto) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      AuthorizationManager.AuthorizeForResourceAdministration(downtimeDto.ResourceId);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("UpdateDowntime")) {
+        var downtimeDao = pm.DowntimeDao;
+        pm.UseTransaction(() => {
+          var downtime = downtimeDao.GetById(downtimeDto.Id);
+          if (downtime != null) {
+            downtimeDto.CopyToEntity(downtime);
+          } else {
+            downtimeDao.Save(downtimeDto.ToEntity());
+          }
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public IEnumerable<DT.Downtime> GetDowntimesForResource(Guid resourceId) {
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetDowntimesForResource")) {
+        var downtimeDao = pm.DowntimeDao;
+        return pm.UseTransaction(() => downtimeDao.GetByResourceId(resourceId)
+          .Select(x => x.ToDto())
+          .ToList()
+        );
+      }
     }
     #endregion
@@ -714,48 +928,61 @@
     #region User Methods
     public string GetUsernameByUserId(Guid userId) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
-      var user = ServiceLocator.Instance.UserManager.GetUserById(userId);
-      if (user != null)
-        return user.UserName;
-      else
-        return null;
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      var user = UserManager.GetUserById(userId);
+      return user != null ? user.UserName : null;
     }
 
     public Guid GetUserIdByUsername(string username) {
-      authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
+      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
       var user = ServiceLocator.Instance.UserManager.GetUserByName(username);
-      return user != null ? (Guid)user.ProviderUserKey : Guid.Empty;
-    }
-    #endregion
-
-    #region UserPriority Methods
-    public IEnumerable<UserPriority> GetUserPriorities() {
-      return trans.UseTransaction(() => dao.GetUserPriorities(x => true));
-    }
-    #endregion
-
-    #region Helper Methods
-    private IEnumerable<Task> GetChildTasks(Guid? parentTaskId, bool recursive, bool includeParent) {
-      var tasks = new List<Task>(dao.GetTasks(x => parentTaskId == null ? !x.ParentTaskId.HasValue : x.ParentTaskId.Value == parentTaskId));
-
-      if (recursive) {
-        var childs = new List<Task>();
-        foreach (var task in tasks) {
-          childs.AddRange(GetChildTasks(task.Id, recursive, false));
-        }
-        tasks.AddRange(childs);
-      }
-
-      if (includeParent) tasks.Add(GetTask(parentTaskId.Value));
-      return tasks;
-    }
-    #endregion
-
-    #region Statistics Methods
-    public IEnumerable<Statistics> GetStatistics() {
-      return trans.UseTransaction(() => { return dao.GetStatistics(x => true); });
-    }
-    public IEnumerable<Statistics> GetStatisticsForTimePeriod(DateTime from, DateTime to) {
-      return trans.UseTransaction(() => { return dao.GetStatistics(x => x.Timestamp >= from && x.Timestamp <= to); });
+      return user != null ? (Guid?)user.ProviderUserKey ?? Guid.Empty : Guid.Empty;
+    }
+    #endregion
+
+    #region UserPriorities Methods
+    public IEnumerable<DT.UserPriority> GetUserPriorities() {
+      var pm = PersistenceManager;
+      using (new PerformanceLogger("GetUserPriorities")) {
+        var userPriorityDao = pm.UserPriorityDao;
+        return pm.UseTransaction(() => userPriorityDao.GetAll()
+          .Select(x => x.ToDto())
+          .ToList()
+        );
+      }
+    }
+    #endregion
+
+    #region Private Helper Methods
+    private void UpdateTaskState(IPersistenceManager pm, DA.Task task, DT.TaskState taskState, Guid? slaveId, Guid? userId, string exception) {
+      var stateLogDao = pm.StateLogDao;
+      var taskStateEntity = taskState.ToEntity();
+      if (task.Command == DA.Command.Pause && task.State == DA.TaskState.Paused
+          || task.Command == DA.Command.Abort && task.State == DA.TaskState.Aborted
+          || task.Command == DA.Command.Stop && task.State == DA.TaskState.Aborted) {
+        task.Command = null;
+      } else if (taskStateEntity == DA.TaskState.Paused && task.Command != null) {
+        // slave paused and uploaded the task (no user-command) -> set waiting.
+        taskStateEntity = DA.TaskState.Waiting;
+      }
+      stateLogDao.Save(new DA.StateLog {
+        State = taskStateEntity,
+        DateTime = DateTime.Now,
+        TaskId = task.TaskId,
+        UserId = userId,
+        SlaveId = slaveId,
+        Exception = exception
+      });
+      task.State = taskStateEntity;
+    }
+
+    private DA.Resource AuthorizeForResource(IPersistenceManager pm, Guid resourceId) {
+      var resourceDao = pm.ResourceDao;
+      var resource = resourceDao.GetById(resourceId);
+      if (resource == null) throw new SecurityException("Not authorized");
+      if (resource.OwnerUserId != UserManager.CurrentUserId
+          && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
+        throw new SecurityException("Not authorized");
+      }
+      return resource;
     }
     #endregion
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveStatisticsGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/HiveStatisticsGenerator.cs	(revision 12878)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/HiveStatisticsGenerator.cs	(revision 12878)
@@ -0,0 +1,396 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using System.Collections.Generic;
+using System.Data.Linq;
+using System.Linq;
+using HeuristicLab.Services.Access.DataAccess;
+using HeuristicLab.Services.Hive.DataAccess;
+using HeuristicLab.Services.Hive.DataAccess.Manager;
+
+namespace HeuristicLab.Services.Hive {
+  public class HiveStatisticsGenerator : IStatisticsGenerator {
+
+    private const string UnknownUserName = "Unknown";
+    private static readonly TimeSpan SmallestTimeSpan = new TimeSpan(0, 5, 0);
+    private static readonly TaskState[] CompletedStates = { TaskState.Finished, TaskState.Aborted, TaskState.Failed };
+
+    public void GenerateStatistics() {
+      using (var pm = new PersistenceManager()) {
+        pm.UseTransaction(() => {
+          UpdateDimUserTable(pm);
+          UpdateDimJobTable(pm);
+          UpdateDimClientsTable(pm);
+          pm.SubmitChanges();
+        });
+
+        DimTime time = null;
+        pm.UseTransaction(() => {
+          time = UpdateDimTimeTable(pm);
+          pm.SubmitChanges();
+        });
+
+        if (time != null) {
+          pm.UseTransaction(() => {
+            UpdateFactClientInfoTable(time, pm);
+            pm.SubmitChanges();
+          });
+
+          pm.UseTransaction(() => {
+            UpdateTaskFactsTable(time, pm);
+            try {
+              pm.SubmitChanges();
+              UpdateExistingDimJobs(pm);
+              pm.SubmitChanges();
+            }
+            catch (DuplicateKeyException e) {
+              var logger = LogFactory.GetLogger(typeof(HiveStatisticsGenerator).Namespace);
+              logger.Log(string.Format(
+                @"Propable change from summertime to wintertime, resulting in overlapping times.
+                          On wintertime to summertime change, slave timeouts and a fact gap will occur. 
+                          Exception Details: {0}", e));
+            }
+          });
+        }
+      }
+    }
+
+    private DimTime UpdateDimTimeTable(PersistenceManager pm) {
+      var dimTimeDao = pm.DimTimeDao;
+      var now = DateTime.Now;
+      var timeEntry = new DimTime {
+        Time = now,
+        Minute = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0),
+        Hour = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0),
+        Day = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0),
+        Month = new DateTime(now.Year, now.Month, 1, 0, 0, 0),
+        Year = new DateTime(now.Year, 1, 1, 0, 0, 0)
+      };
+      return dimTimeDao.Save(timeEntry);
+    }
+
+    private void UpdateDimUserTable(PersistenceManager pm) {
+      var dimUserDao = pm.DimUserDao;
+      var resourceDao = pm.ResourceDao;
+      var jobDao = pm.JobDao;
+      var existingUserIds = dimUserDao.GetAll().Select(x => x.UserId);
+      var vaildResourceOwnerIds = resourceDao.GetResourcesWithValidOwner().Select(x => x.OwnerUserId.Value);
+      var jobOwnerIds = jobDao.GetAll().Select(x => x.OwnerUserId);
+      var newUserIds = vaildResourceOwnerIds
+        .Union(jobOwnerIds)
+        .Where(id => !existingUserIds.Contains(id))
+        .ToList();
+      dimUserDao.Save(newUserIds.Select(x => new DimUser {
+        UserId = x,
+        Name = GetUserName(x)
+      }));
+    }
+
+    private void UpdateDimJobTable(PersistenceManager pm) {
+      var dimJobDao = pm.DimJobDao;
+      var jobDao = pm.JobDao;
+      var taskDao = pm.TaskDao;
+      var dimJobIds = dimJobDao.GetAll().Select(x => x.JobId);
+      var newJobs = jobDao.GetAll()
+        .Where(x => !dimJobIds.Contains(x.JobId))
+        .Select(x => new {
+          JobId = x.JobId,
+          UserId = x.OwnerUserId,
+          JobName = x.Name ?? string.Empty,
+          DateCreated = x.DateCreated,
+          TotalTasks = taskDao.GetAll().Count(y => y.JobId == x.JobId)
+        })
+        .ToList();
+      dimJobDao.Save(newJobs.Select(x => new DimJob {
+        JobId = x.JobId,
+        JobName = x.JobName,
+        UserId = x.UserId,
+        UserName = GetUserName(x.UserId),
+        DateCreated = x.DateCreated,
+        TotalTasks = x.TotalTasks,
+        CompletedTasks = 0,
+        DateCompleted = null
+      }));
+    }
+
+    private void UpdateExistingDimJobs(PersistenceManager pm) {
+      var jobDao = pm.JobDao;
+      var dimJobDao = pm.DimJobDao;
+      var factTaskDao = pm.FactTaskDao;
+      foreach (var dimJob in dimJobDao.GetNotCompletedJobs()) {
+        var taskStates = factTaskDao.GetByJobId(dimJob.JobId)
+            .GroupBy(x => x.TaskState)
+            .Select(x => new {
+              State = x.Key,
+              Count = x.Count()
+            }).ToList();
+        int totalTasks = 0, completedTasks = 0;
+        foreach (var state in taskStates) {
+          totalTasks += state.Count;
+          if (CompletedStates.Contains(state.State)) {
+            completedTasks += state.Count;
+          }
+        }
+        if (totalTasks == completedTasks) {
+          var completeDate = factTaskDao.GetLastCompletedTaskFromJob(dimJob.JobId);
+          if (completeDate == null) {
+            if (jobDao.GetById(dimJob.JobId) == null) {
+              completeDate = DateTime.Now;
+            }
+          }
+          dimJob.DateCompleted = completeDate;
+        }
+        dimJob.TotalTasks = totalTasks;
+        dimJob.CompletedTasks = completedTasks;
+      }
+    }
+
+    private void UpdateDimClientsTable(PersistenceManager pm) {
+      var dimClientDao = pm.DimClientDao;
+      var slaveDao = pm.SlaveDao;
+      var slaves = slaveDao.GetAll();
+      var recentlyAddedClients = dimClientDao.GetActiveClients();
+      var slaveIds = slaves.Select(x => x.ResourceId);
+
+      var removedClientIds = recentlyAddedClients
+        .Where(x => !slaveIds.Contains(x.ResourceId))
+        .Select(x => x.Id);
+      var modifiedClients =
+        from slave in slaves
+        join client in recentlyAddedClients on slave.ResourceId equals client.ResourceId
+        where (slave.Name != client.Name
+               || slave.ParentResourceId == null && client.ResourceGroupId != null // because both can be null and null comparison
+               || slave.ParentResourceId != null && client.ResourceGroupId == null // does return no entry on the sql server
+               || slave.ParentResourceId != client.ResourceGroupId
+               || ((slave.ParentResource != null) && slave.ParentResource.ParentResourceId != client.ResourceGroup2Id))
+        select new {
+          SlaveId = slave.ResourceId,
+          ClientId = client.Id
+        };
+      var clientIds = dimClientDao.GetActiveClients().Select(x => x.ResourceId);
+      var modifiedClientIds = modifiedClients.Select(x => x.SlaveId);
+      var newClients = slaves
+        .Where(x => !clientIds.Contains(x.ResourceId)
+                    || modifiedClientIds.Contains(x.ResourceId))
+        .Select(x => new {
+          x.ResourceId,
+          x.Name,
+          ResourceGroupId = x.ParentResourceId,
+          GroupName = x.ParentResource != null ? x.ParentResource.Name : null,
+          ResourceGroup2Id = x.ParentResource != null ? x.ParentResource.ParentResourceId : null,
+          GroupName2 = x.ParentResource != null ? x.ParentResource.ParentResource != null ? x.ParentResource.ParentResource.Name : null : null
+        })
+        .ToList();
+
+      var clientsToUpdate = removedClientIds.Union(modifiedClients.Select(x => x.ClientId));
+      dimClientDao.UpdateExpirationTime(clientsToUpdate, DateTime.Now);
+      dimClientDao.Save(newClients.Select(x => new DimClient {
+        ResourceId = x.ResourceId,
+        Name = x.Name,
+        ExpirationTime = null,
+        ResourceGroupId = x.ResourceGroupId,
+        GroupName = x.GroupName,
+        ResourceGroup2Id = x.ResourceGroup2Id,
+        GroupName2 = x.GroupName2
+      }));
+    }
+
+    private void UpdateFactClientInfoTable(DimTime newTime, PersistenceManager pm) {
+      var factClientInfoDao = pm.FactClientInfoDao;
+      var slaveDao = pm.SlaveDao;
+      var dimClientDao = pm.DimClientDao;
+
+      var newRawFactInfos =
+        from s in slaveDao.GetAll()
+        join c in dimClientDao.GetActiveClients() on s.ResourceId equals c.ResourceId
+        join lcf in factClientInfoDao.GetLastUpdateTimestamps() on c.ResourceId equals lcf.ResourceId into joinCf
+        from cf in joinCf.DefaultIfEmpty()
+        select new {
+          ClientId = c.Id,
+          UserId = s.OwnerUserId ?? Guid.Empty,
+          TotalCores = s.Cores ?? 0,
+          FreeCores = s.FreeCores ?? 0,
+          TotalMemory = s.Memory ?? 0,
+          FreeMemory = s.FreeMemory ?? 0,
+          CpuUtilization = s.CpuUtilization,
+          SlaveState = s.SlaveState,
+          IsAllowedToCalculate = s.IsAllowedToCalculate,
+          LastFactTimestamp = cf.Timestamp
+        };
+
+      factClientInfoDao.Save(
+        from x in newRawFactInfos.ToList()
+        let duration = x.LastFactTimestamp != null
+                       ? (int)(newTime.Time - (DateTime)x.LastFactTimestamp).TotalSeconds
+                       : (int)SmallestTimeSpan.TotalSeconds
+        select new FactClientInfo {
+          ClientId = x.ClientId,
+          DimTime = newTime,
+          UserId = x.UserId,
+          NumUsedCores = x.TotalCores - x.FreeCores,
+          NumTotalCores = x.TotalCores,
+          UsedMemory = x.TotalMemory - x.FreeMemory,
+          TotalMemory = x.TotalMemory,
+          CpuUtilization = Math.Round(x.CpuUtilization, 2),
+          SlaveState = x.SlaveState,
+          IdleTime = x.SlaveState == SlaveState.Idle && x.IsAllowedToCalculate ? duration : 0,
+          UnavailableTime = x.SlaveState == SlaveState.Idle && !x.IsAllowedToCalculate ? duration : 0,
+          OfflineTime = x.SlaveState == SlaveState.Offline ? duration : 0,
+          IsAllowedToCalculate = x.IsAllowedToCalculate
+        }
+      );
+    }
+
+    private void UpdateTaskFactsTable(DimTime newTime, PersistenceManager pm) {
+      var factTaskDao = pm.FactTaskDao;
+      var taskDao = pm.TaskDao;
+      var dimClientDao = pm.DimClientDao;
+
+      var factTaskIds = factTaskDao.GetAll().Select(x => x.TaskId);
+      var notFinishedFactTasks = factTaskDao.GetNotFinishedTasks().Select(x => new {
+        x.TaskId,
+        x.LastClientId
+      });
+
+      var newTasks =
+        from task in taskDao.GetAllChildTasks()
+        let stateLogs = task.StateLogs.OrderByDescending(x => x.DateTime)
+        let lastSlaveId = stateLogs.First(x => x.SlaveId != null).SlaveId
+        where (!factTaskIds.Contains(task.TaskId)
+               || notFinishedFactTasks.Select(x => x.TaskId).Contains(task.TaskId))
+        join lastFactTask in notFinishedFactTasks on task.TaskId equals lastFactTask.TaskId into lastFactPerTask
+        from lastFact in lastFactPerTask.DefaultIfEmpty()
+        join client in dimClientDao.GetActiveClients() on lastSlaveId equals client.ResourceId into clientsPerSlaveId
+        from client in clientsPerSlaveId.DefaultIfEmpty()
+        select new {
+          TaskId = task.TaskId,
+          JobId = task.JobId,
+          Priority = task.Priority,
+          CoresRequired = task.CoresNeeded,
+          MemoryRequired = task.MemoryNeeded,
+          State = task.State,
+          StateLogs = stateLogs.OrderBy(x => x.DateTime),
+          LastClientId = client != null
+                         ? client.Id : lastFact != null
+                         ? lastFact.LastClientId : (Guid?)null
+        };
+      factTaskDao.Save(
+        from x in newTasks.ToList()
+        let taskData = CalculateFactTaskData(x.StateLogs)
+        select new FactTask {
+          TaskId = x.TaskId,
+          JobId = x.JobId,
+          StartTime = taskData.StartTime,
+          EndTime = taskData.EndTime,
+          LastClientId = x.LastClientId,
+          Priority = x.Priority,
+          CoresRequired = x.CoresRequired,
+          MemoryRequired = x.MemoryRequired,
+          NumCalculationRuns = taskData.CalculationRuns,
+          NumRetries = taskData.Retries,
+          WaitingTime = taskData.WaitingTime,
+          CalculatingTime = taskData.CalculatingTime,
+          TransferTime = taskData.TransferTime,
+          TaskState = x.State,
+          Exception = taskData.Exception,
+          InitialWaitingTime = taskData.InitialWaitingTime
+        });
+      factTaskDao.Delete(notFinishedFactTasks.Select(x => x.TaskId));
+    }
+
+    private string GetUserName(Guid userId) {
+      try {
+        // we cannot use the ServiceLocator.Instance.UserManager since the janitor service
+        // is not hosted in the iis the MemberShip.GetUser method causes exceptions
+        // needs to be further investigated current workaround: use the authenticationcontext
+        // we could also connect to the access service to get the user name
+        using (ASPNETAuthenticationDataContext dc = new ASPNETAuthenticationDataContext()) {
+          var user = dc.aspnet_Users.SingleOrDefault(x => x.UserId == userId);
+          return user != null ? user.UserName : UnknownUserName;
+        }
+      }
+      catch (Exception) {
+        return UnknownUserName;
+      }
+    }
+
+    private class FactTaskData {
+      public int CalculationRuns { get; set; }
+      public int Retries { get; set; }
+      public long CalculatingTime { get; set; }
+      public long WaitingTime { get; set; }
+      public long TransferTime { get; set; }
+      public long InitialWaitingTime { get; set; }
+      public string Exception { get; set; }
+      public DateTime? StartTime { get; set; }
+      public DateTime? EndTime { get; set; }
+    }
+
+    private FactTaskData CalculateFactTaskData(IEnumerable<StateLog> stateLogs) {
+      var factTaskData = new FactTaskData();
+      var enumerator = stateLogs.GetEnumerator();
+      if (enumerator.MoveNext()) {
+        StateLog current = enumerator.Current, first = current, prev = null;
+        while (current != null) {
+          var next = enumerator.MoveNext() ? enumerator.Current : null;
+          int timeSpanInSeconds;
+          if (next != null) {
+            timeSpanInSeconds = (int)(next.DateTime - current.DateTime).TotalSeconds;
+          } else {
+            timeSpanInSeconds = (int)(DateTime.Now - current.DateTime).TotalSeconds;
+            factTaskData.Exception = current.Exception;
+          }
+          switch (current.State) {
+            case TaskState.Calculating:
+              factTaskData.CalculatingTime += timeSpanInSeconds;
+              factTaskData.CalculationRuns++;
+              if (factTaskData.CalculationRuns == 1) {
+                factTaskData.StartTime = current.DateTime;
+                factTaskData.InitialWaitingTime = (int)(current.DateTime - first.DateTime).TotalSeconds;
+              }
+              if (prev != null && prev.State != TaskState.Transferring) {
+                factTaskData.Retries++;
+              }
+              break;
+
+            case TaskState.Waiting:
+              factTaskData.WaitingTime += timeSpanInSeconds;
+              break;
+
+            case TaskState.Transferring:
+              factTaskData.TransferTime += timeSpanInSeconds;
+              break;
+
+            case TaskState.Finished:
+            case TaskState.Failed:
+            case TaskState.Aborted:
+              factTaskData.EndTime = current.DateTime;
+              break;
+          }
+          prev = current;
+          current = next;
+        }
+      }
+      return factTaskData;
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs	(revision 12753)
+++ 	(revision )
@@ -1,166 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-using HeuristicLab.Services.Hive.DataAccess;
-using DT = HeuristicLab.Services.Hive.DataTransfer;
-
-namespace HeuristicLab.Services.Hive {
-  public interface IHiveDao {
-    #region Task Methods
-    DT.Task GetTask(Guid id);
-    IEnumerable<DT.Task> GetTasks(Expression<Func<Task, bool>> predicate);
-    IEnumerable<DT.LightweightTask> GetLightweightTasks(Expression<Func<Task, bool>> predicate);
-    IEnumerable<DT.LightweightTask> GetLightweightTasksWithoutStateLog(Expression<Func<Task, bool>> predicate);
-    Guid AddTask(DT.Task dto);
-    void UpdateTaskAndPlugins(DT.Task dto);
-    void UpdateTaskAndStateLogs(DT.Task dto);
-    void UpdateTask(DT.Task dto);
-    void DeleteTask(Guid id);
-    IEnumerable<TaskInfoForScheduler> GetWaitingTasks(DT.Slave slave);
-    IEnumerable<DT.Task> GetParentTasks(IEnumerable<Guid> resourceIds, int count, bool finished);
-    DT.Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception);
-    #endregion
-
-    #region TaskData Methods
-    DT.TaskData GetTaskData(Guid id);
-    IEnumerable<DT.TaskData> GetTaskDatas(Expression<Func<TaskData, bool>> predicate);
-    Guid AddTaskData(DT.TaskData dto);
-    void UpdateTaskData(DT.TaskData dto);
-    void DeleteTaskData(Guid id);
-    #endregion
-
-    #region StateLog Methods
-    DT.StateLog GetStateLog(Guid id);
-    IEnumerable<DT.StateLog> GetStateLogs(Expression<Func<StateLog, bool>> predicate);
-    Guid AddStateLog(DT.StateLog dto);
-    void UpdateStateLog(DT.StateLog dto);
-    void DeleteStateLog(Guid id);
-    #endregion
-
-    #region Job Methods
-    DT.Job GetJob(Guid id);
-    IEnumerable<DT.Job> GetJobs(Expression<Func<Job, bool>> predicate);
-    IEnumerable<JobInfoForScheduler> GetJobInfoForScheduler(Expression<Func<Job, bool>> predicate);
-    Guid AddJob(DT.Job dto);
-    void UpdateJob(DT.Job dto);
-    void DeleteJob(Guid id);
-    #endregion
-
-    #region JobPermission Methods
-    DT.JobPermission GetJobPermission(Guid jobId, Guid grantedUserId);
-    IEnumerable<DT.JobPermission> GetJobPermissions(Expression<Func<JobPermission, bool>> predicate);
-    void AddJobPermission(DT.JobPermission dto);
-    void UpdateJobPermission(DT.JobPermission dto);
-    void DeleteJobPermission(Guid jobId, Guid grantedUserId);
-    void SetJobPermission(Guid jobId, Guid grantedByUserId, Guid grantedUserId, Permission permission);
-    #endregion
-
-    #region Plugin Methods
-    DT.Plugin GetPlugin(Guid id);
-    IEnumerable<DT.Plugin> GetPlugins(Expression<Func<Plugin, bool>> predicate);
-    Guid AddPlugin(DT.Plugin dto);
-    void UpdatePlugin(DT.Plugin dto);
-    void DeletePlugin(Guid id);
-    #endregion
-
-    #region PluginData Methods
-    DT.PluginData GetPluginData(Guid id);
-    IEnumerable<DT.PluginData> GetPluginDatas(Expression<Func<PluginData, bool>> predicate);
-    Guid AddPluginData(DT.PluginData dto);
-    void UpdatePluginData(DT.PluginData dto);
-    void DeletePluginData(Guid id);
-    #endregion
-
-    #region Slave Methods
-    DT.Slave GetSlave(Guid id);
-    IEnumerable<DT.Slave> GetSlaves(Expression<Func<Slave, bool>> predicate);
-    Guid AddSlave(DT.Slave dto);
-    void UpdateSlave(DT.Slave dto);
-    void DeleteSlave(Guid id);
-    #endregion
-
-    #region SlaveGroup Methods
-    DT.SlaveGroup GetSlaveGroup(Guid id);
-    IEnumerable<DT.SlaveGroup> GetSlaveGroups(Expression<Func<SlaveGroup, bool>> predicate);
-    Guid AddSlaveGroup(DT.SlaveGroup dto);
-    void UpdateSlaveGroup(DT.SlaveGroup dto);
-    void DeleteSlaveGroup(Guid id);
-    #endregion
-
-    #region Resource Methods
-    DT.Resource GetResource(Guid id);
-    IEnumerable<DT.Resource> GetResources(Expression<Func<Resource, bool>> predicate);
-    Guid AddResource(DT.Resource dto);
-    void UpdateResource(DT.Resource dto);
-    void DeleteResource(Guid id);
-    void AssignJobToResource(Guid taskId, IEnumerable<Guid> resourceIds);
-    IEnumerable<DT.Resource> GetAssignedResources(Guid jobId);
-    IEnumerable<DT.Resource> GetParentResources(Guid resourceId);
-    IEnumerable<DT.Resource> GetChildResources(Guid resourceId);
-    IEnumerable<DT.Task> GetJobsByResourceId(Guid resourceId);
-    #endregion
-
-    #region ResourcePermission Methods
-    DT.ResourcePermission GetResourcePermission(Guid resourceId, Guid grantedUserId);
-    IEnumerable<DT.ResourcePermission> GetResourcePermissions(Expression<Func<ResourcePermission, bool>> predicate);
-    void AddResourcePermission(DT.ResourcePermission dto);
-    void UpdateResourcePermission(DT.ResourcePermission dto);
-    void DeleteResourcePermission(Guid resourceId, Guid grantedUserId);
-    #endregion
-
-    #region Authorization Methods
-    Permission GetPermissionForTask(Guid taskId, Guid userId);
-    Permission GetPermissionForJob(Guid jobId, Guid userId);
-    Guid GetJobForTask(Guid taskId);
-    #endregion
-
-    #region Lifecycle Methods
-    DateTime GetLastCleanup();
-    void SetLastCleanup(DateTime datetime);
-    #endregion
-
-    #region Downtime Methods
-    DT.Downtime GetDowntime(Guid id);
-    IEnumerable<DT.Downtime> GetDowntimes(Expression<Func<Downtime, bool>> predicate);
-    Guid AddDowntime(DT.Downtime dto);
-    void UpdateDowntime(DT.Downtime dto);
-    void DeleteDowntime(Guid id);
-    #endregion
-
-    #region Statistics Methods
-    Dictionary<Guid, int> GetWaitingTasksByUserForResources(List<Guid> resourceIds);
-    Dictionary<Guid, int> GetCalculatingTasksByUserForResources(List<Guid> resourceIds);
-    DT.Statistics GetStatistic(Guid id);
-    IEnumerable<DT.Statistics> GetStatistics(Expression<Func<Statistics, bool>> predicate);
-    Guid AddStatistics(DT.Statistics dto);
-    void DeleteStatistics(Guid id);
-    List<DT.UserStatistics> GetUserStatistics();
-    #endregion
-
-    #region UserPriority Methods
-    IEnumerable<DT.UserPriority> GetUserPriorities(Expression<Func<UserPriority, bool>> predicate);
-    void EnqueueUserPriority(DT.UserPriority userPriority);
-    #endregion
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IOptimizedHiveDao.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IOptimizedHiveDao.cs	(revision 12753)
+++ 	(revision )
@@ -1,80 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Services.Hive.DataAccess;
-using DT = HeuristicLab.Services.Hive.DataTransfer;
-namespace HeuristicLab.Services.Hive {
-  public interface IOptimizedHiveDao {
-    #region Task Methods
-    Task GetTaskById(Guid task);
-    Task GetTaskByDto(DT.Task taskDto);
-    Tuple<Task, Guid?> GetTaskByIdAndLastStateLogSlaveId(Guid taskId);
-
-    IEnumerable<TaskInfoForScheduler> GetWaitingTasks(Slave slave);
-    IQueryable<DT.LightweightTask> GetLightweightTasks(Guid jobId);
-
-    void UpdateTask(Task task);
-    Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception);
-
-    Guid AddTask(Task task);
-    void AssignJobToResource(Guid taskId, IEnumerable<Guid> resourceIds);
-
-    bool TaskIsAllowedToBeCalculatedBySlave(Guid taskId, Guid slaveId);
-    #endregion
-
-    #region TaskData Methods
-    TaskData GetTaskDataByDto(DT.TaskData taskDataDto);
-    void UpdateTaskData(TaskData taskData);
-    #endregion
-
-    #region Plugin Methods
-    Plugin GetPluginById(Guid pluginId);
-    #endregion
-
-    #region Slave Methods
-    Slave GetSlaveById(Guid id);
-
-    void UpdateSlave(Slave slave);
-
-    bool SlaveHasToShutdownComputer(Guid slaveId);
-    bool SlaveIsAllowedToCalculate(Guid slaveId);
-    #endregion
-
-    #region Resource Methods
-    IEnumerable<Guid> GetAssignedResourceIds(Guid jobId);
-    #endregion
-
-    #region Website Methods
-
-    IEnumerable<Guid> GetAllResourceIds();
-
-    int GetNumberOfWaitingTasks();
-
-    Dictionary<Guid, int> GetCalculatingTasksByUser();
-
-    Dictionary<Guid, int> GetWaitingTasksByUser();
-
-    #endregion
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IServiceLocator.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IServiceLocator.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IServiceLocator.cs	(revision 12878)
@@ -20,5 +20,6 @@
 #endregion
 
-using HeuristicLab.Services.Hive.DataAccess;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
+using HeuristicLab.Services.Hive.Manager;
 
 namespace HeuristicLab.Services.Hive {
@@ -26,8 +27,7 @@
     Access.IRoleVerifier RoleVerifier { get; }
     IAuthorizationManager AuthorizationManager { get; }
-    IHiveDao HiveDao { get; }
-    IOptimizedHiveDao OptimizedHiveDao { get; }
+    IPersistenceManager PersistenceManager { get; }
     IEventManager EventManager { get; }
-    ITransactionManager TransactionManager { get; }
+    IStatisticsGenerator StatisticsGenerator { get; }
     Access.IUserManager UserManager { get; }
     HeartbeatManager HeartbeatManager { get; }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IStatisticsGenerator.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IStatisticsGenerator.cs	(revision 12878)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IStatisticsGenerator.cs	(revision 12878)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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
+
+namespace HeuristicLab.Services.Hive {
+  public interface IStatisticsGenerator {
+    void GenerateStatistics();
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/AuthorizationManager.cs	(revision 12878)
@@ -22,5 +22,8 @@
 using System;
 using System.Security;
+using HeuristicLab.Services.Access;
 using HeuristicLab.Services.Hive.DataAccess;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
+using DA = HeuristicLab.Services.Hive.DataAccess;
 using DT = HeuristicLab.Services.Hive.DataTransfer;
 
@@ -28,27 +31,72 @@
 namespace HeuristicLab.Services.Hive {
   public class AuthorizationManager : IAuthorizationManager {
+
+    private const string NOT_AUTHORIZED = "Current user is not authorized to access the requested resource";
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    private IUserManager UserManager {
+      get { return ServiceLocator.Instance.UserManager; }
+    }
+
+    private IRoleVerifier RoleVerifier {
+      get { return ServiceLocator.Instance.RoleVerifier; }
+    }
+
     public void Authorize(Guid userId) {
       if (userId != ServiceLocator.Instance.UserManager.CurrentUserId)
-        throw new SecurityException("Current user is not authorized to access object");
+        throw new SecurityException(NOT_AUTHORIZED);
     }
 
     public void AuthorizeForTask(Guid taskId, DT.Permission requiredPermission) {
       if (ServiceLocator.Instance.RoleVerifier.IsInRole(HiveRoles.Slave)) return; // slave-users can access all tasks
-
-      Permission permission = ServiceLocator.Instance.HiveDao.GetPermissionForTask(taskId, ServiceLocator.Instance.UserManager.CurrentUserId);
-      if (permission == Permission.NotAllowed || (permission != DT.Convert.ToEntity(requiredPermission) && DT.Convert.ToEntity(requiredPermission) == Permission.Full))
-        throw new SecurityException("Current user is not authorized to access task");
+      var pm = PersistenceManager;
+      var taskDao = pm.TaskDao;
+      pm.UseTransaction(() => {
+        var task = taskDao.GetById(taskId);
+        if (task == null) throw new SecurityException(NOT_AUTHORIZED);
+        AuthorizeJob(pm, task.JobId, requiredPermission);
+      });
     }
 
     public void AuthorizeForJob(Guid jobId, DT.Permission requiredPermission) {
-      Permission permission = ServiceLocator.Instance.HiveDao.GetPermissionForJob(jobId, ServiceLocator.Instance.UserManager.CurrentUserId);
-      if (permission == Permission.NotAllowed || (permission != DT.Convert.ToEntity(requiredPermission) && DT.Convert.ToEntity(requiredPermission) == Permission.Full))
-        throw new SecurityException("Current user is not authorized to access task");
+      var pm = PersistenceManager;
+      pm.UseTransaction(() => {
+        AuthorizeJob(pm, jobId, requiredPermission);
+      });
     }
 
     public void AuthorizeForResourceAdministration(Guid resourceId) {
-      Resource resource = DT.Convert.ToEntity(ServiceLocator.Instance.HiveDao.GetResource(resourceId));
-      if (resource.OwnerUserId != ServiceLocator.Instance.UserManager.CurrentUserId && !ServiceLocator.Instance.RoleVerifier.IsInRole(HiveRoles.Administrator))
-        throw new SecurityException("Current user is not authorized to access resource");
+      var pm = PersistenceManager;
+      var resourceDao = pm.ResourceDao;
+      pm.UseTransaction(() => {
+        var resource = resourceDao.GetById(resourceId);
+        if (resource == null) throw new SecurityException(NOT_AUTHORIZED);
+        if (resource.OwnerUserId != UserManager.CurrentUserId
+            && !RoleVerifier.IsInRole(HiveRoles.Administrator)) {
+          throw new SecurityException(NOT_AUTHORIZED);
+        }
+      });
+    }
+
+    private DA.Permission GetPermissionForJob(IPersistenceManager pm, Guid jobId, Guid userId) {
+      var jobDao = pm.JobDao;
+      var jobPermissionDao = pm.JobPermissionDao;
+      var job = jobDao.GetById(jobId);
+      if (job == null) return DA.Permission.NotAllowed;
+      if (job.OwnerUserId == userId) return DA.Permission.Full;
+      var jobPermission = jobPermissionDao.GetByJobAndUserId(jobId, userId);
+      if (jobPermission == null) return DA.Permission.NotAllowed;
+      return jobPermission.Permission;
+    }
+
+    private void AuthorizeJob(IPersistenceManager pm, Guid jobId, DT.Permission requiredPermission) {
+      var requiredPermissionEntity = requiredPermission.ToEntity();
+      DA.Permission permission = GetPermissionForJob(pm, jobId, UserManager.CurrentUserId);
+      if (permission == Permission.NotAllowed
+          || ((permission != requiredPermissionEntity) && requiredPermissionEntity == Permission.Full)) {
+        throw new SecurityException(NOT_AUTHORIZED);
+      }
     }
   }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/EventManager.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/EventManager.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/EventManager.cs	(revision 12878)
@@ -21,63 +21,28 @@
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Services.Hive.DataAccess;
-using DT = HeuristicLab.Services.Hive.DataTransfer;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
 
-
-namespace HeuristicLab.Services.Hive {
-  /// <summary>
-  /// This class offers methods for cleaning up offline slaves and task
-  /// </summary>
+namespace HeuristicLab.Services.Hive.Manager {
   public class EventManager : IEventManager {
-    private IHiveDao dao {
-      get { return ServiceLocator.Instance.HiveDao; }
-    }
-    private IAuthorizationManager auth {
-      get { return ServiceLocator.Instance.AuthorizationManager; }
-    }
-    private ILogger log {
-      get { return LogFactory.GetLogger(this.GetType().Namespace); }
-    }
-    private DataAccess.ITransactionManager trans {
-      get { return ServiceLocator.Instance.TransactionManager; }
+    private const string SlaveTimeout = "Slave timed out.";
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
     }
 
     public void Cleanup() {
-      trans.UseTransaction(() => {
-        SetTimeoutSlavesOffline();
-        SetTimeoutTasksWaiting();
-        DeleteObsoleteSlaves();
+      var pm = PersistenceManager;
+      pm.UseTransaction(() => {
+        SetTimeoutSlavesOffline(pm);
+        SetTimeoutTasksWaiting(pm);
+        DeleteObsoleteSlaves(pm);
+        pm.SubmitChanges();
       });
 
-      trans.UseTransaction(() => {
-        FinishParentTasks();
-        UpdateStatistics();
+      pm.UseTransaction(() => {
+        FinishParentTasks(pm);
+        pm.SubmitChanges();
       });
-    }
-
-    private void UpdateStatistics() {
-      var slaves = dao.GetSlaves(x => x.SlaveState == SlaveState.Calculating || x.SlaveState == SlaveState.Idle);
-
-      var stats = new DataTransfer.Statistics();
-      stats.TimeStamp = DateTime.Now;
-      var slaveStats = new List<DT.SlaveStatistics>();
-      foreach (var slave in slaves) {
-        slaveStats.Add(new DT.SlaveStatistics() {
-          SlaveId = slave.Id,
-          Cores = slave.Cores.HasValue ? slave.Cores.Value : 0,
-          FreeCores = slave.FreeCores.HasValue ? slave.FreeCores.Value : 0,
-          Memory = slave.Memory.HasValue ? slave.Memory.Value : 0,
-          FreeMemory = slave.FreeMemory.HasValue ? slave.FreeMemory.Value : 0,
-          CpuUtilization = slave.CpuUtilization
-        });
-      }
-      stats.SlaveStatistics = slaveStats;
-      //collecting user statistics slows down the db and results in timeouts. 
-      //we have to find another way to deal with this.  
-      //until then the next line is commented out...
-      //stats.UserStatistics = dtoDao.GetUserStatistics();
-      dao.AddStatistics(stats);
     }
 
@@ -85,10 +50,12 @@
     /// Searches for slaves which are timed out, puts them and their task offline
     /// </summary>
-    private void SetTimeoutSlavesOffline() {
-      var slaves = dao.GetSlaves(x => x.SlaveState != SlaveState.Offline);
-      foreach (DT.Slave slave in slaves) {
-        if (!slave.LastHeartbeat.HasValue || (DateTime.Now - slave.LastHeartbeat.Value) > HeuristicLab.Services.Hive.Properties.Settings.Default.SlaveHeartbeatTimeout) {
-          slave.SlaveState = DT.SlaveState.Offline;
-          dao.UpdateSlave(slave);
+    private void SetTimeoutSlavesOffline(IPersistenceManager pm) {
+      var slaveDao = pm.SlaveDao;
+      var slaves = slaveDao.GetOnlineSlaves();
+      foreach (var slave in slaves) {
+        if (!slave.LastHeartbeat.HasValue ||
+            (DateTime.Now - slave.LastHeartbeat.Value) >
+            Properties.Settings.Default.SlaveHeartbeatTimeout) {
+          slave.SlaveState = SlaveState.Offline;
         }
       }
@@ -98,8 +65,18 @@
     /// Looks for parent tasks which have FinishWhenChildJobsFinished and set their state to finished
     /// </summary>
-    private void FinishParentTasks() {
-      var parentTasksToFinish = dao.GetParentTasks(dao.GetResources(x => true).Select(x => x.Id), 0, true);
+    private void FinishParentTasks(IPersistenceManager pm) {
+      var resourceDao = pm.ResourceDao;
+      var taskDao = pm.TaskDao;
+      var resourceIds = resourceDao.GetAll().Select(x => x.ResourceId).ToList();
+      var parentTasksToFinish = taskDao.GetParentTasks(resourceIds, 0, true);
       foreach (var task in parentTasksToFinish) {
-        dao.UpdateTaskState(task.Id, TaskState.Finished, null, null, string.Empty);
+        task.State = TaskState.Finished;
+        task.StateLogs.Add(new StateLog {
+          State = task.State,
+          SlaveId = null,
+          UserId = null,
+          Exception = string.Empty,
+          DateTime = DateTime.Now
+        });
       }
     }
@@ -108,11 +85,18 @@
     /// Looks for task which have not sent heartbeats for some time and reschedules them for calculation
     /// </summary>
-    private void SetTimeoutTasksWaiting() {
-      var tasks = dao.GetTasks(x => (x.State == TaskState.Calculating && (DateTime.Now - x.LastHeartbeat) > HeuristicLab.Services.Hive.Properties.Settings.Default.CalculatingJobHeartbeatTimeout)
-                               || (x.State == TaskState.Transferring && (DateTime.Now - x.LastHeartbeat) > HeuristicLab.Services.Hive.Properties.Settings.Default.TransferringJobHeartbeatTimeout));
-      foreach (var j in tasks) {
-        DT.Task task = dao.UpdateTaskState(j.Id, TaskState.Waiting, null, null, "Slave timed out.");
+    private void SetTimeoutTasksWaiting(IPersistenceManager pm) {
+      var taskDao = pm.TaskDao;
+      var tasks = taskDao.GetAll().Where(x => (x.State == TaskState.Calculating && (DateTime.Now - x.LastHeartbeat) > Properties.Settings.Default.CalculatingJobHeartbeatTimeout)
+                                           || (x.State == TaskState.Transferring && (DateTime.Now - x.LastHeartbeat) > Properties.Settings.Default.TransferringJobHeartbeatTimeout));
+      foreach (var task in tasks) {
+        task.State = TaskState.Waiting;
+        task.StateLogs.Add(new StateLog {
+          State = task.State,
+          SlaveId = null,
+          UserId = null,
+          Exception = SlaveTimeout,
+          DateTime = DateTime.Now
+        });
         task.Command = null;
-        dao.UpdateTask(task);
       }
     }
@@ -121,15 +105,17 @@
     /// Searches for slaves that are disposable and deletes them if they were offline for too long
     /// </summary>
-    private void DeleteObsoleteSlaves() {
-      var slaves = dao.GetSlaves(x => x.IsDisposable.GetValueOrDefault() &&
-                                      x.SlaveState == SlaveState.Offline &&
-                                      (DateTime.Now - x.LastHeartbeat) > Hive.Properties.Settings.Default.SweepInterval)
-                                .Select(x => x.Id)
-                                .ToArray();
-
-      foreach (Guid slaveId in slaves) {
-        var downtimesAvailable = dao.GetDowntimes(x => x.ResourceId == slaveId).Any();
+    private void DeleteObsoleteSlaves(IPersistenceManager pm) {
+      var slaveDao = pm.SlaveDao;
+      var downtimeDao = pm.DowntimeDao;
+      var slaveIds = slaveDao.GetAll()
+        .Where(x => x.IsDisposable.GetValueOrDefault()
+                 && x.SlaveState == SlaveState.Offline
+                 && (DateTime.Now - x.LastHeartbeat) > Properties.Settings.Default.SweepInterval)
+        .Select(x => x.ResourceId)
+        .ToList();
+      foreach (var id in slaveIds) {
+        bool downtimesAvailable = downtimeDao.GetByResourceId(id).Any();
         if (!downtimesAvailable) {
-          dao.DeleteSlave(slaveId);
+          slaveDao.Delete(id);
         }
       }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 12878)
@@ -25,18 +25,18 @@
 using System.Threading;
 using HeuristicLab.Services.Hive.DataAccess;
-using Heartbeat = HeuristicLab.Services.Hive.DataTransfer.Heartbeat;
-
-namespace HeuristicLab.Services.Hive {
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
+using HeuristicLab.Services.Hive.DataTransfer;
+using DA = HeuristicLab.Services.Hive.DataAccess;
+
+namespace HeuristicLab.Services.Hive.Manager {
   public class HeartbeatManager {
     private const string MutexName = "HiveTaskSchedulingMutex";
 
-    private IOptimizedHiveDao dao {
-      get { return ServiceLocator.Instance.OptimizedHiveDao; }
-    }
-    private ITaskScheduler taskScheduler {
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    private ITaskScheduler TaskScheduler {
       get { return ServiceLocator.Instance.TaskScheduler; }
-    }
-    private DataAccess.ITransactionManager trans {
-      get { return ServiceLocator.Instance.TransactionManager; }
     }
 
@@ -47,9 +47,8 @@
     public List<MessageContainer> ProcessHeartbeat(Heartbeat heartbeat) {
       List<MessageContainer> actions = new List<MessageContainer>();
-
-      Slave slave = null;
-      trans.UseTransaction(() => {
-        slave = dao.GetSlaveById(heartbeat.SlaveId);
-      });
+      var pm = PersistenceManager;
+      var slaveDao = pm.SlaveDao;
+      var taskDao = pm.TaskDao;
+      var slave = pm.UseTransaction(() => slaveDao.GetById(heartbeat.SlaveId));
       if (slave == null) {
         actions.Add(new MessageContainer(MessageContainer.MessageType.SayHello));
@@ -58,22 +57,22 @@
           actions.Add(new MessageContainer(MessageContainer.MessageType.NewHBInterval));
         }
-        if (dao.SlaveHasToShutdownComputer(slave.ResourceId)) {
+        if (slaveDao.SlaveHasToShutdownComputer(slave.ResourceId)) {
           actions.Add(new MessageContainer(MessageContainer.MessageType.ShutdownComputer));
         }
-
-        // update slave data
+        // 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.SlaveState = (heartbeat.JobProgress != null && heartbeat.JobProgress.Count > 0)
+          ? DA.SlaveState.Calculating
+          : DA.SlaveState.Idle;
         slave.LastHeartbeat = DateTime.Now;
-
-        trans.UseTransaction(() => {
-          dao.UpdateSlave(slave);
+        pm.UseTransaction(() => {
+          slave.IsAllowedToCalculate = slaveDao.SlaveIsAllowedToCalculate(slave.ResourceId);
+          pm.SubmitChanges();
         });
 
         // update task data
-        actions.AddRange(UpdateTasks(heartbeat, slave.IsAllowedToCalculate));
+        actions.AddRange(UpdateTasks(pm, heartbeat, slave.IsAllowedToCalculate));
 
         // assign new task
@@ -82,18 +81,22 @@
           var mutex = new Mutex(false, MutexName);
           try {
-
             mutexAquired = mutex.WaitOne(Properties.Settings.Default.SchedulingPatience);
-            if (!mutexAquired)
+            if (mutexAquired) {
+              var waitingTasks = pm.UseTransaction(() => taskDao.GetWaitingTasks(slave)
+                  .Select(x => new TaskInfoForScheduler {
+                    TaskId = x.TaskId,
+                    JobId = x.JobId,
+                    Priority = x.Priority
+                  })
+                  .ToList()
+              );
+              var availableTasks = TaskScheduler.Schedule(waitingTasks).ToArray();
+              if (availableTasks.Any()) {
+                var task = availableTasks.First();
+                AssignTask(pm, slave, task.TaskId);
+                actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateTask, task.TaskId));
+              }
+            } else {
               LogFactory.GetLogger(this.GetType().Namespace).Log("HeartbeatManager: The mutex used for scheduling could not be aquired.");
-            else {
-              trans.UseTransaction(() => {
-                IEnumerable<TaskInfoForScheduler> availableTasks = null;
-                availableTasks = taskScheduler.Schedule(dao.GetWaitingTasks(slave).ToArray());
-                if (availableTasks.Any()) {
-                  var task = availableTasks.First();
-                  AssignTask(slave, task.TaskId);
-                  actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateTask, task.TaskId));
-                }
-              });
             }
           }
@@ -102,5 +105,5 @@
           }
           catch (Exception ex) {
-            LogFactory.GetLogger(this.GetType().Namespace).Log("HeartbeatManager threw an exception in ProcessHeartbeat: " + ex.ToString());
+            LogFactory.GetLogger(this.GetType().Namespace).Log(string.Format("HeartbeatManager threw an exception in ProcessHeartbeat: {0}", ex));
           }
           finally {
@@ -112,10 +115,23 @@
     }
 
-    private void AssignTask(Slave slave, Guid taskId) {
-      var task = dao.UpdateTaskState(taskId, TaskState.Transferring, slave.ResourceId, null, null);
-
-      // from now on the task has some time to send the next heartbeat (ApplicationConstants.TransferringJobHeartbeatTimeout)
-      task.LastHeartbeat = DateTime.Now;
-      dao.UpdateTask(task);
+    private void AssignTask(IPersistenceManager pm, DA.Slave slave, Guid taskId) {
+      const DA.TaskState transferring = DA.TaskState.Transferring;
+      DateTime now = DateTime.Now;
+      var taskDao = pm.TaskDao;
+      var stateLogDao = pm.StateLogDao;
+      pm.UseTransaction(() => {
+        var task = taskDao.GetById(taskId);
+        stateLogDao.Save(new DA.StateLog {
+          State = transferring,
+          DateTime = now,
+          TaskId = taskId,
+          SlaveId = slave.ResourceId,
+          UserId = null,
+          Exception = null
+        });
+        task.State = transferring;
+        task.LastHeartbeat = now;
+        pm.SubmitChanges();
+      });
     }
 
@@ -124,52 +140,59 @@
     /// Checks if all the task sent by heartbeat are supposed to be calculated by this slave
     /// </summary>
-    private IEnumerable<MessageContainer> UpdateTasks(Heartbeat heartbeat, bool IsAllowedToCalculate) {
-      List<MessageContainer> actions = new List<MessageContainer>();
-
-      if (heartbeat.JobProgress == null)
+    private IEnumerable<MessageContainer> UpdateTasks(IPersistenceManager pm, Heartbeat heartbeat, bool isAllowedToCalculate) {
+      var taskDao = pm.TaskDao;
+      var assignedResourceDao = pm.AssignedResourceDao;
+      var actions = new List<MessageContainer>();
+      if (heartbeat.JobProgress == null || !heartbeat.JobProgress.Any())
         return actions;
 
-      if (!IsAllowedToCalculate && heartbeat.JobProgress.Count != 0) {
+      if (!isAllowedToCalculate && heartbeat.JobProgress.Count != 0) {
         actions.Add(new MessageContainer(MessageContainer.MessageType.PauseAll));
       } else {
+        // 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,
+             Command = task.Command,
+             SlaveId = lastStateLog != null ? lastStateLog.SlaveId : default(Guid)
+           }).ToList()
+        );
+
         // process the jobProgresses
         foreach (var jobProgress in heartbeat.JobProgress) {
-          Tuple<Task, Guid?> taskWithLastStateLogSlaveId = null;
-          trans.UseTransaction(() => {
-            taskWithLastStateLogSlaveId = dao.GetTaskByIdAndLastStateLogSlaveId(jobProgress.Key);
-          });
-          var curTask = taskWithLastStateLogSlaveId != null ? taskWithLastStateLogSlaveId.Item1 : null;
+          var progress = jobProgress;
+          var curTask = taskInfos.SingleOrDefault(x => x.TaskId == progress.Key);
           if (curTask == null) {
-            // task does not exist in db
-            actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, jobProgress.Key));
+            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 {
-            var slaveId = taskWithLastStateLogSlaveId.Item2;
+            var slaveId = curTask.SlaveId;
             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)) {
+              LogFactory.GetLogger(this.GetType().Namespace).Log("The slave " + heartbeat.SlaveId + " is not supposed to calculate task: " + curTask.TaskId);
+            } else if (!assignedResourceDao.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 {
-              // save task execution time
-              curTask.ExecutionTimeMs = jobProgress.Value.TotalMilliseconds;
-              curTask.LastHeartbeat = DateTime.Now;
-
+              // update task execution time
+              pm.UseTransaction(() => {
+                taskDao.UpdateExecutionTime(curTask.TaskId, progress.Value.TotalMilliseconds);
+              });
               switch (curTask.Command) {
-                case Command.Stop:
+                case DA.Command.Stop:
                   actions.Add(new MessageContainer(MessageContainer.MessageType.StopTask, curTask.TaskId));
                   break;
-                case Command.Pause:
+                case DA.Command.Pause:
                   actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curTask.TaskId));
                   break;
-                case Command.Abort:
+                case DA.Command.Abort:
                   actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curTask.TaskId));
                   break;
               }
-              trans.UseTransaction(() => {
-                dao.UpdateTask(curTask);
-              });
             }
           }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/OptimizedHiveDao.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/OptimizedHiveDao.cs	(revision 12753)
+++ 	(revision )
@@ -1,298 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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;
-using System.Collections.Generic;
-using System.Data.Linq;
-using System.Linq;
-using DT = HeuristicLab.Services.Hive.DataTransfer;
-
-namespace HeuristicLab.Services.Hive.DataAccess {
-  public class OptimizedHiveDao : IOptimizedHiveDao {
-    private HiveDataContext Db { get; set; }
-
-    public OptimizedHiveDao(HiveDataContext db) {
-      Db = db;
-    }
-
-    #region Task Methods
-    public Task GetTaskById(Guid taskId) {
-      return GetTaskByIdQuery(Db, taskId).SingleOrDefault();
-    }
-
-    private static readonly Func<HiveDataContext, Guid, IQueryable<Task>> GetTaskByIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid taskId) =>
-      from t in db.Tasks
-      where t.TaskId == taskId
-      select t
-    );
-
-    public Task GetTaskByDto(DT.Task taskDto) {
-      var task = GetTaskById(taskDto.Id);
-      DT.Convert.ToEntity(taskDto, task);
-      return task;
-    }
-
-    public Tuple<Task, Guid?> GetTaskByIdAndLastStateLogSlaveId(Guid taskId) {
-      return GetTaskByIdAndLastStateLogSlaveIdQuery(Db, taskId).SingleOrDefault();
-    }
-
-    private static readonly Func<HiveDataContext, Guid, IQueryable<Tuple<Task, Guid?>>> GetTaskByIdAndLastStateLogSlaveIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid taskId) =>
-      from t in db.Tasks
-      let lastStateLog = t.StateLogs.OrderByDescending(sl => sl.DateTime).FirstOrDefault()
-      where t.TaskId == taskId
-      select new Tuple<Task, Guid?>(t, lastStateLog != null ? lastStateLog.SlaveId : null)
-    );
-
-    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 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 readonly 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.OrderBy(sl => sl.DateTime).Select(sl => ConvertStateLog(sl)).ToList(),
-          State = ConvertTaskState(task.State),
-          Command = ConvertCommand(task.Command),
-          LastTaskDataUpdate = task.JobData.LastUpdate
-        }
-    );
-
-    private static readonly Func<StateLog, DT.StateLog> ConvertStateLog = sl => DT.Convert.ToDto(sl);
-    private static readonly Func<TaskState, DT.TaskState> ConvertTaskState = ts => DT.Convert.ToDto(ts);
-    private static readonly 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) {
-      Db.StateLogs.InsertOnSubmit(new StateLog {
-        TaskId = taskId,
-        State = taskState,
-        SlaveId = slaveId,
-        UserId = userId,
-        Exception = exception,
-        DateTime = DateTime.Now
-      });
-
-      var task = GetTaskById(taskId);
-      task.State = taskState;
-
-      Db.SubmitChanges();
-
-      return task;
-    }
-
-    public Guid AddTask(Task task) {
-      Db.Tasks.InsertOnSubmit(task);
-      Db.SubmitChanges();
-      return task.TaskId;
-    }
-
-    public void AssignJobToResource(Guid taskId, IEnumerable<Guid> resourceIds) {
-      Db.AssignedResources.InsertAllOnSubmit(resourceIds.Select(resourceId => new AssignedResource { TaskId = taskId, ResourceId = resourceId }));
-      Db.SubmitChanges();
-    }
-
-    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
-
-    #region TaskData Methods
-    public TaskData GetTaskDataById(Guid id) {
-      return GetTaskDataByIdQuery(Db, id).SingleOrDefault();
-    }
-
-    private static readonly Func<HiveDataContext, Guid, IQueryable<TaskData>> GetTaskDataByIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid id) =>
-      from t in db.TaskDatas
-      where t.TaskId == id
-      select t
-    );
-
-    public TaskData GetTaskDataByDto(DT.TaskData dto) {
-      var taskData = GetTaskDataById(dto.TaskId);
-      DT.Convert.ToEntity(dto, taskData);
-      return taskData;
-    }
-
-    public void UpdateTaskData(TaskData taskData) {
-      Db.SubmitChanges();
-    }
-    #endregion
-
-    #region Plugin Methods
-    public Plugin GetPluginById(Guid pluginId) {
-      return GetPluginByIdQuery(Db, pluginId).SingleOrDefault();
-    }
-
-    private static readonly Func<HiveDataContext, Guid, IQueryable<Plugin>> GetPluginByIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid pluginId) =>
-      from p in db.Plugins
-      where p.PluginId == pluginId
-      select p
-    );
-    #endregion
-
-    #region Slave Methods
-    public Slave GetSlaveById(Guid id) {
-      return GetSlaveByIdQuery(Db, id).SingleOrDefault();
-    }
-
-    private static readonly Func<HiveDataContext, Guid, IQueryable<Slave>> GetSlaveByIdQuery = CompiledQuery.Compile((HiveDataContext db, Guid slaveId) =>
-      from s in db.Resources.OfType<Slave>()
-      where s.ResourceId == slaveId
-      select s
-    );
-
-    public void UpdateSlave(Slave slave) {
-      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.ToString()).FirstOrDefault() > 0;
-    }
-
-    public bool SlaveIsAllowedToCalculate(Guid slaveId) {
-      return Db.ExecuteQuery<int>(DowntimeQueryString, slaveId, DateTime.Now, DowntimeType.Offline.ToString()).FirstOrDefault() == 0;
-    }
-    #endregion
-
-    #region Resource Methods
-    public IEnumerable<Guid> GetAssignedResourceIds(Guid taskId) {
-      return GetAssignedResourceIdsQuery(Db, taskId);
-    }
-
-    private static readonly Func<HiveDataContext, Guid, IQueryable<Guid>> GetAssignedResourceIdsQuery = CompiledQuery.Compile((HiveDataContext db, Guid taskId) =>
-      from ar in db.AssignedResources
-      where ar.TaskId == taskId
-      select ar.ResourceId
-    );
-    #endregion
-
-
-    #region Website Methods
-    private const string GetAllResourceIdsString = @"SELECT ResourceId FROM [Resource]";
-    public IEnumerable<Guid> GetAllResourceIds() {
-      return Db.ExecuteQuery<Guid>(GetAllResourceIdsString);
-    }
-
-    private const string GetNumberOfWaitingTasksString = @"SELECT COUNT(TaskId) 
-                                                           FROM [Task] 
-                                                           WHERE TaskState LIKE 'Waiting'";
-    public int GetNumberOfWaitingTasks() {
-      return Db.ExecuteQuery<int>(GetNumberOfWaitingTasksString).Single();
-    }
-
-    private class UserTasks {
-      public Guid OwnerUserId;
-      public int Count;
-    }
-
-    private const string GetCalculatingTasksByUserString = @"SELECT Job.OwnerUserId, COUNT(Task.TaskId) as Count 
-                                                             FROM Task, Job 
-                                                             WHERE TaskState LIKE 'Calculating' AND Task.JobId = Job.JobId
-                                                             GROUP BY Job.OwnerUserId";
-
-    public Dictionary<Guid, int> GetCalculatingTasksByUser() {
-      var result = Db.ExecuteQuery<UserTasks>(GetCalculatingTasksByUserString);
-      Dictionary<Guid, int> lst = new Dictionary<Guid, int>();
-
-      foreach (var userTask in result) {
-        lst.Add(userTask.OwnerUserId, userTask.Count);
-      }
-      return lst;
-    }
-
-    private const string GetWaitingTasksByUserString = @"SELECT Job.OwnerUserId, COUNT(Task.TaskId) as Count 
-                                                         FROM Task, Job 
-                                                         WHERE TaskState LIKE 'Waiting' AND Task.JobId = Job.JobId
-                                                         GROUP BY Job.OwnerUserId";
-
-    public Dictionary<Guid, int> GetWaitingTasksByUser() {
-      var result = Db.ExecuteQuery<UserTasks>(GetWaitingTasksByUserString);
-      Dictionary<Guid, int> lst = new Dictionary<Guid, int>();
-
-      foreach (var userTask in result) {
-        lst.Add(userTask.OwnerUserId, userTask.Count);
-      }
-      return lst;
-    }
-    #endregion
-  }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/PerformanceLogger.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/PerformanceLogger.cs	(revision 12878)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/PerformanceLogger.cs	(revision 12878)
@@ -0,0 +1,47 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+using System.Diagnostics;
+using HeuristicLab.Services.Hive.DataAccess;
+
+namespace HeuristicLab.Services.Hive {
+  public class PerformanceLogger : IDisposable {
+
+    private readonly Stopwatch stopwatch;
+    private string name;
+
+    public PerformanceLogger(string name) {
+      this.name = name;
+      if (Properties.Settings.Default.ProfileServicePerformance) {
+        stopwatch = new Stopwatch();
+        stopwatch.Start();
+      }
+    }
+    public void Dispose() {
+      if (Properties.Settings.Default.ProfileServicePerformance) {
+        stopwatch.Stop();
+        LogFactory.GetLogger(this.GetType().Namespace)
+          .Log(string.Format("{0} took {1}ms", name, stopwatch.ElapsedMilliseconds));
+      }
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.Designer.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.Designer.cs	(revision 12878)
@@ -1,9 +1,9 @@
 ﻿//------------------------------------------------------------------------------
 // <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.34014
+//     Dieser Code wurde von einem Tool generiert.
+//     Laufzeitversion:4.0.30319.42000
 //
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
+//     Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+//     der Code erneut generiert wird.
 // </auto-generated>
 //------------------------------------------------------------------------------
@@ -13,5 +13,5 @@
     
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
     public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
         
@@ -86,4 +86,22 @@
             }
         }
+        
+        [global::System.Configuration.ApplicationScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ProfileServicePerformance {
+            get {
+                return ((bool)(this["ProfileServicePerformance"]));
+            }
+        }
+        
+        [global::System.Configuration.ApplicationScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("00:03:00")]
+        public global::System.TimeSpan GenerateStatisticsInterval {
+            get {
+                return ((global::System.TimeSpan)(this["GenerateStatisticsInterval"]));
+            }
+        }
     }
 }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.settings
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.settings	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.settings	(revision 12878)
@@ -24,4 +24,10 @@
       <Value Profile="(Default)">00:00:20</Value>
     </Setting>
+    <Setting Name="ProfileServicePerformance" Type="System.Boolean" Scope="Application">
+      <Value Profile="(Default)">True</Value>
+    </Setting>
+    <Setting Name="GenerateStatisticsInterval" Type="System.TimeSpan" Scope="Application">
+      <Value Profile="(Default)">00:03:00</Value>
+    </Setting>
   </Settings>
 </SettingsFile>
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/RoundRobinTaskScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/RoundRobinTaskScheduler.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/RoundRobinTaskScheduler.cs	(revision 12878)
@@ -23,10 +23,11 @@
 using System.Collections.Generic;
 using System.Linq;
-using HeuristicLab.Services.Hive.DataTransfer;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
+using DA = HeuristicLab.Services.Hive.DataAccess;
 
 namespace HeuristicLab.Services.Hive {
   public class RoundRobinTaskScheduler : ITaskScheduler {
-    private IHiveDao dao {
-      get { return ServiceLocator.Instance.HiveDao; }
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
     }
 
@@ -34,10 +35,24 @@
       if (!tasks.Any()) return Enumerable.Empty<TaskInfoForScheduler>();
 
-      var userPriorities = dao.GetUserPriorities(x => true).OrderBy(x => x.DateEnqueued).ToArray();
+      var pm = PersistenceManager;
+      var userPriorityDao = pm.UserPriorityDao;
+      var jobDao = pm.JobDao;
 
-      var jobs = new List<JobInfoForScheduler>();
-      foreach (var userPriority in userPriorities) {
-        jobs.AddRange(dao.GetJobInfoForScheduler(x => x.OwnerUserId == userPriority.Id));
-      }
+      var userPriorities = pm.UseTransaction(() => userPriorityDao.GetAll()
+        .OrderBy(x => x.DateEnqueued)
+        .ToArray()
+      );
+
+      var userIds = userPriorities.Select(x => x.UserId).ToList();
+      var jobs = pm.UseTransaction(() => {
+        return jobDao.GetAll()
+          .Where(x => userIds.Contains(x.OwnerUserId))
+          .Select(x => new {
+            Id = x.JobId,
+            DateCreated = x.DateCreated,
+            OwnerUserId = x.OwnerUserId
+          })
+          .ToList();
+      });
 
       var taskJobRelations = tasks.Join(jobs,
@@ -55,8 +70,8 @@
       for (int i = 0; i < count; i++) {
         var defaultEntry = taskJobRelations.First(); // search first task which is not included yet
-        var priorityEntries = taskJobRelations.Where(x => x.JobInfo.OwnerUserId == userPriorities[priorityIndex].Id).ToArray(); // search for tasks with desired user priority
+        var priorityEntries = taskJobRelations.Where(x => x.JobInfo.OwnerUserId == userPriorities[priorityIndex].UserId).ToArray(); // search for tasks with desired user priority
         while (!priorityEntries.Any() && priorityIndex < userPriorities.Length - 1) {
           priorityIndex++;
-          priorityEntries = taskJobRelations.Where(x => x.JobInfo.OwnerUserId == userPriorities[priorityIndex].Id).ToArray();
+          priorityEntries = taskJobRelations.Where(x => x.JobInfo.OwnerUserId == userPriorities[priorityIndex].UserId).ToArray();
         }
         if (priorityEntries.Any()) { // tasks with desired user priority found
@@ -65,5 +80,5 @@
             taskJobRelations.Remove(priorityEntry);
             scheduledTasks.Add(priorityEntry.Task);
-            UpdateUserPriority(userPriorities[priorityIndex]);
+            UpdateUserPriority(pm, userPriorities[priorityIndex]);
             priorityIndex++;
           } else { // there are other tasks with higher priorities
@@ -75,14 +90,15 @@
           scheduledTasks.Add(defaultEntry.Task);
         }
-
         if (priorityIndex >= (userPriorities.Length - 1)) priorityIndex = 0;
       }
+      return scheduledTasks;
 
-      return scheduledTasks;
     }
 
-    private void UpdateUserPriority(UserPriority up) {
-      up.DateEnqueued = DateTime.Now;
-      dao.EnqueueUserPriority(up);
+    private void UpdateUserPriority(IPersistenceManager pm, DA.UserPriority up) {
+      pm.UseTransaction(() => {
+        up.DateEnqueued = DateTime.Now;
+        pm.SubmitChanges();
+      });
     }
   }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 12878)
@@ -41,13 +41,4 @@
 
     [OperationContract]
-    IEnumerable<Task> GetTasks();
-
-    [OperationContract]
-    IEnumerable<LightweightTask> GetLightweightTasks(IEnumerable<Guid> taskIds);
-
-    [OperationContract]
-    IEnumerable<LightweightTask> GetLightweightChildTasks(Guid? parentTaskId, bool recursive, bool includeParent);
-
-    [OperationContract]
     IEnumerable<LightweightTask> GetLightweightJobTasks(Guid jobId);
 
@@ -65,10 +56,4 @@
 
     [OperationContract]
-    void DeleteTask(Guid taskId);
-
-    [OperationContract]
-    void DeleteChildTasks(Guid parentTaskId);
-
-    [OperationContract]
     Task UpdateTaskState(Guid taskId, TaskState taskState, Guid? slaveId, Guid? userId, string exception);
     #endregion
@@ -89,17 +74,7 @@
     Job GetJob(Guid id);
 
-    /// <summary>
-    /// Returns all task for the current user
-    /// </summary>
     [OperationContract]
     IEnumerable<Job> GetJobs();
 
-    /// <summary>
-    /// Returns all task in the hive (only for admins)
-    /// </summary>
-    /// <returns></returns>
-    [OperationContract]
-    IEnumerable<Job> GetAllJobs();
-
     [OperationContract]
     Guid AddJob(Job jobDto);
@@ -142,7 +117,4 @@
     [OperationContract]
     Plugin GetPlugin(Guid pluginId);
-
-    [OperationContract]
-    Plugin GetPluginByHash(byte[] hash);
 
     [OperationContract]
@@ -155,7 +127,4 @@
     [OperationContract]
     IEnumerable<PluginData> GetPluginDatas(List<Guid> pluginIds);
-
-    [OperationContract]
-    void DeletePlugin(Guid pluginId);
     #endregion
 
@@ -171,9 +140,4 @@
     #endregion
 
-    #region Resource Methods
-    [OperationContract]
-    IEnumerable<Resource> GetChildResources(Guid resourceId);
-    #endregion
-
     #region Slave Methods
     [OperationContract]
@@ -187,7 +151,4 @@
 
     [OperationContract]
-    SlaveGroup GetSlaveGroup(Guid slaveGroupId);
-
-    [OperationContract]
     IEnumerable<Slave> GetSlaves();
 
@@ -217,7 +178,4 @@
 
     [OperationContract]
-    IEnumerable<Task> GetTasksByResourceId(Guid resourceId);
-
-    [OperationContract]
     void TriggerEventManager(bool force);
 
@@ -234,5 +192,5 @@
 
     [OperationContract]
-    void UpdateDowntime(Downtime downtime);
+    void UpdateDowntime(Downtime downtimeDto);
 
     [OperationContract]
@@ -251,11 +209,4 @@
     [OperationContract]
     IEnumerable<UserPriority> GetUserPriorities();
-    #endregion
-
-    #region Statistics Methods
-    [OperationContract]
-    IEnumerable<Statistics> GetStatistics();
-    [OperationContract]
-    IEnumerable<Statistics> GetStatisticsForTimePeriod(DateTime from, DateTime to);
     #endregion
   }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceLocator.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceLocator.cs	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceLocator.cs	(revision 12878)
@@ -21,7 +21,9 @@
 
 using HeuristicLab.Services.Hive.DataAccess;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
+using HeuristicLab.Services.Hive.DataAccess.Manager;
+using HeuristicLab.Services.Hive.Manager;
 
 namespace HeuristicLab.Services.Hive {
-
   public class ServiceLocator : IServiceLocator {
     private static IServiceLocator instance;
@@ -34,18 +36,10 @@
     }
 
-    private IHiveDao hiveDao;
-    public IHiveDao HiveDao {
-      get {
-        if (hiveDao == null) hiveDao = new HiveDao();
-        return hiveDao;
-      }
-    }
-
-    public IOptimizedHiveDao OptimizedHiveDao {
+    public IPersistenceManager PersistenceManager {
       get {
         var dataContext = HiveOperationContext.Current != null
                             ? HiveOperationContext.Current.DataContext
                             : new HiveDataContext(Settings.Default.HeuristicLab_Hive_LinqConnectionString);
-        return new OptimizedHiveDao(dataContext);
+        return new PersistenceManager(dataContext);
       }
     }
@@ -75,10 +69,7 @@
     }
 
-    private ITransactionManager transactionManager;
-    public ITransactionManager TransactionManager {
-      get {
-        if (transactionManager == null) transactionManager = new TransactionManager();
-        return transactionManager;
-      }
+    private IStatisticsGenerator statisticsGenerator;
+    public IStatisticsGenerator StatisticsGenerator {
+      get { return statisticsGenerator ?? (statisticsGenerator = new HiveStatisticsGenerator()); }
     }
 
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Settings.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Settings.cs	(revision 12753)
+++ 	(revision )
@@ -1,49 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2015 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
-
-namespace HeuristicLab.Services.Hive.Properties {
-    
-    
-    // This class allows you to handle specific events on the settings class:
-    //  The SettingChanging event is raised before a setting's value is changed.
-    //  The PropertyChanged event is raised after a setting's value is changed.
-    //  The SettingsLoaded event is raised after the setting values are loaded.
-    //  The SettingsSaving event is raised before the setting values are saved.
-    public sealed partial class Settings {
-        
-        public Settings() {
-            // // To add event handlers for saving and changing settings, uncomment the lines below:
-            //
-            // this.SettingChanging += this.SettingChangingEventHandler;
-            //
-            // this.SettingsSaving += this.SettingsSavingEventHandler;
-            //
-        }
-        
-        private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
-            // Add code to handle the SettingChangingEvent event here.
-        }
-        
-        private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
-            // Add code to handle the SettingsSaving event here.
-        }
-    }
-}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/app.config
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/app.config	(revision 12753)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/app.config	(revision 12878)
@@ -29,5 +29,12 @@
                 <value>00:00:20</value>
             </setting>
+            <setting name="ProfileServicePerformance" serializeAs="String">
+                <value>True</value>
+            </setting>
+            <setting name="GenerateStatisticsInterval" serializeAs="String">
+                <value>00:03:00</value>
+            </setting>
         </HeuristicLab.Services.Hive.Properties.Settings>
     </applicationSettings>
-<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup>
+</configuration>
