HTTPCLIENT-652:

* Reverting most of my previous changes. Passing a state object to the connection manager when trying to obtain a connection is completely pointless, as usually connection state information becomes available only after the connection has been established, for instance, after having been challenged by an authenticating server. Therefore, it is necessary to be able to set a state object on an active connection
* added method to set state object on ManagedClientConnection

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@646918 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2008-04-10 18:30:12 +00:00
parent 8ff6eedd9e
commit 824b785a99
16 changed files with 79 additions and 148 deletions

View File

@ -229,5 +229,11 @@ public interface ManagedClientConnection extends
boolean isMarkedReusable() boolean isMarkedReusable()
; ;
void setState(Object state)
;
boolean isStateful()
;
} // interface ManagedClientConnection } // interface ManagedClientConnection

View File

@ -75,7 +75,10 @@ public abstract class AbstractPoolEntry {
//@@@ currently accessed from connection manager(s) as attribute //@@@ currently accessed from connection manager(s) as attribute
//@@@ avoid that, derived classes should decide whether update is allowed //@@@ avoid that, derived classes should decide whether update is allowed
//@@@ SCCM: yes, TSCCM: no //@@@ SCCM: yes, TSCCM: no
protected volatile ConnRoute route; protected volatile HttpRoute route;
/** Connection state object */
protected volatile Object state;
/** The tracked route, or <code>null</code> before tracking starts. */ /** The tracked route, or <code>null</code> before tracking starts. */
protected volatile RouteTracker tracker; protected volatile RouteTracker tracker;
@ -89,7 +92,7 @@ public abstract class AbstractPoolEntry {
* or <code>null</code> * or <code>null</code>
*/ */
protected AbstractPoolEntry(OperatedClientConnection occ, protected AbstractPoolEntry(OperatedClientConnection occ,
ConnRoute route) { HttpRoute route) {
this.connection = occ; this.connection = occ;
this.route = route; this.route = route;
this.tracker = null; this.tracker = null;

View File

@ -170,5 +170,16 @@ public abstract class AbstractPooledConnAdapter extends AbstractClientConnAdapte
} }
} }
// non-javadoc, see interface ManagedClientConnection
public boolean isStateful() {
assertAttached();
return poolEntry.state != null;
}
// non-javadoc, see interface ManagedClientConnection
public void setState(final Object state) {
poolEntry.state = state;
}
} // class AbstractPooledConnAdapter } // class AbstractPooledConnAdapter

View File

@ -1,98 +0,0 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* 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 org.apache.http.conn.routing.HttpRoute;
import org.apache.http.util.LangUtils;
/**
* A route for {@link ManagedClientConnection} along with the state information
* associated with that connection.
*
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
*
*/
public class ConnRoute {
private final HttpRoute route;
private final Object state;
public ConnRoute(final HttpRoute route, final Object state) {
super();
if (route == null) {
throw new IllegalArgumentException("HTTP route may not be null");
}
this.route = route;
this.state = state;
}
public HttpRoute getRoute() {
return this.route;
}
public Object getState() {
return this.state;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) return false;
if (this == obj) return true;
if (obj instanceof ConnRoute) {
ConnRoute that = (ConnRoute) obj;
return this.route.equals(that.route)
&& LangUtils.equals(this.state, that.state);
} else {
return false;
}
}
@Override
public int hashCode() {
int hash = LangUtils.HASH_SEED;
hash = LangUtils.hashCode(hash, this.route);
hash = LangUtils.hashCode(hash, this.state);
return hash;
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append(this.route);
if (this.state != null) {
buffer.append(" [");
buffer.append(this.state);
buffer.append("]");
}
return buffer.toString();
}
}

View File

@ -239,7 +239,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
} }
} }
managedConn = new ConnAdapter(uniquePoolEntry, new ConnRoute(route, state)); managedConn = new ConnAdapter(uniquePoolEntry, route);
return managedConn; return managedConn;
} }
@ -420,11 +420,12 @@ public class SingleClientConnManager implements ClientConnectionManager {
* @param entry the pool entry for the connection being wrapped * @param entry the pool entry for the connection being wrapped
* @param plan the planned route for this connection * @param plan the planned route for this connection
*/ */
protected ConnAdapter(PoolEntry entry, ConnRoute route) { protected ConnAdapter(PoolEntry entry, HttpRoute route) {
super(SingleClientConnManager.this, entry); super(SingleClientConnManager.this, entry);
markReusable(); markReusable();
entry.route = route; entry.route = route;
} }
} }

View File

@ -47,9 +47,9 @@ import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectionPoolTimeoutException; import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.OperatedClientConnection; import org.apache.http.conn.OperatedClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.params.HttpParams; import org.apache.http.params.HttpParams;
import org.apache.http.impl.conn.IdleConnectionHandler; import org.apache.http.impl.conn.IdleConnectionHandler;
import org.apache.http.impl.conn.ConnRoute;
@ -209,10 +209,14 @@ public abstract class AbstractConnPool implements RefQueueHandler {
* if the calling thread was interrupted * if the calling thread was interrupted
*/ */
public final public final
BasicPoolEntry getEntry(ConnRoute route, long timeout, TimeUnit tunit, BasicPoolEntry getEntry(
HttpRoute route,
Object state,
long timeout,
TimeUnit tunit,
ClientConnectionOperator operator) ClientConnectionOperator operator)
throws ConnectionPoolTimeoutException, InterruptedException { throws ConnectionPoolTimeoutException, InterruptedException {
return newPoolEntryRequest().getPoolEntry(route, timeout, tunit, operator); return newPoolEntryRequest().getPoolEntry(route, state, timeout, tunit, operator);
} }
/** /**
@ -247,7 +251,7 @@ public abstract class AbstractConnPool implements RefQueueHandler {
//@@@ flag in the BasicPoolEntryRef, to be reset when freed? //@@@ flag in the BasicPoolEntryRef, to be reset when freed?
final boolean lost = issuedConnections.remove(ref); final boolean lost = issuedConnections.remove(ref);
if (lost) { if (lost) {
final ConnRoute route = final HttpRoute route =
((BasicPoolEntryRef)ref).getRoute(); ((BasicPoolEntryRef)ref).getRoute();
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Connection garbage collected. " + route); LOG.debug("Connection garbage collected. " + route);
@ -274,7 +278,7 @@ public abstract class AbstractConnPool implements RefQueueHandler {
* *
* @param route the route of the pool entry that was lost * @param route the route of the pool entry that was lost
*/ */
protected abstract void handleLostEntry(ConnRoute route) protected abstract void handleLostEntry(HttpRoute route)
; ;

View File

@ -35,8 +35,8 @@ import java.lang.ref.ReferenceQueue;
import org.apache.http.conn.OperatedClientConnection; import org.apache.http.conn.OperatedClientConnection;
import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.conn.AbstractPoolEntry; import org.apache.http.impl.conn.AbstractPoolEntry;
import org.apache.http.impl.conn.ConnRoute;
@ -67,7 +67,7 @@ public class BasicPoolEntry extends AbstractPoolEntry {
* or <code>null</code> * or <code>null</code>
*/ */
public BasicPoolEntry(ClientConnectionOperator op, public BasicPoolEntry(ClientConnectionOperator op,
ConnRoute route, HttpRoute route,
ReferenceQueue<Object> queue) { ReferenceQueue<Object> queue) {
//@@@ create connection in base? or delay creation until needed? //@@@ create connection in base? or delay creation until needed?
super(op.createConnection(), route); super(op.createConnection(), route);
@ -92,7 +92,7 @@ public class BasicPoolEntry extends AbstractPoolEntry {
return super.connection; return super.connection;
} }
protected final ConnRoute getPlannedRoute() { protected final HttpRoute getPlannedRoute() {
return super.route; return super.route;
} }

View File

@ -34,7 +34,7 @@ package org.apache.http.impl.conn.tsccm;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue; import java.lang.ref.ReferenceQueue;
import org.apache.http.impl.conn.ConnRoute; import org.apache.http.conn.routing.HttpRoute;
@ -46,7 +46,7 @@ import org.apache.http.impl.conn.ConnRoute;
public class BasicPoolEntryRef extends WeakReference<BasicPoolEntry> { public class BasicPoolEntryRef extends WeakReference<BasicPoolEntry> {
/** The planned route of the entry. */ /** The planned route of the entry. */
private final ConnRoute route; private final HttpRoute route;
/** /**
@ -72,7 +72,7 @@ public class BasicPoolEntryRef extends WeakReference<BasicPoolEntry> {
* *
* @return the planned route * @return the planned route
*/ */
public final ConnRoute getRoute() { public final HttpRoute getRoute() {
return this.route; return this.route;
} }

View File

@ -46,7 +46,6 @@ import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.ConnectionPoolTimeoutException; import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.params.HttpConnectionManagerParams; import org.apache.http.conn.params.HttpConnectionManagerParams;
import org.apache.http.impl.conn.ConnRoute;
@ -84,7 +83,7 @@ public class ConnPoolByRoute extends AbstractConnPool {
* Keys are of class {@link HttpRoute}, * Keys are of class {@link HttpRoute},
* values of class {@link RouteSpecificPool}. * values of class {@link RouteSpecificPool}.
*/ */
protected final Map<ConnRoute, RouteSpecificPool> routeToPool; protected final Map<HttpRoute, RouteSpecificPool> routeToPool;
@ -128,8 +127,8 @@ public class ConnPoolByRoute extends AbstractConnPool {
* *
* @return a map * @return a map
*/ */
protected Map<ConnRoute,RouteSpecificPool> createRouteToPoolMap() { protected Map<HttpRoute, RouteSpecificPool> createRouteToPoolMap() {
return new HashMap<ConnRoute, RouteSpecificPool>(); return new HashMap<HttpRoute, RouteSpecificPool>();
} }
@ -141,7 +140,7 @@ public class ConnPoolByRoute extends AbstractConnPool {
* *
* @return the new pool * @return the new pool
*/ */
protected RouteSpecificPool newRouteSpecificPool(ConnRoute route) { protected RouteSpecificPool newRouteSpecificPool(HttpRoute route) {
return new RouteSpecificPool(route); return new RouteSpecificPool(route);
} }
@ -170,7 +169,7 @@ public class ConnPoolByRoute extends AbstractConnPool {
* @return the pool for the argument route, * @return the pool for the argument route,
* never <code>null</code> if <code>create</code> is <code>true</code> * never <code>null</code> if <code>create</code> is <code>true</code>
*/ */
protected RouteSpecificPool getRoutePool(ConnRoute route, protected RouteSpecificPool getRoutePool(HttpRoute route,
boolean create) { boolean create) {
RouteSpecificPool rospl = null; RouteSpecificPool rospl = null;
@ -193,7 +192,7 @@ public class ConnPoolByRoute extends AbstractConnPool {
//@@@ consider alternatives for gathering statistics //@@@ consider alternatives for gathering statistics
public int getConnectionsInPool(ConnRoute route) { public int getConnectionsInPool(HttpRoute route) {
try { try {
poolLock.lock(); poolLock.lock();
@ -224,12 +223,13 @@ public class ConnPoolByRoute extends AbstractConnPool {
} }
public BasicPoolEntry getPoolEntry( public BasicPoolEntry getPoolEntry(
ConnRoute route, HttpRoute route,
Object state,
long timeout, long timeout,
TimeUnit tunit, TimeUnit tunit,
ClientConnectionOperator operator) ClientConnectionOperator operator)
throws InterruptedException, ConnectionPoolTimeoutException { throws InterruptedException, ConnectionPoolTimeoutException {
return getEntryBlocking(route, timeout, tunit, operator, aborter); return getEntryBlocking(route, state, timeout, tunit, operator, aborter);
} }
}; };
@ -256,14 +256,14 @@ public class ConnPoolByRoute extends AbstractConnPool {
* if the calling thread was interrupted * if the calling thread was interrupted
*/ */
protected BasicPoolEntry getEntryBlocking( protected BasicPoolEntry getEntryBlocking(
ConnRoute route, HttpRoute route, Object state,
long timeout, TimeUnit tunit, long timeout, TimeUnit tunit,
ClientConnectionOperator operator, ClientConnectionOperator operator,
Aborter aborter) Aborter aborter)
throws ConnectionPoolTimeoutException, InterruptedException { throws ConnectionPoolTimeoutException, InterruptedException {
int maxHostConnections = HttpConnectionManagerParams int maxHostConnections = HttpConnectionManagerParams
.getMaxConnectionsPerHost(this.params, route.getRoute()); .getMaxConnectionsPerHost(this.params, route);
int maxTotalConnections = HttpConnectionManagerParams int maxTotalConnections = HttpConnectionManagerParams
.getMaxTotalConnections(this.params); .getMaxTotalConnections(this.params);
@ -363,7 +363,7 @@ public class ConnPoolByRoute extends AbstractConnPool {
@Override @Override
public void freeEntry(BasicPoolEntry entry) { public void freeEntry(BasicPoolEntry entry) {
ConnRoute route = entry.getPlannedRoute(); HttpRoute route = entry.getPlannedRoute();
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Freeing connection. " + route); LOG.debug("Freeing connection. " + route);
} }
@ -493,7 +493,7 @@ public class ConnPoolByRoute extends AbstractConnPool {
*/ */
protected void deleteEntry(BasicPoolEntry entry) { protected void deleteEntry(BasicPoolEntry entry) {
ConnRoute route = entry.getPlannedRoute(); HttpRoute route = entry.getPlannedRoute();
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Deleting connection. " + route); LOG.debug("Deleting connection. " + route);
@ -546,7 +546,7 @@ public class ConnPoolByRoute extends AbstractConnPool {
// non-javadoc, see base class AbstractConnPool // non-javadoc, see base class AbstractConnPool
@Override @Override
protected void handleLostEntry(ConnRoute route) { protected void handleLostEntry(HttpRoute route) {
try { try {
poolLock.lock(); poolLock.lock();

View File

@ -35,7 +35,6 @@ import java.util.concurrent.TimeUnit;
import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.ConnectionPoolTimeoutException; import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.conn.ConnRoute;
/** /**
* Encapsulates a request for a {@link BasicPoolEntry}. * Encapsulates a request for a {@link BasicPoolEntry}.
@ -62,7 +61,8 @@ public interface PoolEntryRequest {
* if the calling thread was interrupted * if the calling thread was interrupted
*/ */
BasicPoolEntry getPoolEntry( BasicPoolEntry getPoolEntry(
ConnRoute route, HttpRoute route,
Object state,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
ClientConnectionOperator operator) ClientConnectionOperator operator)

View File

@ -33,7 +33,7 @@ package org.apache.http.impl.conn.tsccm;
import java.util.Queue; import java.util.Queue;
import java.util.LinkedList; import java.util.LinkedList;
import org.apache.http.impl.conn.ConnRoute; import org.apache.http.conn.routing.HttpRoute;
/** /**
@ -44,7 +44,7 @@ import org.apache.http.impl.conn.ConnRoute;
public class RouteSpecificPool { public class RouteSpecificPool {
/** The route this pool is for. */ /** The route this pool is for. */
protected final ConnRoute route; protected final HttpRoute route;
/** /**
* The list of free entries. * The list of free entries.
@ -65,7 +65,7 @@ public class RouteSpecificPool {
* *
* @param r the route for which to pool * @param r the route for which to pool
*/ */
public RouteSpecificPool(ConnRoute route) { public RouteSpecificPool(HttpRoute route) {
this.route = route; this.route = route;
this.freeEntries = new LinkedList<BasicPoolEntry>(); this.freeEntries = new LinkedList<BasicPoolEntry>();
this.waitingThreads = new LinkedList<WaitingThread>(); this.waitingThreads = new LinkedList<WaitingThread>();
@ -78,7 +78,7 @@ public class RouteSpecificPool {
* *
* @return the route * @return the route
*/ */
public final ConnRoute getRoute() { public final HttpRoute getRoute() {
return route; return route;
} }

View File

@ -45,7 +45,6 @@ import org.apache.http.conn.ManagedClientConnection;
import org.apache.http.conn.OperatedClientConnection; import org.apache.http.conn.OperatedClientConnection;
import org.apache.http.params.HttpParams; import org.apache.http.params.HttpParams;
import org.apache.http.impl.conn.DefaultClientConnectionOperator; import org.apache.http.impl.conn.DefaultClientConnectionOperator;
import org.apache.http.impl.conn.ConnRoute;
@ -171,7 +170,7 @@ public class ThreadSafeClientConnManager
} }
final BasicPoolEntry entry = poolRequest.getPoolEntry( final BasicPoolEntry entry = poolRequest.getPoolEntry(
new ConnRoute(route, state), timeout, tunit, connOperator); route, state, timeout, tunit, connOperator);
return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry); return new BasicPooledConnAdapter(ThreadSafeClientConnManager.this, entry);
} }
@ -242,9 +241,9 @@ public class ThreadSafeClientConnManager
* *
* @return the total number of pooled connections for that route * @return the total number of pooled connections for that route
*/ */
public int getConnectionsInPool(HttpRoute route, Object state) { public int getConnectionsInPool(HttpRoute route) {
return ((ConnPoolByRoute)connectionPool).getConnectionsInPool( return ((ConnPoolByRoute)connectionPool).getConnectionsInPool(
new ConnRoute(route, state)); route);
} }

View File

@ -75,4 +75,11 @@ public class ClientConnAdapterMockup extends AbstractClientConnAdapter {
throw new UnsupportedOperationException("just a mockup"); throw new UnsupportedOperationException("just a mockup");
} }
public boolean isStateful() {
throw new UnsupportedOperationException("just a mockup");
}
public void setState(Object state) {
throw new UnsupportedOperationException("just a mockup");
}
} }

View File

@ -406,13 +406,13 @@ public class TestTSCCMNoServer extends TestCase {
assertEquals("connectionsInPool", assertEquals("connectionsInPool",
mgr.getConnectionsInPool(), 1); mgr.getConnectionsInPool(), 1);
assertEquals("connectionsInPool(host)", assertEquals("connectionsInPool(host)",
mgr.getConnectionsInPool(route, null), 1); mgr.getConnectionsInPool(route), 1);
mgr.releaseConnection(conn); mgr.releaseConnection(conn);
assertEquals("connectionsInPool", assertEquals("connectionsInPool",
mgr.getConnectionsInPool(), 1); mgr.getConnectionsInPool(), 1);
assertEquals("connectionsInPool(host)", assertEquals("connectionsInPool(host)",
mgr.getConnectionsInPool(route, null), 1); mgr.getConnectionsInPool(route), 1);
// this implicitly deletes them // this implicitly deletes them
mgr.closeIdleConnections(0L, TimeUnit.MILLISECONDS); mgr.closeIdleConnections(0L, TimeUnit.MILLISECONDS);
@ -420,7 +420,7 @@ public class TestTSCCMNoServer extends TestCase {
assertEquals("connectionsInPool", assertEquals("connectionsInPool",
mgr.getConnectionsInPool(), 0); mgr.getConnectionsInPool(), 0);
assertEquals("connectionsInPool(host)", assertEquals("connectionsInPool(host)",
mgr.getConnectionsInPool(route, null), 0); mgr.getConnectionsInPool(route), 0);
mgr.shutdown(); mgr.shutdown();
} }

View File

@ -50,7 +50,6 @@ import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory; import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.conn.ClientConnectionOperator; import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.impl.conn.DefaultClientConnectionOperator; import org.apache.http.impl.conn.DefaultClientConnectionOperator;
import org.apache.http.impl.conn.ConnRoute;
@ -114,13 +113,13 @@ public class TestDumbHelpers extends TestCase {
// expected // expected
} }
bpe = new BasicPoolEntry(ccop, new ConnRoute(route, null), null); bpe = new BasicPoolEntry(ccop, route, null);
assertEquals ("wrong operator", ccop, bpe.getOperator()); assertEquals ("wrong operator", ccop, bpe.getOperator());
assertEquals ("wrong route", route, bpe.getPlannedRoute().getRoute()); assertEquals ("wrong route", route, bpe.getPlannedRoute());
assertNotNull("missing ref", bpe.getWeakRef()); assertNotNull("missing ref", bpe.getWeakRef());
assertEquals("bad weak ref", bpe, bpe.getWeakRef().get()); assertEquals("bad weak ref", bpe, bpe.getWeakRef().get());
assertEquals("bad ref route", route, bpe.getWeakRef().getRoute().getRoute()); assertEquals("bad ref route", route, bpe.getWeakRef().getRoute());
} }

View File

@ -40,7 +40,6 @@ import junit.framework.TestSuite;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.conn.ConnRoute;
@ -84,7 +83,7 @@ public class TestWaitingThread extends TestCase {
assertNull ("thread from nowhere", wt.getThread()); assertNull ("thread from nowhere", wt.getThread());
HttpRoute route = new HttpRoute(TARGET); HttpRoute route = new HttpRoute(TARGET);
RouteSpecificPool rospl = new RouteSpecificPool(new ConnRoute(route, null)); RouteSpecificPool rospl = new RouteSpecificPool(route);
wt = new WaitingThread(cnd, rospl); wt = new WaitingThread(cnd, rospl);
assertEquals("wrong condition", cnd, wt.getCondition()); assertEquals("wrong condition", cnd, wt.getCondition());
assertEquals("wrong pool", rospl, wt.getPool()); assertEquals("wrong pool", rospl, wt.getPool());