Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Hive.Client.Communication/3.2/WcfService.cs @ 1959

Last change on this file since 1959 was 1959, checked in by kgrading, 15 years ago

fixed persistence problems (#493)

File size: 12.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using System.ServiceModel;
27using HeuristicLab.Hive.Contracts.Interfaces;
28using HeuristicLab.Hive.Contracts;
29using HeuristicLab.Hive.Contracts.BusinessObjects;
30using HeuristicLab.Hive.Client.Common;
31using HeuristicLab.Hive.Client.Communication.ServerService;
32using HeuristicLab.PluginInfrastructure;
33using System.IO;
34using System.Runtime.Serialization.Formatters.Binary;
35
36namespace HeuristicLab.Hive.Client.Communication {
37  /// <summary>
38  /// WcfService class is implemented as a Singleton and works as a communication Layer with the Server
39  /// </summary>
40  public class WcfService {
41    private static WcfService instance;
42    /// <summary>
43    /// Getter for the Instance of the WcfService
44    /// </summary>
45    /// <returns>the Instance of the WcfService class</returns>
46    public static WcfService Instance {
47      get {
48        if (instance == null) {
49          instance = new WcfService();
50        }
51        return instance;
52      }
53    }
54
55    public DateTime ConnectedSince { get; private set; }   
56    public NetworkEnum.WcfConnState ConnState { get; private set; }
57    public string ServerIP { get; private set; }
58    public int ServerPort { get; private set; }
59
60    public event EventHandler ConnectionRestored;   
61    public event EventHandler ServerChanged;
62    public event EventHandler Connected;   
63
64    public ClientFacadeClient proxy = null;
65
66    /// <summary>
67    /// Constructor
68    /// </summary>
69    private WcfService() {
70      ConnState = NetworkEnum.WcfConnState.Disconnected;
71    }
72
73    /// <summary>
74    /// Connects with the Server, registers the events and fires the Connected (and quiet possibly the ConnectionRestored) Event.
75    /// </summary>
76    public void Connect() {
77      try {
78        proxy = new ClientFacadeClient(
79          WcfSettings.GetStreamedBinding(),
80          new EndpointAddress("net.tcp://" + ServerIP + ":" + ServerPort + "/HiveServer/ClientCommunicator")
81        );
82
83        proxy.LoginCompleted += new EventHandler<LoginCompletedEventArgs>(proxy_LoginCompleted);
84        proxy.SendStreamedJobCompleted += new EventHandler<SendStreamedJobCompletedEventArgs>(proxy_SendStreamedJobCompleted);
85        proxy.StoreFinishedJobResultStreamedCompleted += new EventHandler<StoreFinishedJobResultStreamedCompletedEventArgs>(proxy_StoreFinishedJobResultStreamedCompleted);
86        proxy.ProcessSnapshotStreamedCompleted += new EventHandler<ProcessSnapshotStreamedCompletedEventArgs>(proxy_ProcessSnapshotStreamedCompleted);
87        proxy.ProcessHeartBeatCompleted += new EventHandler<ProcessHeartBeatCompletedEventArgs>(proxy_ProcessHeartBeatCompleted);
88        proxy.Open();
89
90        ConnState = NetworkEnum.WcfConnState.Connected;
91        ConnectedSince = DateTime.Now;
92       
93        if (Connected != null)
94          Connected(this, new EventArgs());                               
95        //Todo: This won't be hit. EVER       
96        if (ConnState == NetworkEnum.WcfConnState.Failed)
97          ConnectionRestored(this, new EventArgs());       
98      }
99      catch (Exception ex) {     
100        HandleNetworkError(ex);
101      }
102    }
103
104
105    /// <summary>
106    /// Changes the Connectionsettings (serverIP & serverPort) and reconnects
107    /// </summary>
108    /// <param name="serverIP">current Server IP</param>
109    /// <param name="serverPort">current Server Port</param>
110    public void Connect(String serverIP, int serverPort) {
111      String oldIp = this.ServerIP;
112      int oldPort = this.ServerPort;
113      this.ServerIP = serverIP;
114      this.ServerPort = serverPort;     
115      Connect();
116      if (oldIp != serverIP || oldPort != ServerPort)
117        if(ServerChanged != null)
118          ServerChanged(this, new EventArgs());
119    }
120   
121    /// <summary>
122    /// Disconnects the Client from the Server
123    /// </summary>
124    public void Disconnect() {
125      ConnState = NetworkEnum.WcfConnState.Disconnected;
126    }
127
128    /// <summary>
129    /// Network communication Error Handler - Every network error gets logged and the connection switches to faulted state
130    /// </summary>
131    /// <param name="e">The Exception</param>
132    private void HandleNetworkError(Exception e) {
133      ConnState = NetworkEnum.WcfConnState.Failed;
134      Logging.Instance.Error(this.ToString(), "exception: ", e);
135    }
136
137   
138
139    /// <summary>
140    /// Methods for the Server Login
141    /// </summary>
142    #region Login
143    public event System.EventHandler<LoginCompletedEventArgs> LoginCompleted;
144    public void LoginAsync(ClientInfo clientInfo) {
145      if (ConnState == NetworkEnum.WcfConnState.Connected)
146        proxy.LoginAsync(clientInfo);
147    }
148    private void proxy_LoginCompleted(object sender, LoginCompletedEventArgs e) {
149      if (e.Error == null)
150        LoginCompleted(sender, e);
151      else
152        HandleNetworkError(e.Error.InnerException);
153    }
154
155    public void LoginSync(ClientInfo clientInfo) {
156      try {
157        if (ConnState == NetworkEnum.WcfConnState.Connected) {
158          Response res = proxy.Login(clientInfo);
159          if (!res.Success) {
160            Logging.Instance.Error(this.ToString(), "Login Failed! " + res.StatusMessage);
161            HandleNetworkError(null);
162          } else {
163            ConnState = NetworkEnum.WcfConnState.Loggedin;
164            Logging.Instance.Info(this.ToString(), res.StatusMessage);
165          }
166        }
167      }
168      catch (Exception e) {
169        HandleNetworkError(e);
170      }
171    }
172
173    #endregion
174
175    /// <summary>
176    /// Pull a Job from the Server
177    /// </summary>
178    #region PullJob
179    public event System.EventHandler<SendJobCompletedEventArgs> SendJobCompleted;
180    public void SendJobAsync(Guid guid) {
181      if (ConnState == NetworkEnum.WcfConnState.Loggedin)       
182        proxy.SendStreamedJobAsync(guid);
183    }
184
185    void proxy_SendStreamedJobCompleted(object sender, SendStreamedJobCompletedEventArgs e) {
186      if (e.Error == null) {
187        Stream stream =
188          (Stream)e.Result;
189               
190        BinaryFormatter formatter =
191          new BinaryFormatter();
192        ResponseJob response = (ResponseJob)formatter.Deserialize(stream);
193
194        SendJobCompletedEventArgs completedEventArgs =
195          new SendJobCompletedEventArgs(new object[] { response }, e.Error, e.Cancelled, e.UserState);
196        SendJobCompleted(sender, completedEventArgs);
197      } else
198        HandleNetworkError(e.Error);
199    }
200
201    #endregion
202
203    /// <summary>
204    /// Send back finished Job Results
205    /// </summary>
206    #region SendJobResults
207    public event System.EventHandler<StoreFinishedJobResultCompletedEventArgs> StoreFinishedJobResultCompleted;
208    public void StoreFinishedJobResultAsync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception, bool finished) {
209      if (ConnState == NetworkEnum.WcfConnState.Loggedin)
210        proxy.StoreFinishedJobResultStreamedAsync(
211          GetStreamedJobResult(clientId, jobId, result, percentage, exception));
212    }
213    private void proxy_StoreFinishedJobResultStreamedCompleted(object sender, StoreFinishedJobResultStreamedCompletedEventArgs e) {
214      if (e.Error == null) {
215        StoreFinishedJobResultCompletedEventArgs args =
216          new StoreFinishedJobResultCompletedEventArgs(
217            new object[] { e.Result }, e.Error, e.Cancelled, e.UserState);
218        StoreFinishedJobResultCompleted(sender, args);
219      } else
220        HandleNetworkError(e.Error);
221    }
222
223    #endregion
224
225    #region Processsnapshots
226    public event System.EventHandler<ProcessSnapshotCompletedEventArgs> ProcessSnapshotCompleted;
227    public void ProcessSnapshotAsync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception, bool finished) {
228      if(ConnState == NetworkEnum.WcfConnState.Loggedin)
229        proxy.ProcessSnapshotStreamedAsync(
230          GetStreamedJobResult(
231            clientId, jobId, result, percentage, exception));
232    }
233    void proxy_ProcessSnapshotStreamedCompleted(object sender, ProcessSnapshotStreamedCompletedEventArgs e) {
234      if (e.Error == null) {
235        ProcessSnapshotCompletedEventArgs args =
236          new ProcessSnapshotCompletedEventArgs(
237            new object[] { e.Result }, e.Error, e.Cancelled, e.UserState);
238
239        ProcessSnapshotCompleted(sender, args);
240      } else
241        HandleNetworkError(e.Error);
242    }   
243   
244    #endregion
245
246    /// <summary>
247    /// Methods for sending the periodically Heartbeat
248    /// </summary>
249    #region Heartbeat
250
251    public event System.EventHandler<ProcessHeartBeatCompletedEventArgs> SendHeartBeatCompleted;
252    public void SendHeartBeatAsync(HeartBeatData hbd) {
253      if (ConnState == NetworkEnum.WcfConnState.Loggedin)
254        proxy.ProcessHeartBeatAsync(hbd);
255    }
256
257    private void proxy_ProcessHeartBeatCompleted(object sender, ProcessHeartBeatCompletedEventArgs e) {
258      if (e.Error == null && e.Result.Success == true)
259        SendHeartBeatCompleted(sender, e);
260      else
261        HandleNetworkError(e.Error);
262    }
263
264    #endregion 
265
266    /// <summary>
267    /// Send back finished and Stored Job Results
268    /// </summary>
269    /*#region SendJobResults
270    public event System.EventHandler<StoreFinishedJobResultCompletedEventArgs> ProcessStoredJobResultCompleted;
271    public void ProcessStoredJobResultAsync(Guid clientId, long jobId, byte[] result, double percentage, Exception exception, bool finished) {
272      if (ConnState == NetworkEnum.WcfConnState.Loggedin)
273        //TODO: some sort of algo for the stored jobs
274        proxy.ProcessJobResultAsync(clientId, jobId, result, percentage, exception, finished);
275    } 
276    #endregion  */
277
278    private Stream GetStreamedJobResult(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception) {
279      JobResult jobResult =
280          new JobResult();
281      jobResult.ClientId = clientId;
282      jobResult.JobId = jobId;
283      jobResult.Result = result;
284      jobResult.Percentage = percentage;
285      jobResult.Exception = exception;
286
287      MemoryStream stream =
288        new MemoryStream();
289
290      BinaryFormatter formatter =
291        new BinaryFormatter();
292
293      formatter.Serialize(stream, jobResult);
294      stream.Seek(0, SeekOrigin.Begin);
295
296      return stream;
297    }
298
299    public ResponseResultReceived SendStoredJobResultsSync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception, bool finished) {     
300      return proxy.StoreFinishedJobResultStreamed(
301        GetStreamedJobResult(clientId, jobId, result, percentage, exception));
302    }
303
304    public Response IsJobStillNeeded(Guid jobId) {
305      try {
306        return proxy.IsJobStillNeeded(jobId);
307      }
308      catch (Exception e) {
309        HandleNetworkError(e);
310        return null;
311      }
312     
313    }
314
315    public ResponseResultReceived ProcessSnapshotSync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception) {
316      try {
317        Logging.Instance.Info(this.ToString(), "Snapshot for Job " + jobId + " submitted");
318        return proxy.ProcessSnapshotStreamed(
319          GetStreamedJobResult(clientId, jobId, result, percentage, exception));
320      }
321      catch (Exception e) {
322        HandleNetworkError(e);
323        return null;
324      }
325    }
326
327    public List<CachedHivePluginInfo> RequestPlugins(List<HivePluginInfo> requestedPlugins) {
328      try {
329        Stream stream = proxy.SendStreamedPlugins(requestedPlugins.ToArray());
330
331        BinaryFormatter formatter =
332          new BinaryFormatter();
333        ResponsePlugin response = (ResponsePlugin)formatter.Deserialize(stream);
334        return response.Plugins;       
335      }
336      catch (Exception e) {
337        HandleNetworkError(e);
338        return null;
339      }
340    }
341
342    public void Logout(Guid guid) {
343      try {
344        proxy.Logout(guid);
345      }
346      catch (Exception e) {
347        HandleNetworkError(e);
348      }
349    }
350  }
351}
Note: See TracBrowser for help on using the repository browser.