/* * Copyright (c) 2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.db.common; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.coordinator.common.Configuration; import com.emc.storageos.coordinator.client.model.Constants; import com.emc.storageos.coordinator.client.model.DbVersionInfo; import com.emc.storageos.coordinator.exceptions.FatalCoordinatorException; /** * class provides methods to check dbsvc status */ public class DbServiceStatusChecker { private static final Logger log = LoggerFactory.getLogger(DbServiceStatusChecker.class); private static final int MAX_WAIT_TIME_IN_MIN = 10; private static final int WAIT_INTERVAL_IN_SEC = 1; private CoordinatorClient coordinator; private String version; private int clusterNodeCount; private DbVersionInfo dbVersionInfo; private String serviceName; /** * Set coordinator * * @param coordinator */ public void setCoordinator(CoordinatorClient coordinator) { this.coordinator = coordinator; } public void setVersion(String version) { this.version = version; } public void setDbVersionInfo(DbVersionInfo info) { dbVersionInfo = info; } public void setServiceName(String serviceName) { this.serviceName = serviceName; } /** * Set ClusterNodeCount * * @param clusterNodeCount */ public void setClusterNodeCount(int clusterNodeCount) { this.clusterNodeCount = clusterNodeCount; } public int getClusterNodeCount() { return clusterNodeCount; } private String getDbsvcVersion(boolean isVersioned) { if (isVersioned) { if (this.version == null) { throw new IllegalStateException(String.format( "version is not set for a versioned configuration")); } return version; } return null; } /** * Checks to see if any node in the cluster has entered a certain state */ private boolean isAnyNodeInState(String state, boolean isVersioned) throws Exception { List<Configuration> configs = coordinator.queryAllConfiguration(coordinator.getSiteId(), coordinator.getVersionedDbConfigPath(serviceName, getDbsvcVersion(isVersioned))); for (int i = 0; i < configs.size(); i++) { Configuration config = configs.get(i); String value = config.getConfig(state); if (value != null && Boolean.parseBoolean(value)) { return true; } } return false; } /** * Checks to see if the cassandra cluster finished entering a certain state */ private boolean isClusterStateDone(String state, boolean isVersioned, String svcName) throws Exception { if (clusterNodeCount == 0) { throw new IllegalStateException("node count not set"); } List<Configuration> configs = coordinator.queryAllConfiguration(coordinator.getSiteId(), coordinator.getVersionedDbConfigPath(svcName, getDbsvcVersion(isVersioned))); List<Configuration> leftoverConfig = coordinator.queryAllConfiguration(coordinator.getVersionedDbConfigPath(svcName, getDbsvcVersion(isVersioned))); configs.addAll(leftoverConfig); Set<String> qualifiedConfigs = new HashSet<String>(); for (int i = 0; i < configs.size(); i++) { Configuration config = configs.get(i); String value = config.getConfig(state); if (value != null && Boolean.parseBoolean(value)) { qualifiedConfigs.add(config.getId()); } } return (qualifiedConfigs.size() == clusterNodeCount); } private boolean isClusterStateDone(String state, boolean isVersioned) throws Exception { return isClusterStateDone(state, isVersioned, serviceName); } /** * A private helper method to wait for all cluster nodes until they all become * a certain state (JOINED/MIGRATION_INIT/etc) */ private void waitForAllNodesToBecome(String state, boolean isVersioned, String svcName) { final String prefix = "Waiting for all cluster nodes to become state: " + state; long start = System.currentTimeMillis(); log.info(prefix); while (System.currentTimeMillis() - start < MAX_WAIT_TIME_IN_MIN * 60 * 1000) { try { if (isClusterStateDone(state, isVersioned, svcName)) { log.info("{} : Done", prefix); return; } Thread.sleep(WAIT_INTERVAL_IN_SEC * 1000); } catch (InterruptedException ex) { log.warn("InterruptedException:{}", ex); } catch (FatalCoordinatorException ex) { log.error("fatal coodinator exception", ex); throw ex; } catch (Exception ex) { log.error("exception checking node status", ex); } } log.info("{} : Timed out", prefix); throw new IllegalStateException(String.format("%s : Timed out", prefix)); } private void waitForAllNodesToBecome(String state, boolean isVersioned) { waitForAllNodesToBecome(state, isVersioned, serviceName); } public boolean isDbSchemaVersionChanged() { String currentVersion = coordinator.getCurrentDbSchemaVersion(); String targetVersion = coordinator.getTargetDbSchemaVersion(); log.info("currentVersion: {}, targetVersion {} ", currentVersion, targetVersion); return !(currentVersion.equals(targetVersion)); } public boolean checkAllNodesJoined() throws Exception { return isClusterStateDone(DbConfigConstants.JOINED, false); } public boolean checkAllNodesInMigrationInit() throws Exception { return isClusterStateDone(DbConfigConstants.MIGRATION_INIT, true); } public boolean checkAnyNodeInitDone() throws Exception { return isAnyNodeInState(DbConfigConstants.INIT_DONE, true); } public void waitForAllNodesJoined() { waitForAllNodesToBecome(DbConfigConstants.JOINED, false); } public void waitForAllNodesMigrationInit() { waitForAllNodesMigrationInit(serviceName); } public void waitForAllNodesMigrationInit(String svcName) { waitForAllNodesToBecome(DbConfigConstants.MIGRATION_INIT, true, svcName); } public boolean isMigrationDone() { String targetVersion = coordinator.getTargetDbSchemaVersion(); String currentVersion = coordinator.getCurrentDbSchemaVersion(); log.debug("current version {}, target version {}", currentVersion, targetVersion); if (currentVersion != null && currentVersion.equals(targetVersion)) { log.debug("migration done already"); return true; } return false; } public void waitForMigrationDone() { final String prefix = "Waiting for current version to match target version ..."; log.warn(prefix); String targetVersion = coordinator.getTargetDbSchemaVersion(); while (true) { try { String currentVersion = coordinator.getCurrentDbSchemaVersion(); log.debug("current version {}, target version {}", currentVersion, targetVersion); if (currentVersion != null && currentVersion.equals(targetVersion)) { log.info("{} : Done", prefix); return; } // check every 30 seconds and there's no timeout Thread.sleep(WAIT_INTERVAL_IN_SEC * 30 * 1000); } catch (InterruptedException ex) { log.warn("InterruptedException:{}", ex); } catch (Exception ex) { log.error("exception checking db status", ex); } } } public void waitForAnyNodeInitDone() { long start = System.currentTimeMillis(); log.info("Waiting for db schema initialization ... "); while (System.currentTimeMillis() - start < MAX_WAIT_TIME_IN_MIN * 60 * 1000) { try { if (checkAnyNodeInitDone()) { log.info("Waiting for db schema initialization ... Done"); return; } Thread.sleep(WAIT_INTERVAL_IN_SEC * 1000); } catch (InterruptedException ex) { log.warn("InterruptedException:{}", ex); } catch (Exception ex) { log.error("exception checking db status", ex); } } log.info("Waiting for db schema initialization ... Timed out"); } }