Index: trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml	(revision 9123)
@@ -42,5 +42,5 @@
       <Association Name="Resource_Downtime" Member="Downtimes" Storage="_UptimeCalendars" ThisKey="ResourceId" OtherKey="ResourceId" Type="Downtime" />
       <Association Name="Resource_StateLog" Member="StateLogs" ThisKey="ResourceId" OtherKey="SlaveId" Type="StateLog" />
-      <Association Name="Resource_SlavePermission" Member="ResourcePermissions" ThisKey="ResourceId" OtherKey="ResourceId" Type="ResourcePermission" />
+      <Association Name="Resource_ResourcePermission" Member="ResourcePermissions" ThisKey="ResourceId" OtherKey="ResourceId" Type="ResourcePermission" />
       <Association Name="Resource_Resource" Member="ParentResource" ThisKey="ParentResourceId" OtherKey="ResourceId" Type="Resource" IsForeignKey="true" />
       <Type Name="Slave" InheritanceCode="Slave" IsInheritanceDefault="true">
@@ -201,5 +201,11 @@
       <Column Name="GrantedUserId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
       <Column Name="GrantedByUserId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" CanBeNull="false" />
-      <Association Name="Resource_SlavePermission" Member="Resource" ThisKey="ResourceId" OtherKey="ResourceId" Type="Resource" IsForeignKey="true" />
+      <Association Name="Resource_ResourcePermission" Member="Resource" ThisKey="ResourceId" OtherKey="ResourceId" Type="Resource" IsForeignKey="true" />
+    </Type>
+  </Table>
+  <Table Name="" Member="UserPriorities">
+    <Type Name="UserPriority">
+      <Column Name="UserId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
+      <Column Name="DateEnqueued" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="false" />
     </Type>
   </Table>
Index: trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout	(revision 9123)
@@ -33,8 +33,8 @@
       </nestedChildShapes>
     </classShape>
-    <classShape Id="8d5712f7-7a1a-4a89-bd4d-fd60200d3306" absoluteBounds="13.5, 2.5, 2, 2.1554996744791666">
+    <classShape Id="8d5712f7-7a1a-4a89-bd4d-fd60200d3306" absoluteBounds="13.5, 2.5, 2, 2.3478011067708326">
       <DataClassMoniker Name="/HiveDataContext/Downtime" />
       <nestedChildShapes>
-        <elementListCompartment Id="7d8f121b-35bb-4753-a25f-3fac1562e68e" absoluteBounds="13.515, 2.9600000000000009, 1.9700000000000002, 1.5954996744791665" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
+        <elementListCompartment Id="7d8f121b-35bb-4753-a25f-3fac1562e68e" absoluteBounds="13.515, 2.9600000000000009, 1.9700000000000002, 1.7878011067708333" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
       </nestedChildShapes>
     </classShape>
@@ -57,5 +57,5 @@
       </nestedChildShapes>
     </classShape>
-    <inheritanceConnector edgePoints="[(11.25 : 1.98159912109375); (10.875 : 1.98159912109375)]" fixedFrom="Algorithm" fixedTo="Algorithm" TargetRelationshipDomainClassId="7a7fe09e-e9ef-4b01-9ff3-bde95e827b62">
+    <inheritanceConnector edgePoints="[(11.25 : 1.98159912109375); (10.875 : 1.98159912109375)]" fixedFrom="NotFixed" fixedTo="NotFixed" TargetRelationshipDomainClassId="7a7fe09e-e9ef-4b01-9ff3-bde95e827b62">
       <nodes>
         <classShapeMoniker Id="706a4581-6daf-4e71-ae2a-87d50b27a051" />
@@ -63,5 +63,5 @@
       </nodes>
     </inheritanceConnector>
-    <inheritanceConnector edgePoints="[(13.25 : 1.40469482421875); (13.5 : 1.40469482421875)]" fixedFrom="Algorithm" fixedTo="Algorithm" TargetRelationshipDomainClassId="7a7fe09e-e9ef-4b01-9ff3-bde95e827b62">
+    <inheritanceConnector edgePoints="[(13.25 : 1.40469482421875); (13.5 : 1.40469482421875)]" fixedFrom="NotFixed" fixedTo="NotFixed" TargetRelationshipDomainClassId="7a7fe09e-e9ef-4b01-9ff3-bde95e827b62">
       <nodes>
         <classShapeMoniker Id="706a4581-6daf-4e71-ae2a-87d50b27a051" />
@@ -121,5 +121,5 @@
       </nestedChildShapes>
     </classShape>
-    <associationConnector edgePoints="[(11.25 : 1.45954756054688); (10.9375 : 1.45954756054688); (10.9375 : 0.6875); (2.75 : 0.6875); (2.75 : 1)]" fixedFrom="Algorithm" fixedTo="Algorithm">
+    <associationConnector edgePoints="[(11.25 : 1.98159912109375); (10.9375 : 1.98159912109375); (10.9375 : 0.6875); (2.75 : 0.6875); (2.75 : 1)]" fixedFrom="NotFixed" fixedTo="NotFixed">
       <AssociationMoniker Name="/HiveDataContext/Resource/Resource_StateLog" />
       <nodes>
@@ -172,5 +172,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(13.25 : 2.73159912109375); (13.5 : 2.73159912109375)]" fixedFrom="Algorithm" fixedTo="Algorithm">
+    <associationConnector edgePoints="[(13.25 : 2.73159912109375); (13.5 : 2.73159912109375)]" fixedFrom="NotFixed" fixedTo="NotFixed">
       <AssociationMoniker Name="/HiveDataContext/Resource/Resource_Downtime" />
       <nodes>
@@ -234,6 +234,6 @@
       </nestedChildShapes>
     </classShape>
-    <associationConnector edgePoints="[(12.5942481820367 : 2.9631982421875); (12.5942481820367 : 3.875)]" fixedFrom="Algorithm" fixedTo="Algorithm">
-      <AssociationMoniker Name="/HiveDataContext/Resource/Resource_SlavePermission" />
+    <associationConnector edgePoints="[(12.5942481820367 : 2.9631982421875); (12.5942481820367 : 3.875)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+      <AssociationMoniker Name="/HiveDataContext/Resource/Resource_ResourcePermission" />
       <nodes>
         <classShapeMoniker Id="706a4581-6daf-4e71-ae2a-87d50b27a051" />
@@ -241,4 +241,10 @@
       </nodes>
     </associationConnector>
+    <classShape Id="f9e8867f-fd15-4a72-8ca4-4f02cd3f141f" absoluteBounds="4.125, 5.5, 2, 1.1939925130208327">
+      <DataClassMoniker Name="/HiveDataContext/UserPriority" />
+      <nestedChildShapes>
+        <elementListCompartment Id="ee41f516-7d9c-4a1d-a1b8-bbe00a6ffea8" absoluteBounds="4.14, 5.96, 1.9700000000000002, 0.63399251302083326" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
+      </nestedChildShapes>
+    </classShape>
   </nestedChildShapes>
 </ordesignerObjectsDiagram>
Index: trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs	(revision 9123)
@@ -82,4 +82,7 @@
     partial void UpdateResourcePermission(ResourcePermission instance);
     partial void DeleteResourcePermission(ResourcePermission instance);
+    partial void InsertUserPriority(UserPriority instance);
+    partial void UpdateUserPriority(UserPriority instance);
+    partial void DeleteUserPriority(UserPriority instance);
     #endregion
 		
@@ -247,4 +250,12 @@
 			{
 				return this.GetTable<ResourcePermission>();
+			}
+		}
+		
+		public System.Data.Linq.Table<UserPriority> UserPriorities
+		{
+			get
+			{
+				return this.GetTable<UserPriority>();
 			}
 		}
@@ -1087,5 +1098,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Resource_SlavePermission", Storage="_ResourcePermissions", ThisKey="ResourceId", OtherKey="ResourceId")]
+		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Resource_ResourcePermission", Storage="_ResourcePermissions", ThisKey="ResourceId", OtherKey="ResourceId")]
 		public EntitySet<ResourcePermission> ResourcePermissions
 		{
@@ -4383,5 +4394,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Resource_SlavePermission", Storage="_Resource", ThisKey="ResourceId", OtherKey="ResourceId", IsForeignKey=true)]
+		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Resource_ResourcePermission", Storage="_Resource", ThisKey="ResourceId", OtherKey="ResourceId", IsForeignKey=true)]
 		public Resource Resource
 		{
@@ -4437,4 +4448,90 @@
 		}
 	}
+	
+	[global::System.Data.Linq.Mapping.TableAttribute(Name="")]
+	public partial class UserPriority : INotifyPropertyChanging, INotifyPropertyChanged
+	{
+		
+		private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
+		
+		private System.Guid _UserId;
+		
+		private System.DateTime _DateEnqueued;
+		
+    #region Extensibility Method Definitions
+    partial void OnLoaded();
+    partial void OnValidate(System.Data.Linq.ChangeAction action);
+    partial void OnCreated();
+    partial void OnUserIdChanging(System.Guid value);
+    partial void OnUserIdChanged();
+    partial void OnDateEnqueuedChanging(System.DateTime value);
+    partial void OnDateEnqueuedChanged();
+    #endregion
+		
+		public UserPriority()
+		{
+			OnCreated();
+		}
+		
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_UserId", DbType="UniqueIdentifier NOT NULL", IsPrimaryKey=true)]
+		public System.Guid UserId
+		{
+			get
+			{
+				return this._UserId;
+			}
+			set
+			{
+				if ((this._UserId != value))
+				{
+					this.OnUserIdChanging(value);
+					this.SendPropertyChanging();
+					this._UserId = value;
+					this.SendPropertyChanged("UserId");
+					this.OnUserIdChanged();
+				}
+			}
+		}
+		
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_DateEnqueued", DbType="DateTime NOT NULL")]
+		public System.DateTime DateEnqueued
+		{
+			get
+			{
+				return this._DateEnqueued;
+			}
+			set
+			{
+				if ((this._DateEnqueued != value))
+				{
+					this.OnDateEnqueuedChanging(value);
+					this.SendPropertyChanging();
+					this._DateEnqueued = value;
+					this.SendPropertyChanged("DateEnqueued");
+					this.OnDateEnqueuedChanged();
+				}
+			}
+		}
+		
+		public event PropertyChangingEventHandler PropertyChanging;
+		
+		public event PropertyChangedEventHandler PropertyChanged;
+		
+		protected virtual void SendPropertyChanging()
+		{
+			if ((this.PropertyChanging != null))
+			{
+				this.PropertyChanging(this, emptyChangingEventArgs);
+			}
+		}
+		
+		protected virtual void SendPropertyChanged(String propertyName)
+		{
+			if ((this.PropertyChanged != null))
+			{
+				this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+			}
+		}
+	}
 }
 #pragma warning restore 1591
Index: trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 9123)
@@ -122,4 +122,9 @@
   CONSTRAINT [PK_Lifecycle] PRIMARY KEY ([LifecycleId])
   )
+CREATE TABLE [UserPriority](
+  [UserId] UniqueIdentifier NOT NULL,
+  [DateEnqueued] DateTime NOT NULL,
+  CONSTRAINT [PK_UserPriority] PRIMARY KEY ([UserId])
+  )
 CREATE TABLE [DeletedJobStatistics](
   [UserId] UniqueIdentifier NOT NULL,
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Convert.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Convert.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Convert.cs	(revision 9123)
@@ -527,4 +527,22 @@
     }
     #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/DataTransfer/UserPriority.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/UserPriority.cs	(revision 9123)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/UserPriority.cs	(revision 9123)
@@ -0,0 +1,32 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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 UserPriority : HiveItem {
+    [DataMember]
+    public DateTime DateEnqueued { 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 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/HeuristicLab.Services.Hive-3.3.csproj	(revision 9123)
@@ -114,4 +114,5 @@
     <Compile Include="Convert.cs" />
     <Compile Include="DataTransfer\Command.cs" />
+    <Compile Include="DataTransfer\UserPriority.cs" />
     <Compile Include="DataTransfer\ResourcePermission.cs" />
     <Compile Include="DataTransfer\Downtime.cs" />
@@ -139,4 +140,8 @@
     <Compile Include="HiveJanitor.cs" />
     <Compile Include="Interfaces\IHiveDao.cs" />
+    <Compile Include="Interfaces\ITaskScheduler.cs" />
+    <Compile Include="Scheduler\TaskInfoForScheduler.cs" />
+    <Compile Include="Scheduler\JobInfoForScheduler.cs" />
+    <Compile Include="Scheduler\RoundRobinTaskScheduler.cs" />
     <Compile Include="Settings.cs" />
     <None Include="app.config" />
@@ -196,5 +201,5 @@
   </PropertyGroup>
   <PropertyGroup>
-   <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
+    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
 set ProjectDir=$(ProjectDir)
 set SolutionDir=$(SolutionDir)
@@ -202,5 +207,5 @@
 
 call PreBuildEvent.cmd</PreBuildEvent>
-<PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
+    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
 export ProjectDir=$(ProjectDir)
 export SolutionDir=$(SolutionDir)
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 9123)
@@ -84,5 +84,5 @@
     }
 
-    public void UpdateTask(DT.Task dto) {
+    public void UpdateTaskAndPlugins(DT.Task dto) {
       using (var db = CreateContext()) {
         var entity = db.Tasks.FirstOrDefault(x => x.TaskId == dto.Id);
@@ -94,4 +94,13 @@
           }
         }
+        db.SubmitChanges();
+      }
+    }
+
+    public void UpdateTask(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);
         db.SubmitChanges();
       }
@@ -134,5 +143,5 @@
     }
 
-    public IEnumerable<DT.Task> GetWaitingTasks(DT.Slave slave, int count) {
+    public IEnumerable<TaskInfoForScheduler> GetWaitingTasks(DT.Slave slave) {
       using (var db = CreateContext()) {
         var resourceIds = GetParentResources(slave.Id).Select(r => r.Id);
@@ -147,7 +156,6 @@
                        && ar.Task.CoresNeeded <= slave.FreeCores
                        && ar.Task.MemoryNeeded <= slave.FreeMemory
-                    orderby ar.Task.Priority descending, db.Random() // take random task to avoid the race condition that occurs when this method is called concurrently (the same task would be returned)
-                    select DT.Convert.ToDto(ar.Task);
-        var waitingTasks = (count == 0 ? query : query.Take(count)).ToArray();
+                    select new TaskInfoForScheduler() { TaskId = ar.Task.TaskId, JobId = ar.Task.JobId, Priority = ar.Task.Priority };
+        var waitingTasks = query.ToArray();
         return waitingTasks;
       }
@@ -277,8 +285,16 @@
     }
 
+    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;
@@ -923,4 +939,21 @@
     #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) {
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 9123)
@@ -142,5 +142,5 @@
       author.AuthorizeForTask(taskDto.Id, Permission.Full);
       trans.UseTransaction(() => {
-        dao.UpdateTask(taskDto);
+        dao.UpdateTaskAndPlugins(taskDto);
       });
     }
@@ -152,5 +152,5 @@
       //trans.UseTransaction(() => { // cneumuel: try without transaction
       taskData.LastUpdate = DateTime.Now;
-      dao.UpdateTask(task);
+      dao.UpdateTaskAndPlugins(task);
       dao.UpdateTaskData(taskData);
       //}, false, true);
@@ -194,5 +194,5 @@
         }
 
-        dao.UpdateTask(task);
+        dao.UpdateTaskAndPlugins(task);
         return task;
       });
@@ -499,4 +499,10 @@
     #endregion
 
+    #region Resource Methods
+    public IEnumerable<Resource> GetChildResources(Guid resourceId) {
+      return dao.GetChildResources(resourceId);
+    }
+    #endregion
+
     #region Slave Methods
     public int GetNewHeartbeatInterval(Guid slaveId) {
@@ -671,4 +677,10 @@
     #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) {
@@ -687,4 +699,13 @@
     }
     #endregion
+
+    #region Statistics Methods
+    public IEnumerable<Statistics> GetStatistics() {
+      return dao.GetStatistics(x => true);
+    }
+    public IEnumerable<Statistics> GetStatisticsForTimePeriod(DateTime from, DateTime to) {
+      return dao.GetStatistics(x => x.Timestamp >= from && x.Timestamp <= to);
+    }
+    #endregion
   }
 }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs	(revision 9123)
@@ -33,7 +33,8 @@
     IEnumerable<DT.LightweightTask> GetLightweightTasks(Expression<Func<Task, bool>> predicate);
     Guid AddTask(DT.Task dto);
+    void UpdateTaskAndPlugins(DT.Task dto);
     void UpdateTask(DT.Task dto);
     void DeleteTask(Guid id);
-    IEnumerable<DT.Task> GetWaitingTasks(DT.Slave slave, int count);
+    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);
@@ -59,4 +60,5 @@
     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);
@@ -156,4 +158,9 @@
     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/IServiceLocator.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IServiceLocator.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IServiceLocator.cs	(revision 9123)
@@ -31,4 +31,5 @@
     Access.IUserManager UserManager { get; }
     HeartbeatManager HeartbeatManager { get; }
+    ITaskScheduler TaskScheduler { get; }
   }
 }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/ITaskScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/ITaskScheduler.cs	(revision 9123)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Interfaces/ITaskScheduler.cs	(revision 9123)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.Collections.Generic;
+using HeuristicLab.Services.Hive.DataTransfer;
+
+namespace HeuristicLab.Services.Hive {
+  public interface ITaskScheduler {
+    IEnumerable<TaskInfoForScheduler> Schedule(IEnumerable<TaskInfoForScheduler> tasks, int count = 1);
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 9123)
@@ -23,4 +23,5 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using HeuristicLab.Services.Hive.DataTransfer;
 using DA = HeuristicLab.Services.Hive.DataAccess;
@@ -28,9 +29,11 @@
 namespace HeuristicLab.Services.Hive {
   public class HeartbeatManager {
+    private const string MutexName = "HiveTaskSchedulingMutex";
+
     private IHiveDao dao {
       get { return ServiceLocator.Instance.HiveDao; }
     }
-    private IAuthorizationManager auth {
-      get { return ServiceLocator.Instance.AuthorizationManager; }
+    private ITaskScheduler taskScheduler {
+      get { return ServiceLocator.Instance.TaskScheduler; }
     }
 
@@ -66,9 +69,27 @@
         // assign new task
         if (heartbeat.AssignJob && slave.IsAllowedToCalculate && heartbeat.FreeCores > 0) {
-          var availableJobs = dao.GetWaitingTasks(slave, 1);
-          if (availableJobs.Count() > 0) {
-            var job = availableJobs.First();
-            if (AssignJob(slave, job))
-              actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateTask, job.Id));
+          bool mutexAquired = false;
+          var mutex = new Mutex(false, MutexName);
+          try {
+            mutexAquired = mutex.WaitOne(Properties.Settings.Default.SchedulingPatience);
+            if (!mutexAquired)
+              DA.LogFactory.GetLogger(this.GetType().Namespace).Log("HeartbeatManager: The mutex used for scheduling could not be aquired.");
+            else {
+              var availableTasks = taskScheduler.Schedule(dao.GetWaitingTasks(slave));
+              if (availableTasks.Any()) {
+                var task = availableTasks.First();
+                AssignJob(slave, task.TaskId);
+                actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateTask, task.TaskId));
+              }
+            }
+          }
+          catch (AbandonedMutexException) {
+            DA.LogFactory.GetLogger(this.GetType().Namespace).Log("HeartbeatManager: The mutex used for scheduling has been abandoned.");
+          }
+          catch (Exception ex) {
+            DA.LogFactory.GetLogger(this.GetType().Namespace).Log("HeartbeatManager threw an exception in ProcessHeartbeat: " + ex.ToString());
+          }
+          finally {
+            if (mutexAquired) mutex.ReleaseMutex();
           }
         }
@@ -77,15 +98,10 @@
     }
 
-    // returns true if assignment was successful
-    private bool AssignJob(Slave slave, Task task) {
-      // load task again and check if it is still available (this is an attempt to reduce the race condition which causes multiple heartbeats to get the same task assigned)
-      if (dao.GetTask(task.Id).State != TaskState.Waiting) return false;
-
-      task = dao.UpdateTaskState(task.Id, DataAccess.TaskState.Transferring, slave.Id, null, null);
+    private void AssignJob(Slave slave, Guid taskId) {
+      var task = dao.UpdateTaskState(taskId, DataAccess.TaskState.Transferring, slave.Id, null, null);
 
       // from now on the task has some time to send the next heartbeat (ApplicationConstants.TransferringJobHeartbeatTimeout)
       task.LastHeartbeat = DateTime.Now;
       dao.UpdateTask(task);
-      return true;
     }
 
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.Designer.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.Designer.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.Designer.cs	(revision 9123)
@@ -2,5 +2,5 @@
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:4.0.30319.269
+//     Runtime Version:4.0.30319.17929
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
@@ -13,5 +13,5 @@
     
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
     public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
         
@@ -77,4 +77,13 @@
             }
         }
+        
+        [global::System.Configuration.ApplicationScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("00:00:20")]
+        public global::System.TimeSpan SchedulingPatience {
+            get {
+                return ((global::System.TimeSpan)(this["SchedulingPatience"]));
+            }
+        }
     }
 }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.settings
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.settings	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Properties/Settings.settings	(revision 9123)
@@ -21,4 +21,7 @@
       <Value Profile="(Default)">3.00:00:00</Value>
     </Setting>
+    <Setting Name="SchedulingPatience" Type="System.TimeSpan" Scope="Application">
+      <Value Profile="(Default)">00:00:20</Value>
+    </Setting>
   </Settings>
 </SettingsFile>
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/JobInfoForScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/JobInfoForScheduler.cs	(revision 9123)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/JobInfoForScheduler.cs	(revision 9123)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Services.Hive {
+  public class JobInfoForScheduler {
+    public Guid Id;
+    public Guid OwnerUserId;
+    public DateTime DateCreated;
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/RoundRobinTaskScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/RoundRobinTaskScheduler.cs	(revision 9123)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/RoundRobinTaskScheduler.cs	(revision 9123)
@@ -0,0 +1,89 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 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.DataTransfer;
+
+namespace HeuristicLab.Services.Hive {
+  public class RoundRobinTaskScheduler : ITaskScheduler {
+    private IHiveDao dao {
+      get { return ServiceLocator.Instance.HiveDao; }
+    }
+
+    public IEnumerable<TaskInfoForScheduler> Schedule(IEnumerable<TaskInfoForScheduler> tasks, int count = 1) {
+      if (!tasks.Any()) return Enumerable.Empty<TaskInfoForScheduler>();
+
+      var userPriorities = dao.GetUserPriorities(x => true).OrderBy(x => x.DateEnqueued).ToArray();
+
+      var jobs = new List<JobInfoForScheduler>();
+      foreach (var userPriority in userPriorities) {
+        jobs.AddRange(dao.GetJobInfoForScheduler(x => x.OwnerUserId == userPriority.Id));
+      }
+
+      var taskJobRelations = tasks.Join(jobs,
+        task => task.JobId,
+        job => job.Id,
+        (task, job) => new { Task = task, JobInfo = job })
+        .OrderByDescending(x => x.Task.Priority)
+        .ToList();
+
+      var scheduledTasks = new List<TaskInfoForScheduler>();
+      int priorityIndex = 0;
+
+      if (count == 0 || count > taskJobRelations.Count) count = taskJobRelations.Count;
+
+      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
+        while (!priorityEntries.Any() && priorityIndex < userPriorities.Length - 1) {
+          priorityIndex++;
+          priorityEntries = taskJobRelations.Where(x => x.JobInfo.OwnerUserId == userPriorities[priorityIndex].Id).ToArray();
+        }
+        if (priorityEntries.Any()) { // tasks with desired user priority found
+          var priorityEntry = priorityEntries.OrderByDescending(x => x.Task.Priority).ThenBy(x => x.JobInfo.DateCreated).First();
+          if (defaultEntry.Task.Priority <= priorityEntry.Task.Priority) {
+            taskJobRelations.Remove(priorityEntry);
+            scheduledTasks.Add(priorityEntry.Task);
+            UpdateUserPriority(userPriorities[priorityIndex]);
+            priorityIndex++;
+          } else { // there are other tasks with higher priorities
+            taskJobRelations.Remove(defaultEntry);
+            scheduledTasks.Add(defaultEntry.Task);
+          }
+        } else {
+          taskJobRelations.Remove(defaultEntry);
+          scheduledTasks.Add(defaultEntry.Task);
+        }
+
+        if (priorityIndex >= (userPriorities.Length - 1)) priorityIndex = 0;
+      }
+
+      return scheduledTasks;
+    }
+
+    private void UpdateUserPriority(UserPriority up) {
+      up.DateEnqueued = DateTime.Now;
+      dao.EnqueueUserPriority(up);
+    }
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/TaskInfoForScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/TaskInfoForScheduler.cs	(revision 9123)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/Scheduler/TaskInfoForScheduler.cs	(revision 9123)
@@ -0,0 +1,30 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Services.Hive {
+  public class TaskInfoForScheduler {
+    public Guid JobId;
+    public Guid TaskId;
+    public int Priority;
+  }
+}
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 9123)
@@ -168,4 +168,9 @@
     #endregion
 
+    #region Resource Methods
+    [OperationContract]
+    IEnumerable<Resource> GetChildResources(Guid resourceId);
+    #endregion
+
     #region Slave Methods
     [OperationContract]
@@ -238,4 +243,16 @@
     [OperationContract]
     Guid GetUserIdByUsername(string username);
+    #endregion
+
+    #region UserPriorities Methods
+    [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 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/ServiceLocator.cs	(revision 9123)
@@ -89,4 +89,12 @@
       }
     }
+
+    private ITaskScheduler taskScheduler;
+    public ITaskScheduler TaskScheduler {
+      get {
+        if (taskScheduler == null) taskScheduler = new RoundRobinTaskScheduler();
+        return taskScheduler;
+      }
+    }
   }
 }
Index: trunk/sources/HeuristicLab.Services.Hive/3.3/app.config
===================================================================
--- trunk/sources/HeuristicLab.Services.Hive/3.3/app.config	(revision 9120)
+++ trunk/sources/HeuristicLab.Services.Hive/3.3/app.config	(revision 9123)
@@ -26,4 +26,7 @@
                 <value>3.00:00:00</value>
             </setting>
+            <setting name="SchedulingPatience" serializeAs="String">
+                <value>00:00:20</value>
+            </setting>
         </HeuristicLab.Services.Hive.Properties.Settings>
     </applicationSettings>
