Index: /trunk/sources/HeuristicLab.Hive.Contracts/ApplicationConstants.cs
===================================================================
--- /trunk/sources/HeuristicLab.Hive.Contracts/ApplicationConstants.cs	(revision 1368)
+++ /trunk/sources/HeuristicLab.Hive.Contracts/ApplicationConstants.cs	(revision 1369)
@@ -73,4 +73,7 @@
     public static string RESPONSE_COMMUNICATOR_JOB_IS_NOT_BEEING_CALCULATED = "Communicator.JobIsNotBeenigCalculated";
     public static string RESPONSE_COMMUNICATOR_WRONG_CLIENT_FOR_JOB = "Communicator.WrongClientForJob";
+    public static string RESPONSE_COMMUNICATOR_JOB_ALLREADY_FINISHED = "Job allready finished. Not needed anymore";
+    public static string RESPONSE_COMMUNICATOR_JOB_DOESNT_EXIST = "No job exists with this id";
+    public static string RESPONSE_COMMUNICATOR_SEND_JOBRESULT = "Please send the Jobresult to the server";
 
     public static string RESPONSE_JOB_ALL_JOBS = "Job.AllJobs";
Index: /trunk/sources/HeuristicLab.Hive.Contracts/HeuristicLab.Hive.Contracts.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Hive.Contracts/HeuristicLab.Hive.Contracts.csproj	(revision 1368)
+++ /trunk/sources/HeuristicLab.Hive.Contracts/HeuristicLab.Hive.Contracts.csproj	(revision 1369)
@@ -103,4 +103,5 @@
     <Compile Include="ResponseHB.cs" />
     <Compile Include="ResponseList.cs" />
+    <Compile Include="ResponsePlugin.cs" />
     <Compile Include="ResponseResultReceived.cs" />
   </ItemGroup>
Index: /trunk/sources/HeuristicLab.Hive.Contracts/Interfaces/IClientCommunicator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Hive.Contracts/Interfaces/IClientCommunicator.cs	(revision 1368)
+++ /trunk/sources/HeuristicLab.Hive.Contracts/Interfaces/IClientCommunicator.cs	(revision 1369)
@@ -48,4 +48,8 @@
     [OperationContract]
     Response Logout(Guid clientId);
+    [OperationContract]
+    Response IsJobStillNeeded(long jobId);
+    [OperationContract]
+    ResponsePlugin SendPlugins(List<String> pluginList);
   }
 }
Index: /trunk/sources/HeuristicLab.Hive.Contracts/ResponsePlugin.cs
===================================================================
--- /trunk/sources/HeuristicLab.Hive.Contracts/ResponsePlugin.cs	(revision 1369)
+++ /trunk/sources/HeuristicLab.Hive.Contracts/ResponsePlugin.cs	(revision 1369)
@@ -0,0 +1,14 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.Serialization;
+
+namespace HeuristicLab.Hive.Contracts {
+
+  [DataContract]
+  public class ResponsePlugin : Response {
+    [DataMember]
+    public byte[] Plugins { get; set; }
+  }
+}
Index: /trunk/sources/HeuristicLab.Hive.Server.Core/ClientCommunicator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Hive.Server.Core/ClientCommunicator.cs	(revision 1368)
+++ /trunk/sources/HeuristicLab.Hive.Server.Core/ClientCommunicator.cs	(revision 1369)
@@ -46,11 +46,10 @@
       new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
 
-    // todo: access modifier!
-    IClientAdapter clientAdapter;
-    IJobAdapter jobAdapter;
-    IJobResultsAdapter jobResultAdapter;
-    ILifecycleManager lifecycleManager;
-    IInternalJobManager jobManager;
-    IScheduler scheduler;
+    private IClientAdapter clientAdapter;
+    private IJobAdapter jobAdapter;
+    private IJobResultsAdapter jobResultAdapter;
+    private ILifecycleManager lifecycleManager;
+    private IInternalJobManager jobManager;
+    private IScheduler scheduler;
 
     /// <summary>
@@ -145,5 +144,4 @@
 
       // todo: allClients legacy ?
-      ICollection<ClientInfo> allClients = clientAdapter.GetAll();
       ClientInfo client = clientAdapter.GetById(clientInfo.ClientId);
       if (client != null && client.State != State.offline && client.State != State.nullState) {
@@ -167,8 +165,8 @@
     /// <param name="hbData"></param>
     /// <returns></returns>
-    // todo: new name for "SendHeartBeat" e.g. ProcessHeartBeat
     public ResponseHB ProcessHeartBeat(HeartBeatData hbData) {
       ResponseHB response = new ResponseHB();
 
+      // check if the client is logged in
       response.ActionRequest = new List<MessageContainer>();
       if (clientAdapter.GetById(hbData.ClientId).State == State.offline ||
@@ -180,4 +178,5 @@
       }
 
+      // save timestamp of this heartbeat
       heartbeatLock.EnterWriteLock();
       if (lastHeartbeats.ContainsKey(hbData.ClientId)) {
@@ -190,4 +189,6 @@
       response.Success = true;
       response.StatusMessage = ApplicationConstants.RESPONSE_COMMUNICATOR_HEARTBEAT_RECEIVED;
+      // check if client has a free core for a new job
+      // if true, ask scheduler for a new job for this client
       if (hbData.FreeCores > 0 && scheduler.ExistsJobForClient(hbData))
         response.ActionRequest.Add(new MessageContainer(MessageContainer.MessageType.FetchJob));
@@ -208,5 +209,10 @@
             response.Success = false;
             response.StatusMessage = ApplicationConstants.RESPONSE_COMMUNICATOR_JOB_IS_NOT_BEEING_CALCULATED;
+          } else if(curJob.State == State.finished) {
+            // another client has finished this job allready
+            // the client can abort it
+            response.ActionRequest.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, curJob.Id));        
           } else {
+            // save job progress
             curJob.Percentage = jobProgress.Value;
             jobAdapter.Update(curJob);
@@ -279,4 +285,9 @@
         return response;
       }
+      if (job.State == State.finished) {
+        response.Success = true;
+        response.StatusMessage = ApplicationConstants.RESPONSE_COMMUNICATOR_JOBRESULT_RECEIVED;
+        return response;        
+      }
       if (job.State != State.calculating) {
         response.Success = false;
@@ -358,4 +369,35 @@
     }
 
+    /// <summary>
+    /// If a client goes offline and restores a job he was calculating 
+    /// he can ask the client if he still needs the job result
+    /// </summary>
+    /// <param name="jobId"></param>
+    /// <returns></returns>
+    public Response IsJobStillNeeded(long jobId) {
+      Response response = new Response();
+      Job job = jobAdapter.GetById(jobId);
+      if (job == null) {
+        response.Success = false;
+        response.StatusMessage = ApplicationConstants.RESPONSE_COMMUNICATOR_JOB_DOESNT_EXIST;
+        return response;
+      }
+      if (job.State == State.finished) {
+        response.Success = true;
+        response.StatusMessage = ApplicationConstants.RESPONSE_COMMUNICATOR_JOB_ALLREADY_FINISHED;
+        return response;
+      }
+      job.State = State.finished;
+      jobAdapter.Update(job);
+      
+      response.Success = true;
+      response.StatusMessage = ApplicationConstants.RESPONSE_COMMUNICATOR_SEND_JOBRESULT;
+      return response;
+    }
+
+    public ResponsePlugin SendPlugins(List<string> pluginList) {
+      throw new NotImplementedException();
+    }
+
     #endregion
   }
Index: /trunk/sources/HeuristicLab.Hive.Server.Core/ClientFacade.cs
===================================================================
--- /trunk/sources/HeuristicLab.Hive.Server.Core/ClientFacade.cs	(revision 1368)
+++ /trunk/sources/HeuristicLab.Hive.Server.Core/ClientFacade.cs	(revision 1369)
@@ -61,4 +61,12 @@
     }
 
+    public Response IsJobStillNeeded(long jobId) {
+      return clientCommunicator.IsJobStillNeeded(jobId);
+    }
+
+    public ResponsePlugin SendPlugins(List<string> pluginList) {
+      return clientCommunicator.SendPlugins(pluginList);
+    }
+
     #endregion
   }
