Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3578 was 3578, checked in by kgrading, 14 years ago

Removed References to HiveLogging and updated the default logging mechanism (#991)

File size: 16.5 KB
RevLine 
[3011]1#region License Information
[1132]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;
[923]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;
[993]31using HeuristicLab.Hive.Client.Communication.ServerService;
[1450]32using HeuristicLab.PluginInfrastructure;
[1939]33using System.IO;
34using System.Runtime.Serialization.Formatters.Binary;
[3578]35using HeuristicLab.Tracing;
[923]36
37namespace HeuristicLab.Hive.Client.Communication {
[1132]38  /// <summary>
39  /// WcfService class is implemented as a Singleton and works as a communication Layer with the Server
40  /// </summary>
[923]41  public class WcfService {
42    private static WcfService instance;
[1132]43    /// <summary>
44    /// Getter for the Instance of the WcfService
45    /// </summary>
46    /// <returns>the Instance of the WcfService class</returns>
[923]47    public static WcfService Instance {
[3578]48      get {       
[923]49        if (instance == null) {
[3578]50          Logger.Debug("New WcfService Instance created");
[923]51          instance = new WcfService();
52        }
53        return instance;
54      }
55    }
56
[932]57    public DateTime ConnectedSince { get; private set; }   
58    public NetworkEnum.WcfConnState ConnState { get; private set; }
59    public string ServerIP { get; private set; }
60    public int ServerPort { get; private set; }
[923]61
[924]62    public event EventHandler ConnectionRestored;   
[1081]63    public event EventHandler ServerChanged;
64    public event EventHandler Connected;   
[924]65
[1939]66    public ClientFacadeClient proxy = null;
[923]67
[1132]68    /// <summary>
69    /// Constructor
70    /// </summary>
[923]71    private WcfService() {
[949]72      ConnState = NetworkEnum.WcfConnState.Disconnected;
[923]73    }
[1132]74
75    /// <summary>
76    /// Connects with the Server, registers the events and fires the Connected (and quiet possibly the ConnectionRestored) Event.
77    /// </summary>
[923]78    public void Connect() {
79      try {
[3578]80        Logger.Debug("Starting the Connection Process");
[2025]81        if (String.Empty.Equals(ServerIP) || ServerPort == 0) {
[3578]82          Logger.Info("No Server IP or Port set!");
[2025]83          return;
84        }
[3578]85
86        Logger.Debug("Creating the new connection proxy");
[1939]87        proxy = new ClientFacadeClient(
88          WcfSettings.GetStreamedBinding(),
[1081]89          new EndpointAddress("net.tcp://" + ServerIP + ":" + ServerPort + "/HiveServer/ClientCommunicator")
90        );
[3578]91        Logger.Debug("Created the new connection proxy");
[923]92
[3578]93        Logger.Debug("Registring new Events");
[923]94        proxy.LoginCompleted += new EventHandler<LoginCompletedEventArgs>(proxy_LoginCompleted);
[1939]95        proxy.SendStreamedJobCompleted += new EventHandler<SendStreamedJobCompletedEventArgs>(proxy_SendStreamedJobCompleted);
96        proxy.StoreFinishedJobResultStreamedCompleted += new EventHandler<StoreFinishedJobResultStreamedCompletedEventArgs>(proxy_StoreFinishedJobResultStreamedCompleted);
97        proxy.ProcessSnapshotStreamedCompleted += new EventHandler<ProcessSnapshotStreamedCompletedEventArgs>(proxy_ProcessSnapshotStreamedCompleted);
[1366]98        proxy.ProcessHeartBeatCompleted += new EventHandler<ProcessHeartBeatCompletedEventArgs>(proxy_ProcessHeartBeatCompleted);
[3578]99        Logger.Debug("Registered new Events");
100        Logger.Debug("Opening the Connection");
[1082]101        proxy.Open();
[3578]102        Logger.Debug("Opened the Connection");
[1082]103
[932]104        ConnState = NetworkEnum.WcfConnState.Connected;
[1097]105        ConnectedSince = DateTime.Now;
[3578]106
107        if (Connected != null) {
108          Logger.Debug("Calling the connected Event");
109          Connected(this, new EventArgs());
110          //Todo: This won't be hit. EVER       
111        }
[1097]112        if (ConnState == NetworkEnum.WcfConnState.Failed)
113          ConnectionRestored(this, new EventArgs());       
[923]114      }
[1371]115      catch (Exception ex) {     
116        HandleNetworkError(ex);
[923]117      }
118    }
119
[1379]120
[1132]121    /// <summary>
122    /// Changes the Connectionsettings (serverIP & serverPort) and reconnects
123    /// </summary>
124    /// <param name="serverIP">current Server IP</param>
125    /// <param name="serverPort">current Server Port</param>
[932]126    public void Connect(String serverIP, int serverPort) {
[3578]127      Logger.Debug("Called Connected with " + serverIP + ":" + serverPort);
[993]128      String oldIp = this.ServerIP;
129      int oldPort = this.ServerPort;
[932]130      this.ServerIP = serverIP;
[944]131      this.ServerPort = serverPort;     
[923]132      Connect();
[993]133      if (oldIp != serverIP || oldPort != ServerPort)
[1036]134        if(ServerChanged != null)
135          ServerChanged(this, new EventArgs());
[923]136    }
[2025]137
138    public void SetIPAndPort(String serverIP, int serverPort) {
[3578]139      Logger.Debug("Called with " + serverIP + ":" + serverPort);
[2025]140      this.ServerIP = serverIP;
141      this.ServerPort = serverPort;
142    }
[1132]143   
144    /// <summary>
145    /// Disconnects the Client from the Server
146    /// </summary>
[932]147    public void Disconnect() {
148      ConnState = NetworkEnum.WcfConnState.Disconnected;
149    }
150
[1132]151    /// <summary>
152    /// Network communication Error Handler - Every network error gets logged and the connection switches to faulted state
153    /// </summary>
154    /// <param name="e">The Exception</param>
[1371]155    private void HandleNetworkError(Exception e) {
[932]156      ConnState = NetworkEnum.WcfConnState.Failed;
[3578]157      Logger.Error("Network exception occurred: " + e);
[923]158    }
159
[1132]160   
161
162    /// <summary>
163    /// Methods for the Server Login
164    /// </summary>
[923]165    #region Login
166    public event System.EventHandler<LoginCompletedEventArgs> LoginCompleted;
[3011]167    public void LoginAsync(ClientDto clientInfo) {
[3578]168      if (ConnState == NetworkEnum.WcfConnState.Connected) {
169        Logger.Debug("STARTED: Login Async");
[923]170        proxy.LoginAsync(clientInfo);
[3578]171      }
[923]172    }
173    private void proxy_LoginCompleted(object sender, LoginCompletedEventArgs e) {
[3578]174      if (e.Error == null) {
175        Logger.Debug("ENDED: Login Async");
[923]176        LoginCompleted(sender, e);
[3578]177      } else
[1371]178        HandleNetworkError(e.Error.InnerException);
[923]179    }
[1097]180
[3011]181    public void LoginSync(ClientDto clientInfo) {
[1097]182      try {
183        if (ConnState == NetworkEnum.WcfConnState.Connected) {
[3578]184          Logger.Debug("STARTED: Login Sync");
[1097]185          Response res = proxy.Login(clientInfo);
[1959]186          if (!res.Success) {
[3578]187            Logger.Error("FAILED: Login Failed! " + res.StatusMessage);
188            throw new Exception(res.StatusMessage);
[1959]189          } else {
[3578]190            Logger.Info("ENDED: Login succeeded" + res.StatusMessage);
191            ConnState = NetworkEnum.WcfConnState.Loggedin;           
[1959]192          }
[1097]193        }
194      }
195      catch (Exception e) {
[1371]196        HandleNetworkError(e);
[1097]197      }
198    }
199
[923]200    #endregion
201
[1132]202    /// <summary>
203    /// Pull a Job from the Server
204    /// </summary>
[923]205    #region PullJob
[1367]206    public event System.EventHandler<SendJobCompletedEventArgs> SendJobCompleted;
207    public void SendJobAsync(Guid guid) {
[3578]208      if (ConnState == NetworkEnum.WcfConnState.Loggedin) {
209        Logger.Debug("STARTED: Fetching of Jobs from Server for Client");
[1939]210        proxy.SendStreamedJobAsync(guid);
[3578]211      }
[923]212    }
[1939]213
214    void proxy_SendStreamedJobCompleted(object sender, SendStreamedJobCompletedEventArgs e) {
215      if (e.Error == null) {
[3578]216        Logger.Debug("ENDED: Fetching of Jobs from Server for Client");
[2117]217        Stream stream = null;
[2122]218        MemoryStream memStream = null;
[1939]219
[2117]220        try {
221          stream = (Stream)e.Result;
222
223          //first deserialize the response
224          BinaryFormatter formatter =
225            new BinaryFormatter();
226          ResponseJob response =
227            (ResponseJob)formatter.Deserialize(stream);
228
229          //second deserialize the BLOB
[2122]230          memStream = new MemoryStream();
231
[2117]232          byte[] buffer = new byte[3024];
233          int read = 0;
234          while ((read = stream.Read(buffer, 0, buffer.Length)) > 0) {
235            memStream.Write(buffer, 0, read);
236          }
237
[2122]238          memStream.Close();
239
[2117]240          SendJobCompletedEventArgs completedEventArgs =
241            new SendJobCompletedEventArgs(new object[] { response, memStream.GetBuffer() }, e.Error, e.Cancelled, e.UserState);
242          SendJobCompleted(sender, completedEventArgs);
[3578]243        } catch (Exception ex) {
244          Logger.Error(ex);
245        } finally {
[2117]246          if(stream != null)
247            stream.Dispose();
[2122]248
249          if (memStream != null)
250            memStream.Dispose();
[2117]251        }
[1939]252      } else
[1371]253        HandleNetworkError(e.Error);
[923]254    }
[1939]255
[923]256    #endregion
257
[1132]258    /// <summary>
259    /// Send back finished Job Results
260    /// </summary>
[923]261    #region SendJobResults
[1379]262    public event System.EventHandler<StoreFinishedJobResultCompletedEventArgs> StoreFinishedJobResultCompleted;
[1449]263    public void StoreFinishedJobResultAsync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception, bool finished) {
[2117]264      if (ConnState == NetworkEnum.WcfConnState.Loggedin) {
[3578]265        Logger.Debug("STARTED: Sending back the finished job results");
266        Logger.Debug("Building stream");
[2117]267        Stream stream =
268          GetStreamedJobResult(clientId, jobId, result, percentage, exception);
[3578]269        Logger.Debug("Builded stream");
270        Logger.Debug("Making the call");
[2117]271        proxy.StoreFinishedJobResultStreamedAsync(stream, stream);
272      }
273     }
[1939]274    private void proxy_StoreFinishedJobResultStreamedCompleted(object sender, StoreFinishedJobResultStreamedCompletedEventArgs e) {
[3578]275      Logger.Debug("Finished storing the job");
[2117]276      Stream stream =
277        (Stream)e.UserState;
[3578]278      if (stream != null) {
279        Logger.Debug("Stream not null, disposing it");
[2117]280        stream.Dispose();
[3578]281      }
[1939]282      if (e.Error == null) {
283        StoreFinishedJobResultCompletedEventArgs args =
284          new StoreFinishedJobResultCompletedEventArgs(
285            new object[] { e.Result }, e.Error, e.Cancelled, e.UserState);
[3578]286        Logger.Debug("calling the Finished Job Event");
[1939]287        StoreFinishedJobResultCompleted(sender, args);
[3578]288        Logger.Debug("ENDED: Sending back the finished job results");
[1939]289      } else
[1371]290        HandleNetworkError(e.Error);
[923]291    }
292
293    #endregion
294
[1379]295    #region Processsnapshots
296    public event System.EventHandler<ProcessSnapshotCompletedEventArgs> ProcessSnapshotCompleted;
[1449]297    public void ProcessSnapshotAsync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception, bool finished) {
[2117]298      if (ConnState == NetworkEnum.WcfConnState.Loggedin) {
299        Stream stream = GetStreamedJobResult(
300            clientId, jobId, result, percentage, exception);
301
302        proxy.ProcessSnapshotStreamedAsync(stream, stream);
303      }
[1379]304    }
[1939]305    void proxy_ProcessSnapshotStreamedCompleted(object sender, ProcessSnapshotStreamedCompletedEventArgs e) {
[2117]306      Stream stream =
307        (Stream)e.UserState;
308      if (stream != null)
309        stream.Dispose();
310     
[1939]311      if (e.Error == null) {
312        ProcessSnapshotCompletedEventArgs args =
313          new ProcessSnapshotCompletedEventArgs(
314            new object[] { e.Result }, e.Error, e.Cancelled, e.UserState);
315
316        ProcessSnapshotCompleted(sender, args);
317      } else
[1379]318        HandleNetworkError(e.Error);
319    }   
320   
321    #endregion
[2107]322                                                 
[1132]323    /// <summary>
324    /// Methods for sending the periodically Heartbeat
325    /// </summary>
[923]326    #region Heartbeat
327
[1366]328    public event System.EventHandler<ProcessHeartBeatCompletedEventArgs> SendHeartBeatCompleted;
[923]329    public void SendHeartBeatAsync(HeartBeatData hbd) {
[1255]330      if (ConnState == NetworkEnum.WcfConnState.Loggedin)
[3578]331        Logger.Debug("STARTING: sending heartbeat");
[1366]332        proxy.ProcessHeartBeatAsync(hbd);
[923]333    }
334
[1366]335    private void proxy_ProcessHeartBeatCompleted(object sender, ProcessHeartBeatCompletedEventArgs e) {
[3578]336      if (e.Error == null && e.Result.Success == true) {
[923]337        SendHeartBeatCompleted(sender, e);
[3578]338        Logger.Debug("ENDED: sending heartbeats");
339      } else {
[2107]340        try {
[3578]341          Logger.Error("Error: " + e.Result.StatusMessage);
[2107]342        }
[3578]343        catch (Exception ex) {
344          Logger.Error("Error: ", ex);
345        }
[1371]346        HandleNetworkError(e.Error);
[2063]347      }
[923]348    }
349
[1097]350    #endregion 
[1271]351
352    /// <summary>
353    /// Send back finished and Stored Job Results
354    /// </summary>
[1939]355    private Stream GetStreamedJobResult(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception) {
[2117]356      JobResult jobResult =
357          new JobResult();
[1939]358      jobResult.ClientId = clientId;
359      jobResult.JobId = jobId;
360      jobResult.Percentage = percentage;
361      jobResult.Exception = exception;
362
[2117]363      MultiStream stream =
364              new MultiStream();
[2099]365
[2117]366      //first send result
367      stream.AddStream(
368        new StreamedObject<JobResult>(jobResult));
[1939]369
[2117]370      //second stream the job binary data
371      MemoryStream memStream =
372        new MemoryStream(result, false);
373      stream.AddStream(memStream);
[1939]374
375      return stream;
376    }
377
[1812]378    public ResponseResultReceived SendStoredJobResultsSync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception, bool finished) {     
[1939]379      return proxy.StoreFinishedJobResultStreamed(
380        GetStreamedJobResult(clientId, jobId, result, percentage, exception));
[1271]381    }
[1450]382
[1959]383    public Response IsJobStillNeeded(Guid jobId) {
384      try {
[3578]385        Logger.Debug("STARTING: Sync call: IsJobStillNeeded");
386        Response res = proxy.IsJobStillNeeded(jobId);
387        Logger.Debug("ENDED: Sync call: IsJobStillNeeded");
388        return res;
[1959]389      }
390      catch (Exception e) {
391        HandleNetworkError(e);
392        return null;
393      }
394     
395    }
396
[1812]397    public ResponseResultReceived ProcessSnapshotSync(Guid clientId, Guid jobId, byte[] result, double percentage, Exception exception) {
[3578]398      try {       
[1939]399        return proxy.ProcessSnapshotStreamed(
400          GetStreamedJobResult(clientId, jobId, result, percentage, exception));
[1812]401      }
402      catch (Exception e) {
403        HandleNetworkError(e);
404        return null;
405      }
406    }
407
[3011]408    public List<CachedHivePluginInfoDto> RequestPlugins(List<HivePluginInfoDto> requestedPlugins) {
[1450]409      try {
[3578]410        Logger.Debug("STARTED: Requesting Plugins for Job");
411        Logger.Debug("STARTED: Getting the stream");
[1939]412        Stream stream = proxy.SendStreamedPlugins(requestedPlugins.ToArray());
[3578]413        Logger.Debug("ENDED: Getting the stream");
[1939]414        BinaryFormatter formatter =
415          new BinaryFormatter();
[3578]416        Logger.Debug("STARTED: Deserializing the stream");
[1939]417        ResponsePlugin response = (ResponsePlugin)formatter.Deserialize(stream);
[3578]418        Logger.Debug("ENDED: Deserializing the stream");
419        if (stream != null)
420          stream.Dispose();       
[1635]421        return response.Plugins;       
[1450]422      }
423      catch (Exception e) {
424        HandleNetworkError(e);
425        return null;
426      }
427    }
428
[1635]429    public void Logout(Guid guid) {
430      try {
[3578]431        Logger.Debug("STARTED: Logout");
[1635]432        proxy.Logout(guid);
[3578]433        Logger.Debug("ENDED: Logout");
[1635]434      }
435      catch (Exception e) {
436        HandleNetworkError(e);
437      }
438    }
[3203]439
440    public ResponseCalendar GetCalendarSync(Guid clientId) {
441      try {
[3578]442        Logger.Debug("STARTED: Syncing Calendars");
443        ResponseCalendar cal = proxy.GetCalendar(clientId);
444        Logger.Debug("ENDED: Syncing Calendars");
445        return cal;
[3203]446      }
447      catch (Exception e) {
448        HandleNetworkError(e);
449        return null;
450      }
451    }
452
453    public Response SetCalendarStatus (Guid clientId, CalendarState state) {
454      try {
[3578]455        Logger.Debug("STARTED: Setting Calendar status to: " + state);
456        Response resp = proxy.SetCalendarStatus(clientId, state);
457        Logger.Debug("ENDED: Setting Calendar status to: " + state);
458        return resp;
[3203]459      } catch (Exception e) {
460        HandleNetworkError(e);
461        return null;
462      }
463    }
464
[923]465  }
466}
Note: See TracBrowser for help on using the repository browser.