
org.btrplace.scheduler.choco.constraint.CSplitAmong Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scheduler-choco Show documentation
Show all versions of scheduler-choco Show documentation
Implementation of the VM scheduler that use
the Constraint Programming solver CHOCO to compute solutions.
The newest version!
/*
* Copyright 2021 The BtrPlace Authors. All rights reserved.
* Use of this source code is governed by a LGPL-style
* license that can be found in the LICENSE.txt file.
*/
package org.btrplace.scheduler.choco.constraint;
import org.btrplace.model.Instance;
import org.btrplace.model.Mapping;
import org.btrplace.model.Node;
import org.btrplace.model.VM;
import org.btrplace.model.constraint.Among;
import org.btrplace.model.constraint.SplitAmong;
import org.btrplace.scheduler.SchedulerException;
import org.btrplace.scheduler.choco.Parameters;
import org.btrplace.scheduler.choco.ReconfigurationProblem;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.variables.IntVar;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Choco implementation of the {@link org.btrplace.model.constraint.SplitAmong} constraint.
*
* @author Fabien Hermenier
*/
public class CSplitAmong implements ChocoConstraint {
private final SplitAmong cstr;
/**
* Make a new constraint.
*
* @param s the constraint to rely on
*/
public CSplitAmong(SplitAmong s) {
this.cstr = s;
}
@Override
public boolean inject(Parameters ps, ReconfigurationProblem rp) throws SchedulerException {
if (cstr.isContinuous() && !cstr.isSatisfied(rp.getSourceModel())) {
rp.getLogger().debug("The constraint '{}' must be already satisfied to provide a continuous restriction", cstr);
return false;
}
Collection> vGroups = cstr.getGroupsOfVMs();
Collection> pGroups = cstr.getGroupsOfNodes();
Model csp = rp.getModel();
IntVar[] grpVars = new IntVar[vGroups.size()];
//VM is assigned on a node <-> group variable associated to the VM
//is assigned to the group of nodes it belong too.
int i = 0;
for (Collection vms : vGroups) {
Among a = new Among(vms, pGroups);
//If the constraint is continuous, there is no way a group of VMs already bound to a group of
//nodes can move to another group. It also means the group of VMs will never overlap
a.setContinuous(cstr.isContinuous());
CAmong ca = new CAmong(a);
if (!ca.inject(ps, rp)) {
return false;
}
grpVars[i++] = ca.getGroupVariable();
}
//forces all the vGroups to use different group of nodes
csp.post(csp.allDifferent(grpVars, "DEFAULT"));
return true;
}
/**
* Get the group the node belong to.
*
* @param n the node
* @return the group identifier, {@code -1} if the node does not belong to a group
*/
public int getPGroup(Node n) {
int i = 0;
for (Collection pGrp : cstr.getGroupsOfNodes()) {
if (pGrp.contains(n)) {
break;
}
i++;
}
return i;
}
@Override
public Set getMisPlacedVMs(Instance i) {
//contains the set of VMs hosted on a group id.
@SuppressWarnings("unchecked")
Collection[] usedGrp = new Set[cstr.getGroupsOfNodes().size()];
Mapping map = i.getModel().getMapping();
Set bad = new HashSet<>();
for (Collection vms : cstr.getGroupsOfVMs()) {
int grp = -1;
for (VM vm : vms) {
if (map.isRunning(vm)) {
Node n = map.getVMLocation(vm);
int g = getPGroup(n);
if (g == -1) {
//The VM is on a node that belong to none of the given groups
bad.add(vm);
} else if (grp == -1) {
grp = g;
usedGrp[g] = vms;
} else if (g != grp) {
//The VMs spread over multiple group of nodes, the group of VMs is mis-placed
bad.addAll(vms);
if (usedGrp[g] != null) {
bad.addAll(usedGrp[g]);
}
bad.addAll(usedGrp[grp]);
}
}
}
}
return bad;
}
@Override
public String toString() {
return cstr.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy