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();
}
}