dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / HdsdScriptVisitor.java
1 package dol.visitor.hdsd;
2
3
4 import java.io.FileOutputStream;
5 import java.io.OutputStream;
6 import java.util.Iterator;
7 import java.util.List;
8
9 import dol.datamodel.architecture.Configuration;
10 import dol.datamodel.architecture.Processor;
11 import dol.datamodel.mapping.Mapping;
12 import dol.main.UserInterface;
13 import dol.util.CodePrintStream;
14 import dol.visitor.MapVisitor;
15
16 /**
17  *  Visitor that is used to generate a shell script to
18  *  distribute, run, monitor, profile and clean up a distributed
19  *  simulation.
20  */
21 public class HdsdScriptVisitor extends MapVisitor {
22
23     /**
24      * Constructor.
25      *
26      * @param dir path of the shell script
27      */
28     public HdsdScriptVisitor(String dir) {
29         _dir = dir;
30     }
31
32     /**
33      * Create the shell script for the given mapping.
34      *
35      * @param x mapping that needs to be rendered.
36      */
37     public void visitComponent(Mapping x) {
38         try {
39             String filename = _dir + "/" + "scd.sh";
40             OutputStream file = new FileOutputStream(filename);
41             CodePrintStream ps = new CodePrintStream(file);
42
43             List<Processor> pList = x.getProcessorList();
44             int numProcessors = pList.size();
45             
46             // arrays to hold strings for generation
47             String[] hNames = new String[numProcessors];
48             String[] hAddrs = new String[numProcessors];
49             String[] hDirs = new String[numProcessors];
50             String[] hUsers = new String[numProcessors];
51             
52             // get processor information and fill to string arrays
53             int numSlaves = 0;
54             Iterator<Processor> iter = pList.iterator();
55             while (iter.hasNext())
56             {
57                 Processor p = iter.next();
58                 int pIdx = numSlaves;
59                 boolean master = false;
60                 Configuration c = p.getCfg("master"); 
61                 if (c != null && c.getValue().equals("true"))
62                     master = true;
63                 
64                 // if it is the master, it will be the last processor
65                 if (master)
66                     pIdx = numProcessors-1;
67                 
68                 // fill information to string arrays
69                 hNames[pIdx] = p.getName();
70                 hAddrs[pIdx] = p.getCfg("address").getValue();
71                 c = p.getCfg("basedir");
72                 if (c != null)
73                 {
74                     String dir = c.getValue();
75                     // remove tailing '/'
76                     if ( dir.endsWith("/") )
77                         dir = dir.replaceAll("/" + "$", "");
78                     if (dir.equals(""))
79                         hDirs[pIdx] = hNames[pIdx];
80                     else
81                         hDirs[pIdx] = dir + "/" + hNames[pIdx];
82                 }
83                 else
84                     hDirs[pIdx] = hNames[pIdx];
85                 c = p.getCfg("username");
86                 if (c != null)
87                     hUsers[pIdx] = c.getValue() + "@";
88                 else
89                     hUsers[pIdx] = "";
90                 
91                 if (!master)
92                     numSlaves++;
93             } // end get and fill information
94             
95             /* generate script */
96             // head
97             ps.println("#!/bin/bash");
98             ps.println();
99             ps.println("SCRIPTNAME=\"`echo $0 | sed 's/.*\\///'`\"");
100             ps.println();
101             
102             // host configuration
103             ps.println("### host configuration");
104             ps.print("NAME=( ");
105             for (int i=0; i<numProcessors; i++)
106                 ps.print("\"" + hNames[i] + "\" ");
107             ps.println(")");
108             ps.print("ADDR=( ");
109             for (int i=0; i<numProcessors; i++)
110                 ps.print("\"" + hAddrs[i] + "\" ");
111             ps.println(")");
112             ps.print("DIR=( ");
113             for (int i=0; i<numProcessors; i++)
114                 ps.print("\"" + hDirs[i] + "\" ");
115             ps.println(")");
116             ps.print("USER=( ");
117             for (int i=0; i<numProcessors; i++)
118                 ps.print("\"" + hUsers[i] + "\" ");
119             ps.println(")");
120             ps.println();
121
122             // paths
123             ps.println("### dol classpath");
124             ps.println("DOLPATH=\"" + _ui.getDOLPath() + "\"");
125             ps.println("CLASSPATH=\"${DOLPATH}/jars/jdom.jar:"
126                     + "${DOLPATH}/jars/xercesImpl.jar:"
127                     + "${DOLPATH}/build/bin/main\"");
128             ps.println("export CLASSPATH");
129             ps.println();
130             ps.println("### systemcd path");
131             ps.println("SCDPATH=\"" + System.getProperty("user.dir")
132                     + "/" + _dir + "\"");
133             ps.println();
134             
135             // function usage
136             ps.println("### function declarations");
137             ps.println();
138             ps.println("# function: prints usage information");
139             ps.println("function usage()");
140             ps.println("{");
141             ps.prefixInc();
142                 ps.printPrefixln("echo");
143                 ps.printPrefixln("echo \"Usage: ${SCRIPTNAME} COMMAND [OPTION]\"");
144                 ps.printPrefixln("echo");
145                 ps.printPrefixln("echo -e \"distribute\\tdistributes the binaries to the simulators\"");
146                 ps.printPrefixln("echo");
147                 ps.printPrefixln("echo -e \"run\\t\\truns the simulation and prints stdout of the master\"");
148                 ps.printPrefixln("echo -e \"\\t\\tall stdouts are written to stdout_NETSIM.txt\"");
149                 ps.printPrefixln("echo");
150                 ps.printPrefixln("echo -e \"check\\t\\tchecks which simulators are still active\"");
151                 ps.printPrefixln("echo");
152                 ps.printPrefixln("echo -e \"kill\\t\\tkills all simulators\"");
153                 ps.printPrefixln("echo");
154                 ps.printPrefixln("echo -e \"profile PN.xml\\tretrieves the profiles from the simulators,\" \\");
155                 ps.prefixInc();
156                     ps.printPrefixln("\"processes them and\"");
157                 ps.prefixDec();
158                 ps.printPrefixln("echo -e \"\\t\\tstores the cumulative results in PN_annotaded.xml\"");
159                 ps.printPrefixln("echo");
160                 ps.printPrefixln("echo -e \"cleanup\\t\\tremoves the simulation directory on all simulators\"");
161                 ps.printPrefixln("echo");
162                 ps.printPrefixln("echo -e \"help, -h\\tprints this help\"");
163                 ps.printPrefixln("echo");
164             ps.prefixDec();
165             ps.println("}");
166             ps.println();
167
168             // function profile
169             ps.println("# function: adds profiling information of one simulator to xml");
170             ps.println("function profile()");
171             ps.println("{");
172             ps.prefixInc();
173                 ps.printPrefixln("echo \"Retrieving profile from ${ADDR[$1]}\"");
174                 ps.printPrefixln("scp ${USER[$1]}${ADDR[$1]}:${DIR[$1]}/profile_${NAME[$1]}.txt .");
175                 ps.printPrefixln("if [ $? -ne 0 ]; then");
176                 ps.prefixInc();
177                     ps.printPrefixln("echo");
178                     ps.printPrefixln("echo \"Retrieving profile from ${NAME[$1]} failed!\"");
179                     ps.printPrefixln("echo");
180                     ps.printPrefixln("rm scd_tmp_profiled.xml");
181                     ps.printPrefixln("exit 1");
182                 ps.prefixDec();
183                 ps.printPrefixln("fi");
184                 ps.printPrefixln("echo \"Profiling ${NAME[$1]}\"");
185                 ps.printPrefixln("java dol.main.Main -P scd_tmp_profiled.xml -T profile_${NAME[$1]}.txt > scd_profilerout.txt 2>&1");
186                 ps.printPrefixln("if [ $? -ne 0 ]; then");
187                 ps.prefixInc();
188                     ps.printPrefixln("echo");
189                     ps.printPrefixln("echo \"Profiling ${NAME[$1]} failed!\"");
190                     ps.printPrefixln("echo \"Check scd_tmp_profilerout.txt for more information.\"");
191                     ps.printPrefixln("echo");
192                     ps.printPrefixln("rm scd_tmp_profiled.xml");
193                     ps.printPrefixln("exit 1");
194                 ps.prefixDec();
195                 ps.printPrefixln("fi");
196                 ps.printPrefixln("rm scd_profilerout.txt");
197                 ps.printPrefixln("mv scd_tmp_profiled_annotated.xml scd_tmp_profiled.xml");
198                 ps.printPrefixln("rm profile_${NAME[$1]}.txt");
199             ps.prefixDec();
200             ps.println("}");
201             ps.println();
202
203             // main programm start
204             ps.println("### main program");
205             ps.println();
206             ps.println("# require at least one argument");
207             ps.println("if [ ! $# -ge 1 ]; then");
208             ps.prefixInc();
209                 ps.printPrefixln("echo");
210                 ps.printPrefixln("echo \"Error: At least one argument is required!\"");
211                 ps.printPrefixln("usage");
212                 ps.printPrefixln("exit 1");
213             ps.prefixDec();
214             ps.println("fi");
215             ps.println();
216             ps.println("# switch on operation");
217             ps.println("case \"$1\" in");
218             
219             // distribute binaries to simulators
220             ps.println("\"distribute\")");
221             ps.prefixInc();
222                 ps.printPrefixln("echo \"Distributing binaries to simulators...\"");
223                 ps.printPrefixln("# prepare directories");
224                 for (int i=0; i<numProcessors; i++)
225                     ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
226                             + "]} \"test -d ${DIR[" + i + "]} || mkdir -p "
227                             + "${DIR[" + i + "]}\"");
228                 ps.printPrefixln("# copy files");
229                 for (int i=0; i<numProcessors; i++)
230                     ps.printPrefixln("scp ${SCDPATH}/scd_${NAME[" + i
231                             + "]} ${USER[" + i + "]}${ADDR[" + i
232                             + "]}:${DIR[" + i + "]}/");
233             ps.prefixDec();
234             ps.println(";;");
235             
236             // run the simulation
237             ps.println("\"run\")");
238             ps.prefixInc();
239                 ps.printPrefixln("echo \"Running simulation...\"");
240                 for (int i=0; i<numProcessors-1; i++)
241                     ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
242                             + "]}  \"cd ${DIR[" + i + "]}; ./scd_${NAME["
243                             + i + "]}\" > stdout_${NAME[" + i + "]}.txt 2>&1 &");
244                 ps.printPrefixln("ssh ${USER[" + (numProcessors-1)
245                         + "]}${ADDR[" + (numProcessors-1)
246                         + "]}  \"cd ${DIR[" + (numProcessors-1)
247                         + "]}; ./scd_${NAME[" + (numProcessors-1)
248                         + "]}\" 2>&1 | tee stdout_${NAME["
249                         + (numProcessors-1) + "]}.txt");
250             ps.prefixDec();
251             ps.println(";;");
252             
253             // check if simulators are running
254             ps.println("\"check\")");
255             ps.prefixInc();
256                 ps.printPrefixln("echo \"Checking which simulators are active...\"");
257                 for (int i=0; i<numProcessors; i++)
258                     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\"");
259             ps.prefixDec();
260             ps.println(";;");
261             
262             // kill all simulators
263             ps.println("\"kill\")");
264             ps.prefixInc();
265                 ps.printPrefixln("echo \"Killing all simulators...\"");
266                 for (int i=0; i<numProcessors; i++)
267                     ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i + "]} \"killall -e scd_${NAME[" + i + "]}\"");
268             ps.prefixDec();
269             ps.println(";;");
270             
271             // get and process profiles
272             ps.println("\"profile\")");
273             ps.prefixInc();
274                 ps.printPrefixln("# require 2 arguments");
275                 ps.printPrefixln("if [ $# -ne 2 ]; then");
276                 ps.prefixInc();
277                     ps.printPrefixln("echo");
278                     ps.printPrefixln("echo \"Error: Illegal number of arguments!\"");
279                     ps.printPrefixln("echo");
280                     ps.printPrefixln("echo \"Usage: ${SCRIPTNAME} profile processnetwork.xml\"");
281                     ps.printPrefixln("echo");
282                     ps.printPrefixln("exit 1");
283                 ps.prefixDec();
284                 ps.printPrefixln("fi");
285                 ps.println();
286                 ps.printPrefixln("# check if process nework file exists");
287                 ps.printPrefixln("if [ ! -f \"$2\" ]; then");
288                 ps.prefixInc();
289                     ps.printPrefixln("echo");
290                     ps.printPrefixln("echo \"Error: File not found!\"");
291                     ps.printPrefixln("echo");
292                     ps.printPrefixln("exit 1");
293                 ps.prefixDec();
294                 ps.printPrefixln("fi");
295                 ps.println();
296                 ps.printPrefixln("# check file extension");
297                 ps.printPrefixln("echo $2 | grep -e '\\.xml$' > /dev/null");
298                 ps.printPrefixln("if [ $? -ne 0 ]; then");
299                 ps.prefixInc();
300                     ps.printPrefixln("echo");
301                     ps.printPrefixln("echo \"Error: Illegal file extension: required .xml!\"");
302                     ps.printPrefixln("echo");
303                     ps.printPrefixln("exit 1");
304                 ps.prefixDec();
305                 ps.printPrefixln("fi");
306                 ps.println();
307                 ps.printPrefixln("PFILE=`echo $2 | sed 's/.*\\///' | sed 's/\\.xml$/_annotated.xml/'`");
308                 ps.printPrefixln("echo \"Profiling into ${PFILE}...\"");
309                 ps.println();
310                 ps.printPrefixln("# check that the DOL is found and the classpath set correctly");
311                 ps.printPrefixln("java dol.main.Main > /dev/null 2>&1");
312                 ps.printPrefixln("if [ $? -eq 1 ]; then");
313                 ps.prefixInc();
314                     ps.printPrefixln("echo");
315                     ps.printPrefixln("echo \"DOL framework not found!\"");
316                     ps.printPrefixln("echo");
317                     ps.printPrefixln("exit 1");
318                 ps.prefixDec();
319                 ps.printPrefixln("fi");
320                 ps.printPrefixln("cp \"$2\" scd_tmp_profiled.xml");
321                 ps.println();
322                 for (int i=0; i<numProcessors; i++)
323                     ps.printPrefixln("profile " + i);
324                 ps.println();
325                 ps.printPrefixln("mv scd_tmp_profiled.xml \"${PFILE}\""); 
326             ps.prefixDec();
327             ps.println(";;");
328             
329             // deleting remote files
330             ps.printPrefixln("\"cleanup\")");
331             ps.prefixInc();
332                 ps.printPrefixln("echo \"Deleting simulator directory on simulators...\"");
333                 for (int i=0; i<numProcessors; i++)
334                     ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
335                             + "]} \"rm -r ${DIR[" + i + "]}\"");
336             ps.prefixDec();
337             ps.println(";;");
338             
339             // tail
340             ps.println("\"help\")");
341             ps.prefixInc();
342                 ps.printPrefixln("usage");
343             ps.prefixDec();
344             ps.println(";;");
345             ps.println("\"-h\")");
346             ps.prefixInc();
347                 ps.printPrefixln("usage");
348             ps.prefixDec();
349             ps.println(";;");
350             ps.println("\"--help\")");
351             ps.prefixInc();
352                 ps.printPrefixln("usage");
353             ps.prefixDec();
354             ps.println(";;");
355             ps.println("*)");
356             ps.prefixInc();
357                 ps.printPrefixln("echo");
358                 ps.printPrefixln("echo \"Error: Illegal command: $1\"");
359                 ps.printPrefixln("usage");
360                 ps.printPrefixln("exit 1");
361             ps.prefixDec();
362             ps.println(";;");
363             ps.println("esac");
364
365         } catch (Exception e) {
366             System.out.println("HdsdMakefileVisitor: exception occured: "
367                     + e.getMessage());
368             e.printStackTrace();
369         }
370
371     } // end visitor
372
373     protected String _dir = null;
374     protected UserInterface _ui = UserInterface.getInstance();
375 }
376