package lsr.paxos.test;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import lsr.common.Configuration;
import lsr.common.ProcessDescriptor;
import lsr.paxos.replica.Replica;
import lsr.service.AbstractService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Pongs the requests to the client.
*/
public class EchoService extends AbstractService {
private byte[] last = new byte[0];
private final Random random;
private volatile int lastSeqNo = 0;
private final static long SAMPLING_MS = 100;
private final static long MIN_SAMPLING_MS = 25;
public EchoService() {
super();
random = new Random(System.currentTimeMillis() + this.hashCode());
// Creates an executor with named thread that runs task printing stats
Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "EchoServiceRPS");
thread.setDaemon(true);
thread.setPriority(Thread.MAX_PRIORITY);
return thread;
}
}).scheduleAtFixedRate(new Runnable() {
private int lastSeenSeqNo = 0;
private long lastSeenTime = 0;
public void run() {
// Hrm.... Java and the behavior of 'scheduleAtFixedRate' are
// far far from what one expects...
long time = System.currentTimeMillis();
if (time - lastSeenTime <= MIN_SAMPLING_MS)
return;
int seqNo = lastSeqNo;
logger.info(ProcessDescriptor.processDescriptor.logMark_Benchmark, "RPS: {}",
(seqNo - lastSeenSeqNo) * (1000.0 / (time - lastSeenTime)));
lastSeenSeqNo = seqNo;
lastSeenTime = time;
}
}, SAMPLING_MS, SAMPLING_MS, TimeUnit.MILLISECONDS);
}
public byte[] execute(byte[] value, int seqNo) {
logger.info("<Service> Executed request no. {}", seqNo);
if (random.nextInt(10000) == 0) {
assert (last != null);
fireSnapshotMade(seqNo + 1, new byte[] {1}, value);
logger.info("Made snapshot");
}
last = value;
lastSeqNo = seqNo;
return value;
}
public void askForSnapshot(int lastSnapshotInstance) {
// ignore
}
public void forceSnapshot(int lastSnapshotInstance) {
// ignore
}
public void updateToSnapshot(int instanceId, byte[] snapshot) {
// ignore
}
public static void main(String[] args) throws IOException, InterruptedException,
ExecutionException {
if (args.length > 2) {
usage();
System.exit(1);
}
int localId = Integer.parseInt(args[0]);
Configuration conf = new Configuration();
Replica replica = new Replica(conf, localId, new EchoService());
replica.start();
System.in.read();
System.exit(-1);
}
private static void usage() {
System.out.println("Invalid arguments. Usage:\n"
+ " java " + EchoService.class.getCanonicalName() + " <replicaID>");
}
private static final Logger logger = LoggerFactory.getLogger(EchoService.class);
}