package eu.choreos.vv.loadgenerator;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import eu.choreos.vv.client.Client;
import eu.choreos.vv.data.ReportData;
import eu.choreos.vv.experiments.Experiment;
import eu.choreos.vv.loadgenerator.strategy.LoadGenerationStrategy;
/**
* Load generator that trigger the requests as fast as possible
*
*/
public class ParallelLoadGenerator <K, T> implements LoadGenerator<K, T>, Callable<Double> {
static final String LABEL = "response time (msec)";
private int poolSize;
private int timeout;
private Client<K, T> client;
private LoadGenerationStrategy strategy;
protected long delay;
@Override
public String getLabel() {
return LABEL;
}
@Override
public ReportData execute(int numberOfCalls, Client<K, T> client)
throws Exception {
final ExecutorService executorService = Executors
.newFixedThreadPool(poolSize);
final List<Future<Double>> futureResults = new ArrayList<Future<Double>>();
final List<Number> measurements = new ArrayList<Number>();
Date start, end;
this.client = client;
strategy.setMeanDelay(delay);
strategy.setup();
try {
start = new Date();
for (int i = 0; i < numberOfCalls; i++) {
strategy.beforeRequest();
performRequest(executorService, futureResults);
strategy.afterRequest();
}
executorService.shutdown();
while (!executorService.awaitTermination(timeout, TimeUnit.SECONDS))
;
end = new Date();
} catch (InterruptedException e) {
executorService.shutdownNow();
throw e;
}
for (Future<Double> future : futureResults)
measurements.add(future.get());
ReportData report = new ReportData();
report.setMeasurements("responseTime", measurements);
report.setStartTime(start);
report.setEndTime(end);
return report;
}
protected void performRequest(final ExecutorService executorService,
final List<Future<Double>> futureResults) throws Exception {
Future<Double> result = executorService.submit(this);
futureResults.add(result);
}
public LoadGenerationStrategy getStrategy() {
return strategy;
}
public void setStrategy(LoadGenerationStrategy strategy) {
this.strategy = strategy;
}
@Override
public void setDelay(long delay) {
this.delay = delay;
}
public long getDelay() {
return delay;
}
public int getPoolSize() {
return poolSize;
}
public void setPoolSize(int poolSize) {
this.poolSize = poolSize;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
// public static void sleep(long delay) throws InterruptedException {
// long millis = delay / 1000000;
// int nanos = (int) (delay % 1000000);
// Thread.sleep(millis, nanos);
//
// }
/**
* Calls the other methods in a proper sequence. It can be used by an
* ExecutorService.
*
* @return finalMeasurement() - initialMeasurement()
*/
@Override
public Double call() throws Exception {
K valueBefore = client.beforeRequest();
double start = System.currentTimeMillis();
T valueRequest = client.request(valueBefore);
double end = System.currentTimeMillis();
client.afterRequest(valueRequest);
return (end - start);
}
}