Fixes #341171 (Locking in HttpDestination blocks all requests to the same address).

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2963 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Simone Bordet 2011-04-04 14:30:11 +00:00
parent a2b1ceabc8
commit 8df474ea97
2 changed files with 57 additions and 40 deletions

View File

@ -30,6 +30,7 @@ jetty-7.4.0-SNAPSHOT
+ JETTY-1354 Added jetty-nested + JETTY-1354 Added jetty-nested
+ Ensure generated fragment names are unique + Ensure generated fragment names are unique
+ Added extra session removal test + Added extra session removal test
+ 341171 Locking in HttpDestination blocks all requests to the same address
jetty-7.3.1.v20110307 7 March 2011 jetty-7.3.1.v20110307 7 March 2011
+ 316382 Support a more strict SSL option with certificates + 316382 Support a more strict SSL option with certificates

View File

@ -10,6 +10,7 @@
// http://www.opensource.org/licenses/apache2.0.php // http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses. // You may elect to redistribute this code under either of these licenses.
// ======================================================================== // ========================================================================
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.io.IOException; import java.io.IOException;
@ -35,7 +36,6 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
/** /**
*
* @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $ * @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $
*/ */
public class HttpDestination public class HttpDestination
@ -81,7 +81,8 @@ public class HttpDestination
_ssl = ssl; _ssl = ssl;
_maxConnections = maxConnections; _maxConnections = maxConnections;
String addressString = address.getHost(); String addressString = address.getHost();
if (address.getPort() != (_ssl ? 443 : 80)) addressString += ":" + address.getPort(); if (address.getPort() != (_ssl ? 443 : 80))
addressString += ":" + address.getPort();
_hostHeader = new ByteArrayBuffer(addressString); _hostHeader = new ByteArrayBuffer(addressString);
} }
@ -149,35 +150,40 @@ public class HttpDestination
* Get a connection. We either get an idle connection if one is available, or * Get a connection. We either get an idle connection if one is available, or
* we make a new connection, if we have not yet reached maxConnections. If we * we make a new connection, if we have not yet reached maxConnections. If we
* have reached maxConnections, we wait until the number reduces. * have reached maxConnections, we wait until the number reduces.
*
* @param timeout max time prepared to block waiting to be able to get a connection * @param timeout max time prepared to block waiting to be able to get a connection
* @return * @return a HttpConnection for this destination
* @throws IOException * @throws IOException if an I/O error occurs
*/ */
private HttpConnection getConnection(long timeout) throws IOException private HttpConnection getConnection(long timeout) throws IOException
{ {
HttpConnection connection = null; HttpConnection connection = null;
while ((connection == null) && (connection = getIdleConnection()) == null && timeout>0) while ((connection == null) && (connection = getIdleConnection()) == null && timeout > 0)
{ {
boolean starting = false; boolean startConnection = false;
synchronized (this) synchronized (this)
{ {
int totalConnections = _connections.size() + _pendingConnections; int totalConnections = _connections.size() + _pendingConnections;
if (totalConnections < _maxConnections) if (totalConnections < _maxConnections)
{ {
_newConnection++; _newConnection++;
startNewConnection(); startConnection = true;
starting = true;
} }
} }
if (!starting) if (startConnection)
{ {
startNewConnection();
try try
{ {
Thread.currentThread(); Object o = _newQueue.take();
Thread.sleep(200); if (o instanceof HttpConnection)
timeout-=200; {
connection = (HttpConnection)o;
}
else
throw (IOException)o;
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
@ -186,21 +192,17 @@ public class HttpDestination
} }
else else
{ {
try try
{ {
Object o = _newQueue.take(); Thread.currentThread();
if (o instanceof HttpConnection) Thread.sleep(200);
{ timeout -= 200;
connection = (HttpConnection)o; }
} catch (InterruptedException e)
else {
throw (IOException)o; Log.ignore(e);
} }
catch (InterruptedException e) }
{
Log.ignore(e);
}
}
} }
return connection; return connection;
} }
@ -220,17 +222,17 @@ public class HttpDestination
{ {
synchronized (this) synchronized (this)
{ {
if (connection!=null) if (connection != null)
{ {
_connections.remove(connection); _connections.remove(connection);
connection.close(); connection.close();
connection=null; connection = null;
} }
if (_idle.size() > 0) if (_idle.size() > 0)
connection = _idle.remove(_idle.size()-1); connection = _idle.remove(_idle.size() - 1);
} }
if (connection==null) if (connection == null)
return null; return null;
// Check if the connection was idle, // Check if the connection was idle,
@ -248,8 +250,8 @@ public class HttpDestination
{ {
_pendingConnections++; _pendingConnections++;
} }
final Connector connector=_client._connector; final Connector connector = _client._connector;
if (connector!=null) if (connector != null)
connector.startConnection(this); connector.startConnection(this);
} }
catch (Exception e) catch (Exception e)
@ -263,6 +265,7 @@ public class HttpDestination
{ {
Throwable connect_failure = null; Throwable connect_failure = null;
boolean startConnection = false;
synchronized (this) synchronized (this)
{ {
_pendingConnections--; _pendingConnections--;
@ -280,10 +283,13 @@ public class HttpDestination
// Since an existing connection had failed, we need to create a // Since an existing connection had failed, we need to create a
// connection if the queue is not empty and client is running. // connection if the queue is not empty and client is running.
if (!_queue.isEmpty() && _client.isStarted()) if (!_queue.isEmpty() && _client.isStarted())
startNewConnection(); startConnection = true;
} }
} }
if (startConnection)
startNewConnection();
if (connect_failure != null) if (connect_failure != null)
{ {
try try
@ -401,12 +407,16 @@ public class HttpDestination
} }
else else
{ {
boolean startConnection = false;
synchronized (this) synchronized (this)
{ {
_connections.remove(connection); _connections.remove(connection);
if (!_queue.isEmpty()) if (!_queue.isEmpty())
startNewConnection(); startConnection = true;
} }
if (startConnection)
startNewConnection();
} }
} }
@ -421,14 +431,18 @@ public class HttpDestination
Log.ignore(e); Log.ignore(e);
} }
boolean startConnection = false;
synchronized (this) synchronized (this)
{ {
_idle.remove(connection); _idle.remove(connection);
_connections.remove(connection); _connections.remove(connection);
if (!_queue.isEmpty() && _client.isStarted()) if (!_queue.isEmpty() && _client.isStarted())
startNewConnection(); startConnection = true;
} }
if (startConnection)
startNewConnection();
} }
public void send(HttpExchange ex) throws IOException public void send(HttpExchange ex) throws IOException
@ -509,14 +523,16 @@ public class HttpDestination
} }
else else
{ {
boolean startConnection = false;
synchronized (this) synchronized (this)
{ {
_queue.add(ex); _queue.add(ex);
if (_connections.size() + _pendingConnections < _maxConnections) if (_connections.size() + _pendingConnections < _maxConnections)
{ startConnection = true;
startNewConnection();
}
} }
if (startConnection)
startNewConnection();
} }
} }
@ -526,7 +542,7 @@ public class HttpDestination
{ {
// If server closes the connection, put the exchange back // If server closes the connection, put the exchange back
// to the exchange queue and recycle the connection // to the exchange queue and recycle the connection
if(!connection.send(exchange)) if (!connection.send(exchange))
{ {
_queue.addFirst(exchange); _queue.addFirst(exchange);
returnIdleConnection(connection); returnIdleConnection(connection);