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

com.dell.doradus.mbeans.StorageManager Maven / Gradle / Ivy

/*
 * Copyright (C) 2014 Dell, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dell.doradus.mbeans;

import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dell.doradus.core.ServerConfig;
import com.dell.doradus.management.LongJob;
import com.dell.doradus.management.StorageManagerMXBean;

/**
 * Implements the StorageManagerMXBean interface to the Cassandra database node
 * specified by configuration settings of running Doradus-server instance.
 * 

* NOTE: The constructors of this class is not intended for direct usage. * Instead, use {@code getStorageManager} static method of the * {@code MBeanProvider} class. */ public class StorageManager extends MBeanBase implements StorageManagerMXBean { private Logger logger = LoggerFactory.getLogger(getClass().getSimpleName()); static int JOB_LIST_MAX_SIZE = 100; /** * Creates new StorageManager instance and optionally registers it on the * platform MBeanServer. * * @param publish * The true, if you want to register the created instance. * Otherwise, nonpublic bean will be constructed. */ public StorageManager(boolean publish) { this.domain = JMX_DOMAIN_NAME; this.type = JMX_TYPE_NAME; if (publish) { register(); } } /** * Blocks until the active asynchronous operation (-"long job") completed * execution or the timeout occurs. * * @param timeoutInSeconds the maximum time to wait, in seconds * @param unit the time unit of the timeout argument * @return true if job terminated and false * if the timeout elapsed before termination * @throws InterruptedException if interrupted while waiting. */ public synchronized boolean awaitJobTermination(long timeoutInSeconds) throws InterruptedException { if (future != null && !future.isDone()) { logger.info("Blocking until active job completed (timeout: " + timeoutInSeconds + " secs)."); return executor.awaitTermination(timeoutInSeconds, TimeUnit.SECONDS); } return true; } /** * The operation mode of the Cassandra node. * * @return one of: NORMAL, CLIENT, JOINING, LEAVING, DECOMMISSIONED, MOVING, * DRAINING, or DRAINED. */ @Override public String getOperationMode() { String mode = getNode().getOperationMode(); if(mode != null && NORMAL.equals(mode.toUpperCase())) { mode = NORMAL; } return mode; } @Override public String getReleaseVersion() { return getNode().getReleaseVersion(); } /** * @return , */ public String getOS() { return getNode().getOS(); } /** * @return {@code FOREGROUND}, {@code BACKGROUND}, or {@code UNKNOWN} */ public int getStartMode() { try { return getNode().isInForeground() ? FOREGROUND : BACKGROUND; } catch(Exception ex) { return UNKNOWN; } } /** * The descriptor of asynchronous operation (-"long job") which this manager * either executes currently or has executed last. * * @return The LongJob instance or null if there were no requests of such * operations. */ @Override public LongJob getRecentJob() { return recentJob; } /** * Gets the descriptor of asynchronous operation (-"long job") which this manager * either executes currently or has executed earlier. * @param jobID The ID of an asynchronous operation. * @return The LongJob instance or null, if ID is unknown in this manager. */ @Override public LongJob getJobByID(String jobID) { return jobMap.get(jobID); } /** * Enumerates all asynchronous operations which this manager * either executes currently or has executed earlier. * @return The mapping of job ID to the job name. */ public String[] getJobList() { return (String[])jobList.toArray(new String[0]); } /** * The names list of data snapshots which exist in the local (!) storage * node. * * @return a String[] of snapshot names. * @exception java.lang.IllegalStateException * if storage node is not local. */ @Override public String[] getSnapshotList() { return getNode().getSnapshotList(); } /** * Returns the total number of nodes in database cluster. Zero is returned if unavailable. * @return */ public int getNodesCount() { return getNode().getNodesCount(); } /** * Starts the asynchronous operation (- "long job") that will create new * data snapshot. The operation will be completed with FAILED status if * storage node is not in NORMAL mode or specified snapshot already exists. * * @param snapshotName * The name of snapshot. * @exception java.lang.IllegalStateException * if other job is executing currently. */ @Override public String startCreateSnapshot(String snapshotName) { String jobID = consNextJobID(); String jobName = consJobName("createBackup", snapshotName); LongJob job = getNode().consCreateSnapshotJob(jobID, jobName, snapshotName); startJob(job); return jobID; } /** * Starts the asynchronous operation (- "long job") that will delete * specified data snapshot. It is empty job if specified snapshot does not * exist. The operation will be completed with FAILED status if storage node * is not in NORMAL mode. * * @param snapshotName * The name of snapshot. * @exception java.lang.IllegalStateException * If other job is executing currently. */ @Override public String startDeleteSnapshot(String snapshotName) { String jobID = consNextJobID(); String jobName = consJobName("deleteBackup", snapshotName); LongJob job = getNode().consDeleteSnapshotJob(jobID, jobName, snapshotName); startJob(job); return jobID; } /** * Starts the asynchronous operation (- "long job") that will restore the * data of local (!) storage node from specified snapshot. The operation * will be completed with FAILED status if storage node is not local, * storage node is not in NORMAL mode, or specified snapshot does not exist. * *

* WARN: This operation will shut down and restart the storage node using * the "doradus-cassandra.bat" utility tool (- STOP and START commands). * That is, it is supposed that 1) Cassandra works as a Windows * service, and 2) the running Doradus-server has rights of Windows * administrator. * * @param snapshotName * The name of snapshot. * @exception java.lang.IllegalStateException * If other job is executing currently. */ @Override public String startRestoreFromSnapshot(String snapshotName) { String jobID = consNextJobID(); String jobName = consJobName("restoreBackup", snapshotName); LongJob job = getNode().consRestoreFromSnapshotJob(jobID, jobName, snapshotName); startJob(job); return jobID; } ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// private String consJobName(String opName, String... args) { StringBuilder b = new StringBuilder(); b.append(opName + "("); for(int i = 0; i < args.length; i++) { if(i > 0) b.append(", "); b.append(args[i]); } b.append(")"); return b.toString(); } private CassandraNode getNode() { if (node == null) { synchronized (this) { if (node == null) { ServerConfig c = ServerConfig.getInstance(); node = new CassandraNode(c.dbhost, c.jmxport); } } } return node; } private synchronized void startJob(LongJob job) { if (future != null && !future.isDone()) { throw new IllegalStateException("Service busy. The \"" + recentJob.getName() + "\" job is in progress."); } if (executor == null) { executor = Executors.newSingleThreadExecutor(); } if(jobList.size() >= JOB_LIST_MAX_SIZE) { String firstId = jobList.get(0); jobList.remove(0); jobMap.remove(firstId); } recentJob = job; jobMap.put(job.getId(), job); jobList.add(job.getId()); future = executor.submit(job); } private synchronized String consNextJobID() { if(pid == null) { pid = getProcessId(); } return pid + "-" + (++jobCount); } private String getProcessId() { // something like '@', at least in SUN / Oracle JVMs final String jvmName = ManagementFactory.getRuntimeMXBean().getName(); final int index = jvmName.indexOf('@'); if(index >= 1) { try { return Long.toString(Long.parseLong(jvmName.substring(0, index))); } catch (NumberFormatException e) { } } logger.warn("Can't get current process id. Instead, using the JVM name: " + jvmName); return jvmName; } private static int jobCount; private CassandraNode node; private LongJob recentJob; private ExecutorService executor; private Future future; private String pid; private Map jobMap = new HashMap(); private List jobList = new LinkedList(); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy