All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.btrplace.plan.ReconfigurationPlanChecker Maven / Gradle / Ivy

The newest version!
/*
 * Copyright  2020 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.plan;

import org.btrplace.model.Model;
import org.btrplace.model.constraint.SatConstraint;
import org.btrplace.model.constraint.SatConstraintChecker;
import org.btrplace.plan.event.Action;
import org.btrplace.plan.event.ActionVisitor;
import org.btrplace.plan.event.Allocate;
import org.btrplace.plan.event.AllocateEvent;
import org.btrplace.plan.event.BootNode;
import org.btrplace.plan.event.BootVM;
import org.btrplace.plan.event.Event;
import org.btrplace.plan.event.ForgeVM;
import org.btrplace.plan.event.KillVM;
import org.btrplace.plan.event.MigrateVM;
import org.btrplace.plan.event.ResumeVM;
import org.btrplace.plan.event.ShutdownNode;
import org.btrplace.plan.event.ShutdownVM;
import org.btrplace.plan.event.SubstitutedVMEvent;
import org.btrplace.plan.event.SuspendVM;
import org.btrplace.scheduler.InconsistentSolutionException;

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;

/**
 * Checker to verify if a reconfiguration plan satisfies a set of
 * {@link org.btrplace.model.constraint.SatConstraintChecker}.
 * 

* In practice, the origin model is send to each of the checkers. * Then it notifies all the checkers for the beginning and the end moment of each of the actions and events. * Finally, it sends the resulting model to each of the checkers. *

* Actions start and end moment are notified in the increasing order of their associated moment with * a priority given to the end moments. * * @author Fabien Hermenier */ public class ReconfigurationPlanChecker implements ActionVisitor { private boolean startingEvent = true; private static final TimedBasedActionComparator STARTS_CMP = new TimedBasedActionComparator(true, true); private static final TimedBasedActionComparator ENDS_CMP = new TimedBasedActionComparator(false, true); private final List> checkers; /** * Make a new instance. */ public ReconfigurationPlanChecker() { checkers = new ArrayList<>(); } /** * Add an additional checker. * * @param c the checker to add * @return {@code true} iff the checker has been added */ public boolean addChecker(SatConstraintChecker c) { return checkers.add(c); } /** * Remove a checker. * * @param c the checker to remove * @return {@code true} iff the checker was present */ public boolean removeChecker(SatConstraintChecker c) { return checkers.remove(c); } @Override public SatConstraint visit(Allocate a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public Object visit(AllocateEvent a) { for (SatConstraintChecker c : checkers) { if (!c.consume(a)) { return c.getConstraint(); } } return null; } @Override public SatConstraint visit(SubstitutedVMEvent a) { for (SatConstraintChecker c : checkers) { if (!c.consume(a)) { return c.getConstraint(); } } return null; } @Override public SatConstraint visit(BootNode a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public SatConstraint visit(BootVM a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public SatConstraint visit(ForgeVM a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public SatConstraint visit(KillVM a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public SatConstraint visit(MigrateVM a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public Object visit(ResumeVM a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public Object visit(ShutdownNode a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public Object visit(ShutdownVM a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } @Override public Object visit(SuspendVM a) { for (SatConstraintChecker c : checkers) { if (startingEvent) { if (!c.start(a)) { return c.getConstraint(); } } else { c.end(a); } } return null; } /** * Check if a plan satisfies all the {@link SatConstraintChecker}. * * @param p the plan to check * @throws SatConstraintViolationException if a violation is detected */ public void check(ReconfigurationPlan p) throws SatConstraintViolationException { if (checkers.isEmpty()) { return; } checkModel(p.getOrigin(), true); if (!p.getActions().isEmpty()) { PriorityQueue starts = new PriorityQueue<>(p.getActions().size(), STARTS_CMP); PriorityQueue ends = new PriorityQueue<>(p.getActions().size(), ENDS_CMP); starts.addAll(p.getActions()); ends.addAll(p.getActions()); //Starts the actions int curMoment = starts.peek().getStart(); while (!starts.isEmpty() || !ends.isEmpty()) { Action a = ends.peek(); while (a != null && a.getEnd() == curMoment) { ends.remove(); startingEvent = false; visitAndThrowOnViolation(a); visitEvents(a, Action.Hook.POST); a = ends.peek(); } a = starts.peek(); while (a != null && a.getStart() == curMoment) { starts.remove(); startingEvent = true; visitEvents(a, Action.Hook.PRE); visitAndThrowOnViolation(a); a = starts.peek(); } int nextEnd = Integer.MAX_VALUE; if (!ends.isEmpty()) { nextEnd = ends.peek().getEnd(); } int nextStart = Integer.MAX_VALUE; if (!starts.isEmpty()) { nextStart = starts.peek().getStart(); } curMoment = Math.min(nextEnd, nextStart); } } Model mo = p.getResult(); if (mo == null) { throw new InconsistentSolutionException(p, "The resulting reconfiguration plan is not applyable"); } checkModel(mo, false); } private void visitAndThrowOnViolation(Action a) throws SatConstraintViolationException { SatConstraint c = (SatConstraint) a.visit(this); if (c != null) { throw new ContinuousViolationException(c, a); } } private void visitEvents(Action a, Action.Hook k) throws SatConstraintViolationException { SatConstraint c; for (Event e : a.getEvents(k)) { c = (SatConstraint) e.visit(this); if (c != null) { throw new ContinuousViolationException(c, a); } } } /** * Check for the validity of a model. * * @param mo the model to check * @param start {@code true} iff the model corresponds to the origin model. Otherwise it is considered * to be the resulting model * @throws SatConstraintViolationException if at least one constraint is violated. */ private void checkModel(Model mo, boolean start) throws SatConstraintViolationException { for (SatConstraintChecker c : checkers) { if (start && !c.startsWith(mo)) { SatConstraint cs = c.getConstraint(); if (cs != null) { throw new DiscreteViolationException(c.getConstraint(), mo); } } else if (!start && !c.endsWith(mo)) { SatConstraint cs = c.getConstraint(); if (cs != null) { throw new DiscreteViolationException(c.getConstraint(), mo); } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy