HTTPCLIENT-1127: a better fix for the deal-lock between SingleClientConnManager.releaseConnection() and SingleClientConnManager.shutdown(); previous fix may have broken ThreadSafeClientConnManager
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1180361 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6bd3da869d
commit
28de736437
|
@ -112,7 +112,7 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
|||
* Detaches this adapter from the wrapped connection.
|
||||
* This adapter becomes useless.
|
||||
*/
|
||||
protected void detach() {
|
||||
protected synchronized void detach() {
|
||||
wrappedConnection = null;
|
||||
duration = Long.MAX_VALUE;
|
||||
}
|
||||
|
@ -300,18 +300,15 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
|||
}
|
||||
}
|
||||
|
||||
public void releaseConnection() {
|
||||
synchronized (connManager) {
|
||||
public synchronized void releaseConnection() {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
released = true;
|
||||
connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public void abortConnection() {
|
||||
synchronized (connManager) {
|
||||
public synchronized void abortConnection() {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
|
@ -323,7 +320,6 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
|||
}
|
||||
connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getAttribute(final String id) {
|
||||
OperatedClientConnection conn = getWrappedConnection();
|
||||
|
|
|
@ -105,7 +105,7 @@ public abstract class AbstractPooledConnAdapter extends AbstractClientConnAdapte
|
|||
* This adapter becomes useless.
|
||||
*/
|
||||
@Override
|
||||
protected void detach() {
|
||||
protected synchronized void detach() {
|
||||
poolEntry = null;
|
||||
super.detach();
|
||||
}
|
||||
|
|
|
@ -82,19 +82,19 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
|
||||
/** The one and only entry in this pool. */
|
||||
@GuardedBy("this")
|
||||
protected PoolEntry uniquePoolEntry;
|
||||
protected volatile PoolEntry uniquePoolEntry;
|
||||
|
||||
/** The currently issued managed connection, if any. */
|
||||
@GuardedBy("this")
|
||||
protected ConnAdapter managedConn;
|
||||
protected volatile ConnAdapter managedConn;
|
||||
|
||||
/** The time of the last connection release, or -1. */
|
||||
@GuardedBy("this")
|
||||
protected long lastReleaseTime;
|
||||
protected volatile long lastReleaseTime;
|
||||
|
||||
/** The time the last released connection expires and shouldn't be reused. */
|
||||
@GuardedBy("this")
|
||||
protected long connectionExpiresTime;
|
||||
protected volatile long connectionExpiresTime;
|
||||
|
||||
/** Indicates whether this connection manager is shut down. */
|
||||
protected volatile boolean isShutDown;
|
||||
|
@ -205,7 +205,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
* @return a connection that can be used to communicate
|
||||
* along the given route
|
||||
*/
|
||||
public synchronized ManagedClientConnection getConnection(HttpRoute route, Object state) {
|
||||
public ManagedClientConnection getConnection(HttpRoute route, Object state) {
|
||||
if (route == null) {
|
||||
throw new IllegalArgumentException("Route may not be null.");
|
||||
}
|
||||
|
@ -215,6 +215,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
log.debug("Get connection for route " + route);
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (managedConn != null)
|
||||
throw new IllegalStateException(MISUSE_MESSAGE);
|
||||
|
||||
|
@ -254,8 +255,9 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
|
||||
return managedConn;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void releaseConnection(
|
||||
public void releaseConnection(
|
||||
ManagedClientConnection conn,
|
||||
long validDuration, TimeUnit timeUnit) {
|
||||
assertStillUp();
|
||||
|
@ -271,6 +273,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
}
|
||||
|
||||
ConnAdapter sca = (ConnAdapter) conn;
|
||||
synchronized (sca) {
|
||||
if (sca.poolEntry == null)
|
||||
return; // already released
|
||||
ClientConnectionManager manager = sca.getManager();
|
||||
|
@ -278,7 +281,6 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
throw new IllegalArgumentException
|
||||
("Connection not obtained from this manager.");
|
||||
}
|
||||
|
||||
try {
|
||||
// make sure that the response has been read completely
|
||||
if (sca.isOpen() && (this.alwaysShutDown ||
|
||||
|
@ -300,6 +302,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
iox);
|
||||
} finally {
|
||||
sca.detach();
|
||||
synchronized (this) {
|
||||
managedConn = null;
|
||||
lastReleaseTime = System.currentTimeMillis();
|
||||
if(validDuration > 0)
|
||||
|
@ -308,14 +311,17 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
connectionExpiresTime = Long.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void closeExpiredConnections() {
|
||||
if(System.currentTimeMillis() >= connectionExpiresTime) {
|
||||
public void closeExpiredConnections() {
|
||||
long time = connectionExpiresTime;
|
||||
if (System.currentTimeMillis() >= time) {
|
||||
closeIdleConnections(0, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void closeIdleConnections(long idletime, TimeUnit tunit) {
|
||||
public void closeIdleConnections(long idletime, TimeUnit tunit) {
|
||||
assertStillUp();
|
||||
|
||||
// idletime can be 0 or negative, no problem there
|
||||
|
@ -323,6 +329,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
throw new IllegalArgumentException("Time unit must not be null.");
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if ((managedConn == null) && uniquePoolEntry.connection.isOpen()) {
|
||||
final long cutoff =
|
||||
System.currentTimeMillis() - tunit.toMillis(idletime);
|
||||
|
@ -336,14 +343,16 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void shutdown() {
|
||||
|
||||
public void shutdown() {
|
||||
this.isShutDown = true;
|
||||
|
||||
if (managedConn != null)
|
||||
managedConn.detach();
|
||||
ConnAdapter conn = managedConn;
|
||||
if (conn != null)
|
||||
conn.detach();
|
||||
|
||||
synchronized (this) {
|
||||
try {
|
||||
if (uniquePoolEntry != null) // and connection open?
|
||||
uniquePoolEntry.shutdown();
|
||||
|
@ -352,6 +361,8 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
log.debug("Problem while shutting down manager.", iox);
|
||||
} finally {
|
||||
uniquePoolEntry = null;
|
||||
managedConn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,10 +370,13 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
* @deprecated no longer used
|
||||
*/
|
||||
@Deprecated
|
||||
protected synchronized void revokeConnection() {
|
||||
if (managedConn == null)
|
||||
protected void revokeConnection() {
|
||||
ConnAdapter conn = managedConn;
|
||||
if (conn == null)
|
||||
return;
|
||||
managedConn.detach();
|
||||
conn.detach();
|
||||
|
||||
synchronized (this) {
|
||||
try {
|
||||
uniquePoolEntry.shutdown();
|
||||
} catch (IOException iox) {
|
||||
|
@ -370,6 +384,7 @@ public class SingleClientConnManager implements ClientConnectionManager {
|
|||
log.debug("Problem while shutting down connection.", iox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The pool entry for this connection manager.
|
||||
|
|
Loading…
Reference in New Issue