1 | package de.uka.ipd.sdq.pcmsolver.transformations.pcm2lqn; |
2 | |
3 | import java.math.BigInteger; |
4 | import java.util.List; |
5 | |
6 | import org.antlr.runtime.RecognitionException; |
7 | import org.apache.log4j.Logger; |
8 | import org.eclipse.emf.common.util.EList; |
9 | |
10 | import LqnCore.ActivityDefType; |
11 | import LqnCore.ActivityMakingCallType; |
12 | import LqnCore.ActivityPhasesType; |
13 | import LqnCore.EntryType; |
14 | import LqnCore.PhaseActivities; |
15 | import LqnCore.PrecedenceType; |
16 | import LqnCore.ProcessorType; |
17 | import LqnCore.SchedulingType; |
18 | import LqnCore.TaskSchedulingType; |
19 | import LqnCore.TaskType; |
20 | import LqnCore.TypeType; |
21 | import de.uka.ipd.sdq.pcm.core.PCMRandomVariable; |
22 | import de.uka.ipd.sdq.pcm.repository.BasicComponent; |
23 | import de.uka.ipd.sdq.pcm.repository.RepositoryComponent; |
24 | import de.uka.ipd.sdq.pcm.seff.ResourceDemandingSEFF; |
25 | import de.uka.ipd.sdq.pcm.seff.ServiceEffectSpecification; |
26 | import de.uka.ipd.sdq.pcm.usagemodel.Branch; |
27 | import de.uka.ipd.sdq.pcm.usagemodel.BranchTransition; |
28 | import de.uka.ipd.sdq.pcm.usagemodel.ClosedWorkload; |
29 | import de.uka.ipd.sdq.pcm.usagemodel.Delay; |
30 | import de.uka.ipd.sdq.pcm.usagemodel.EntryLevelSystemCall; |
31 | import de.uka.ipd.sdq.pcm.usagemodel.Loop; |
32 | import de.uka.ipd.sdq.pcm.usagemodel.OpenWorkload; |
33 | import de.uka.ipd.sdq.pcm.usagemodel.ScenarioBehaviour; |
34 | import de.uka.ipd.sdq.pcm.usagemodel.Start; |
35 | import de.uka.ipd.sdq.pcm.usagemodel.Stop; |
36 | import de.uka.ipd.sdq.pcm.usagemodel.UsageModel; |
37 | import de.uka.ipd.sdq.pcm.usagemodel.UsageScenario; |
38 | import de.uka.ipd.sdq.pcm.usagemodel.util.UsagemodelSwitch; |
39 | import de.uka.ipd.sdq.pcmsolver.transformations.ContextWrapper; |
40 | import de.uka.ipd.sdq.pcmsolver.visitors.EMFQueryHelper; |
41 | import de.uka.ipd.sdq.pcmsolver.visitors.ExpressionHelper; |
42 | import de.uka.ipd.sdq.probfunction.ExponentialDistribution; |
43 | import de.uka.ipd.sdq.probfunction.ProbabilityFunction; |
44 | import de.uka.ipd.sdq.probfunction.math.ManagedPMF; |
45 | import de.uka.ipd.sdq.probfunction.math.exception.DomainNotNumbersException; |
46 | import de.uka.ipd.sdq.probfunction.math.exception.FunctionNotInTimeDomainException; |
47 | import de.uka.ipd.sdq.probfunction.math.exception.StringNotPDFException; |
48 | import de.uka.ipd.sdq.stoex.DoubleLiteral; |
49 | import de.uka.ipd.sdq.stoex.Expression; |
50 | import de.uka.ipd.sdq.stoex.FunctionLiteral; |
51 | import de.uka.ipd.sdq.stoex.IntLiteral; |
52 | import de.uka.ipd.sdq.stoex.ProbabilityFunctionLiteral; |
53 | import de.uka.ipd.sdq.stoex.analyser.visitors.ExpressionInferTypeVisitor; |
54 | import de.uka.ipd.sdq.stoex.analyser.visitors.ExpressionSolveVisitor; |
55 | |
56 | public class UsageModel2Lqn extends UsagemodelSwitch<String> { |
57 | |
58 | private static final String USAGE_DELAY = "USAGE_DELAY"; |
59 | |
60 | private static Logger logger = Logger.getLogger(UsageModel2Lqn.class |
61 | .getName()); |
62 | |
63 | private int counter; |
64 | |
65 | private ContextWrapper myContextWrapper; |
66 | private LqnBuilder lqnBuilder; |
67 | |
68 | public UsageModel2Lqn(LqnBuilder aLqnBuilder, ContextWrapper ctxWrp) { |
69 | lqnBuilder = aLqnBuilder; |
70 | myContextWrapper = ctxWrp; |
71 | counter = 0; |
72 | } |
73 | |
74 | @Override |
75 | public String caseUsageModel(UsageModel usageModel) { |
76 | |
77 | ProcessorType pt = lqnBuilder.addProcessor(USAGE_DELAY); |
78 | pt.setScheduling(SchedulingType.INF); |
79 | TaskType tt = lqnBuilder.addTask(USAGE_DELAY,pt); |
80 | |
81 | EntryType et = lqnBuilder.addEntry(USAGE_DELAY+counter,tt); |
82 | et.setType(TypeType.PH1PH2); |
83 | ActivityPhasesType apt = lqnBuilder.addActivityPhases(USAGE_DELAY+counter); |
84 | apt.setHostDemandMean("0.0"); |
85 | PhaseActivities pa = lqnBuilder.addPhaseActivities(apt); |
86 | et.setEntryPhaseActivities(pa); |
87 | counter++; |
88 | |
89 | EList<UsageScenario> scenList = usageModel |
90 | .getUsageScenario_UsageModel(); |
91 | for (UsageScenario us : scenList) { |
92 | doSwitch(us); |
93 | } |
94 | return null; |
95 | } |
96 | |
97 | @Override |
98 | public String caseUsageScenario(UsageScenario object) { |
99 | doSwitch(object.getWorkload_UsageScenario()); |
100 | doSwitch(object.getScenarioBehaviour_UsageScenario()); |
101 | |
102 | // Generating a reply leads to an error, therefore commented out: |
103 | // ReplyActivityType rat = lqnFactory.createReplyActivityType(); |
104 | // rat.setName((String)doSwitch(object.getScenarioBehaviour_UsageScenario())); |
105 | // |
106 | // ReplyEntryType ret = lqnFactory.createReplyEntryType(); |
107 | // ret.setName(object.getEntityName()+"_Entry"); // TODO |
108 | // ret.getReplyActivity().add(rat); |
109 | // |
110 | // taskActivityGraph.getReplyEntry().add(ret); |
111 | |
112 | return null; |
113 | } |
114 | |
115 | @Override |
116 | public String caseClosedWorkload(ClosedWorkload closedWorkload) { |
117 | UsageScenario us = (UsageScenario) closedWorkload.eContainer(); |
118 | String id = Pcm2LqnHelper.getIdForUsageScenario(us); |
119 | |
120 | ProcessorType pt = lqnBuilder.addProcessor(id); |
121 | |
122 | TaskType tt = lqnBuilder.addTask(id,pt); |
123 | String population = new Integer(closedWorkload.getPopulation()) |
124 | .toString(); |
125 | PCMRandomVariable thinkTime = closedWorkload |
126 | .getThinkTime_ClosedWorkload(); |
127 | if (thinkTime == null){ |
128 | throw new RuntimeException("No think tiome defined for closed workload. Fix your model and validate it before running the analyses."); |
129 | } |
130 | tt.setMultiplicity(new BigInteger(population)); |
131 | tt.setThinkTime(thinkTime.getSpecification()); |
132 | tt.setScheduling(TaskSchedulingType.REF); |
133 | |
134 | EntryType et = lqnBuilder.addEntry(id,tt); |
135 | lqnBuilder.addOutputEntryDistributionType(et); |
136 | lqnBuilder.addTaskActivityGraph(tt); |
137 | |
138 | return null; |
139 | } |
140 | |
141 | @Override |
142 | public String caseOpenWorkload(OpenWorkload openWorkload) { |
143 | UsageScenario us = (UsageScenario) openWorkload.eContainer(); |
144 | String id = Pcm2LqnHelper.getIdForUsageScenario(us); |
145 | |
146 | ProcessorType pt = lqnBuilder.addProcessor(id); |
147 | TaskType tt = lqnBuilder.addTask(id,pt); |
148 | |
149 | EntryType et = lqnBuilder.addEntry(id,tt); |
150 | |
151 | //Arrival rate is Kehrwert of the inter arrival time |
152 | double interarrivaltime = 0; |
153 | ExpressionInferTypeVisitor visitor = new ExpressionInferTypeVisitor(); |
154 | String specification = openWorkload.getInterArrivalTime_OpenWorkload().getSpecification(); |
155 | |
156 | Expression exp = ExpressionHelper.parseToExpression(specification); |
157 | //TOOD: Only handles IntLiterals and DoubleLiterals |
158 | if (IntLiteral.class.isInstance(exp)){ |
159 | IntLiteral intExp = (IntLiteral) exp; |
160 | interarrivaltime = intExp.getValue(); |
161 | } else if (DoubleLiteral.class.isInstance(exp)) { |
162 | DoubleLiteral doubleExp = (DoubleLiteral) exp; |
163 | interarrivaltime = doubleExp.getValue(); |
164 | } else if(FunctionLiteral.class.isInstance(exp)) { |
165 | ExpressionSolveVisitor expressionSolveVisitor = new ExpressionSolveVisitor(ExpressionHelper.getTypeAnnotation(exp)); |
166 | Expression result = (Expression) expressionSolveVisitor.doSwitch(exp); |
167 | if (ProbabilityFunctionLiteral.class.isInstance(result)){ |
168 | ProbabilityFunctionLiteral propFunctionLiteral = (ProbabilityFunctionLiteral)result; |
169 | ProbabilityFunction probFunc = propFunctionLiteral.getFunction_ProbabilityFunctionLiteral(); |
170 | if (probFunc instanceof ExponentialDistribution){ |
171 | ExponentialDistribution expDistr = (ExponentialDistribution)probFunc; |
172 | interarrivaltime = 1/expDistr.getRate(); |
173 | } |
174 | } else { |
175 | throw new RuntimeException("Only double values, integer values or exponential functions are supported as interarrival time. You provided something else: "+specification); |
176 | } |
177 | } else { |
178 | throw new RuntimeException("Only double values, integer values or exponential functions are supported as interarrival time. You provided something else: "+specification); |
179 | } |
180 | |
181 | String arrivalRate = (1.0 / interarrivaltime)+""; |
182 | et.setOpenArrivalRate(arrivalRate); |
183 | |
184 | lqnBuilder.addTaskActivityGraph(tt); |
185 | |
186 | return null; |
187 | } |
188 | |
189 | @Override |
190 | public String caseScenarioBehaviour(ScenarioBehaviour object) { |
191 | return doSwitch(getStartAction(object)); |
192 | } |
193 | |
194 | @Override |
195 | public String caseStart(Start object) { |
196 | String id = Pcm2LqnHelper.getId(object, myContextWrapper); |
197 | String entryId = ""; |
198 | |
199 | if (object.eContainer().eContainer() instanceof UsageScenario) { |
200 | UsageScenario us = (UsageScenario) object.eContainer().eContainer(); |
201 | ActivityDefType adt = lqnBuilder.addActivityDef(id); |
202 | entryId = Pcm2LqnHelper.getIdForUsageScenario(us)+"_Entry"; |
203 | adt.setBoundToEntry(entryId); |
204 | } else if (object.eContainer().eContainer() instanceof Loop){ |
205 | Loop loop = (Loop)object.eContainer().eContainer(); |
206 | ActivityDefType adt = lqnBuilder.addActivityDef(id); |
207 | entryId = Pcm2LqnHelper.getId(loop, myContextWrapper)+"_Entry"; |
208 | adt.setBoundToEntry(entryId); |
209 | } else { //nested scenario behaviour |
210 | lqnBuilder.addActivityDef(id); |
211 | } |
212 | |
213 | String successorId = (String) doSwitch(object.getSuccessor()); |
214 | lqnBuilder.addSequencePrecedence(id, successorId); |
215 | |
216 | if (entryId.equals("")) return id; |
217 | else return entryId; |
218 | } |
219 | |
220 | @Override |
221 | public String caseStop(Stop object) { |
222 | String id = Pcm2LqnHelper.getId(object, myContextWrapper); |
223 | lqnBuilder.addActivityDef(id); |
224 | return id; |
225 | } |
226 | |
227 | @Override |
228 | public String caseEntryLevelSystemCall(EntryLevelSystemCall object) { |
229 | |
230 | String id = Pcm2LqnHelper.getIdForEntryLevelSystemCall(object); |
231 | |
232 | List<ContextWrapper> contextWrapperList= myContextWrapper.getContextWrapperFor(object); |
233 | |
234 | double branchProb = 1.0/contextWrapperList.size(); |
235 | |
236 | for (ContextWrapper contextWrapperForComponentInstance : contextWrapperList) { |
237 | |
238 | myContextWrapper = contextWrapperForComponentInstance; |
239 | createCallActivity(object, id, contextWrapperForComponentInstance, branchProb); |
240 | |
241 | } |
242 | |
243 | |
244 | String successorId = (String) doSwitch(object.getSuccessor()); |
245 | lqnBuilder.addSequencePrecedence(id, successorId); |
246 | |
247 | return id; |
248 | } |
249 | |
250 | private void createCallActivity(EntryLevelSystemCall object, String id, |
251 | ContextWrapper contextWrapperForComponentInstance, double callMeans) { |
252 | RepositoryComponent offeringComponent = contextWrapperForComponentInstance.getAssCtx() |
253 | .getEncapsulatedComponent__AssemblyContext(); |
254 | |
255 | String entryId = ""; |
256 | if (offeringComponent instanceof BasicComponent) { |
257 | ServiceEffectSpecification seff = contextWrapperForComponentInstance |
258 | .getNextSEFF(object); |
259 | Rdseff2Lqn seffVisitor = new Rdseff2Lqn(lqnBuilder, contextWrapperForComponentInstance); |
260 | try { |
261 | entryId = (String) seffVisitor |
262 | .doSwitch((ResourceDemandingSEFF) seff); |
263 | } catch (RuntimeException e) { |
264 | logger.error("Error while visiting RDSEFF"); |
265 | throw e; |
266 | } |
267 | } else { |
268 | logger.error("Composite Component type not yet supported."); |
269 | throw new UnsupportedOperationException(); |
270 | } |
271 | |
272 | lqnBuilder.addActivityDef(id); |
273 | lqnBuilder.addActivityMakingCall(id, entryId, CallType.SYNCH, callMeans); |
274 | |
275 | } |
276 | |
277 | @Override |
278 | public String caseDelay(Delay object) { |
279 | // String id = Pcm2LqnHelper.getId(object, myContextWrapper); |
280 | // |
281 | // ActivityDefType adt = lqnBuilder.addActivityDef(id); |
282 | // adt.setThinkTime(object.getTimeSpecification_Delay() |
283 | // .getSpecification()); |
284 | // |
285 | // String successorId = (String) doSwitch(object.getSuccessor()); |
286 | // lqnBuilder.addSequencePrecedence(id, successorId); |
287 | // |
288 | // return id; |
289 | |
290 | String id = Pcm2LqnHelper.getId(object, myContextWrapper); |
291 | |
292 | ProcessorType delayProcessor = lqnBuilder.getProcessor(USAGE_DELAY); |
293 | TaskType delayTask = delayProcessor.getTask().get(0); |
294 | |
295 | EntryType et = lqnBuilder.addEntry(USAGE_DELAY+counter,delayTask); |
296 | et.setType(TypeType.PH1PH2); |
297 | |
298 | // the entry makes a call to the processor |
299 | ActivityPhasesType apt = lqnBuilder.addActivityPhases(USAGE_DELAY+counter); |
300 | counter++; |
301 | |
302 | String hostDemand = object.getTimeSpecification_Delay().getSpecification(); |
303 | apt.setHostDemandMean(hostDemand); |
304 | |
305 | PhaseActivities pa = lqnBuilder.addPhaseActivities(apt); |
306 | et.setEntryPhaseActivities(pa); |
307 | |
308 | lqnBuilder.addActivityDef(id); |
309 | lqnBuilder.addActivityMakingCall(id, et.getName(), CallType.SYNCH); |
310 | |
311 | String successorId = (String) doSwitch(object.getSuccessor()); |
312 | lqnBuilder.addSequencePrecedence(id, successorId); |
313 | |
314 | return id; |
315 | } |
316 | |
317 | @Override |
318 | public String caseBranch(Branch object) { |
319 | String id = Pcm2LqnHelper.getId(object, myContextWrapper); |
320 | |
321 | lqnBuilder.addActivityDef(id); |
322 | PrecedenceType ptBegin = lqnBuilder.addBeginBranchPrecedence(id); |
323 | PrecedenceType ptEnd = lqnBuilder.addEndBranchPrecedence(); |
324 | |
325 | EList<BranchTransition> btList = object.getBranchTransitions_Branch(); |
326 | for (BranchTransition bt : btList) { |
327 | ScenarioBehaviour sb = bt.getBranchedBehaviour_BranchTransition(); |
328 | |
329 | String startId = (String) doSwitch(sb); |
330 | String branchProb = new Double(bt.getBranchProbability()) |
331 | .toString(); |
332 | lqnBuilder.addActivityOrType(startId,branchProb,ptBegin); |
333 | |
334 | String stopId = Pcm2LqnHelper.getId(getStopAction(sb), myContextWrapper); |
335 | lqnBuilder.addActivityType(stopId, ptEnd); |
336 | } |
337 | |
338 | String successorId = (String) doSwitch(object.getSuccessor()); |
339 | ptEnd.getPost().getActivity().setName(successorId); |
340 | |
341 | return id; |
342 | } |
343 | |
344 | @Override |
345 | public String caseLoop(Loop object) { |
346 | String id = Pcm2LqnHelper.getId(object, myContextWrapper); |
347 | |
348 | String startId = handleLoopBody(object,id); // creates a new task/processor |
349 | |
350 | lqnBuilder.addActivityDef(id); // for the loop action |
351 | // makes an external call to the task representing the loop body: |
352 | ActivityMakingCallType amct = lqnBuilder.addActivityMakingCall(id, |
353 | startId, CallType.SYNCH); |
354 | amct.setCallsMean(getLoopIterations(object)); |
355 | |
356 | String successorId = (String) doSwitch(object.getSuccessor()); |
357 | lqnBuilder.addSequencePrecedence(id, successorId); |
358 | |
359 | return id; |
360 | } |
361 | |
362 | private String handleLoopBody(Loop loop, String id) { |
363 | ProcessorType pt = lqnBuilder.addProcessor(id); |
364 | TaskType tt = lqnBuilder.addTask(id,pt); |
365 | //tt.setScheduling(TaskSchedulingType.INF); |
366 | |
367 | EntryType et = lqnBuilder.addEntry(id,tt); |
368 | lqnBuilder.addTaskActivityGraph(tt); |
369 | |
370 | ScenarioBehaviour sb = loop.getBodyBehaviour_Loop(); |
371 | String startId = (String) doSwitch(getStartAction(sb)); |
372 | String stopId = Pcm2LqnHelper.getId(getStopAction(sb), myContextWrapper); |
373 | lqnBuilder.addReplyActivity(id, startId, stopId); |
374 | |
375 | lqnBuilder.restoreFormerTaskActivityGraph(); |
376 | |
377 | return startId; |
378 | } |
379 | |
380 | private String getLoopIterations(Loop object) { |
381 | ManagedPMF pmf = null; |
382 | try { |
383 | pmf = ManagedPMF.createFromString(object.getLoopIteration_Loop() |
384 | .getSpecification()); |
385 | } catch (StringNotPDFException e) { |
386 | e.printStackTrace(); |
387 | } catch (RecognitionException e) { |
388 | e.printStackTrace(); |
389 | } |
390 | if (pmf != null) { |
391 | try { |
392 | return pmf.getPmfTimeDomain().getArithmeticMeanValue() + ""; |
393 | } catch (DomainNotNumbersException e) { |
394 | return "0.0"; |
395 | } catch (FunctionNotInTimeDomainException e) { |
396 | return "0.0"; |
397 | } |
398 | } else { |
399 | return "0.0"; |
400 | } |
401 | } |
402 | |
403 | private Stop getStopAction(ScenarioBehaviour object) { |
404 | Stop stopAction = (Stop) EMFQueryHelper.getObjectByType(object |
405 | .getActions_ScenarioBehaviour(), Stop.class); |
406 | return stopAction; |
407 | } |
408 | |
409 | private Start getStartAction(ScenarioBehaviour object) { |
410 | Start startAction = (Start) EMFQueryHelper.getObjectByType(object |
411 | .getActions_ScenarioBehaviour(), Start.class); |
412 | return startAction; |
413 | } |
414 | |
415 | } |