package test; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.text.DecimalFormat; import java.util.Properties; import java.util.Vector; import at.ac.tuwien.dsg.sybl.model.annotations.SYBL_CodeRegionDirective; import at.ac.tuwien.dsg.sybl.model.annotations.SYBL_CodeRegionDirective.AnnotType; import com.yahoo.ycsb.Client; import com.yahoo.ycsb.DB; import com.yahoo.ycsb.DBException; import com.yahoo.ycsb.DBFactory; import com.yahoo.ycsb.UnknownDBException; import com.yahoo.ycsb.Utils; import com.yahoo.ycsb.Workload; import com.yahoo.ycsb.WorkloadException; import com.yahoo.ycsb.measurements.Measurements; import com.yahoo.ycsb.measurements.exporter.MeasurementsExporter; import com.yahoo.ycsb.measurements.exporter.TextMeasurementsExporter; public class WorkloadStarter { public WorkloadStarter() { } public void runWorkloadFromFile(String workloadFile){ String [] st = new String[5]; st[0]= "-P"; st[1]=workloadFile; st[2]="-P"; st[3]="config.dat"; st[4]="-s"; Client.main(st); } public void runYCSBWorkload(){ runWorkloadFromFile("workloads/workloada"); } @SYBL_CodeRegionDirective(annotatedEntityID="methodrunWorkload",type=AnnotType.DURING, constraints="Co1:CONSTRAINT cpuUsageData < 65;" + "Co2:CONSTRAINT cpuUsageData > 30; " + "Co3:CONSTRAINT cpuUsageData < 85 WHEN cost > 70", monitoring ="Mo1:MONITORING cost = cost.instant;" + "Mo2: MONITORING dataThroughput = throughput.datasource;" + "Mo3: MONITORING cpuAllocatedData = cpu.size.datasource;" + "Mo4: MONITORING cpuUsage = cpu.usage;" + "Mo5: MONITORING cpuUsageData = cpu.usage.datasource", strategies="St1:STRATEGY CASE Violated(Co2): scaleInDataSource; " + "St2:STRATEGY CASE Enabled(Co1) AND Violated(Co1): scaleOutDataSource;" + "St3:STRATEGY CASE Enabled(Co3) AND Violated(Co3): scaleOutDataSource;", priorities="Priority(Co3) > Priority(Co1)") public void runWorkload(){ Properties props=new Properties(); props.setProperty("readallfields", "true"); props.setProperty("readproportion", "0.5"); props.setProperty("updateproportion", "0.1"); props.setProperty("scanproportion", "0.1"); props.setProperty("insertproportion", "0.3"); props.setProperty("requestdistribution", "zipfian"); props.setProperty("db", "com.yahoo.ycsb.db.CassandraClient10"); props.setProperty("hosts","128.130.172.213"); props.setProperty("workload", "com.yahoo.ycsb.workloads.CoreWorkload"); props.setProperty("exportFile","resultsIntensiveWorkload.csv"); String dbname="cassandra-10"; props.setProperty("threadcount","100"); props.setProperty("operationcount","100000"); props.setProperty("recordcount","100000"); String label=""; Workload workload = null; boolean dotransactions=true; int threadcount=1; int target=0; boolean status=true; if (!checkRequiredProperties(props)) { System.exit(0); } //set up measurements Measurements.setProperties(props); ClassLoader classLoader = Client.class.getClassLoader(); Class workloadclass = null; try { workloadclass = classLoader.loadClass(props.getProperty("workload")); } catch (ClassNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } //get number of threads, target and db threadcount=Integer.parseInt(props.getProperty("threadcount","1")); dbname=props.getProperty("db","com.yahoo.ycsb.BasicDB"); target=Integer.parseInt(props.getProperty("target","0")); try { workload=(Workload)workloadclass.newInstance(); } catch (InstantiationException | IllegalAccessException e1) { e1.printStackTrace(); } try { workload.init(props); } catch (WorkloadException e) { e.printStackTrace(); e.printStackTrace(System.out); System.exit(0); } //warningthread.interrupt(); Vector<Thread> threads=new Vector<Thread>(); for (int threadid=0; threadid<threadcount; threadid++) { DB db=null; try { db=DBFactory.newDB(dbname,props); } catch (UnknownDBException e) { System.out.println("Unknown DB "+dbname); System.exit(0); } int opcount=Integer.parseInt(props.getProperty("operationcount","0")); double targetperthreadperms=-1; if (target>0) { double targetperthread=((double)target)/((double)threadcount); targetperthreadperms=targetperthread/1000.0; } Thread t=new ClientThread(db,dotransactions,workload,threadid,threadcount,props,opcount/threadcount,targetperthreadperms); threads.add(t); //t.start(); } StatusThread statusthread=null; if (status) { boolean standardstatus=false; if (props.getProperty("measurementtype","").compareTo("timeseries")==0) { standardstatus=true; } statusthread=new StatusThread(threads,label,standardstatus); statusthread.start(); } long st=System.currentTimeMillis(); for (Thread t : threads) { t.start(); } Thread terminator = null; int opsDone = 0; for (Thread t : threads) { try { t.join(); opsDone += ((ClientThread)t).getOpsDone(); } catch (InterruptedException e) { } } long en=System.currentTimeMillis(); if (terminator != null && !terminator.isInterrupted()) { terminator.interrupt(); } if (status) { statusthread.interrupt(); } try { workload.cleanup(); } catch (WorkloadException e) { e.printStackTrace(); e.printStackTrace(System.out); System.exit(0); } try { exportMeasurements(props, opsDone, en - st); } catch (IOException e) { System.err.println("Could not export measurements, error: " + e.getMessage()); e.printStackTrace(); System.exit(-1); } try { System.err.println("Now sleeping ..."); Thread.sleep(270000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static boolean checkRequiredProperties(Properties props) { if (props.getProperty("workload")==null) { System.out.println("Missing property: "+"workload"); return false; } return true; } /** * Exports the measurements to either sysout or a file using the exporter * loaded from conf. * @throws IOException Either failed to write to output stream or failed to close it. */ private static void exportMeasurements(Properties props, int opcount, long runtime) throws IOException { MeasurementsExporter exporter = null; try { // if no destination file is provided the results will be written to stdout OutputStream out; String exportFile = props.getProperty("exportfile"); if (exportFile == null) { out = System.out; } else { out = new FileOutputStream(exportFile); } // if no exporter is provided the default text one will be used String exporterStr = props.getProperty("exporter", "com.yahoo.ycsb.measurements.exporter.TextMeasurementsExporter"); try { exporter = (MeasurementsExporter) Class.forName(exporterStr).getConstructor(OutputStream.class).newInstance(out); } catch (Exception e) { System.err.println("Could not find exporter " + exporterStr + ", will use default text reporter."); e.printStackTrace(); exporter = new TextMeasurementsExporter(out); } exporter.write("OVERALL", "RunTime(ms)", runtime); double throughput = 1000.0 * ((double) opcount) / ((double) runtime); exporter.write("OVERALL", "Throughput(ops/sec)", throughput); Measurements.getMeasurements().exportMeasurements(exporter); } finally { if (exporter != null) { exporter.close(); } } } } class StatusThread extends Thread { Vector<Thread> _threads; String _label; boolean _standardstatus; /** * The interval for reporting status. */ public static final long sleeptime=10000; public StatusThread(Vector<Thread> threads, String label, boolean standardstatus) { _threads=threads; _label=label; _standardstatus=standardstatus; } /** * Run and periodically report status. */ public void run() { long st=System.currentTimeMillis(); long lasten=st; long lasttotalops=0; boolean alldone; do { alldone=true; int totalops=0; //terminate this thread when all the worker threads are done for (Thread t : _threads) { if (t.getState()!=Thread.State.TERMINATED) { alldone=false; } ClientThread ct=(ClientThread)t; totalops+=ct.getOpsDone(); } long en=System.currentTimeMillis(); long interval=en-st; //double throughput=1000.0*((double)totalops)/((double)interval); double curthroughput=1000.0*(((double)(totalops-lasttotalops))/((double)(en-lasten))); lasttotalops=totalops; lasten=en; DecimalFormat d = new DecimalFormat("#.##"); if (totalops==0) { System.err.println(_label+" "+(interval/1000)+" sec: "+totalops+" operations; "+Measurements.getMeasurements().getSummary()); } else { System.err.println(_label+" "+(interval/1000)+" sec: "+totalops+" operations; "+d.format(curthroughput)+" current ops/sec; "+Measurements.getMeasurements().getSummary()); } if (_standardstatus) { if (totalops==0) { System.out.println(_label+" "+(interval/1000)+" sec: "+totalops+" operations; "+Measurements.getMeasurements().getSummary()); } else { System.out.println(_label+" "+(interval/1000)+" sec: "+totalops+" operations; "+d.format(curthroughput)+" current ops/sec; "+Measurements.getMeasurements().getSummary()); } } try { sleep(sleeptime); } catch (InterruptedException e) { //do nothing } } while (!alldone); } } /** * A thread for executing transactions or data inserts to the database. * * @author cooperb * */ class ClientThread extends Thread { DB _db; boolean _dotransactions; Workload _workload; int _opcount; double _target; int _opsdone; int _threadid; int _threadcount; Object _workloadstate; Properties _props; /** * Constructor. * * @param db the DB implementation to use * @param dotransactions true to do transactions, false to insert data * @param workload the workload to use * @param threadid the id of this thread * @param threadcount the total number of threads * @param props the properties defining the experiment * @param opcount the number of operations (transactions or inserts) to do * @param targetperthreadperms target number of operations per thread per ms */ public ClientThread(DB db, boolean dotransactions, Workload workload, int threadid, int threadcount, Properties props, int opcount, double targetperthreadperms) { //TODO: consider removing threadcount and threadid _db=db; _dotransactions=dotransactions; _workload=workload; _opcount=opcount; _opsdone=0; _target=targetperthreadperms; _threadid=threadid; _threadcount=threadcount; _props=props; //System.out.println("Interval = "+interval); } public int getOpsDone() { return _opsdone; } public void run() { try { _db.init(); } catch (DBException e) { e.printStackTrace(); e.printStackTrace(System.out); return; } try { _workloadstate=_workload.initThread(_props,_threadid,_threadcount); } catch (WorkloadException e) { e.printStackTrace(); e.printStackTrace(System.out); return; } //spread the thread operations out so they don't all hit the DB at the same time try { //GH issue 4 - throws exception if _target>1 because random.nextInt argument must be >0 //and the sleep() doesn't make sense for granularities < 1 ms anyway if ( (_target>0) && (_target<=1.0) ) { sleep(Utils.random().nextInt((int)(1.0/_target))); } } catch (InterruptedException e) { // do nothing. } try { if (_dotransactions) { long st=System.currentTimeMillis(); while (((_opcount == 0) || (_opsdone < _opcount)) && !_workload.isStopRequested()) { if (!_workload.doTransaction(_db,_workloadstate)) { break; } _opsdone++; //throttle the operations if (_target>0) { //this is more accurate than other throttling approaches we have tried, //like sleeping for (1/target throughput)-operation latency, //because it smooths timing inaccuracies (from sleep() taking an int, //current time in millis) over many operations while (System.currentTimeMillis()-st<((double)_opsdone)/_target) { try { sleep(1); } catch (InterruptedException e) { // do nothing. } } } } } else { long st=System.currentTimeMillis(); while (((_opcount == 0) || (_opsdone < _opcount)) && !_workload.isStopRequested()) { if (!_workload.doInsert(_db,_workloadstate)) { break; } _opsdone++; //throttle the operations if (_target>0) { //this is more accurate than other throttling approaches we have tried, //like sleeping for (1/target throughput)-operation latency, //because it smooths timing inaccuracies (from sleep() taking an int, //current time in millis) over many operations while (System.currentTimeMillis()-st<((double)_opsdone)/_target) { try { sleep(1); } catch (InterruptedException e) { // do nothing. } } } } } } catch (Exception e) { e.printStackTrace(); e.printStackTrace(System.out); System.exit(0); } try { _db.cleanup(); } catch (DBException e) { e.printStackTrace(); e.printStackTrace(System.out); return; } } }