/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive.resourcemanager.core; import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; import org.objectweb.proactive.core.util.MutableInteger; import org.ow2.proactive.resourcemanager.db.RMDBManager; import org.ow2.proactive.resourcemanager.rmnode.RMNode; import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; /** * Encapsulates the logic about Nodes lock restoration upon Resource Manager restart. * <p> * It was decided to keep the mechanism simple by considering the node source name only * when the lock restoration is made. The hostname does not enter into account. * <p> * Considering the hostname is non-trivial since it is not stable. It may change on * machine restart or due to node state change. Besides, some infrastructures are * dynamics and the number of nodes deployed from a restart to another may differ. * <p> * This class is not thread-safe. * * @author ActiveEon Team * @since 01/02/17 */ public class NodesLockRestorationManager { private static final Logger log = Logger.getLogger(NodesLockRestorationManager.class); private final RMCore rmCore; protected Map<String, MutableInteger> nodeLockedOnPreviousRun; protected boolean initialized; NodesLockRestorationManager(RMCore rmCore) { this.nodeLockedOnPreviousRun = Maps.newHashMap(); this.rmCore = rmCore; } protected void initialize() { Stopwatch stopwatch = null; if (log.isInfoEnabled()) { stopwatch = Stopwatch.createStarted(); } nodeLockedOnPreviousRun = findNodesLockedOnPreviousRun(); if (log.isInfoEnabled()) { stopwatch.stop(); log.info("Identifying nodes locked on the previous run required " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms"); } if (nodeLockedOnPreviousRun.isEmpty()) { log.info("There is no locks to restore"); } else { log.info("Here is the number of nodes to lock per node source:"); for (Map.Entry<String, MutableInteger> entry : nodeLockedOnPreviousRun.entrySet()) { log.info(" - nodeSource=" + entry.getKey() + ", host=" + entry.getKey() + ", count=" + entry.getValue().getValue()); } } initialized = true; } Map<String, MutableInteger> findNodesLockedOnPreviousRun() { RMDBManager dbManager = rmCore.getDbManager(); Map<String, MutableInteger> nodesLockedOnPreviousRun = dbManager.findNodesLockedOnPreviousRun(); dbManager.clearLockHistory(); return nodesLockedOnPreviousRun; } Map<String, MutableInteger> getNodeLockedOnPreviousRun() { return nodeLockedOnPreviousRun; } public boolean isInitialized() { return initialized; } /** * Handle the specified node for lock restoration. * * @param node the node to consider. */ public void handle(RMNode node) { if (!isNodeValidToBeRestored(node)) { if (log.isDebugEnabled()) { String nodeUrl = node.getNodeURL(); if (!initialized) { logSkipReason(nodeUrl, "manager is not yet initialized"); } else if (node.isLocked()) { logSkipReason(nodeUrl, "it is locked"); } else { logSkipReason(nodeUrl, "restoration is complete"); } } return; } String nodeSource = node.getNodeSourceName(); MutableInteger nodeCount = nodeLockedOnPreviousRun.get(nodeSource); if (nodeCount != null) { lockNode(node); int newNodeCount = nodeCount.add(-1); if (newNodeCount == 0) { nodeLockedOnPreviousRun.remove(nodeSource); } } } private boolean isNodeValidToBeRestored(RMNode node) { return initialized && !node.isLocked() && !isRestorationCompleted(); } private void logSkipReason(String nodeUrl, String reason) { log.info("Node '" + nodeUrl + "' skipped because " + reason); } boolean isRestorationCompleted() { return initialized && nodeLockedOnPreviousRun.isEmpty(); } boolean lockNode(RMNode node) { String nodeUrl = node.getNodeURL(); if (rmCore.lockNodes(ImmutableSet.of(nodeUrl)).getBooleanValue()) { log.info("Node '" + nodeUrl + "' has been locked with success"); return true; } else { log.info("Locking '" + nodeUrl + "' has failed"); return false; } } }