mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java

branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
equal deleted inserted replaced
-1:000000000000 0:3f07c1ed81f3
1 /*
2 * ====================================================================
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ====================================================================
19 *
20 * This software consists of voluntary contributions made by many
21 * individuals on behalf of the Apache Software Foundation. For more
22 * information on the Apache Software Foundation, please see
23 * <http://www.apache.org/>.
24 *
25 */
26
27 package ch.boye.httpclientandroidlib.impl.conn.tsccm;
28
29 import java.io.IOException;
30 import java.util.concurrent.TimeUnit;
31
32 import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog;
33 /* LogFactory removed by HttpClient for Android script. */
34 import ch.boye.httpclientandroidlib.annotation.ThreadSafe;
35 import ch.boye.httpclientandroidlib.conn.params.ConnPerRouteBean;
36 import ch.boye.httpclientandroidlib.conn.routing.HttpRoute;
37 import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry;
38 import ch.boye.httpclientandroidlib.conn.ClientConnectionManager;
39 import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator;
40 import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest;
41 import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException;
42 import ch.boye.httpclientandroidlib.conn.ManagedClientConnection;
43 import ch.boye.httpclientandroidlib.conn.OperatedClientConnection;
44 import ch.boye.httpclientandroidlib.params.HttpParams;
45 import ch.boye.httpclientandroidlib.impl.conn.DefaultClientConnectionOperator;
46 import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory;
47
48 /**
49 * Manages a pool of {@link OperatedClientConnection client connections} and
50 * is able to service connection requests from multiple execution threads.
51 * Connections are pooled on a per route basis. A request for a route which
52 * already the manager has persistent connections for available in the pool
53 * will be services by leasing a connection from the pool rather than
54 * creating a brand new connection.
55 * <p>
56 * ThreadSafeClientConnManager maintains a maximum limit of connection on
57 * a per route basis and in total. Per default this implementation will
58 * create no more than than 2 concurrent connections per given route
59 * and no more 20 connections in total. For many real-world applications
60 * these limits may prove too constraining, especially if they use HTTP
61 * as a transport protocol for their services. Connection limits, however,
62 * can be adjusted using HTTP parameters.
63 *
64 * @since 4.0
65 */
66 @ThreadSafe
67 public class ThreadSafeClientConnManager implements ClientConnectionManager {
68
69 public HttpClientAndroidLog log;
70
71 /** The schemes supported by this connection manager. */
72 protected final SchemeRegistry schemeRegistry; // @ThreadSafe
73
74 @Deprecated
75 protected final AbstractConnPool connectionPool;
76
77 /** The pool of connections being managed. */
78 protected final ConnPoolByRoute pool;
79
80 /** The operator for opening and updating connections. */
81 protected final ClientConnectionOperator connOperator; // DefaultClientConnectionOperator is @ThreadSafe
82
83 protected final ConnPerRouteBean connPerRoute;
84
85 /**
86 * Creates a new thread safe connection manager.
87 *
88 * @param schreg the scheme registry.
89 */
90 public ThreadSafeClientConnManager(final SchemeRegistry schreg) {
91 this(schreg, -1, TimeUnit.MILLISECONDS);
92 }
93
94 /**
95 * @since 4.1
96 */
97 public ThreadSafeClientConnManager() {
98 this(SchemeRegistryFactory.createDefault());
99 }
100
101 /**
102 * Creates a new thread safe connection manager.
103 *
104 * @param schreg the scheme registry.
105 * @param connTTL max connection lifetime, <=0 implies "infinity"
106 * @param connTTLTimeUnit TimeUnit of connTTL
107 *
108 * @since 4.1
109 */
110 public ThreadSafeClientConnManager(final SchemeRegistry schreg,
111 long connTTL, TimeUnit connTTLTimeUnit) {
112 super();
113 if (schreg == null) {
114 throw new IllegalArgumentException("Scheme registry may not be null");
115 }
116 this.log = new HttpClientAndroidLog(getClass());
117 this.schemeRegistry = schreg;
118 this.connPerRoute = new ConnPerRouteBean();
119 this.connOperator = createConnectionOperator(schreg);
120 this.pool = createConnectionPool(connTTL, connTTLTimeUnit) ;
121 this.connectionPool = this.pool;
122 }
123
124 /**
125 * Creates a new thread safe connection manager.
126 *
127 * @param params the parameters for this manager.
128 * @param schreg the scheme registry.
129 *
130 * @deprecated use {@link ThreadSafeClientConnManager#ThreadSafeClientConnManager(SchemeRegistry)}
131 */
132 @Deprecated
133 public ThreadSafeClientConnManager(HttpParams params,
134 SchemeRegistry schreg) {
135 if (schreg == null) {
136 throw new IllegalArgumentException("Scheme registry may not be null");
137 }
138 this.log = new HttpClientAndroidLog(getClass());
139 this.schemeRegistry = schreg;
140 this.connPerRoute = new ConnPerRouteBean();
141 this.connOperator = createConnectionOperator(schreg);
142 this.pool = (ConnPoolByRoute) createConnectionPool(params) ;
143 this.connectionPool = this.pool;
144 }
145
146 @Override
147 protected void finalize() throws Throwable {
148 try {
149 shutdown();
150 } finally {
151 super.finalize();
152 }
153 }
154
155 /**
156 * Hook for creating the connection pool.
157 *
158 * @return the connection pool to use
159 *
160 * @deprecated use #createConnectionPool(long, TimeUnit))
161 */
162 @Deprecated
163 protected AbstractConnPool createConnectionPool(final HttpParams params) {
164 return new ConnPoolByRoute(connOperator, params);
165 }
166
167 /**
168 * Hook for creating the connection pool.
169 *
170 * @return the connection pool to use
171 *
172 * @since 4.1
173 */
174 protected ConnPoolByRoute createConnectionPool(long connTTL, TimeUnit connTTLTimeUnit) {
175 return new ConnPoolByRoute(connOperator, connPerRoute, 20, connTTL, connTTLTimeUnit);
176 }
177
178 /**
179 * Hook for creating the connection operator.
180 * It is called by the constructor.
181 * Derived classes can override this method to change the
182 * instantiation of the operator.
183 * The default implementation here instantiates
184 * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
185 *
186 * @param schreg the scheme registry.
187 *
188 * @return the connection operator to use
189 */
190 protected ClientConnectionOperator
191 createConnectionOperator(SchemeRegistry schreg) {
192
193 return new DefaultClientConnectionOperator(schreg);// @ThreadSafe
194 }
195
196 public SchemeRegistry getSchemeRegistry() {
197 return this.schemeRegistry;
198 }
199
200 public ClientConnectionRequest requestConnection(
201 final HttpRoute route,
202 final Object state) {
203
204 final PoolEntryRequest poolRequest = pool.requestPoolEntry(
205 route, state);
206
207 return new ClientConnectionRequest() {
208
209 public void abortRequest() {
210 poolRequest.abortRequest();
211 }
212
213 public ManagedClientConnection getConnection(
214 long timeout, TimeUnit tunit) throws InterruptedException,
215 ConnectionPoolTimeoutException {
216 if (route == null) {
217 throw new IllegalArgumentException("Route may not be null.");
218 }
219
220 if (log.isDebugEnabled()) {
221 log.debug("Get connection: " + route + ", timeout = " + timeout);
222 }
223
224 BasicPoolEntry entry = poolRequest.getPoolEntry(timeout, tunit);
225 return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry);
226 }
227
228 };
229
230 }
231
232 public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
233
234 if (!(conn instanceof BasicPooledConnAdapter)) {
235 throw new IllegalArgumentException
236 ("Connection class mismatch, " +
237 "connection not obtained from this manager.");
238 }
239 BasicPooledConnAdapter hca = (BasicPooledConnAdapter) conn;
240 if ((hca.getPoolEntry() != null) && (hca.getManager() != this)) {
241 throw new IllegalArgumentException
242 ("Connection not obtained from this manager.");
243 }
244 synchronized (hca) {
245 BasicPoolEntry entry = (BasicPoolEntry) hca.getPoolEntry();
246 if (entry == null) {
247 return;
248 }
249 try {
250 // make sure that the response has been read completely
251 if (hca.isOpen() && !hca.isMarkedReusable()) {
252 // In MTHCM, there would be a call to
253 // SimpleHttpConnectionManager.finishLastResponse(conn);
254 // Consuming the response is handled outside in 4.0.
255
256 // make sure this connection will not be re-used
257 // Shut down rather than close, we might have gotten here
258 // because of a shutdown trigger.
259 // Shutdown of the adapter also clears the tracked route.
260 hca.shutdown();
261 }
262 } catch (IOException iox) {
263 if (log.isDebugEnabled())
264 log.debug("Exception shutting down released connection.",
265 iox);
266 } finally {
267 boolean reusable = hca.isMarkedReusable();
268 if (log.isDebugEnabled()) {
269 if (reusable) {
270 log.debug("Released connection is reusable.");
271 } else {
272 log.debug("Released connection is not reusable.");
273 }
274 }
275 hca.detach();
276 pool.freeEntry(entry, reusable, validDuration, timeUnit);
277 }
278 }
279 }
280
281 public void shutdown() {
282 log.debug("Shutting down");
283 pool.shutdown();
284 }
285
286 /**
287 * Gets the total number of pooled connections for the given route.
288 * This is the total number of connections that have been created and
289 * are still in use by this connection manager for the route.
290 * This value will not exceed the maximum number of connections per host.
291 *
292 * @param route the route in question
293 *
294 * @return the total number of pooled connections for that route
295 */
296 public int getConnectionsInPool(final HttpRoute route) {
297 return pool.getConnectionsInPool(route);
298 }
299
300 /**
301 * Gets the total number of pooled connections. This is the total number of
302 * connections that have been created and are still in use by this connection
303 * manager. This value will not exceed the maximum number of connections
304 * in total.
305 *
306 * @return the total number of pooled connections
307 */
308 public int getConnectionsInPool() {
309 return pool.getConnectionsInPool();
310 }
311
312 public void closeIdleConnections(long idleTimeout, TimeUnit tunit) {
313 if (log.isDebugEnabled()) {
314 log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit);
315 }
316 pool.closeIdleConnections(idleTimeout, tunit);
317 }
318
319 public void closeExpiredConnections() {
320 log.debug("Closing expired connections");
321 pool.closeExpiredConnections();
322 }
323
324 /**
325 * since 4.1
326 */
327 public int getMaxTotal() {
328 return pool.getMaxTotalConnections();
329 }
330
331 /**
332 * since 4.1
333 */
334 public void setMaxTotal(int max) {
335 pool.setMaxTotalConnections(max);
336 }
337
338 /**
339 * @since 4.1
340 */
341 public int getDefaultMaxPerRoute() {
342 return connPerRoute.getDefaultMaxPerRoute();
343 }
344
345 /**
346 * @since 4.1
347 */
348 public void setDefaultMaxPerRoute(int max) {
349 connPerRoute.setDefaultMaxPerRoute(max);
350 }
351
352 /**
353 * @since 4.1
354 */
355 public int getMaxForRoute(final HttpRoute route) {
356 return connPerRoute.getMaxForRoute(route);
357 }
358
359 /**
360 * @since 4.1
361 */
362 public void setMaxForRoute(final HttpRoute route, int max) {
363 connPerRoute.setMaxForRoute(route, max);
364 }
365
366 }
367

mercurial