| 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 | } |