Merge remote-tracking branch 'origin/master' into jetty-8

This commit is contained in:
Jan Bartel 2011-11-21 18:18:09 +11:00
commit 0e9449ac85
16 changed files with 1920 additions and 104 deletions

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -55,7 +56,7 @@ public class LikeJettyXml
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(100);
threadPool.setMaxThreads(500);
server.setThreadPool(threadPool);
// Setup Connectors
@ -63,7 +64,7 @@ public class LikeJettyXml
connector.setPort(8080);
connector.setMaxIdleTime(30000);
connector.setConfidentialPort(8443);
connector.setStatsOn(true);
connector.setStatsOn(false);
server.setConnectors(new Connector[]
{ connector });
@ -86,10 +87,16 @@ public class LikeJettyXml
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
});
ssl_connector.setStatsOn(true);
ssl_connector.setStatsOn(false);
server.addConnector(ssl_connector);
ssl_connector.open();
SslSocketConnector ssl2_connector = new SslSocketConnector(cf);
ssl2_connector.setPort(8444);
ssl2_connector.setStatsOn(false);
server.addConnector(ssl2_connector);
ssl2_connector.open();
/*

View File

@ -1,6 +1,8 @@
package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@ -33,11 +35,26 @@ public class Curl
client.start();
boolean async=true;
boolean dump= false;
boolean verbose= false;
final CountDownLatch latch = new CountDownLatch(args.length);
int urls=0;
for (String arg : args)
{
if (!arg.startsWith("-"))
urls++;
}
final CountDownLatch latch = new CountDownLatch(urls);
for (String arg : args)
{
if ("--verbose".equals(arg))
{
verbose=true;
continue;
}
if ("--sync".equals(arg))
{
async=false;
@ -63,6 +80,7 @@ public class Curl
}
final boolean d = dump;
final boolean v = verbose;
HttpExchange ex = new HttpExchange()
{
AtomicBoolean counted=new AtomicBoolean(false);
@ -105,6 +123,7 @@ public class Curl
super.onResponseContent(content);
if (d)
System.out.print(content.toString());
if (v)
System.err.println("got "+content.length());
}
@ -116,6 +135,7 @@ public class Curl
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
super.onResponseHeader(name,value);
if (v)
System.err.println(name+": "+value);
}
@ -127,6 +147,7 @@ public class Curl
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
if (v)
System.err.println();
}
@ -138,6 +159,7 @@ public class Curl
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
super.onResponseStatus(version,status,reason);
if (v)
System.err.println(version+" "+status+" "+reason);
}
};

View File

@ -0,0 +1,211 @@
package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/* ------------------------------------------------------------ */
/**
*/
public class Siege
{
private static final class ConcurrentExchange extends HttpExchange
{
private final long _start=System.currentTimeMillis();
private final HttpClient _client;
private final CountDownLatch _latch;
volatile int _status;
volatile int _count;
volatile long _bytes;
final List<String> _uris;
final int _repeats;
int _u;
int _r;
AtomicBoolean counted=new AtomicBoolean(false);
public ConcurrentExchange(HttpClient client,CountDownLatch latch, List<String> uris, int repeats)
{
_client = client;
_latch = latch;
_uris = uris;
_repeats = repeats;
}
@Override
protected void onConnectionFailed(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onConnectionFailed(ex);
}
@Override
protected void onException(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onException(ex);
}
@Override
protected void onExpire()
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onExpire();
}
@Override
protected void onResponseComplete() throws IOException
{
if (_status==200)
_count++;
if (!next() && !counted.getAndSet(true))
{
_latch.countDown();
long duration=System.currentTimeMillis()-_start;
System.err.printf("Got %d/%d with %dB in %dms %d%n",_count,_uris.size()*_repeats,_bytes,duration,_latch.getCount());
}
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseContent(Buffer content) throws IOException
{
_bytes+=content.length();
super.onResponseContent(content);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer)
*/
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
super.onResponseHeader(name,value);
if ("Set-Cookie".equalsIgnoreCase(name.toString()))
{
String v=value.toString();
int c = v.indexOf(';');
if (c>=0)
v=v.substring(0,c);
addRequestHeader("Cookie",v);
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete()
*/
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer)
*/
@Override
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
_status=status;
super.onResponseStatus(version,status,reason);
}
public boolean next()
{
if (_u>=_uris.size())
{
_u=0;
_r++;
if (_r>=_repeats)
return false;
}
String uri=_uris.get(_u++);
reset();
setMethod(HttpMethods.GET);
setURL(uri);
try
{
_client.send(this);
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
}
public static void main(String[] args)
throws Exception
{
if (args.length==0)
args=new String[]
{ "-c", "2", "-r", "2", "http://localhost:8080/dump", "http://localhost:8080/d.txt"};
int concurrent=1;
int repeats=1;
final List<String> uris = new ArrayList<String>();
for (int i=0; i<args.length; i++)
{
String arg=args[i];
if ("-c".equals(arg))
{
concurrent=Integer.parseInt(args[++i]);
continue;
}
if ("-r".equals(arg))
{
repeats=Integer.parseInt(args[++i]);
continue;
}
uris.add(arg);
}
QueuedThreadPool pool = new QueuedThreadPool();
pool.setMaxThreads(500);
pool.setDaemon(true);
HttpClient client = new HttpClient();
client.setThreadPool(pool);
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setIdleTimeout(30000);
client.setConnectTimeout(30000);
client.setMaxConnectionsPerAddress(concurrent*2);
client.start();
final CountDownLatch latch = new CountDownLatch(concurrent);
for (int i=0;i<concurrent;i++)
{
ConcurrentExchange ex = new ConcurrentExchange(client,latch,uris,repeats);
if (!ex.next())
latch.countDown();
}
latch.await();
client.stop();
pool.stop();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -162,6 +162,8 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
// we are not interested in further selecting
_key.interestOps(0);
if (!_dispatched)
updateKey();
return;
}

View File

@ -585,15 +585,6 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// Log and dump some status
_paused=true;
LOG.warn("Selector {} is too busy, pausing!",this);
final SelectSet set = this;
SelectorManager.this.dispatch(
new Runnable(){
public void run()
{
System.err.println(set+":\n"+set.dump());
}
public String toString() {return "Dump-"+super.toString();}
});
}
}
}
@ -991,6 +982,16 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
dumpto.add(key.attachment()+" - - ");
}
}
/* ------------------------------------------------------------ */
public String toString()
{
String s=super.toString()+" "+SelectorManager.this.getState();
Selector selector=_selector;
if (selector!=null && selector.isOpen())
s+=",k="+selector.keys().size()+",s="+selector.selectedKeys().size();
return s;
}
}
/* ------------------------------------------------------------ */

View File

@ -16,7 +16,6 @@ package org.eclipse.jetty.io.nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@ -236,7 +235,21 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
/* ------------------------------------------------------------ */
public void onClose()
{
}
/* ------------------------------------------------------------ */
@Override
public void onIdleExpired()
{
try
{
_sslEndPoint.shutdownOutput();
}
catch (IOException e)
{
LOG.warn(e);
super.onIdleExpired();
}
}
/* ------------------------------------------------------------ */
@ -586,6 +599,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
_engine.closeOutbound();
_oshut=true;
}
flush();
}
public boolean isOutputShutdown()
@ -793,7 +807,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
o=_outbound;
u=_unwrapBuf;
}
return "SSL:"+_endp+" "+_engine.getHandshakeStatus()+" i/u/o="+(i==null?0:i.length())+"/"+(u==null?0:u.length())+"/"+(o==null?0:o.length()+(_oshut?" oshut":""));
return "SSL:"+_endp+" "+_engine.getHandshakeStatus()+" i/u/o="+(i==null?0:i.length())+"/"+(u==null?0:u.length())+"/"+(o==null?0:o.length()+(_ishut?" ishut":"")+(_oshut?" oshut":""));
}
}

View File

@ -42,6 +42,7 @@ import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
@ -176,6 +177,11 @@ public abstract class AbstractHttpConnection extends AbstractConnection
_server = server;
}
protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endpoint, HttpParser.EventHandler requestHandler)
{
return new HttpParser(requestBuffers, endpoint, requestHandler);
}
/* ------------------------------------------------------------ */
/**
* @return the parser used by this connection

View File

@ -161,7 +161,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
if (_generator.isIdle() && !_request.getAsyncContinuation().isSuspended())
{
// then no more can happen, so close.
_endp.shutdownOutput();
_endp.close();
}
}

View File

@ -102,6 +102,7 @@ public class BlockingHttpConnection extends AbstractHttpConnection
// Reset the parser/generator
progress=true;
reset();
_endp.flush();
// look for a switched connection instance?
if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
@ -114,7 +115,7 @@ public class BlockingHttpConnection extends AbstractHttpConnection
// TODO Is this required?
if (!_generator.isPersistent() && !_endp.isOutputShutdown())
{
System.err.println("Safety net oshut!!!");
LOG.warn("Safety net oshut!!! Please open a bugzilla");
_endp.shutdownOutput();
}
}

View File

@ -69,6 +69,8 @@ public class ShutdownHandler extends AbstractHandler
private boolean _exitJvm = false;
/**
* Creates a listener that lets the server be shut down remotely (but only from localhost).
*
@ -110,6 +112,10 @@ public class ShutdownHandler extends AbstractHandler
LOG.info("Shutting down by request from " + getRemoteAddr(request));
new Thread()
{
public void run ()
{
try
{
shutdownServer();
@ -123,6 +129,8 @@ public class ShutdownHandler extends AbstractHandler
throw new RuntimeException("Shutting down server",e);
}
}
}.start();
}
private boolean requestFromLocalhost(HttpServletRequest request)
{

View File

@ -31,14 +31,11 @@ import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.server.AsyncHttpConnection;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.util.thread.Timeout.Task;
/* ------------------------------------------------------------------------------- */
/**
@ -297,7 +294,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
/* ------------------------------------------------------------------------------- */
protected AsyncConnection newConnection(SocketChannel channel,final AsyncEndPoint endpoint)
{
return new SelectChannelHttpConnection(SelectChannelConnector.this,endpoint,getServer());
return new AsyncHttpConnection(SelectChannelConnector.this,endpoint,getServer());
}
/* ------------------------------------------------------------ */
@ -310,24 +307,9 @@ public class SelectChannelConnector extends AbstractNIOConnector
channel=_acceptChannel;
}
if (channel==null)
AggregateLifeCycle.dump(out,indent,Arrays.asList(new Object[]{null,"CLOSED",_manager}));
AggregateLifeCycle.dump(out,indent,Arrays.asList(null,"CLOSED",_manager));
else
AggregateLifeCycle.dump(out,indent,Arrays.asList(new Object[]{channel,channel.isOpen()?"OPEN":"CLOSED",_manager}));
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private class SelectChannelHttpConnection extends AsyncHttpConnection
{
private final AsyncEndPoint _endpoint;
private SelectChannelHttpConnection(Connector connector, EndPoint endpoint, Server server)
{
super(connector,endpoint,server);
_endpoint=null;
}
AggregateLifeCycle.dump(out,indent,Arrays.asList(channel,channel.isOpen()?"OPEN":"CLOSED",_manager));
}
/* ------------------------------------------------------------ */

View File

@ -14,16 +14,12 @@
package org.eclipse.jetty.server.ssl;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffers;
@ -33,10 +29,7 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.server.AsyncHttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -541,13 +534,6 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
return integralPort==0||integralPort==request.getServerPort();
}
/* ------------------------------------------------------------------------------- */
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
return super.newEndPoint(channel,selectSet,key);
}
/* ------------------------------------------------------------------------------- */
@Override
protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint)
@ -555,10 +541,8 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
try
{
SSLEngine engine = createSSLEngine(channel);
SslConnection connection = new SslConnection(engine,endpoint);
AsyncConnection delegate = super.newConnection(channel,connection.getSslEndPoint());
SslConnection connection = newSslConnection(endpoint, engine);
AsyncConnection delegate = newPlainConnection(channel, connection.getSslEndPoint());
connection.getSslEndPoint().setConnection(delegate);
connection.setAllowRenegotiate(_sslContextFactory.isAllowRenegotiate());
return connection;
@ -569,6 +553,16 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
}
}
protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint)
{
return super.newConnection(channel, endPoint);
}
protected SslConnection newSslConnection(AsyncEndPoint endpoint, SSLEngine engine)
{
return new SslConnection(engine, endpoint);
}
/* ------------------------------------------------------------ */
/**
* @param channel A channel which if passed is used as to extract remote

View File

@ -14,12 +14,18 @@ package org.eclipse.jetty.server.handler;
//========================================================================
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@ -48,7 +54,35 @@ public class ShutdownHandlerTest
public void shutdownServerWithCorrectTokenAndIPTest() throws Exception
{
setDefaultExpectations();
final CountDownLatch countDown = new CountDownLatch(1);
server.addLifeCycleListener(new AbstractLifeCycle.Listener ()
{
public void lifeCycleStarting(LifeCycle event)
{
}
public void lifeCycleStarted(LifeCycle event)
{
}
public void lifeCycleFailure(LifeCycle event, Throwable cause)
{
}
public void lifeCycleStopping(LifeCycle event)
{
}
public void lifeCycleStopped(LifeCycle event)
{
countDown.countDown();
}
});
shutdownHandler.handle("/shutdown",null,request,response);
boolean stopped = countDown.await(1000, TimeUnit.MILLISECONDS); //wait up to 1 sec to stop
assertTrue("Server lifecycle stop listener called", stopped);
assertEquals("Server should be stopped","STOPPED",server.getState());
}

View File

@ -256,14 +256,7 @@ public class SslContextFactory extends AbstractLifeCycle
{
// verify that keystore and truststore
// parameters are set up correctly
try
{
checkKeyStore();
}
catch(IllegalStateException e)
{
LOG.ignore(e);
}
KeyStore keyStore = loadKeyStore();
KeyStore trustStore = loadTrustStore();
@ -1158,13 +1151,17 @@ public class SslContextFactory extends AbstractLifeCycle
/* ------------------------------------------------------------ */
/**
* Check KetyStore Configuration. Ensures that if keystore has been
* Check KeyStore Configuration. Ensures that if keystore has been
* configured but there's no truststore, that keystore is
* used as truststore.
* @throws IllegalStateException if SslContextFactory configuration can't be used.
*/
public void checkKeyStore()
{
if (_context != null)
return; //nothing to check if using preconfigured context
if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
throw new IllegalStateException("SSL doesn't have a valid keystore");

View File

@ -160,4 +160,25 @@ public class SslContextFactoryTest
{
}
}
@Test
public void testNoKeyConfig() throws Exception
{
SslContextFactory cf = new SslContextFactory();
try
{
((StdErrLog)Log.getLogger(AbstractLifeCycle.class)).setHideStacks(true);
cf.setTrustStore("/foo");
cf.start();
Assert.fail();
}
catch (IllegalStateException e)
{
}
catch (Exception e)
{
Assert.fail("Unexpected exception");
}
}
}