package process_handlers; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import benchmark.ProcessListener; import benchmark.TestLoader; import commands.Command; import commands.ReplicaCommand; import commands.ReplicaCommand.CommandType; public class ReplicaProcessController implements ReplicaHandler { final public String launchCommand; final public int numberOfReplica; private ReplicaCommand lastCommand; private ProcessListener listener; private OutputStream os; private OutputStream file_bos; private Process process; private boolean stopping; public String toString() { return String.valueOf(numberOfReplica); } private class InputStreamReader implements Runnable { private final InputStream source; private final OutputStream sink; public InputStreamReader(InputStream is, OutputStream os) { this.source = is; this.sink = os; } @Override public void run() { byte[] b = new byte[1024 * 8]; try { int count = source.read(b); while (count != -1) { sink.write(b, 0, count); // sink.flush(); count = source.read(b); // System.out.println(Thread.currentThread().getName() + ":Read: " + count); } } catch (IOException e) { if (!stopping) throw new RuntimeException("Process could not log output", e); } } } public ReplicaProcessController(final int target, int vnrunhost, ReplicaCommand lastCommand, ProcessListener _listener) { numberOfReplica = target; this.lastCommand = lastCommand; listener = _listener; String cmd = TestLoader.getReplicaCmd(); int replicaNo = vnrunhost - 1; cmd = cmd.replaceAll("MODEL", TestLoader.getModelnetFile()); cmd = cmd.replaceAll("NUM", String.valueOf(target - 1)); cmd = cmd.replaceAll("VNODE", String.valueOf(replicaNo)); launchCommand = cmd; try { process = Runtime.getRuntime().exec(launchCommand); } catch (IOException e) { e.printStackTrace(); System.exit(1); } final ReplicaProcessController me = this; os = process.getOutputStream(); listener.processCreated(me); try { file_bos = //new BufferedOutputStream( new FileOutputStream("replica__" + target + ".log", true); //1024*16); } catch (FileNotFoundException e1) { e1.printStackTrace(); System.exit(1); } // Separate threads to read the stdout and stderr new Thread(new InputStreamReader(process.getInputStream(), file_bos), "Replica-" + replicaNo + "-stdout").start(); new Thread(new InputStreamReader(process.getErrorStream(), file_bos), "Replica-" + replicaNo + "-stderr").start(); // Waits until the process exits. new Thread("Replica-" + replicaNo) { public void run() { try { process.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } if (listener != null) { if (process.exitValue() == 0) listener.processFinished(me); else if ((me.lastCommand).getType() == CommandType.Stop) { listener.processFinished(me); } else { listener.errorCaught(me); } } } }.start(); } private void flushFileOut() { try { file_bos.flush(); } catch (IOException e1) { } } @Override public void addProcessListener(ProcessListener procesListener) { if (listener != null) throw new RuntimeException(); listener = procesListener; } @Override public void kill() { stopping = true; process.destroy(); flushFileOut(); } @Override public void stop() { stopping = true; try { // A newline is interpreted by the replica client as a sign to stop. os.write('\n'); os.flush(); } catch (IOException e) { process.destroy(); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); flushFileOut(); System.exit(1); } try { process.exitValue(); } catch (IllegalThreadStateException e) { process.destroy(); } flushFileOut(); } public Command getLastCommand() { return lastCommand; } public void setLastCommand(Command c) { if (c instanceof ReplicaCommand) lastCommand = (ReplicaCommand) c; } }