package lsr.paxos.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import lsr.common.Configuration;
import lsr.paxos.client.Client;
import lsr.paxos.client.ReplicationException;
public class GenericMultiClient {
private Vector<ClientThread> clients = new Vector<ClientThread>();
private AtomicInteger runningClients = new AtomicInteger(0);
private final Semaphore finishedLock = new Semaphore(1);
private long startTime;
private int lastRequestCount;
private final Random rnd = new Random();
private final boolean randomRequests;
private final int requestSize;
private final Configuration configuration;
class ClientThread extends Thread {
private final byte[] request;
final Client client;
private ArrayBlockingQueue<Integer> sends;
public ClientThread() throws IOException {
setDaemon(true);
client = new Client(configuration);
sends = new ArrayBlockingQueue<Integer>(128);
request = new byte[requestSize];
}
@Override
public void run() {
try {
client.connect();
while (true) {
Integer count;
count = sends.take();
for (int i = 0; i < count; i++) {
if (randomRequests)
rnd.nextBytes(request);
if (Thread.interrupted()) {
break;
}
@SuppressWarnings("unused")
byte[] response;
response = client.execute(request);
}
int stillActive = runningClients.decrementAndGet();
if (stillActive == 0) {
finishedSend();
}
}
} catch (ReplicationException e) {
System.err.println(e.getLocalizedMessage());
System.exit(1);
} catch (InterruptedException e) {
int stillActive = runningClients.decrementAndGet();
if (stillActive == 0) {
finishedSend();
}
}
}
public void execute(int count) throws InterruptedException {
sends.put(count);
}
}
public GenericMultiClient(int requestSize, boolean randomRequests) throws IOException {
this.configuration = new Configuration();
this.requestSize = requestSize;
this.randomRequests = randomRequests;
}
public void run() throws IOException, ReplicationException, InterruptedException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String line = reader.readLine();
if (line == null)
// EOF
break;
String[] args = line.split(" ");
if (args[0].equals("bye")) {
for (ClientThread client : clients)
client.interrupt();
break;
}
if (args[0].equals("kill")) {
for (ClientThread client : clients)
client.interrupt();
continue;
}
if (args.length < 2) {
System.err.println("Wrong command length! Expected:");
printUsage();
continue;
}
int clientCount;
int requests;
try {
clientCount = Integer.parseInt(args[0]);
requests = Integer.parseInt(args[1]);
} catch (NumberFormatException e) {
System.err.println("Wrong argument! Expected:");
printUsage();
continue;
}
execute(clientCount, requests);
}
}
public void finishedSend() {
long duration = System.currentTimeMillis() - startTime;
System.err.println(String.format("Finished %d %4.2f\n", duration,
(double) lastRequestCount / duration));
finishedLock.release();
}
private void execute(int clientCount, int requests)
throws ReplicationException, IOException, InterruptedException {
finishedLock.acquire();
for (int i = clients.size(); i < clientCount; i++) {
ClientThread client = new ClientThread();
client.start();
clients.add(client);
}
runningClients.addAndGet(clientCount);
startTime = System.currentTimeMillis();
lastRequestCount = clientCount * requests;
for (int i = 0; i < clientCount; i++) {
clients.get(i).execute(requests);
}
}
public static void main(String[] args) throws IOException, ReplicationException,
InterruptedException {
if (args.length != 2) {
showUsage();
System.exit(1);
}
printUsage();
GenericMultiClient client = new GenericMultiClient(Integer.parseInt(args[0]),
Boolean.parseBoolean(args[1]));
client.run();
}
private static void showUsage() {
System.out.println(GenericMultiClient.class.getCanonicalName() +
" <requestSize> <randomEachRequest>");
}
private static void printUsage() {
System.out.println("bye -- quits (killing clients if necessay)");
System.out.println("kill -- stops all clients");
System.out.println("<clientCount> <requestsPerClient> [<any string>] -- sends requests");
}
}