1 package Analysis.TaskStateAnalysis;
7 import java.io.FileWriter;
8 import java.io.FileOutputStream;
11 public class SafetyAnalysis {
13 private Hashtable executiongraph;
14 private TreeMap safeexecution;
15 private static final int OR = 0;
16 private static final int AND = 1;
17 private Hashtable reducedgraph;
18 private String classname;
22 /*Structure that stores a possible optional
23 task which would be safe to execute and
24 the possible flagstates the object could
25 be in before executing the task during an
26 execution without failure*/
28 public class MyOptional{
29 public TaskDescriptor td;
30 public HashSet flagstates;
32 protected MyOptional(TaskDescriptor td, HashSet flagstates){
34 this.flagstates = flagstates;
37 public boolean equal(MyOptional myo){
38 if (this.td.getSymbol().compareTo(myo.td.getSymbol())==0)
39 if(this.flagstates.equals(myo.flagstates))
46 public SafetyAnalysis(Hashtable executiongraph, State state){
47 this.executiongraph = executiongraph;
48 this.safeexecution = new TreeMap();
49 this.reducedgraph = new Hashtable();
54 public void unMarkProcessed(Vector nodes){
55 for(Iterator it = nodes.iterator(); it.hasNext();){
56 EGTaskNode tn = (EGTaskNode)it.next();
61 /*returns a hashset of tags used during the analysis */
62 private HashSet createNodeTags(EGTaskNode tn){
63 HashSet nodetags = new HashSet();
64 String flagstate = tn.getFSName();
65 String word = new String();
66 StringTokenizer st = new StringTokenizer(flagstate);
67 while (st.hasMoreTokens()){
68 word = st.nextToken();
69 if (word.compareTo("Tag")==0)
70 nodetags.add(st.nextToken());
72 for(Iterator it = nodetags.iterator(); it.hasNext();){
73 System.out.println("nodetag :"+it.next());
78 /*finds the the source node in the execution graph*/
79 private EGTaskNode findSourceNode(Vector nodes){
80 for(Iterator it = nodes.iterator(); it.hasNext();){
81 EGTaskNode tn = (EGTaskNode)it.next();
83 System.out.println("Found Source Node !!");
90 /*returns the nodes corresponding to the tasks
91 that can fire with the object in flagstate
93 private Vector findEGTaskNode(String previousflagstate, Vector nodes){
94 Vector tns = new Vector();
95 for(Iterator it = nodes.iterator(); it.hasNext();){
96 EGTaskNode tn = (EGTaskNode)it.next();
97 if(tn.getFSName().compareTo(previousflagstate)==0)
102 else if (tns.size() > 1){
103 for(Iterator it = tns.iterator(); it.hasNext();){
104 EGTaskNode tn = (EGTaskNode)it.next();
111 /*returns the executiongraph corresponding to the classname*/
112 private Vector getConcernedClass( String classname ){
113 Enumeration e = executiongraph.keys();
114 while( e.hasMoreElements() ){
115 ClassDescriptor cd = (ClassDescriptor)e.nextElement();
116 if (classname.compareTo(cd.getSymbol())==0)
117 return (Vector)executiongraph.get(cd);
122 /*Method used for debugging*/
123 public void buildPath() throws java.io.IOException {
125 byte[] b = new byte[100] ;
126 HashSet safetasks = new HashSet();
127 System.out.println("Enter the Class of the object concerned :");
128 int k = System.in.read(b);
129 classname = new String(b,0,k-1);
130 System.out.println("Enter the flagstate :");
131 k = System.in.read(b);
132 String previousflagstate = new String(b,0,k-1);
134 //get the graph result of executiongraph class
135 Vector nodes = new Vector();
136 nodes = getConcernedClass( classname );
138 System.out.println("Impossible to find "+classname+". Maybe not declared in the source code.");
143 EGTaskNode sourcenode = findSourceNode(nodes);
144 doGraphMarking(sourcenode);
146 //get the tasknodes possible to execute with the flagstate before failure
147 HashSet tempnodes = new HashSet();
148 Vector tns = new Vector();
149 tns = findEGTaskNode(previousflagstate, nodes);
151 System.out.println("No task corresponding");
155 //compute the result for all the nodes contained in tns.
156 //return the intersection. (because it is not possible to choose)
158 HashSet availabletasks = new HashSet();
159 for(Iterator it = tns.iterator(); it.hasNext();){
161 unMarkProcessed(nodes);
162 EGTaskNode tn = (EGTaskNode)it.next();
163 HashSet nodetags = createNodeTags(tn);
164 availabletasks = createUnion(determineIfIsSafe(tn, nodetags), availabletasks);
166 System.out.println("-----------------------------");
167 for(Iterator it2 = availabletasks.iterator(); it2.hasNext();){
168 MyOptional mm = (MyOptional)it2.next();
169 System.out.println("\t"+mm.td.getSymbol());
170 System.out.println("with flags :");
171 for(Iterator it3 = mm.flagstates.iterator(); it3.hasNext();){
172 System.out.println("\t"+((FlagState)it3.next()).getTextLabel());
174 resultingFS(mm, classname);
175 System.out.println("-----------------------------");
177 if(counter == 1) safetasks = availabletasks;
178 else safetasks = createIntersection(availabletasks, safetasks);
181 System.out.println("----------FINAL--------------");
182 for(Iterator it2 = safetasks.iterator(); it2.hasNext();){
183 MyOptional mm = (MyOptional)it2.next();
184 System.out.println("\t"+mm.td.getSymbol());
185 System.out.println("with flags :");
186 for(Iterator it3 = mm.flagstates.iterator(); it3.hasNext();){
187 System.out.println("\t"+((FlagState)it3.next()).getTextLabel());
189 resultingFS(mm, classname);
190 System.out.println("-----");
192 System.out.println("----------FINAL--------------");
195 /*Actual method used by the compiler.
196 It computes the analysis for every
197 possible flagstates of every classes*/
198 public void buildPath(Vector flagstates, ClassDescriptor cd) throws java.io.IOException {
202 /*Marks the executiongraph :
207 private void doGraphMarking(EGTaskNode extremity) throws java.io.IOException{
208 //detects if there is a loop or no more nodes to explore
209 if (extremity.isMarked() || !((Iterator)extremity.edges()).hasNext()){
210 if (!((Iterator)extremity.edges()).hasNext()) extremity.mark();
211 reducedgraph.put(extremity.getuid(), extremity);
216 reducedgraph.put(extremity.getuid(), extremity);
218 //calls doGraphMarking recursively with the next nodes as params
219 for( Iterator it = extremity.edges(); it.hasNext(); ){
220 TEdge edge = (TEdge)it.next();
221 doGraphMarking((EGTaskNode)edge.getTarget());
226 private void process(EGTaskNode tn){
229 testIfNextIsSelfLoop(tn);
234 private void testIfOptional(EGTaskNode tn){
235 for(Iterator edges = tn.edges(); edges.hasNext();){
236 TEdge edge = (TEdge)edges.next();
237 EGTaskNode nexttn = (EGTaskNode)edge.getTarget();
238 if (nexttn.getTD()!=null)
239 if(nexttn.getTD().isOptional(classname))
240 nexttn.setOptional();
244 private void testIfMultiple(EGTaskNode tn){
245 for(Iterator edges = tn.edges(); edges.hasNext();){
246 TEdge edge = (TEdge)edges.next();
247 EGTaskNode nexttn = (EGTaskNode)edge.getTarget();
248 if( nexttn.getTD().numParameters() > 1 ){
249 nexttn.setMultipleParams();
254 //maybe a little bug to fix
255 private void testIfRuntime(EGTaskNode tn){
256 for(Iterator edges = tn.edges(); edges.hasNext();){
257 TEdge edge = (TEdge)edges.next();
258 EGTaskNode nexttn = (EGTaskNode)edge.getTarget();
259 if( ((String)nexttn.getName()).compareTo("Runtime") == 0 )
264 /*That correspond to the case where it is
265 not possible for us to choose a path of
266 execution. The optional task has to be
267 present in all the possible executions
268 at this point. So we mark the node as an
270 private void testIfSameTask(EGTaskNode tn){
271 Vector vtemp = new Vector();
272 Vector tomark = new Vector();
273 for(Iterator edges = tn.edges(); edges.hasNext();){
274 TEdge edge = (TEdge)edges.next();
275 EGTaskNode nexttn = (EGTaskNode)edge.getTarget();
277 for (Iterator it = vtemp.iterator(); it.hasNext();){
278 EGTaskNode nexttn2 = (EGTaskNode)it.next();
279 if (nexttn.getName()==nexttn2.getName()){
285 if (contains == 0) vtemp.add(nexttn);
288 for(Iterator it2 = tomark.iterator(); it2.hasNext();)
289 ((EGTaskNode)it2.next()).setAND();
292 //maybe little bug to fix
293 private void testIfNextIsSelfLoop(EGTaskNode tn){
294 for(Iterator edges = tn.edges(); edges.hasNext();){
295 TEdge edge = (TEdge)edges.next();
296 EGTaskNode nexttn = (EGTaskNode)edge.getTarget();
297 if(nexttn.isSelfLoop()) nexttn.setAND();
302 /*recursive method that returns a set of MyOptionals
303 The computation basically consist in returning the
304 intersection or union of sets depending on the nature
305 of the node : OR -> UNION
307 The method also looks for tag changes.
309 private HashSet determineIfIsSafe(EGTaskNode tn, HashSet nodetags){
310 if(tn == null) return null;
311 if(!tagChange(tn, nodetags)){
313 HashSet temp = new HashSet();
314 //if the tn is optional and there is no more nodes/presence of a loop
315 //create the MyOptional and return it as a singleton.
316 if( !((Iterator)tn.edges()).hasNext() || tn.isMarked() || tn.isSelfLoop()){
317 HashSet fstemp = new HashSet();
318 fstemp.add(tn.getFS());
319 MyOptional mo = new MyOptional(tn.getTD(), fstemp);
323 //else compute the edges, create the MyOptional and add it to the set.
326 temp = computeEdges(tn, nodetags);
327 HashSet fstemp = new HashSet();
328 fstemp.add(tn.getFS());
329 MyOptional mo = new MyOptional(tn.getTD(), fstemp);
335 //if not optional but terminal just return an empty set.
336 if( !((Iterator)tn.edges()).hasNext() || tn.isMarked() || tn.isSelfLoop()){
337 HashSet temp = new HashSet();
340 //if not terminal return the computation of the edges.
343 return computeEdges(tn, nodetags);
347 //if there has been a tag change return an empty set.
349 HashSet temp = new HashSet();
354 /*check if there has been a tag Change*/
355 private boolean tagChange(EGTaskNode tn, HashSet nodetags){
356 HashSet tags = new HashSet();
357 String flagstate = tn.getFSName();
358 String word = new String();
359 StringTokenizer st = new StringTokenizer(flagstate);
360 while (st.hasMoreTokens()){
361 word = st.nextToken();
362 if (word.compareTo("Tag")==0)
363 tags.add(st.nextToken());
365 //compare the tag needed now to the tag of the initial node
366 for(Iterator it = tags.iterator(); it.hasNext();){
367 String tag = (String)it.next();
368 if( !nodetags.contains(tag)){
369 System.out.println("Tag Change :"+tag);
378 private HashSet computeEdges(EGTaskNode tn, HashSet nodetags){
379 Hashtable andlist = new Hashtable();
380 Vector orlist = new Vector();
381 for(Iterator edges = tn.edges(); edges.hasNext();){
382 EGTaskNode tntemp = (EGTaskNode)((TEdge)edges.next()).getTarget();
383 if(tntemp.type() == OR) orlist.add(tntemp);
384 else if(tntemp.type() == AND){
385 if(andlist.containsKey(tntemp.getName())){
386 ((Vector)andlist.get(tntemp.getName())).add(tntemp);}
388 Vector vector = new Vector();
390 andlist.put(tntemp.getName(), vector);
395 return (createUnion(computeOrVector(orlist, nodetags), computeAndList(andlist, nodetags)));
398 private HashSet computeOrVector( Vector orlist, HashSet nodetags){
399 if(orlist.isEmpty()){
400 HashSet temp = new HashSet();
404 HashSet temp = new HashSet();
405 for(Iterator tns = orlist.iterator(); tns.hasNext();){
406 EGTaskNode tn = (EGTaskNode)tns.next();
407 temp = createUnion(determineIfIsSafe(tn, nodetags), temp);
414 private HashSet computeAndList(Hashtable andlist, HashSet nodetags){
415 if( andlist.isEmpty()){
416 HashSet temp = new HashSet();
420 HashSet temp = new HashSet();
421 Collection c = andlist.values();
422 for(Iterator vectors = c.iterator(); vectors.hasNext();){
423 Vector vector = (Vector)vectors.next();
424 temp = createUnion(computeAndVector(vector, nodetags), temp);
431 private HashSet computeAndVector(Vector vector, HashSet nodetags){
432 HashSet temp = new HashSet();
434 for(Iterator tns = vector.iterator(); tns.hasNext();){
435 EGTaskNode tn = (EGTaskNode)tns.next();
438 temp = determineIfIsSafe(tn, nodetags);
441 temp = createIntersection(determineIfIsSafe(tn, nodetags), temp);
447 private HashSet createUnion( HashSet A, HashSet B){
450 //remove duplicated MyOptionals (might happend)
451 Vector toremove = new Vector();
452 System.out.println("A contains "+A.size()+" elements");
454 for(Iterator itA = A.iterator(); itA.hasNext();){
455 MyOptional myA = (MyOptional)itA.next();
457 System.out.println("myA = "+myA.td.getSymbol());
458 Iterator itA2 = A.iterator();
459 for(int j = 0; j<i; j++){
462 for(Iterator itA3 = itA2; itA3.hasNext();){
463 MyOptional myA2 = (MyOptional)itA3.next();
464 System.out.println("myA2 = "+myA2.td.getSymbol());
467 System.out.println("removed!");
471 for( Iterator it = toremove.iterator(); it.hasNext();)
477 private HashSet createIntersection( HashSet A, HashSet B){
478 HashSet result = new HashSet();
479 for(Iterator itB = B.iterator(); itB.hasNext();){
480 MyOptional myB = (MyOptional)itB.next();
481 for(Iterator itA = A.iterator(); itA.hasNext();){
482 MyOptional myA = (MyOptional)itA.next();
483 if(((String)myA.td.getSymbol()).compareTo((String)myB.td.getSymbol())==0){
484 HashSet newfs = new HashSet();
485 newfs.addAll(myA.flagstates);
486 newfs.addAll(myB.flagstates);
487 MyOptional newmy = new MyOptional(myB.td, newfs);
496 /*Thoose two tasks create the dot file named markedgraph.dot */
498 private void createDOTFile() throws java.io.IOException {
499 Collection v = reducedgraph.values();
500 java.io.PrintWriter output;
501 File dotfile_flagstates= new File("markedgraph.dot");
502 FileOutputStream dotstream=new FileOutputStream(dotfile_flagstates,true);
503 output = new java.io.PrintWriter(dotstream, true);
504 output.println("digraph dotvisitor {");
505 output.println("\tnode [fontsize=10,height=\"0.1\", width=\"0.1\"];");
506 output.println("\tedge [fontsize=6];");
508 output.println("}\n");
511 private void traverse(java.io.PrintWriter output, Collection v) {
514 for(Iterator it1 = v.iterator(); it1.hasNext();){
515 tn = (EGTaskNode)it1.next();
516 output.println("\t"+tn.getLabel()+" [label=\""+tn.getTextLabel()+"\"");
517 if (tn.isOptional()){
518 if (tn.isMultipleParams()) output.println(", shape = tripleoctagon");
519 else output.println(", shape=doubleoctagon");
521 else if (tn.isMultipleParams()) output.println(", shape=octagon");
522 if (tn.type()==AND) output.println(", color=blue");
523 output.println("];");
525 for(Iterator it2 = tn.edges();it2.hasNext();){
526 EGTaskNode tn2 = (EGTaskNode)((Edge)it2.next()).getTarget();
527 output.println("\t"+tn.getLabel()+" -> "+tn2.getLabel()+";");
533 /* returns a set of the possible sets of flagstates
534 resulting from the execution of the optional task.
535 To do it with have to look for TaskExit FlatNodes
538 private HashSet resultingFS(MyOptional mo, ClassDescriptor cd){
539 return resultingFS(mo, cd.getSymbol());
542 private HashSet resultingFS(MyOptional mo, String classname){
543 Stack stack = new Stack();
544 HashSet result = new HashSet();
545 FlatMethod fm = state.getMethodFlat((TaskDescriptor)mo.td);
546 FlatNode fn = (FlatNode)fm;
548 Stack nodestack=new Stack();
549 HashSet discovered=new HashSet();
553 //Iterating through the nodes
554 while(!nodestack.isEmpty()) {
555 FlatNode fn1 = (FlatNode) nodestack.pop();
556 if (fn1.kind()==FKind.FlatFlagActionNode) {
557 FlatFlagActionNode ffan=(FlatFlagActionNode)fn1;
558 if (ffan.getTaskType() == FlatFlagActionNode.TASKEXIT) {
560 System.out.println("TASKEXIT");
562 HashSet tempset = new HashSet();
563 for(Iterator it_fs = mo.flagstates.iterator(); it_fs.hasNext();){
564 FlagState fstemp = (FlagState)it_fs.next();
565 for(Iterator it_tfp=ffan.getTempFlagPairs();it_tfp.hasNext();) {
566 TempFlagPair tfp=(TempFlagPair)it_tfp.next();
567 TempDescriptor td = tfp.getTemp();
568 if (((String)((ClassDescriptor)((TypeDescriptor)td.getType()).getClassDesc()).getSymbol()).compareTo(classname)==0){
569 fstemp=fstemp.setFlag(tfp.getFlag(),ffan.getFlagChange(tfp));
572 System.out.println("new flag : "+fstemp.getTextLabel());
576 continue; // avoid queueing the return node if reachable
578 }else if (fn1.kind()==FKind.FlatReturnNode) {
580 System.out.println("RETURN NODE REACHABLE WITHOUT TASKEXITS");
582 result.add(mo.flagstates);
585 /* Queue other nodes past this one */
586 for(int i=0;i<fn1.numNext();i++) {
587 FlatNode fnext=fn1.getNext(i);
588 if (!discovered.contains(fnext)) {
589 discovered.add(fnext);
590 nodestack.push(fnext);