From: Sasha Sherstnev Date: Thu, 8 Aug 2013 13:23:35 +0000 (+0100) Subject: Add a file with the runnig command and environment in each wrok dir X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=8fd86d4a7a3f975e4571d9cf50732962847f86e8;p=jabaws.git Add a file with the runnig command and environment in each wrok dir --- diff --git a/engine/compbio/engine/local/ExecutableWrapper.java b/engine/compbio/engine/local/ExecutableWrapper.java index 9e652f9..5809be4 100644 --- a/engine/compbio/engine/local/ExecutableWrapper.java +++ b/engine/compbio/engine/local/ExecutableWrapper.java @@ -1,6 +1,8 @@ /* Copyright (c) 2009 Peter Troshin - * - * JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0 + * Copyright (c) 2013 Alexander Sherstnev + * + * Java Bioinformatics Analysis Web Services (JABAWS) + * @version: 2.5 * * This library is free software; you can redistribute it and/or modify it under the terms of the * Apache License version 2 as published by the Apache Software Foundation @@ -22,6 +24,8 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -48,62 +52,58 @@ import compbio.util.annotation.Immutable; public final class ExecutableWrapper implements Callable> { + public static final String PROC_IN_FILE = "procInput.txt"; public static final String PROC_OUT_FILE = "procOutput.txt"; public static final String PROC_ERR_FILE = "procError.txt"; private static ExecutorService es; - - private static final Logger log = Logger.getLogger(ExecutableWrapper.class); - private final ConfiguredExecutable confExec; - private final ProcessBuilder pbuilder; - public ExecutableWrapper(ConfiguredExecutable executable, - String workDirectory) throws JobSubmissionException { - this.confExec = executable; - String cmd = null; - try { - cmd = executable.getCommand(ExecProvider.Local); - PathValidator.validateExecutable(cmd); - } catch (IllegalArgumentException e) { - log.error(e.getMessage(), e.getCause()); - throw new JobSubmissionException(e); - } - List params = executable.getParameters().getCommands(); - params.add(0, cmd); - - pbuilder = new ProcessBuilder(params); - if (executable.getEnvironment() != null) { - log.debug("Setting command environment variables: " + pbuilder.environment()); - Util.mergeEnvVariables(pbuilder.environment(), executable.getEnvironment()); - log.debug("Process environment:" + pbuilder.environment()); - } - log.debug("Setting command: " + pbuilder.command()); - PathValidator.validateDirectory(workDirectory); - pbuilder.directory(new File(workDirectory)); - log.debug("Current working directory is " + SysPrefs.getCurrentDirectory()); - log.debug("Setting working directory: " + workDirectory); - // Initialize private executor to dump processes output if any to the - // file system - synchronized (log) { - if (es == null) { - // Two threads are necessary for the process to write in two - // streams error and output - // simultaneously and hold the stream until exit. If only one - // thread is used, the second stream may never - // get access to the thread efficiently deadlocking the - // proccess! - this.es = Executors.newCachedThreadPool(); - log.debug("Initializing executor for local processes output dump"); - // Make sure that the executors are going to be properly closed - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - shutdownService(); - } - }); - } + private static final Logger log = Logger.getLogger(ExecutableWrapper.class); + + public ExecutableWrapper(ConfiguredExecutable executable, String workDirectory) throws JobSubmissionException { + this.confExec = executable; + String cmd = null; + try { + cmd = executable.getCommand(ExecProvider.Local); + PathValidator.validateExecutable(cmd); + } catch (IllegalArgumentException e) { + log.error(e.getMessage(), e.getCause()); + throw new JobSubmissionException(e); + } + List params = executable.getParameters().getCommands(); + params.add(0, cmd); + + pbuilder = new ProcessBuilder(params); + if (executable.getEnvironment() != null) { + log.debug("Setting command environment variables: " + pbuilder.environment()); + Util.mergeEnvVariables(pbuilder.environment(), executable.getEnvironment()); + log.debug("Process environment:" + pbuilder.environment()); + } + log.debug("Setting command: " + pbuilder.command()); + PathValidator.validateDirectory(workDirectory); + pbuilder.directory(new File(workDirectory)); + log.debug("Current working directory is " + SysPrefs.getCurrentDirectory()); + log.debug("Setting working directory: " + workDirectory); + // Initialize private executor to dump processes output if any to the file system + synchronized (log) { + if (es == null) { + /* + * Two threads are necessary for the process to write in two streams error and output + * simultaneously and hold the stream until exit. If only one thread is used, the + * second stream may never get access to the thread efficiently deadlocking the proccess! + */ + this.es = Executors.newCachedThreadPool(); + log.debug("Initializing executor for local processes output dump"); + // Make sure that the executors are going to be properly closed + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + shutdownService(); + } + }); + } } } @@ -114,8 +114,8 @@ public final class ExecutableWrapper implements * otherwise as the executor service is taken care of internally. */ public static final void shutdownService() { - if (es != null) { - es.shutdownNow(); + if (es != null) { + es.shutdownNow(); } } @@ -126,6 +126,7 @@ public final class ExecutableWrapper implements * capture immediately this could lead to the call method to stale, as * execution could not proceed without output being captured. Every call to * call() method will use 2 threads + * @throws JobSubmissionException */ @Override public ConfiguredExecutable call() throws IOException { @@ -134,91 +135,90 @@ public final class ExecutableWrapper implements Future outputf = null; PrintStream errorStream = null; PrintStream outStream = null; - try { - log.info("Calculation started at " + System.nanoTime()); - Util.writeStatFile(confExec.getWorkDirectory(), JobStatus.STARTED - .toString()); - // pb.redirectErrorStream(false); - proc = pbuilder.start(); - - /* - * any error message? - */ - errorStream = new PrintStream(new File(pbuilder.directory() - + File.separator + getError())); - StreamGobbler errorGobbler = new StreamGobbler(proc - .getErrorStream(), errorStream, OutputType.ERROR); - - // any output? - outStream = new PrintStream(new File(pbuilder.directory() - + File.separator + getOutput())); - StreamGobbler outputGobbler = new StreamGobbler(proc - .getInputStream(), outStream, OutputType.OUTPUT); - - // kick them off - errorf = es.submit(errorGobbler); - outputf = es.submit(outputGobbler); - - // any error??? - int exitVal = proc.waitFor(); - log.info("Calculation completed at " + System.nanoTime()); - Util.writeStatFile(confExec.getWorkDirectory(), JobStatus.FINISHED - .toString()); - // Let streams to write for a little more - errorf.get(2, TimeUnit.SECONDS); - outputf.get(2, TimeUnit.SECONDS); - // Close streams - errorStream.close(); - outStream.close(); - log.debug("Local process exit value: " + exitVal); + PrintStream comStream = null; + + try { + log.info("Calculation started at " + System.nanoTime()); + Util.writeStatFile(confExec.getWorkDirectory(), JobStatus.STARTED.toString()); + proc = pbuilder.start(); + + // store input command and program environment + comStream = new PrintStream(new File(pbuilder.directory() + File.separator + PROC_IN_FILE)); + comStream.append("# program command\n"); + for (String par : pbuilder.command()) { + comStream.append(par + " "); + } + comStream.append("\n\n# program environment\n"); + for (Entry var : pbuilder.environment().entrySet()) { + comStream.append(var.getKey() + " =\t" + var.getValue() + "\n"); + } + comStream.close(); + + // any error message? + errorStream = new PrintStream(new File(pbuilder.directory() + File.separator + getError())); + StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), errorStream, OutputType.ERROR); + + // any output? + outStream = new PrintStream(new File(pbuilder.directory() + File.separator + getOutput())); + StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), outStream, OutputType.OUTPUT); + + // kick it off + errorf = es.submit(errorGobbler); + outputf = es.submit(outputGobbler); + + // any error??? + int exitVal = proc.waitFor(); + log.info("Calculation completed at " + System.nanoTime()); + Util.writeStatFile(confExec.getWorkDirectory(), JobStatus.FINISHED.toString()); + // Let streams to write for a little more + errorf.get(2, TimeUnit.SECONDS); + outputf.get(2, TimeUnit.SECONDS); + + // Close streams + errorStream.close(); + outStream.close(); + log.debug("Local process exit value: " + exitVal); } catch (ExecutionException e) { - // Log and ignore this is not important - log.trace("Native Process output threw exception: " - + e.getMessage()); + // Log and ignore this is not important + log.trace("Native Process output threw exception: " + e.getMessage()); } catch (TimeoutException e) { - // Log and ignore this is not important - log - .trace("Native Process output took longer then 2s to write, aborting: " - + e.getMessage()); + // Log and ignore this is not important + log.trace("Native Process output took longer then 2s to write, aborting: " + e.getMessage()); } catch (InterruptedException e) { - log.error("Native Process was interrupted aborting: " - + e.getMessage()); - proc.destroy(); - errorf.cancel(true); - outputf.cancel(true); - // restore interruption status - Thread.currentThread().interrupt(); - } finally { - if (proc != null) { - // just to make sure that we do not left anything running + log.error("Native Process was interrupted aborting: " + e.getMessage()); proc.destroy(); - } - if (errorf != null) { errorf.cancel(true); - } - if (outputf != null) { outputf.cancel(true); - } - FileUtil.closeSilently(log, errorStream); - FileUtil.closeSilently(log, outStream); + // restore interruption status + Thread.currentThread().interrupt(); + } finally { + // just to make sure that we do not left anything running + if (proc != null) { + proc.destroy(); + } + if (errorf != null) { + errorf.cancel(true); + } + if (outputf != null) { + outputf.cancel(true); + } + FileUtil.closeSilently(log, errorStream); + FileUtil.closeSilently(log, outStream); } return confExec; } private String getOutput() { - if (confExec.getOutput() != null - && confExec.getExecutable() instanceof PipedExecutable) { - return confExec.getOutput(); + if (confExec.getOutput() != null && confExec.getExecutable() instanceof PipedExecutable) { + return confExec.getOutput(); } return PROC_OUT_FILE; } private String getError() { - if (confExec.getError() != null - && confExec.getExecutable() instanceof PipedExecutable) { - return confExec.getError(); + if (confExec.getError() != null && confExec.getExecutable() instanceof PipedExecutable) { + return confExec.getError(); } return PROC_ERR_FILE; } - }