/* * Copyright (c) 2010 Ecole des Mines de Nantes. * * 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.execution; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import entropy.execution.driver.Driver; import entropy.execution.driver.DriverFactory; import entropy.execution.driver.DriverInstantiationException; import entropy.plan.TimedReconfigurationPlan; import entropy.plan.action.Action; /** * An execution module dedicated to the execution of time bounded Action. All feasible actions are made in parallel. * The execution module try to execute new action when a Action is committed. * * @author Fabien Hermenier */ public class TimedReconfigurationExecuter { /** * Get the dependencies, an action is for */ private Map<Action, List<Dependencies>> revDependencies; /** * The factory to create drivers. */ private DriverFactory factory; /** * All the action that don't have been commited. */ private List<Action> uncommited; private Logger logger = LoggerFactory.getLogger("Actuator"); /** * Make a new Execution module for a specific plan. Each action will be executed after * adaptation by a specific DriverFactory * * @param f the DriverFactory to transfrom the action into a driver */ public TimedReconfigurationExecuter(DriverFactory f) { this.factory = f; this.revDependencies = new HashMap<Action, List<Dependencies>>(); this.uncommited = new LinkedList<Action>(); } /** * Start the execution of a plan. * The method is blocking and ends once all the actions have been performed * * @param plan the plan to execute */ public void start(TimedReconfigurationPlan plan) { revDependencies.clear(); uncommited.clear(); uncommited.addAll(plan.getActions()); TimedExecutionGraph g = plan.extractExecutionGraph(); //Set the reverse dependencies map for (Dependencies dep : g.extractDependencies()) { for (Action a : dep.getUnsatisfiedDependencies()) { if (!revDependencies.containsKey(a)) { revDependencies.put(a, new LinkedList<Dependencies>()); } revDependencies.get(a).add(dep); } } //Start the feasible actions // ie, actions with a start moment equals to 0. for (Action a : plan) { if (a.getStartMoment() == 0) { instantiateAndStart(a); } } //Check each second if all the actions has been performed while (uncommited.size() != 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } } } /** * Associate an action with a driver and start its execution * using a {@link Executor}. * * @param a the action to instantiate and start */ private void instantiateAndStart(Action a) { try { Driver drv = factory.transform(a); new Executor(drv, this).start(); } catch (DriverInstantiationException ex) { logger.error(ex.getMessage(), ex); } } /** * Commit the execution of an action. * If the execution of the action succeed. Unlocked actions * are started. * * @param e the executor that commit the action */ public void commit(Executor e) { Action a = e.getDriver().getAction(); uncommited.remove(a); if (e.hasSuceeded()) { if (revDependencies.containsKey(a)) { //Get the associated depenencies and update it for (Dependencies dep : revDependencies.get(a)) { dep.removeDependency(a); //Launch new feasible actions. if (dep.isFeasible()) { instantiateAndStart(dep.getAction()); } } } } else { logger.error("Reconfiguration aborded: " + e.getException().getMessage(), e.getException()); } } /** * Get all the uncommited actions. * A reconfiguration process is terminated once * all the actions on a plan has been commited * * @return a list that may be empty */ public List<Action> getUncommitedActions() { return this.uncommited; } }