package org.activiti.test.async.executor.hazelcast;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
/**
* @author Joram Barrez
*/
public class Main {
private static ProcessEngine processEngine;
public static void main(String[] args) throws Exception {
if (args.length == 0) {
System.err.println("Arguments needed");
System.err.println("First argument: { job-creator | job-executor | mixed}, to determine what this Main program will be doing: creating jobs, executing them or both");
System.err.println("Arguments in case of job-creator: { nrOfJobs nrOfJobCreationThreads}");
System.err.println("Arguments in case of job-executor: { nrOfJobs }");
System.err.println("In case of mixed: { nrOfJobs nrOfJobCreationThreads } ");
System.err.println();
System.err.println("Example usage : java -XX:MaxPermSize=512m -Xmx2G -Xms512m -jar theJar.jar job-creator 1000 4");
System.err.println("Example usage : java -XX:MaxPermSize=512m -Xmx2G -Xms512m -jar theJar.jar job-executor 1000");
System.err.println("Example usage : java -XX:MaxPermSize=512m -Xmx2G -Xms512m -jar theJar.jar mixed 1000 4");
System.err.println();
System.err.println("The last argument can always be 'keepDb'. In that case, no drop of the database schema will be done, which is the default for job creation or mixed.");
System.exit(-1);
}
int nrOfJobs = Integer.valueOf(args[1]);
int nrOfThreads = args[2] != null ? Integer.valueOf(args[2]) : -1;
boolean keepDb = "keepDb".equals(args[args.length - 1]);
boolean dropDb = !keepDb;
if ("job-creator".equals(args[0])) {
startCreateJobs(nrOfJobs, nrOfThreads, dropDb);
} else if ("job-executor".equals(args[0])) {
startExecuteJobs(nrOfJobs, dropDb);
} else if ("mixed".equals(args[0])) {
startMixed(nrOfJobs, nrOfThreads, dropDb);
} else {
System.err.println("Unknown argument '" + args[0] + "'");
System.exit(-1);
}
}
private static void startCreateJobs(int nrOfJobs, int nrOfThreads, boolean dropDb) throws Exception {
System.out.println(new Date() + " [Job Creator] Starting. Need to create " + nrOfJobs + " job with " + nrOfThreads + " threads");
// Job creator needs to be started first, as it will clean the database!
createJobCreatorProcessEngine(false, dropDb);
processEngine.getRepositoryService().createDeployment().name("job")
.addClasspathResource("job.bpmn20.xml").deploy();
ExecutorService executor = Executors.newFixedThreadPool(nrOfThreads);
for (int i = 0; i < nrOfJobs; i++) {
Runnable worker = new StartTestProcessInstanceThread();
executor.execute(worker);
}
executor.shutdown();
System.out.println(new Date() + " [Job Creator] All StartProcessInstanceThreads handed off to executor service");
boolean finishedAllInstances = false;
long unfinishedCount = 0;
long finishedCount = 0;
while (finishedAllInstances == false) {
unfinishedCount = processEngine.getHistoryService()
.createHistoricProcessInstanceQuery().unfinished().count();
finishedCount = processEngine.getHistoryService()
.createHistoricProcessInstanceQuery().finished().count();
finishedAllInstances = finishedCount >= nrOfJobs;
if (!finishedAllInstances) {
System.out.println(new Date() + " [Job Creator] " + finishedCount + " finished process instances in db, " + unfinishedCount + " unfinished process instances in db.");
Thread.sleep(10000L);
}
}
}
private static void startExecuteJobs(int nrOfJobs, boolean dropDb) throws Exception {
System.out.println(new Date() + " [Job Executor] Starting. Need to execute " + nrOfJobs + " jobs in total.");
createJobExecutorProcessEngine(false, dropDb);
boolean finishedAllInstances = false;
long lastPrintTime = 0;
long finishedCount = 0;
long start = System.currentTimeMillis();
while (finishedAllInstances == false) {
finishedCount = processEngine.getHistoryService()
.createHistoricProcessInstanceQuery().finished().count();
if (finishedCount >= nrOfJobs) {
finishedAllInstances = true;
} else {
if (System.currentTimeMillis() - lastPrintTime > 5000L) {
lastPrintTime = System.currentTimeMillis();
int percentage = (int) (((double) finishedCount / (double) nrOfJobs) * 100.0);
System.out.println(new Date() + " [Job Executor] Executed " + finishedCount + "/" + nrOfJobs + " jobs (" + percentage + "%)");
}
Thread.sleep(1000L);
}
}
long end = System.currentTimeMillis();
System.out.println();
System.out.println();
System.out.println("Jobs executed by this node: " + SleepDelegate.nrOfExecutions.get());
long time = end - start;
System.out.println("Took " + time + " ms");
double perSecond = ((double) SleepDelegate.nrOfExecutions.get() / (double) time) * 1000;
System.out.println("Which is " + perSecond + " jobs/second");
System.out.println();
System.out.println();
}
private static void startMixed(final int nrOfJobs, final int nrOfThreads, boolean dropDb) throws Exception {
createJobExecutorProcessEngine(true, dropDb);
// Create Jobs
Thread createJobsThread = new Thread(new Runnable() {
public void run() {
try {
startCreateJobs(nrOfJobs, nrOfThreads, false);
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
});
createJobsThread.start();
// Execute jobs
Thread executeJobsThread = new Thread(new Runnable() {
public void run() {
try {
startExecuteJobs(nrOfJobs, false);
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
});
executeJobsThread.start();
createJobsThread.join();
executeJobsThread.join();
processEngine.close();
System.out.println("Done.");
System.exit(0);
}
private static void createJobCreatorProcessEngine(boolean replaceExisting, boolean isDropDatabaseSchema) {
if (processEngine == null || replaceExisting) {
System.out.println("Creating process engine with config activiti_job_creator.cfg.xml. Dropping db first = " + isDropDatabaseSchema);
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti_job_creator.cfg.xml");
if (isDropDatabaseSchema) {
processEngineConfiguration.setDatabaseSchemaUpdate("drop-create");
}
processEngine = processEngineConfiguration.buildProcessEngine();
}
}
private static void createJobExecutorProcessEngine(boolean replaceExisting, boolean isDropDatabaseSchema) {
if (processEngine == null || replaceExisting) {
System.out.println("Creating process engine with config activiti_with_jobexecutor.cfg.xml. Dropping db first = " + isDropDatabaseSchema);
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("activiti_with_jobexecutor.cfg.xml");
if (isDropDatabaseSchema) {
processEngineConfiguration.setDatabaseSchemaUpdate("drop-create");
}
processEngine = processEngineConfiguration.buildProcessEngine();
}
}
public static class StartTestProcessInstanceThread implements Runnable {
public void run() {
processEngine.getRuntimeService().startProcessInstanceByKey("job");
}
}
}