/* * Copyright (c) Fabien Hermenier * * This file is part of Entropy. * * Entropy is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Entropy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Entropy. If not, see <http://www.gnu.org/licenses/>. */ package entropy.plan.choco.actionModel; import solver.variables.IntVar; import entropy.configuration.Configuration; import entropy.configuration.VirtualMachine; import entropy.plan.action.Resume; import entropy.plan.choco.ReconfigurationProblem; import entropy.plan.choco.actionModel.slice.DemandingSlice; /** * Model the action that resume a virtual machine. * The action is modeled with one demanding slice. The action will start at the * beginning of the slice however, it may finish before the end of the slice (if the duration of the action * is < to the duration of the slice). This little hack tends to resume the VM sooner. * * @author Fabien Hermenier */ public class ResumeActionModel extends VirtualMachineActionModel { /** * The moment the action ends. */ private IntVar finish; /** * Make a new resume action model. * <p/> * Add the action to the model with the following constraints. * <ul> * <li>{@code resumeDuration = {localValue, remoteValue}}</li> * <li>{@code hoster() = currentNode <=> resumeDuration=localValue }</li> * <li>{@code duration().inf == Math.min(remoteCost, localCost) }</li> * <li>{@code duration() >= resumeDuration }</li> * <li>{@code end() > start() }</li> * </ul> * * @param model the model of the reconfiguration problem * @param vm the virtual machine associated to the action * @param localValue the duration of a local resume * @param remoteValue the duration of the remote resume */ public ResumeActionModel(ReconfigurationProblem model, VirtualMachine vm, int localValue, int remoteValue) { super(vm); this.finish = model.createBoundIntVar("end(resume(" + vm.getName() + "))", 0, ReconfigurationProblem.MAX_TIME); this.dSlice = new DemandingSlice(model, "resume(" + getVirtualMachine().getName() + ")", vm.getCPUDemand(), vm.getMemoryDemand()); duration = model.createEnumIntVar("duration(resume(" + getVirtualMachine().getName() + "))", new int[]{localValue, remoteValue}); dSlice.addToModel(model); int curLocation = model.getNode(model.getSourceConfiguration().getLocation(getVirtualMachine())); IntVar stay = model.createBooleanVar("rt(" + getVirtualMachine().getName() + ")"); model.post(ReifiedFactory.builder(stay, model.eq(curLocation, dSlice.hoster()), model)); model.post(model.ifOnlyIf(stay, model.eq(duration, localValue))); model.post(model.leq(finish, model.getEnd())); //always: a.end() >= a.start() && a.end() <= max(a.start() + localValue, start + endValue) model.post(model.geq(dSlice.duration(), duration)); model.post(model.eq(finish, model.plus(start(), duration))); } /** * Get the moment the action finishes * The slice may finish later ! * * @return the moment the action ends */ @Override public final IntVar end() { return finish; } /** * Get the moment the action starts. * * @return the moment the demanding slice starts. */ @Override public final IntVar start() { return dSlice.start(); } @Override public Resume getDefinedAction(ReconfigurationProblem solver) { return new Resume(getVirtualMachine(), solver.getSourceConfiguration().getLocation(getVirtualMachine()), solver.getNode(dSlice.hoster().getVal()), start().getVal(), end().getVal()); } @Override public boolean putResult(ReconfigurationProblem solver, Configuration cfg) { cfg.setRunOn(getVirtualMachine(), solver.getNode(dSlice.hoster().getVal())); return true; } @Override public String toString() { return "resume(" + getVirtualMachine().getName() + ")"; } }