reusability flag in ManagedClientConnection

git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@508798 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Roland Weber 2007-02-17 19:41:26 +00:00
parent 486dd14981
commit 1c10f5e392
4 changed files with 114 additions and 29 deletions

View File

@ -144,4 +144,52 @@ public interface ManagedClientConnection
*/
/**
* Marks this connection as being in a reusable communication state.
* The checkpoints for reuseable communication states (in the absence
* of pipelining) are before sending a request and after receiving
* the response in it's entirety.
* The connection will automatically clear the checkpoint when
* used for communication. A call to this method indicates that
* the next checkpoint has been reached.
* <br/>
* A reusable communication state is necessary but not sufficient
* for the connection to be reused.
* A {@link #getRoute route} mismatch, the connection being closed,
* or other circumstances might prevent reuse.
*/
void markReusable()
;
/**
* Marks this connection as not being in a reusable state.
* This can be used immediately before releasing this connection
* to prevent it's reuse. Reasons for preventing reuse include
* error conditions and the evaluation of a
* {@link org.apache.http.ConnectionReuseStrategy reuse strategy}.
* <br/>
* <b>Note:</b>
* It is <i>not</i> necessary to call here before writing to
* or reading from this connection. Communication attempts will
* automatically unmark the state as non-reusable. It can then
* be switched back using {@link #markReusable markReusable}.
*/
void unmarkReusable()
;
/**
* Indicates whether this connection is in a reusable communication state.
* See {@link #markReusable markReusable} and
* {@link #unmarkReusable unmarkReusable} for details.
*
* @return <code>true</code> if this connection is marked as being in
* a reusable communication state,
* <code>false</code> otherwise
*/
boolean isMarkedReusable()
;
} // interface ManagedClientConnection

View File

@ -188,27 +188,6 @@ public class DefaultClientRequestDirector
//@@@ how to handle CONNECT requests for tunnelling?
//@@@ refuse to send external CONNECT via director? special handling?
//@@@ this check for secure connections is an ugly hack until the
//@@@ director is changed to expect HttpRoute instead of HostConfig
/*
//@@@ the actual check should be whether the socket factory
//@@@ for the target host scheme is a SecureSocketFactory
HttpRoute route = null;
{
final boolean secure =
!"http".equals(hostconf.getHost().getSchemeName());
if (hostconf.getProxyHost() == null)
route = new HttpRoute(hostconf.getHost(),
hostconf.getLocalAddress(),
secure);
else
route = new HttpRoute(hostconf.getHost(),
hostconf.getLocalAddress(),
hostconf.getProxyHost(),
secure);
} //@@@ end of ugly HostConfiguration -> HttpRoute conversion
*/
//@@@ should the request parameters already be used below?
//@@@ probably yes, but they're not linked yet
//@@@ will linking above cause problems with linking in reqExec?
@ -288,6 +267,7 @@ public class DefaultClientRequestDirector
HttpResponse connected =
requestExec.execute(connect, managedConn, context);
managedConn.markReusable();
int status = connected.getStatusLine().getStatusCode();
//@@@ log something about the response?
@ -422,21 +402,26 @@ public class DefaultClientRequestDirector
if ((response == null) || (response.getEntity() == null) ||
!response.getEntity().isStreaming()) {
// connection not needed and assumed to be in re-usable state
//@@@ evaluate connection re-use strategy, close if necessary
//@@@ evaluate connection re-use strategy,
//@@@ close and/or mark as non-reusable if necessary
managedConn = null;
mcc.markReusable();
connManager.releaseConnection(mcc);
}
} else {
// we got here as the result of an exception
// no response will be returned, release the connection
managedConn = null;
//@@@ is the connection in a re-usable state?
//@@@ is the connection in a re-usable state? consume response?
//@@@ for now, just shut it down
// Do not delegate this to the connection manager, can't
// tell whether it would shut down or close gracefully.
try {
if (mcc.isOpen())
mcc.shutdown();
} catch (IOException ignore) {
// can't allow exception while handling exception
//@@@ log as debug or warning?
}
connManager.releaseConnection(mcc);
}

View File

@ -52,6 +52,11 @@ import org.apache.http.conn.ManagedClientConnection;
* by derived classes. Operations for querying the connection state
* are delegated to the wrapped connection if there is one, or
* return a default value if there is none.
* <br/>
* This adapter tracks the checkpoints for reusable communication states,
* as indicated by {@link #markReusable markReusable} and queried by
* {@link #isMarkedReusable isMarkedReusable}.
* All send and receive operations will automatically clear the mark.
*
* @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
*
@ -67,15 +72,21 @@ public abstract class AbstractClientConnectionAdapter
/** The wrapped connection. */
protected OperatedClientConnection wrappedConnection;
/** The reusability marker. */
protected boolean markedReusable;
/**
* Creates a new connection adapter.
* The adapter is initially <i>not</i>
* {@link #isMarkedReusable marked} as reusable.
*
* @param conn the connection to wrap, or <code>null</code>
*/
protected AbstractClientConnectionAdapter(OperatedClientConnection conn) {
wrappedConnection = conn;
markedReusable = false;
} // <constructor>
@ -133,6 +144,7 @@ public abstract class AbstractClientConnectionAdapter
throws HttpException, IOException {
assertWrappedConn();
markedReusable = false;
wrappedConnection.receiveResponseEntity(response);
}
@ -142,6 +154,7 @@ public abstract class AbstractClientConnectionAdapter
throws HttpException, IOException {
assertWrappedConn();
markedReusable = false;
return wrappedConnection.receiveResponseHeader(params);
}
@ -151,6 +164,7 @@ public abstract class AbstractClientConnectionAdapter
throws HttpException, IOException {
assertWrappedConn();
markedReusable = false;
wrappedConnection.sendRequestEntity(request);
}
@ -160,6 +174,7 @@ public abstract class AbstractClientConnectionAdapter
throws HttpException, IOException {
assertWrappedConn();
markedReusable = false;
wrappedConnection.sendRequestHeader(request);
}
@ -195,5 +210,19 @@ public abstract class AbstractClientConnectionAdapter
return wrappedConnection.isSecure();
}
// non-javadoc, see interface ManagedClientConnection
public void markReusable() {
markedReusable = true;
}
// non-javadoc, see interface ManagedClientConnection
public void unmarkReusable() {
markedReusable = false;
}
// non-javadoc, see interface ManagedClientConnection
public boolean isMarkedReusable() {
return markedReusable;
}
} // class AbstractClientConnectionAdapter

View File

@ -360,9 +360,34 @@ public class ThreadSafeClientConnManager
("Connection not obtained from this manager.");
}
TrackingPoolEntry entry = hca.poolEntry;
hca.detach();
releasePoolEntry(entry);
try {
// make sure that the response has been read completely
if (!hca.isMarkedReusable()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Released connection not marked reusable.");
}
// In MTHCM, method releasePoolEntry below would call
// SimpleHttpConnectionManager.finishLastResponse(conn);
//@@@ consume response here or outside? (rolandw: outside)
// make sure this connection will not be re-used
//@@@ Can we set some kind of flag before shutting down?
//@@@ If shutdown throws an exception, we can't be sure
//@@@ that the connection will consider itself closed.
// be nice and call close() rather than shutdown()?
// I'm not in a nice mood today. -rolandw-
hca.shutdown();
}
} catch (IOException iox) {
//@@@ log as warning? let pass?
if (LOG.isDebugEnabled())
LOG.debug("Exception shutting down released connection",
iox);
} finally {
TrackingPoolEntry entry = hca.poolEntry;
hca.detach();
releasePoolEntry(entry);
}
}
@ -377,9 +402,6 @@ public class ThreadSafeClientConnManager
if (entry == null)
return;
// make sure that the response has been read completely
System.out.println("@@@ should consume response and free connection");
//@@@ SimpleHttpConnectionManager.finishLastResponse(conn);
connectionPool.freeConnection(entry);
}
@ -1295,6 +1317,7 @@ public class ThreadSafeClientConnManager
protected HttpConnectionAdapter(TrackingPoolEntry entry) {
super(entry.connection);
poolEntry = entry;
super.markedReusable = true;
}