diff --git a/edu.kit.ipd.descartes.adaptation/.classpath b/edu.kit.ipd.descartes.adaptation/.classpath index ad32c83a7885b8953a938b41df3b4fd4fe1aae01..4ca2b4b81d7f0360a0849f4be915a203afc9178d 100644 --- a/edu.kit.ipd.descartes.adaptation/.classpath +++ b/edu.kit.ipd.descartes.adaptation/.classpath @@ -2,6 +2,7 @@ <classpath> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/log4j"/> <classpathentry kind="src" path="src"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/edu.kit.ipd.descartes.adaptation/META-INF/MANIFEST.MF b/edu.kit.ipd.descartes.adaptation/META-INF/MANIFEST.MF index e8ee70166fedd910a2b9c89575a3c3265bb346db..1e3889adefe156d5324bcf054eb9a1e9535727b0 100644 --- a/edu.kit.ipd.descartes.adaptation/META-INF/MANIFEST.MF +++ b/edu.kit.ipd.descartes.adaptation/META-INF/MANIFEST.MF @@ -4,20 +4,20 @@ Bundle-Name: Adaptation Bundle-SymbolicName: edu.kit.ipd.descartes.adaptation;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Activator: edu.kit.ipd.descartes.adaptation.Activator -Require-Bundle: org.eclipse.osgi;bundle-version="3.8.2", - org.eclipse.ui, +Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.ocl, edu.kit.ipd.descartes.mm.resourcelandscape;bundle-version="1.0.0", edu.kit.ipd.descartes.mm.adaptation;bundle-version="1.0.0", - edu.kit.ipd.descartes.ql.core.engine;bundle-version="1.0.0" + edu.kit.ipd.descartes.ql.core.engine;bundle-version="1.0.0", + org.eclipse.emf.ecore.change;bundle-version="2.8.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Import-Package: edu.kit.ipd.descartes.ql.lang.descartesQL, +Import-Package: edu.kit.ipd.descartes.ql.core.engine, + edu.kit.ipd.descartes.ql.lang.descartesQL, edu.kit.ipd.descartes.ql.models.mapping.domain, edu.kit.ipd.descartes.ql.models.mapping.mapping, edu.kit.ipd.descartes.ql.models.repository, - org.apache.log4j;version="1.2.15", org.eclipse.core.resources, org.eclipse.emf.ecore.xmi.impl, org.eclipse.ocl.ecore diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/AdaptationControl.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/AdaptationControl.java index 818d44fff97231e021a228c024b8abf620177eab..dc6659697a0a8dd75e3d26bb43dc15d08b906708 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/AdaptationControl.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/AdaptationControl.java @@ -4,8 +4,8 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; -import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Level; +import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.xmi.DanglingHREFException; @@ -45,6 +45,7 @@ public class AdaptationControl { private AdaptationProcessModelLoader adaptationProcessModelLoader = AdaptationProcessModelLoader.getInstance(); private IPerformanceDataRepositoryHandler perfDataRepoHandler; + private DmmModelActionHandler dmmModelActionHandler; private AdaptationProcess adaptationProcess = null; private TacticExecutor executor = null; private IModelAnalyzer modelAnalyzer = null; @@ -78,7 +79,8 @@ public class AdaptationControl { perfDataRepoHandler.load(performanceDataRepoXmiFilePath); // set handlers - executor = new TacticExecutor(new DmmModelActionHandler()); + dmmModelActionHandler = new DmmModelActionHandler(); + executor = new TacticExecutor(dmmModelActionHandler); modelAnalyzer = new PcmModelAnalyzer(); evaluator = new WeightingFunctionEvaluator(); } catch (IOException e) { @@ -89,8 +91,7 @@ public class AdaptationControl { /* (non-Javadoc) refactor this after integration of QL Engine */ private static void prepare(String propertiesfile) { - BasicConfigurator.configure(); - Logger.getRootLogger().setLevel(Level.DEBUG); + LogManager.getRootLogger().setLevel(Level.DEBUG); AdaptationControl adaptationController = new AdaptationControl(); // Initialize controller (load models, create Action perfDataRepoHandler, etc.) @@ -118,16 +119,15 @@ public class AdaptationControl { applyTactic(currentTactic); analyzeModel(); - processResults(); evaluate(); // save results try { logger.debug("Saving tactics evaluation results..."); - adaptationProcessModelLoader.saveAll(); + AdaptationProcessModelLoader.saveAll(); } catch (IOException e) { if (e.getCause() instanceof DanglingHREFException) - logger.error("Error while persisting results because of dangling references. Probably not all changes have been saved"); + logger.error("Error while persisting results because of dangling references. Probably not all changes have been saved."); else logger.error("Error while persisting evaluation results.", e); } @@ -162,23 +162,16 @@ public class AdaptationControl { } /** - * Choose a suitable model analyzer and analyze the reconfigured model. + * Choose a suitable model analyzer and analyze the reconfigured model. Next, process the + * results of the applied weighted tactic. For example, store the results in a performance data + * repository. */ public void analyzeModel() { modelAnalyzer.analyze(); - } - - /** - * Process the results of the applied weighted tactic. For example, store the results in a - * performance data repository. - * - * @param tactic - */ - public void processResults() { - WeightedTactic tactic = TacticsHistory.getInstance().getLatestAppliedTactic(); - + if (TacticsHistory.getInstance().wasLatestTacticSuccessful()) { + // TODO Call model analysis Impact latestImpact = perfDataRepoHandler.getLatestImpact(tactic); if (latestImpact != null) tactic.setLastImpact(latestImpact); @@ -194,25 +187,21 @@ public class AdaptationControl { * @param tactic */ public void evaluate() { - WeightedTactic tactic = TacticsHistory.getInstance().getLatestAppliedTactic(); - - if (TacticsHistory.getInstance().wasLatestTacticSuccessful()) { - + + if (!TacticsHistory.getInstance().wasLatestTacticSuccessful()) + evaluator.punishTactic(tactic); + else { // Check if tactic has made anything stupid, i.e., violates the objectives. If yes, undo // and/or assign bad weight. - if (evaluator.degradationDetected(tactic)) { - logger.warn("Degradation detected for tactic " + tactic.getName()); - // undo tactic - // assign negative weight + if (evaluator.qosDegradationDetected(tactic)) { + logger.warn("QoS degradation detected after applying tactic " + tactic.getName()); + executor.undoPreviousTactic(); + evaluator.punishTactic(tactic); + } else { + evaluator.evaluate(tactic); } - - // If everything is fine, assign new weight. - evaluator.evaluate(tactic); - } else { - evaluator.punishTactic(tactic); } - } /** diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/TacticExecutor.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/TacticExecutor.java index 6710af5d5bd74ac45ecfce6041eec4bca582832b..49865c04743222a9f81156ec9ea26ba94ee9f723 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/TacticExecutor.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/TacticExecutor.java @@ -1,20 +1,27 @@ package edu.kit.ipd.descartes.adaptation; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import org.apache.log4j.Logger; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.change.ChangeDescription; import edu.kit.ipd.descartes.adaptation.exceptions.InvalidAdaptationPlan; import edu.kit.ipd.descartes.adaptation.exceptions.OperationNotPerformedException; +import edu.kit.ipd.descartes.adaptation.model.dmm.AdaptationProcessModelLoader; import edu.kit.ipd.descartes.adaptation.model.dmm.util.OclEvaluationHelper; +import edu.kit.ipd.descartes.adaptation.util.BlueYonderExperimentTracker; +import edu.kit.ipd.descartes.adaptation.util.IObserver; import edu.kit.ipd.descartes.mm.adaptation.AbstractControlFlowElement; import edu.kit.ipd.descartes.mm.adaptation.Action; import edu.kit.ipd.descartes.mm.adaptation.ActionReference; import edu.kit.ipd.descartes.mm.adaptation.AdaptationPlan; import edu.kit.ipd.descartes.mm.adaptation.BranchAction; import edu.kit.ipd.descartes.mm.adaptation.LoopAction; +import edu.kit.ipd.descartes.mm.adaptation.Parameter; import edu.kit.ipd.descartes.mm.adaptation.StartAction; import edu.kit.ipd.descartes.mm.adaptation.StopAction; import edu.kit.ipd.descartes.mm.adaptation.WeightedTactic; @@ -24,14 +31,17 @@ import edu.kit.ipd.descartes.mm.resourcelandscape.ResourcelandscapePackage; public class TacticExecutor { - static Logger logger = Logger.getLogger(TacticExecutor.class); + private static Logger logger = Logger.getLogger(TacticExecutor.class); + private List<IObserver> observers = new ArrayList<IObserver>(); private IActionHandler dmmModelActionHandler; private TacticsHistory hist; + private ChangeDescription changeDescription = null; public TacticExecutor(IActionHandler actionExecutor) { dmmModelActionHandler = actionExecutor; hist = TacticsHistory.getInstance(); + register(BlueYonderExperimentTracker.getInstance()); // TODO implement clean observer pattern } /** @@ -43,6 +53,7 @@ public class TacticExecutor { */ public void applyTactic(WeightedTactic weightedTactic) { try { + AdaptationProcessModelLoader.startRecording(); executeAdaptationPlan(weightedTactic.getUsedTactic().getImplementedPlan()); logger.info("Tactic " + weightedTactic.getUsedTactic().getName() + " successfully applied."); @@ -50,6 +61,7 @@ public class TacticExecutor { // if this point is reached everything was fine, so persist them (save the models) dmmModelActionHandler.persistActions(); + changeDescription = AdaptationProcessModelLoader.endRecording(); return; } catch (OperationNotPerformedException e) { logger.error("Tactic " + weightedTactic.getUsedTactic().getName() @@ -141,10 +153,12 @@ public class TacticExecutor { private void execLoopAction(AbstractControlFlowElement loopAction) throws OperationNotPerformedException { LoopAction loop = (LoopAction) loopAction; - int numberOfIterations = loop.getCounter(); + Parameter counter = loop.getCounter(); + int counterValue = Integer.parseInt(counter.getValue()); + int i = 1; - while (i <= numberOfIterations) { + while (i <= counterValue) { logger.debug("Executing iteration " + i + " of loop action " + loop.getBody().getName()); executeAdaptationPlan(loop.getBody()); i++; @@ -172,4 +186,20 @@ public class TacticExecutor { return invariant; } + public void undoPreviousTactic() { + logger.info("Reverting model to previous state"); + for(IObserver o : observers) + o.undo(); + if (changeDescription != null) + changeDescription.apply(); + } + + public void register(IObserver observer) { + observers.add(observer); + } + + public void remove(IObserver observer) { + observers.remove(observer); + } + } diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/IEvaluator.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/IEvaluator.java index f9b22b23288c4ef5303bab64dd60342f86032bc1..eb0deedaefeab0f9ac36cdcfc4ac5d56b7573d09 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/IEvaluator.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/IEvaluator.java @@ -1,5 +1,6 @@ package edu.kit.ipd.descartes.adaptation.evaluation; +import edu.kit.ipd.descartes.mm.adaptation.Objective; import edu.kit.ipd.descartes.mm.adaptation.WeightedTactic; /** @@ -13,18 +14,19 @@ public interface IEvaluator { /** * Evaluates the impact of a {@link WeightedTactic}. * - * @param wt + * @param tactic * The weighted tactic to evaluate */ - public void evaluate(WeightedTactic wt); + public void evaluate(WeightedTactic tactic); /** - * Checks if any QoS property has degraded significantly after applying the tactic. + * Checks if any QoS property has degraded significantly, i.e. any {@link Objective}has been + * violated, after applying the tactic. * * @param tactic * @return */ - public boolean degradationDetected(WeightedTactic tactic); + public boolean qosDegradationDetected(WeightedTactic tactic); /** * Reduces the weight of the given tactic. diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/WeightingFunctionEvaluator.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/WeightingFunctionEvaluator.java index a124c0ad3da4eeb5de35fda07da899d060b1f24e..61e8eda5d01c794990c49e0f060b56dcc68dd9f2 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/WeightingFunctionEvaluator.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/WeightingFunctionEvaluator.java @@ -19,7 +19,7 @@ import edu.kit.ipd.descartes.perfdatarepo.Result; */ public class WeightingFunctionEvaluator implements IEvaluator { - private static final String RESPONSETIME_IDENTIFIER = "time"; + private static final String RESPONSETIME_IDENTIFIER = "ResponseTime"; private IWeightingFunction calculator = null; private static Logger logger = Logger.getLogger(WeightingFunctionEvaluator.class); @@ -56,7 +56,7 @@ public class WeightingFunctionEvaluator implements IEvaluator { tactic.setCurrentWeight(newWeight); } - public boolean degradationDetected(WeightedTactic tactic) { + public boolean qosDegradationDetected(WeightedTactic tactic) { Impact impact = tactic.getLastImpact(); Result before = impact.getBefore(); Result after = impact.getAfter(); diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/weightingfunction/ResourceEfficiency.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/weightingfunction/BlueYonderResourceEfficiencyWeightingFunction.java similarity index 91% rename from edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/weightingfunction/ResourceEfficiency.java rename to edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/weightingfunction/BlueYonderResourceEfficiencyWeightingFunction.java index 831f34c4a5e80e1faecf418bc2cbbaa140a92bc9..3d1ea4e0b89c61076038d3711c5db277a5f00fd6 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/weightingfunction/ResourceEfficiency.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/evaluation/weightingfunction/BlueYonderResourceEfficiencyWeightingFunction.java @@ -9,14 +9,14 @@ import edu.kit.ipd.descartes.perfdatarepo.Impact; import edu.kit.ipd.descartes.perfdatarepo.MetricValue; import edu.kit.ipd.descartes.perfdatarepo.Result; -public class ResourceEfficiency implements IWeightingFunction { +public class BlueYonderResourceEfficiencyWeightingFunction implements IWeightingFunction { private static final String UTIL_IDENTIFIER = "Util"; private static final double THRESHOLD = 0.05; private WeightingFunction function = null; - private static Logger logger = Logger.getLogger(ResourceEfficiency.class); + private static Logger logger = Logger.getLogger(BlueYonderResourceEfficiencyWeightingFunction.class); -// public ResourceEfficiency() { +// public BlueYonderResourceEfficiencyWeightingFunction() { // AbstractEcoreModelLoader loader = PerformanceDataRepositoryModelLoader.getInstance(); // String pdrLocation = loader.getCurrentModelUri().toFileString(); // logger.debug("Initializing query engine adaptor for performance data repository " + pdrLocation); diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/AdaptationProcessModelLoader.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/AdaptationProcessModelLoader.java index 6993974ffc60b26786f4e6d2b7876960aa77519d..061b80aee9118c665bbefb8efc933de759e0e241 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/AdaptationProcessModelLoader.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/AdaptationProcessModelLoader.java @@ -8,6 +8,8 @@ import java.util.Map; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.change.ChangeDescription; +import org.eclipse.emf.ecore.change.util.ChangeRecorder; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; @@ -29,6 +31,7 @@ public class AdaptationProcessModelLoader extends AbstractEcoreModelLoader { AdaptationpointsPackage.eINSTANCE, ContainerrepositoryPackage.eINSTANCE, AdaptationPackage.eINSTANCE }; private static AdaptationProcessModelLoader instance = null; + private static ChangeRecorder recorder = null; public static AdaptationProcessModelLoader getInstance() { if (instance == null) { @@ -41,9 +44,9 @@ public class AdaptationProcessModelLoader extends AbstractEcoreModelLoader { initializeResourceSet(new ResourceSetImpl()); } - public void saveAll() throws IOException { + public static void saveAll() throws IOException { - EList<Resource> resources = getResourceSet().getResources(); + EList<Resource> resources = getInstance().getResourceSet().getResources(); Map<String, String> options = new HashMap<String, String>(); options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE.toString()); options.put(XMIResource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER, Boolean.TRUE.toString()); @@ -54,7 +57,8 @@ public class AdaptationProcessModelLoader extends AbstractEcoreModelLoader { res.save(options); } catch (IOException e) { if (e.getCause() instanceof DanglingHREFException) { - String newMessage = "Error while persisting " + res.getURI() + " because of dangling references. Probably not all changes have been saved.\n"; + String newMessage = "Error while persisting " + res.getURI() + + " because of dangling references. Probably not all changes have been saved.\n"; throw new IOException(newMessage + e.getMessage(), e.getCause()); } } @@ -88,4 +92,17 @@ public class AdaptationProcessModelLoader extends AbstractEcoreModelLoader { public AdaptationProcess load(URI uri) { return (AdaptationProcess) super.load(uri); } + + public static void startRecording() { + recorder = new ChangeRecorder(getInstance().getResourceSet()); + } + + public static ChangeDescription endRecording() { + return recorder.endRecording(); + } + + public static void endRecordingAndRollback() { + recorder.endRecording().apply(); + + } } diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/DmmModelActionHandler.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/DmmModelActionHandler.java index a52011478c469c75fcbd690dc1553949ed9655ca..7885def765a618179ed3d527933b5b0801c5c818 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/DmmModelActionHandler.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/DmmModelActionHandler.java @@ -2,6 +2,7 @@ package edu.kit.ipd.descartes.adaptation.model.dmm; import java.io.IOException; import java.util.List; +import java.util.Random; import org.apache.log4j.Logger; import org.eclipse.emf.common.util.EList; @@ -168,7 +169,7 @@ public class DmmModelActionHandler implements IActionHandler { return invariant; } - private void migrate(Entity adaptableEntity, VariationType targets, AdaptationScope adaptationScope) { + private void migrate(Entity adaptableEntity, VariationType targets, AdaptationScope adaptationScope) throws OperationNotPerformedException { switch (adaptableEntity.eClass().getClassifierID()) { case ResourcelandscapePackage.RUNTIME_ENVIRONMENT: logger.debug("Starting migration of a runtime environment referring to container template " @@ -184,25 +185,30 @@ public class DmmModelActionHandler implements IActionHandler { EList<Entity> migrationTargets = ((SetOfConfigurations) targets).getVariants(); RuntimeEnvironment migratedEntity = (RuntimeEnvironment) adaptableEntity; - Container parent = migratedEntity.getContainedIn(); + Container source = migratedEntity.getContainedIn(); // TODO Here you could implement something more sophisticated // e.g., choose the container with the lowest util. - Entity randomTarget = randomTarget(migrationTargets, parent); - if (!(randomTarget instanceof Container)) + Entity target = randomTarget(migrationTargets, source); + + if (!(target instanceof Container)) throw new IllegalArgumentException( "Migration could not be performed because target is not a container!"); - - Container targetContainer = (Container) randomTarget; + Container targetContainer = (Container) target; + + if (migrationTargets.size() == 1 && EcoreUtil.equals(source, target)) + throw new OperationNotPerformedException("Migration operation not executed because source and destination are identical."); targetContainer.getContains().add(migratedEntity); - parent.getContains().remove(migratedEntity); + source.getContains().remove(migratedEntity); break; case ContainerrepositoryPackage.CONTAINER_TEMPLATE: - logger.debug("Starting migration of a container referring to container template " - + adaptableEntity.getName() + " (ID: " + adaptableEntity.getId() + ")"); - ContainerTemplate ct = (ContainerTemplate) adaptableEntity; - Container c = DmmModelActionHelper.findSuitableContainer(ct, adaptationScope); - migrate(c, targets, adaptationScope); +// logger.debug("Starting migration of a container referring to container template " +// + adaptableEntity.getName() + " (ID: " + adaptableEntity.getId() + ")"); + ContainerTemplate containerTemplate = (ContainerTemplate) adaptableEntity; + Container migratedContainer = DmmModelActionHelper.findSuitableContainer(containerTemplate, adaptationScope, targets); + if (migratedContainer == null) + throw new OperationNotPerformedException("Could not execute migration operation because no suitable migration candidate found"); + migrate(migratedContainer, targets, adaptationScope); break; default: throw new IllegalArgumentException("No implemented migrate operation for " + adaptableEntity); @@ -211,11 +217,13 @@ public class DmmModelActionHandler implements IActionHandler { } private Entity randomTarget(EList<Entity> destinations, Entity source) { - Entity destination = null; - - while (destination == null || EcoreUtil.equals(destination, source)) { - int destSize = destinations.size() - 1; - int destNumber = (int) Math.round(Math.random() * destSize); + if (destinations.size() == 1) + return destinations.get(0); + + Entity destination = destinations.get(0); + Random randomGenerator = new Random(); + while (EcoreUtil.equals(destination, source)) { + int destNumber = randomGenerator.nextInt(destinations.size()); destination = destinations.get(destNumber); } diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/util/DmmModelActionHelper.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/util/DmmModelActionHelper.java index ea7338fecdbc0e14dc93adb25a98decdb2910a09..203cd216b199d83a892c25443e86c106be2c8b48 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/util/DmmModelActionHelper.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/dmm/util/DmmModelActionHelper.java @@ -3,14 +3,16 @@ package edu.kit.ipd.descartes.adaptation.model.dmm.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Random; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import edu.kit.ipd.descartes.core.AdaptableEntity; +import edu.kit.ipd.descartes.core.Entity; import edu.kit.ipd.descartes.core.NamedElement; import edu.kit.ipd.descartes.mm.adaptation.AdaptationScope; +import edu.kit.ipd.descartes.mm.adaptationpoints.SetOfConfigurations; +import edu.kit.ipd.descartes.mm.adaptationpoints.VariationType; import edu.kit.ipd.descartes.mm.containerrepository.ContainerTemplate; import edu.kit.ipd.descartes.mm.resourceconfiguration.ConfigurationSpecification; import edu.kit.ipd.descartes.mm.resourceconfiguration.ResourceconfigurationPackage; @@ -26,19 +28,19 @@ public class DmmModelActionHelper { * @return the {@link EObject} of the model instance that contains {@code aEntity} */ public static EObject findParentConfiguredInstance(AdaptableEntity aEntity) { - + ConfigurationSpecification c = null; - + if (aEntity.eClass().getClassifierID() == ResourceconfigurationPackage.NUMBER_OF_PARALLEL_PROCESSING_UNITS) c = (ConfigurationSpecification) aEntity.eContainer().eContainer(); else if (aEntity.eClass().getClassifierID() == ResourceconfigurationPackage.PASSIVE_RESOURCE_CAPACITY) c = (ConfigurationSpecification) aEntity.eContainer(); else return null; - + return c.eContainer(); } - + /** * Query for a {@link Container} with similar specs * @@ -50,15 +52,14 @@ public class DmmModelActionHelper { Container comparatorContainer) { List<Container> resultList = new ArrayList<Container>(); - + for (Container c : candidates) { /* * Make sure we find a RuntimeEnvironment with 1. a DIFFERENT ID 2. similar properties * and 3. name must contain COPY_MARK to make sure we remove only a copy */ - if (c.getId() != comparatorContainer.getId() - && c.getName().contains(DmmModelChanger.COPY_MARK) + if (c.getId() != comparatorContainer.getId() && c.getName().contains(DmmModelChanger.COPY_MARK) && EcoreUtil.equals(comparatorContainer.getConfigSpec(), c.getConfigSpec()) && EcoreUtil.equals(comparatorContainer.getTemplate(), c.getTemplate())) { resultList.add(c); @@ -66,11 +67,10 @@ public class DmmModelActionHelper { } return resultList; } - + /** - * Query for a {@link RuntimeEnvironment} that - * has been copied (contains {@link DmmModelChanger.COPY_MARK}) and refers to - * the same ContainerTemplate. + * Query for a {@link RuntimeEnvironment} that has been copied (contains + * {@link DmmModelChanger.COPY_MARK}) and refers to the same ContainerTemplate. * * @param candidates * @param comparatorRE @@ -81,20 +81,19 @@ public class DmmModelActionHelper { for (RuntimeEnvironment re : candidates) { - if (re.getId() != comparatorRE.getId() - && re.getName().contains(DmmModelChanger.COPY_MARK) -// && EcoreUtil.equals(comparatorRE.getConfigSpec(), re.getConfigSpec()) -// && EcoreUtil.equals(comparatorRE.getContainedIn(), re.getContainedIn()) + if (re.getId() != comparatorRE.getId() && re.getName().contains(DmmModelChanger.COPY_MARK) + // && EcoreUtil.equals(comparatorRE.getConfigSpec(), re.getConfigSpec()) + // && EcoreUtil.equals(comparatorRE.getContainedIn(), re.getContainedIn()) && EcoreUtil.equals(comparatorRE.getTemplate(), re.getTemplate())) { return re; } } return null; } - + public static NamedElement findEntityWithName(NamedElement element, String name) { - - if(element.getName().equals(name)) + + if (element.getName().equals(name)) return element; else { NamedElement result = null; @@ -107,61 +106,64 @@ public class DmmModelActionHelper { return result; } } - - /** Queries for all Container instances that have a similar configuration - * specification as Container <code>c</code>. Similar configuration - * specification meas that ContainerTemplate and ConfigurationSpecification - * are equal. + + /** + * Queries for all Container instances that have a similar configuration specification as + * Container <code>c</code>. Similar configuration specification meas that ContainerTemplate and + * ConfigurationSpecification are equal. * - * @param c + * @param c * @return A list of Container instances */ public static List<Container> queryContainersWithSimilarSpecs(Container c) { - List<Container> result = queryContainersWithSimilarTemplate(c); - return filterContainersWithSimilarSpecs(result, c); + List<Container> result = queryContainersWithSimilarTemplate(c); + return filterContainersWithSimilarSpecs(result, c); } - /**Queries for a RuntimeEnvironment whose ContainerTemplate is similar to the - * given RuntimeEnvironment <code>re</code> and whose capacity is below <code>maxValue</code>. + /** + * Queries for a RuntimeEnvironment whose ContainerTemplate is similar to the given + * RuntimeEnvironment <code>re</code> and whose capacity is below <code>maxValue</code>. * * @param re * @param maxValue * @return */ public static RuntimeEnvironment queryUnfilledRuntimeEnvironment(RuntimeEnvironment re, double maxValue) { - //TODO SEAMS specific helper function! Generalize! - String queryExpression = "RuntimeEnvironment.allInstances()->select( re | re.template = self.template )->select(re | re.configSpec.oclAsType(resourceconfiguration::ActiveResourceSpecification).processingResourceSpecifications->forAll(nrOfParProcUnits.number < "+maxValue+"))"; - List<EObject> resultList = new ArrayList<EObject>( - OclEvaluationHelper.query(re, queryExpression, re.eClass())); - - if (resultList.size()>0) + // TODO SEAMS specific helper function! Generalize! + String queryExpression = "RuntimeEnvironment.allInstances()->select( re | re.template = self.template )->select(re | re.configSpec.oclAsType(resourceconfiguration::ActiveResourceSpecification).processingResourceSpecifications->forAll(nrOfParProcUnits.number < " + + maxValue + "))"; + List<EObject> resultList = new ArrayList<EObject>(OclEvaluationHelper.query(re, queryExpression, re.eClass())); + + if (resultList.size() > 0) return (RuntimeEnvironment) resultList.get(0); else return null; } - + public static RuntimeEnvironment queryNotEmptyRuntimeEnvironment(RuntimeEnvironment re, double minValue) { // TODO SEAMS specific helper function! Generalize! - String queryExpression = "RuntimeEnvironment.allInstances()->select( re | re.template = self.template and not re.configSpec->isEmpty() )->select(re | re.configSpec.oclAsType(resourceconfiguration::ActiveResourceSpecification).processingResourceSpecifications->forAll(nrOfParProcUnits.number > "+minValue+"))"; - List<EObject> resultList = new ArrayList<EObject>( - OclEvaluationHelper.query(re, queryExpression, re.eClass())); - - if (resultList.size()>0) + String queryExpression = "RuntimeEnvironment.allInstances()->select( re | re.template = self.template and not re.configSpec->isEmpty() )->select(re | re.configSpec.oclAsType(resourceconfiguration::ActiveResourceSpecification).processingResourceSpecifications->forAll(nrOfParProcUnits.number > " + + minValue + "))"; + List<EObject> resultList = new ArrayList<EObject>(OclEvaluationHelper.query(re, queryExpression, re.eClass())); + + if (resultList.size() > 0) return (RuntimeEnvironment) resultList.get(0); else return null; } - /**Queries for all Container instances referring to the same - * ContainerTemplate as the given container. + /** + * Queries for all Container instances referring to the same ContainerTemplate as the given + * container. * - * @param container The container to look for + * @param container + * The container to look for * @return All Container Instances referring to the same ContainerTemplate */ public static List<Container> queryContainersWithSimilarTemplate(Container container) { String queryExpression = "RuntimeEnvironment.allInstances()->select( re | re.template = self.template and re.id <> self.id)"; - List<EObject> tempList = new ArrayList<EObject>( - OclEvaluationHelper.query(container, queryExpression, container.eClass())); + List<EObject> tempList = new ArrayList<EObject>(OclEvaluationHelper.query(container, queryExpression, + container.eClass())); List<Container> resultList = new ArrayList<Container>(tempList.size()); for (Iterator<EObject> iterator = tempList.iterator(); iterator.hasNext();) { Container temp = (Container) iterator.next(); @@ -170,40 +172,82 @@ public class DmmModelActionHelper { return resultList; } - - /**Filter the given {@code containerList} for RuntimeEnvironments and cast - * them to {@link RuntimeEnvironment} + /** + * Filter the given {@code containerList} for RuntimeEnvironments and cast them to + * {@link RuntimeEnvironment} + * * @param containerList * @return a list of RuntimeEnvironments */ public static List<RuntimeEnvironment> filterAndConvertRuntimeEnvironment(List<Container> containerList) { List<RuntimeEnvironment> result = new ArrayList<RuntimeEnvironment>(); - + for (Container container : containerList) { - if (container.eClass().getClassifierID() == ResourcelandscapePackage.RUNTIME_ENVIRONMENT) + if (container.eClass().getClassifierID() == ResourcelandscapePackage.RUNTIME_ENVIRONMENT) result.add((RuntimeEnvironment) container); } - + return result; } - - /**Find a container that refers to the given {@link ContainerTemplate} and that suits the - * given {@link AdaptationScope}. + + /** + * Find a container that refers to the given {@link ContainerTemplate} and that suits the given + * {@link AdaptationScope}. * * @param containerTemplate * @param adaptationScope + * @param targets * @return */ - public static Container findSuitableContainer(ContainerTemplate containerTemplate, AdaptationScope adaptationScope) { + public static Container findSuitableContainer(ContainerTemplate containerTemplate, AdaptationScope adaptationScope, VariationType targets) { + // Get all containers referring to the template List<Container> containers = containerTemplate.getReferringContainers(); - Random randomGenerator = new Random(); + List<Entity> variants = ((SetOfConfigurations) targets).getVariants(); + + // Prepare the list of migration targets + List<Container> migrationTargets = new ArrayList<Container>(); + for (Entity entity : variants) { + migrationTargets.add((Container) entity); + } + + for (Container container : containers) { + + // Remove container from migration targets + List<Container> migrationTargetCandidates = excludeSelfContainmentFromTargetList(container, migrationTargets); + + // If there are migration targets left + if (migrationTargetCandidates.size() > 0) { + switch (adaptationScope) { + case RANDOM: + return container; + default: + return null; + } + } + } + return null; + } - switch (adaptationScope) { - case RANDOM: - return containers.get(randomGenerator.nextInt(containers.size())); - default: + /** + * Returns a list of {@code targets} excluding the target the container {@code self} is already + * contained in. + * + * @param self + * @param targets + * @return + */ + public static List<Container> excludeSelfContainmentFromTargetList(Container self, List<Container> targets) { + if (self == null || targets == null) return null; + + List<Container> resultList = new ArrayList<Container>(); + + for (Container target : targets) { + if (!EcoreUtil.equals(target, self.eContainer())) + resultList.add(target); } + + return resultList; } - + } diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/perfdatarepo/ObservationRepositoryHandler.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/perfdatarepo/ObservationRepositoryHandler.java index 473f6868024fbbbb1d3844692f8c7ce8a7d155de..eb62e0cc5f1b3b202e6fd84c1149abddac2da035 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/perfdatarepo/ObservationRepositoryHandler.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/model/perfdatarepo/ObservationRepositoryHandler.java @@ -16,7 +16,7 @@ import edu.kit.ipd.descartes.ql.models.repository.ObservationRepository; public class ObservationRepositoryHandler implements IPerformanceDataRepositoryHandler { - private BlueYonderExperimentTracker tracker = new BlueYonderExperimentTracker(); + private BlueYonderExperimentTracker tracker = BlueYonderExperimentTracker.getInstance(); private static Logger logger = Logger.getLogger(ObservationRepositoryHandler.class); private AbstractEcoreModelLoader modelLoader = null; private ObservationRepository repository = null; diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/util/BlueYonderExperimentTracker.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/util/BlueYonderExperimentTracker.java index 6d29bc93e5bd62221369b297214defad7533c6d6..aa65282269954902df44ab1a6abe9d9b827556d0 100644 --- a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/util/BlueYonderExperimentTracker.java +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/util/BlueYonderExperimentTracker.java @@ -1,32 +1,77 @@ package edu.kit.ipd.descartes.adaptation.util; +import edu.kit.ipd.descartes.adaptation.TacticExecutor; import edu.kit.ipd.descartes.mm.adaptation.WeightedTactic; -public class BlueYonderExperimentTracker { +public class BlueYonderExperimentTracker implements IObserver { private static final String RESULT_NAME = "Xreq-par-$1Yps-desc4-gw-desc3-db-desc2-predict-Z ps=$2-req=5-size=50000"; + private static BlueYonderExperimentTracker instance = null; private int psOnDescOne = 0; private int psOnDescFour = 1; + private int psOnDescOneBackup; + private int psOnDescFourBackup; + + public void setSubject(TacticExecutor te) { + te.register(this); + } public String getCurrentExperimentName() { String result = RESULT_NAME; - + if (psOnDescOne > 0) result = RESULT_NAME.replace("$1", psOnDescOne + "ps-desc1-"); else result = RESULT_NAME.replace("$1", ""); - + result = result.replace("$2", Integer.toString(psOnDescFour)); return result; } public void track(WeightedTactic tactic) { String execTacticName = tactic.getName(); + backupValues(); - if (execTacticName.contains("Low")) { + if (execTacticName.contains("Consolidate")) { + int loopCount = Integer.parseInt(tactic.getUsedTactic().getInputParams().get(0).getValue()); + if (execTacticName.contains("Low")) { + psOnDescFour = psOnDescFour - loopCount; + psOnDescOne = psOnDescOne + loopCount; + } else if (execTacticName.contains("High")) { + psOnDescOne = psOnDescOne - loopCount; + psOnDescFour = psOnDescFour + loopCount; + } + } else if (execTacticName.contains("Low")) { psOnDescOne++; + assert psOnDescFour > 0; + if (execTacticName.contains("Migrate")) + psOnDescFour--; } else if (execTacticName.contains("High")) { psOnDescFour++; + assert psOnDescOne > 0; + if (execTacticName.contains("Migrate")) + psOnDescOne--; } } + + private void backupValues() { + psOnDescOneBackup = psOnDescOne; + psOnDescFourBackup = psOnDescFour; + } + + @Override + public void undo() { + resetValues(); + } + + private void resetValues() { + psOnDescOne = psOnDescOneBackup; + psOnDescFour = psOnDescFourBackup; + } + + public static BlueYonderExperimentTracker getInstance() { + if (instance == null) + instance = new BlueYonderExperimentTracker(); + return instance; + } } diff --git a/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/util/IObserver.java b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/util/IObserver.java new file mode 100644 index 0000000000000000000000000000000000000000..42e15cd83f516c365077decfa37f3c7a68329345 --- /dev/null +++ b/edu.kit.ipd.descartes.adaptation/src/edu/kit/ipd/descartes/adaptation/util/IObserver.java @@ -0,0 +1,7 @@ +package edu.kit.ipd.descartes.adaptation.util; + +public interface IObserver { + + public void undo(); + +}