Runs Gnuplot in a subprocess to generate the graph. This function will block while Gnuplot is running. @param query The query being handled (for logging purposes). @param basepath The base path used for the Gnuplot files. @param plot The plot object to generate Gnuplot's input files
(final HttpQuery query,
final String basepath,
final Plot plot)
| 860 | * @throws GnuplotException if Gnuplot returns non-zero. |
| 861 | */ |
| 862 | static int runGnuplot(final HttpQuery query, |
| 863 | final String basepath, |
| 864 | final Plot plot) throws IOException { |
| 865 | final int nplotted = plot.dumpToFiles(basepath); |
| 866 | final long start_time = System.nanoTime(); |
| 867 | final Process gnuplot = new ProcessBuilder(GNUPLOT, |
| 868 | basepath + ".out", basepath + ".err", basepath + ".gnuplot").start(); |
| 869 | final int rv; |
| 870 | try { |
| 871 | rv = gnuplot.waitFor(); // Couldn't find how to do this asynchronously. |
| 872 | } catch (InterruptedException e) { |
| 873 | Thread.currentThread().interrupt(); // Restore the interrupted status. |
| 874 | throw new IOException("interrupted", e); // I hate checked exceptions. |
| 875 | } finally { |
| 876 | // We need to always destroy() the Process, otherwise we "leak" file |
| 877 | // descriptors and pipes. Unless I'm blind, this isn't actually |
| 878 | // documented in the Javadoc of the !@#$%^ JDK, and in Java 6 there's no |
| 879 | // way to ask the stupid-ass ProcessBuilder to not create fucking pipes. |
| 880 | // I think when the GC kicks in the JVM may run some kind of a finalizer |
| 881 | // that closes the pipes, because I've never seen this issue on long |
| 882 | // running TSDs, except where ulimit -n was low (the default, 1024). |
| 883 | gnuplot.destroy(); |
| 884 | } |
| 885 | gnuplotlatency.add((int) ((System.nanoTime() - start_time) / 1000000)); |
| 886 | if (rv != 0) { |
| 887 | final byte[] stderr = readFile(query, new File(basepath + ".err"), |
| 888 | 4096); |
| 889 | // Sometimes Gnuplot will error out but still create the file. |
| 890 | new File(basepath + ".png").delete(); |
| 891 | if (stderr == null) { |
| 892 | throw new GnuplotException(rv); |
| 893 | } |
| 894 | throw new GnuplotException(new String(stderr)); |
| 895 | } |
| 896 | // Remove the files for stderr/stdout if they're empty. |
| 897 | deleteFileIfEmpty(basepath + ".out"); |
| 898 | deleteFileIfEmpty(basepath + ".err"); |
| 899 | return nplotted; |
| 900 | } |
| 901 | |
| 902 | private static void deleteFileIfEmpty(final String path) { |
| 903 | final File file = new File(path); |
no test coverage detected