Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive/sources/HeuristicLab.Hive/HeuristicLab.Hive.Contracts/3.3/WcfServicePool.cs @ 4755

Last change on this file since 4755 was 4755, checked in by cneumuel, 14 years ago

#1260

  • applied new cloning mechanism
  • changed role names
File size: 5.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.ServiceModel;
24using HeuristicLab.Common;
25using HeuristicLab.Hive.Tracing;
26
27namespace HeuristicLab.Hive.Contracts {
28  public class WcfServicePool<T> {
29    private static object locker = new object();
30
31    private string hostAddress;
32    public string HostAddress {
33      get { return hostAddress; }
34      set {
35        if (hostAddress != value) {
36          hostAddress = value;
37          this.factory = null;
38        }
39      }
40    }
41
42    private string endpointName;
43
44    private string username;
45    public string Username {
46      get { return username; }
47      set {
48        if(username != value) {
49          username = value;
50          this.factory = null;
51        }
52      }
53    }
54
55    private string password;
56    public string Password {
57      set {
58        if (password != value) {
59          password = value;
60          this.factory = null;
61        }
62      }
63    }
64
65    private ChannelFactory<T> factory = null;
66    private Disposable<T> disposableService = null;
67    private int requestCount = 0;
68
69    public WcfServicePool(string username, string password, string endpointName) {
70      this.username = username;
71      this.password = password;
72      this.endpointName = endpointName;
73    }
74    public WcfServicePool(string hostAddress, string username, string password, string endpointName) : this(username, password, endpointName) {
75      this.hostAddress = hostAddress;
76    }
77
78    private T CreateFacade(string endpointName) {
79      lock (locker) {
80        try {
81          return CreateChannel(endpointName);
82        }
83        catch (EndpointNotFoundException ex) {
84          OnExceptionOccured(ex);
85        }
86        return default(T);
87      }
88    }
89
90    protected virtual T CreateChannel(string endpointName) {
91      if (factory == null) {
92        factory = new ChannelFactory<T>(endpointName);
93        if (!string.IsNullOrEmpty(hostAddress)) {
94          WcfSettings.SetEndpointAddress(factory.Endpoint, hostAddress);
95        }
96
97        factory.Credentials.UserName.UserName = username;
98        factory.Credentials.UserName.Password = password;
99      }
100     
101      return factory.CreateChannel();
102    }
103
104    public Disposable<T> GetService() {
105      lock (locker) {
106        requestCount++;
107        Logger.Debug("Request for ServiceProxy (count: " + requestCount + ")");
108        if (disposableService != null) {
109          if (GetServiceState() == CommunicationState.Faulted) {
110            DisposeService();
111          }
112        }
113        if (disposableService == null) {
114          disposableService = new Disposable<T>(CreateFacade(this.endpointName));
115          RegisterServiceEvents();
116        }       
117        return disposableService;
118      }
119    }
120
121    private void RegisterServiceEvents() {
122      disposableService.OnDisposing += new EventHandler(disposableService_OnDisposing);
123      ((ICommunicationObject)disposableService.Obj).Faulted += new EventHandler(WcfServicePool_Faulted);
124    }
125
126    private void DeregisterServiceEvents() {
127      disposableService.OnDisposing -= new EventHandler(disposableService_OnDisposing);
128      ((ICommunicationObject)disposableService.Obj).Faulted -= new EventHandler(WcfServicePool_Faulted);
129    }
130
131    private CommunicationState GetServiceState() {
132      return ((ICommunicationObject)disposableService.Obj).State;
133    }
134
135    void WcfServicePool_Faulted(object sender, EventArgs e) {
136      OnExceptionOccured(new CommunicationException(e.ToString()));
137    }
138
139    private void disposableService_OnDisposing(object sender, EventArgs e) {
140      DisposeService();
141    }
142
143    public void DisposeService() {
144      lock (locker) {
145        requestCount--;
146        Logger.Debug("Disposing ServiceProxy (count: " + requestCount + ")");
147        if (requestCount == 0) {
148          try {
149            DeregisterServiceEvents();
150            WcfSettings.DisposeWcfClient((ICommunicationObject)disposableService.Obj);
151          }
152          catch (Exception e) {
153            OnExceptionOccured(e);
154          }
155          finally {
156            disposableService = null;
157          }
158        } else if (requestCount < 0) {
159          throw new WcfServicePoolException("requestCount cannot be less than 0.");
160        }
161      }
162    }
163
164    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
165    private void OnExceptionOccured(Exception e) {
166      lock (locker) {
167        var handler = ExceptionOccured;
168        if (handler != null) handler(this, new EventArgs<Exception>(e));
169      }
170    }
171  }
172}
Note: See TracBrowser for help on using the repository browser.