revised route tracking in managed connection

git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@505377 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Roland Weber 2007-02-09 17:14:22 +00:00
parent 64dac236b7
commit a72fc9c4c5
3 changed files with 64 additions and 28 deletions

View File

@ -67,6 +67,16 @@ public interface ManagedClientConnection
;
/**
* Obtains the current route of this connection.
*
* @return the route established so far, or
* <code>null</code> if not connected
*/
HttpRoute getRoute()
;
/**
* Opens this connection according to the given route.
*

View File

@ -110,7 +110,7 @@ public final class RouteTracker implements Cloneable {
/**
* Tracks connecting to the target.
*
* @param secure <code>true</code> if the connection is secure,
* @param secure <code>true</code> if the route is secure,
* <code>false</code> otherwise
*/
public final void connectTarget(boolean secure) {
@ -123,20 +123,26 @@ public final class RouteTracker implements Cloneable {
* Tracks connecting to a proxy.
*
* @param proxy the proxy connected to
* @param secure <code>true</code> if the route is secure,
* <code>false</code> otherwise
*/
public final void connectProxy(HttpHost proxy) {
public final void connectProxy(HttpHost proxy, boolean secure) {
if (proxy == null) {
throw new IllegalArgumentException("Proxy host may not be null.");
}
this.connected = true;
this.proxyHost = proxy;
this.secure = secure;
}
/**
* Tracks tunnelling through the proxy.
*
* @param secure <code>true</code> if the route is secure,
* <code>false</code> otherwise
*/
public final void establishTunnel() {
public final void establishTunnel(boolean secure) {
if (this.proxyHost == null) {
throw new IllegalStateException("No tunnel without proxy.");
}
@ -144,6 +150,7 @@ public final class RouteTracker implements Cloneable {
throw new IllegalStateException("No tunnel unless connected.");
}
this.tunnelled = true;
this.secure = secure;
}

View File

@ -47,6 +47,8 @@ import org.apache.http.HttpHost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.HttpRoute;
import org.apache.http.conn.RouteTracker;
import org.apache.http.conn.HostConfiguration;
import org.apache.http.conn.ManagedClientConnection;
import org.apache.http.conn.OperatedClientConnection;
@ -817,7 +819,7 @@ public class ThreadSafeClientConnManager
*/
private synchronized void deleteConnection(TrackingPoolEntry entry) {
HostConfiguration route = entry.route;
HostConfiguration route = entry.tracker.toHostConfig();
if (LOG.isDebugEnabled()) {
LOG.debug("Reclaiming connection, hostConfig=" + route);
@ -1084,14 +1086,8 @@ public class ThreadSafeClientConnManager
/** The route for which this entry gets allocated. */
private HostConfiguration plannedRoute;
/** The host configuration part of the tracked route. */
private HostConfiguration route;
/** The tunnel created flag part of the tracked route. */
private boolean tunnelled;
/** The layered flag part of the tracked route. */
private boolean layered;
/** The tracked route, or <code>null</code> before tracking starts. */
private RouteTracker tracker;
/** The connection manager. */
private ThreadSafeClientConnManager manager;
@ -1112,8 +1108,8 @@ public class ThreadSafeClientConnManager
*/
private TrackingPoolEntry(OperatedClientConnection occ) {
this.connection = occ;
this.route = null;
this.tunnelled = false;
//@@@ pass planned route to the constructor?
this.tracker = null;
this.manager = ThreadSafeClientConnManager.this;
this.reference = new WeakReference(this, REFERENCE_QUEUE);
}
@ -1141,6 +1137,9 @@ public class ThreadSafeClientConnManager
throw new IllegalArgumentException
("Parameters must not be null.");
}
if ((this.tracker != null) && this.tracker.isConnected()) {
throw new IllegalStateException("Connection already open.");
}
// - collect the arguments
// - call the operator
@ -1155,6 +1154,8 @@ public class ThreadSafeClientConnManager
}
final HttpHost proxy = route.getProxyHost();
//@@@ verify against planned route?
if (LOG.isDebugEnabled()) {
if (proxy == null) {
LOG.debug("Open connection to " + target);
@ -1164,12 +1165,18 @@ public class ThreadSafeClientConnManager
}
}
this.tracker = new RouteTracker
(route.getHost(), route.getLocalAddress());
ThreadSafeClientConnManager.this.connectionOperator.openConnection
(this.connection,
(proxy != null) ? proxy : target,
context, params);
this.route = route;
if (proxy == null)
this.tracker.connectTarget(this.connection.isSecure());
else
this.tracker.connectProxy(proxy, this.connection.isSecure());
} // open
@ -1193,17 +1200,18 @@ public class ThreadSafeClientConnManager
("Parameters must not be null.");
}
if (route.getProxyHost() == null) {
throw new IllegalStateException("No proxy in route.");
//@@@ check for proxy in planned route?
if ((this.tracker == null) || !this.tracker.isConnected()) {
throw new IllegalStateException("Connection not open.");
}
if (tunnelled) {
if (this.tracker.isTunnelled()) {
throw new IllegalStateException
("Connection is already tunnelled.");
}
this.connection.update(null, route.getHost(),
this.connection.update(null, tracker.getTargetHost(),
secure, params);
tunnelled = true;
this.tracker.establishTunnel(secure);
} // tunnelCreated
@ -1225,13 +1233,17 @@ public class ThreadSafeClientConnManager
("Parameters must not be null.");
}
if (!this.tunnelled) {
if ((this.tracker == null) || !this.tracker.isConnected()) {
throw new IllegalStateException("Connection not open.");
}
if (!this.tracker.isTunnelled()) {
//@@@ allow this?
throw new IllegalStateException
("Protocol layering without a tunnel not supported.");
}
if (this.layered) {
if (this.tracker.isLayered()) {
throw new IllegalStateException
("Protocol already layered.");
("Multiple protocol layering not supported.");
}
// - collect the arguments
@ -1240,7 +1252,7 @@ public class ThreadSafeClientConnManager
// In this order, we can be sure that only a successful
// layering on top of the connection will be tracked.
final HttpHost target = route.getHost();
final HttpHost target = tracker.getTargetHost();
if (LOG.isDebugEnabled()) {
LOG.debug("Layer protocol on connection to " + target);
@ -1250,7 +1262,7 @@ public class ThreadSafeClientConnManager
.updateSecureConnection(this.connection, target,
context, params);
this.layered = true;
this.tracker.layerProtocol(this.connection.isSecure());
} // layerProtocol
@ -1261,9 +1273,8 @@ public class ThreadSafeClientConnManager
* in both cases. This method should be called regardless of
* whether the close or shutdown succeeds or triggers an error.
*/
private void closing() {
route = null;
tunnelled = false;
private void closing() {
tracker = null;
}
} // class TrackingPoolEntry
@ -1322,6 +1333,14 @@ public class ThreadSafeClientConnManager
}
// non-javadoc, see interface ManagedHttpConnection
public HttpRoute getRoute() {
assertAttached();
return (poolEntry.tracker == null) ?
null : poolEntry.tracker.toRoute();
}
// non-javadoc, see interface ManagedHttpConnection
public void open(HostConfiguration route,
HttpContext context, HttpParams params)