Skip to content
Snippets Groups Projects
Commit 3c01945f authored by Simon Spinner's avatar Simon Spinner
Browse files

Extended version of WorkloadDescriptionDerivation.

parent 4597c448
No related branches found
No related tags found
No related merge requests found
package tools.descartes.prisma.parameterization;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
......@@ -7,244 +8,274 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import org.apache.log4j.Logger;
import javax.security.auth.login.Configuration;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import org.apache.log4j.Logger;
import edu.kit.ipd.descartes.mm.applicationlevel.parameterdependencies.ModelVariableCharacterizationType;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.AssemblyConnector;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.AssemblyContext;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.BasicComponent;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.ComposedStructure;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.CompositeComponent;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.InterfaceProvidingRole;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.Parameter;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.InterfaceRequiringRole;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.ProvidingDelegationConnector;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.RepositoryComponent;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.RequiringDelegationConnector;
import edu.kit.ipd.descartes.mm.applicationlevel.repository.Signature;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.AbstractAction;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.BranchAction;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.CoarseGrainedBehavior;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.ComponentInternalBehavior;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.ExternalCallAction;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.FineGrainedBehavior;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.ForkAction;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.InternalAction;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.LoopAction;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.ResourceDemand;
import edu.kit.ipd.descartes.mm.applicationlevel.servicebehavior.util.ServicebehaviorSwitch;
import edu.kit.ipd.descartes.mm.applicationlevel.system.System;
import edu.kit.ipd.descartes.mm.deployment.Deployment;
import edu.kit.ipd.descartes.mm.deployment.DeploymentContext;
import edu.kit.ipd.descartes.mm.resourceconfiguration.ActiveResourceSpecification;
import edu.kit.ipd.descartes.mm.resourceconfiguration.ConfigurationSpecification;
import edu.kit.ipd.descartes.mm.resourceconfiguration.ProcessingResourceSpecification;
import edu.kit.ipd.descartes.mm.resourceconfiguration.SchedulingPolicy;
import edu.kit.ipd.descartes.mm.resourcelandscape.CompositeHardwareInfrastructure;
import edu.kit.ipd.descartes.mm.resourcelandscape.ComputingInfrastructure;
import edu.kit.ipd.descartes.mm.resourcelandscape.Container;
import edu.kit.ipd.descartes.mm.resourcelandscape.DataCenter;
import edu.kit.ipd.descartes.mm.resourcelandscape.HardwareInfrastructure;
import edu.kit.ipd.descartes.mm.resourcetype.ProcessingResourceType;
import edu.kit.ipd.descartes.mm.resourcetype.ResourceType;
import tools.descartes.librede.configuration.ConfigurationFactory;
import tools.descartes.librede.configuration.ExternalCall;
import tools.descartes.librede.configuration.ModelEntity;
import tools.descartes.librede.configuration.Resource;
import tools.descartes.librede.configuration.SchedulingStrategy;
import tools.descartes.librede.configuration.Service;
import tools.descartes.librede.configuration.WorkloadDescription;
public class WorkloadDescriptionDerivation {
private static final Logger log = Logger.getLogger(WorkloadDescriptionDerivation.class);
// a set of all visited containers for which resources have already been analysed.
// the containers are identified by their id.
private Table<String, ProcessingResourceType, Resource> resources = HashBasedTable.create();
private Map<String, Service> services = new HashMap<>();
private Table<Service, Resource, List<ResourceDemand>> demands = HashBasedTable.create();
public WorkloadDescription deriveWorkloadDescription(Deployment deployment) {
// Set of all fully analyzed services
private final Set<Service> completeServices = new HashSet<>();
private MappingModel mapping = new MappingModel();
private Map<AssemblyContext, Container> deploymentMapping = new HashMap<>();
private Resource delayResource = null;
WorkloadDescription workload = ConfigurationFactory.eINSTANCE.createWorkloadDescription();
public MappingModel getMapping() {
return mapping;
}
public void updateWorkloadDescription(Deployment deployment) {
mapping.reset();
completeServices.clear();
deploymentMapping.clear();
for (DataCenter dc : deployment.getTargetResourceLandscape().getConsistsOf()) {
for (HardwareInfrastructure hw : dc.getContains()) {
visitHardwareInfrastructure(hw);
}
for (DeploymentContext depCtx : deployment.getDeploymentContexts()) {
deploymentMapping.put(depCtx.getAssemblyContext(), depCtx.getResourceContainer());
}
for (DeploymentContext ctx : deployment.getDeploymentContexts()) {
// TODO: consider also assembly context and deployment context structure to distingiush services?
RepositoryComponent component = ctx.getAssemblyContext().getEncapsulatedComponent();
determineServicesOfComponent(ctx.getResourceContainer(), component);
Stack<ComposedStructure> callStack = new Stack<ComposedStructure>();
System system = deployment.getSystem();
callStack.push(system);
for (AssemblyContext ctx : system.getAssemblyContexts()) {
Container deploymentTarget = deploymentMapping.get(ctx);
if (deploymentTarget != null) {
visitAssemblyContext(callStack, deploymentTarget, ctx);
} else {
log.warn("Assembly context " + ctx.getName() + " is not deployed on any container.");
}
}
workload.getResources().addAll(resources.values());
workload.getServices().addAll(services.values());
return workload;
// Remove all empty services
List<Service> nonemptyServices = new LinkedList<>();
for (Service curService : completeServices) {
if (curService.getTasks().isEmpty()) {
List<ExternalCall> calls = new ArrayList<>(curService.getIncomingCalls());
for (ExternalCall curCall : calls) {
curCall.getService().getTasks().remove(curCall);
mapping.unmapExternalCall(curCall);
}
mapping.unmapService(curService);
} else {
nonemptyServices.add(curService);
}
}
addDelayResource();
mapping.removeUnmappedEntites();
}
private void visitHardwareInfrastructure(HardwareInfrastructure hw) {
if (hw instanceof CompositeHardwareInfrastructure) {
CompositeHardwareInfrastructure castedHw = (CompositeHardwareInfrastructure)hw;
for (HardwareInfrastructure child : castedHw.getContains()) {
visitHardwareInfrastructure(child);
private void addDelayResource() {
if (delayResource == null) {
delayResource = ConfigurationFactory.eINSTANCE.createResource();
delayResource.setName("Delay");
delayResource.setSchedulingStrategy(SchedulingStrategy.IS);
delayResource.setNumberOfServers(1);
mapping.getWorkload().getResources().add(delayResource);
}
for (ModelEntity curEntity : mapping.getNewEntities()) {
if (curEntity instanceof Service) {
Service curService = (Service)curEntity;
if (curService.getIncomingCalls().isEmpty()) {
tools.descartes.librede.configuration.ResourceDemand delayDemand = ConfigurationFactory.eINSTANCE.createResourceDemand();
delayDemand.setName("Delay");
delayDemand.setResource(delayResource);
curService.getTasks().add(delayDemand);
}
}
} else if (hw instanceof Container) {
visitContainer((Container)hw);
}
}
private void visitContainer(Container container) {
// find all processing resources
for (ConfigurationSpecification spec : container.getConfigSpec()) {
if (spec instanceof ActiveResourceSpecification) {
ActiveResourceSpecification activeResources = ((ActiveResourceSpecification) spec);
for (ProcessingResourceSpecification procRes : activeResources.getProcessingResourceSpecifications()) {
Resource res = ConfigurationFactory.eINSTANCE.createResource();
res.setName(procRes.getId());
res.setNumberOfServers(procRes.getNrOfParProcUnits().getNumber());
res.setSchedulingStrategy(convertSchedulingStrategy(procRes.getSchedulingPolicy()));
Resource old = resources.put(container.getId(), procRes.getActiveResourceType(), res);
if (old != null) {
log.warn("Multiple resources of type " + procRes.getActiveResourceType().getName() + " available for container " + container.getName());
}
}
private void visitAssemblyContext(Stack<ComposedStructure> callStack, Container deploymentTarget, AssemblyContext assembly) {
RepositoryComponent component = assembly.getEncapsulatedComponent();
for (InterfaceProvidingRole role : assembly.getEncapsulatedComponent().getInterfaceProvidingRoles()) {
for (Signature sig : role.getInterface().getSignatures()) {
determineTasks(callStack, deploymentTarget, assembly, component, role, sig);
}
}
// visit all child containers.
for (Container child : container.getContains()) {
visitContainer(child);
}
}
private void determineServicesOfComponent(Container container, RepositoryComponent component) {
// TODO: also consider composite components
if (!(component instanceof BasicComponent)) {
throw new IllegalArgumentException("Only BasicComponent is currently supported");
}
BasicComponent casted = (BasicComponent)component;
for (CoarseGrainedBehavior coarse : casted.getCoarseGrainedBehavior()) {
// in a coarse grained behavior, each resource type should be used only once
Set<ResourceType> visitedTypes = new HashSet<ResourceType>();
Signature signature = coarse.getDescribedSignature();
for (ResourceDemand demand : coarse.getResourceDemand()) {
if (demand.getResourceType() instanceof ProcessingResourceType) {
if (visitedTypes.contains(demand.getResourceType())) {
throw new IllegalStateException("Multiple demands for the same resource type specificed.");
}
visitedTypes.add(demand.getResourceType());
private void determineTasks(Stack<ComposedStructure> callStack, Container deploymentTarget, AssemblyContext assembly, RepositoryComponent component, InterfaceProvidingRole role, Signature sig) {
if (component instanceof CompositeComponent) {
CompositeComponent composite = (CompositeComponent)component;
ProvidingDelegationConnector con = getDelegationConnector(composite, role);
if (con != null) {
RepositoryComponent inner = (RepositoryComponent)con.getInnerInterfaceProvidingRole().getInterfaceProvidingEntity();
callStack.push(composite);
determineTasks(callStack, deploymentTarget, con.getAssemblyContext(), inner, con.getInnerInterfaceProvidingRole(), sig);
callStack.pop();
} else {
log.warn("No providing delegation connector found for role " + role.getName());
}
} else if (component instanceof RepositoryComponent) {
BasicComponent implementation = (BasicComponent)component;
FineGrainedBehavior behavior = getImplementationBehavior(implementation, role, sig);
if (behavior != null) {
Service service = mapping.mapService(assembly, sig, deploymentTarget);
if (!completeServices.contains(service)) {
visitComponentInternalBehavior(service, callStack, deploymentTarget, assembly, sig, behavior.getBehavior(), "");
completeServices.add(service);
Resource accessedResource = getResource(container, (ProcessingResourceType)demand.getResourceType());
Service curService = getService(signature, "");
addResourceDemand(curService, accessedResource, demand);
if (service.getName().startsWith("specj-mfg/specj-mfg/WorkOrderSession#org.spec.jent.ejb.mfg.session.WorkOrderService")) {
// WORKAROUND: for specjent
// The WorkOrderService interface is called internally and externally
// Introduce an additional component to mark it as a system interface
Service proxyService = mapping.mapService("Proxy:" + service.getName(), assembly, sig, deploymentTarget);
if (proxyService.getTasks().isEmpty()) {
ExternalCall call = ConfigurationFactory.eINSTANCE.createExternalCall();
call.setCalledService(service);
call.setName(service.getName());
proxyService.getTasks().add(call);
}
}
}
} else {
log.warn("No fine-grained behavior found for component " + component.getName());
}
}
for (FineGrainedBehavior fine : casted.getFineGrainedBehavior()) {
Signature signature = fine.getDescribedSignature();
visitComponentInternalBehavior(signature, container, fine.getBehavior(), "");
}
private FineGrainedBehavior getImplementationBehavior(BasicComponent component, InterfaceProvidingRole role, Signature sig) {
for (FineGrainedBehavior currentBehavior : component.getFineGrainedBehavior()) {
if (currentBehavior.getInterfaceProvidingRole().equals(role)
&& currentBehavior.getDescribedSignature().equals(sig)) {
return currentBehavior;
}
}
return null;
}
private void visitComponentInternalBehavior(Signature signature, Container container, ComponentInternalBehavior behavior, String path) {
private ProvidingDelegationConnector getDelegationConnector(CompositeComponent composite, InterfaceProvidingRole role) {
for (ProvidingDelegationConnector connector : composite.getProvidingDelegationConnectors()) {
if (connector.getOuterInterfaceProvidingRole().equals(role)) {
return connector;
}
}
return null;
}
private void visitComponentInternalBehavior(Service service, Stack<ComposedStructure> callStack, Container deploymentTarget, AssemblyContext assembly, Signature signature, ComponentInternalBehavior behavior, String path) {
int i = 0;
path = path + "/actions.";
for (AbstractAction action : behavior.getActions()) {
if (action instanceof ForkAction) {
forEachComponentInternalBehavior(signature, container, ((ForkAction) action).getForkedBehaviors(), path + i +"/forkedBehaviors");
// Only consider threads for which we will wait for completion
// Other types of threads do not influence the response time behavior of the current service.
if (((ForkAction)action).isWithSynchronizationBarrier()) {
forEachComponentInternalBehavior(service, callStack, deploymentTarget, assembly, signature, ((ForkAction) action).getForkedBehaviors(), path + i +"/forkedBehaviors");
}
} else if (action instanceof BranchAction) {
forEachComponentInternalBehavior(signature, container, ((BranchAction) action).getBranches(), path + i + "/branches");
forEachComponentInternalBehavior(service, callStack, deploymentTarget, assembly, signature, ((BranchAction) action).getBranches(), path + i + "/branches");
} else if (action instanceof LoopAction) {
forEachComponentInternalBehavior(signature, container, Collections.singletonList(((LoopAction) action).getLoopBodyBehavior()), path + i + "/loopBodyBehavior");
forEachComponentInternalBehavior(service, callStack, deploymentTarget, assembly, signature, Collections.singletonList(((LoopAction) action).getLoopBodyBehavior()), path + i + "/loopBodyBehavior");
} else if (action instanceof InternalAction) {
visitInternalAction(signature, container, (InternalAction)action, path + i);
visitInternalAction(service, deploymentTarget, assembly, signature, (InternalAction)action, path + i);
} else if (action instanceof ExternalCallAction) {
visitExternalCallAction(service, callStack, (ExternalCallAction) action);
}
i++;
}
}
private void forEachComponentInternalBehavior(Signature signature, Container container, List<ComponentInternalBehavior> behaviors, String path) {
private void forEachComponentInternalBehavior(Service service, Stack<ComposedStructure> callStack, Container deploymentTarget, AssemblyContext assembly, Signature signature, List<ComponentInternalBehavior> behaviors, String path) {
int j = 0;
for (ComponentInternalBehavior b : behaviors) {
visitComponentInternalBehavior(signature, container, b, path + path + "." + j);
visitComponentInternalBehavior(service, callStack, deploymentTarget, assembly, signature, b, path + path + "." + j);
j++;
}
}
private void visitInternalAction(Signature signature, Container container, InternalAction action, String path) {
for (ResourceDemand demand : action.getResourceDemand()) {
if (demand.getResourceType() instanceof ProcessingResourceType) {
Resource accessedResource = getResource(container, (ProcessingResourceType)demand.getResourceType());
// TODO: add service hierarchy?
Service curService = getService(signature, path);
addResourceDemand(curService, accessedResource, demand);
}
}
}
private Resource getResource(Container container, ProcessingResourceType resourceType) {
Resource accessedResource = resources.get(container.getId(), resourceType);
if (accessedResource == null) {
throw new IllegalStateException("Unknown resource.");
}
return accessedResource;
}
private void addResourceDemand(Service service, Resource resource, ResourceDemand demand) {
List<ResourceDemand> vars = demands.get(service, resource);
if (vars == null) {
//IMPORTANT: only register the service once with the resource.
resource.getServices().add(service);
vars = new LinkedList<>();
demands.put(service, resource, vars);
private void visitExternalCallAction(Service service, Stack<ComposedStructure> callStack, ExternalCallAction action) {
InterfaceRequiringRole requiringRole = action.getExternalCall().getInterfaceRequiringRole();
AssemblyContext providingCtx = getCalledAssemblyContext(callStack, requiringRole);
Container targetContainer = deploymentMapping.get(providingCtx);
if (providingCtx != null) {
Service calledService = mapping.mapService(providingCtx, action.getExternalCall().getSignature(), targetContainer);
// Recursive calls are currently not supported.
if (!calledService.equals(service)) {
mapping.mapExternalCall(service, calledService, action.getExternalCall());
}
} else {
log.warn("No providing assembly context found for requiring role " + requiringRole.getName());
}
vars.add(demand);
}
private Service getService(Signature curSignature, String action) {
String serviceName = createServiceName(curSignature, action);
Service curService = services.get(serviceName);
if (curService == null) {
curService = ConfigurationFactory.eINSTANCE.createService();
curService.setName(serviceName);
curService.setBackgroundService(false);
services.put(serviceName, curService);
private AssemblyContext getCalledAssemblyContext(Stack<ComposedStructure> callStack, InterfaceRequiringRole requiringRole) {
ComposedStructure parent = callStack.peek();
for (AssemblyConnector connector : parent.getAssemblyConnectors()) {
if (connector.getInterfaceRequiringRole().equals(requiringRole)) {
return connector.getProvidingAssemblyContext();
}
}
return curService;
}
private SchedulingStrategy convertSchedulingStrategy(SchedulingPolicy policy) {
switch(policy) {
case DELAY:
return SchedulingStrategy.IS;
case FCFS:
return SchedulingStrategy.FCFS;
case PROCESSOR_SHARING:
return SchedulingStrategy.PS;
case RANDOM:
case NA:
default:
return SchedulingStrategy.UNKOWN;
for (RequiringDelegationConnector connector : parent.getRequiringDelegationConnectors()) {
if (connector.getInnerInterfaceRequiringRole().equals(requiringRole)) {
// We have to go up one level in the callstack to determine the called component
callStack.pop();
AssemblyContext providingCtx = getCalledAssemblyContext(callStack, connector.getOuterInterfaceRequiringRole());
// Restore call stack
callStack.push(parent);
return providingCtx;
}
}
return null;
}
private String createServiceName(Signature signature, String action) {
StringBuilder name = new StringBuilder();
name.append(signature.getInterface().getName());
name.append("#");
name.append(signature.getName());
name.append("(");
boolean first = true;
for (Parameter param : signature.getParameters()) {
if (!first) {
name.append(",");
private void visitInternalAction(Service parent, Container deploymentTarget, AssemblyContext assembly, Signature signature, InternalAction action, String path) {
for (ResourceDemand demand : action.getResourceDemand()) {
if (demand.getCharacterization() == ModelVariableCharacterizationType.EMPIRICAL) {
if (demand.getResourceType() instanceof ProcessingResourceType) {
Resource curResource = mapping.mapResource(deploymentTarget, demand.getResourceType());
if (curResource == null) {
log.warn("No processing resource of type " + demand.getResourceType() + " found in container " + deploymentTarget.getName() + ".");
continue;
}
Service curService = mapping.mapService(assembly, signature, deploymentTarget);
mapping.mapResourceDemand(curResource, curService, demand);
}
}
name.append(param.getDataType());
first = false;
}
name.append(")");
if (!action.isEmpty()) {
name.append(":");
name.append(action);
}
return name.toString();
}
}
}
\ No newline at end of file
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