| 1 | /** |
| 2 | * |
| 3 | */ |
| 4 | package de.uka.ipd.sdq.pcmsolver.handler; |
| 5 | |
| 6 | import java.util.Iterator; |
| 7 | |
| 8 | import org.apache.log4j.Logger; |
| 9 | import org.eclipse.emf.common.util.EList; |
| 10 | |
| 11 | import de.uka.ipd.sdq.context.computed_allocation.ComputedAllocationFactory; |
| 12 | import de.uka.ipd.sdq.context.computed_allocation.ResourceDemand; |
| 13 | import de.uka.ipd.sdq.pcm.allocation.AllocationContext; |
| 14 | import de.uka.ipd.sdq.pcm.core.CoreFactory; |
| 15 | import de.uka.ipd.sdq.pcm.core.PCMRandomVariable; |
| 16 | import de.uka.ipd.sdq.pcm.resourceenvironment.ProcessingResourceSpecification; |
| 17 | import de.uka.ipd.sdq.pcm.resourceenvironment.ResourceContainer; |
| 18 | import de.uka.ipd.sdq.pcm.resourcetype.ProcessingResourceType; |
| 19 | import de.uka.ipd.sdq.pcm.seff.InternalAction; |
| 20 | import de.uka.ipd.sdq.pcm.seff.seff_performance.ParametricResourceDemand; |
| 21 | import de.uka.ipd.sdq.pcmsolver.visitors.ExpressionHelper; |
| 22 | import de.uka.ipd.sdq.pcmsolver.visitors.SeffVisitor; |
| 23 | import de.uka.ipd.sdq.stoex.Expression; |
| 24 | |
| 25 | /** |
| 26 | * @author Koziolek |
| 27 | * |
| 28 | */ |
| 29 | public class InternalActionHandler{ |
| 30 | |
| 31 | private static Logger logger = Logger.getLogger(InternalActionHandler.class.getName()); |
| 32 | |
| 33 | private ComputedAllocationFactory compAllocationFactory = ComputedAllocationFactory.eINSTANCE; |
| 34 | |
| 35 | private SeffVisitor visitor; |
| 36 | |
| 37 | public InternalActionHandler(SeffVisitor seffVisitor) { |
| 38 | visitor=seffVisitor; |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * @param action |
| 43 | */ |
| 44 | public void handle(InternalAction action) { |
| 45 | //EList<ParametricResourceDemand> resourceDem = action.getResourceDemand_Action() |
| 46 | |
| 47 | Iterator resourceDemands = action.getResourceDemand_Action().iterator(); |
| 48 | while (resourceDemands.hasNext()) { |
| 49 | ParametricResourceDemand prd = (ParametricResourceDemand) resourceDemands.next(); |
| 50 | ProcessingResourceType requiredResourceType = prd.getRequiredResource_ParametricResourceDemand(); |
| 51 | |
| 52 | if (requiredResourceType.getEntityName().equals("SystemExternalResource")){ |
| 53 | EList<ResourceContainer> resConList = visitor.getContextWrapper().getPcmInstance().getResourceEnvironment().getResourceContainer_ResourceEnvironment(); |
| 54 | for (ResourceContainer resCon : resConList){ |
| 55 | if(resCon.getEntityName().equals("SystemExternalResourceContainer")){ |
| 56 | ProcessingResourceSpecification prs = resCon.getActiveResourceSpecifications_ResourceContainer().get(0); |
| 57 | createActualResourceDemand(action, prd, prs); |
| 58 | } |
| 59 | } |
| 60 | } else { |
| 61 | EList<ProcessingResourceSpecification> resourceList = getResourceList(); |
| 62 | for (ProcessingResourceSpecification prs : resourceList) { |
| 63 | ProcessingResourceType currentResourceType = prs |
| 64 | .getActiveResourceType_ActiveResourceSpecification(); |
| 65 | if (currentResourceType.getEntityName().equals( |
| 66 | requiredResourceType.getEntityName())) { |
| 67 | createActualResourceDemand(action, prd, prs); |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * Create a ResourceDemand in the computed allocation context |
| 76 | * for the given ParametricResourceDemand and ProcessingResourceSpecification |
| 77 | * The resulting ResourceDemand already takes into account the processing rate. |
| 78 | * @param prd |
| 79 | * @param prs |
| 80 | */ |
| 81 | private void createActualResourceDemand(InternalAction action, ParametricResourceDemand prd, ProcessingResourceSpecification prs) { |
| 82 | // TODO: include current branch conditions and loop iterations |
| 83 | |
| 84 | String spec = prd.getSpecification_ParametericResourceDemand().getSpecification(); |
| 85 | |
| 86 | // quick fix: (convert pmfs to pdfs). This quick fix allows to use resource demands like "100 * file.BYTESIZE". |
| 87 | // Do not remove this until PMFs can be properly handled by the following, because the modelling of compression |
| 88 | // or other file handling would become difficult, one could not use the BYTESIZE characterization anymore in resource demands. |
| 89 | // spec = spec.replaceAll("IntPMF", "DoublePDF"); |
| 90 | // spec = spec.replaceAll("DoublePMF", "DoublePDF"); |
| 91 | |
| 92 | String actResDemSpecification = getSolvedSpecification(spec, prs); |
| 93 | |
| 94 | // actResDemSpecification = actResDemSpecification.replaceAll("IntPMF", "DoublePDF"); |
| 95 | // actResDemSpecification = actResDemSpecification.replaceAll("DoublePMF", "DoublePDF"); |
| 96 | |
| 97 | // TODO: Is there a better way to check the type of the specification? |
| 98 | // if(actResDemSpecification.contains("PMF") == true) { |
| 99 | // throw new RuntimeException("Resource demand specification \"" + spec |
| 100 | // + "\" of InternalAction \"" + action.getEntityName() + "\" (ID = \"" + action.getId() |
| 101 | // + "\") evaluates to a probability mass function (PMF), but only probability density functions (PDF) are allowed."); |
| 102 | // } |
| 103 | |
| 104 | ResourceDemand ard = compAllocationFactory.createResourceDemand(); |
| 105 | ard.setParametricResourceDemand_ResourceDemand(prd); |
| 106 | |
| 107 | PCMRandomVariable rv = CoreFactory.eINSTANCE.createPCMRandomVariable(); |
| 108 | rv.setSpecification(actResDemSpecification); |
| 109 | |
| 110 | //convertLiteralsToPDFs(rv); |
| 111 | |
| 112 | ard.setSpecification_ResourceDemand(rv); |
| 113 | |
| 114 | visitor.getContextWrapper().getCompAllCtx() |
| 115 | .getResourceDemands_ComputedAllocationContext().add(ard); |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * Get a combined expression for the demanded time: specification / processing rate prs |
| 120 | * |
| 121 | * As the expressions can be more complex, we added parentheses, resulting in |
| 122 | * (specification)/((prs)*1.0). This expression is then solved in the ContextWrapper of this.visitor. |
| 123 | * and finally again printed to a String. |
| 124 | * |
| 125 | * @param specification |
| 126 | * @param prs |
| 127 | * @return A String with the solved expression. |
| 128 | */ |
| 129 | private String getSolvedSpecification(String specification, ProcessingResourceSpecification prs) { |
| 130 | |
| 131 | // quickly incorporate processing rate |
| 132 | /* As both divisor and divident may evaluate to an integer and the first may be smaller |
| 133 | * than the latter, I added the factor *1.0 so that it is not falsely rounded to 0 |
| 134 | * (without *1.0, e.g. (4) / 20 would result in a demand of 0 instead of 0.2) |
| 135 | */ |
| 136 | specification = "("+ specification+") / (("+prs.getProcessingRate_ProcessingResourceSpecification().getSpecification()+")*1.0)"; |
| 137 | logger.debug("Actual Resource Demand (Expression): "+specification); |
| 138 | |
| 139 | Expression solvedExpr = (Expression) ExpressionHelper |
| 140 | .getSolvedExpression(specification, visitor.getContextWrapper()); |
| 141 | |
| 142 | |
| 143 | |
| 144 | String solvedSpecification = ExpressionHelper |
| 145 | .getSolvedExpressionAsString(specification, |
| 146 | visitor.getContextWrapper()); |
| 147 | logger.debug("Computed Actual Resource Demand: "+solvedSpecification); |
| 148 | return solvedSpecification; |
| 149 | } |
| 150 | |
| 151 | /** |
| 152 | * @return |
| 153 | */ |
| 154 | private EList<ProcessingResourceSpecification> getResourceList() { |
| 155 | AllocationContext ac = visitor.getContextWrapper().getAllCtx(); |
| 156 | ResourceContainer currentResourceContainer = ac.getResourceContainer_AllocationContext(); |
| 157 | EList<ProcessingResourceSpecification> resourceList = currentResourceContainer |
| 158 | .getActiveResourceSpecifications_ResourceContainer(); |
| 159 | return resourceList; |
| 160 | } |
| 161 | |
| 162 | } |