Changes in preparation for #340040 (Support for a total timeout).

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3044 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Simone Bordet 2011-04-29 13:47:09 +00:00
parent 9be79e1750
commit 26751210e4
3 changed files with 89 additions and 31 deletions

View File

@ -130,22 +130,36 @@ public class HttpConnection extends AbstractConnection
scep.scheduleWrite();
}
long exchTimeout = _exchange.getTimeout();
if (exchTimeout > 0)
{
if (exchTimeout!=_destination.getHttpClient().getTimeout())
_endp.setMaxIdleTime((int)exchTimeout);
_destination.getHttpClient().schedule(_timeout, exchTimeout);
}
else
{
_destination.getHttpClient().schedule(_timeout);
}
scheduleTimeout();
return true;
}
}
protected void scheduleTimeout() throws IOException
{
HttpClient httpClient = _destination.getHttpClient();
long exchangeTimeout = _exchange.getTimeout();
long timeout = exchangeTimeout;
if (timeout <= 0)
timeout = httpClient.getTimeout();
long endPointTimeout = _endp.getMaxIdleTime();
if (timeout > 0 && timeout > endPointTimeout)
{
// Make it larger than the exchange timeout so that there are
// no races in trying to close the endpoint between the 2 timeouts
_endp.setMaxIdleTime(2 * (int)timeout);
}
if (exchangeTimeout > 0)
httpClient.schedule(_timeout, exchangeTimeout);
else
httpClient.schedule(_timeout);
}
public Connection handle() throws IOException
{
if (_exchange != null)
@ -369,12 +383,13 @@ public class HttpConnection extends AbstractConnection
if (_exchange != null)
{
HttpExchange exchange=_exchange;
_exchange.disassociate();
if (_exchange.getTimeout()>0 && _exchange.getTimeout()!=getDestination().getHttpClient().getTimeout())
_endp.setMaxIdleTime((int)getDestination().getHttpClient().getTimeout());
exchange.disassociate();
_exchange = null;
// Reset the maxIdleTime because it may have been changed
if (!close)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
@ -714,7 +729,7 @@ public class HttpConnection extends AbstractConnection
{
if (ex != null && ex.getStatus() < HttpExchange.STATUS_COMPLETED)
ex.setStatus(HttpExchange.STATUS_EXPIRED);
try
{
close();

View File

@ -19,7 +19,6 @@ import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
@ -72,7 +71,7 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
_sslBuffers = BuffersFactory.newBuffers(
direct?Type.DIRECT:Type.INDIRECT,ssl_session.getApplicationBufferSize(),
direct?Type.DIRECT:Type.INDIRECT,ssl_session.getApplicationBufferSize(),
direct?Type.DIRECT:Type.INDIRECT,_maxBuffers);
direct?Type.DIRECT:Type.INDIRECT,_maxBuffers);
_httpClient._threadPool.dispatch(this);
}
@ -105,12 +104,8 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
}
else
{
channel.configureBlocking( true );
channel.socket().setSoTimeout(_httpClient.getConnectTimeout());
channel.socket().connect(address.toSocketAddress(),_httpClient.getConnectTimeout());
channel.configureBlocking(false);
channel.socket().setSoTimeout((int)_httpClient.getTimeout());
channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
_selectorManager.register( channel, destination );
}
@ -192,17 +187,17 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
if (dest.isProxied())
{
SSLEngine engine=newSslEngine();
ep = new ProxySelectChannelEndPoint(channel,selectSet,key,_sslBuffers,engine);
ep = new ProxySelectChannelEndPoint(channel, selectSet, key, _sslBuffers, engine, (int)_httpClient.getIdleTimeout());
}
else
{
SSLEngine engine=newSslEngine();
ep = new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,engine);
ep = new SslSelectChannelEndPoint(_sslBuffers, channel, selectSet, key, engine, (int)_httpClient.getIdleTimeout());
}
}
else
{
ep=new SelectChannelEndPoint(channel,selectSet,key);
ep = new SelectChannelEndPoint(channel, selectSet, key, (int)_httpClient.getIdleTimeout());
}
HttpConnection connection=(HttpConnection)ep.getConnection();
@ -281,10 +276,10 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
private final SelectChannelEndPoint plainEndPoint;
private volatile boolean upgraded = false;
public ProxySelectChannelEndPoint(SocketChannel channel, SelectorManager.SelectSet selectSet, SelectionKey key, Buffers sslBuffers, SSLEngine engine) throws IOException
public ProxySelectChannelEndPoint(SocketChannel channel, SelectorManager.SelectSet selectSet, SelectionKey key, Buffers sslBuffers, SSLEngine engine, int maxIdleTimeout) throws IOException
{
super(sslBuffers, channel, selectSet, key, engine);
this.plainEndPoint = new SelectChannelEndPoint(channel, selectSet, key);
super(sslBuffers, channel, selectSet, key, engine, maxIdleTimeout);
this.plainEndPoint = new SelectChannelEndPoint(channel, selectSet, key, maxIdleTimeout);
}
public void upgrade()

View File

@ -16,13 +16,11 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
@ -94,11 +92,17 @@ public class TimeoutExchangeTest
}
private void startClient(long clientTimeout) throws Exception
{
startClient(clientTimeout, 20000);
}
private void startClient(long clientTimeout, long maxIdleTimeout) throws Exception
{
_httpClient = new HttpClient();
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(2);
_httpClient.setTimeout(clientTimeout);
_httpClient.setIdleTimeout(maxIdleTimeout);
_httpClient.start();
}
@ -184,6 +188,50 @@ public class TimeoutExchangeTest
Assert.assertFalse(httpExchange.isErrorOccurred());
}
@Test
public void testDefaultTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception
{
startClient(3000, 1000);
long serverSleep = 2000;
// The idle timeout is shorter than the default timeout, but will be
// temporarily increased on the endpoint in order for the exchange to complete.
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS));
Assert.assertFalse(httpExchange.isTimeoutOccurred());
Assert.assertTrue(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
@Test
public void testExchangeTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception
{
startClient(4000, 3000);
long serverSleep = 1000;
long exchangeTimeout = 2000;
// The idle timeout is shorter than the default timeout, but will be
// temporarily increased on the endpoint in order for the exchange to complete.
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
httpExchange.setTimeout(exchangeTimeout);
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS));
Assert.assertFalse(httpExchange.isTimeoutOccurred());
Assert.assertTrue(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
private class CustomContentExchange extends ContentExchange
{
private final CountDownLatch _doneLatch = new CountDownLatch(1);