make multicore version PERT benchmark work on RAW(without interruption)
[IRC.git] / Robust / src / Analysis / Scheduling / ScheduleNode.java
1 package Analysis.Scheduling;
2
3 import java.util.*;
4
5 import Analysis.TaskStateAnalysis.FEdge;
6 import Analysis.TaskStateAnalysis.FlagState;
7 import Util.GraphNode;
8
9 /** This class holds flag transition diagram(s) can be put on one core.
10  */
11 public class ScheduleNode extends GraphNode implements Cloneable{
12     
13     private int uid;
14     private int gid;
15     private static int nodeID=0;
16
17     private Vector<ClassNode> classNodes;
18     Vector<ScheduleEdge> scheduleEdges;
19     
20     private int executionTime;
21
22     /** Class constructor
23      *  @param cd ClassDescriptor
24      *  @param fStates
25      */
26     public ScheduleNode(int gid) {
27         this.uid = ScheduleNode.nodeID++;
28         this.gid = gid;
29         this.executionTime = -1;
30         this.classNodes = null;
31         this.scheduleEdges = null;
32     }
33     
34     public ScheduleNode(ClassNode cn, int gid) {
35         this.uid = ScheduleNode.nodeID++;
36         this.gid = gid;
37         this.classNodes = new Vector<ClassNode>();
38         this.scheduleEdges = new Vector<ScheduleEdge>();
39         this.classNodes.add(cn);
40         this.addEdge(cn.getEdgeVector());
41         this.executionTime = -1;
42     }
43    
44     public int getuid() {
45         return uid;
46     }
47     
48     public String toString() {
49         String temp = new String("");
50         for(int i = 0; i < classNodes.size(); i++) {
51             temp += classNodes.elementAt(i).getClassDescriptor().toString() + ", ";
52         }
53         temp += getTextLabel();
54         return temp;
55     }
56     
57     public Vector getClassNodes() {
58         return classNodes;
59     }
60     
61     public Iterator getClassNodesIterator() {
62         if(classNodes == null) {
63             return null;
64         }
65         return classNodes.iterator();
66     }
67     
68     public void resetClassNodes() {
69         classNodes = null;
70     }
71     
72     public Vector getScheduleEdges() {
73         return scheduleEdges;
74     }
75     
76     public Iterator getScheduleEdgesIterator() {
77         if(scheduleEdges == null) {
78             return null;
79         }
80         return scheduleEdges.iterator();
81     }
82     
83     public void resetScheduleEdges() {
84         scheduleEdges = null;
85     }
86     
87     public int getExeTime() {
88         if(this.executionTime == -1) {
89             try {
90                 calExeTime();
91             } catch (Exception e) {
92                 e.printStackTrace();
93             }
94         }
95         return this.executionTime;
96     }
97     
98     public void calExeTime() throws Exception {
99         if(this.classNodes.size() != 1) {
100             throw new Exception("Error: there are multiple ClassNodes inside the ScheduleNode when calculating executionTime");
101         }
102         ClassNode cn = this.classNodes.elementAt(0);
103         if(!cn.isSorted()) {
104             throw new Error("Error: Non-sorted ClassNode!");
105         }
106         this.executionTime = cn.getFlagStates().elementAt(0).getExeTime();
107     }
108     
109     /** Tests for equality of two flagstate objects.
110     */
111     
112     public boolean equals(Object o) {
113         if (o instanceof ScheduleNode) {
114             ScheduleNode fs=(ScheduleNode)o;
115             if(fs.gid == this.gid) {
116                 if(fs.uid != this.uid) {
117                     return false;
118                 }
119             }
120             if ((fs.executionTime != this.executionTime)){ 
121                 return false;
122             }
123             if(fs.classNodes != null) {
124                 if(!fs.classNodes.equals(classNodes)) {
125                     return false;
126                 }
127             } else if(classNodes != null) {
128                 return false;
129             }
130             return true;
131         }
132         return false;
133     }
134
135     public int hashCode() {
136         int hashcode = gid^uid^executionTime;
137         if(this.classNodes != null) {
138             hashcode ^= classNodes.hashCode();
139         }
140         return hashcode;
141     }
142
143     public String getLabel() {
144         return "cluster" + uid;
145     }   
146
147     public String getTextLabel() {
148         String label=null;
149         
150         if (label==null)
151             return " ";
152         return label;
153     }
154     
155     public Object clone(Hashtable<ClassNode, ClassNode> cn2cn, int gid) {
156         ScheduleNode o = null;
157         try {
158             o = (ScheduleNode)super.clone();
159         } catch(CloneNotSupportedException e){
160             e.printStackTrace();
161         }
162         o.uid = ScheduleNode.nodeID++;
163         o.gid = gid;
164         // Clone all the internal ClassNodes and ScheduleEdges
165         Vector<ClassNode> tcns = new Vector<ClassNode>();
166         Vector<ScheduleEdge> tses = new Vector<ScheduleEdge>();
167         int i = 0;
168         for(i = 0; i < this.classNodes.size(); i++) {
169             ClassNode tcn = this.classNodes.elementAt(i);
170             ClassNode cn = (ClassNode)tcn.clone();
171             cn.setScheduleNode(o);
172             tcns.add(cn);
173             cn2cn.put(tcn, cn);
174         }
175         for(i = 0; i < this.scheduleEdges.size(); i++) {
176             ScheduleEdge temp = this.scheduleEdges.elementAt(i);
177             ScheduleEdge se = null;
178             switch(temp.getType()) {
179             case ScheduleEdge.NEWEDGE: {
180                 se = new ScheduleEdge(o, "new", temp.getFstate(), ScheduleEdge.NEWEDGE, gid);
181                 se.setProbability(temp.getProbability());
182                 se.setNewRate(temp.getNewRate());
183                 break;
184             }
185             case ScheduleEdge.TRANSEDGE: {
186                 se = new ScheduleEdge(o, "transmit", temp.getFstate(), ScheduleEdge.TRANSEDGE, gid);
187                 se.setProbability(temp.getProbability());
188                 se.setNewRate(temp.getNewRate());
189                 break;
190             }
191             }
192             se.setSourceCNode(cn2cn.get(temp.getSourceCNode()));
193             se.setTargetCNode(cn2cn.get(temp.getTargetCNode()));
194             se.setTransTime(temp.getTransTime());
195             se.setFEdge(temp.getFEdge());
196             se.setTargetFState(temp.getTargetFState());
197             se.setIsclone(true);
198             tses.add(se);
199         }
200         o.classNodes = tcns;
201         o.scheduleEdges = tses;
202         tcns = null;
203         tses = null;
204         
205         o.inedges = new Vector();
206         o.edges = new Vector();
207         return o;
208     }
209     
210     public void mergeSEdge(ScheduleEdge se) throws Exception {  
211         ScheduleNode sn = (ScheduleNode)se.getTarget();
212         Vector<ClassNode> targetCNodes = (Vector<ClassNode>)sn.getClassNodes();
213         Vector<ScheduleEdge> targetSEdges = (Vector<ScheduleEdge>)sn.getScheduleEdges();
214         
215         for(int i = 0; i <  targetCNodes.size(); i++) {
216             targetCNodes.elementAt(i).setScheduleNode(this);
217         }
218         
219         if(classNodes == null) {
220             classNodes = targetCNodes;
221             scheduleEdges = targetSEdges;
222         } else {
223             if(targetCNodes.size() != 0) {
224                 classNodes.addAll(targetCNodes);
225             }
226             if(targetSEdges.size() != 0) {
227                 scheduleEdges.addAll(targetSEdges);
228             }
229         }
230         targetCNodes = null;
231         
232         if(ScheduleEdge.TRANSEDGE == se.getType()) {
233             sn.removeInedge(se);
234             this.removeEdge(se);
235
236             // merge the split ClassNode of same class
237             FlagState sfs = se.getFstate();
238             FlagState tfs = se.getTargetFState();
239             ClassNode scn = se.getSourceCNode();
240             ClassNode tcn = se.getTargetCNode();
241             sfs.getEdgeVector().addAll(tfs.getEdgeVector());
242             // merge the subtree whose root is nfs from the whole flag transition tree
243             Vector<FlagState> sfss = scn.getFlagStates();
244             sfss.addAll(tcn.getFlagStates());
245             sfss.removeElement(tfs);
246             classNodes.removeElement(tcn);
247
248             // flush the exeTime of fs and its ancestors
249             sfs.setExeTime(0);
250             Queue<FlagState> toiterate = new LinkedList<FlagState>();
251             toiterate.add(sfs);
252             while(!toiterate.isEmpty()) {
253                 FlagState tmpfs = toiterate.poll();
254                 int ttime = tmpfs.getExeTime();
255                 Iterator it_inedges = tmpfs.inedges();
256                 while(it_inedges.hasNext()) {
257                     FEdge fEdge = (FEdge)it_inedges.next();
258                     FlagState temp = (FlagState)fEdge.getSource();
259                     int time = fEdge.getExeTime() + ttime;
260                     if(temp.getExeTime() > time) {
261                         temp.setExeTime(time);
262                         toiterate.add(temp);
263                     }
264                 }
265             }
266             toiterate = null;
267
268             // redirct internal ScheduleEdge from tcn to scn
269             for(int i = 0; i < targetSEdges.size(); ++i) {
270                 ScheduleEdge tmpse = targetSEdges.elementAt(i);
271                 if(tmpse.getSourceCNode().equals(tcn)) {
272                     tmpse.setSourceCNode(scn);
273                 }
274             }
275             
276             // redirect external ScheduleEdges to this ScheduleNode
277             // and scn if it is originally from tcn
278             Iterator it_edges = sn.edges();
279             while(it_edges.hasNext()) {
280                 ScheduleEdge tse = (ScheduleEdge)it_edges.next();
281                 tse.setSource(this);
282                 if(tse.getSourceCNode().equals(tcn)) {
283                 tse.setSourceCNode(scn);
284                 }
285                 this.edges.addElement(tse);
286             }
287             
288             targetSEdges = null;
289             
290             // As all tasks inside one ScheduleNode are executed sequentially,
291             // simply add the execution time of all the ClassNodes inside one ScheduleNode. 
292             if(this.executionTime == -1) {
293                 throw new Exception("Error: ScheduleNode without initiate execution time when analysising.");
294             }
295             if(this.executionTime < sn.getExeTime()) {
296                 this.executionTime = sn.getExeTime();
297             }
298         } else if(ScheduleEdge.NEWEDGE == se.getType()) {
299             targetSEdges = null;
300         
301             scheduleEdges.add(se);
302             se.resetListExeTime();
303             sn.removeInedge(se);
304             this.removeEdge(se);
305             Iterator it_edges = sn.edges();
306             while(it_edges.hasNext()) {
307                 ScheduleEdge tse = (ScheduleEdge)it_edges.next();
308                 tse.setSource(this);
309                 this.edges.addElement(tse);
310             }
311             
312             // As all tasks inside one ScheduleNode are executed sequentially,
313             // simply add the execution time of all the ClassNodes inside one ScheduleNode. 
314             if(this.executionTime == -1) {
315                 this.executionTime = 0;
316             }
317             this.executionTime += ((ScheduleNode)se.getTarget()).getExeTime();
318         }
319     }
320 }