1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package gnu.hylafax.pool;
24
25 import gnu.hylafax.Client;
26
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Iterator;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
36
37 public class ClientPool implements gnu.hylafax.ClientPool {
38
39 private final static Log log = LogFactory.getLog(ClientPool.class);
40
41 private boolean blocked = false;
42
43 private HashMap clientMap;
44
45 private LinkedQueue clients;
46
47 private ClientPoolConfiguration configuration;
48
49 private ArrayList creationTimes;
50
51 private boolean logClientCreationTimes = true;
52
53 private Object mutex = new Object();
54
55 private int size = 0;
56
57 private boolean stopped = false;
58
59 private int totalSize = 0;
60
61 private HashSet workingClients;
62
63 private HashSet workingClientsToClose;
64
65 private int workingSize = 0;
66
67 public ClientPool(ClientPoolConfiguration configuration) {
68 this.configuration = configuration;
69 clients = new LinkedQueue();
70 clientMap = new HashMap();
71 workingClients = new HashSet();
72 workingClientsToClose = new HashSet();
73 creationTimes = new ArrayList();
74 }
75
76 private synchronized boolean addClient() throws ClientPoolException {
77 log.debug("Trying To Create Client, Total Connections: " + totalSize
78 + ", Max Allowed: " + getConfiguration().getMaxPoolSize());
79 boolean maximumCapacityReached = getConfiguration().getMaxPoolSize() <= totalSize
80 && getConfiguration().getMaxPoolSize() != 0
81 && getConfiguration().isPooling();
82 if (maximumCapacityReached) {
83 log.debug("Maximum Clients Reached.");
84 return false;
85 }
86
87 PooledClient client = createClient();
88 log.debug("Client Created.");
89
90 put(client);
91 clientMap.put(client, client);
92 totalSize++;
93
94 return true;
95 }
96
97 private PooledClient createClient() throws ClientPoolException {
98 return openClient(new HylaFAXPooledClient(this));
99 }
100
101 private void destroyClient(PooledClient client) throws ClientPoolException {
102 try {
103 client.destroy();
104 } catch (Exception e) {
105 throw new ClientPoolException("Could Not Destroy Client: "
106 + e.getMessage());
107 } finally {
108
109
110 totalSize--;
111 workingClients.remove(client);
112 clientMap.remove(client);
113 }
114 }
115
116 public long getAverageClientCreationTime() {
117 if (creationTimes.size() > 0) {
118 long average = 0;
119 for (int count = 0; count < creationTimes.size(); count++) {
120 average += ((Long) creationTimes.get(count)).longValue();
121 }
122 return average / creationTimes.size();
123 }
124 return -1;
125 }
126
127 public long getBlockingTimeout() {
128 return getConfiguration().getBlockingTimeout();
129 }
130
131 public Client getClient() throws ClientPoolException {
132
133 long startTime = System.currentTimeMillis();
134
135 log.debug("Wants A Client.");
136
137 PooledClient client = null;
138
139 try {
140
141 synchronized (mutex) {
142 if (clients.isEmpty()) {
143 while (client == null) {
144 if (!keepBlocking(startTime)) {
145 ClientPoolException e = new ClientPoolException(
146 "Could Not Obtain Client During Blocking Timeout ("
147 + getConfiguration()
148 .getBlockingTimeout()
149 + " ms)");
150 throw e;
151 }
152
153 boolean clientAdded = false;
154 try {
155 clientAdded = addClient();
156 } catch (ClientPoolException e) {
157 log.warn("Could Not Create Connection: "
158 + e.getMessage());
159 }
160
161 if (!clientAdded) {
162 log.warn("Pool Is Empty And Will Block Here.");
163 blocked = true;
164 }
165
166 client = (PooledClient) clients.poll(getConfiguration()
167 .getRetryInterval());
168 if (client == null)
169 log.warn("No Clients Available.");
170 else if (!clientAdded)
171 log.info("Obtained Connection.");
172 }
173
174 } else {
175 client = (PooledClient) clients.take();
176 }
177 }
178 } catch (InterruptedException e) {
179 throw new ClientPoolException(
180 "Interrupted Thread and No Free Connection Available.");
181 }
182
183 size--;
184
185 ((HylaFAXPooledClient) client).setWorking(true);
186 workingClients.add(client);
187
188 log.debug("Got Client.");
189
190 return client;
191 }
192
193 public HashMap getClientMap() {
194 return clientMap;
195 }
196
197 public ClientPoolConfiguration getConfiguration() {
198 return configuration;
199 }
200
201 public int getMaxPoolSize() {
202 return getConfiguration().getMaxPoolSize();
203 }
204
205 public int getMinPoolSize() {
206 return getConfiguration().getMinPoolSize();
207 }
208
209 public long getNoopInterval() {
210 return getConfiguration().getMaxNoopTime();
211 }
212
213 public int getSize() {
214 return size;
215 }
216
217 public int getTotalSize() {
218 return totalSize;
219 }
220
221 public String getUserName() {
222 return getConfiguration().getUserName();
223 }
224
225 public int getWorkingSize() {
226 return workingSize;
227 }
228
229 public boolean isLogClientCreationTimes() {
230 return logClientCreationTimes;
231 }
232
233 public boolean isStopped() {
234 return stopped;
235 }
236
237 public boolean keepBlocking(long startTime) {
238 return System.currentTimeMillis() - startTime < getConfiguration()
239 .getBlockingTimeout();
240 }
241
242 PooledClient openClient(HylaFAXPooledClient client)
243 throws ClientPoolException {
244 try {
245 long startTime = System.currentTimeMillis();
246
247 ClientPoolConfiguration config = getConfiguration();
248
249 if (config.getHost() != null && config.getPort() != -1)
250 client.poolOpen(config.getHost(), config.getPort());
251 else if (config.getHost() != null)
252 client.poolOpen(config.getHost());
253 else
254 client.poolOpen();
255
256 if (config.getUserName() != null)
257 client.poolUser(config.getUserName());
258
259 if (config.getPassword() != null)
260 client.poolPass(config.getPassword());
261
262 if (config.getAdminPassword() != null)
263 client.poolAdmin(config.getAdminPassword());
264
265 if (config.getTimeZone() != null)
266 client.poolTzone(config.getTimeZone());
267
268 if (isLogClientCreationTimes())
269 creationTimes.add(new Long(System.currentTimeMillis()
270 - startTime));
271
272 client.setPassive(true);
273 client.start();
274 return client;
275 } catch (Exception e) {
276 throw new ClientPoolException(e.getMessage());
277 }
278 }
279
280 public void put(PooledClient client) throws ClientPoolException {
281 try {
282 if (!client.isValid())
283 workingClientsToClose.add(client);
284 ((HylaFAXPooledClient) client).setWorking(false);
285
286
287
288
289 if (blocked)
290 log.warn("Will Be Unblocked");
291
292 if (getConfiguration().isPooling()) {
293 if (workingClientsToClose.remove(client)) {
294 destroyClient(client);
295 addClient();
296 } else {
297 clients.put(client);
298 size++;
299 }
300 }
301 blocked = false;
302
303
304 if (!getConfiguration().isPooling())
305 destroyClient(client);
306
307 log.debug("Released Client.");
308
309 } catch (InterruptedException e) {
310 log.warn("Was Interrupted.", e);
311 destroyClient(client);
312 } finally {
313
314
315 workingClients.remove(client);
316 }
317 }
318
319 public void restart() {
320
321 workingClientsToClose.addAll(workingClients);
322
323
324 while (getSize() > 0)
325 try {
326 PooledClient client = (PooledClient) getClient();
327 destroyClient(client);
328 } catch (ClientPoolException e) {
329 log.warn("Could Not Close Connection.", e);
330 }
331
332 while (getTotalSize() < getConfiguration().getMinPoolSize())
333 try {
334 addClient();
335 } catch (Exception e) {
336 log.warn("Could Not Add Connection.", e);
337 }
338 }
339
340 public void setBlockingTimeout(long blockingTimeout) {
341 getConfiguration().setBlockingTimeout(blockingTimeout);
342 }
343
344 public void setClientMap(HashMap clientMap) {
345 this.clientMap = clientMap;
346 }
347
348 public void setConfiguration(ClientPoolConfiguration configuration) {
349 this.configuration = configuration;
350 }
351
352 public void setLogClientCreationTimes(boolean logClientCreationTimes) {
353 this.logClientCreationTimes = logClientCreationTimes;
354 }
355
356 public void setMaxPoolSize(int maxPoolSize) {
357 getConfiguration().setMaxPoolSize(maxPoolSize);
358 }
359
360 public void setMinPoolSize(int minPoolSize) {
361 getConfiguration().setMinPoolSize(minPoolSize);
362 }
363
364 public void setNoopInterval(long noopInterval) {
365 getConfiguration().setMaxNoopTime(noopInterval);
366 }
367
368 public void setPassword(String password) {
369 getConfiguration().setPassword(password);
370 }
371
372 public void setSize(int size) {
373 this.size = size;
374 }
375
376 public void setTotalSize(int totalSize) {
377 this.totalSize = totalSize;
378 }
379
380 public void setUserName(String userName) {
381 getConfiguration().setUserName(userName);
382 }
383
384 public void setWorkingSize(int workingSize) {
385 this.workingSize = workingSize;
386 }
387
388 public void start() throws ClientPoolException {
389 stopped = false;
390 for (int i = 0; i < getConfiguration().getMinPoolSize(); i++) {
391 addClient();
392 }
393 }
394
395 public void stop() {
396 stopped = true;
397
398 Iterator iter = workingClients.iterator();
399 while (iter.hasNext()) {
400 try {
401 PooledClient item = (PooledClient) iter.next();
402 destroyClient(item);
403 } catch (ClientPoolException e) {
404 log.warn("Could Not Close Connection.", e);
405 }
406 }
407
408
409 while (getSize() > 0)
410 try {
411 PooledClient item = (PooledClient) getClient();
412 destroyClient(item);
413 } catch (ClientPoolException e) {
414 log.warn("Could Not Close Connection.", e);
415 }
416 totalSize = 0;
417 }
418
419 }