/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wicket.threadtest.tester;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.wicket.threadtest.tester.CommandRunner.CommandRunnerObserver;
import org.apache.wicket.util.time.Duration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author eelcohillenius
*/
public final class Tester implements CommandRunnerObserver
{
private static final Logger log = LoggerFactory.getLogger(Tester.class);
private static HttpClientParams params;
static
{
params = new HttpClientParams();
params.setParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, true);
}
/**
* Main method for just starting the server
*
* @param args
*/
public static void main(String[] args)
{
// start server on its own
int port = 8090;
if (args.length > 0)
{
port = Integer.valueOf(args[0]);
}
Server server = startServer(port);
try
{
server.start();
}
catch (Exception e)
{
e.printStackTrace();
try
{
server.stop();
}
catch (Exception e1)
{
e1.printStackTrace();
}
System.exit(1);
}
}
/**
* Start Jetty server instance and return the handle.
*
* @param port
* @return server handle
*/
private static Server startServer(int port)
{
Server server;
// start up server
server = new Server(port);
WebAppContext ctx = new WebAppContext("./src/main/webapp", "/");
server.setHandler(ctx);
try
{
server.start();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
return server;
}
private int activeThreads = 0;
private final List<Command> commands;
private String host = "localhost";
/**
* if true, each thread will represent a seperate session. If false, the test behaves like one
* client issuing multiple concurrent requests.
*/
private final boolean multipleSessions;
private final int numberOfThreads;
private int port = 8090;
/**
* Construct.
*
* @param command
* Command to execute
* @param numberOfThreads
* Number of threads to run the commands. Each thread runs all commands
* @param multipleSessions
* if true, each thread will represent a seperate session. If false, the test behaves
* like one client issuing multiple concurrent requests
*/
public Tester(Command command, int numberOfThreads, boolean multipleSessions)
{
this(Arrays.asList(command), numberOfThreads, multipleSessions);
}
/**
* Construct.
*
* @param commands
* Commands to execute
* @param numberOfThreads
* Number of threads to run the commands. Each thread runs all commands
* @param multipleSessions
* if true, each thread will represent a separate session. If false, the test behaves
* like one client issuing multiple concurrent requests
*/
public Tester(List<Command> commands, int numberOfThreads, boolean multipleSessions)
{
this.commands = commands;
this.numberOfThreads = numberOfThreads;
this.multipleSessions = multipleSessions;
}
/**
* Gets host.
*
* @return host
*/
public String getHost()
{
return host;
}
/**
* Gets port.
*
* @return port
*/
public int getPort()
{
return port;
}
public synchronized void onDone(CommandRunner runner)
{
activeThreads--;
notifyAll();
}
public synchronized void onError(CommandRunner runner, Exception e)
{
activeThreads--;
notifyAll();
}
/**
* Runs the test.
*
* @throws Exception
*/
public void run() throws Exception
{
activeThreads = 0;
HttpConnectionManagerParams connManagerParams = new HttpConnectionManagerParams();
connManagerParams.setDefaultMaxConnectionsPerHost(numberOfThreads * 2);
MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager();
manager.setParams(connManagerParams);
Server server = null;
GetMethod getMethod = new GetMethod("http://localhost:" + port + "/");
try
{
getMethod.setFollowRedirects(true);
HttpClient httpClient = new HttpClient(params, manager);
int code = httpClient.executeMethod(getMethod);
if (code != 200)
{
server = startServer(port);
}
}
catch (Exception e)
{
server = startServer(port);
}
finally
{
getMethod.releaseConnection();
}
try
{
ThreadGroup g = new ThreadGroup("runners");
Thread[] threads = new Thread[numberOfThreads];
HttpClient client = null;
for (int i = 0; i < numberOfThreads; i++)
{
if (multipleSessions)
{
client = new HttpClient(params, manager);
client.getHostConfiguration().setHost(host, port);
}
else
{
if (client == null)
{
client = new HttpClient(params, manager);
client.getHostConfiguration().setHost(host, port);
}
}
threads[i] = new Thread(g, new CommandRunner(commands, client, this));
}
long start = System.currentTimeMillis();
for (int i = 0; i < numberOfThreads; i++)
{
activeThreads++;
threads[i].start();
}
while (activeThreads > 0)
{
synchronized (this)
{
wait();
}
}
long end = System.currentTimeMillis();
long time = end - start;
log.info("\n******** finished in " + Duration.milliseconds(time) + " (" + time +
" milis)");
}
finally
{
MultiThreadedHttpConnectionManager.shutdownAll();
if (server != null)
{
server.stop();
}
}
}
/**
* Sets host.
*
* @param host
* host
*/
public void setHost(String host)
{
this.host = host;
}
/**
* Sets port.
*
* @param port
* port
*/
public void setPort(int port)
{
this.port = port;
}
}