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