Skip to content

Commit

Permalink
Ensure services are executed after their requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
FloBoJa committed Nov 20, 2023
1 parent bc777fa commit 602f60b
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.palladiosimulator.somox.analyzer.rules.engine;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
Expand Down Expand Up @@ -106,30 +108,49 @@ public Set<T> getSelected() {
return Collections.unmodifiableSet(selectedServices);
}

public List<T> getSelectedOrdered() {
List<T> orderedServices = new LinkedList<>();
Queue<T> selectedServices = new ArrayDeque<>(getSelected());
List<T> dependingServices = new LinkedList<>();
while (!selectedServices.isEmpty()) {
T candidate = selectedServices.poll();
if (isNotDependingOnAny(candidate, selectedServices) && isNotDependingOnAny(candidate, dependingServices)) {
orderedServices.add(candidate);

selectedServices.addAll(dependingServices);
dependingServices.clear();
public Queue<Collection<T>> getExecutionOrder() {
List<Collection<T>> executionOrder = new ArrayList<>();
Queue<T> remainingServices = new ArrayDeque<>(getSelected());
List<T> requiringServices = new LinkedList<>();
while (!remainingServices.isEmpty()) {
T candidate = remainingServices.poll();
if (isRequiringAny(candidate, remainingServices) || isRequiringAny(candidate, requiringServices)) {
requiringServices.add(candidate);
} else {
dependingServices.add(candidate);
addAfterRequirements(candidate, executionOrder);

remainingServices.addAll(requiringServices);
requiringServices.clear();
}
}
if (!dependingServices.isEmpty()) {
if (!requiringServices.isEmpty()) {
throw new IllegalStateException("Dependency cycle in services, no possible execution order.");
}
return orderedServices;
return new ArrayDeque<>(executionOrder);
}

private boolean isNotDependingOnAny(T service, Collection<T> services) {
private void addAfterRequirements(T service, List<Collection<T>> executionOrder) {
if (executionOrder.isEmpty() || isRequiringAny(service, executionOrder.get(executionOrder.size() - 1))) {
Collection<T> newStep = new ArrayList<>();
newStep.add(service);
executionOrder.add(newStep);
return;
}

Collection<T> earliestCandidate = executionOrder.get(executionOrder.size() - 1);
for (int i = executionOrder.size() - 2; i >= 0; i--) {
Collection<T> currentStep = executionOrder.get(i);
if (isRequiringAny(service, currentStep)) {
break;
}
earliestCandidate = currentStep;
}
earliestCandidate.add(service);
}

private boolean isRequiringAny(T service, Collection<T> services) {
Set<String> dependencies = service.getRequiredServices();
return !services.stream().map(Service::getID).anyMatch(dependencies::contains);
return services.stream().map(Service::getID).anyMatch(dependencies::contains);
}

public Collection<T> getAvailable() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package org.palladiosimulator.somox.analyzer.rules.workflow;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.palladiosimulator.somox.analyzer.rules.blackboard.RuleEngineBlackboard;
import org.palladiosimulator.somox.analyzer.rules.configuration.RuleEngineBlackboardKeys;
import org.palladiosimulator.somox.analyzer.rules.engine.Rule;
Expand All @@ -18,15 +22,15 @@ public class RuleEngineJob extends AbstractExtendableJob<RuleEngineBlackboard> {
public RuleEngineJob(RuleEngineConfiguration configuration) {
super.setBlackboard(new RuleEngineBlackboard());

super.add(createDiscoverersJob(configuration));
super.addAll(createDiscovererJobs(configuration));

super.add(createRulesJob(configuration));
super.addAll(createRuleJobs(configuration));

super.add(createBuildRulesJob(configuration));
super.addAll(createBuildRulesJob(configuration));

super.add(new RuleEngineBlackboardInteractingJob(configuration, getBlackboard()));

super.add(createAnalystsJob(configuration));
super.addAll(createAnalystJobs(configuration));

// Generate service effect specifications based on AST nodes and merge them into repository
super.add(
Expand Down Expand Up @@ -57,57 +61,75 @@ public RuleEngineJob(RuleEngineConfiguration configuration) {
super.add(new PlantUmlJob(configuration, getBlackboard()));
}

private ParallelJob createRulesJob(RuleEngineConfiguration configuration) {
ParallelJob parentJob = new ParallelJob();

for (Rule rule : configuration.getConfig(Rule.class)
.getSelectedOrdered()) {
// Assume only build rules depend on build rules.
if (!rule.isBuildRule()) {
private List<ParallelJob> createRuleJobs(RuleEngineConfiguration configuration) {
List<ParallelJob> jobs = new ArrayList<>();

for (Collection<Rule> step : configuration.getConfig(Rule.class).getExecutionOrder()) {
ParallelJob parentJob = new ParallelJob();
for (Rule rule : step) {
// Assume only build rules depend on build rules.
if (rule.isBuildRule()) {
continue;
}
IBlackboardInteractingJob<RuleEngineBlackboard> ruleJob = rule.create(configuration, myBlackboard);
parentJob.add(ruleJob);
logger.info("Adding rule job \"" + ruleJob.getName() + "\"");
}
jobs.add(parentJob);
}

return parentJob;
return jobs;
}

private ParallelJob createBuildRulesJob(RuleEngineConfiguration configuration) {
ParallelJob parentJob = new ParallelJob();

for (Rule rule : configuration.getConfig(Rule.class)
.getSelectedOrdered()) {
if (rule.isBuildRule()) {
private List<ParallelJob> createBuildRulesJob(RuleEngineConfiguration configuration) {
List<ParallelJob> jobs = new ArrayList<>();

for (Collection<Rule> step : configuration.getConfig(Rule.class).getExecutionOrder()) {
ParallelJob parentJob = new ParallelJob();
for (Rule rule : step) {
// Assume only build rules depend on build rules.
if (!rule.isBuildRule()) {
continue;
}
IBlackboardInteractingJob<RuleEngineBlackboard> ruleJob = rule.create(configuration, myBlackboard);
parentJob.add(ruleJob);
logger.info("Adding build rule job \"" + ruleJob.getName() + "\"");
}
jobs.add(parentJob);
}

return parentJob;
return jobs;
}

private ParallelJob createDiscoverersJob(RuleEngineConfiguration configuration) {
ParallelJob parentJob = new ParallelJob();
for (Discoverer discoverer : configuration.getConfig(Discoverer.class)
.getSelected()) {
IBlackboardInteractingJob<RuleEngineBlackboard> discovererJob = discoverer.create(configuration,
myBlackboard);
parentJob.add(discovererJob);
logger.info("Adding discoverer job \"" + discovererJob.getName() + "\"");
private List<ParallelJob> createDiscovererJobs(RuleEngineConfiguration configuration) {
List<ParallelJob> jobs = new ArrayList<>();

for (Collection<Discoverer> step : configuration.getConfig(Discoverer.class).getExecutionOrder()) {
ParallelJob parentJob = new ParallelJob();
for (Discoverer discoverer : step) {
IBlackboardInteractingJob<RuleEngineBlackboard> discovererJob = discoverer.create(configuration, myBlackboard);
parentJob.add(discovererJob);
logger.info("Adding discoverer job \"" + discovererJob.getName() + "\"");
}
jobs.add(parentJob);
}
return parentJob;

return jobs;
}

private ParallelJob createAnalystsJob(RuleEngineConfiguration configuration) {
ParallelJob parentJob = new ParallelJob();
for (Analyst analyst : configuration.getConfig(Analyst.class)
.getSelected()) {
IBlackboardInteractingJob<RuleEngineBlackboard> analystJob = analyst.create(configuration, myBlackboard);
parentJob.add(analystJob);
logger.info("Adding analyst job \"" + analystJob.getName() + "\"");
private List<ParallelJob> createAnalystJobs(RuleEngineConfiguration configuration) {
List<ParallelJob> jobs = new ArrayList<>();

for (Collection<Analyst> step : configuration.getConfig(Analyst.class).getExecutionOrder()) {
ParallelJob parentJob = new ParallelJob();
for (Analyst analyst : step) {
IBlackboardInteractingJob<RuleEngineBlackboard> analystJob = analyst.create(configuration, myBlackboard);
parentJob.add(analystJob);
logger.info("Adding analyst job \"" + analystJob.getName() + "\"");
}
jobs.add(parentJob);
}
return parentJob;

return jobs;
}
}

0 comments on commit 602f60b

Please sign in to comment.