Skip to content
Snippets Groups Projects
Commit 54d0a456 authored by Nikolaus Huber's avatar Nikolaus Huber
Browse files

git-svn-id: https://se1.informatik.uni-wuerzburg.de/usvn/svn/code/code/DMM/trunk@13067 9e42b895-fcda-4063-8a3b-11be15eb1bbd
parent 2149abc0
No related branches found
No related tags found
No related merge requests found
Showing
with 1222 additions and 0 deletions
<?xml version="1.0" encoding="UTF-8"?>
<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="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>edu.kit.ipd.descartes.adaptation.model.adaptation</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
eclipse.preferences.version=1
pluginProject.equinox=false
pluginProject.extensions=false
resolve.requirebundle=false
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: ModelAdaptor
Bundle-SymbolicName: edu.kit.ipd.descartes.adaptation.model.adaptation
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: edu.kit.ipd.descartes.adaptation.model.adaptation.Activator
Bundle-Vendor: Descartes Research Group
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package:
edu.kit.ipd.descartes.adaptation.model.repository,
edu.kit.ipd.descartes.adaptation.model.repository.dmm,
edu.kit.ipd.descartes.core,
edu.kit.ipd.descartes.identifier,
edu.kit.ipd.descartes.mm.adaptation,
edu.kit.ipd.descartes.mm.adaptationpoints,
edu.kit.ipd.descartes.mm.containerrepository,
edu.kit.ipd.descartes.mm.resourceconfiguration,
edu.kit.ipd.descartes.mm.resourcelandscape,
edu.kit.ipd.descartes.mm.runtimeenvironmentclasses,
edu.kit.ipd.descartes.perfdatarepo,
org.apache.log4j;version="1.2.15",
org.eclipse.emf.common,
org.eclipse.emf.common.util,
org.eclipse.emf.ecore,
org.eclipse.emf.ecore.util,
org.eclipse.ocl.ecore,
org.osgi.framework;version="1.3.0"
Export-Package: edu.kit.ipd.descartes.adaptation.model.adaptation,
edu.kit.ipd.descartes.adaptation.model.adaptation.dmm,
edu.kit.ipd.descartes.adaptation.model.adaptation.dmm.util,
edu.kit.ipd.descartes.adaptation.model.adaptation.exceptions
Require-Bundle: org.eclipse.ocl;bundle-version="3.2.1"
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
package edu.kit.ipd.descartes.adaptation.model.adaptation;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
private static BundleContext context;
static BundleContext getContext() {
return context;
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
}
}
/**
*
*/
package edu.kit.ipd.descartes.adaptation.model.adaptation;
import edu.kit.ipd.descartes.adaptation.model.adaptation.exceptions.OperationNotPerformedException;
import edu.kit.ipd.descartes.mm.adaptation.AdaptationActionOperation;
import edu.kit.ipd.descartes.mm.adaptationpoints.AdaptationPoint;
/**
* @author nhuber
*
*
*
*/
public interface IActionHandler {
public void execute(AdaptationPoint point, AdaptationActionOperation adaptationOperation) throws OperationNotPerformedException;
public void persistActions();
}
package edu.kit.ipd.descartes.adaptation.model.adaptation.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;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import edu.kit.ipd.descartes.adaptation.model.adaptation.IActionHandler;
import edu.kit.ipd.descartes.adaptation.model.adaptation.dmm.util.DmmModelActionHelper;
import edu.kit.ipd.descartes.adaptation.model.adaptation.dmm.util.DmmModelChanger;
import edu.kit.ipd.descartes.adaptation.model.adaptation.dmm.util.OclEvaluationHelper;
import edu.kit.ipd.descartes.adaptation.model.adaptation.exceptions.OperationNotPerformedException;
import edu.kit.ipd.descartes.adaptation.model.repository.dmm.AdaptationProcessModelLoader;
import edu.kit.ipd.descartes.core.AdaptableEntity;
import edu.kit.ipd.descartes.core.Entity;
import edu.kit.ipd.descartes.mm.adaptation.AdaptationActionOperation;
import edu.kit.ipd.descartes.mm.adaptation.AdaptationScope;
import edu.kit.ipd.descartes.mm.adaptationpoints.AdaptationPoint;
import edu.kit.ipd.descartes.mm.adaptationpoints.ModelEntityConfigurationRange;
import edu.kit.ipd.descartes.mm.adaptationpoints.ModelVariableConfigurationRange;
import edu.kit.ipd.descartes.mm.adaptationpoints.PropertyRange;
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.containerrepository.ContainerrepositoryPackage;
import edu.kit.ipd.descartes.mm.resourcelandscape.Container;
import edu.kit.ipd.descartes.mm.resourcelandscape.ResourcelandscapePackage;
import edu.kit.ipd.descartes.mm.resourcelandscape.RuntimeEnvironment;
public class DmmModelActionHandler implements IActionHandler {
static Logger logger = Logger.getLogger(DmmModelActionHandler.class);
public DmmModelActionHandler() {
logger.info("DMM models loaded.");
}
private void saveModels() {
try {
AdaptationProcessModelLoader.saveAll();
} catch (IOException e) {
logger.error("Error while saving models", e);
}
}
@Override
public void execute(AdaptationPoint point, AdaptationActionOperation operation)
throws OperationNotPerformedException {
logger.debug("Executing adaptation action <<" + operation.getAdaptationOperationDirection().getLiteral() + ", "
+ operation.getAdaptationOperationScope().getLiteral() + ">> on adaptation point <<" + point.getName()
+ ">>.");
if (point instanceof ModelEntityConfigurationRange) {
logger.debug("Type of Adaptation: EntityConfigurationRange");
execEntityConfigRangeAdaptation(point, operation);
} else if (point instanceof ModelVariableConfigurationRange) {
logger.debug("Type of Adaptation Point: VariableConfigurationRange");
execVariableConfigRangeAdaptation(point, operation);
} else {
logger.error("No matching type found for given adaptation point " + point.toString());
throw new OperationNotPerformedException(
"No maching adaptation point execution found for adaptation point " + point);
}
}
public void execVariableConfigRangeAdaptation(AdaptationPoint point, AdaptationActionOperation operation)
throws OperationNotPerformedException {
ModelVariableConfigurationRange configRange = (ModelVariableConfigurationRange) point;
AdaptableEntity adaptedEntity = configRange.getAdaptableEntity();
EObject actuallyConfiguredInstance = DmmModelActionHelper.findParentConfiguredInstance(adaptedEntity);
switch (actuallyConfiguredInstance.eClass().getClassifierID()) {
case ResourcelandscapePackage.RUNTIME_ENVIRONMENT:
DmmModelChanger.scaleModelVariable(configRange, operation.getAdaptationOperationDirection());
break;
case ContainerrepositoryPackage.CONTAINER_TEMPLATE:
DmmModelChanger.scaleContainerTemplate((ContainerTemplate) actuallyConfiguredInstance, configRange,
operation);
break;
case ResourcelandscapePackage.CONTAINER:
/*
* This code should not be reached because RUNTIME_ENVIRONMENTS are also containers.
* Only AbstractHardwareInfrastructures are Containers but not RuntimeEnvironments, but
* they cannot be changed because they're hardware
*/
logger.error("You cannot specify an adaptation point for " + actuallyConfiguredInstance.eClass());
break;
default:
logger.error("No adaptation action implemented for type " + actuallyConfiguredInstance.eClass());
break;
}
}
public void execEntityConfigRangeAdaptation(AdaptationPoint point, AdaptationActionOperation operation)
throws OperationNotPerformedException {
ModelEntityConfigurationRange configRange = (ModelEntityConfigurationRange) point;
Entity adaptableEntity = configRange.getAdaptableEntity();
VariationType range = configRange.getVariationPossibility();
switch (operation.getAdaptationOperationDirection()) {
case INCREASE:
scaleOutModelEntity(adaptableEntity, range);
break;
case DECREASE:
scaleInModelEntity(adaptableEntity, range);
break;
case MIGRATE:
logger.debug("Executing MIGRATE operation");
migrate(adaptableEntity, range, operation.getAdaptationOperationScope());
break;
default:
throw new OperationNotPerformedException("Operation " + operation + " on adaptation point "
+ point.getName() + " not supported");
}
}
private void scaleInModelEntity(Entity adaptableEntity, VariationType range) throws OperationNotPerformedException {
logger.debug("Executing DECREASE operation");
Entity scaledEntity = scaleIn(adaptableEntity);
if (scaledEntity == null)
throw new OperationNotPerformedException("Could not scale " + adaptableEntity.getName()
+ ". Minimum has been reached!");
}
private void scaleOutModelEntity(Entity adaptableEntity, VariationType range) throws OperationNotPerformedException {
logger.debug("Executing INCREASE operation");
RuntimeEnvironment scaledRE = scaleOut(adaptableEntity);
if (!invariantsAreValid(adaptableEntity, (PropertyRange) range)) { // spawn new
// runtimeEnvironment on
// different machine
List<Container> possibleTargets = DmmModelActionHelper.queryContainersWithSimilarTemplate(scaledRE
.getContainedIn());
for (Container nextContainer : possibleTargets) {
scaledRE.setContainedIn(nextContainer);
if (invariantsAreValid(scaledRE, (PropertyRange) range)) {
logger.debug("Scaling entity " + scaledRE.getName() + " on altenative container "
+ nextContainer.getName() + " (ID: " + nextContainer.getId() + ")");
return;
}
}
// in case a violation occured and no alternative container was found
EcoreUtil.delete(scaledRE, true);
throw new OperationNotPerformedException("Could not scale " + adaptableEntity.getName()
+ ". Maxiumum has been reached!");
}
}
private boolean invariantsAreValid(Entity adaptableEntity, PropertyRange range) {
boolean invariant = OclEvaluationHelper.evaluateOclConstraint(adaptableEntity, range.getMinValueConstraint()
.getOclString(), adaptableEntity.eClass());
if (!invariant)
logger.debug("Invariant " + range.getMinValueConstraint().getOclString() + " violated");
invariant &= OclEvaluationHelper.evaluateOclConstraint(adaptableEntity, range.getMaxValueConstraint()
.getOclString(), adaptableEntity.eClass());
if (!invariant)
logger.debug("Invariant " + range.getMaxValueConstraint().getOclString() + " violated");
return invariant;
}
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 "
+ adaptableEntity.getName() + " (ID: " + adaptableEntity.getId() + ")");
/*
* 1. Copy RE 2. Attach copy to a target specified in the Adaptation Point 3. Delete
* origin
*/
if (!(targets instanceof SetOfConfigurations))
throw new IllegalArgumentException(
"Migration could not be performed because no target specification found!");
EList<Entity> migrationTargets = ((SetOfConfigurations) targets).getVariants();
RuntimeEnvironment migratedEntity = (RuntimeEnvironment) adaptableEntity;
Container source = migratedEntity.getContainedIn();
// TODO Here you could implement something more sophisticated
// e.g., choose the container with the lowest util.
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) 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);
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 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);
}
}
private Entity randomTarget(EList<Entity> destinations, Entity source) {
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);
}
return destination;
}
private Entity scaleIn(Entity adaptableEntity) {
Entity result = null;
switch (adaptableEntity.eClass().getClassifierID()) {
case ResourcelandscapePackage.RUNTIME_ENVIRONMENT:
result = DmmModelChanger.scaleInRuntimeEnvironmentInstance((RuntimeEnvironment) adaptableEntity);
break;
case ContainerrepositoryPackage.CONTAINER_TEMPLATE:
// TODO: move to DmmModelChanger
result = scaleInContainerTemplate((ContainerTemplate) adaptableEntity);
break;
default:
throw new IllegalArgumentException("No implemented scale in operation for " + adaptableEntity);
}
return result;
}
private RuntimeEnvironment scaleOut(Entity adaptableEntity) {
RuntimeEnvironment re = null;
switch (adaptableEntity.eClass().getClassifierID()) {
case ResourcelandscapePackage.RUNTIME_ENVIRONMENT:
re = DmmModelChanger.createNewRuntimeEnvironmentInstance((RuntimeEnvironment) adaptableEntity);
break;
case ContainerrepositoryPackage.CONTAINER_TEMPLATE:
re = scaleOutContainerTemplate((ContainerTemplate) adaptableEntity);
break;
default:
throw new IllegalArgumentException("No implemented scale out operation for " + adaptableEntity);
}
return re;
}
private Entity scaleInContainerTemplate(ContainerTemplate template) {
Container referringContainer = template.getReferringContainers().get(0);
RuntimeEnvironment removedRe = null;
if (referringContainer != null && referringContainer instanceof RuntimeEnvironment) {
removedRe = DmmModelChanger.scaleInRuntimeEnvironmentInstance((RuntimeEnvironment) referringContainer);
} else {
logger.error("Cannot scale " + referringContainer);
}
if (removedRe != null)
template.getReferringContainers().remove(removedRe);
return removedRe;
}
/**
* Creates a new RuntimeEnvironment. If you want to scale an attribute of the ContainerTemplate,
* ModelVariableConfigurationRange must be used. However, here we are scaling a
* ModelEntityConfigurationRange.
*/
// this is just a helper function
private RuntimeEnvironment scaleOutContainerTemplate(ContainerTemplate template) {
if (template.getReferringContainers().size() == 0) {
logger.debug("No referring containers found for template " + template.getName()
+ ", creating new instance from template.");
return DmmModelChanger.createNewRuntimeEnvironmentInstanceFromTemplate(template);
} else {
Container referringContainer = template.getReferringContainers().get(0);
if (referringContainer != null && referringContainer instanceof RuntimeEnvironment) {
return DmmModelChanger.createNewRuntimeEnvironmentInstance((RuntimeEnvironment) referringContainer);
} else {
logger.error("Cannot scale " + referringContainer);
}
}
return null;
}
@Override
public void persistActions() {
saveModels();
}
// private boolean checkInvariants(EObject adaptableEntity, PropertyRange range) {
// OclEvaluationHelper evalHelper = new OclEvaluationHelper();
// boolean invariant = evalHelper.evaluate(adaptableEntity,
// range.getMinValueConstraint().getOclString());
//
// if (!invariant)
// logger.error("Invariant " + range.getMinValueConstraint().getOclString() + " violated");
//
// invariant &= evalHelper.evaluate(adaptableEntity,
// range.getMaxValueConstraint().getOclString());
//
// if (!invariant)
// logger.error("Invariant " + range.getMaxValueConstraint().getOclString() + " violated");
//
// return invariant;
// }
}
package edu.kit.ipd.descartes.adaptation.model.adaptation.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;
import edu.kit.ipd.descartes.mm.resourcelandscape.Container;
import edu.kit.ipd.descartes.mm.resourcelandscape.ResourcelandscapePackage;
import edu.kit.ipd.descartes.mm.resourcelandscape.RuntimeEnvironment;
public class DmmModelActionHelper {
/**
*
* @param aEntity
* @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
*
* @param candidates
* @param comparatorContainer
* @return
*/
public static List<Container> filterContainersWithSimilarSpecs(List<Container> candidates,
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)
&& EcoreUtil.equals(comparatorContainer.getConfigSpec(), c.getConfigSpec())
&& EcoreUtil.equals(comparatorContainer.getTemplate(), c.getTemplate())) {
resultList.add(c);
}
}
return resultList;
}
/**
* Query for a {@link RuntimeEnvironment} that has been copied (contains
* {@link DmmModelChanger.COPY_MARK}) and refers to the same ContainerTemplate.
*
* @param candidates
* @param comparatorRE
* @return
*/
public static RuntimeEnvironment filterCopiedRuntimeEnvironment(List<RuntimeEnvironment> candidates,
RuntimeEnvironment comparatorRE) {
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())
&& EcoreUtil.equals(comparatorRE.getTemplate(), re.getTemplate())) {
return re;
}
}
return null;
}
public static RuntimeEnvironment filterRuntimeEnvironment(List<RuntimeEnvironment> candidates,
RuntimeEnvironment comparatorRE) {
// Filter RE with copy mark first
RuntimeEnvironment reWithCopyMark = filterCopiedRuntimeEnvironment(candidates, comparatorRE);
if (reWithCopyMark != null) {
return reWithCopyMark;
} else {
// If there is no copy mark, filter an RE with different ID
for (RuntimeEnvironment re : candidates) {
if (re.getId() != comparatorRE.getId()
// && EcoreUtil.equals(comparatorRE.getConfigSpec(), re.getConfigSpec())
// && EcoreUtil.equals(comparatorRE.getContainedIn(), re.getContainedIn())
&& EcoreUtil.equals(comparatorRE.getTemplate(), re.getTemplate())) {
return re;
}
}
}
// If no matches have been found, return the comparator element
return comparatorRE;
}
public static NamedElement findEntityWithName(NamedElement element, String name) {
if (element.getName().equals(name))
return element;
else {
NamedElement result = null;
for (Iterator<EObject> iterator = element.eContents().iterator(); iterator.hasNext();) {
NamedElement nextElement = (NamedElement) iterator.next();
result = findEntityWithName(nextElement, name);
if (result != null)
return result;
}
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.
*
* @param c
* @return A list of Container instances
*/
public static List<Container> queryContainersWithSimilarSpecs(Container 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>.
*
* @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)
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)
return (RuntimeEnvironment) resultList.get(0);
else
return null;
}
/**
* Queries for all Container instances referring to the same ContainerTemplate as the given
* container.
*
* @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)";
String queryExpression = "RuntimeEnvironment.allInstances()->select( re | re.template = self.template)";
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();
resultList.add(temp);
}
return resultList;
}
/**
* 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)
result.add((RuntimeEnvironment) container);
}
return result;
}
/**
* Find a container that refers to the given {@link ContainerTemplate} and that suits the given
* {@link AdaptationScope}. This is the new target.
*
* @param containerTemplate
* @param adaptationScope
* @param targets
* @return
*/
public static Container findSuitableContainer(ContainerTemplate containerTemplate, AdaptationScope adaptationScope,
VariationType targets) {
// Get all containers referring to the template
List<Container> containers = containerTemplate.getReferringContainers();
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:
Random generator = new Random();
int next = generator.nextInt(containers.size());
return containers.get(next);
default:
return null;
}
}
}
return null;
}
/**
* 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;
}
}
package edu.kit.ipd.descartes.adaptation.model.adaptation.dmm.util;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import edu.kit.ipd.descartes.adaptation.model.adaptation.exceptions.OperationNotPerformedException;
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.AdaptationActionOperation;
import edu.kit.ipd.descartes.mm.adaptation.AdaptationDirection;
import edu.kit.ipd.descartes.mm.adaptation.AdaptationScope;
import edu.kit.ipd.descartes.mm.adaptationpoints.ModelVariableConfigurationRange;
import edu.kit.ipd.descartes.mm.containerrepository.ContainerTemplate;
import edu.kit.ipd.descartes.mm.resourceconfiguration.ConfigurationSpecification;
import edu.kit.ipd.descartes.mm.resourceconfiguration.NumberOfParallelProcessingUnits;
import edu.kit.ipd.descartes.mm.resourceconfiguration.ResourceconfigurationPackage;
import edu.kit.ipd.descartes.mm.resourcelandscape.Container;
import edu.kit.ipd.descartes.mm.resourcelandscape.ResourcelandscapeFactory;
import edu.kit.ipd.descartes.mm.resourcelandscape.RuntimeEnvironment;
import edu.kit.ipd.descartes.mm.runtimeenvironmentclasses.RuntimeEnvironmentClasses;
public class DmmModelChanger {
private static final int FIRST = 0;
/**
* Denotes a Container as a copy of another by
* adding this mark to its name.
*/
public static final String COPY_MARK = "-Copy";
static Logger logger = Logger.getLogger(DmmModelChanger.class);
/**
* Scales the actual number of a given model variable
*
* @param adaptedEntity
* @param operation
*/
public static void scaleModelVariable(ModelVariableConfigurationRange range, AdaptationDirection direction)
throws OperationNotPerformedException {
switch (range.getAdaptableEntity().eClass().getClassifierID()) {
case ResourceconfigurationPackage.NUMBER_OF_PARALLEL_PROCESSING_UNITS:
adaptNumberOfCores(range.getAdaptableEntity(), range, direction);
break;
default:
logger.error("SCALING THIS TYPE OF MODEL VARIABLE HAS NOT BEEN IMPLEMENTED YET!");
break;
}
}
private static void adaptNumberOfCores(AdaptableEntity adaptedEntity, ModelVariableConfigurationRange range,
AdaptationDirection direction) throws OperationNotPerformedException {
NumberOfParallelProcessingUnits adaptableModelEntity = (NumberOfParallelProcessingUnits) adaptedEntity;
Entity containingEntity = (Entity) adaptableModelEntity.getProcessingResourceSpec().getParentResourceSpecification().eContainer();
Integer currentValue = adaptableModelEntity.getNumber();
Integer maxValue = (int) Math.floor(range.getMaxValue());
Integer minValue = (int) Math.ceil(range.getMinValue());
if (direction == AdaptationDirection.INCREASE) {
// if current value less than max value
if (currentValue < maxValue) {
adaptableModelEntity.setNumber(currentValue + 1);
logger.info("Number of " + containingEntity.getName() + " (ID: " + containingEntity.getId() + ")" + " increased to "
+ (currentValue + 1) + ".");
} else
throw new OperationNotPerformedException("Adaptation operation " + direction.getLiteral()
+ " for adaptation point " + adaptedEntity.getName()
+ " could not be executed because the maximum has been reached");
} else if (direction == AdaptationDirection.DECREASE) {
// if current value greater than min value
if (currentValue > minValue) {
adaptableModelEntity.setNumber(currentValue - 1);
logger.info("Number of " + containingEntity.getName() + " (ID: " + containingEntity.getId() + ")" + " decreased to "
+ (currentValue - 1) + ".");
} else
throw new OperationNotPerformedException("Adaptation operation " + direction.getLiteral()
+ " for adaptation point " + adaptedEntity.getName()
+ " could not be executed because the minimum has been reached");
} else
logger.error("Adaptation direction " + direction.getLiteral() + " not defined for "
+ adaptedEntity.eClass());
}
/**
* Removes the given {@link RuntimeEnvironment} instance
*
* @param runtimeEnvironment
* the {@link RuntimeEnvironment} to remove
* @return
*/
public static RuntimeEnvironment scaleInRuntimeEnvironmentInstance(RuntimeEnvironment runtimeEnvironment) {
List<Container> similarContainers = DmmModelActionHelper.queryContainersWithSimilarTemplate(runtimeEnvironment);
List<RuntimeEnvironment> containedEntities = DmmModelActionHelper.filterAndConvertRuntimeEnvironment(similarContainers);
RuntimeEnvironment similarEntity = DmmModelActionHelper.filterRuntimeEnvironment(containedEntities, runtimeEnvironment);
if (similarEntity != null) {
runtimeEnvironment.getTemplate().getReferringContainers().remove(similarEntity);
similarEntity.getContainedIn().getContains().remove(similarEntity);
logger.info("RuntimeEnvironment " + similarEntity.getName() + " (ID: " + similarEntity.getId() + ") removed.");
} else
logger.error("Could not remove a runtime environment instance because no similar entity has been found.");
return (RuntimeEnvironment) similarEntity;
}
/**
* Creates a new {@link RuntimeEnvironment} instance
*
* @param runtimeEnvironment
* the {@link RuntimeEnvironment} to copy
* @return
*/
public static RuntimeEnvironment createNewRuntimeEnvironmentInstance(RuntimeEnvironment runtimeEnvironment) {
RuntimeEnvironment newRuntimeEnvironment = EcoreUtil.copy(runtimeEnvironment);
newRuntimeEnvironment.setId(EcoreUtil.generateUUID());
newRuntimeEnvironment.setName(newRuntimeEnvironment.getName() + COPY_MARK);
newRuntimeEnvironment.setTemplate(runtimeEnvironment.getTemplate());
runtimeEnvironment.getTemplate().getReferringContainers().add(newRuntimeEnvironment);
if (runtimeEnvironment.getConfigSpec().size() > 0) {
newRuntimeEnvironment.getConfigSpec().clear();
newRuntimeEnvironment.getConfigSpec().addAll(EcoreUtil.copyAll(runtimeEnvironment.getTemplate().getTemplateConfig()));
}
runtimeEnvironment.getContainedIn().getContains().add(newRuntimeEnvironment);
logger.debug("New RuntimeEnvironment " + newRuntimeEnvironment.getName() + " (ID: " +
newRuntimeEnvironment.getId() + ") to " +
newRuntimeEnvironment.getContainedIn().getName() + " (ID: " + newRuntimeEnvironment.getContainedIn().getId() + ") added." );
return newRuntimeEnvironment;
}
/**
* Scales either the model variable if AdaptationScope is set to ALL
* or scales a ModelEntity referring to <code>actuallyConfiguredInstance</code>
* according to the specified <code>operation</code>.
*
* @param actuallyConfiguredInstance
* @param range
* @param operation
* @throws OperationNotPerformedException
*/
public static void scaleContainerTemplate(ContainerTemplate actuallyConfiguredInstance, ModelVariableConfigurationRange range, AdaptationActionOperation operation) throws OperationNotPerformedException {
Container container = null;
AdaptationScope scope = operation.getAdaptationOperationScope();
AdaptationDirection direction = operation.getAdaptationOperationDirection();
if (operation.getAdaptationOperationScope() == AdaptationScope.ALL) {
switch (direction) {
case INCREASE : // falls SCALE_UP/DOWN -> ndere Template
scaleModelVariable(range, direction);
break;
case DECREASE : // falls SCALE_UP/DOWN -> ndere Template
scaleModelVariable(range, direction);
break;
default :
logger.error(scope.getLiteral() + ", " + direction.getLiteral() + " not defined for " + range.getAdaptableEntity().eClass());
break;
}
}
else {
switch (scope) {
case RANDOM:
// pick a random instance referring to this template and
// change its configuration
container = pickRandomReferringContainer(actuallyConfiguredInstance);
break;
case LEAST_UTILIZED_FIRST:
logger.error("NOT IMPLEMENTED YET");
break;
case MOST_UTILIZED_FIRST:
logger.error("NOT IMPLEMENTED YET");
break;
default:
logger.error("No adaptation operation defined for " + scope.getLiteral() + ", "
+ direction.getLiteral());
break;
}
if (container != null)
try {
scaleResourceProvidedByContainer(container, range, direction);
} catch (OperationNotPerformedException e) {
logger.error(container.getName() + " could not be adapted. Trying alternative containers.");
scaleResourcesOfAlternativeContainer(range, container, direction);
}
else
throw new OperationNotPerformedException("No adaptable container found.");
}
}
private static void scaleResourcesOfAlternativeContainer(ModelVariableConfigurationRange range, Container container,
AdaptationDirection direction) throws OperationNotPerformedException {
Container targetContainer = null;
switch (direction) {
case INCREASE:
targetContainer = DmmModelActionHelper.queryUnfilledRuntimeEnvironment((RuntimeEnvironment) container, range.getMaxValue());
break;
case DECREASE:
targetContainer = DmmModelActionHelper.queryNotEmptyRuntimeEnvironment((RuntimeEnvironment) container, range.getMinValue());
break;
default:
logger.error("No corresponding AdaptationDirection found for :" + range + ".");
break;
}
if (targetContainer == null) {
logger.error("No alternative container for adaptation found!");
throw new OperationNotPerformedException("No alternative container found. Scale operation not performed!");
} else {
scaleResourceProvidedByContainer(targetContainer, range, direction);
}
}
/**Scales the resource (capacity) provided by the container, e.g.,
* the number of virtual cores of a VM.
*
* @param container The container to be scaled
* @param range The min and max capacity
* @param direction Specifies if up- or down-scaling
* @throws OperationNotPerformedException
*/
public static void scaleResourceProvidedByContainer(Container container, ModelVariableConfigurationRange range,
AdaptationDirection direction) throws OperationNotPerformedException {
boolean copyWasCreated = false;
if (container.getConfigSpec().isEmpty()) // Better check if configSpecs are identical
{
copyTemplateSpecToConfigSpec(container);
copyWasCreated = true;
}
NamedElement changedElement = getRespectiveAdaptableConfigSpecElement(container, range);
if (changedElement != null && changedElement instanceof AdaptableEntity) {
AdaptableEntity adaptableEntity = (AdaptableEntity) changedElement;
try {
adaptNumberOfCores(adaptableEntity, range, direction);
// in case operation was not executed, e.g. because min was reached
} catch (OperationNotPerformedException e) {
//undo copy of config spec
if (copyWasCreated)
container.getConfigSpec().clear();
throw e;
}
}
// If template and configSpec are identical, remove config spec
if (EcoreUtil.equals(container.getConfigSpec(), container.getTemplate().getTemplateConfig()))
container.getConfigSpec().clear();
}
private static NamedElement getRespectiveAdaptableConfigSpecElement(Container container,
ModelVariableConfigurationRange range) {
NamedElement changedElement = null;
for (Iterator<ConfigurationSpecification> iterator = container.getConfigSpec().iterator(); iterator.hasNext();) {
ConfigurationSpecification configurationSpecification = (ConfigurationSpecification) iterator.next();
changedElement = DmmModelActionHelper.findEntityWithName(configurationSpecification, range
.getAdaptableEntity().getName());
if (!changedElement.equals(null))
break;
}
return changedElement;
}
private static void copyTemplateSpecToConfigSpec(Container container) {
Collection<ConfigurationSpecification> copiedList = EcoreUtil.copyAll(container.getTemplate()
.getTemplateConfig());
container.getConfigSpec().addAll(copiedList);
}
private static Container pickRandomReferringContainer(ContainerTemplate template) {
Random randomGenerator = new Random();
EList<Container> containers = template.getReferringContainers();
int index = randomGenerator.nextInt(containers.size());
return containers.get(index);
}
public static RuntimeEnvironment createNewRuntimeEnvironmentInstanceFromTemplate(ContainerTemplate template) {
RuntimeEnvironment newRe = ResourcelandscapeFactory.eINSTANCE.createRuntimeEnvironment();
newRe.setId(EcoreUtil.generateUUID());
newRe.setName("RuntimeEnvironmentInstanceOfTemplate_" + template.getName());
newRe.setTemplate(template);
newRe.setOfClass(RuntimeEnvironmentClasses.MIDDLEWARE);
newRe.setContainedIn(template.getRunningOn().get(FIRST));
template.getReferringContainers().add(newRe);
return newRe;
}
}
package edu.kit.ipd.descartes.adaptation.model.adaptation.dmm.util;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import edu.kit.ipd.descartes.mm.adaptation.Event;
import edu.kit.ipd.descartes.mm.adaptation.RelationalOperator;
import edu.kit.ipd.descartes.mm.adaptation.Specification;
import edu.kit.ipd.descartes.perfdatarepo.MetricType;
import edu.kit.ipd.descartes.perfdatarepo.MetricValue;
import edu.kit.ipd.descartes.perfdatarepo.Result;
public class ObjectivesHelper {
public static boolean compare(double left, double right, RelationalOperator operator) {
switch (operator) {
case EQUAL:
return left == right;
case NOT_EQUAL:
return left != right;
case LESS:
return left < right;
case LESS_EQUAL:
return left <= right;
case GREATER:
return left > right;
case GREATER_EQUAL:
return left >= right;
default:
return false;
}
}
public static boolean isObjectiveFulfilled(Event event, Result result) {
List<Specification> specs = event.getTriggers().getObjective().getSpecifications();
for (Specification specification : specs) {
MetricType m = specification.getMetricType();
// TODO: Connect QueryEngine: Double actualValue = QueryEngineAdapter.getValueForMetricType(m);
Double actualValue = getValueForMetricType(m, result);
Double threshold = specification.getValue();
if (!ObjectivesHelper.compare(actualValue, threshold, specification.getRelationalOperator()))
return false;
}
return true;
}
private static double getValueForMetricType(MetricType metricType, Result result) {
EList<MetricValue> metricValues = result.getMetricValues();
for (MetricValue metricValue : metricValues) {
if (sameMetricType(metricValue, metricType))
return metricValue.getValue();
}
return Double.NaN;
}
private static boolean sameMetricType(MetricValue metricValue, MetricType metricType) {
// return metricValue.getMetricType().equals(metricType);
return (metricValue.getMetricType().getName().equals(metricType.getName()));
// && metricValue.getMetricType().getId().equals(metricType.getId()));
}
}
package edu.kit.ipd.descartes.adaptation.model.adaptation.dmm.util;
import java.util.Set;
import org.apache.log4j.Logger;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.ocl.OCL;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.Query;
import org.eclipse.ocl.ecore.Constraint;
import org.eclipse.ocl.ecore.EcoreEnvironmentFactory;
import org.eclipse.ocl.expressions.OCLExpression;
import org.eclipse.ocl.helper.OCLHelper;
/**
* @author nhuber
*
*/
public class OclEvaluationHelper {
private static Logger logger = Logger.getLogger(OclEvaluationHelper.class);
/**
* @param checkedObject the checked object
* @param constraint the constraint to evaluate on the object
* @param context the {@link EClass} of the given object
* @return
* {@code true} if check was successful
*/
public static boolean evaluateOclConstraint(EObject checkedObject, String constraint, EClass context) {
Constraint invariant = null;
OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl;
ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);
OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper();
helper.setContext(context);
try {
invariant = helper.createInvariant(constraint);
} catch (ParserException e) {
logger.error("Error parsing OCL string '" + constraint + "'", e);
return false;
}
Query<EClassifier, EClass, EObject> eval = ocl.createQuery(invariant);
return eval.check(checkedObject);
}
/**
* Executes the query on a given object.
*
* @param obj the model instance the query is executed on
* @param queryExpression the OCL query
* @param context the eClass of the model instance
* @return
*/
public static Set<EObject> query(EObject obj, String queryExpression, EClassifier context) {
OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl;
ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);
OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper();
helper.setContext(context);
OCLExpression<EClassifier> query;
try {
query = helper.createQuery(queryExpression);
} catch (ParserException e) {
logger.error("Error parsing OCL query '" + queryExpression + "'", e);
return null;
}
// create a Query to evaluate our query expression
Query<EClassifier, EClass, EObject> queryEval = ocl.createQuery(query);
Object result = queryEval.evaluate(obj);
if (result.toString().contains("invalid"))
return null;
@SuppressWarnings("unchecked")
Set<EObject> resultList = (Set<EObject>) result;
return resultList;
}
}
package edu.kit.ipd.descartes.adaptation.model.adaptation.exceptions;
public class InvalidAdaptationPlan extends Exception {
public InvalidAdaptationPlan(String message) {
super(message);
}
/**
*
*/
private static final long serialVersionUID = 963013704332157870L;
}
package edu.kit.ipd.descartes.adaptation.model.adaptation.exceptions;
public class OperationNotPerformedException extends Exception {
public OperationNotPerformedException(String message) {
super(message);
}
/**
*
*/
private static final long serialVersionUID = 7144698514945329908L;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment