KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xsocket > stream > NonBlockingConnectionPool


1 // $Id: BlockingConnection.java 1134 2007-04-05 17:44:43Z grro $
2
/*
3  * Copyright (c) xsocket.org, 2006 - 2007. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
20  * The latest copy of this software may be found on http://www.xsocket.org/
21  */

22 package org.xsocket.stream;
23
24 import java.io.IOException JavaDoc;
25 import java.lang.annotation.Inherited JavaDoc;
26 import java.net.InetAddress JavaDoc;
27 import java.net.InetSocketAddress JavaDoc;
28 import java.nio.BufferUnderflowException JavaDoc;
29 import java.nio.ByteBuffer JavaDoc;
30 import java.nio.channels.WritableByteChannel JavaDoc;
31 import java.util.concurrent.Executor JavaDoc;
32 import java.util.logging.Level JavaDoc;
33 import java.util.logging.Logger JavaDoc;
34
35 import org.xsocket.ClosedConnectionException;
36 import org.xsocket.MaxReadSizeExceededException;
37
38
39
40
41 /**
42  * A connection pool implementation. A connection pool will be used on the
43  * client-side, if connections for the same server (address) will be created
44  * in a serial manner in a sort period of time. By pooling such connections the overhead of establishing
45  * a connection will be avoided
46  * For pool management reasons, timeouts can be defined. The
47  * IdleTimeout defines the max idle time in the pool. After this time the
48  * free connection will be closed. In the same way, the max living time
49  * defines the timout of the connection. If a free connection exceeds
50  * this time, the connection will be closed. <br>
51  * Additional the max size of the active connections can be defined.
52  * If a connection is requested and the max limit of the active connection
53  * is reached, the request will be blocked until a connection becomes free
54  * or the maxWaitTime will be reached. <br>
55  *
56  * <pre>
57  * // create a connection pool with idle timeout 60 sec
58  * NonBlockingConnectionPool pool = new NonBlockingConnectionPool(60L * 1000L);
59  *
60  * INonBlockingCinnection con = null;
61  *
62  * try {
63  * // retrieve a connection (if no connection is in pool, a new one will be created)
64  * con = pool.getNonBlockingConnection(host, port);
65  * con.write("Hello");
66  * ...
67  *
68  * // always close the connection! (the connection will be returned into the connection pool)
69  * con.close();
70  *
71  * } catch (IOException) {
72  * if (con != null) {
73  * try {
74  * // if the connection is invalid -> destroy it (it will not return into the pool)
75  * pool.destroyConnection(con);
76  * } catch (Exception ignore) { }
77  * }
78  * }
79  * </pre>
80  *
81  * @author grro@xsocket.org
82  */

83 public final class NonBlockingConnectionPool extends AbstractConnectionPool {
84
85     private static final Logger JavaDoc LOG = Logger.getLogger(NonBlockingConnectionPool.class.getName());
86
87     public static final long UNLIMITED_TIMEOUT = AbstractConnectionPool.MAX_TIMEOUT;
88
89
90     /**
91      * constructor
92      *
93      * @param timeToIdleMillis the max idle time in the pool. After this time the free connection will be closed
94      */

95     public NonBlockingConnectionPool(long timeToIdleMillis) {
96         this(timeToIdleMillis, Integer.MAX_VALUE, NULL);
97     }
98
99
100     public NonBlockingConnectionPool(long timeToIdleMillis, int maxActive, long maxWaitTimeMillis) {
101         super(timeToIdleMillis, MAX_TIMEOUT, maxActive, maxWaitTimeMillis, MAX_SIZE);
102     }
103
104
105     /**
106      * get a pool connection for the given address. If no free connection is in the pool,
107      * a new one will be created <br> <br>
108      *
109      * This method is thread safe
110      *
111      * @param host the server address
112      * @param port the sever port
113      * @return the connection
114      * @throws WaitTimeoutException if the wait timeout has been reached (this will only been thrown if wait time has been set)
115      * @throws IOException if an exception occurs
116      */

117     public INonBlockingConnection getNonBlockingConnection(String JavaDoc host, int port) throws IOException JavaDoc, WaitTimeoutException {
118         return (INonBlockingConnection) getConnection(new InetSocketAddress JavaDoc(host, port), null);
119     }
120
121
122     /**
123      * get a pool connection for the given address. If no free connection is in the pool,
124      * a new one will be created <br> <br>
125      *
126      * This method is thread safe
127      *
128      * @param address the server address
129      * @param port the sever port
130      * @return the connection
131      * @throws WaitTimeoutException if the wait timeout has been reached (this will only been thrown if wait time has been set)
132      * @throws IOException if an exception occurs
133      */

134     public INonBlockingConnection getNonBlockingConnection(InetAddress JavaDoc address, int port) throws IOException JavaDoc, WaitTimeoutException {
135         return (INonBlockingConnection) getConnection(new InetSocketAddress JavaDoc(address, port), null);
136     }
137
138
139
140     /**
141      * get a pool connection for the given address. If no free connection is in the pool,
142      * a new one will be created <br> <br>
143      *
144      * This method is thread safe
145      *
146      * @param address the server address
147      * @param port the sever port
148      * @param appHandler the application handler (supported: IConnectHandler, IDisconnectHandler, IDataHandler and ITimeoutHandler)
149      * @return the connection
150      * @throws WaitTimeoutException if the wait timeout has been reached (this will only been thrown if wait time has been set)
151      * @throws IOException if an exception occurs
152      */

153     public INonBlockingConnection getNonBlockingConnection(InetAddress JavaDoc address, int port, IHandler appHandler) throws IOException JavaDoc, WaitTimeoutException {
154         return getNonBlockingConnection(address, port, appHandler, null);
155     }
156
157
158
159     /**
160      * get a pool connection for the given address. If no free connection is in the pool,
161      * a new one will be created <br> <br>
162      *
163      * This method is thread safe
164      *
165      * @param address the server address
166      * @param port the sever port
167      * @param appHandler the application handler (supported: IConnectHandler, IDisconnectHandler, IDataHandler and ITimeoutHandler)
168      * @param workerPool the worker pool to use
169      * @return the connection
170      * @throws WaitTimeoutException if the wait timeout has been reached (this will only been thrown if wait time has been set)
171      * @throws IOException if an exception occurs
172      */

173     public INonBlockingConnection getNonBlockingConnection(InetAddress JavaDoc address, int port, IHandler appHandler, Executor JavaDoc workerPool) throws IOException JavaDoc, WaitTimeoutException {
174         return (INonBlockingConnection) getConnection(new InetSocketAddress JavaDoc(address, port), appHandler, workerPool);
175     }
176
177
178     private INonBlockingConnection getConnection(InetSocketAddress JavaDoc address, IHandler appHandler, Executor JavaDoc workerPool) throws IOException JavaDoc, WaitTimeoutException {
179         PoolableNonBlockingConnection connection = (PoolableNonBlockingConnection) getConnection(address, workerPool);
180         if (connection != null) {
181             connection.setHandler(appHandler);
182             connection.notiyConnect();
183             return connection;
184         } else {
185             throw new IOException JavaDoc("couldn't create a connection to " + address);
186         }
187     }
188
189
190
191
192     /**
193      * {@link Inherited}
194      */

195     @Override JavaDoc
196     PoolableConnection createConnection(InetSocketAddress JavaDoc address, Executor JavaDoc workerPool) throws IOException JavaDoc {
197         if (workerPool != null) {
198             return new PoolableNonBlockingConnection(address, workerPool);
199         } else {
200             return new PoolableNonBlockingConnection(address);
201         }
202     }
203
204
205
206     private final class PoolableNonBlockingConnection extends PoolableConnection implements INonBlockingConnection {
207
208         public PoolableNonBlockingConnection(InetSocketAddress JavaDoc address) throws IOException JavaDoc {
209             super(NonBlockingConnectionPool.this, new NonBlockingConnection(address.getAddress(), address.getPort(), new HandlerProxy()), address);
210             getHandlerProxy().init(this);
211         }
212
213         public PoolableNonBlockingConnection(InetSocketAddress JavaDoc address, Executor JavaDoc workerPool) throws IOException JavaDoc {
214             super(NonBlockingConnectionPool.this, new NonBlockingConnection(address.getAddress(), address.getPort(), new HandlerProxy(), workerPool), address);
215             getHandlerProxy().init(this);
216         }
217
218         public INonBlockingConnection setOption(String JavaDoc name, Object JavaDoc value) throws IOException JavaDoc {
219             return getUnderlyingConnection().setOption(name, value);
220         }
221
222         void setHandler(IHandler handler) {
223             getHandlerProxy().setHandler(handler);
224         }
225
226         private HandlerProxy getHandlerProxy() {
227             return (HandlerProxy) getUnderlyingConnection().getAppHandler();
228         }
229
230         void notiyConnect() throws IOException JavaDoc {
231             HandlerProxy hdlProxy = (HandlerProxy) getUnderlyingConnection().getAppHandler();
232             hdlProxy.notifyConnect(getUnderlyingConnection());
233         }
234
235         @Override JavaDoc
236         void reset() throws IOException JavaDoc {
237             setHandler(null);
238
239             super.reset();
240         }
241
242         public void setFlushmode(FlushMode flushMode) {
243             getUnderlyingConnection().setFlushmode(flushMode);
244         }
245
246         public FlushMode getFlushmode() {
247             return getUnderlyingConnection().getFlushmode();
248         }
249
250         public void setWriteTransferRate(int bytesPerSecond) throws ClosedConnectionException, IOException JavaDoc {
251             getUnderlyingConnection().setWriteTransferRate(bytesPerSecond);
252         }
253
254         public ByteBuffer JavaDoc[] readAvailable() throws IOException JavaDoc, ClosedConnectionException {
255             return getUnderlyingConnection().readAvailable();
256         }
257
258         public boolean readAvailableByDelimiter(String JavaDoc delimiter, WritableByteChannel JavaDoc outputChannel) throws IOException JavaDoc, ClosedConnectionException {
259             return getUnderlyingConnection().readAvailableByDelimiter(delimiter, outputChannel);
260         }
261
262         public boolean readAvailableByDelimiter(String JavaDoc delimiter, String JavaDoc encoding, WritableByteChannel JavaDoc outputChannel) throws IOException JavaDoc, ClosedConnectionException {
263             return getUnderlyingConnection().readAvailableByDelimiter(delimiter, encoding, outputChannel);
264         }
265
266         public int getNumberOfAvailableBytes() {
267             return getUnderlyingConnection().getNumberOfAvailableBytes();
268         }
269
270         public int indexOf(String JavaDoc str) {
271             return getUnderlyingConnection().indexOf(str);
272         }
273
274         private NonBlockingConnection getUnderlyingConnection() {
275             return (NonBlockingConnection) getDelegee();
276         }
277     }
278
279
280     private static final class HandlerProxy implements IDataHandler, IDisconnectHandler, ITimeoutHandler {
281
282         private PoolableNonBlockingConnection poolableConnection = null;
283
284         private IHandler handler = null;
285         private boolean isDataHandler = false;
286         private boolean isConnectHandler = false;
287         private boolean isDisconnectHandler = false;
288         private boolean isTimeoutHandler = false;
289
290         void init(PoolableNonBlockingConnection poolableConnection) {
291             this.poolableConnection = poolableConnection;
292         }
293
294         void setHandler(IHandler handler) {
295             this.handler = handler;
296
297             if (handler != null) {
298                 isDataHandler = (handler instanceof IDataHandler);
299                 isConnectHandler = (handler instanceof IConnectHandler);
300                 isDisconnectHandler = (handler instanceof IDisconnectHandler);
301                 isTimeoutHandler = (handler instanceof ITimeoutHandler);
302             }
303         }
304
305
306         void notifyConnect(INonBlockingConnection connection) throws IOException JavaDoc {
307             if (isConnectHandler) {
308                 ((IConnectHandler) handler).onConnect(poolableConnection);
309             }
310         }
311
312         public boolean onData(INonBlockingConnection connection) throws IOException JavaDoc, BufferUnderflowException JavaDoc, MaxReadSizeExceededException {
313             if (isDataHandler) {
314                 ((IDataHandler) handler).onData(poolableConnection);
315             }
316             return true;
317         }
318
319
320         public boolean onDisconnect(INonBlockingConnection connection) throws IOException JavaDoc {
321             if (isDisconnectHandler) {
322                 ((IDisconnectHandler) handler).onDisconnect(poolableConnection);
323             }
324
325             poolableConnection.reallyClose();
326             return true;
327         }
328
329
330         public boolean onConnectionTimeout(INonBlockingConnection connection) throws IOException JavaDoc {
331             poolableConnection.setReuseable(false);
332
333             boolean isHandled = false;
334             if(isTimeoutHandler) {
335                 isHandled = ((ITimeoutHandler) handler).onConnectionTimeout(poolableConnection);
336             }
337
338             if (!isHandled) {
339                 poolableConnection.reallyClose();
340             }
341
342             return true;
343         }
344
345
346         public boolean onIdleTimeout(INonBlockingConnection connection) throws IOException JavaDoc {
347             poolableConnection.setReuseable(false);
348
349             if (LOG.isLoggable(Level.FINE)) {
350                 LOG.fine("idle timout occured for pooled connection " + poolableConnection.getId());
351             }
352
353             boolean isHandled = false;
354             if(isTimeoutHandler) {
355                 isHandled = ((ITimeoutHandler) handler).onIdleTimeout(poolableConnection);
356             }
357
358             if (!isHandled) {
359                 poolableConnection.reallyClose();
360             }
361
362             return true;
363         }
364     }
365 }
366
Popular Tags