Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HiveService.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HiveService.cs	(revision 5511)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HiveService.cs	(revision 5526)
@@ -31,6 +31,6 @@
 
     #region Job Methods
-    //[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
-    //[PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Guid AddJob(Job job, JobData jobData, IEnumerable<Guid> resourceIds) {
       using (trans.OpenTransaction()) {
@@ -51,4 +51,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Guid AddChildJob(Guid parentJobId, Job job, JobData jobData) {
       using (trans.OpenTransaction()) {
@@ -58,24 +60,39 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public Job GetJob(Guid jobId) {
       return dao.GetJob(jobId);
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public IEnumerable<Job> GetJobs() {
       return dao.GetJobs(x => true);
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public IEnumerable<LightweightJob> GetLightweightJobs(IEnumerable<Guid> jobIds) {
       return dao.GetJobs(x => jobIds.Contains(x.JobId)).Select(x => new LightweightJob(x)).ToArray();
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public IEnumerable<LightweightJob> GetLightweightChildJobs(Guid? parentJobId, bool recursive, bool includeParent) {
       return GetChildJobs(parentJobId, recursive, includeParent).Select(x => new LightweightJob(x)).ToArray();
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public JobData GetJobData(Guid jobId) {
       return dao.GetJobData(jobId);
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void UpdateJob(Job job) {
       using (trans.OpenTransaction()) {
@@ -84,4 +101,7 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void UpdateJobData(Job job, JobData jobData) {
       using (trans.OpenTransaction()) {
@@ -92,4 +112,7 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void DeleteJob(Guid jobId) {
       using (trans.OpenTransaction()) {
@@ -98,4 +121,7 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void DeleteChildJobs(Guid parentJobId) {
       using (trans.OpenTransaction()) {
@@ -111,4 +137,7 @@
 
     #region Job Control Methods
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void StopJob(Guid jobId) {
       using (trans.OpenTransaction()) {
@@ -116,4 +145,8 @@
       }
     }
+
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void PauseJob(Guid jobId) {
       using (trans.OpenTransaction()) {
@@ -124,5 +157,6 @@
 
     #region HiveExperiment Methods
-
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public HiveExperiment GetHiveExperiment(Guid id) {
       return dao.GetHiveExperiments(x =>
@@ -132,8 +166,12 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public IEnumerable<HiveExperiment> GetHiveExperiments() {
       return dao.GetHiveExperiments(x => x.OwnerUserId == auth.UserId || x.HiveExperimentPermissions.Count(hep => hep.Permission != Permission.NotAllowed && hep.GrantedUserId == auth.UserId) > 0);
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Guid AddHiveExperiment(HiveExperiment hiveExperimentDto) {
       using (trans.OpenTransaction()) {
@@ -144,4 +182,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void UpdateHiveExperiment(HiveExperiment hiveExperimentDto) {
       using (trans.OpenTransaction()) {
@@ -150,4 +190,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void DeleteHiveExperiment(Guid hiveExperimentId) {
       using (trans.OpenTransaction()) {
@@ -159,4 +201,5 @@
 
     #region Login Methods
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void Hello(Slave slaveInfo) {
       using (trans.OpenTransaction()) {
@@ -171,4 +214,5 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public void GoodBye(Guid slaveId) {
       using (trans.OpenTransaction()) {
@@ -183,4 +227,5 @@
 
     #region Heartbeat Methods
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public List<MessageContainer> Heartbeat(Heartbeat heartbeat) {
       using (trans.OpenTransaction()) {
@@ -191,4 +236,6 @@
 
     #region Plugin Methods
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Guid AddPlugin(Plugin plugin, List<PluginData> pluginDatas) {
       using (trans.OpenTransaction()) {
@@ -203,8 +250,15 @@
       }
     }
+
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public IEnumerable<Plugin> GetPlugins() {
       return dao.GetPlugins(x => true);
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Slave)]
     public IEnumerable<PluginData> GetPluginDatas(List<Guid> pluginIds) {
       List<PluginData> pluginDatas = new List<PluginData>();
@@ -226,4 +280,6 @@
 
     #region Slave Methods
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Guid AddSlave(Slave slave) {
       using (trans.OpenTransaction()) {
@@ -232,4 +288,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Guid AddSlaveGroup(SlaveGroup slaveGroup) {
       using (trans.OpenTransaction()) {
@@ -238,4 +296,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Slave GetSlave(Guid slaveId) {
       return dao.GetSlave(slaveId);
@@ -246,12 +306,18 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public IEnumerable<Slave> GetSlaves() {
       return dao.GetSlaves(x => true);
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public IEnumerable<SlaveGroup> GetSlaveGroups() {
       return dao.GetSlaveGroups(x => true);
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void UpdateSlave(Slave slave) {
       using (trans.OpenTransaction()) {
@@ -260,4 +326,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void UpdateSlaveGroup(SlaveGroup slaveGroup) {
       using (trans.OpenTransaction()) {
@@ -266,4 +334,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void DeleteSlave(Guid slaveId) {
       using (trans.OpenTransaction()) {
@@ -272,4 +342,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void DeleteSlaveGroup(Guid slaveGroupId) {
       using (trans.OpenTransaction()) {
@@ -278,4 +350,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void AddResourceToGroup(Guid slaveGroupId, Guid resourceId) {
       using (trans.OpenTransaction()) {
@@ -286,4 +360,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public void RemoveResourceFromGroup(Guid slaveGroupId, Guid resourceId) {
       using (trans.OpenTransaction()) {
@@ -294,4 +370,6 @@
     }
 
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Administrator)]
+    // [PrincipalPermission(SecurityAction.Demand, Role = HiveRoles.Client)]
     public Guid GetResourceId(string resourceName) {
       using (trans.OpenTransaction()) {
@@ -325,6 +403,4 @@
 
     #endregion
-
-
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs	(revision 5511)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/LifecycleManager.cs	(revision 5526)
@@ -36,4 +36,8 @@
     public void Start() {
       if (ExecutionState == Core.ExecutionState.Stopped) {
+        // kick off the event immediately
+        timer_Tick(this, EventArgs.Empty);
+
+        // start the timer
         this.timer.Interval = (int)new TimeSpan(0, 0, 30).TotalMilliseconds;
         this.timer.Start();
@@ -54,21 +58,39 @@
       lock (locker) {
         using (trans.OpenTransaction()) {
-          var slaves = dao.GetSlaves(x => x.SlaveState != SlaveState.Offline);
-          foreach (Slave slave in slaves) {
-            if (!slave.LastHeartbeat.HasValue || (DateTime.Now - slave.LastHeartbeat.Value).TotalSeconds > ApplicationConstants.HeartbeatTimeout) {
-              slave.SlaveState = SlaveState.Offline;
-              AbortJobs(slave.Id);
-              dao.UpdateSlave(slave);
-            }
-          }
+          SetTimeoutSlavesOffline();
+          FinishParentJobs();
         }
       }
     }
 
-    private void AbortJobs(Guid slaveId) {
-      var jobs = dao.GetJobs(x => x.StateLogs.Last().SlaveId == slaveId);
+    /// <summary>
+    /// Searches for slaves which are timed out, puts them and their jobs offline
+    /// </summary>
+    private void SetTimeoutSlavesOffline() {
+      var slaves = dao.GetSlaves(x => x.SlaveState != SlaveState.Offline);
+      foreach (Slave slave in slaves) {
+        if (!slave.LastHeartbeat.HasValue || (DateTime.Now - slave.LastHeartbeat.Value).TotalSeconds > ApplicationConstants.HeartbeatTimeout) {
+          slave.SlaveState = SlaveState.Offline;
+          SetJobsWaiting(slave.Id);
+          dao.UpdateSlave(slave);
+        }
+      }
+    }
+
+    /// <summary>
+    /// Looks for parent jobs which have FinishWhenChildJobsFinished and set their state to finished
+    /// </summary>
+    private void FinishParentJobs() {
+      var parentJobsToFinish = dao.GetParentJobs(dao.GetResources(x => true).Select(x => x.Id), 0, true);
+      foreach (var job in parentJobsToFinish) {
+        job.SetState(JobState.Finished);
+        dao.UpdateJob(job);
+      }
+    }
+
+    private void SetJobsWaiting(Guid slaveId) {
+      var jobs = dao.GetJobs(x => x.State == JobState.Calculating).Where(x => x.StateLog.Last().SlaveId == slaveId);
       foreach (var j in jobs) {
         j.StateLog.Add(new StateLog() { 
-          UserId = auth.UserId, 
           State = JobState.Waiting,
           JobId = j.Id,
