dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / HdsdScriptVisitor.java
diff --git a/dol/src/dol/visitor/hdsd/HdsdScriptVisitor.java b/dol/src/dol/visitor/hdsd/HdsdScriptVisitor.java
new file mode 100644 (file)
index 0000000..322cb77
--- /dev/null
@@ -0,0 +1,376 @@
+package dol.visitor.hdsd;
+
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+import dol.visitor.MapVisitor;
+
+/**
+ *  Visitor that is used to generate a shell script to
+ *  distribute, run, monitor, profile and clean up a distributed
+ *  simulation.
+ */
+public class HdsdScriptVisitor extends MapVisitor {
+
+    /**
+     * Constructor.
+     *
+     * @param dir path of the shell script
+     */
+    public HdsdScriptVisitor(String dir) {
+        _dir = dir;
+    }
+
+    /**
+     * Create the shell script for the given mapping.
+     *
+     * @param x mapping that needs to be rendered.
+     */
+    public void visitComponent(Mapping x) {
+        try {
+            String filename = _dir + "/" + "scd.sh";
+            OutputStream file = new FileOutputStream(filename);
+            CodePrintStream ps = new CodePrintStream(file);
+
+            List<Processor> pList = x.getProcessorList();
+            int numProcessors = pList.size();
+            
+            // arrays to hold strings for generation
+            String[] hNames = new String[numProcessors];
+            String[] hAddrs = new String[numProcessors];
+            String[] hDirs = new String[numProcessors];
+            String[] hUsers = new String[numProcessors];
+            
+            // get processor information and fill to string arrays
+            int numSlaves = 0;
+            Iterator<Processor> iter = pList.iterator();
+            while (iter.hasNext())
+            {
+                Processor p = iter.next();
+                int pIdx = numSlaves;
+                boolean master = false;
+                Configuration c = p.getCfg("master"); 
+                if (c != null && c.getValue().equals("true"))
+                    master = true;
+                
+                // if it is the master, it will be the last processor
+                if (master)
+                    pIdx = numProcessors-1;
+                
+                // fill information to string arrays
+                hNames[pIdx] = p.getName();
+                hAddrs[pIdx] = p.getCfg("address").getValue();
+                c = p.getCfg("basedir");
+                if (c != null)
+                {
+                    String dir = c.getValue();
+                    // remove tailing '/'
+                    if ( dir.endsWith("/") )
+                        dir = dir.replaceAll("/" + "$", "");
+                    if (dir.equals(""))
+                        hDirs[pIdx] = hNames[pIdx];
+                    else
+                        hDirs[pIdx] = dir + "/" + hNames[pIdx];
+                }
+                else
+                    hDirs[pIdx] = hNames[pIdx];
+                c = p.getCfg("username");
+                if (c != null)
+                    hUsers[pIdx] = c.getValue() + "@";
+                else
+                    hUsers[pIdx] = "";
+                
+                if (!master)
+                    numSlaves++;
+            } // end get and fill information
+            
+            /* generate script */
+            // head
+            ps.println("#!/bin/bash");
+            ps.println();
+            ps.println("SCRIPTNAME=\"`echo $0 | sed 's/.*\\///'`\"");
+            ps.println();
+            
+            // host configuration
+            ps.println("### host configuration");
+            ps.print("NAME=( ");
+            for (int i=0; i<numProcessors; i++)
+                ps.print("\"" + hNames[i] + "\" ");
+            ps.println(")");
+            ps.print("ADDR=( ");
+            for (int i=0; i<numProcessors; i++)
+                ps.print("\"" + hAddrs[i] + "\" ");
+            ps.println(")");
+            ps.print("DIR=( ");
+            for (int i=0; i<numProcessors; i++)
+                ps.print("\"" + hDirs[i] + "\" ");
+            ps.println(")");
+            ps.print("USER=( ");
+            for (int i=0; i<numProcessors; i++)
+                ps.print("\"" + hUsers[i] + "\" ");
+            ps.println(")");
+            ps.println();
+
+            // paths
+            ps.println("### dol classpath");
+            ps.println("DOLPATH=\"" + _ui.getDOLPath() + "\"");
+            ps.println("CLASSPATH=\"${DOLPATH}/jars/jdom.jar:"
+                    + "${DOLPATH}/jars/xercesImpl.jar:"
+                    + "${DOLPATH}/build/bin/main\"");
+            ps.println("export CLASSPATH");
+            ps.println();
+            ps.println("### systemcd path");
+            ps.println("SCDPATH=\"" + System.getProperty("user.dir")
+                    + "/" + _dir + "\"");
+            ps.println();
+            
+            // function usage
+            ps.println("### function declarations");
+            ps.println();
+            ps.println("# function: prints usage information");
+            ps.println("function usage()");
+            ps.println("{");
+            ps.prefixInc();
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo \"Usage: ${SCRIPTNAME} COMMAND [OPTION]\"");
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo -e \"distribute\\tdistributes the binaries to the simulators\"");
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo -e \"run\\t\\truns the simulation and prints stdout of the master\"");
+                ps.printPrefixln("echo -e \"\\t\\tall stdouts are written to stdout_NETSIM.txt\"");
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo -e \"check\\t\\tchecks which simulators are still active\"");
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo -e \"kill\\t\\tkills all simulators\"");
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo -e \"profile PN.xml\\tretrieves the profiles from the simulators,\" \\");
+                ps.prefixInc();
+                    ps.printPrefixln("\"processes them and\"");
+                ps.prefixDec();
+                ps.printPrefixln("echo -e \"\\t\\tstores the cumulative results in PN_annotaded.xml\"");
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo -e \"cleanup\\t\\tremoves the simulation directory on all simulators\"");
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo -e \"help, -h\\tprints this help\"");
+                ps.printPrefixln("echo");
+            ps.prefixDec();
+            ps.println("}");
+            ps.println();
+
+            // function profile
+            ps.println("# function: adds profiling information of one simulator to xml");
+            ps.println("function profile()");
+            ps.println("{");
+            ps.prefixInc();
+                ps.printPrefixln("echo \"Retrieving profile from ${ADDR[$1]}\"");
+                ps.printPrefixln("scp ${USER[$1]}${ADDR[$1]}:${DIR[$1]}/profile_${NAME[$1]}.txt .");
+                ps.printPrefixln("if [ $? -ne 0 ]; then");
+                ps.prefixInc();
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("echo \"Retrieving profile from ${NAME[$1]} failed!\"");
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("rm scd_tmp_profiled.xml");
+                    ps.printPrefixln("exit 1");
+                ps.prefixDec();
+                ps.printPrefixln("fi");
+                ps.printPrefixln("echo \"Profiling ${NAME[$1]}\"");
+                ps.printPrefixln("java dol.main.Main -P scd_tmp_profiled.xml -T profile_${NAME[$1]}.txt > scd_profilerout.txt 2>&1");
+                ps.printPrefixln("if [ $? -ne 0 ]; then");
+                ps.prefixInc();
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("echo \"Profiling ${NAME[$1]} failed!\"");
+                    ps.printPrefixln("echo \"Check scd_tmp_profilerout.txt for more information.\"");
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("rm scd_tmp_profiled.xml");
+                    ps.printPrefixln("exit 1");
+                ps.prefixDec();
+                ps.printPrefixln("fi");
+                ps.printPrefixln("rm scd_profilerout.txt");
+                ps.printPrefixln("mv scd_tmp_profiled_annotated.xml scd_tmp_profiled.xml");
+                ps.printPrefixln("rm profile_${NAME[$1]}.txt");
+            ps.prefixDec();
+            ps.println("}");
+            ps.println();
+
+            // main programm start
+            ps.println("### main program");
+            ps.println();
+            ps.println("# require at least one argument");
+            ps.println("if [ ! $# -ge 1 ]; then");
+            ps.prefixInc();
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo \"Error: At least one argument is required!\"");
+                ps.printPrefixln("usage");
+                ps.printPrefixln("exit 1");
+            ps.prefixDec();
+            ps.println("fi");
+            ps.println();
+            ps.println("# switch on operation");
+            ps.println("case \"$1\" in");
+            
+            // distribute binaries to simulators
+            ps.println("\"distribute\")");
+            ps.prefixInc();
+                ps.printPrefixln("echo \"Distributing binaries to simulators...\"");
+                ps.printPrefixln("# prepare directories");
+                for (int i=0; i<numProcessors; i++)
+                    ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
+                            + "]} \"test -d ${DIR[" + i + "]} || mkdir -p "
+                            + "${DIR[" + i + "]}\"");
+                ps.printPrefixln("# copy files");
+                for (int i=0; i<numProcessors; i++)
+                    ps.printPrefixln("scp ${SCDPATH}/scd_${NAME[" + i
+                            + "]} ${USER[" + i + "]}${ADDR[" + i
+                            + "]}:${DIR[" + i + "]}/");
+            ps.prefixDec();
+            ps.println(";;");
+            
+            // run the simulation
+            ps.println("\"run\")");
+            ps.prefixInc();
+                ps.printPrefixln("echo \"Running simulation...\"");
+                for (int i=0; i<numProcessors-1; i++)
+                    ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
+                            + "]}  \"cd ${DIR[" + i + "]}; ./scd_${NAME["
+                            + i + "]}\" > stdout_${NAME[" + i + "]}.txt 2>&1 &");
+                ps.printPrefixln("ssh ${USER[" + (numProcessors-1)
+                        + "]}${ADDR[" + (numProcessors-1)
+                        + "]}  \"cd ${DIR[" + (numProcessors-1)
+                        + "]}; ./scd_${NAME[" + (numProcessors-1)
+                        + "]}\" 2>&1 | tee stdout_${NAME["
+                        + (numProcessors-1) + "]}.txt");
+            ps.prefixDec();
+            ps.println(";;");
+            
+            // check if simulators are running
+            ps.println("\"check\")");
+            ps.prefixInc();
+                ps.printPrefixln("echo \"Checking which simulators are active...\"");
+                for (int i=0; i<numProcessors; i++)
+                    ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i + "]} \"pgrep -x scd_${NAME[" + i + "]} > /dev/null && echo ${NAME[" + i + "]} is active || echo ${NAME[" + i + "]} is not active\"");
+            ps.prefixDec();
+            ps.println(";;");
+            
+            // kill all simulators
+            ps.println("\"kill\")");
+            ps.prefixInc();
+                ps.printPrefixln("echo \"Killing all simulators...\"");
+                for (int i=0; i<numProcessors; i++)
+                    ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i + "]} \"killall -e scd_${NAME[" + i + "]}\"");
+            ps.prefixDec();
+            ps.println(";;");
+            
+            // get and process profiles
+            ps.println("\"profile\")");
+            ps.prefixInc();
+                ps.printPrefixln("# require 2 arguments");
+                ps.printPrefixln("if [ $# -ne 2 ]; then");
+                ps.prefixInc();
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("echo \"Error: Illegal number of arguments!\"");
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("echo \"Usage: ${SCRIPTNAME} profile processnetwork.xml\"");
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("exit 1");
+                ps.prefixDec();
+                ps.printPrefixln("fi");
+                ps.println();
+                ps.printPrefixln("# check if process nework file exists");
+                ps.printPrefixln("if [ ! -f \"$2\" ]; then");
+                ps.prefixInc();
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("echo \"Error: File not found!\"");
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("exit 1");
+                ps.prefixDec();
+                ps.printPrefixln("fi");
+                ps.println();
+                ps.printPrefixln("# check file extension");
+                ps.printPrefixln("echo $2 | grep -e '\\.xml$' > /dev/null");
+                ps.printPrefixln("if [ $? -ne 0 ]; then");
+                ps.prefixInc();
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("echo \"Error: Illegal file extension: required .xml!\"");
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("exit 1");
+                ps.prefixDec();
+                ps.printPrefixln("fi");
+                ps.println();
+                ps.printPrefixln("PFILE=`echo $2 | sed 's/.*\\///' | sed 's/\\.xml$/_annotated.xml/'`");
+                ps.printPrefixln("echo \"Profiling into ${PFILE}...\"");
+                ps.println();
+                ps.printPrefixln("# check that the DOL is found and the classpath set correctly");
+                ps.printPrefixln("java dol.main.Main > /dev/null 2>&1");
+                ps.printPrefixln("if [ $? -eq 1 ]; then");
+                ps.prefixInc();
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("echo \"DOL framework not found!\"");
+                    ps.printPrefixln("echo");
+                    ps.printPrefixln("exit 1");
+                ps.prefixDec();
+                ps.printPrefixln("fi");
+                ps.printPrefixln("cp \"$2\" scd_tmp_profiled.xml");
+                ps.println();
+                for (int i=0; i<numProcessors; i++)
+                    ps.printPrefixln("profile " + i);
+                ps.println();
+                ps.printPrefixln("mv scd_tmp_profiled.xml \"${PFILE}\""); 
+            ps.prefixDec();
+            ps.println(";;");
+            
+            // deleting remote files
+            ps.printPrefixln("\"cleanup\")");
+            ps.prefixInc();
+                ps.printPrefixln("echo \"Deleting simulator directory on simulators...\"");
+                for (int i=0; i<numProcessors; i++)
+                    ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
+                            + "]} \"rm -r ${DIR[" + i + "]}\"");
+            ps.prefixDec();
+            ps.println(";;");
+            
+            // tail
+            ps.println("\"help\")");
+            ps.prefixInc();
+                ps.printPrefixln("usage");
+            ps.prefixDec();
+            ps.println(";;");
+            ps.println("\"-h\")");
+            ps.prefixInc();
+                ps.printPrefixln("usage");
+            ps.prefixDec();
+            ps.println(";;");
+            ps.println("\"--help\")");
+            ps.prefixInc();
+                ps.printPrefixln("usage");
+            ps.prefixDec();
+            ps.println(";;");
+            ps.println("*)");
+            ps.prefixInc();
+                ps.printPrefixln("echo");
+                ps.printPrefixln("echo \"Error: Illegal command: $1\"");
+                ps.printPrefixln("usage");
+                ps.printPrefixln("exit 1");
+            ps.prefixDec();
+            ps.println(";;");
+            ps.println("esac");
+
+        } catch (Exception e) {
+            System.out.println("HdsdMakefileVisitor: exception occured: "
+                    + e.getMessage());
+            e.printStackTrace();
+        }
+
+    } // end visitor
+
+    protected String _dir = null;
+    protected UserInterface _ui = UserInterface.getInstance();
+}
+