--- /dev/null
+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();
+}
+