Java tutorial
/** * (C) Copyright IBM Corp. 2010, 2015 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.ibm.bi.dml.debug; import java.io.PrintStream; import java.util.HashMap; import org.apache.commons.cli.CommandLine; import org.apache.commons.lang.math.IntRange; import com.ibm.bi.dml.debug.DMLDebuggerFunctions; import com.ibm.bi.dml.runtime.controlprogram.context.ExecutionContext; import com.ibm.bi.dml.runtime.controlprogram.context.ExecutionContextFactory; import com.ibm.bi.dml.runtime.instructions.cp.BreakPointInstruction.BPINSTRUCTION_STATUS; /** * This class implements a debugger control module for DML scripts. * Note: ONLY USED FOR DEBUGGING PURPOSES */ public class DMLDebugger { // This will be supported in subsquent release. turning off the -debug 'optimize' feature for current release. //public static boolean ENABLE_DEBUG_OPTIMIZER = false; //default debug mode //public static boolean ENABLE_SERVER_SIDE_DEBUG_MODE = false; //default debug mode //public static final String DEBUGGER_SYSTEMML_CONFIG_FILEPATH = "./DebuggerSystemML-config.xml"; private DMLDebuggerProgramInfo dbprog; //parsed and compiled DML script w/ hops, lops and runtime program public DMLDebuggerInterface debuggerUI; //debugger command line interface private DMLDebuggerFunctions dbFunctions; //debugger functions interface private CommandLine cmd; //debugger function command //support for obtaining STDOUT/STDERR streams of DML program running in debug mode private PrintStream originalOut = null; private PrintStream originalErr = null; private String dmlScriptStr; //DML script contents (including new lines) HashMap<String, String> argVals; //key-value pairs defining arguments of DML script ExecutionContext preEC = null; ExecutionContext currEC = null; String[] lines; volatile boolean quit = false; /** * Constructor for DML debugger CLI */ public DMLDebugger(DMLDebuggerProgramInfo p, String dmlScript, HashMap<String, String> args) { dbprog = p; dmlScriptStr = dmlScript; lines = dmlScriptStr.split("\n"); argVals = args; debuggerUI = new DMLDebuggerInterface(); dbFunctions = new DMLDebuggerFunctions(); preEC = ExecutionContextFactory.createContext(dbprog.rtprog); setupDMLRuntime(); } /** * Sets up DML runtime with DML script and instructions information */ private void setupDMLRuntime() { dbprog.setDMLInstMap(); preEC.getDebugState().setDMLScript(lines); } /** * Sets STDOUT stream of a DML program running in debug mode */ @SuppressWarnings("unused") private void setStdOut() { originalOut = System.out; System.setOut(originalOut); } /** * Gets STDOUT stream of a DML program running in debug mode * @return STDOUT stream of DML program */ @SuppressWarnings("unused") private PrintStream getStdOut() { System.out.flush(); return originalOut; } /** * Sets STDERR stream of a DML program running in debug mode */ @SuppressWarnings("unused") private void setStdErr() { originalErr = System.err; System.setOut(originalErr); } /** * Gets STDERR stream of a DML program running in debug mode * @return STDERR stream of DML program */ @SuppressWarnings("unused") private PrintStream getStdErr() { System.err.flush(); return originalErr; } /** * Get debug function command from debugger CLI * @throws DMLDebuggerException */ private void getCommand() throws DMLDebuggerException { cmd = debuggerUI.getDebuggerCommand(); } /** * Class for running the DML runtime as a thread */ Runnable DMLRuntime = new Runnable() { public void run() { try { // System.out.println("Starting DML script ..."); dbprog.rtprog.execute(currEC); // System.out.println("DML script has finished execution."); synchronized (DMLDebugger.class) { quit = true; } } catch (Exception e) { System.err.println("Exception raised by DML runtime:" + e); } } }; /** * Controls the communication between debugger CLI and DML runtime. */ @SuppressWarnings("deprecation") public synchronized void runSystemMLDebugger() { debuggerUI.setOptions(); debuggerUI.getDebuggerCLI(); Thread runtime = new Thread(DMLRuntime); boolean isRuntimeInstruction = false; while (!quit) { try { //get debugger function from CLI getCommand(); if (cmd != null) { isRuntimeInstruction = false; //check for help if (cmd.hasOption("h")) { debuggerUI.getDebuggerCLI(); } //check for exit else if (cmd.hasOption("q")) { synchronized (DMLDebugger.class) { quit = true; } runtime.stop(); } else if (cmd.hasOption("r")) { if (currEC != null) { System.out.println( "Runtime has already started. Try \"s\" to go to next line, or \"c\" to continue running your DML script."); } else { currEC = preEC; runtime.start(); isRuntimeInstruction = true; } } else if (cmd.hasOption("c")) { if (currEC == null) System.out.println( "Runtime has not been started. Try \"r\" to start DML runtime execution."); else if (!runtime.isAlive()) { System.err.println("Invalid debug state."); //System.out.println("Runtime terminated. Try \"-c\" to recompile followed by \"r\" to restart DML runtime execution."); } else { System.out.println("Resuming DML script execution ..."); preEC.getDebugState().setCommand(null); runtime.resume(); isRuntimeInstruction = true; } } else if (cmd.hasOption("si")) { if (!runtime.isAlive()) { currEC = preEC; runtime.start(); isRuntimeInstruction = true; // System.out.println("Runtime must be started before single stepping can be enabled. Try \"r\" to start DML runtime execution."); } //else { preEC.getDebugState().setCommand("step_instruction"); runtime.resume(); isRuntimeInstruction = true; //} } else if (cmd.hasOption("s")) { if (!runtime.isAlive()) { currEC = preEC; runtime.start(); isRuntimeInstruction = true; //System.out.println("Runtime must be started before step over can be enabled. Try \"r\" to start DML runtime execution."); } //else { preEC.getDebugState().setCommand("step_line"); runtime.resume(); isRuntimeInstruction = true; //} } // else if (cmd.hasOption("step_return")) { // if (!runtime.isAlive()) { // System.out.println("Runtime must be started before step return can be enabled. Try \"r\" to start DML runtime execution."); // } // else { // String fname = dbFunctions.getValue(cmd.getOptionValues("step_return")); // dbprog.rtprog.setCommand("step return"); // if (fname != null) { // dbprog.rtprog.setCommandArg(fname); // } // runtime.resume(); // isRuntimeInstruction = true; // } // } else if (cmd.hasOption("b")) { int lineNumber = dbFunctions.getValue(cmd.getOptionValues("b"), lines.length); if (lineNumber > 0) { if (DMLBreakpointManager.getBreakpoint(lineNumber) == null) System.out.println("Sorry, a breakpoint cannot be inserted at line " + lineNumber + ". Please try a different line number."); else { if (DMLBreakpointManager.getBreakpoint(lineNumber) .getBPInstructionStatus() != BPINSTRUCTION_STATUS.INVISIBLE) { System.out.format("Breakpoint at line %d already exists.\n", lineNumber); } else { dbprog.accessBreakpoint(lineNumber, 0, BPINSTRUCTION_STATUS.ENABLED); } } } } else if (cmd.hasOption("d")) { int lineNumber = dbFunctions.getValue(cmd.getOptionValues("d"), lines.length); if (lineNumber > 0 && DMLBreakpointManager.getBreakpoint(lineNumber) != null && DMLBreakpointManager.getBreakpoint(lineNumber) .getBPInstructionStatus() != BPINSTRUCTION_STATUS.INVISIBLE) { dbprog.accessBreakpoint(lineNumber, 1, BPINSTRUCTION_STATUS.INVISIBLE); //dbprog.accessBreakpoint(lineNumber, 1, BPINSTRUCTION_STATUS.DISABLED); } else { System.out.println("Sorry, a breakpoint cannot be deleted at line " + lineNumber + ". Please try a different line number."); } } else if (cmd.hasOption("i")) { String[] infoOptions = cmd.getOptionValues("i"); if (infoOptions == null || infoOptions.length == 0) { System.err.println( "The command \"info\" requires option. Try \"info break\" or \"info frame\"."); } else if (infoOptions[0].trim().compareTo("break") == 0) { dbFunctions.listBreakpoints(DMLBreakpointManager.getBreakpoints()); } else if (infoOptions[0].trim().compareTo("frame") == 0) { if (!runtime.isAlive()) System.err.println( "Runtime has not been started. Try \"r\" or \"s\" to start DML runtime execution."); else dbFunctions.printCallStack(currEC.getDebugState().getCurrentFrame(), currEC.getDebugState().getCallStack()); } else { System.err.println( "Invalid option for command \"info\". Try \"info break\" or \"info frame\"."); } } else if (cmd.hasOption("p")) { String[] pOptions = cmd.getOptionValues("p"); if (pOptions == null || pOptions.length != 1) { System.err.println("Incorrect options for command \"print\""); } else { String varName = pOptions[0].trim(); if (runtime.isAlive()) { if (varName.contains("[")) { // matrix with index: can be cell or column or row try { //System.out.println("" + varName); String variableNameWithoutIndices = varName.split("\\[")[0].trim(); //System.out.println("" + variableNameWithoutIndices); String indexString = (varName.split("\\[")[1].trim()).split("\\]")[0] .trim(); //System.out.println(">>" + indexString + "<<"); String rowIndexStr = ""; String colIndexStr = ""; if (indexString.startsWith(",")) { colIndexStr = indexString.split(",")[1].trim(); } else if (indexString.endsWith(",")) { rowIndexStr = indexString.split(",")[0].trim(); } else { rowIndexStr = indexString.split(",")[0].trim(); colIndexStr = indexString.split(",")[1].trim(); } int rowIndex = -1; int colIndex = -1; if (rowIndexStr.compareTo("") != 0) { rowIndex = Integer.parseInt(rowIndexStr); } if (colIndexStr.compareTo("") != 0) { colIndex = Integer.parseInt(colIndexStr); } //System.out.println("" + rowIndex + " " + colIndex); dbFunctions.print(currEC.getDebugState().getVariables(), variableNameWithoutIndices, "value", rowIndex, colIndex); } catch (Exception indicesException) { System.err.println( "Incorrect fomat for \"p\". If you are trying to print matrix variable M, you can use M[1,] or M[,1] or M[1,1] (without spaces)."); } } else { // Print entire matrix dbFunctions.print(currEC.getDebugState().getVariables(), varName, "value", -1, -1); } } else System.err.println( "Runtime has not been started. Try \"r\" or \"s\" to start DML runtime execution."); } } else if (cmd.hasOption("whatis")) { String[] pOptions = cmd.getOptionValues("whatis"); if (pOptions == null || pOptions.length != 1) { System.err.println("Incorrect options for command \"whatis\""); } else { String varName = pOptions[0].trim(); dbFunctions.print(currEC.getDebugState().getVariables(), varName, "metadata", -1, -1); } } else if (cmd.hasOption("set")) { String[] pOptions = cmd.getOptionValues("set"); if (pOptions == null || pOptions.length != 2) { System.err.println("Incorrect options for command \"set\""); } else { try { if (pOptions[0].contains("[")) { String[] paramsToSetMatrix = new String[4]; paramsToSetMatrix[0] = pOptions[0].split("\\[")[0].trim(); String indexString = (pOptions[0].split("\\[")[1].trim()).split("\\]")[0] .trim(); paramsToSetMatrix[1] = indexString.split(",")[0].trim(); paramsToSetMatrix[2] = indexString.split(",")[1].trim(); paramsToSetMatrix[3] = pOptions[1].trim(); dbFunctions.setMatrixCell(currEC.getDebugState().getVariables(), paramsToSetMatrix); } else { dbFunctions.setScalarValue(currEC.getDebugState().getVariables(), pOptions); } } catch (Exception exception1) { System.out.println( "Only scalar variable or a matrix cell available in current frame can be set in current version."); } } } else if (cmd.hasOption("l")) { String[] pOptions = cmd.getOptionValues("l"); String[] argsForRange = new String[2]; int currentPC = 1; if (runtime.isAlive()) { currentPC = currEC.getDebugState().getPC().getLineNumber(); } IntRange range = null; if (pOptions == null) { // Print first 10 lines range = new IntRange(currentPC, Math.min(lines.length, currentPC + 10)); } else if (pOptions.length == 1 && pOptions[0].trim().toLowerCase().compareTo("all") == 0) { // Print entire program range = new IntRange(1, lines.length); } else if (pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("next") == 0) { int numLines = 10; try { numLines = Integer.parseInt(pOptions[1]); } catch (Exception e1) { } argsForRange[0] = "" + currentPC; argsForRange[1] = "" + Math.min(lines.length, numLines + currentPC); range = dbFunctions.getRange(argsForRange, lines.length); } else if (pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("prev") == 0) { int numLines = 10; try { numLines = Integer.parseInt(pOptions[1]); } catch (Exception e1) { } argsForRange[0] = "" + Math.max(1, currentPC - numLines); argsForRange[1] = "" + currentPC; range = dbFunctions.getRange(argsForRange, lines.length); } if (range == null) { System.err.println( "Incorrect usage of command \"l\". Try \"l\" or \"l all\" or \"l next 5\" or \"l prev 5\"."); } else { if (range.getMinimumInteger() > 0) { dbFunctions.printLines(lines, range); } else { System.err.println( "Sorry no lines that can be printed. Try \"l\" or \"l all\" or \"l next 5\" or \"l prev 5\"."); } } // Old code: // IntRange range = dbFunctions.getRange(cmd.getOptionValues("p"), lines.length); //if (range.getMinimumInteger() > 0) { // dbFunctions.printLines(lines, range); // } } else if (cmd.hasOption("li")) { String[] pOptions = cmd.getOptionValues("li"); String[] argsForRange = new String[2]; int currentPC = 1; if (runtime.isAlive()) { currentPC = currEC.getDebugState().getPC().getLineNumber(); } IntRange range = null; if (pOptions == null) { // Print first 10 lines range = new IntRange(currentPC, Math.min(lines.length, currentPC + 10)); } else if (pOptions.length == 1 && pOptions[0].trim().toLowerCase().compareTo("all") == 0) { // Print entire program range = new IntRange(1, lines.length); } else if (pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("next") == 0) { int numLines = 10; try { numLines = Integer.parseInt(pOptions[1]); } catch (Exception e1) { } argsForRange[0] = "" + currentPC; argsForRange[1] = "" + Math.min(lines.length, numLines + currentPC); range = dbFunctions.getRange(argsForRange, lines.length); } else if (pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("prev") == 0) { int numLines = 10; try { numLines = Integer.parseInt(pOptions[1]); } catch (Exception e1) { } argsForRange[0] = "" + Math.max(1, currentPC - numLines); argsForRange[1] = "" + currentPC; range = dbFunctions.getRange(argsForRange, lines.length); } if (range == null) { System.err.println( "Incorrect usage of command \"li\". Try \"li\" or \"li all\" or \"li next 5\" or \"li prev 5\"."); } else { if (range.getMinimumInteger() > 0) { dbFunctions.printInstructions(lines, dbprog.getDMLInstMap(), range, false); } else { System.err.println( "Sorry no lines that can be printed. Try \"li\" or \"li all\" or \"li next 5\" or \"li prev 5\"."); } } // Old code: // IntRange range = dbFunctions.getRange(cmd.getOptionValues("p"), lines.length); //if (range.getMinimumInteger() > 0) { // dbFunctions.printLines(lines, range); // } } else if (cmd.hasOption("set_scalar")) { if (!runtime.isAlive()) System.err.println( "Runtime has not been started. Try \"r\" to start DML runtime execution."); else dbFunctions.setScalarValue(currEC.getDebugState().getVariables(), cmd.getOptionValues("set_scalar")); } else if (cmd.hasOption("m")) { String varname = dbFunctions.getValue(cmd.getOptionValues("m")); if (runtime.isAlive()) dbFunctions.printMatrixVariable(currEC.getDebugState().getVariables(), varname); else System.err.println( "Runtime has not been started. Try \"r\" to start DML runtime execution."); } else if (cmd.hasOption("x")) { if (!runtime.isAlive()) System.err.println( "Runtime has not been started. Try \"r\" to start DML runtime execution."); else { dbFunctions.printMatrixCell(currEC.getDebugState().getVariables(), cmd.getOptionValues("x")); } } else if (cmd.hasOption("set_cell")) { if (!runtime.isAlive()) System.err.println( "Runtime has not been started. Try \"r\" to start DML runtime execution."); else { dbFunctions.setMatrixCell(currEC.getDebugState().getVariables(), cmd.getOptionValues("set_cell")); } } else { System.err.println("Undefined command. Try \"help\"."); } //block until runtime suspends execution or terminates //while(runtime.isAlive() && !currEC.getProgram().isStopped()) { wait(300); // To avoid race condition between submitting job and //System.out.println(">> Before while"); while (isRuntimeInstruction && !currEC.getDebugState().canAcceptNextCommand()) { if (quit) { break; } else { wait(300); //wait } } //System.out.println(">> After while"); } wait(300); } catch (Exception e) { System.err.println("Error processing debugger command. Try \"help\"."); } } } // Since the recompile option is disabled in the debugger to make the interface much cleaner // /** // * compile: Compile DML script and generate hops, lops and runtime program for debugger. // * @param dmlScriptStr DML script contents (including new lines) // * @param argVals Key-value pairs defining arguments of DML script // * @throws ParseException // * @throws IOException // * @throws DMLRuntimeException // * @throws LanguageException // * @throws HopsException // * @throws LopsException // * @throws DMLUnsupportedOperationException // * @throws Exception // */ // private void recompile(String dmlScriptStr, HashMap<String,String> argVals) // throws ParseException, IOException, DMLRuntimeException, LanguageException, HopsException, LopsException, DMLUnsupportedOperationException, Exception // { // dbprog = new DMLDebuggerProgramInfo(); // // //Step 1: parse dml script // if(DMLScript.ENABLE_PYTHON_PARSING) { // PyDMLParserWrapper parser = new PyDMLParserWrapper(); // dbprog.prog = parser.parse(DMLScript.DML_FILE_PATH_ANTLR_PARSER, dmlScriptStr, argVals); // } // else { // DMLParserWrapper parser = new DMLParserWrapper(); // dbprog.prog = parser.parse(DMLScript.DML_FILE_PATH_ANTLR_PARSER, dmlScriptStr, argVals); // } // // //Step 3: construct HOP DAGs (incl LVA and validate) // dbprog.dmlt = new DMLTranslator(dbprog.prog); // dbprog.dmlt.liveVariableAnalysis(dbprog.prog); // dbprog.dmlt.validateParseTree(dbprog.prog); // dbprog.dmlt.constructHops(dbprog.prog); // // //Step 4: rewrite HOP DAGs (incl IPA and memory estimates) // dbprog.dmlt.rewriteHopsDAG(dbprog.prog); // // //Step 5: construct LOP DAGs // dbprog.dmlt.constructLops(dbprog.prog); // // //Step 6: generate runtime program // dbprog.rtprog = dbprog.prog.getRuntimeProgram(dbprog.conf); // // //Set debug mode flag // setupDMLRuntime(); // } }