mirror of
https://github.com/apache/httpcomponents-client.git
synced 2025-02-18 16:07:11 +00:00
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:
parent
486dd14981
commit
1c10f5e392
@ -144,4 +144,52 @@ boolean release()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
} // interface ManagedClientConnection
|
||||||
|
@ -188,27 +188,6 @@ protected void establishRoute(HttpRoute route, HttpContext context)
|
|||||||
//@@@ how to handle CONNECT requests for tunnelling?
|
//@@@ how to handle CONNECT requests for tunnelling?
|
||||||
//@@@ refuse to send external CONNECT via director? special handling?
|
//@@@ 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?
|
//@@@ should the request parameters already be used below?
|
||||||
//@@@ probably yes, but they're not linked yet
|
//@@@ probably yes, but they're not linked yet
|
||||||
//@@@ will linking above cause problems with linking in reqExec?
|
//@@@ will linking above cause problems with linking in reqExec?
|
||||||
@ -288,6 +267,7 @@ protected boolean createTunnel(HttpRoute route, HttpContext context)
|
|||||||
|
|
||||||
HttpResponse connected =
|
HttpResponse connected =
|
||||||
requestExec.execute(connect, managedConn, context);
|
requestExec.execute(connect, managedConn, context);
|
||||||
|
managedConn.markReusable();
|
||||||
int status = connected.getStatusLine().getStatusCode();
|
int status = connected.getStatusLine().getStatusCode();
|
||||||
//@@@ log something about the response?
|
//@@@ log something about the response?
|
||||||
|
|
||||||
@ -422,21 +402,26 @@ protected void cleanupConnection(boolean success, HttpResponse response)
|
|||||||
if ((response == null) || (response.getEntity() == null) ||
|
if ((response == null) || (response.getEntity() == null) ||
|
||||||
!response.getEntity().isStreaming()) {
|
!response.getEntity().isStreaming()) {
|
||||||
// connection not needed and assumed to be in re-usable state
|
// 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;
|
managedConn = null;
|
||||||
|
mcc.markReusable();
|
||||||
connManager.releaseConnection(mcc);
|
connManager.releaseConnection(mcc);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we got here as the result of an exception
|
// we got here as the result of an exception
|
||||||
// no response will be returned, release the connection
|
// no response will be returned, release the connection
|
||||||
managedConn = null;
|
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
|
//@@@ 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 {
|
try {
|
||||||
if (mcc.isOpen())
|
if (mcc.isOpen())
|
||||||
mcc.shutdown();
|
mcc.shutdown();
|
||||||
} catch (IOException ignore) {
|
} catch (IOException ignore) {
|
||||||
// can't allow exception while handling exception
|
// can't allow exception while handling exception
|
||||||
|
//@@@ log as debug or warning?
|
||||||
}
|
}
|
||||||
connManager.releaseConnection(mcc);
|
connManager.releaseConnection(mcc);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,11 @@
|
|||||||
* by derived classes. Operations for querying the connection state
|
* by derived classes. Operations for querying the connection state
|
||||||
* are delegated to the wrapped connection if there is one, or
|
* are delegated to the wrapped connection if there is one, or
|
||||||
* return a default value if there is none.
|
* 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>
|
* @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
|
||||||
*
|
*
|
||||||
@ -67,15 +72,21 @@ public abstract class AbstractClientConnectionAdapter
|
|||||||
/** The wrapped connection. */
|
/** The wrapped connection. */
|
||||||
protected OperatedClientConnection wrappedConnection;
|
protected OperatedClientConnection wrappedConnection;
|
||||||
|
|
||||||
|
/** The reusability marker. */
|
||||||
|
protected boolean markedReusable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new connection adapter.
|
* 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>
|
* @param conn the connection to wrap, or <code>null</code>
|
||||||
*/
|
*/
|
||||||
protected AbstractClientConnectionAdapter(OperatedClientConnection conn) {
|
protected AbstractClientConnectionAdapter(OperatedClientConnection conn) {
|
||||||
|
|
||||||
wrappedConnection = conn;
|
wrappedConnection = conn;
|
||||||
|
markedReusable = false;
|
||||||
|
|
||||||
} // <constructor>
|
} // <constructor>
|
||||||
|
|
||||||
@ -133,6 +144,7 @@ public void receiveResponseEntity(HttpResponse response)
|
|||||||
throws HttpException, IOException {
|
throws HttpException, IOException {
|
||||||
|
|
||||||
assertWrappedConn();
|
assertWrappedConn();
|
||||||
|
markedReusable = false;
|
||||||
wrappedConnection.receiveResponseEntity(response);
|
wrappedConnection.receiveResponseEntity(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +154,7 @@ public HttpResponse receiveResponseHeader(HttpParams params)
|
|||||||
throws HttpException, IOException {
|
throws HttpException, IOException {
|
||||||
|
|
||||||
assertWrappedConn();
|
assertWrappedConn();
|
||||||
|
markedReusable = false;
|
||||||
return wrappedConnection.receiveResponseHeader(params);
|
return wrappedConnection.receiveResponseHeader(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +164,7 @@ public void sendRequestEntity(HttpEntityEnclosingRequest request)
|
|||||||
throws HttpException, IOException {
|
throws HttpException, IOException {
|
||||||
|
|
||||||
assertWrappedConn();
|
assertWrappedConn();
|
||||||
|
markedReusable = false;
|
||||||
wrappedConnection.sendRequestEntity(request);
|
wrappedConnection.sendRequestEntity(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,6 +174,7 @@ public void sendRequestHeader(HttpRequest request)
|
|||||||
throws HttpException, IOException {
|
throws HttpException, IOException {
|
||||||
|
|
||||||
assertWrappedConn();
|
assertWrappedConn();
|
||||||
|
markedReusable = false;
|
||||||
wrappedConnection.sendRequestHeader(request);
|
wrappedConnection.sendRequestHeader(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,5 +210,19 @@ public boolean isSecure() {
|
|||||||
return wrappedConnection.isSecure();
|
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
|
} // class AbstractClientConnectionAdapter
|
||||||
|
@ -360,9 +360,34 @@ public void releaseConnection(ManagedClientConnection conn) {
|
|||||||
("Connection not obtained from this manager.");
|
("Connection not obtained from this manager.");
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackingPoolEntry entry = hca.poolEntry;
|
try {
|
||||||
hca.detach();
|
// make sure that the response has been read completely
|
||||||
releasePoolEntry(entry);
|
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 @@ private void releasePoolEntry(TrackingPoolEntry entry) {
|
|||||||
if (entry == null)
|
if (entry == null)
|
||||||
return;
|
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);
|
connectionPool.freeConnection(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1295,6 +1317,7 @@ private class HttpConnectionAdapter
|
|||||||
protected HttpConnectionAdapter(TrackingPoolEntry entry) {
|
protected HttpConnectionAdapter(TrackingPoolEntry entry) {
|
||||||
super(entry.connection);
|
super(entry.connection);
|
||||||
poolEntry = entry;
|
poolEntry = entry;
|
||||||
|
super.markedReusable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user