package datastore.bench;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import smartkv.server.bench.TestInformation;
import bftsmart.tom.ServiceProxy;
import bftsmart.tom.TimeoutException;
import datastore.bench.flowsimulations.FlowSimulation;
import datastore.bench.flowsimulations.deviceManager.WorkloadPerFlow;
public abstract class BenchClient implements Runnable{
static long test_start_time = System.currentTimeMillis();
public static void main(String[] args) throws InterruptedException{
if (args.length < 3) {
System.out.println("Usage: ... ThroughputLatencyClient <num. threads> <number of operations per thread> <interval> <verbose?> <stored statistics?> <start_id> <CASE (see above)?>");
System.out.println(MultiFlowTypes.getValues());
System.exit(-1);
}
int numThreads = Integer.parseInt(args[0]);
int numberOfFlows = Integer.parseInt(args[1]);
boolean verbose =Boolean.parseBoolean(args[3]);
long interval = Integer.parseInt(args[2]);
boolean storedStatistics = Boolean.parseBoolean(args[4]);
int start_id = Integer.parseInt(args[5]);
String type = args[6];
if (!MultiFlowTypes.simulations.containsKey(type) && !type.equals("all")){
System.out.println("invalid test case.");
System.out.println(MultiFlowTypes.getValues());
System.exit(0);
}
if (!type.equals("all")){
performTest(numThreads, numberOfFlows, verbose, interval,
storedStatistics, start_id, type);
}
else{
for (String t : MultiFlowTypes.simulations.keySet()){
performTest(numThreads, numberOfFlows, verbose, interval,
storedStatistics, start_id, t);
}
}
System.exit(0);
}
/**
* @param numThreads
* @param numberOfFlows
* @param verbose
* @param interval
* @param storedStatistics
* @param start_id
* @param type
*/
private static void performTest(int numThreads, int numberOfFlows,
boolean verbose, long interval, boolean storedStatistics,
int start_id, String type) {
DescriptiveStatistics[] stats = new DescriptiveStatistics[numThreads];
for(int i=0; i<numThreads; i++) {
stats[i] = new DescriptiveStatistics();
}
boolean end = createAndWaitForThreads(numThreads, numberOfFlows, verbose, interval,
storedStatistics, start_id, type, stats);
if (!end) System.exit(-1);
Long random = sendFinalSignToServer(type,numThreads, start_id);
printResultsAndFinish(numThreads, stats,type, random, numberOfFlows);
System.exit(0);
}
private static Long sendFinalSignToServer(String name, int threads, int start_id){
ServiceProxy proxy = new ServiceProxy(start_id);
TestInformation t = new TestInformation(name,threads);
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(out);
try {
dos.writeInt(-3);
byte[] s =serialize(t);
dos.writeInt(s.length);
dos.write(s);
dos.flush(); dos.close();
proxy.invokeOrdered(out.toByteArray());
proxy.close();
} catch (IOException e) {
return null;
}
return t.random;
}
/**
* @param numThreads
* @param stats
* @param signaled
*/
private static void printResultsAndFinish(int numThreads,
DescriptiveStatistics[] stats,String type, Long random, int ops) {
SummaryStatistics statsEnd = new SummaryStatistics();
for (int i = 0 ; i < numThreads ; i++){
double[] vals = stats[i].getSortedValues();
int len = (int) (vals.length *( 0.95));
for (int j = 0 ; j < len ; j++ ){
statsEnd.addValue(vals[j]);
}
}
try{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("./latency", true)));
out.print( type +":" + numThreads + ":"+ statsEnd.getN() + ":" + statsEnd.getMean() + ":" +statsEnd.getStandardDeviation() + ":" + statsEnd.getMin() + ":" + statsEnd.getMax() + ":" + random
+ ":" + ops);
//Print Test information.
out.print(":(");
WorkloadPerFlow f = MultiFlowTypes.simulations.get(type);
out.print(f.workloadDescription +";");
int[][] requests = f.requests;
for (int i = 0 ; i < requests.length ; i++){
out.print(requests[i][0] == FlowSimulation.WRITE_OP ? "W" : "R");
out.print(",");
out.print(requests[i][1] + "," +requests[i][2]);
if ((i + 1) < requests.length){
out.print(";");
}
}
out.print(")");
//Test duration
out.print(":" + ((System.currentTimeMillis() - test_start_time) / (1000 *60) ));
out.println("");
out.close();
System.out.println("Printed results");
}catch(Exception e ){
System.out.println("failed to write");
}
}
/**
* @param numThreads
* @param numberOfFlows
* @param verbose
* @param interval
* @param storedStatistics
* @param start_id
* @param type
* @param stats
*/
private static boolean createAndWaitForThreads(int numThreads,
int numberOfFlows, boolean verbose, long interval,
boolean storedStatistics, int start_id, String type,
DescriptiveStatistics[] stats) {
Thread[] c = new Thread[numThreads];
Boolean[] end_condition = new Boolean[numThreads];
if (verbose){
System.out.println("Creating threads");
}
for(int i=0; i<numThreads; i++) {
c[i] = new Thread(new MultiFlowTypes(i, numberOfFlows, verbose, interval, storedStatistics, start_id,type, stats[i], end_condition));
}
for(int i=0; i<numThreads; i++) {
c[i].start();
}
if (verbose){
System.out.println("Threads created... ");
}
for(int i=0; i<numThreads; i++) {
try {
c[i].join();
} catch (InterruptedException ex) {
ex.printStackTrace(System.err);
}
}
int sum=0;
try{
for (Boolean o : end_condition){
if (o) sum++;
}
}catch(NullPointerException e){
;
}
if (sum > ((2.0/3.0 ) * numThreads)){
return true;
}
else return false;
}
protected final ServiceProxy proxy ;
protected final int id;
protected final DescriptiveStatistics latency;
protected final int numFlows;
protected final boolean verbose;
protected final long interval;
protected final int start_id;
private Boolean[] end_condition;
//protected SummaryStatistics latency2 = new SummaryStatistics();
public BenchClient(int id, int numFlows, boolean verbose, long interval, boolean storedStatistics, int start_id, String type, DescriptiveStatistics stats, Boolean[] end_condition){
this.id = id;
proxy = new ServiceProxy(start_id + id);
this.numFlows = numFlows;
this.verbose = verbose;
this.interval = interval;
this.end_condition = end_condition;
this.start_id = start_id;
this.latency = stats;
if (verbose)
System.out.println("Starting thread :" + id);
}
@Override
public void run(){
byte[] start= null;
byte[] end = null;
try{
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.writeInt(-1);
dos.flush(); dos.close();
start = out.toByteArray();
out = new ByteArrayOutputStream();
dos = new DataOutputStream(out);
dos.writeInt(-2);
dos.flush(); dos.close();
end = out.toByteArray();
}catch(Exception e){
e.printStackTrace();
}
if (verbose){
System.out.println("Starting thread " + this.id);
}
boolean cond = bombit(end);
this.end_condition[this.id] = cond;
proxy.close();
// System.out.println("Stats: " + latency.toString());
}
/**
* @param end
*/
long success;
final private boolean bombit(final byte[] end) {
for (long i = 0; i < numFlows + 1000 ; i++){
if (verbose && (i % interval) == 0 ){
System.out.println("Thread " + id + " on request: " + i);
}
long tflow_started = System.currentTimeMillis();
try{
flow.run(proxy);
}catch(TimeoutException e ){
return false;
}
final long total = System.currentTimeMillis() - tflow_started;
try{
proxy.invokeUnordered(end);
}catch(Exception e){
System.out.println( id + "failed request");
continue;
}
end(total, i);
}
//System.out.println(latency.getN()/(numFlows*1.0) + "Successfull");
return true;
}
//TODO extract these methods to a standalone package.
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(obj);
o.flush();
o.close();
return b.toByteArray();
}
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return o.readObject();
}
WorkloadPerFlow flow;
//protected abstract FlowSimulation chooseNextFlow();
protected abstract void end(long t, long i);
}