You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2011/08/08 12:59:56 UTC
svn commit: r1154916 - in
/httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn:
HttpConnPool.java HttpPoolEntry.java ManagedClientConnectionImpl.java
PoolingClientConnectionManager.java
Author: olegk
Date: Mon Aug 8 10:59:55 2011
New Revision: 1154916
URL: http://svn.apache.org/viewvc?rev=1154916&view=rev
Log:
Redesign of connection management classes based on new pooling components from HttpCore
Added:
httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java (with props)
httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java (with props)
httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java (with props)
httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java (with props)
Added: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java?rev=1154916&view=auto
==============================================================================
--- httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java (added)
+++ httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java Mon Aug 8 10:59:55 2011
@@ -0,0 +1,78 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.impl.conn;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.logging.Log;
+import org.apache.http.HttpConnection;
+import org.apache.http.conn.OperatedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.pool.AbstractConnPool;
+
+/**
+ * @since 4.2
+ */
+class HttpConnPool extends AbstractConnPool<HttpRoute, OperatedClientConnection, HttpPoolEntry> {
+
+ private final Log log;
+ private final long timeToLive;
+ private final TimeUnit tunit;
+
+ public HttpConnPool(final Log log,
+ final int defaultMaxPerRoute, final int maxTotal,
+ final long timeToLive, final TimeUnit tunit) {
+ super(defaultMaxPerRoute, maxTotal);
+ this.log = log;
+ this.timeToLive = timeToLive;
+ this.tunit = tunit;
+ }
+
+ @Override
+ protected OperatedClientConnection createConnection(final HttpRoute route) throws IOException {
+ return new DefaultClientConnection();
+ }
+
+ @Override
+ protected HttpPoolEntry createEntry(final HttpRoute route, final OperatedClientConnection conn) {
+ return new HttpPoolEntry(this.log, route, conn, this.timeToLive, this.tunit);
+ }
+
+ @Override
+ protected void closeEntry(final HttpPoolEntry entry) {
+ HttpConnection conn = entry.getConnection();
+ try {
+ conn.shutdown();
+ } catch (IOException ex) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("I/O error shutting down connection", ex);
+ }
+ }
+ }
+
+}
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpConnPool.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java?rev=1154916&view=auto
==============================================================================
--- httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java (added)
+++ httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java Mon Aug 8 10:59:55 2011
@@ -0,0 +1,77 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.http.impl.conn;
+
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.logging.Log;
+import org.apache.http.conn.OperatedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.RouteTracker;
+import org.apache.http.pool.PoolEntry;
+
+/**
+ * @since 4.2
+ */
+class HttpPoolEntry extends PoolEntry<HttpRoute, OperatedClientConnection> {
+
+ private final Log log;
+ private final RouteTracker tracker;
+
+ public HttpPoolEntry(
+ final Log log,
+ final HttpRoute route,
+ final OperatedClientConnection conn,
+ final long timeToLive, final TimeUnit tunit) {
+ super(route, conn, timeToLive, tunit);
+ this.log = log;
+ this.tracker = new RouteTracker(route);
+ }
+
+ @Override
+ public boolean isExpired(long now) {
+ boolean expired = super.isExpired(now);
+ if (expired && this.log.isDebugEnabled()) {
+ this.log.debug("Connection " + this + " expired @ " + new Date(getExpiry()));
+ }
+ return expired;
+ }
+
+ RouteTracker getTracker() {
+ return this.tracker;
+ }
+
+ HttpRoute getPlannedRoute() {
+ return getRoute();
+ }
+
+ HttpRoute getEffectiveRoute() {
+ return this.tracker.toRoute();
+ }
+
+}
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/HttpPoolEntry.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java?rev=1154916&view=auto
==============================================================================
--- httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java (added)
+++ httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java Mon Aug 8 10:59:55 2011
@@ -0,0 +1,503 @@
+/*
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.conn;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.http.HttpConnectionMetrics;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.annotation.NotThreadSafe;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ClientConnectionOperator;
+import org.apache.http.conn.ManagedClientConnection;
+import org.apache.http.conn.OperatedClientConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.routing.RouteTracker;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+
+@NotThreadSafe
+class ManagedClientConnectionImpl implements ManagedClientConnection {
+
+ private final Lock lock;
+ private final ClientConnectionManager manager;
+ private final ClientConnectionOperator operator;
+ private volatile HttpPoolEntry poolEntry;
+ private volatile boolean reusable;
+ private volatile long duration;
+
+ ManagedClientConnectionImpl(
+ final ClientConnectionManager manager,
+ final ClientConnectionOperator operator,
+ final HttpPoolEntry entry) {
+ super();
+ if (manager == null) {
+ throw new IllegalArgumentException("Connection manager may not be null");
+ }
+ if (operator == null) {
+ throw new IllegalArgumentException("Connection operator may not be null");
+ }
+ if (entry == null) {
+ throw new IllegalArgumentException("HTTP pool entry may not be null");
+ }
+ this.lock = new ReentrantLock();
+ this.manager = manager;
+ this.operator = operator;
+ this.poolEntry = entry;
+ this.reusable = false;
+ this.duration = Long.MAX_VALUE;
+ }
+
+ Lock getLock() {
+ return this.lock;
+ }
+
+ HttpPoolEntry getPoolEntry() {
+ return this.poolEntry;
+ }
+
+ void detach() {
+ this.poolEntry = null;
+ }
+
+ boolean isDetached() {
+ return this.poolEntry == null;
+ }
+
+ public ClientConnectionManager getManager() {
+ return this.manager;
+ }
+
+ private OperatedClientConnection getConnection() {
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ return null;
+ }
+ return this.poolEntry.getConnection();
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ private OperatedClientConnection ensureConnection() {
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ return this.poolEntry.getConnection();
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void close() throws IOException {
+ OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ conn.close();
+ }
+ }
+
+ public void shutdown() throws IOException {
+ OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ conn.shutdown();
+ }
+ }
+
+ public boolean isOpen() {
+ OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ return conn.isOpen();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isStale() {
+ OperatedClientConnection conn = getConnection();
+ if (conn != null) {
+ return conn.isStale();
+ } else {
+ return true;
+ }
+ }
+
+ public void setSocketTimeout(int timeout) {
+ OperatedClientConnection conn = ensureConnection();
+ conn.setSocketTimeout(timeout);
+ }
+
+ public int getSocketTimeout() {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.getSocketTimeout();
+ }
+
+ public HttpConnectionMetrics getMetrics() {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.getMetrics();
+ }
+
+ public void flush() throws IOException {
+ OperatedClientConnection conn = ensureConnection();
+ conn.flush();
+ }
+
+ public boolean isResponseAvailable(int timeout) throws IOException {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.isResponseAvailable(timeout);
+ }
+
+ public void receiveResponseEntity(
+ final HttpResponse response) throws HttpException, IOException {
+ OperatedClientConnection conn = ensureConnection();
+ conn.receiveResponseEntity(response);
+ }
+
+ public HttpResponse receiveResponseHeader() throws HttpException, IOException {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.receiveResponseHeader();
+ }
+
+ public void sendRequestEntity(
+ final HttpEntityEnclosingRequest request) throws HttpException, IOException {
+ OperatedClientConnection conn = ensureConnection();
+ conn.sendRequestEntity(request);
+ }
+
+ public void sendRequestHeader(
+ final HttpRequest request) throws HttpException, IOException {
+ OperatedClientConnection conn = ensureConnection();
+ conn.sendRequestHeader(request);
+ }
+
+ public InetAddress getLocalAddress() {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.getLocalAddress();
+ }
+
+ public int getLocalPort() {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.getLocalPort();
+ }
+
+ public InetAddress getRemoteAddress() {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.getRemoteAddress();
+ }
+
+ public int getRemotePort() {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.getRemotePort();
+ }
+
+ public boolean isSecure() {
+ OperatedClientConnection conn = ensureConnection();
+ return conn.isSecure();
+ }
+
+ public SSLSession getSSLSession() {
+ OperatedClientConnection conn = ensureConnection();
+ SSLSession result = null;
+ Socket sock = conn.getSocket();
+ if (sock instanceof SSLSocket) {
+ result = ((SSLSocket)sock).getSession();
+ }
+ return result;
+ }
+
+ public Object getAttribute(final String id) {
+ OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).getAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public Object removeAttribute(final String id) {
+ OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ return ((HttpContext) conn).removeAttribute(id);
+ } else {
+ return null;
+ }
+ }
+
+ public void setAttribute(final String id, final Object obj) {
+ OperatedClientConnection conn = ensureConnection();
+ if (conn instanceof HttpContext) {
+ ((HttpContext) conn).setAttribute(id, obj);
+ }
+ }
+
+ public HttpRoute getRoute() {
+ synchronized (this.poolEntry) {
+ return this.poolEntry.getEffectiveRoute();
+ }
+ }
+
+ public void open(
+ final HttpRoute route,
+ final HttpContext context,
+ final HttpParams params) throws IOException {
+ if (route == null) {
+ throw new IllegalArgumentException("Route may not be null");
+ }
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ OperatedClientConnection conn;
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ if (tracker.isConnected()) {
+ throw new IllegalStateException("Connection already open");
+ }
+ conn = this.poolEntry.getConnection();
+ } finally {
+ this.lock.unlock();
+ }
+
+ HttpHost proxy = route.getProxyHost();
+ this.operator.openConnection(
+ conn,
+ (proxy != null) ? proxy : route.getTargetHost(),
+ route.getLocalAddress(),
+ context, params);
+
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ if (proxy == null) {
+ tracker.connectTarget(conn.isSecure());
+ } else {
+ tracker.connectProxy(proxy, conn.isSecure());
+ }
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void tunnelTarget(
+ boolean secure, final HttpParams params) throws IOException {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ HttpHost target;
+ OperatedClientConnection conn;
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ if (!tracker.isConnected()) {
+ throw new IllegalStateException("Connection not open");
+ }
+ if (tracker.isTunnelled()) {
+ throw new IllegalStateException("Connection is already tunnelled");
+ }
+ target = tracker.getTargetHost();
+ conn = this.poolEntry.getConnection();
+ } finally {
+ this.lock.unlock();
+ }
+
+ conn.update(null, target, secure, params);
+
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.tunnelTarget(secure);
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void tunnelProxy(
+ final HttpHost next, boolean secure, final HttpParams params) throws IOException {
+ if (next == null) {
+ throw new IllegalArgumentException("Next proxy amy not be null");
+ }
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ OperatedClientConnection conn;
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ if (!tracker.isConnected()) {
+ throw new IllegalStateException("Connection not open");
+ }
+ conn = this.poolEntry.getConnection();
+ } finally {
+ this.lock.unlock();
+ }
+
+ conn.update(null, next, secure, params);
+
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.tunnelProxy(next, secure);
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void layerProtocol(
+ final HttpContext context, final HttpParams params) throws IOException {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ HttpHost target;
+ OperatedClientConnection conn;
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new ConnectionShutdownException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ if (!tracker.isConnected()) {
+ throw new IllegalStateException("Connection not open");
+ }
+ if (!tracker.isTunnelled()) {
+ throw new IllegalStateException("Protocol layering without a tunnel not supported");
+ }
+ if (tracker.isLayered()) {
+ throw new IllegalStateException("Multiple protocol layering not supported");
+ }
+ target = tracker.getTargetHost();
+ conn = this.poolEntry.getConnection();
+ } finally {
+ this.lock.unlock();
+ }
+ this.operator.updateSecureConnection(conn, target, context, params);
+
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ throw new InterruptedIOException();
+ }
+ RouteTracker tracker = this.poolEntry.getTracker();
+ tracker.layerProtocol(conn.isSecure());
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public Object getState() {
+ return this.poolEntry.getState();
+ }
+
+ public void setState(final Object state) {
+ this.poolEntry.setState(state);
+ }
+
+ public void markReusable() {
+ this.reusable = true;
+ }
+
+ public void unmarkReusable() {
+ this.reusable = false;
+ }
+
+ public boolean isMarkedReusable() {
+ return this.reusable;
+ }
+
+ public void setIdleDuration(long duration, TimeUnit unit) {
+ if(duration > 0) {
+ this.duration = unit.toMillis(duration);
+ } else {
+ this.duration = -1;
+ }
+ }
+
+ public void releaseConnection() {
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ return;
+ }
+ this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
+ this.poolEntry = null;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ public void abortConnection() {
+ this.lock.lock();
+ try {
+ if (this.poolEntry == null) {
+ return;
+ }
+ this.reusable = false;
+ OperatedClientConnection conn = this.poolEntry.getConnection();
+ try {
+ conn.shutdown();
+ } catch (IOException ignore) {
+ }
+ this.manager.releaseConnection(this, this.duration, TimeUnit.MILLISECONDS);
+ this.poolEntry = null;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+}
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/ManagedClientConnectionImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java?rev=1154916&view=auto
==============================================================================
--- httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java (added)
+++ httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java Mon Aug 8 10:59:55 2011
@@ -0,0 +1,318 @@
+/*
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.conn;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.Lock;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.annotation.ThreadSafe;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ClientConnectionOperator;
+import org.apache.http.conn.ClientConnectionRequest;
+import org.apache.http.conn.ConnectionPoolTimeoutException;
+import org.apache.http.conn.ManagedClientConnection;
+import org.apache.http.conn.OperatedClientConnection;
+import org.apache.http.pool.ConnPoolControl;
+import org.apache.http.pool.PoolStats;
+import org.apache.http.impl.conn.DefaultClientConnectionOperator;
+import org.apache.http.impl.conn.SchemeRegistryFactory;
+
+/**
+ * Manages a pool of {@link OperatedClientConnection client connections} and
+ * is able to service connection requests from multiple execution threads.
+ * Connections are pooled on a per route basis. A request for a route which
+ * already the manager has persistent connections for available in the pool
+ * will be services by leasing a connection from the pool rather than
+ * creating a brand new connection.
+ * <p>
+ * PoolingConnectionManager maintains a maximum limit of connection on
+ * a per route basis and in total. Per default this implementation will
+ * create no more than than 2 concurrent connections per given route
+ * and no more 20 connections in total. For many real-world applications
+ * these limits may prove too constraining, especially if they use HTTP
+ * as a transport protocol for their services. Connection limits, however,
+ * can be adjusted using HTTP parameters.
+ *
+ * @since 4.2
+ */
+@ThreadSafe
+public class PoolingClientConnectionManager implements ClientConnectionManager, ConnPoolControl<HttpRoute> {
+
+ private final Log log = LogFactory.getLog(getClass());
+
+ private final SchemeRegistry schemeRegistry;
+
+ private final HttpConnPool pool;
+
+ private final ClientConnectionOperator operator;
+
+ public PoolingClientConnectionManager(final SchemeRegistry schreg) {
+ this(schreg, -1, TimeUnit.MILLISECONDS);
+ }
+
+ public PoolingClientConnectionManager() {
+ this(SchemeRegistryFactory.createDefault());
+ }
+
+ public PoolingClientConnectionManager(
+ final SchemeRegistry schemeRegistry,
+ final long timeToLive, final TimeUnit tunit) {
+ super();
+ if (schemeRegistry == null) {
+ throw new IllegalArgumentException("Scheme registry may not be null");
+ }
+ this.schemeRegistry = schemeRegistry;
+ this.operator = createConnectionOperator(schemeRegistry);
+ this.pool = new HttpConnPool(this.log, 2, 20, timeToLive, tunit);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ shutdown();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Hook for creating the connection operator.
+ * It is called by the constructor.
+ * Derived classes can override this method to change the
+ * instantiation of the operator.
+ * The default implementation here instantiates
+ * {@link DefaultClientConnectionOperator DefaultClientConnectionOperator}.
+ *
+ * @param schreg the scheme registry.
+ *
+ * @return the connection operator to use
+ */
+ protected ClientConnectionOperator createConnectionOperator(SchemeRegistry schreg) {
+ return new DefaultClientConnectionOperator(schreg);
+ }
+
+ public SchemeRegistry getSchemeRegistry() {
+ return this.schemeRegistry;
+ }
+
+ private String format(final HttpRoute route, final Object state) {
+ StringBuilder buf = new StringBuilder();
+ buf.append("[route: ").append(route).append("]");
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ private String formatStats(final HttpRoute route) {
+ StringBuilder buf = new StringBuilder();
+ PoolStats totals = this.pool.getTotalStats();
+ PoolStats stats = this.pool.getStats(route);
+ buf.append("[total kept alive: ").append(totals.getAvailable()).append("; ");
+ buf.append("route allocated: ").append(stats.getLeased() + stats.getAvailable());
+ buf.append(" of ").append(stats.getMax()).append("; ");
+ buf.append("total allocated: ").append(totals.getLeased() + totals.getAvailable());
+ buf.append(" of ").append(totals.getMax()).append("]");
+ return buf.toString();
+ }
+
+ private String format(final HttpPoolEntry entry) {
+ StringBuilder buf = new StringBuilder();
+ buf.append("[id: ").append(entry.getId()).append("]");
+ buf.append("[route: ").append(entry.getRoute()).append("]");
+ Object state = entry.getState();
+ if (state != null) {
+ buf.append("[state: ").append(state).append("]");
+ }
+ return buf.toString();
+ }
+
+ public ClientConnectionRequest requestConnection(
+ final HttpRoute route,
+ final Object state) {
+ if (route == null) {
+ throw new IllegalArgumentException("HTTP route may not be null");
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection request: " + format(route, state) + formatStats(route));
+ }
+ final Future<HttpPoolEntry> future = this.pool.lease(route, state);
+
+ return new ClientConnectionRequest() {
+
+ public void abortRequest() {
+ future.cancel(true);
+ }
+
+ public ManagedClientConnection getConnection(
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+ return leaseConnection(future, timeout, tunit);
+ }
+
+ };
+
+ }
+
+ ManagedClientConnection leaseConnection(
+ final Future<HttpPoolEntry> future,
+ final long timeout,
+ final TimeUnit tunit) throws InterruptedException, ConnectionPoolTimeoutException {
+ HttpPoolEntry entry;
+ try {
+ entry = future.get(timeout, tunit);
+ if (entry == null || future.isCancelled()) {
+ throw new InterruptedException();
+ }
+ if (entry.getConnection() == null) {
+ throw new IllegalStateException("Pool entry with no connection");
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection leased: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ return new ManagedClientConnectionImpl(this, this.operator, entry);
+ } catch (ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ if (cause == null) {
+ cause = ex;
+ }
+ this.log.error("Unexpected exception leasing connection from pool", cause);
+ // Should never happen
+ throw new InterruptedException();
+ } catch (TimeoutException ex) {
+ throw new ConnectionPoolTimeoutException("Timeout waiting for connection");
+ }
+ }
+
+ public void releaseConnection(
+ final ManagedClientConnection conn, final long keepalive, final TimeUnit tunit) {
+
+ if (!(conn instanceof ManagedClientConnectionImpl)) {
+ throw new IllegalArgumentException
+ ("Connection class mismatch, " +
+ "connection not obtained from this manager.");
+ }
+ ManagedClientConnectionImpl managedConn = (ManagedClientConnectionImpl) conn;
+ if (managedConn.getManager() != this) {
+ throw new IllegalStateException("Connection not obtained from this manager.");
+ }
+
+ Lock lock = managedConn.getLock();
+ lock.lock();
+ try {
+ HttpPoolEntry entry = managedConn.getPoolEntry();
+ if (entry == null) {
+ return;
+ }
+ try {
+ if (managedConn.isOpen() && !managedConn.isMarkedReusable()) {
+ try {
+ managedConn.shutdown();
+ } catch (IOException iox) {
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("I/O exception shutting down released connection", iox);
+ }
+ }
+ }
+ entry.updateExpiry(keepalive, tunit != null ? tunit : TimeUnit.MILLISECONDS);
+ if (this.log.isDebugEnabled()) {
+ String s;
+ if (keepalive > 0) {
+ s = "for " + keepalive + " " + tunit;
+ } else {
+ s = "indefinitely";
+ }
+ this.log.debug("Connection " + format(entry) + " can be kept alive " + s);
+ }
+ } finally {
+ this.pool.release(entry, managedConn.isMarkedReusable());
+ managedConn.detach();
+ }
+ if (this.log.isDebugEnabled()) {
+ this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute()));
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void shutdown(long waitMs) throws IOException {
+ this.log.debug("Connection manager is shutting down");
+ this.pool.shutdown(waitMs);
+ this.log.debug("Connection manager shut down");
+ }
+
+ public void shutdown() {
+ try {
+ shutdown(2000);
+ } catch (IOException ex) {
+ this.log.error("I/O exception while shutting down connection pool", ex);
+ }
+ }
+
+ public void closeIdleConnections(long idleTimeout, TimeUnit tunit) {
+ if (log.isDebugEnabled()) {
+ log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit);
+ }
+ pool.closeIdle(idleTimeout, tunit);
+ }
+
+ public void closeExpiredConnections() {
+ this.log.debug("Closing expired connections");
+ this.pool.closeExpired();
+ }
+
+ public void setMaxTotal(int max) {
+ this.pool.setMaxTotal(max);
+ }
+
+ public void setDefaultMaxPerRoute(int max) {
+ this.pool.setDefaultMaxPerRoute(max);
+ }
+
+ public void setMaxPerRoute(final HttpRoute route, int max) {
+ this.pool.setMaxPerRoute(route, max);
+ }
+
+ public PoolStats getTotalStats() {
+ return this.pool.getTotalStats();
+ }
+
+ public PoolStats getStats(final HttpRoute route) {
+ return this.pool.getStats(route);
+ }
+
+}
+
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpclient/branches/conn-mgmt-redesign/httpclient/src/main/java/org/apache/http/impl/conn/PoolingClientConnectionManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain