You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by rv...@apache.org on 2015/04/28 23:40:45 UTC
[40/51] [partial] incubator-geode git commit: Init
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthMonitor.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthMonitor.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthMonitor.java
new file mode 100644
index 0000000..ca7f067
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthMonitor.java
@@ -0,0 +1,428 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.SystemFailure;
+import com.gemstone.gemfire.admin.AdminException;
+import com.gemstone.gemfire.admin.GemFireHealth;
+import com.gemstone.gemfire.admin.GemFireHealthConfig;
+import com.gemstone.gemfire.admin.GemFireMemberStatus;
+import com.gemstone.gemfire.admin.RegionSubRegionSnapshot;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionAttributes;
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+import com.gemstone.gemfire.internal.Assert;
+import com.gemstone.gemfire.internal.Config;
+import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.admin.AdminBridgeServer;
+import com.gemstone.gemfire.internal.admin.CacheInfo;
+import com.gemstone.gemfire.internal.admin.DLockInfo;
+import com.gemstone.gemfire.internal.admin.GemFireVM;
+import com.gemstone.gemfire.internal.admin.GfManagerAgent;
+import com.gemstone.gemfire.internal.admin.HealthListener;
+import com.gemstone.gemfire.internal.admin.Stat;
+import com.gemstone.gemfire.internal.admin.StatAlertDefinition;
+import com.gemstone.gemfire.internal.admin.StatListener;
+import com.gemstone.gemfire.internal.admin.StatResource;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.LoggingThreadGroup;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+
+/**
+ * A thread that monitors the health of the distributed system. It is
+ * kind of like a {@link
+ * com.gemstone.gemfire.distributed.internal.HealthMonitorImpl}. In
+ * order to get it to place nice with the rest of the health
+ * monitoring APIs, this class pretends that it is a
+ * <code>GemFireVM</code>. Kind of hokey, but it beats a bunch of
+ * special-case code.
+ *
+ * @author David Whitlock
+ *
+ * @since 3.5
+ * */
+class DistributedSystemHealthMonitor implements Runnable, GemFireVM {
+
+ private static final Logger logger = LogService.getLogger();
+
+ /** Evaluates the health of the distributed system */
+ private DistributedSystemHealthEvaluator eval;
+
+ /** Notified when the health of the distributed system changes */
+ private GemFireHealthImpl healthImpl;
+
+ /** The number of seconds between health checks */
+ private int interval;
+
+ /** The thread in which the monitoring occurs */
+ private Thread thread;
+
+ /** Has this monitor been asked to stop? */
+ private volatile boolean stopRequested = false;
+
+ /** The health of the distributed system the last time we checked. */
+ private GemFireHealth.Health prevHealth = GemFireHealth.GOOD_HEALTH;
+
+ /** The most recent <code>OKAY_HEALTH</code> diagnoses of the
+ * GemFire system */
+ private List okayDiagnoses;
+
+ /** The most recent <code>POOR_HEALTH</code> diagnoses of the
+ * GemFire system */
+ private List poorDiagnoses;
+
+ ////////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>DistributedSystemHealthMonitor</code> that
+ * evaluates the health of the distributed system against the given
+ * thresholds once every <code>interval</code> seconds.
+ *
+ * @param eval
+ * Used to evaluate the health of the distributed system
+ * @param healthImpl
+ * Receives callbacks when the health of the distributed
+ * system changes
+ * @param interval
+ * How often the health is checked
+ */
+ DistributedSystemHealthMonitor(DistributedSystemHealthEvaluator eval,
+ GemFireHealthImpl healthImpl,
+ int interval) {
+ this.eval = eval;
+ this.healthImpl = healthImpl;
+ this.interval = interval;
+ this.okayDiagnoses = new ArrayList();
+ this.poorDiagnoses = new ArrayList();
+
+ ThreadGroup group =
+ LoggingThreadGroup.createThreadGroup(LocalizedStrings.DistributedSystemHealthMonitor_HEALTH_MONITORS.toLocalizedString(), logger);
+ String name = LocalizedStrings.DistributedSystemHealthMonitor_HEALTH_MONITOR_FOR_0.toLocalizedString(eval.getDescription());
+ this.thread = new Thread(group, this, name);
+ this.thread.setDaemon(true);
+ }
+
+ /**
+ * Does the work of monitoring the health of the distributed
+ * system.
+ */
+ public void run() {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Monitoring health of {} every {} seconds", this.eval.getDescription(), interval);
+ }
+
+ while (!this.stopRequested) {
+ SystemFailure.checkFailure();
+ try {
+ Thread.sleep(interval * 1000);
+ List status = new ArrayList();
+ eval.evaluate(status);
+
+ GemFireHealth.Health overallHealth = GemFireHealth.GOOD_HEALTH;
+ this.okayDiagnoses.clear();
+ this.poorDiagnoses.clear();
+
+ for (Iterator iter = status.iterator(); iter.hasNext(); ) {
+ AbstractHealthEvaluator.HealthStatus health =
+ (AbstractHealthEvaluator.HealthStatus) iter.next();
+ if (overallHealth == GemFireHealth.GOOD_HEALTH) {
+ if ((health.getHealthCode() != GemFireHealth.GOOD_HEALTH)) {
+ overallHealth = health.getHealthCode();
+ }
+
+ } else if (overallHealth == GemFireHealth.OKAY_HEALTH) {
+ if (health.getHealthCode() == GemFireHealth.POOR_HEALTH) {
+ overallHealth = GemFireHealth.POOR_HEALTH;
+ }
+ }
+
+ GemFireHealth.Health healthCode = health.getHealthCode();
+ if (healthCode == GemFireHealth.OKAY_HEALTH) {
+ this.okayDiagnoses.add(health.getDiagnosis());
+
+ } else if (healthCode == GemFireHealth.POOR_HEALTH) {
+ this.poorDiagnoses.add(health.getDiagnosis());
+ break;
+ }
+ }
+
+ if (overallHealth != prevHealth) {
+ healthImpl.healthChanged(this, overallHealth);
+ this.prevHealth = overallHealth;
+ }
+
+ } catch (InterruptedException ex) {
+ // We're all done
+ // No need to reset the interrupted flag, since we're going to exit.
+ break;
+ }
+ }
+
+ eval.close();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Stopped checking for distributed system health");
+ }
+ }
+
+ /**
+ * Starts this <code>DistributedSystemHealthMonitor</code>
+ */
+ void start(){
+ this.thread.start();
+ }
+
+ /**
+ * Stops this <code>DistributedSystemHealthMonitor</code>
+ */
+ void stop() {
+ if (this.thread.isAlive()) {
+ this.stopRequested = true;
+ this.thread.interrupt();
+ this.healthImpl.nodeLeft(null, this);
+
+ try {
+ this.thread.join();
+ }
+ catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ logger.warn(LocalizedMessage.create(LocalizedStrings.DistributedSystemHealthMonitor_INTERRUPTED_WHILE_STOPPING_HEALTH_MONITOR_THREAD), ex);
+ }
+ }
+ }
+
+ ////////////////////// GemFireVM Methods //////////////////////
+
+ public java.net.InetAddress getHost() {
+ try {
+ return SocketCreator.getLocalHost();
+
+ } catch (Exception ex) {
+ throw new com.gemstone.gemfire.InternalGemFireException(LocalizedStrings.DistributedSystemHealthMonitor_COULD_NOT_GET_LOCALHOST.toLocalizedString());
+ }
+ }
+
+ public String getName() {
+// return getId().toString();
+ throw new UnsupportedOperationException("Not a real GemFireVM");
+ }
+
+ public java.io.File getWorkingDirectory() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public java.io.File getGemFireDir() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public java.util.Date getBirthDate() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Properties getLicenseInfo(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public GemFireMemberStatus getSnapshot() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public RegionSubRegionSnapshot getRegionSnapshot() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public StatResource[] getStats(String statisticsTypeName){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public StatResource[] getAllStats(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public DLockInfo[] getDistributedLockInfo(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void addStatListener(StatListener observer,
+ StatResource observedResource,
+ Stat observedStat){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void removeStatListener(StatListener observer){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void addHealthListener(HealthListener observer,
+ GemFireHealthConfig cfg){
+
+ }
+
+ public void removeHealthListener(){
+
+ }
+
+ public void resetHealthStatus(){
+ this.prevHealth = GemFireHealth.GOOD_HEALTH;
+ }
+
+ public String[] getHealthDiagnosis(GemFireHealth.Health healthCode){
+ if (healthCode == GemFireHealth.GOOD_HEALTH) {
+ return new String[0];
+
+ } else if (healthCode == GemFireHealth.OKAY_HEALTH) {
+ String[] array = new String[this.okayDiagnoses.size()];
+ this.okayDiagnoses.toArray(array);
+ return array;
+
+ } else {
+ Assert.assertTrue(healthCode == GemFireHealth.POOR_HEALTH);
+ String[] array = new String[this.poorDiagnoses.size()];
+ this.poorDiagnoses.toArray(array);
+ return array;
+ }
+ }
+
+ public Config getConfig(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void setConfig(Config cfg){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public GfManagerAgent getManagerAgent(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public String[] getSystemLogs(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void setInspectionClasspath(String classpath){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public String getInspectionClasspath(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region[] getRootRegions(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region getRegion(CacheInfo c, String path) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region createVMRootRegion(CacheInfo c, String name,
+ RegionAttributes attrs) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region createSubregion(CacheInfo c, String parentPath,
+ String name, RegionAttributes attrs) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void setCacheInspectionMode(int mode) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public int getCacheInspectionMode(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void takeRegionSnapshot(String regionName, int snapshotId){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public InternalDistributedMember getId() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo getCacheInfo() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public String getVersionInfo() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo setCacheLockTimeout(CacheInfo c, int v) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo setCacheLockLease(CacheInfo c, int v) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo setCacheSearchTimeout(CacheInfo c, int v) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer addBridgeServer(CacheInfo cache)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer getBridgeInfo(CacheInfo cache,
+ int id)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer startBridgeServer(CacheInfo cache,
+ AdminBridgeServer bridge)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer stopBridgeServer(CacheInfo cache,
+ AdminBridgeServer bridge)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ /**
+ * This operation is not supported for this object. Will throw
+ * UnsupportedOperationException if invoked.
+ */
+ public void setAlertsManager(StatAlertDefinition[] alertDefs,
+ long refreshInterval, boolean setRemotely) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ /**
+ * This operation is not supported for this object. Will throw
+ * UnsupportedOperationException if invoked.
+ */
+ public void setRefreshInterval(long refreshInterval) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ /**
+ * This operation is not supported for this object. Will throw
+ * UnsupportedOperationException if invoked.
+ */
+ public void updateAlertDefinitions(StatAlertDefinition[] alertDefs,
+ int actionCode) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorConfigImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorConfigImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorConfigImpl.java
new file mode 100644
index 0000000..1e3e7e8
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorConfigImpl.java
@@ -0,0 +1,183 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import com.gemstone.gemfire.admin.DistributionLocator;
+import com.gemstone.gemfire.admin.DistributionLocatorConfig;
+import com.gemstone.gemfire.distributed.internal.InternalLocator;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+import java.net.InetAddress;
+import java.util.Properties;
+
+/**
+ * Provides an implementation of
+ * <code>DistributionLocatorConfig</code>.
+ *
+ * @author David Whitlock
+ * @since 4.0
+ */
+public class DistributionLocatorConfigImpl
+ extends ManagedEntityConfigImpl
+ implements DistributionLocatorConfig {
+
+ /** The minimum networking port (0) */
+ public static final int MIN_PORT = 0;
+
+ /** The maximum networking port (65535) */
+ public static final int MAX_PORT = 65535;
+
+ ////////////////////// Instance Fields //////////////////////
+
+ /** The port on which this locator listens */
+ private int port;
+
+ /** The address to bind to on a multi-homed host */
+ private String bindAddress;
+
+ /** The properties used to configure the DistributionLocator's
+ DistributedSystem */
+ private Properties dsProperties;
+
+ /** The DistributionLocator that was created with this config */
+ private DistributionLocator locator;
+
+ ////////////////////// Static Methods //////////////////////
+
+ /**
+ * Contacts a distribution locator on the given host and port and
+ * creates a <code>DistributionLocatorConfig</code> for it.
+ *
+ * @see InternalLocator#getLocatorInfo
+ *
+ * @return <code>null</code> if the locator cannot be contacted
+ */
+ static DistributionLocatorConfig
+ createConfigFor(String host, int port, InetAddress bindAddress) {
+
+ String[] info = null;
+ if (bindAddress != null) {
+ info = InternalLocator.getLocatorInfo(bindAddress, port);
+ }
+ else {
+ info = InternalLocator.getLocatorInfo(InetAddressUtil.toInetAddress(host), port);
+ }
+ if (info == null) {
+ return null;
+ }
+
+ DistributionLocatorConfigImpl config =
+ new DistributionLocatorConfigImpl();
+ config.setHost(host);
+ config.setPort(port);
+ if (bindAddress != null) {
+ config.setBindAddress(bindAddress.getHostAddress());
+ }
+ config.setWorkingDirectory(info[0]);
+ config.setProductDirectory(info[1]);
+
+ return config;
+ }
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>DistributionLocatorConfigImpl</code> with the
+ * default settings.
+ */
+ public DistributionLocatorConfigImpl() {
+ this.port = 0;
+ this.bindAddress = null;
+ this.locator = null;
+ this.dsProperties = new java.util.Properties();
+ this.dsProperties.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
+ }
+
+ ///////////////////// Instance Methods /////////////////////
+
+ /**
+ * Sets the locator that was configured with this
+ * <Code>DistributionLocatorConfigImpl</code>.
+ */
+ void setLocator(DistributionLocator locator) {
+ this.locator = locator;
+ }
+
+ @Override
+ protected boolean isReadOnly() {
+ return this.locator != null && this.locator.isRunning();
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ public void setPort(int port) {
+ checkReadOnly();
+ this.port = port;
+ configChanged();
+ }
+
+ public String getBindAddress() {
+ return this.bindAddress;
+ }
+
+ public void setBindAddress(String bindAddress) {
+ checkReadOnly();
+ this.bindAddress = bindAddress;
+ configChanged();
+ }
+
+ public void setDistributedSystemProperties(Properties props) {
+ this.dsProperties = props;
+ }
+
+ public Properties getDistributedSystemProperties() {
+ return this.dsProperties;
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+
+ if (port < MIN_PORT || port > MAX_PORT) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributionLocatorConfigImpl_PORT_0_MUST_BE_AN_INTEGER_BETWEEN_1_AND_2.toLocalizedString(new Object[] {Integer.valueOf(port), Integer.valueOf(MIN_PORT), Integer.valueOf(MAX_PORT)}));
+ }
+
+ if (this.bindAddress != null &&
+ InetAddressUtil.validateHost(this.bindAddress) == null) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributionLocatorConfigImpl_INVALID_HOST_0.toLocalizedString(this.bindAddress));
+ }
+ }
+
+ /**
+ * Currently, listeners are not supported on the locator config.
+ */
+ @Override
+ protected void configChanged() {
+
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ DistributionLocatorConfigImpl clone =
+ (DistributionLocatorConfigImpl) super.clone();
+ clone.locator = null;
+ return clone;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("DistributionLocatorConfig: host=").append(getHost());
+ sb.append(", bindAddress=").append(getBindAddress());
+ sb.append(", port=").append(getPort());
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorImpl.java
new file mode 100755
index 0000000..d970816
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributionLocatorImpl.java
@@ -0,0 +1,322 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.admin.internal;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.admin.AdminDistributedSystem;
+import com.gemstone.gemfire.admin.DistributionLocator;
+import com.gemstone.gemfire.admin.DistributionLocatorConfig;
+import com.gemstone.gemfire.admin.ManagedEntityConfig;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+import com.gemstone.gemfire.internal.admin.remote.DistributionLocatorId;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+
+/**
+ * Default administrative implementation of a DistributionLocator.
+ *
+ * @author Kirk Lund
+ * @since 3.5
+ */
+public class DistributionLocatorImpl
+ implements DistributionLocator, InternalManagedEntity {
+
+ private static final Logger logger = LogService.getLogger();
+
+ /** How many new <code>DistributionLocator</code>s have been created? */
+ private static int newLocators = 0;
+
+ //////////////////// Instance Fields ////////////////////
+
+ /** The configuration object for this locator */
+ private final DistributionLocatorConfigImpl config;
+
+ /** The id of this distribution locator */
+ private final String id;
+
+ /** Used to control the actual DistributionLocator service */
+ private ManagedEntityController controller;
+
+ /** The system that this locator is a part of */
+ private AdminDistributedSystemImpl system;
+
+ // -------------------------------------------------------------------------
+ // constructor(s)...
+ // -------------------------------------------------------------------------
+
+ /**
+ * Constructs new instance of <code>DistributionLocatorImpl</code>
+ * that is a member of the given distributed system.
+ */
+ public DistributionLocatorImpl(DistributionLocatorConfig config,
+ AdminDistributedSystemImpl system) {
+ this.config = (DistributionLocatorConfigImpl) config;
+ this.config.validate();
+ this.config.setManagedEntity(this);
+ this.id = getNewId();
+ this.controller = system.getEntityController();
+ this.system = system;
+ }
+
+ // -------------------------------------------------------------------------
+ // Attribute accessors/mutators...
+ // -------------------------------------------------------------------------
+
+ public String getId() {
+ return this.id;
+ }
+
+ public String getNewId() {
+ synchronized (DistributionLocatorImpl.class) {
+ return "Locator" + (++newLocators);
+ }
+ }
+
+ /**
+ * Returns the configuration object for this locator.
+ *
+ * @since 4.0
+ */
+ public DistributionLocatorConfig getConfig() {
+ return this.config;
+ }
+
+ public AdminDistributedSystem getDistributedSystem() {
+ return this.system;
+ }
+
+ /**
+ * Unfortunately, it doesn't make much sense to maintain the state
+ * of a locator. The admin API does not receive notification when
+ * the locator actually starts and stops. If we try to guess, we'll
+ * just end up with race conditions galore. So, we can't fix bug
+ * 32455 for locators.
+ */
+ public int setState(int state) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributionLocatorImpl_CAN_NOT_SET_THE_STATE_OF_A_LOCATOR.toLocalizedString());
+ }
+
+ // -------------------------------------------------------------------------
+ // Operations...
+ // -------------------------------------------------------------------------
+
+ /**
+ * Polls to determine whether or not this managed entity has
+ * started.
+ */
+ public boolean waitToStart(long timeout)
+ throws InterruptedException {
+
+ if (Thread.interrupted()) throw new InterruptedException();
+
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() - start < timeout) {
+ if (this.isRunning()) {
+ return true;
+
+ } else {
+ Thread.sleep(100);
+ }
+ }
+
+ logger.info(LocalizedMessage.create(
+ LocalizedStrings.DistributionLocatorImpl_DONE_WAITING_FOR_LOCATOR));
+ return this.isRunning();
+ }
+
+ /**
+ * Polls to determine whether or not this managed entity has
+ * stopped.
+ */
+ public boolean waitToStop(long timeout)
+ throws InterruptedException {
+
+ if (Thread.interrupted()) throw new InterruptedException();
+
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() - start < timeout) {
+ if (!this.isRunning()) {
+ return true;
+
+ } else {
+ Thread.sleep(100);
+ }
+ }
+
+ return !this.isRunning();
+ }
+
+ public boolean isRunning() {
+ DM dm = ((AdminDistributedSystemImpl)getDistributedSystem()).getDistributionManager();
+ if(dm == null) {
+ try {
+ return this.controller.isRunning(this);
+ }
+ catch (IllegalStateException e) {
+ return false;
+ }
+ }
+
+ String host = getConfig().getHost();
+ int port = getConfig().getPort();
+ String bindAddress = getConfig().getBindAddress();
+
+ boolean found = false;
+ Map<InternalDistributedMember, Collection<String>> hostedLocators = dm.getAllHostedLocators();
+ for (Iterator<InternalDistributedMember> memberIter = hostedLocators.keySet().iterator(); memberIter.hasNext();) {
+ for (Iterator<String> locatorIter = hostedLocators.get(memberIter.next()).iterator(); locatorIter.hasNext();) {
+ DistributionLocatorId locator = new DistributionLocatorId(locatorIter.next());
+ found = found || locator.getHost().getHostAddress().equals(host);
+ found = found || locator.getHost().getHostName().equals(host);
+ if (!found && !host.contains(".")) {
+ try {
+ InetAddress inetAddr = InetAddress.getByName(host);
+ found = locator.getHost().getHostName().equals(inetAddr.getHostName());
+ if (!found) {
+ found = locator.getHost().getHostAddress().equals(inetAddr.getHostAddress());
+ }
+ }
+ catch (UnknownHostException e) {
+ // try config host as if it is an IP address instead of host name
+ }
+ }
+ if (locator.getBindAddress() != null && !locator.getBindAddress().isEmpty()
+ && bindAddress != null && !bindAddress.isEmpty()) {
+ found = found && locator.getBindAddress().equals(bindAddress);
+ }
+ found = found && locator.getPort() == port;
+ if (found) {
+ return true;
+ }
+ }
+ }
+ return found;
+ }
+
+ public void start() {
+ this.config.validate();
+ this.controller.start(this);
+ this.config.setLocator(this);
+ this.system.updateLocatorsString();
+ }
+
+ public void stop() {
+ this.controller.stop(this);
+ this.config.setLocator(null);
+ }
+
+ public String getLog() {
+ return this.controller.getLog(this);
+ }
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return a string representation of the object
+ */
+ @Override
+ public String toString() {
+ return "DistributionLocator " + getId();
+ }
+
+ //////////////////////// Command execution ////////////////////////
+
+ public ManagedEntityConfig getEntityConfig() {
+ return this.getConfig();
+ }
+
+ public String getEntityType() {
+ return "Locator";
+ }
+
+ public String getStartCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" start-locator -q -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+ sb.append(" -port=");
+ sb.append(this.getConfig().getPort());
+ Properties props = config.getDistributedSystemProperties();
+ Enumeration en = props.propertyNames();
+ while (en.hasMoreElements()) {
+ String pn = (String)en.nextElement();
+ sb.append(" -Dgemfire." + pn + "=" + props.getProperty(pn));
+ }
+
+ String bindAddress = this.getConfig().getBindAddress();
+ if (bindAddress != null && bindAddress.length() > 0) {
+ sb.append(" -address=");
+ sb.append(this.getConfig().getBindAddress());
+ }
+ sb.append(" ");
+
+ String sslArgs =
+ this.controller.buildSSLArguments(this.system.getConfig());
+ if (sslArgs != null) {
+ sb.append(sslArgs);
+ }
+
+ return sb.toString().trim();
+ }
+
+ public String getStopCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" stop-locator -q -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+ sb.append(" -port=");
+ sb.append(this.getConfig().getPort());
+
+ String bindAddress = this.getConfig().getBindAddress();
+ if (bindAddress != null && bindAddress.length() > 0) {
+ sb.append(" -address=");
+ sb.append(this.getConfig().getBindAddress());
+ }
+ sb.append(" ");
+
+ String sslArgs =
+ this.controller.buildSSLArguments(this.system.getConfig());
+ if (sslArgs != null) {
+ sb.append(sslArgs);
+ }
+
+ return sb.toString().trim();
+ }
+
+ public String getIsRunningCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" status-locator -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ return sb.toString().trim();
+ }
+
+ public String getLogCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" tail-locator-log -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ return sb.toString().trim();
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/EnabledManagedEntityController.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/EnabledManagedEntityController.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/EnabledManagedEntityController.java
new file mode 100755
index 0000000..8555f96
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/EnabledManagedEntityController.java
@@ -0,0 +1,403 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.admin.AdminDistributedSystem;
+import com.gemstone.gemfire.admin.DistributedSystemConfig;
+import com.gemstone.gemfire.admin.ManagedEntity;
+import com.gemstone.gemfire.admin.ManagedEntityConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.ProcessOutputReader;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.LoggingThreadGroup;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+
+/**
+ * Implements the actual administration (starting, stopping, etc.) of
+ * GemFire {@link ManagedEntity}s. It {@link Runtime#exec(java.lang.String) executes}
+ * commands to administer the entities based on information provided
+ * by the {@link InternalManagedEntity} object. Note that it does not
+ * use <code>SystemAdmin</code> to manage "local" entities; it always
+ * execs the scripts.
+ *
+ * <P>
+ *
+ * This class is a refactoring of <code>Systemcontroller</code>,
+ * <code>RemoteCommand</code>, and <code>LocatorRemoteCommand</code>.
+ *
+ * @author David Whitlock
+ * @author Kirk Lund (original SystemController)
+ * @since 4.0
+ */
+class EnabledManagedEntityController implements ManagedEntityController {
+ private static final Logger logger = LogService.getLogger();
+
+// /** A lock to ensure that only entity is managed at a time. See bug
+// * 31374. */
+// private static Object startStopLock = new Object();
+
+ /** Known strings found in output indicating error. */
+ private static final String[] ERROR_OUTPUTS = new String[] {
+ "No such file or directory",
+ "The system cannot find the file specified.",
+ "Access is denied.",
+ "cannot open",
+ "ERROR"
+ };
+
+ /** Token in command prefix to be replaced with actual HOST */
+ private static final String HOST = "{HOST}";
+
+ /** Token in command prefix to be replaced with actual execution CMD */
+ private static final String CMD = "{CMD}";
+
+ ////////////////////// Instance Fields //////////////////////
+
+ /** The thread group in which threads launched by this system
+ * controller reside. */
+ private final ThreadGroup threadGroup;
+
+ /** System to which the managed entities belong */
+ private final AdminDistributedSystem system;
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>ManagedEntityController</code> for entities
+ * in the given distributed system.
+ */
+ EnabledManagedEntityController(AdminDistributedSystem system) {
+ this.system = system;
+ this.threadGroup =
+ LoggingThreadGroup.createThreadGroup("ManagedEntityController threads", logger);
+ }
+
+ ///////////////////// Instance Methods /////////////////////
+
+ /**
+ * Returns <code>true</code> if the <code>output</code> string
+ * contains a known error message.
+ */
+ private boolean outputIsError(String output) {
+ if (output == null) return false;
+ boolean error = false;
+ for (int i = 0; i < ERROR_OUTPUTS.length; i++) {
+ error = output.indexOf(ERROR_OUTPUTS[i]) > -1;
+ if (error) return error;
+ }
+ return error;
+ }
+
+ /**
+ * Executes a command using {@link Runtime#exec(java.lang.String)}.
+ *
+ * @param command
+ * The full command to remotely execute
+ *
+ * @return Output from the command that was executed or
+ * <code>null</code> if the executing the command failed.
+ */
+ protected String execute(String command,
+ InternalManagedEntity entity) {
+ /* TODO: this is getting ugly... clients of this method really need to
+ have the ability to do their own parsing/checking of 'output' */
+ if (command == null || command.length() == 0) {
+ throw new IllegalArgumentException(LocalizedStrings.ManagedEntityController_EXECUTION_COMMAND_IS_EMPTY.toLocalizedString());
+ }
+
+ File workingDir =
+ new File(entity.getEntityConfig().getWorkingDirectory());
+ logger.info(LocalizedMessage.create(LocalizedStrings.ManagedEntityController_EXECUTING_REMOTE_COMMAND_0_IN_DIRECTORY_1, new Object[] {command, workingDir}));
+ Process p = null;
+ try {
+ p = Runtime.getRuntime().exec(command, null /* env */,
+ workingDir);
+
+ } catch (java.io.IOException e) {
+ logger.fatal(LocalizedMessage.create(LocalizedStrings.ManagedEntityController_WHILE_EXECUTING_0, command), e);
+ return null;
+ }
+
+ final ProcessOutputReader pos = new ProcessOutputReader(p);
+ int retCode = pos.getExitCode();
+ final String output = pos.getOutput();
+ logger.info(LocalizedMessage.create(LocalizedStrings.ManagedEntityController_RESULT_OF_EXECUTING_0_IS_1, new Object[] {command, Integer.valueOf(retCode)}));
+ logger.info(LocalizedMessage.create(LocalizedStrings.ManagedEntityController_OUTPUT_OF_0_IS_1, new Object[] {command, output}));
+
+ if (retCode != 0 || outputIsError(output)) {
+ logger.warn(LocalizedMessage.create(LocalizedStrings.ManagedEntityController_REMOTE_EXECUTION_OF_0_FAILED, command));
+ return null;
+ }
+
+ return output;
+ }
+
+ /** Returns true if the path ends with a path separator. */
+ private boolean endsWithSeparator(String path) {
+ return path.endsWith("/") || path.endsWith("\\");
+ }
+
+ /** Translates the path between Windows and UNIX. */
+ private String getOSPath(String path) {
+ if (pathIsWindows(path)) {
+ return path.replace('/', '\\');
+ } else {
+ return path.replace('\\', '/');
+ }
+ }
+
+// /** Returns true if the path is on Windows. */
+// private boolean pathIsWindows(File path) {
+// return pathIsWindows(path.toString());
+// }
+
+ /** Returns true if the path is on Windows. */
+ private boolean pathIsWindows(String path) {
+ if (path != null && path.length() > 1) {
+ return (Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') ||
+ (path.startsWith("//") || path.startsWith("\\\\"));
+ }
+ return false;
+ }
+
+ /**
+ * If the managed entity resides on a remote host, then
+ * <code>command</code> is munged to take the remote command into account.
+ *
+ * @throws IllegalStateException
+ * If a remote command is required, but one has not been
+ * specified.
+ */
+ private String arrangeRemoteCommand(InternalManagedEntity entity,
+ String cmd) {
+
+ String host = entity.getEntityConfig().getHost();
+ if (InetAddressUtil.isLocalHost(host)) {
+ // No arranging necessary
+ return cmd;
+ }
+
+ String prefix = entity.getEntityConfig().getRemoteCommand();
+ if (prefix == null || prefix.length() <= 0) {
+ prefix = entity.getDistributedSystem().getRemoteCommand();
+ }
+
+ if (prefix == null || prefix.length() <= 0) {
+ throw new IllegalStateException(LocalizedStrings.ManagedEntityController_A_REMOTE_COMMAND_MUST_BE_SPECIFIED_TO_OPERATE_ON_A_MANAGED_ENTITY_ON_HOST_0
+ .toLocalizedString(host));
+ }
+
+ int hostIdx = prefix.indexOf(HOST);
+ int cmdIdx = prefix.indexOf(CMD);
+ if (hostIdx == -1 && cmdIdx == -1) {
+ return prefix + " " + host + " " + cmd;
+ }
+
+ if (hostIdx >= 0) {
+ String start = prefix.substring(0, hostIdx);
+ String end = null;
+ if (hostIdx + HOST.length() >= prefix.length()) {
+ end = "";
+ } else {
+ end = prefix.substring(hostIdx + HOST.length());
+ }
+ prefix = start + host + end;
+ cmdIdx = prefix.indexOf(CMD); //recalculate;
+ }
+
+ if (cmdIdx >= 0) {
+ String start = prefix.substring(0, cmdIdx);
+ String end = null;
+ if (cmdIdx + CMD.length() >= prefix.length()) {
+ end = "";
+ } else {
+ end = prefix.substring(cmdIdx + CMD.length());
+ }
+ prefix = start + cmd + end;
+ }
+ return prefix;
+ }
+
+ /**
+ * Returns the full path to the executable in
+ * <code>$GEMFIRE/bin</code> taking into account the {@linkplain
+ * ManagedEntityConfig#getProductDirectory product directory} and the
+ * platform's file separator.
+ *
+ * <P>
+ *
+ * Note: we should probably do a better job of determine whether or
+ * not the machine on which the entity runs is Windows or Linux.
+ *
+ * @param executable
+ * The name of the executable that resides in
+ * <code>$GEMFIRE/bin</code>.
+ */
+ public String getProductExecutable(InternalManagedEntity entity,
+ String executable) {
+ String productDirectory =
+ entity.getEntityConfig().getProductDirectory();
+ String path = null;
+ File productDir = new File(productDirectory);
+// if (productDir != null) (cannot be null)
+ {
+ path = productDir.getPath();
+ if (!endsWithSeparator(path)) {
+ path += File.separator;
+ }
+ path += "bin" + File.separator;
+ }
+// else {
+// path = "";
+// }
+
+ String bat = "";
+ if (pathIsWindows(path)) {
+ bat = ".bat";
+ }
+ return getOSPath(path) + executable + bat;
+ }
+
+ /**
+ * Builds optional SSL command-line arguments. Returns null if SSL is not
+ * enabled for the distributed system.
+ */
+ public String buildSSLArguments(DistributedSystemConfig config) {
+ Properties sslProps = buildSSLProperties(config, true);
+ if (sslProps == null) return null;
+
+ StringBuffer sb = new StringBuffer();
+ for (Iterator iter = sslProps.keySet().iterator(); iter.hasNext();) {
+ String key = (String) iter.next();
+ String value = sslProps.getProperty(key);
+ sb.append(" -J-D" + key + "=" + value);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Builds optional SSL properties for DistributionLocator. Returns null if SSL
+ * is not enabled for the distributed system.
+ *
+ * @param forCommandLine
+ * true indicates that
+ * {@link DistributionConfig#GEMFIRE_PREFIX} should be
+ * prepended so the argument will become -Dgemfire.xxxx
+ */
+ private Properties buildSSLProperties(DistributedSystemConfig config,
+ boolean forCommandLine) {
+ if (!config.isSSLEnabled()) return null;
+
+ String prefix = "";
+ if (forCommandLine) prefix = DistributionConfig.GEMFIRE_PREFIX;
+
+ Properties sslProps = (Properties) config.getSSLProperties().clone();
+ // add ssl-enabled, etc...
+ sslProps.setProperty(prefix +
+ DistributionConfig.MCAST_PORT_NAME,
+ "0");
+ sslProps.setProperty(prefix +
+ DistributionConfig.SSL_ENABLED_NAME,
+ String.valueOf(config.isSSLEnabled()));
+ sslProps.setProperty(prefix +
+ DistributionConfig.SSL_CIPHERS_NAME,
+ config.getSSLCiphers());
+ sslProps.setProperty(prefix +
+ DistributionConfig.SSL_PROTOCOLS_NAME,
+ config.getSSLProtocols());
+ sslProps.setProperty(prefix +
+ DistributionConfig.SSL_REQUIRE_AUTHENTICATION_NAME,
+ String.valueOf(config.isSSLAuthenticationRequired()));
+ return sslProps;
+ }
+
+
+ /**
+ * Starts a managed entity.
+ */
+ public void start(final InternalManagedEntity entity) {
+ final String command =
+ arrangeRemoteCommand(entity, entity.getStartCommand());
+ Thread start = new Thread(this.threadGroup, new Runnable() {
+ public void run() {
+ execute(command, entity);
+ }
+ }, "Start " + entity.getEntityType());
+ start.start();
+ }
+
+ /**
+ * Stops a managed entity.
+ */
+ public void stop(final InternalManagedEntity entity) {
+ final String command =
+ arrangeRemoteCommand(entity, entity.getStopCommand());
+ Thread stop = new Thread(this.threadGroup, new Runnable() {
+ public void run() {
+ execute(command, entity);
+ }
+ }, "Stop " + entity.getEntityType());
+ stop.start();
+ }
+
+ /**
+ * Returns whether or not a managed entity is running
+ */
+ public boolean isRunning(InternalManagedEntity entity) {
+ final String command =
+ arrangeRemoteCommand(entity, entity.getIsRunningCommand());
+ String output = execute(command, entity);
+
+ if (output == null ||
+ (output.indexOf("stop" /* "ing" "ped" */) != -1) ||
+ (output.indexOf("killed") != -1) ||
+ (output.indexOf("starting") != -1)) {
+ return false;
+
+ } else if (output.indexOf("running") != -1) {
+ return true;
+
+ } else {
+ throw new IllegalStateException(LocalizedStrings.ManagedEntityController_COULD_NOT_DETERMINE_IF_MANAGED_ENTITY_WAS_RUNNING_0
+ .toLocalizedString(output));
+ }
+ }
+
+ /**
+ * Returns the contents of a locator's log file. Other APIs are
+ * used to get the log file of managed entities that are also system
+ * members.
+ */
+ public String getLog(DistributionLocatorImpl locator) {
+ String command =
+ arrangeRemoteCommand(locator, locator.getLogCommand());
+ return execute(command, locator);
+ }
+
+ /**
+ * Returns the contents of the given directory using the given
+ * managed entity to determine the host and remote command.
+ */
+ private String listDirectory(InternalManagedEntity entity,
+ String dir) {
+ ManagedEntityConfig config = entity.getEntityConfig();
+ String listFile =
+ pathIsWindows(config.getProductDirectory()) ? "dir " : "ls ";
+ String command =
+ arrangeRemoteCommand(entity, listFile + dir);
+ return execute(command, entity);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java
new file mode 100644
index 0000000..c464a75
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupRequest.java
@@ -0,0 +1,159 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.CancelException;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.cache.persistence.PersistentID;
+import com.gemstone.gemfire.distributed.DistributedMember;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.DistributionManager;
+import com.gemstone.gemfire.distributed.internal.DistributionMessage;
+import com.gemstone.gemfire.distributed.internal.ReplyException;
+import com.gemstone.gemfire.internal.admin.remote.AdminFailureResponse;
+import com.gemstone.gemfire.internal.admin.remote.AdminMultipleReplyProcessor;
+import com.gemstone.gemfire.internal.admin.remote.AdminResponse;
+import com.gemstone.gemfire.internal.admin.remote.CliLegacyMessage;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+
+/**
+ * A request send from an admin VM to all of the peers to indicate
+ * that that should complete the backup operation.
+ *
+ * @author dsmith
+ *
+ */
+public class FinishBackupRequest extends CliLegacyMessage {
+ private static final Logger logger = LogService.getLogger();
+
+ private File targetDir;
+ private File baselineDir;
+
+ public FinishBackupRequest() {
+ super();
+ }
+
+ public FinishBackupRequest(File targetDir,File baselineDir) {
+ this.targetDir = targetDir;
+ this.baselineDir = baselineDir;
+ }
+
+ public static Map<DistributedMember, Set<PersistentID>> send(DM dm, Set recipients, File targetDir, File baselineDir) {
+ FinishBackupRequest request = new FinishBackupRequest(targetDir,baselineDir);
+ request.setRecipients(recipients);
+
+ FinishBackupReplyProcessor replyProcessor = new FinishBackupReplyProcessor(dm, recipients);
+ request.msgId = replyProcessor.getProcessorId();
+ dm.putOutgoing(request);
+ try {
+ replyProcessor.waitForReplies();
+ } catch (ReplyException e) {
+ if(!(e.getCause() instanceof CancelException)) {
+ throw e;
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ AdminResponse response = request.createResponse((DistributionManager)dm);
+ response.setSender(dm.getDistributionManagerId());
+ replyProcessor.process(response);
+ return replyProcessor.results;
+ }
+
+ @Override
+ protected AdminResponse createResponse(DistributionManager dm) {
+ GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
+ HashSet<PersistentID> persistentIds;
+ if(cache == null) {
+ persistentIds = new HashSet<PersistentID>();
+ } else {
+ try {
+ persistentIds = cache.getBackupManager().finishBackup(targetDir, baselineDir);
+ } catch (IOException e) {
+ logger.error(LocalizedMessage.create(LocalizedStrings.CliLegacyMessage_ERROR, this.getClass()), e);
+ return AdminFailureResponse.create(dm, getSender(), e);
+ }
+ }
+
+ return new FinishBackupResponse(this.getSender(), persistentIds);
+ }
+
+ public int getDSFID() {
+ return FINISH_BACKUP_REQUEST;
+ }
+
+ @Override
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ super.fromData(in);
+ targetDir = DataSerializer.readFile(in);
+ baselineDir = DataSerializer.readFile(in);
+ }
+
+ @Override
+ public void toData(DataOutput out) throws IOException {
+ super.toData(out);
+ DataSerializer.writeFile(targetDir, out);
+ DataSerializer.writeFile(baselineDir, out);
+ }
+
+ private static class FinishBackupReplyProcessor extends AdminMultipleReplyProcessor {
+ Map<DistributedMember, Set<PersistentID>> results = Collections.synchronizedMap(new HashMap<DistributedMember, Set<PersistentID>>());
+ public FinishBackupReplyProcessor(DM dm, Collection initMembers) {
+ super(dm, initMembers);
+ }
+
+ @Override
+ protected boolean stopBecauseOfExceptions() {
+ return false;
+ }
+
+
+
+ @Override
+ protected int getAckWaitThreshold() {
+ //Disable the 15 second warning if the backup is taking a long time
+ return 0;
+ }
+
+ @Override
+ public long getAckSevereAlertThresholdMS() {
+ //Don't log severe alerts for backups either
+ return Long.MAX_VALUE;
+ }
+
+ @Override
+ protected void process(DistributionMessage msg, boolean warn) {
+ if(msg instanceof FinishBackupResponse) {
+ final HashSet<PersistentID> persistentIds = ((FinishBackupResponse) msg).getPersistentIds();
+ if(persistentIds != null && !persistentIds.isEmpty()) {
+ results.put(msg.getSender(), persistentIds);
+ }
+ }
+ super.process(msg, warn);
+ }
+
+
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupResponse.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupResponse.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupResponse.java
new file mode 100644
index 0000000..998c0c3
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FinishBackupResponse.java
@@ -0,0 +1,70 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashSet;
+
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.cache.persistence.PersistentID;
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+import com.gemstone.gemfire.internal.admin.remote.AdminResponse;
+
+/**
+ * The reply for a {@link FinishBackupRequest}. The
+ * reply contains the persistent ids of the disk stores
+ * that were backed up on this member.
+ *
+ * @author dsmith
+ *
+ */
+public class FinishBackupResponse extends AdminResponse {
+
+ private HashSet<PersistentID> persistentIds;
+
+ public FinishBackupResponse() {
+ super();
+ }
+
+ public FinishBackupResponse(InternalDistributedMember sender, HashSet<PersistentID> persistentIds) {
+ this.setRecipient(sender);
+ this.persistentIds = persistentIds;
+ }
+
+ public HashSet<PersistentID> getPersistentIds() {
+ return persistentIds;
+ }
+
+ @Override
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ super.fromData(in);
+ persistentIds = DataSerializer.readHashSet(in);
+ }
+
+ @Override
+ public void toData(DataOutput out) throws IOException {
+ super.toData(out);
+ DataSerializer.writeHashSet(persistentIds, out);
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ public int getDSFID() {
+ return FINISH_BACKUP_RESPONSE;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName() + ": " + persistentIds;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskRequest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskRequest.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskRequest.java
new file mode 100644
index 0000000..3336aa2
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskRequest.java
@@ -0,0 +1,89 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.gemstone.gemfire.CancelException;
+import com.gemstone.gemfire.cache.persistence.PersistentID;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.DistributionManager;
+import com.gemstone.gemfire.distributed.internal.ReplyException;
+import com.gemstone.gemfire.internal.admin.remote.AdminMultipleReplyProcessor;
+import com.gemstone.gemfire.internal.admin.remote.AdminResponse;
+import com.gemstone.gemfire.internal.admin.remote.CliLegacyMessage;
+import com.gemstone.gemfire.internal.cache.DiskStoreImpl;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+
+/**
+ * A request to from an admin VM to all non admin members
+ * to start a backup. In the prepare phase of the backup,
+ * the members will suspend bucket destroys to make sure
+ * buckets aren't missed during the backup.
+ *
+ * @author dsmith
+ *
+ */
+public class FlushToDiskRequest extends CliLegacyMessage {
+
+ public FlushToDiskRequest() {
+
+ }
+
+ public static void send(DM dm, Set recipients) {
+ FlushToDiskRequest request = new FlushToDiskRequest();
+ request.setRecipients(recipients);
+
+ FlushToDiskProcessor replyProcessor = new FlushToDiskProcessor(dm, recipients);
+ request.msgId = replyProcessor.getProcessorId();
+ dm.putOutgoing(request);
+ try {
+ replyProcessor.waitForReplies();
+ } catch (ReplyException e) {
+ if(!(e.getCause() instanceof CancelException)) {
+ throw e;
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ AdminResponse response = request.createResponse((DistributionManager)dm);
+ response.setSender(dm.getDistributionManagerId());
+ replyProcessor.process(response);
+ }
+
+ @Override
+ protected AdminResponse createResponse(DistributionManager dm) {
+ GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
+ HashSet<PersistentID> persistentIds;
+ if(cache != null) {
+ Collection<DiskStoreImpl> diskStores = cache.listDiskStoresIncludingRegionOwned();
+ for(DiskStoreImpl store : diskStores) {
+ store.flush();
+ }
+ }
+
+ return new FlushToDiskResponse(this.getSender());
+ }
+
+ public int getDSFID() {
+ return FLUSH_TO_DISK_REQUEST;
+ }
+
+ private static class FlushToDiskProcessor extends AdminMultipleReplyProcessor {
+ public FlushToDiskProcessor(DM dm, Collection initMembers) {
+ super(dm, initMembers);
+ }
+
+ @Override
+ protected boolean stopBecauseOfExceptions() {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskResponse.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskResponse.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskResponse.java
new file mode 100644
index 0000000..b08b133
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/FlushToDiskResponse.java
@@ -0,0 +1,37 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+import com.gemstone.gemfire.internal.admin.remote.AdminResponse;
+
+/**
+ * The response to the {@link FlushToDiskRequest}
+ *
+ * @author dsmith
+ *
+ */
+public class FlushToDiskResponse extends AdminResponse {
+
+ public FlushToDiskResponse() {
+ super();
+ }
+
+ public FlushToDiskResponse(InternalDistributedMember sender) {
+ this.setRecipient(sender);
+ }
+
+ public int getDSFID() {
+ return FLUSH_TO_DISK_RESPONSE;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthConfigImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthConfigImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthConfigImpl.java
new file mode 100644
index 0000000..61e5022
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthConfigImpl.java
@@ -0,0 +1,75 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import com.gemstone.gemfire.admin.*;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+// @todo davidw Delegate to a "parent" config for properties that are not overridden.
+// This will be made easier with a special <code>HealthConfigAttribute</code> class.
+/**
+ * The implementation of <code>GemFireHealthConfig</code>
+ *
+ *
+ * @author David Whitlock
+ *
+ * @since 3.5
+ */
+public class GemFireHealthConfigImpl
+ extends CacheHealthConfigImpl
+ implements GemFireHealthConfig {
+
+ private static final long serialVersionUID = -6797673296902808018L;
+
+ /** The name of the host to which this configuration applies. */
+ private String hostName;
+
+ /** The number of seconds to wait between evaluating the health of
+ * GemFire. */
+ private int interval = DEFAULT_HEALTH_EVALUATION_INTERVAL;
+
+ //////////////////////// Constructors ////////////////////////
+
+ /**
+ * Creates a new <code>GemFireHealthConfigImpl</code> that applies
+ * to the host with the given name.
+ *
+ * @param hostName
+ * The name of the host to which this configuration applies.
+ * If <code>null</code>, then this is the "default"
+ * configuration.
+ */
+ public GemFireHealthConfigImpl(String hostName) {
+ this.hostName = hostName;
+ }
+
+ /////////////////////// Instance Methods ///////////////////////
+
+ public String getHostName() {
+ return this.hostName;
+ }
+
+ public void setHealthEvaluationInterval(int interval) {
+ this.interval = interval;
+ }
+
+ public int getHealthEvaluationInterval() {
+ return this.interval;
+ }
+
+ @Override
+ public String toString() {
+ if (this.hostName == null) {
+ return LocalizedStrings.GemFireHealthConfigImpl_DEFAULT_GEMFIRE_HEALTH_CONFIGURATION.toLocalizedString();
+
+ } else {
+ return LocalizedStrings.GemFireHealthConfigImpl_GEMFIRE_HEALTH_CONFIGURATION_FOR_HOST_0.toLocalizedString(this.hostName);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthEvaluator.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthEvaluator.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthEvaluator.java
new file mode 100644
index 0000000..f5647a9
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/GemFireHealthEvaluator.java
@@ -0,0 +1,179 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.admin.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.admin.GemFireHealth;
+import com.gemstone.gemfire.admin.GemFireHealthConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionManager;
+import com.gemstone.gemfire.internal.Assert;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+
+/**
+ * Evaluates the health of various GemFire components in the VM
+ * according to a {@link GemFireHealthConfig}.
+ *
+ * <P>
+ *
+ * Note that evaluators never reside in the administration VM, they
+ * only in member VMs. They are not <code>Serializable</code> and
+ * aren't meant to be.
+ *
+ * @see MemberHealthEvaluator
+ * @see CacheHealthEvaluator
+ *
+ * @author David Whitlock
+ *
+ * @since 3.5
+ */
+public class GemFireHealthEvaluator {
+
+ private static final Logger logger = LogService.getLogger();
+
+ /** Determines how the health of GemFire is determined */
+ private GemFireHealthConfig config;
+
+ /** Evaluates the health of this member of the distributed system */
+ private MemberHealthEvaluator memberHealth;
+
+ /** Evaluates the health of the Cache hosted in this VM */
+ private CacheHealthEvaluator cacheHealth;
+
+ /** The most recent <code>OKAY_HEALTH</code> diagnoses of the
+ * GemFire system */
+ private List okayDiagnoses;
+
+ /** The most recent <code>POOR_HEALTH</code> diagnoses of the
+ * GemFire system */
+ private List poorDiagnoses;
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>GemFireHealthEvaluator</code>
+ *
+ * @param config
+ * The configuration that determines whether or GemFire is
+ * healthy
+ * @param dm
+ * The distribution manager
+ */
+ public GemFireHealthEvaluator(GemFireHealthConfig config,
+ DistributionManager dm) {
+ if (config == null) {
+ throw new NullPointerException(LocalizedStrings.GemFireHealthEvaluator_NULL_GEMFIREHEALTHCONFIG.toLocalizedString());
+ }
+
+ this.config = config;
+ this.memberHealth = new MemberHealthEvaluator(config, dm);
+ this.cacheHealth = new CacheHealthEvaluator(config, dm);
+ this.okayDiagnoses = new ArrayList();
+ this.poorDiagnoses = new ArrayList();
+ }
+
+ ////////////////////// Instance Methods //////////////////////
+
+ /**
+ * Evaluates the health of the GemFire components in this VM.
+ *
+ * @return The aggregate health code (such as {@link
+ * GemFireHealth#OKAY_HEALTH}) of the GemFire components.
+ */
+ public GemFireHealth.Health evaluate() {
+ List status = new ArrayList();
+ this.memberHealth.evaluate(status);
+ this.cacheHealth.evaluate(status);
+
+ GemFireHealth.Health overallHealth = GemFireHealth.GOOD_HEALTH;
+ this.okayDiagnoses.clear();
+ this.poorDiagnoses.clear();
+
+ for (Iterator iter = status.iterator(); iter.hasNext(); ) {
+ AbstractHealthEvaluator.HealthStatus health =
+ (AbstractHealthEvaluator.HealthStatus) iter.next();
+ if (overallHealth == GemFireHealth.GOOD_HEALTH) {
+ if ((health.getHealthCode() != GemFireHealth.GOOD_HEALTH)) {
+ overallHealth = health.getHealthCode();
+ }
+
+ } else if (overallHealth == GemFireHealth.OKAY_HEALTH) {
+ if (health.getHealthCode() == GemFireHealth.POOR_HEALTH) {
+ overallHealth = GemFireHealth.POOR_HEALTH;
+ }
+ }
+
+ GemFireHealth.Health healthCode = health.getHealthCode();
+ if (healthCode == GemFireHealth.OKAY_HEALTH) {
+ this.okayDiagnoses.add(health.getDiagnosis());
+
+ } else if (healthCode == GemFireHealth.POOR_HEALTH) {
+ this.poorDiagnoses.add(health.getDiagnosis());
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Evaluated health to be {}", overallHealth);
+ }
+ return overallHealth;
+ }
+
+ /**
+ * Returns detailed information explaining the current health status.
+ * Each array element is a different cause for the current status.
+ * An empty array will be returned if the current status is {@link
+ * GemFireHealth#GOOD_HEALTH}.
+ */
+ public String[] getDiagnosis(GemFireHealth.Health healthCode) {
+ if (healthCode == GemFireHealth.GOOD_HEALTH) {
+ return new String[0];
+
+ } else if (healthCode == GemFireHealth.OKAY_HEALTH) {
+ String[] array = new String[this.okayDiagnoses.size()];
+ this.okayDiagnoses.toArray(array);
+ return array;
+
+ } else {
+ Assert.assertTrue(healthCode == GemFireHealth.POOR_HEALTH);
+ String[] array = new String[this.poorDiagnoses.size()];
+ this.poorDiagnoses.toArray(array);
+ return array;
+ }
+ }
+
+ /**
+ * Resets the state of this evaluator
+ */
+ public void reset() {
+ this.okayDiagnoses.clear();
+ this.poorDiagnoses.clear();
+ }
+
+ /**
+ * Returns the heath evaluation interval, in seconds.
+ *
+ * @see GemFireHealthConfig#getHealthEvaluationInterval
+ */
+ public int getEvaluationInterval() {
+ return this.config.getHealthEvaluationInterval();
+ }
+
+ /**
+ * Closes this evaluator and releases all of its resources
+ */
+ public void close() {
+ this.memberHealth.close();
+ this.cacheHealth.close();
+ }
+
+}