From c28403cb2652fa2f79384292d1e864f5154fc859 Mon Sep 17 00:00:00 2001 From: worku005 <dirk-jan.vanworkum@wur.nl> Date: Mon, 2 Dec 2024 13:30:32 +0100 Subject: [PATCH] introducing small class to handle stderr for mcl to fix hanging issue --- .../construction/grouping/Grouping.java | 33 ++++++------ .../java/nl/wur/bif/pantools/utils/Utils.java | 51 +++++++++++++++---- 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/main/java/nl/wur/bif/pantools/construction/grouping/Grouping.java b/src/main/java/nl/wur/bif/pantools/construction/grouping/Grouping.java index 28c709209..fc338b509 100644 --- a/src/main/java/nl/wur/bif/pantools/construction/grouping/Grouping.java +++ b/src/main/java/nl/wur/bif/pantools/construction/grouping/Grouping.java @@ -717,8 +717,7 @@ public class Grouping { * @param pangenome_path The path to the current graph database */ void break_component(LinkedList<Node> component, String pangenome_path) throws InterruptedException { - int group_size, wating_time, time; - double infl; + int group_size; LinkedList<Node> homology_group, singletons_group = new LinkedList(); String graph_path, clusters_path, line, command; BufferedReader clusters_file; @@ -726,25 +725,23 @@ public class Grouping { group_size = component.size(); graph_path = pangenome_path + "/" + component.getFirst().getId() + ".graph"; clusters_path = pangenome_path + "/" + component.getFirst().getId() + ".clusters"; - // Prepare the input file for MCL + + // Prepare the input file for MCL write_similaity_matrix(component, graph_path); - // Estimate the run-time of MCL - time = wating_time = 1 + (int) Math.round(group_size / 100000000.0 * group_size); - for( infl = MCL_INFLATION; infl < 30; infl += 0.5) { - command = "mcl " + graph_path + " --abc -I " + infl + " -o " + clusters_path + " -overlap keep"; - //Pantools.logger.info(command); - if(executeCommand_for(command, wating_time)) - break; - if((tmp_file = new File(clusters_path)).exists()) - tmp_file.delete(); - wating_time += time; - } - if (infl >= 30) { + + // Run MCL + command = "mcl " + graph_path + " --abc -I " + MCL_INFLATION + " -o " + clusters_path + " -overlap keep -V all"; + Pantools.logger.debug(command); + if (!executeCommand_for(command, 5)) { Pantools.logger.info("Failed to split group ID = {}", component.getFirst().getId()); homology_groups_list.put(component); + if ((tmp_file = new File(clusters_path)).exists()) { + tmp_file.delete(); + } } else { + // Read the output of MCL and create homology groups try (Transaction tx = GRAPH_DB.beginTx()) { - try{ + try { clusters_file = new BufferedReader(new FileReader(clusters_path)); final List<Set<Long>> cluster = new ArrayList<>(); // For each line of the MCL output @@ -772,7 +769,7 @@ public class Grouping { clusters_file.close(); new File(clusters_path).delete(); new File(graph_path).delete(); - }catch (IOException ex) { + } catch (IOException ex) { Pantools.logger.info(ex.getMessage()); } tx.success(); @@ -2994,4 +2991,4 @@ public class Grouping { tx.success(); } } -} \ No newline at end of file +} diff --git a/src/main/java/nl/wur/bif/pantools/utils/Utils.java b/src/main/java/nl/wur/bif/pantools/utils/Utils.java index 084d7e770..0af62a900 100644 --- a/src/main/java/nl/wur/bif/pantools/utils/Utils.java +++ b/src/main/java/nl/wur/bif/pantools/utils/Utils.java @@ -571,19 +571,52 @@ public final class Utils { * Executes a shell command in a limited number of seconds. * * @param command The command - * @param seconds The number of seconds + * @param timeout The number of seconds before the command is killed * @return The output of the bash command */ - public static boolean executeCommand_for(String command, int seconds) { - Process p; - boolean success = false; + public static boolean executeCommand_for(String command, int timeout) { + Process process = null; try { - p = Runtime.getRuntime().exec(command); - success = p.waitFor(seconds, TimeUnit.SECONDS); - } catch (Exception e) { - e.printStackTrace(); + process = Runtime.getRuntime().exec(command); + StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream()); //to make sure the process does not hang + StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream()); //to make sure the process does not hang + + outputGobbler.start(); + errorGobbler.start(); + + boolean finished = process.waitFor(timeout, TimeUnit.SECONDS); + outputGobbler.join(); + errorGobbler.join(); + + return finished && process.exitValue() == 0; + } catch (IOException | InterruptedException e) { + Pantools.logger.error("Error executing command: {}", command, e); + return false; + } finally { + if (process != null) { + process.destroy(); + } + } + } + + private static class StreamGobbler extends Thread { + private final InputStream inputStream; + + public StreamGobbler(InputStream inputStream) { + this.inputStream = inputStream; + } + + @Override + public void run() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + String line; + while ((line = reader.readLine()) != null) { + Pantools.logger.trace("{}", line); + } + } catch (IOException e) { + e.printStackTrace(); + } } - return success; } /** -- GitLab