1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,367 @@ 1.4 +/* 1.5 + * ==================================================================== 1.6 + * 1.7 + * Licensed to the Apache Software Foundation (ASF) under one or more 1.8 + * contributor license agreements. See the NOTICE file distributed with 1.9 + * this work for additional information regarding copyright ownership. 1.10 + * The ASF licenses this file to You under the Apache License, Version 2.0 1.11 + * (the "License"); you may not use this file except in compliance with 1.12 + * the License. You may obtain a copy of the License at 1.13 + * 1.14 + * http://www.apache.org/licenses/LICENSE-2.0 1.15 + * 1.16 + * Unless required by applicable law or agreed to in writing, software 1.17 + * distributed under the License is distributed on an "AS IS" BASIS, 1.18 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.19 + * See the License for the specific language governing permissions and 1.20 + * limitations under the License. 1.21 + * ==================================================================== 1.22 + * 1.23 + * This software consists of voluntary contributions made by many 1.24 + * individuals on behalf of the Apache Software Foundation. For more 1.25 + * information on the Apache Software Foundation, please see 1.26 + * <http://www.apache.org/>. 1.27 + * 1.28 + */ 1.29 + 1.30 +package ch.boye.httpclientandroidlib.impl.conn.tsccm; 1.31 + 1.32 +import java.io.IOException; 1.33 +import java.util.concurrent.TimeUnit; 1.34 + 1.35 +import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog; 1.36 +/* LogFactory removed by HttpClient for Android script. */ 1.37 +import ch.boye.httpclientandroidlib.annotation.ThreadSafe; 1.38 +import ch.boye.httpclientandroidlib.conn.params.ConnPerRouteBean; 1.39 +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; 1.40 +import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry; 1.41 +import ch.boye.httpclientandroidlib.conn.ClientConnectionManager; 1.42 +import ch.boye.httpclientandroidlib.conn.ClientConnectionOperator; 1.43 +import ch.boye.httpclientandroidlib.conn.ClientConnectionRequest; 1.44 +import ch.boye.httpclientandroidlib.conn.ConnectionPoolTimeoutException; 1.45 +import ch.boye.httpclientandroidlib.conn.ManagedClientConnection; 1.46 +import ch.boye.httpclientandroidlib.conn.OperatedClientConnection; 1.47 +import ch.boye.httpclientandroidlib.params.HttpParams; 1.48 +import ch.boye.httpclientandroidlib.impl.conn.DefaultClientConnectionOperator; 1.49 +import ch.boye.httpclientandroidlib.impl.conn.SchemeRegistryFactory; 1.50 + 1.51 +/** 1.52 + * Manages a pool of {@link OperatedClientConnection client connections} and 1.53 + * is able to service connection requests from multiple execution threads. 1.54 + * Connections are pooled on a per route basis. A request for a route which 1.55 + * already the manager has persistent connections for available in the pool 1.56 + * will be services by leasing a connection from the pool rather than 1.57 + * creating a brand new connection. 1.58 + * <p> 1.59 + * ThreadSafeClientConnManager maintains a maximum limit of connection on 1.60 + * a per route basis and in total. Per default this implementation will 1.61 + * create no more than than 2 concurrent connections per given route 1.62 + * and no more 20 connections in total. For many real-world applications 1.63 + * these limits may prove too constraining, especially if they use HTTP 1.64 + * as a transport protocol for their services. Connection limits, however, 1.65 + * can be adjusted using HTTP parameters. 1.66 + * 1.67 + * @since 4.0 1.68 + */ 1.69 +@ThreadSafe 1.70 +public class ThreadSafeClientConnManager implements ClientConnectionManager { 1.71 + 1.72 + public HttpClientAndroidLog log; 1.73 + 1.74 + /** The schemes supported by this connection manager. */ 1.75 + protected final SchemeRegistry schemeRegistry; // @ThreadSafe 1.76 + 1.77 + @Deprecated 1.78 + protected final AbstractConnPool connectionPool; 1.79 + 1.80 + /** The pool of connections being managed. */ 1.81 + protected final ConnPoolByRoute pool; 1.82 + 1.83 + /** The operator for opening and updating connections. */ 1.84 + protected final ClientConnectionOperator connOperator; // DefaultClientConnectionOperator is @ThreadSafe 1.85 + 1.86 + protected final ConnPerRouteBean connPerRoute; 1.87 + 1.88 + /** 1.89 + * Creates a new thread safe connection manager. 1.90 + * 1.91 + * @param schreg the scheme registry. 1.92 + */ 1.93 + public ThreadSafeClientConnManager(final SchemeRegistry schreg) { 1.94 + this(schreg, -1, TimeUnit.MILLISECONDS); 1.95 + } 1.96 + 1.97 + /** 1.98 + * @since 4.1 1.99 + */ 1.100 + public ThreadSafeClientConnManager() { 1.101 + this(SchemeRegistryFactory.createDefault()); 1.102 + } 1.103 + 1.104 + /** 1.105 + * Creates a new thread safe connection manager. 1.106 + * 1.107 + * @param schreg the scheme registry. 1.108 + * @param connTTL max connection lifetime, <=0 implies "infinity" 1.109 + * @param connTTLTimeUnit TimeUnit of connTTL 1.110 + * 1.111 + * @since 4.1 1.112 + */ 1.113 + public ThreadSafeClientConnManager(final SchemeRegistry schreg, 1.114 + long connTTL, TimeUnit connTTLTimeUnit) { 1.115 + super(); 1.116 + if (schreg == null) { 1.117 + throw new IllegalArgumentException("Scheme registry may not be null"); 1.118 + } 1.119 + this.log = new HttpClientAndroidLog(getClass()); 1.120 + this.schemeRegistry = schreg; 1.121 + this.connPerRoute = new ConnPerRouteBean(); 1.122 + this.connOperator = createConnectionOperator(schreg); 1.123 + this.pool = createConnectionPool(connTTL, connTTLTimeUnit) ; 1.124 + this.connectionPool = this.pool; 1.125 + } 1.126 + 1.127 + /** 1.128 + * Creates a new thread safe connection manager. 1.129 + * 1.130 + * @param params the parameters for this manager. 1.131 + * @param schreg the scheme registry. 1.132 + * 1.133 + * @deprecated use {@link ThreadSafeClientConnManager#ThreadSafeClientConnManager(SchemeRegistry)} 1.134 + */ 1.135 + @Deprecated 1.136 + public ThreadSafeClientConnManager(HttpParams params, 1.137 + SchemeRegistry schreg) { 1.138 + if (schreg == null) { 1.139 + throw new IllegalArgumentException("Scheme registry may not be null"); 1.140 + } 1.141 + this.log = new HttpClientAndroidLog(getClass()); 1.142 + this.schemeRegistry = schreg; 1.143 + this.connPerRoute = new ConnPerRouteBean(); 1.144 + this.connOperator = createConnectionOperator(schreg); 1.145 + this.pool = (ConnPoolByRoute) createConnectionPool(params) ; 1.146 + this.connectionPool = this.pool; 1.147 + } 1.148 + 1.149 + @Override 1.150 + protected void finalize() throws Throwable { 1.151 + try { 1.152 + shutdown(); 1.153 + } finally { 1.154 + super.finalize(); 1.155 + } 1.156 + } 1.157 + 1.158 + /** 1.159 + * Hook for creating the connection pool. 1.160 + * 1.161 + * @return the connection pool to use 1.162 + * 1.163 + * @deprecated use #createConnectionPool(long, TimeUnit)) 1.164 + */ 1.165 + @Deprecated 1.166 + protected AbstractConnPool createConnectionPool(final HttpParams params) { 1.167 + return new ConnPoolByRoute(connOperator, params); 1.168 + } 1.169 + 1.170 + /** 1.171 + * Hook for creating the connection pool. 1.172 + * 1.173 + * @return the connection pool to use 1.174 + * 1.175 + * @since 4.1 1.176 + */ 1.177 + protected ConnPoolByRoute createConnectionPool(long connTTL, TimeUnit connTTLTimeUnit) { 1.178 + return new ConnPoolByRoute(connOperator, connPerRoute, 20, connTTL, connTTLTimeUnit); 1.179 + } 1.180 + 1.181 + /** 1.182 + * Hook for creating the connection operator. 1.183 + * It is called by the constructor. 1.184 + * Derived classes can override this method to change the 1.185 + * instantiation of the operator. 1.186 + * The default implementation here instantiates 1.187 + * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}. 1.188 + * 1.189 + * @param schreg the scheme registry. 1.190 + * 1.191 + * @return the connection operator to use 1.192 + */ 1.193 + protected ClientConnectionOperator 1.194 + createConnectionOperator(SchemeRegistry schreg) { 1.195 + 1.196 + return new DefaultClientConnectionOperator(schreg);// @ThreadSafe 1.197 + } 1.198 + 1.199 + public SchemeRegistry getSchemeRegistry() { 1.200 + return this.schemeRegistry; 1.201 + } 1.202 + 1.203 + public ClientConnectionRequest requestConnection( 1.204 + final HttpRoute route, 1.205 + final Object state) { 1.206 + 1.207 + final PoolEntryRequest poolRequest = pool.requestPoolEntry( 1.208 + route, state); 1.209 + 1.210 + return new ClientConnectionRequest() { 1.211 + 1.212 + public void abortRequest() { 1.213 + poolRequest.abortRequest(); 1.214 + } 1.215 + 1.216 + public ManagedClientConnection getConnection( 1.217 + long timeout, TimeUnit tunit) throws InterruptedException, 1.218 + ConnectionPoolTimeoutException { 1.219 + if (route == null) { 1.220 + throw new IllegalArgumentException("Route may not be null."); 1.221 + } 1.222 + 1.223 + if (log.isDebugEnabled()) { 1.224 + log.debug("Get connection: " + route + ", timeout = " + timeout); 1.225 + } 1.226 + 1.227 + BasicPoolEntry entry = poolRequest.getPoolEntry(timeout, tunit); 1.228 + return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry); 1.229 + } 1.230 + 1.231 + }; 1.232 + 1.233 + } 1.234 + 1.235 + public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) { 1.236 + 1.237 + if (!(conn instanceof BasicPooledConnAdapter)) { 1.238 + throw new IllegalArgumentException 1.239 + ("Connection class mismatch, " + 1.240 + "connection not obtained from this manager."); 1.241 + } 1.242 + BasicPooledConnAdapter hca = (BasicPooledConnAdapter) conn; 1.243 + if ((hca.getPoolEntry() != null) && (hca.getManager() != this)) { 1.244 + throw new IllegalArgumentException 1.245 + ("Connection not obtained from this manager."); 1.246 + } 1.247 + synchronized (hca) { 1.248 + BasicPoolEntry entry = (BasicPoolEntry) hca.getPoolEntry(); 1.249 + if (entry == null) { 1.250 + return; 1.251 + } 1.252 + try { 1.253 + // make sure that the response has been read completely 1.254 + if (hca.isOpen() && !hca.isMarkedReusable()) { 1.255 + // In MTHCM, there would be a call to 1.256 + // SimpleHttpConnectionManager.finishLastResponse(conn); 1.257 + // Consuming the response is handled outside in 4.0. 1.258 + 1.259 + // make sure this connection will not be re-used 1.260 + // Shut down rather than close, we might have gotten here 1.261 + // because of a shutdown trigger. 1.262 + // Shutdown of the adapter also clears the tracked route. 1.263 + hca.shutdown(); 1.264 + } 1.265 + } catch (IOException iox) { 1.266 + if (log.isDebugEnabled()) 1.267 + log.debug("Exception shutting down released connection.", 1.268 + iox); 1.269 + } finally { 1.270 + boolean reusable = hca.isMarkedReusable(); 1.271 + if (log.isDebugEnabled()) { 1.272 + if (reusable) { 1.273 + log.debug("Released connection is reusable."); 1.274 + } else { 1.275 + log.debug("Released connection is not reusable."); 1.276 + } 1.277 + } 1.278 + hca.detach(); 1.279 + pool.freeEntry(entry, reusable, validDuration, timeUnit); 1.280 + } 1.281 + } 1.282 + } 1.283 + 1.284 + public void shutdown() { 1.285 + log.debug("Shutting down"); 1.286 + pool.shutdown(); 1.287 + } 1.288 + 1.289 + /** 1.290 + * Gets the total number of pooled connections for the given route. 1.291 + * This is the total number of connections that have been created and 1.292 + * are still in use by this connection manager for the route. 1.293 + * This value will not exceed the maximum number of connections per host. 1.294 + * 1.295 + * @param route the route in question 1.296 + * 1.297 + * @return the total number of pooled connections for that route 1.298 + */ 1.299 + public int getConnectionsInPool(final HttpRoute route) { 1.300 + return pool.getConnectionsInPool(route); 1.301 + } 1.302 + 1.303 + /** 1.304 + * Gets the total number of pooled connections. This is the total number of 1.305 + * connections that have been created and are still in use by this connection 1.306 + * manager. This value will not exceed the maximum number of connections 1.307 + * in total. 1.308 + * 1.309 + * @return the total number of pooled connections 1.310 + */ 1.311 + public int getConnectionsInPool() { 1.312 + return pool.getConnectionsInPool(); 1.313 + } 1.314 + 1.315 + public void closeIdleConnections(long idleTimeout, TimeUnit tunit) { 1.316 + if (log.isDebugEnabled()) { 1.317 + log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); 1.318 + } 1.319 + pool.closeIdleConnections(idleTimeout, tunit); 1.320 + } 1.321 + 1.322 + public void closeExpiredConnections() { 1.323 + log.debug("Closing expired connections"); 1.324 + pool.closeExpiredConnections(); 1.325 + } 1.326 + 1.327 + /** 1.328 + * since 4.1 1.329 + */ 1.330 + public int getMaxTotal() { 1.331 + return pool.getMaxTotalConnections(); 1.332 + } 1.333 + 1.334 + /** 1.335 + * since 4.1 1.336 + */ 1.337 + public void setMaxTotal(int max) { 1.338 + pool.setMaxTotalConnections(max); 1.339 + } 1.340 + 1.341 + /** 1.342 + * @since 4.1 1.343 + */ 1.344 + public int getDefaultMaxPerRoute() { 1.345 + return connPerRoute.getDefaultMaxPerRoute(); 1.346 + } 1.347 + 1.348 + /** 1.349 + * @since 4.1 1.350 + */ 1.351 + public void setDefaultMaxPerRoute(int max) { 1.352 + connPerRoute.setDefaultMaxPerRoute(max); 1.353 + } 1.354 + 1.355 + /** 1.356 + * @since 4.1 1.357 + */ 1.358 + public int getMaxForRoute(final HttpRoute route) { 1.359 + return connPerRoute.getMaxForRoute(route); 1.360 + } 1.361 + 1.362 + /** 1.363 + * @since 4.1 1.364 + */ 1.365 + public void setMaxForRoute(final HttpRoute route, int max) { 1.366 + connPerRoute.setMaxForRoute(route, max); 1.367 + } 1.368 + 1.369 +} 1.370 +