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