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:46 UTC
[41/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/BackupStatusImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupStatusImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupStatusImpl.java
new file mode 100644
index 0000000..60e078d
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/BackupStatusImpl.java
@@ -0,0 +1,53 @@
+/*=========================================================================
+ * 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.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+import com.gemstone.gemfire.admin.BackupStatus;
+import com.gemstone.gemfire.cache.persistence.PersistentID;
+import com.gemstone.gemfire.distributed.DistributedMember;
+
+/**
+ * Holds the result of a backup operation.
+ *
+ * @author dsmith
+ *
+ */
+public class BackupStatusImpl implements BackupStatus, Serializable {
+ private static final long serialVersionUID = 3704162840296921840L;
+
+ private Map<DistributedMember, Set<PersistentID>> backedUpDiskStores;
+ private Set<PersistentID> offlineDiskStores;
+
+ public BackupStatusImpl(
+ Map<DistributedMember, Set<PersistentID>> backedUpDiskStores,
+ Set<PersistentID> offlineDiskStores) {
+ super();
+ this.backedUpDiskStores = backedUpDiskStores;
+ this.offlineDiskStores = offlineDiskStores;
+ }
+
+ public Map<DistributedMember, Set<PersistentID>> getBackedUpDiskStores() {
+ return backedUpDiskStores;
+ }
+
+ public Set<PersistentID> getOfflineDiskStores() {
+ return offlineDiskStores;
+ }
+
+ @Override
+ public String toString() {
+ return "BackupStatus[backedUpDiskStores=" + backedUpDiskStores + ", offlineDiskStores=" + offlineDiskStores + "]";
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthConfigImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthConfigImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthConfigImpl.java
new file mode 100644
index 0000000..d06dee7
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthConfigImpl.java
@@ -0,0 +1,83 @@
+/*=========================================================================
+ * 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.*;
+
+/**
+ * The implementation of <code>CacheHealthConfig</code>
+ *
+ * @author David Whitlock
+ *
+ * @since 3.5
+ */
+public abstract class CacheHealthConfigImpl
+ extends MemberHealthConfigImpl implements CacheHealthConfig {
+
+ /** The maximum number of milliseconds a
+ * <code>netSearch</code> operation can take before the cache member
+ * is considered to be unhealthy. */
+ private long maxNetSearchTime = DEFAULT_MAX_NET_SEARCH_TIME;
+
+ /** The maximum mumber of milliseconds a cache
+ * <code>load</code> operation can take before the cache member is
+ * considered to be unhealthy. */
+ private long maxLoadTime = DEFAULT_MAX_LOAD_TIME;
+
+ /** The minimum hit ratio of a healthy cache member. */
+ private double minHitRatio = DEFAULT_MIN_HIT_RATIO;
+
+ /** The maximum number of entries in the event delivery queue
+ * of a healthy cache member. */
+ private long maxEventQueueSize = DEFAULT_MAX_EVENT_QUEUE_SIZE;
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>CacheHealthConfigImpl</code> with the default
+ * configuration.
+ */
+ CacheHealthConfigImpl() {
+
+ }
+
+ ////////////////////// Instance Methods /////////////////////
+
+ public long getMaxNetSearchTime() {
+ return this.maxNetSearchTime;
+ }
+
+ public void setMaxNetSearchTime(long maxNetSearchTime) {
+ this.maxNetSearchTime = maxNetSearchTime;
+ }
+
+ public long getMaxLoadTime() {
+ return this.maxLoadTime;
+ }
+
+ public void setMaxLoadTime(long maxLoadTime) {
+ this.maxLoadTime = maxLoadTime;
+ }
+
+ public double getMinHitRatio() {
+ return this.minHitRatio;
+ }
+
+ public void setMinHitRatio(double minHitRatio) {
+ this.minHitRatio = minHitRatio;
+ }
+
+ public long getMaxEventQueueSize() {
+ return this.maxEventQueueSize;
+ }
+
+ public void setMaxEventQueueSize(long maxEventQueueSize) {
+ this.maxEventQueueSize = maxEventQueueSize;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthEvaluator.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthEvaluator.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthEvaluator.java
new file mode 100644
index 0000000..e9b89e0
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheHealthEvaluator.java
@@ -0,0 +1,315 @@
+/*=========================================================================
+ * 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.List;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.CancelException;
+import com.gemstone.gemfire.admin.CacheHealthConfig;
+import com.gemstone.gemfire.admin.GemFireHealthConfig;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.internal.OSProcess;
+import com.gemstone.gemfire.internal.cache.CacheLifecycleListener;
+import com.gemstone.gemfire.internal.cache.CachePerfStats;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+
+/**
+ * Contains the logic for evaluating the health of a GemFire
+ * <code>Cache</code> instance according to the thresholds provided in
+ * a {@link CacheHealthConfig}.
+ *
+ * @author David Whitlock
+ *
+ * @since 3.5
+ */
+class CacheHealthEvaluator extends AbstractHealthEvaluator
+ implements CacheLifecycleListener {
+
+ private static final Logger logger = LogService.getLogger();
+
+ /** The config from which we get the evaulation criteria */
+ private CacheHealthConfig config;
+
+ /** The description of the cache being evaluated */
+ private String description;
+
+ /** Statistics about the <code>Cache</code> instance. If no cache
+ * has been created in this VM, this field will be <code>null</code>
+ */
+ private CachePerfStats cacheStats;
+
+ /** The previous value of the netsearchTime stat (in nanoseconds) */
+ private long prevNetsearchTime;
+
+ /** The previous value of the netsearchedCompleted stat */
+ private long prevNetsearchesCompleted;
+
+ /** The previous value of the loadTime stat (in nanoseconds) */
+ private long prevLoadTime;
+
+ /** The previous value of the loadedCompleted stat */
+ private long prevLoadsCompleted;
+
+ /** The previous value of the gets stat */
+ private long prevGets;
+
+ ////////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>CacheHealthEvaluator</code>
+ */
+ CacheHealthEvaluator(GemFireHealthConfig config,
+ DM dm) {
+ super(config, dm);
+
+ this.config = config;
+ InternalDistributedSystem system = dm.getSystem();
+ GemFireCacheImpl cache;
+ try {
+ cache = (GemFireCacheImpl) CacheFactory.getInstance(system);
+
+ } catch (CancelException ex) {
+ // No cache in this VM
+ cache = null;
+ }
+
+ initialize(cache, dm);
+ GemFireCacheImpl.addCacheLifecycleListener(this);
+ }
+
+ //////////////////// Instance Methods ////////////////////
+
+ @Override
+ protected String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * Initializes the state of this evaluator based on the given cache
+ * instance.
+ */
+ private void initialize(GemFireCacheImpl cache, DM dm) {
+ StringBuffer sb = new StringBuffer();
+ if (cache != null) {
+ this.cacheStats = cache.getCachePerfStats();
+
+ sb.append("Cache \"");
+ sb.append(cache.getName());
+ sb.append("\"");
+
+ } else {
+ sb.append("No Cache");
+ }
+
+ sb.append(" in member ");
+ sb.append(dm.getId());
+ int pid = OSProcess.getId();
+ if (pid != 0) {
+ sb.append(" with pid ");
+ sb.append(pid);
+ }
+ this.description = sb.toString();
+ }
+
+ public void cacheCreated(GemFireCacheImpl cache) {
+ InternalDistributedSystem system =
+ (InternalDistributedSystem) cache.getDistributedSystem();
+ DM dm = system.getDistributionManager();
+ initialize(cache, dm);
+ }
+
+ /**
+ * Checks to make sure that the average <code>netSearch</code> time
+ * during the previous health check interval is less than the
+ * {@linkplain CacheHealthConfig#getMaxNetSearchTime threshold}. If
+ * not, the status is "okay" health.
+ *
+ * @see CachePerfStats#getNetsearchTime
+ * @see CachePerfStats#getNetsearchesCompleted
+ */
+ void checkNetSearchTime(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ long deltaNetsearchTime =
+ this.cacheStats.getNetsearchTime() - this.prevNetsearchTime;
+ long deltaNetsearchesCompleted =
+ this.cacheStats.getNetsearchesCompleted() -
+ this.prevNetsearchesCompleted;
+
+ if (deltaNetsearchesCompleted != 0) {
+ long ratio = deltaNetsearchTime / deltaNetsearchesCompleted;
+ ratio /= 1000000;
+ long threshold = this.config.getMaxNetSearchTime();
+
+ if (ratio > threshold) {
+ String s = LocalizedStrings.CacheHealthEvaluator_THE_AVERAGE_DURATION_OF_A_CACHE_NETSEARCH_0_MS_EXCEEDS_THE_THRESHOLD_1_MS.toLocalizedString(new Object[] { ratio, threshold });
+ status.add(okayHealth(s));
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure that the average <code>load</code> time
+ * during the previous health check interval is less than the
+ * {@linkplain CacheHealthConfig#getMaxLoadTime threshold}. If
+ * not, the status is "okay" health.
+ *
+ * @see CachePerfStats#getLoadTime
+ * @see CachePerfStats#getLoadsCompleted
+ */
+ void checkLoadTime(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ if (!isFirstEvaluation()) {
+ long deltaLoadTime =
+ this.cacheStats.getLoadTime() - this.prevLoadTime;
+ long deltaLoadsCompleted =
+ this.cacheStats.getLoadsCompleted() -
+ this.prevLoadsCompleted;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Completed {} loads in {} ms", deltaLoadsCompleted, (deltaLoadTime / 1000000));
+ }
+
+ if (deltaLoadsCompleted != 0) {
+ long ratio = deltaLoadTime / deltaLoadsCompleted;
+ ratio /= 1000000;
+ long threshold = this.config.getMaxLoadTime();
+
+ if (ratio > threshold) {
+ String s = LocalizedStrings.CacheHealthEvaluator_THE_AVERAGE_DURATION_OF_A_CACHE_LOAD_0_MS_EXCEEDS_THE_THRESHOLD_1_MS.toLocalizedString(new Object[] { ratio, threshold });
+ if (logger.isDebugEnabled()) {
+ logger.debug(s);
+ }
+ status.add(okayHealth(s));
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure that the cache hit ratio during the previous
+ * health check interval is less than the {@linkplain
+ * CacheHealthConfig#getMinHitRatio threshold}. If not, the status
+ * is "okay" health.
+ *
+ * <P>
+ *
+ * The following formula is used to compute the hit ratio:
+ *
+ * <PRE>
+ * hitRatio = (gets - (loadsCompleted + netsearchesCompleted)) / (gets)
+ * </PRE>
+ *
+ *
+ * @see CachePerfStats#getGets
+ * @see CachePerfStats#getLoadsCompleted
+ * @see CachePerfStats#getNetsearchesCompleted
+ */
+ void checkHitRatio(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ long deltaGets = this.cacheStats.getGets() - this.prevGets;
+ if (deltaGets != 0) {
+ long deltaLoadsCompleted =
+ this.cacheStats.getLoadsCompleted() - this.prevLoadsCompleted;
+ long deltaNetsearchesCompleted =
+ this.cacheStats.getNetsearchesCompleted() -
+ this.prevNetsearchesCompleted;
+
+ double hits =
+ (deltaGets -
+ (deltaLoadsCompleted + deltaNetsearchesCompleted));
+ double hitRatio = hits / deltaGets;
+ double threshold = this.config.getMinHitRatio();
+ if (hitRatio < threshold) {
+ String s = "The hit ratio of this Cache (" + hitRatio +
+ ") is below the threshold (" + threshold + ")";
+ status.add(okayHealth(s));
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure that the {@linkplain
+ * CachePerfStats#getEventQueueSize cache event queue size} does
+ * not exceed the {@linkplain CacheHealthConfig#getMaxEventQueueSize
+ * threshold}. If it does, the status is "okay" health.
+ */
+ void checkEventQueueSize(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ long eventQueueSize = this.cacheStats.getEventQueueSize();
+ long threshold = this.config.getMaxEventQueueSize();
+ if (eventQueueSize > threshold) {
+ String s = LocalizedStrings.CacheHealthEvaluator_THE_SIZE_OF_THE_CACHE_EVENT_QUEUE_0_MS_EXCEEDS_THE_THRESHOLD_1_MS.toLocalizedString(new Object[] { Long.valueOf(eventQueueSize), Long.valueOf(threshold) });
+ status.add(okayHealth(s));
+ }
+ }
+
+
+ /**
+ * Updates the previous values of statistics
+ */
+ private void updatePrevious() {
+ if (this.cacheStats != null && !this.cacheStats.isClosed()) {
+ this.prevLoadTime = this.cacheStats.getLoadTime();
+ this.prevLoadsCompleted = this.cacheStats.getLoadsCompleted();
+ this.prevNetsearchTime = this.cacheStats.getNetsearchTime();
+ this.prevNetsearchesCompleted =
+ this.cacheStats.getNetsearchesCompleted();
+ this.prevGets = this.cacheStats.getGets();
+
+ } else {
+ this.prevLoadTime = 0L;
+ this.prevLoadsCompleted = 0L;
+ this.prevNetsearchTime = 0L;
+ this.prevNetsearchesCompleted = 0L;
+ this.prevGets = 0L;
+ }
+ }
+
+ @Override
+ protected void check(List status) {
+
+ checkNetSearchTime(status);
+ checkLoadTime(status);
+ checkHitRatio(status);
+ checkEventQueueSize(status);
+
+ updatePrevious();
+ }
+
+ @Override
+ public void close() {
+ GemFireCacheImpl.removeCacheLifecycleListener(this);
+ }
+
+ @Override
+ public void cacheClosed(GemFireCacheImpl cache) {
+ // do nothing
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheServerConfigImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheServerConfigImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheServerConfigImpl.java
new file mode 100644
index 0000000..4e4e6b1
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheServerConfigImpl.java
@@ -0,0 +1,127 @@
+/*=========================================================================
+ * 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.CacheServerConfig;
+import com.gemstone.gemfire.admin.CacheVmConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.internal.admin.GemFireVM;
+
+/**
+ * An implementation of <code>CacheVmConfig</code>
+ *
+ * @author David Whitlock
+ * @since 4.0
+ */
+public class CacheServerConfigImpl extends ManagedEntityConfigImpl
+ implements CacheVmConfig, CacheServerConfig {
+
+ /** Declarative caching XML file that is used to initialize the
+ * Cache in the cache server. */
+ private String cacheXMLFile;
+
+ /** Extra classpath for the cache server */
+ private String classpath;
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>CacheServerConfigImpl</code> with the default
+ * configuration settings.
+ */
+ public CacheServerConfigImpl() {
+ this.cacheXMLFile = null;
+ this.classpath = null;
+ }
+
+ /**
+ * Creates a new <code>CacheServerConfigImpl</code> for a running
+ * cache server.
+ */
+ public CacheServerConfigImpl(GemFireVM vm) {
+ super(vm);
+
+ String name = DistributionConfig.CACHE_XML_FILE_NAME;
+ this.cacheXMLFile = vm.getConfig().getAttribute(name);
+ this.classpath = null;
+ }
+
+ /**
+ * Copy constructor
+ */
+ public CacheServerConfigImpl(CacheServerConfig other) {
+ super(other);
+ this.cacheXMLFile = other.getCacheXMLFile();
+ this.classpath = other.getClassPath();
+ }
+
+ /**
+ * Copy constructor
+ */
+ public CacheServerConfigImpl(CacheVmConfig other) {
+ super(other);
+ this.cacheXMLFile = other.getCacheXMLFile();
+ this.classpath = other.getClassPath();
+ }
+
+ ////////////////////// Instance Methods //////////////////////
+
+ public String getCacheXMLFile() {
+ return this.cacheXMLFile;
+ }
+
+ public void setCacheXMLFile(String cacheXMLFile) {
+ checkReadOnly();
+ this.cacheXMLFile = cacheXMLFile;
+ configChanged();
+ }
+
+ public String getClassPath() {
+ return this.classpath;
+ }
+
+ public void setClassPath(String classpath) {
+ checkReadOnly();
+ this.classpath = classpath;
+ configChanged();
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+
+ // Nothing to validate really. Cache.xml file could live on
+ // different file system.
+ }
+
+ /**
+ * Currently, listeners are not supported on the locator config.
+ */
+ @Override
+ protected void configChanged() {
+
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return new CacheServerConfigImpl((CacheVmConfig)this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(super.toString());
+ sb.append(" cacheXMLFile=");
+ sb.append(this.getCacheXMLFile());
+ sb.append(" classPath=");
+ sb.append(this.getClassPath());
+
+ 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/CacheServerImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheServerImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheServerImpl.java
new file mode 100644
index 0000000..00f2b5b
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/CacheServerImpl.java
@@ -0,0 +1,190 @@
+/*=========================================================================
+ * 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.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.DistributionManager;
+import com.gemstone.gemfire.internal.admin.GemFireVM;
+import com.gemstone.gemfire.internal.admin.remote.RemoteApplicationVM;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+/**
+ * Implements the administrative interface to a cache server.
+ *
+ * @author David Whitlock
+ * @since 3.5
+ */
+public class CacheServerImpl extends ManagedSystemMemberImpl
+ implements CacheVm, CacheServer {
+
+ /** How many new <code>CacheServer</code>s have been created? */
+ private static int newCacheServers = 0;
+
+ /////////////////////// Instance Fields ///////////////////////
+
+ /** The configuration object for this cache server */
+ private final CacheServerConfigImpl config;
+
+ ///////////////////////// Constructors ////////////////////////
+
+ /**
+ * Creates a new <code>CacheServerImpl</code> that represents a
+ * non-existsing (unstarted) cache server in a given distributed
+ * system.
+ */
+ public CacheServerImpl(AdminDistributedSystemImpl system,
+ CacheVmConfig config)
+ throws AdminException {
+
+ super(system, config);
+
+ this.config = (CacheServerConfigImpl) config;
+ this.config.setManagedEntity(this);
+ }
+
+ /**
+ * Creates a new <code>CacheServerImpl</code> that represents an
+ * existing dedicated cache server in a given distributed system.
+ */
+ public CacheServerImpl(AdminDistributedSystemImpl system,
+ GemFireVM vm)
+ throws AdminException {
+
+ super(system, vm);
+ this.config = new CacheServerConfigImpl(vm);
+ }
+
+ ////////////////////// Instance Methods //////////////////////
+
+ @Override
+ public SystemMemberType getType() {
+ return SystemMemberType.CACHE_VM;
+ }
+
+ public String getNewId() {
+ synchronized (CacheServerImpl.class) {
+ return "CacheVm" + (++newCacheServers);
+ }
+ }
+
+ public void start() throws AdminException {
+ if (!needToStart()) {
+ return;
+ }
+
+ this.config.validate();
+ this.controller.start(this);
+ this.config.setManagedEntity(this);
+ }
+
+ public void stop() {
+ if (!needToStop()) {
+ return;
+ }
+
+ this.controller.stop(this);
+ // NOTE: DistributedSystem nodeLeft will then set this.manager to null
+ this.config.setManagedEntity(null);
+ }
+
+ public boolean isRunning() {
+ DM dm = ((AdminDistributedSystemImpl)getDistributedSystem()).getDistributionManager();
+ if(dm == null) {
+ try {
+ return this.controller.isRunning(this);
+ }
+ catch (IllegalStateException e) {
+ return false;
+ }
+ }
+ return ((DistributionManager)dm).getDistributionManagerIdsIncludingAdmin().contains(getDistributedMember());
+ }
+
+ public CacheServerConfig getConfig() {
+ return this.config;
+ }
+
+ public CacheVmConfig getVmConfig() {
+ return this.config;
+ }
+
+ //////////////////////// Command execution ////////////////////////
+
+ public ManagedEntityConfig getEntityConfig() {
+ return this.getConfig();
+ }
+
+ public String getEntityType() {
+ // Fix bug 32564
+ return "Cache Vm";
+ }
+
+ public String getStartCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "cacheserver"));
+ sb.append(" start -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ String file = this.getConfig().getCacheXMLFile();
+ if (file != null && file.length() > 0) {
+ sb.append(" ");
+ sb.append(com.gemstone.gemfire.distributed.internal.DistributionConfig.CACHE_XML_FILE_NAME);
+ sb.append("=");
+ sb.append(file);
+ }
+
+ String classpath = this.getConfig().getClassPath();
+ if (classpath != null && classpath.length() > 0) {
+ sb.append(" -classpath=");
+ sb.append(classpath);
+ }
+
+ appendConfiguration(sb);
+
+ return sb.toString().trim();
+ }
+
+ public String getStopCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "cacheserver"));
+ sb.append(" stop -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ return sb.toString().trim();
+ }
+
+ public String getIsRunningCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "cacheserver"));
+ sb.append(" status -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ return sb.toString().trim();
+ }
+
+ /**
+ * Find whether this server is primary for given client (durableClientId)
+ *
+ * @param durableClientId -
+ * durable-id of the client
+ * @return true if the server is primary for given client
+ *
+ * @since 5.6
+ */
+ public boolean isPrimaryForDurableClient(String durableClientId)
+ {
+ RemoteApplicationVM vm = (RemoteApplicationVM)this.getGemFireVM();
+ boolean isPrimary = false;
+ if (vm != null) {
+ isPrimary = vm.isPrimaryForDurableClient(durableClientId);
+}
+ return isPrimary;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterImpl.java
new file mode 100755
index 0000000..4ce4c4e
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterImpl.java
@@ -0,0 +1,272 @@
+/*=========================================================================
+ * 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.admin.ConfigurationParameter;
+import com.gemstone.gemfire.admin.UnmodifiableConfigurationException;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+import java.io.File;
+//import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A single configuration parameter of a system member.
+ *
+ * @author Kirk Lund
+ * @since 3.5
+ *
+ */
+public class ConfigurationParameterImpl
+implements com.gemstone.gemfire.admin.ConfigurationParameter {
+
+ /** Identifying name of this configuration parameter */
+ protected String name;
+ /** Full description of this configuration parameter */
+ protected String description;
+ /** The current value */
+ protected Object value;
+ /** Class type of the value */
+ protected Class type;
+ /** True if this is modifiable; false if read-only */
+ protected boolean userModifiable;
+ /** List of listeners to notify when value changes */
+ private final List listeners = new ArrayList();
+
+ // -------------------------------------------------------------------------
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Constructs new <code>ConfigurationParameterImpl</code>.
+ *
+ * @param name the name of this parameter which cannot change
+ * @param description full description to use
+ * @param value the value of this parameter
+ * @param type the class type of the value
+ * @param userModifiable true if this is modifiable; false if read-only
+ */
+ protected ConfigurationParameterImpl(String name,
+ String description,
+ Object value,
+ Class type,
+ boolean userModifiable) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_CONFIGURATIONPARAMETER_NAME_MUST_BE_SPECIFIED.toLocalizedString());
+ }
+
+ this.name = name;
+ setInternalState(description, value, type, userModifiable);
+ }
+
+ /**
+ * Constructs new <code>ConfigurationParameterImpl</code>.
+ *
+ * @param name the name of this parameter which cannot change
+ * @param value the value of this parameter
+ */
+ protected ConfigurationParameterImpl(String name,
+ Object value) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_CONFIGURATIONPARAMETER_NAME_MUST_BE_SPECIFIED.toLocalizedString());
+ }
+
+ this.name = name;
+ setInternalState(name, value, value.getClass(), true);
+ }
+
+ /** Constructor to allow serialization by subclass */
+ protected ConfigurationParameterImpl() {}
+
+ // -------------------------------------------------------------------------
+ // Attribute accessors and mutators
+ // -------------------------------------------------------------------------
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public Object getValue() {
+ return this.value;
+ }
+
+ public String getValueAsString() {
+ if (isString()) {
+ return (String) this.value;
+ }
+ else if (isInetAddress()) {
+ return InetAddressUtil.toString(this.value);
+ }
+ else if (isFile()) {
+ return this.value.toString();
+ }
+ else if (isOctal()) {
+ String strVal = Integer.toOctalString(((Integer) this.value).intValue());
+ if (!strVal.startsWith("0")) {
+ strVal = "0" + strVal;
+ }
+ return strVal;
+ }
+ else if (isArray()) {
+ List list = Arrays.asList((Object[]) this.value);
+ return list.toString();
+ }
+ else {
+ return this.value.toString();
+ }
+ }
+
+ public Class getValueType() {
+ return this.type;
+ }
+
+ public boolean isModifiable() {
+ return this.userModifiable;
+ }
+
+ public boolean isArray() {
+ return "manager-parameters".equals(this.name) ||
+ "manager-classpaths".equals(this.name);
+ }
+ public boolean isInetAddress() {
+ return java.net.InetAddress.class.isAssignableFrom(this.type);
+ }
+ public boolean isFile() {
+ return java.io.File.class.equals(this.type);
+ }
+ public boolean isOctal() {
+ return "shared-memory-permissions".equals(this.name);
+ }
+ public boolean isString() {
+ return java.lang.String.class.equals(this.type);
+ }
+
+ public void setValue(Object value) throws UnmodifiableConfigurationException {
+ if (!isModifiable()) {
+ throw new UnmodifiableConfigurationException(LocalizedStrings.ConfigurationParameterImpl_0_IS_NOT_A_MODIFIABLE_CONFIGURATION_PARAMETER.toLocalizedString(getName()));
+ }
+ if (value == null) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_0_TO_NULL_VALUE.toLocalizedString(getName()));
+ }
+ if (!getValueType().equals(value.getClass())) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_TYPE_0_WITH_TYPE_1.toLocalizedString(new Object[] {getValueType().getName(), value.getClass().getName()}));
+ }
+
+ if (value instanceof String && !isString()) {
+ // we need to check what the type should be and convert to it...
+ setValueFromString((String) value);
+ }
+ else {
+ this.value = value;
+ }
+ fireConfigurationParameterValueChanged(this);
+ }
+
+ // -------------------------------------------------------------------------
+ // Operations for handling the registration of listeners
+ // Note: this is only for use within impl pkg and subclass pkgs
+ // -------------------------------------------------------------------------
+
+ /** Adds the listener for any changes to this configuration parameter. */
+ public void addConfigurationParameterListener(ConfigurationParameterListener listener) {
+ if (!this.listeners.contains(listener)) {
+ this.listeners.add(listener);
+ }
+ }
+
+ /** Removes the listener if it's currently registered. */
+ public void removeConfigurationParameterListener(ConfigurationParameterListener listener) {
+ if (this.listeners.contains(listener)) {
+ this.listeners.remove(listener);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation methods
+ // -------------------------------------------------------------------------
+
+ protected void setValueFromString(String newValue) {
+ if (newValue == null) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_0_TO_NULL_VALUE.toLocalizedString(getName()));
+ }
+
+ if (isInetAddress()) {
+ this.value = InetAddressUtil.toInetAddress(newValue);
+ }
+ else if (isFile()) {
+ this.value = new File(newValue);
+ }
+ else if (isOctal()) {
+ if (!newValue.startsWith("0")) {
+ newValue = "0" + newValue;
+ }
+ this.value = Integer.valueOf(Integer.parseInt(newValue, 8));
+ }
+ else if (isArray()) {
+ // parse it TODO
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_SETTING_ARRAY_VALUE_FROM_DELIMITED_STRING_IS_NOT_SUPPORTED.toLocalizedString());
+ }
+ else {
+ this.value = newValue;
+ }
+ }
+
+ /**
+ * Fires changed configuration parameter to registered listeners.
+ *
+ * @param parm the configuration parameter the changed
+ */
+ protected void fireConfigurationParameterValueChanged(ConfigurationParameter parm) {
+ ConfigurationParameterListener[] listeners =
+ (ConfigurationParameterListener[]) this.listeners.toArray(
+ new ConfigurationParameterListener[0]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].configurationParameterValueChanged(parm);
+ }
+ }
+
+ /**
+ * Sets the internal state of this configuration parameter.
+ *
+ * @param description full description to use
+ * @param value the value of this parameter
+ * @param type the class type of the value
+ * @param userModifiable true if this is modifiable; false if read-only
+ */
+ protected void setInternalState(String description,
+ Object value,
+ Class type,
+ boolean userModifiable) {
+ if (description == null || description.length() == 0) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_CONFIGURATIONPARAMETER_DESCRIPTION_MUST_BE_SPECIFIED.toLocalizedString());
+ }
+ this.description = description;
+ this.type = type;
+ this.userModifiable = userModifiable;
+
+ if (value == null) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_0_TO_NULL_VALUE.toLocalizedString(getName()));
+ }
+
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterListener.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterListener.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterListener.java
new file mode 100755
index 0000000..0720465
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/ConfigurationParameterListener.java
@@ -0,0 +1,26 @@
+/*=========================================================================
+ * 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.admin.ConfigurationParameter;
+
+/**
+ * Listens to value changes of a
+ * {@link com.gemstone.gemfire.admin.ConfigurationParameter}. This is for
+ * internal use only to allow a {@link SystemMemberImpl} to keep track of
+ * configuration changes made through
+ * {@link ConfigurationParameterImpl#setValue}.
+ *
+ * @author Kirk Lund
+ * @since 3.5
+ *
+ */
+public interface ConfigurationParameterListener {
+ public void configurationParameterValueChanged(ConfigurationParameter parm);
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DisabledManagedEntityController.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DisabledManagedEntityController.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DisabledManagedEntityController.java
new file mode 100755
index 0000000..2af37a3
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DisabledManagedEntityController.java
@@ -0,0 +1,83 @@
+/*=========================================================================
+ * 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 org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.admin.DistributedSystemConfig;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
+
+/**
+ * This is a disabled implementation of ManagedEntityController for bug #47909.
+ *
+ * The old ManagedEntityController was a concrete class which has been renamed
+ * to ManagedEntityControllerImpl. The build.xml now skips building
+ * ManagedEntityControllerImpl. If ManagedEntityControllerImpl is not found
+ * in the classpath then the code uses DisabledManagedEntityController as a
+ * place holder.
+ *
+ * @author Kirk Lund
+ */
+class DisabledManagedEntityController implements ManagedEntityController {
+
+ private static final Logger logger = LogService.getLogger();
+
+ private static final String EXCEPTION_MESSAGE = "Local and remote OS command invocations are disabled for the Admin API.";
+
+ DisabledManagedEntityController() {
+ }
+
+ @Override
+ public void start(InternalManagedEntity entity) {
+ if (logger.isTraceEnabled(LogMarker.MANAGED_ENTITY)){
+ logger.warn(LogMarker.MANAGED_ENTITY, "DisabledManagedEntityController#start {}", EXCEPTION_MESSAGE);
+ }
+ throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
+ }
+
+ @Override
+ public void stop(InternalManagedEntity entity) {
+ if (logger.isTraceEnabled(LogMarker.MANAGED_ENTITY)){
+ logger.warn(LogMarker.MANAGED_ENTITY, "DisabledManagedEntityController#stop {}", EXCEPTION_MESSAGE);
+ }
+ throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
+ }
+
+ @Override
+ public boolean isRunning(InternalManagedEntity entity) {
+ if (logger.isTraceEnabled(LogMarker.MANAGED_ENTITY)){
+ logger.warn(LogMarker.MANAGED_ENTITY, "DisabledManagedEntityController#isRunning {}", EXCEPTION_MESSAGE);
+ }
+ throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
+ }
+
+ @Override
+ public String getLog(DistributionLocatorImpl locator) {
+ if (logger.isTraceEnabled(LogMarker.MANAGED_ENTITY)){
+ logger.warn(LogMarker.MANAGED_ENTITY, "DisabledManagedEntityController#getLog {}", EXCEPTION_MESSAGE);
+ }
+ throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
+ }
+
+ @Override
+ public String buildSSLArguments(DistributedSystemConfig config) {
+ if (logger.isTraceEnabled(LogMarker.MANAGED_ENTITY)){
+ logger.warn(LogMarker.MANAGED_ENTITY, "DisabledManagedEntityController#buildSSLArguments {}", EXCEPTION_MESSAGE);
+ }
+ throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
+ }
+
+ @Override
+ public String getProductExecutable(InternalManagedEntity entity, String executable) {
+ if (logger.isTraceEnabled(LogMarker.MANAGED_ENTITY)){
+ logger.warn(LogMarker.MANAGED_ENTITY, "DisabledManagedEntityController#getProductExecutable {}", EXCEPTION_MESSAGE);
+ }
+ throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemConfigImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemConfigImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemConfigImpl.java
new file mode 100755
index 0000000..4918e29
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemConfigImpl.java
@@ -0,0 +1,1095 @@
+/*=========================================================================
+ * 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.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.GemFireIOException;
+import com.gemstone.gemfire.admin.AdminXmlException;
+import com.gemstone.gemfire.admin.CacheServerConfig;
+import com.gemstone.gemfire.admin.CacheVmConfig;
+import com.gemstone.gemfire.admin.DistributedSystemConfig;
+import com.gemstone.gemfire.admin.DistributionLocator;
+import com.gemstone.gemfire.admin.DistributionLocatorConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionConfigImpl;
+import com.gemstone.gemfire.internal.Banner;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.InternalLogWriter;
+import com.gemstone.gemfire.internal.logging.LocalLogWriter;
+import com.gemstone.gemfire.internal.logging.LogConfig;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.LogWriterFactory;
+import com.gemstone.gemfire.internal.logging.LogWriterImpl;
+import com.gemstone.gemfire.internal.logging.ManagerLogWriter;
+import com.gemstone.gemfire.internal.logging.log4j.LogWriterAppender;
+import com.gemstone.org.jgroups.util.StringId;
+
+/**
+ * An implementation of the configuration object for an
+ * <code>AdminDistributedSystem</code>. After a config has been used
+ * to create an <code>AdminDistributedSystem</code> most of the
+ * configuration attributes cannot be changed. However, some
+ * operations (such as getting information about GemFire managers and
+ * distribution locators) are "passed through" to the
+ * <code>AdminDistributedSystem</code> associated with this
+ * configuration object.
+ *
+ * @since 3.5
+ */
+public class DistributedSystemConfigImpl
+ implements DistributedSystemConfig {
+
+ private static final Logger logger = LogService.getLogger();
+
+ private String entityConfigXMLFile = DEFAULT_ENTITY_CONFIG_XML_FILE;
+ private String systemId = DEFAULT_SYSTEM_ID;
+ private String mcastAddress = DEFAULT_MCAST_ADDRESS;
+ private int mcastPort = DEFAULT_MCAST_PORT;
+ private int ackWaitThreshold = DEFAULT_ACK_WAIT_THRESHOLD;
+ private int ackSevereAlertThreshold = DEFAULT_ACK_SEVERE_ALERT_THRESHOLD;
+ private String locators = DEFAULT_LOCATORS;
+ private String bindAddress = DEFAULT_BIND_ADDRESS;
+ private String serverBindAddress = DEFAULT_BIND_ADDRESS;
+ private String remoteCommand = DEFAULT_REMOTE_COMMAND;
+ private boolean disableTcp = DEFAULT_DISABLE_TCP;
+ private boolean enableNetworkPartitionDetection = DEFAULT_ENABLE_NETWORK_PARTITION_DETECTION;
+ private boolean disableAutoReconnect = DEFAULT_DISABLE_AUTO_RECONNECT;
+ private int memberTimeout = DEFAULT_MEMBER_TIMEOUT;
+ private String membershipPortRange = getMembershipPortRangeString(DEFAULT_MEMBERSHIP_PORT_RANGE);
+ private int tcpPort = DEFAULT_TCP_PORT;
+
+
+ private String logFile = DEFAULT_LOG_FILE;
+ private String logLevel = DEFAULT_LOG_LEVEL;
+ private int logDiskSpaceLimit = DEFAULT_LOG_DISK_SPACE_LIMIT;
+ private int logFileSizeLimit = DEFAULT_LOG_FILE_SIZE_LIMIT;
+ private int refreshInterval = DEFAULT_REFRESH_INTERVAL;
+ private Properties gfSecurityProperties = new Properties();
+
+ /** Listeners to notify when this DistributedSystemConfig changes */
+ private Set listeners = new HashSet();
+
+ /** Configs for CacheServers that this system config is aware of */
+ private Set cacheServerConfigs = new HashSet();
+
+ /** Configs for the managed distribution locators in the distributed
+ * system */
+ private Set locatorConfigs = new HashSet();
+
+ /** The display name of this distributed system */
+ private String systemName = DEFAULT_NAME;
+
+ /** The admin distributed system object that is configured by this
+ * config object.
+ *
+ * @since 4.0 */
+ private AdminDistributedSystemImpl system;
+
+ /** The GemFire log writer used by the distributed system */
+ private InternalLogWriter logWriter;
+
+
+ /////////////////////// Static Methods ///////////////////////
+
+ /**
+ * Filters out all properties that are unique to the admin
+ * <code>DistributedSystemConfig</code> that are not present in the
+ * internal <code>DistributionConfig</code>.
+ *
+ * @since 4.0
+ */
+ private static Properties
+ filterOutAdminProperties(Properties props) {
+
+ Properties props2 = new Properties();
+ for (Enumeration names = props.propertyNames();
+ names.hasMoreElements(); ) {
+ String name = (String) names.nextElement();
+ if (!(ENTITY_CONFIG_XML_FILE_NAME.equals(name) ||
+ REFRESH_INTERVAL_NAME.equals(name) ||
+ REMOTE_COMMAND_NAME.equals(name)
+ )
+ ) {
+ String value = props.getProperty(name);
+ if ((name != null) && (value != null)) {
+ props2.setProperty(name, value);
+ }
+ }
+ }
+
+ return props2;
+ }
+
+ //////////////////////// Constructors ////////////////////////
+
+ /**
+ * Creates a new <code>DistributedSystemConfigImpl</code> based on
+ * the configuration stored in a <code>DistributedSystem</code>'s
+ * <code>DistributionConfig</code>.
+ */
+ public DistributedSystemConfigImpl(DistributionConfig distConfig,
+ String remoteCommand) {
+ if (distConfig == null) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributedSystemConfigImpl_DISTRIBUTIONCONFIG_MUST_NOT_BE_NULL.toLocalizedString());
+ }
+
+ this.mcastAddress = InetAddressUtil.toString(distConfig.getMcastAddress());
+ this.mcastPort = distConfig.getMcastPort();
+ this.locators = distConfig.getLocators();
+ this.membershipPortRange =
+ getMembershipPortRangeString(distConfig.getMembershipPortRange());
+
+ this.systemName = distConfig.getName();
+
+ this.sslEnabled = distConfig.getSSLEnabled();
+ this.sslCiphers = distConfig.getSSLCiphers();
+ this.sslProtocols = distConfig.getSSLProtocols();
+ this.sslAuthenticationRequired = distConfig.getSSLRequireAuthentication();
+
+ this.logFile = distConfig.getLogFile().getPath();
+ this.logLevel =
+ LogWriterImpl.levelToString(distConfig.getLogLevel());
+ this.logDiskSpaceLimit = distConfig.getLogDiskSpaceLimit();
+ this.logFileSizeLimit = distConfig.getLogFileSizeLimit();
+
+ basicSetBindAddress(distConfig.getBindAddress());
+ this.tcpPort = distConfig.getTcpPort();
+
+ this.disableTcp = distConfig.getDisableTcp();
+
+ this.remoteCommand = remoteCommand;
+ this.serverBindAddress = distConfig.getServerBindAddress();
+ this.enableNetworkPartitionDetection = distConfig.getEnableNetworkPartitionDetection();
+ this.memberTimeout = distConfig.getMemberTimeout();
+ this.refreshInterval = DistributedSystemConfig.DEFAULT_REFRESH_INTERVAL;
+ this.gfSecurityProperties = (Properties) distConfig.getSSLProperties().clone();
+ }
+
+ /**
+ * Zero-argument constructor to be used only by subclasses.
+ *
+ * @since 4.0
+ */
+ protected DistributedSystemConfigImpl() {
+
+ }
+
+ /**
+ * Creates a new <code>DistributedSystemConifgImpl</code> whose
+ * configuration is specified by the given <code>Properties</code>
+ * object.
+ */
+ protected DistributedSystemConfigImpl(Properties props) {
+ this(props, false);
+ }
+
+ /**
+ * Creates a new <code>DistributedSystemConifgImpl</code> whose configuration
+ * is specified by the given <code>Properties</code> object.
+ *
+ * @param props
+ * The configuration properties specified by the caller
+ * @param ignoreGemFirePropsFile
+ * whether to skip loading distributed system properties from
+ * gemfire.properties file
+ *
+ * @since 6.5
+ */
+ protected DistributedSystemConfigImpl(Properties props,
+ boolean ignoreGemFirePropsFile) {
+ this(new DistributionConfigImpl(
+ filterOutAdminProperties(props), ignoreGemFirePropsFile),
+ DEFAULT_REMOTE_COMMAND);
+ String remoteCommand = props.getProperty(REMOTE_COMMAND_NAME);
+ if (remoteCommand != null) {
+ this.remoteCommand = remoteCommand;
+ }
+
+ String entityConfigXMLFile =
+ props.getProperty(ENTITY_CONFIG_XML_FILE_NAME);
+ if (entityConfigXMLFile != null) {
+ this.entityConfigXMLFile = entityConfigXMLFile;
+ }
+
+ String refreshInterval =
+ props.getProperty(REFRESH_INTERVAL_NAME);
+ if (refreshInterval != null) {
+ try {
+ this.refreshInterval = Integer.parseInt(refreshInterval);
+ } catch (NumberFormatException nfEx) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributedSystemConfigImpl_0_IS_NOT_A_VALID_INTEGER_1.toLocalizedString(new Object[] { refreshInterval, REFRESH_INTERVAL_NAME }));
+ }
+ }
+ }
+
+ ////////////////////// Instance Methods //////////////////////
+
+ /**
+ * Returns the <code>LogWriterI18n</code> to be used when administering
+ * the distributed system. Returns null if nothing has been provided via
+ * <code>setInternalLogWriter</code>.
+ *
+ * @since 4.0
+ */
+ public InternalLogWriter getInternalLogWriter() {
+ // LOG: used only for sharing between IDS, AdminDSImpl and AgentImpl -- to prevent multiple banners, etc.
+ synchronized (this) {
+ return this.logWriter;
+ }
+ }
+
+ /**
+ * Sets the <code>LogWriterI18n</code> to be used when administering the
+ * distributed system.
+ */
+ public void setInternalLogWriter(InternalLogWriter logWriter) {
+ // LOG: used only for sharing between IDS, AdminDSImpl and AgentImpl -- to prevent multiple banners, etc.
+ synchronized (this) {
+ this.logWriter = logWriter;
+ }
+ }
+
+ public LogConfig createLogConfig() {
+ return new LogConfig() {
+ @Override
+ public int getLogLevel() {
+ return LogWriterImpl.levelNameToCode(DistributedSystemConfigImpl.this.getLogLevel());
+ }
+ @Override
+ public File getLogFile() {
+ return new File(DistributedSystemConfigImpl.this.getLogFile());
+ }
+ @Override
+ public int getLogFileSizeLimit() {
+ return DistributedSystemConfigImpl.this.getLogFileSizeLimit();
+ }
+ @Override
+ public int getLogDiskSpaceLimit() {
+ return DistributedSystemConfigImpl.this.getLogDiskSpaceLimit();
+ }
+ @Override
+ public String getName() {
+ return DistributedSystemConfigImpl.this.getSystemName();
+ }
+ @Override
+ public String toLoggerString() {
+ return DistributedSystemConfigImpl.this.toString();
+ }
+ };
+ }
+
+ /**
+ * Marks this config object as "read only". Attempts to modify a
+ * config object will result in a {@link IllegalStateException}
+ * being thrown.
+ *
+ * @since 4.0
+ */
+ void setDistributedSystem(AdminDistributedSystemImpl system) {
+ this.system = system;
+ }
+
+ /**
+ * Checks to see if this config object is "read only". If it is,
+ * then an {@link IllegalStateException} is thrown.
+ *
+ * @since 4.0
+ */
+ protected void checkReadOnly() {
+ if (this.system != null) {
+ throw new IllegalStateException(LocalizedStrings.DistributedSystemConfigImpl_A_DISTRIBUTEDSYSTEMCONFIG_OBJECT_CANNOT_BE_MODIFIED_AFTER_IT_HAS_BEEN_USED_TO_CREATE_AN_ADMINDISTRIBUTEDSYSTEM.toLocalizedString());
+ }
+ }
+
+ public String getEntityConfigXMLFile() {
+ return this.entityConfigXMLFile;
+ }
+
+ public void setEntityConfigXMLFile(String xmlFile) {
+ checkReadOnly();
+ this.entityConfigXMLFile = xmlFile;
+ configChanged();
+ }
+
+ /**
+ * Parses the XML configuration file that describes managed
+ * entities.
+ *
+ * @throws AdminXmlException
+ * If a problem is encountered while parsing the XML file.
+ */
+ private void parseEntityConfigXMLFile() {
+ String fileName = this.entityConfigXMLFile;
+ File xmlFile = new File(fileName);
+ if (!xmlFile.exists()) {
+ if (DEFAULT_ENTITY_CONFIG_XML_FILE.equals(fileName)) {
+ // Default doesn't exist, no big deal
+ return;
+ } else {
+ throw new AdminXmlException(LocalizedStrings.DistributedSystemConfigImpl_ENTITY_CONFIGURATION_XML_FILE_0_DOES_NOT_EXIST.toLocalizedString(fileName));
+ }
+ }
+
+ try {
+ InputStream is = new FileInputStream(xmlFile);
+ try {
+ ManagedEntityConfigXmlParser.parse(is, this);
+ }
+ finally {
+ is.close();
+ }
+ }
+ catch (IOException ex) {
+ throw new AdminXmlException(LocalizedStrings.DistributedSystemConfigImpl_WHILE_PARSING_0.toLocalizedString(fileName), ex);
+ }
+ }
+
+ public String getSystemId() {
+ return this.systemId;
+ }
+
+ public void setSystemId(String systemId) {
+ checkReadOnly();
+ this.systemId = systemId;
+ configChanged();
+ }
+
+ /** Returns the multicast address for the system */
+ public String getMcastAddress() {
+ return this.mcastAddress;
+ }
+
+ public void setMcastAddress(String mcastAddress) {
+ checkReadOnly();
+ this.mcastAddress = mcastAddress;
+ configChanged();
+ }
+
+ /** Returns the multicast port for the system */
+ public int getMcastPort() {
+ return this.mcastPort;
+ }
+
+ public void setMcastPort(int mcastPort) {
+ checkReadOnly();
+ this.mcastPort = mcastPort;
+ configChanged();
+ }
+
+ public int getAckWaitThreshold() {
+ return this.ackWaitThreshold;
+ }
+
+ public void setAckWaitThreshold(int seconds) {
+ checkReadOnly();
+ this.ackWaitThreshold = seconds;
+ configChanged();
+ }
+
+ public int getAckSevereAlertThreshold() {
+ return this.ackSevereAlertThreshold;
+ }
+
+ public void setAckSevereAlertThreshold(int seconds) {
+ checkReadOnly();
+ this.ackSevereAlertThreshold = seconds;
+ configChanged();
+ }
+
+ /** Returns the comma-delimited list of locators for the system */
+ public String getLocators() {
+ return this.locators;
+ }
+
+ public void setLocators(String locators) {
+ checkReadOnly();
+ if (locators == null) {
+ this.locators = "";
+ }
+ else {
+ this.locators = locators;
+ }
+ configChanged();
+ }
+
+ /**
+ * Returns the value for membership-port-range
+ *
+ * @return the value for the Distributed System property membership-port-range
+ */
+ public String getMembershipPortRange() {
+ return this.membershipPortRange;
+ }
+
+ /**
+ * Sets the Distributed System property membership-port-range
+ *
+ * @param membershipPortRangeStr
+ * the value for membership-port-range given as two numbers separated
+ * by a minus sign.
+ */
+ public void setMembershipPortRange(String membershipPortRangeStr) {
+ /*
+ * FIXME: Setting attributes in DistributedSystemConfig has no effect on
+ * DistributionConfig which is actually used for connection with DS. This is
+ * true for all such attributes. Should be addressed in the Admin Revamp if
+ * we want these 'set' calls to affect anything. Then we can use the
+ * validation code in DistributionConfigImpl code.
+ */
+ checkReadOnly();
+ if (membershipPortRangeStr == null) {
+ this.membershipPortRange = getMembershipPortRangeString(DEFAULT_MEMBERSHIP_PORT_RANGE);
+ } else {
+ try {
+ if (validateMembershipRange(membershipPortRangeStr)) {
+ this.membershipPortRange = membershipPortRangeStr;
+ } else {
+ throw new IllegalArgumentException(
+ LocalizedStrings.DistributedSystemConfigImpl_INVALID_VALUE_FOR_MEMBERSHIP_PORT_RANGE
+ .toLocalizedString(new Object[] {membershipPortRangeStr,
+ MEMBERSHIP_PORT_RANGE_NAME}));
+ }
+ } catch (Exception e) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ public void setTcpPort(int port) {
+ checkReadOnly();
+ this.tcpPort = port;
+ configChanged();
+ }
+
+ public int getTcpPort() {
+ return this.tcpPort;
+ }
+
+ /**
+ * Validates the given string - which is expected in the format as two numbers
+ * separated by a minus sign - in to an integer array of length 2 with first
+ * element as lower end & second element as upper end of the range.
+ *
+ * @param membershipPortRange
+ * membership-port-range given as two numbers separated by a minus
+ * sign.
+ * @return true if the membership-port-range string is valid, false otherwise
+ */
+ private boolean validateMembershipRange(String membershipPortRange) {
+ int[] range = null;
+ if (membershipPortRange != null && membershipPortRange.trim().length() > 0) {
+ String[] splitted = membershipPortRange.split("-");
+ range = new int[2];
+ range[0] = Integer.parseInt(splitted[0].trim());
+ range[1] = Integer.parseInt(splitted[1].trim());
+ //NumberFormatException if any could be thrown
+
+ if (range[0] < 0 || range[0] >= range[1] ||
+ range[1] < 0 || range[1] > 65535) {
+ range = null;
+ }
+ }
+ return range != null;
+ }
+
+ /**
+ * @return the String representation of membershipPortRange with lower & upper
+ * limits of the port range separated by '-' e.g. 1-65535
+ */
+ private static String getMembershipPortRangeString(int[] membershipPortRange) {
+ String membershipPortRangeString = "";
+ if (membershipPortRange != null &&
+ membershipPortRange.length == 2) {
+ membershipPortRangeString = membershipPortRange[0] + "-" +
+ membershipPortRange[1];
+ }
+
+ return membershipPortRangeString;
+ }
+
+ public String getBindAddress() {
+ return this.bindAddress;
+ }
+
+ public void setBindAddress(String bindAddress) {
+ checkReadOnly();
+ basicSetBindAddress(bindAddress);
+ configChanged();
+ }
+
+ public String getServerBindAddress() {
+ return this.serverBindAddress;
+ }
+
+ public void setServerBindAddress(String bindAddress) {
+ checkReadOnly();
+ basicSetServerBindAddress(bindAddress);
+ configChanged();
+ }
+
+ public boolean getDisableTcp() {
+ return this.disableTcp;
+ }
+
+ public void setDisableTcp(boolean flag) {
+ checkReadOnly();
+ disableTcp = flag;
+ configChanged();
+ }
+
+ public void setEnableNetworkPartitionDetection(boolean newValue) {
+ checkReadOnly();
+ this.enableNetworkPartitionDetection = newValue;
+ configChanged();
+ }
+ public boolean getEnableNetworkPartitionDetection() {
+ return this.enableNetworkPartitionDetection;
+ }
+ public void setDisableAutoReconnect(boolean newValue) {
+ checkReadOnly();
+ this.disableAutoReconnect = newValue;
+ configChanged();
+ }
+ public boolean getDisableAutoReconnect() {
+ return this.disableAutoReconnect;
+ }
+ public int getMemberTimeout() {
+ return this.memberTimeout;
+ }
+ public void setMemberTimeout(int value) {
+ checkReadOnly();
+ this.memberTimeout = value;
+ configChanged();
+ }
+
+ private void basicSetBindAddress(String bindAddress) {
+ if (!validateBindAddress(bindAddress)) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributedSystemConfigImpl_INVALID_BIND_ADDRESS_0.toLocalizedString(bindAddress));
+ }
+ this.bindAddress = bindAddress;
+ }
+
+ private void basicSetServerBindAddress(String bindAddress) {
+ if (!validateBindAddress(bindAddress)) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributedSystemConfigImpl_INVALID_BIND_ADDRESS_0.toLocalizedString(bindAddress));
+ }
+ this.serverBindAddress = bindAddress;
+ }
+
+ /** Returns the remote command setting to use for remote administration */
+ public String getRemoteCommand() {
+ return this.remoteCommand;
+ }
+
+ /**
+ * Sets the remote command for this config object. This attribute
+ * may be modified after this config object has been used to create
+ * an admin distributed system.
+ */
+ public void setRemoteCommand(String remoteCommand) {
+ if (!ALLOW_ALL_REMOTE_COMMANDS) {
+ checkRemoteCommand(remoteCommand);
+ }
+ this.remoteCommand = remoteCommand;
+ configChanged();
+ }
+
+ private static final boolean ALLOW_ALL_REMOTE_COMMANDS = Boolean.getBoolean("gemfire.admin.ALLOW_ALL_REMOTE_COMMANDS");
+ private static final String[] LEGAL_REMOTE_COMMANDS = { "rsh", "ssh" };
+ private static final String ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH = "Allowed remote commands include \"rsh {HOST} {CMD}\" or \"ssh {HOST} {CMD}\" with valid rsh or ssh switches. Invalid: ";
+ private final void checkRemoteCommand(final String remoteCommand) {
+ if (remoteCommand == null || remoteCommand.isEmpty()) {
+ return;
+ }
+ final String command = remoteCommand.toLowerCase().trim();
+ if (!command.contains("{host}") || !command.contains("{cmd}")) {
+ throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
+ }
+
+ final StringTokenizer tokenizer = new StringTokenizer(command, " ");
+ final ArrayList<String> array = new ArrayList<String>();
+ for (int i = 0; tokenizer.hasMoreTokens(); i++) {
+ String string = tokenizer.nextToken();
+ if (i == 0) {
+ // first element must be rsh or ssh
+ boolean found = false;
+ for (int j = 0; j < LEGAL_REMOTE_COMMANDS.length; j++) {
+ if (string.contains(LEGAL_REMOTE_COMMANDS[j])) {
+ // verify command is at end of string
+ if (!(string.endsWith(LEGAL_REMOTE_COMMANDS[j]) || string.endsWith(LEGAL_REMOTE_COMMANDS[j]+".exe"))) {
+ throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
+ }
+ found = true;
+ }
+ }
+ if (!found) {
+ throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
+ }
+ } else {
+ final boolean isSwitch = string.startsWith("-");
+ final boolean isHostOrCmd = string.equals("{host}") || string.equals("{cmd}");
+
+ // additional elements must be switches or values-for-switches or {host} or user@{host} or {cmd}
+ if (!isSwitch && !isHostOrCmd) {
+ final String previous = (array == null || array.isEmpty()) ? null : array.get(array.size()-1);
+ final boolean isValueForSwitch = previous != null && previous.startsWith("-");
+ final boolean isHostWithUser = string.contains("@") && string.endsWith("{host}");
+
+ if (!(isValueForSwitch || isHostWithUser)) {
+ throw new IllegalArgumentException(ILLEGAL_REMOTE_COMMAND_RSH_OR_SSH + remoteCommand);
+ }
+ }
+ }
+ array.add(string);
+ }
+ }
+
+ public String getSystemName() {
+ return this.systemName;
+ }
+
+ public void setSystemName(final String systemName) {
+ checkReadOnly();
+ this.systemName = systemName;
+ configChanged();
+ }
+
+ /**
+ * Returns an array of configurations for statically known
+ * CacheServers
+ *
+ * @since 4.0
+ */
+ public CacheServerConfig[] getCacheServerConfigs() {
+ return (CacheServerConfig[]) this.cacheServerConfigs.toArray(
+ new CacheServerConfig[this.cacheServerConfigs.size()]);
+ }
+ public CacheVmConfig[] getCacheVmConfigs() {
+ return (CacheVmConfig[]) this.cacheServerConfigs.toArray(new CacheVmConfig[this.cacheServerConfigs.size()]);
+ }
+
+
+ /**
+ * Creates the configuration for a CacheServer
+ *
+ * @since 4.0
+ */
+ public CacheServerConfig createCacheServerConfig() {
+ CacheServerConfig config = new CacheServerConfigImpl();
+ addCacheServerConfig(config);
+ return config;
+ }
+ public CacheVmConfig createCacheVmConfig() {
+ return (CacheVmConfig)createCacheServerConfig();
+ }
+
+ /**
+ * Adds the configuration for a CacheServer
+ *
+ * @since 4.0
+ */
+ private void addCacheServerConfig(CacheServerConfig managerConfig) {
+ checkReadOnly();
+
+ if (managerConfig == null) return;
+ for (Iterator iter = this.cacheServerConfigs.iterator(); iter.hasNext();) {
+ CacheServerConfigImpl impl = (CacheServerConfigImpl) iter.next();
+ if (impl.equals(managerConfig)) {
+ return;
+ }
+ }
+ this.cacheServerConfigs.add(managerConfig);
+ configChanged();
+ }
+
+ /**
+ * Removes the configuration for a CacheServer
+ *
+ * @since 4.0
+ */
+ public void removeCacheServerConfig(CacheServerConfig managerConfig) {
+ removeCacheVmConfig((CacheVmConfig)managerConfig);
+ }
+ public void removeCacheVmConfig(CacheVmConfig managerConfig) {
+ checkReadOnly();
+ this.cacheServerConfigs.remove(managerConfig);
+ configChanged();
+ }
+
+ /**
+ * Returns the configurations of all managed distribution locators
+ */
+ public DistributionLocatorConfig[] getDistributionLocatorConfigs() {
+ if (this.system != null) {
+ DistributionLocator[] locators =
+ this.system.getDistributionLocators();
+ DistributionLocatorConfig[] configs =
+ new DistributionLocatorConfig[locators.length];
+ for (int i = 0; i < locators.length; i++) {
+ configs[i] = locators[i].getConfig();
+ }
+ return configs;
+
+ } else {
+ Object[] array =
+ new DistributionLocatorConfig[this.locatorConfigs.size()];
+ return (DistributionLocatorConfig[]) this.locatorConfigs.toArray(array);
+ }
+ }
+
+ /** Creates the configuration for a DistributionLocator */
+ public DistributionLocatorConfig createDistributionLocatorConfig() {
+ checkReadOnly();
+ DistributionLocatorConfig config = new DistributionLocatorConfigImpl();
+ addDistributionLocatorConfig(config);
+ return config;
+ }
+
+ /** Adds the configuration for a DistributionLocator */
+ private void addDistributionLocatorConfig(DistributionLocatorConfig config) {
+ checkReadOnly();
+ this.locatorConfigs.add(config);
+ configChanged();
+ }
+
+ /**
+ * Removes the configuration for a DistributionLocator
+ */
+ public void removeDistributionLocatorConfig(DistributionLocatorConfig config) {
+ checkReadOnly();
+ this.locatorConfigs.remove(config);
+ configChanged();
+ }
+
+ /**
+ * Validates the bind address. The address may be a host name or IP address,
+ * but it must not be empty and must be usable for creating an InetAddress.
+ * Cannot have a leading '/' (which InetAddress.toString() produces).
+ *
+ * @param bindAddress host name or IP address to validate
+ */
+ public static boolean validateBindAddress(String bindAddress) {
+ if (bindAddress == null || bindAddress.length() == 0) return true;
+ if (InetAddressUtil.validateHost(bindAddress) == null) return false;
+ return true;
+ }
+
+ public synchronized void configChanged() {
+ ConfigListener[] clients = null;
+ synchronized(this.listeners) {
+ clients = (ConfigListener[])
+ listeners.toArray(new ConfigListener[this.listeners.size()]);
+ }
+ for (int i = 0; i < clients.length; i++) {
+ try {
+ clients[i].configChanged(this);
+ } catch (Exception e) {
+ logger.warn(e.getMessage(), e);
+ }
+ }
+ }
+
+ /** Registers listener for notification of changes in this config. */
+ public void addListener(ConfigListener listener) {
+ synchronized(this.listeners) {
+ this.listeners.add(listener);
+ }
+ }
+
+ /** Removes previously registered listener of this config. */
+ public void removeListener(ConfigListener listener) {
+ synchronized(this.listeners) {
+ this.listeners.remove(listener);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // SSL support...
+ // -------------------------------------------------------------------------
+ private boolean sslEnabled =
+ DistributionConfig.DEFAULT_SSL_ENABLED;
+ private String sslProtocols =
+ DistributionConfig.DEFAULT_SSL_PROTOCOLS;
+ private String sslCiphers =
+ DistributionConfig.DEFAULT_SSL_CIPHERS;
+ private boolean sslAuthenticationRequired =
+ DistributionConfig.DEFAULT_SSL_REQUIRE_AUTHENTICATION;
+ private Properties sslProperties = new Properties();
+
+ public boolean isSSLEnabled() {
+ return this.sslEnabled;
+ }
+ public void setSSLEnabled(boolean enabled) {
+ checkReadOnly();
+ this.sslEnabled = enabled;
+ configChanged();
+ }
+ public String getSSLProtocols() {
+ return this.sslProtocols;
+ }
+ public void setSSLProtocols(String protocols) {
+ checkReadOnly();
+ this.sslProtocols = protocols;
+ configChanged();
+ }
+ public String getSSLCiphers() {
+ return this.sslCiphers;
+ }
+ public void setSSLCiphers(String ciphers) {
+ checkReadOnly();
+ this.sslCiphers = ciphers;
+ configChanged();
+ }
+ public boolean isSSLAuthenticationRequired() {
+ return this.sslAuthenticationRequired;
+ }
+ public void setSSLAuthenticationRequired(boolean authRequired) {
+ checkReadOnly();
+ this.sslAuthenticationRequired = authRequired;
+ configChanged();
+ }
+ public Properties getSSLProperties() {
+ return this.sslProperties;
+ }
+
+ public void setSSLProperties(Properties sslProperties) {
+ checkReadOnly();
+ this.sslProperties = sslProperties;
+ if (this.sslProperties == null) {
+ this.sslProperties = new Properties();
+ }
+ configChanged();
+ }
+
+ public void addSSLProperty(String key, String value) {
+ checkReadOnly();
+ this.sslProperties.put(key, value);
+ configChanged();
+ }
+
+ public void removeSSLProperty(String key) {
+ checkReadOnly();
+ this.sslProperties.remove(key);
+ configChanged();
+ }
+
+ /**
+ *
+ *
+ * @return the gfSecurityProperties
+ * @since 6.6.3
+ */
+ public Properties getGfSecurityProperties() {
+ return gfSecurityProperties;
+ }
+
+ public String getLogFile() {
+ return this.logFile;
+ }
+
+ public void setLogFile(String logFile) {
+ checkReadOnly();
+ this.logFile = logFile;
+ configChanged();
+ }
+
+ public String getLogLevel() {
+ return this.logLevel;
+ }
+
+ public void setLogLevel(String logLevel) {
+ checkReadOnly();
+ this.logLevel = logLevel;
+ configChanged();
+ }
+
+ public int getLogDiskSpaceLimit() {
+ return this.logDiskSpaceLimit;
+ }
+
+ public void setLogDiskSpaceLimit(int limit) {
+ checkReadOnly();
+ this.logDiskSpaceLimit = limit;
+ configChanged();
+ }
+
+ public int getLogFileSizeLimit() {
+ return this.logFileSizeLimit;
+ }
+
+ public void setLogFileSizeLimit(int limit) {
+ checkReadOnly();
+ this.logFileSizeLimit = limit;
+ configChanged();
+ }
+
+ /**
+ * Returns the refreshInterval in seconds
+ */
+ public int getRefreshInterval() {
+ return this.refreshInterval;
+ }
+
+ /**
+ * Sets the refreshInterval in seconds
+ */
+ public void setRefreshInterval(int timeInSecs) {
+ checkReadOnly();
+ this.refreshInterval = timeInSecs;
+ configChanged();
+ }
+
+
+ /**
+ * Makes sure that the mcast port and locators are correct and
+ * consistent.
+ *
+ * @throws IllegalArgumentException
+ * If configuration is not valid
+ */
+ public void validate() {
+ if (this.getMcastPort() < MIN_MCAST_PORT ||
+ this.getMcastPort() > MAX_MCAST_PORT) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributedSystemConfigImpl_MCASTPORT_MUST_BE_AN_INTEGER_INCLUSIVELY_BETWEEN_0_AND_1.toLocalizedString(new Object[] {Integer.valueOf(MIN_MCAST_PORT), Integer.valueOf(MAX_MCAST_PORT)}));
+ }
+
+ // disabled in 5.1 - multicast and locators can be used together
+ //if (!DEFAULT_LOCATORS.equals(this.getLocators()) &&
+ // this.mcastPort > 0) {
+ // throw new IllegalArgumentException(
+ // "mcastPort must be zero when locators are specified");
+ //}
+
+ LogWriterImpl.levelNameToCode(this.logLevel);
+
+ if (this.logFileSizeLimit < MIN_LOG_FILE_SIZE_LIMIT ||
+ this.logFileSizeLimit > MAX_LOG_FILE_SIZE_LIMIT) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributedSystemConfigImpl_LOGFILESIZELIMIT_MUST_BE_AN_INTEGER_BETWEEN_0_AND_1.toLocalizedString(new Object[] {Integer.valueOf(MIN_LOG_FILE_SIZE_LIMIT), Integer.valueOf(MAX_LOG_FILE_SIZE_LIMIT)}));
+ }
+
+ if (this.logDiskSpaceLimit < MIN_LOG_DISK_SPACE_LIMIT ||
+ this.logDiskSpaceLimit > MAX_LOG_DISK_SPACE_LIMIT) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributedSystemConfigImpl_LOGDISKSPACELIMIT_MUST_BE_AN_INTEGER_BETWEEN_0_AND_1.toLocalizedString(new Object[] {Integer.valueOf(MIN_LOG_DISK_SPACE_LIMIT), Integer.valueOf(MAX_LOG_DISK_SPACE_LIMIT)}));
+ }
+
+ parseEntityConfigXMLFile();
+ }
+
+ /**
+ * Makes a deep copy of this config object.
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ DistributedSystemConfigImpl other =
+ (DistributedSystemConfigImpl) super.clone();
+ other.system = null;
+ other.cacheServerConfigs = new HashSet();
+ other.locatorConfigs = new HashSet();
+
+ DistributionLocatorConfig[] myLocators =
+ this.getDistributionLocatorConfigs();
+ for (int i = 0; i < myLocators.length; i++) {
+ DistributionLocatorConfig locator = myLocators[i];
+ other.addDistributionLocatorConfig((DistributionLocatorConfig) locator.clone());
+ }
+
+ CacheServerConfig[] myCacheServers = this.getCacheServerConfigs();
+ for (int i = 0; i < myCacheServers.length; i++) {
+ CacheServerConfig locator = myCacheServers[i];
+ other.addCacheServerConfig((CacheServerConfig) locator.clone());
+ }
+
+ return other;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer(1000);
+ String lf = System.getProperty("line.separator");
+ if (lf == null) lf = ",";
+
+ buf.append("DistributedSystemConfig(");
+ buf.append(lf);
+ buf.append(" system-name=");
+ buf.append(String.valueOf(this.systemName));
+ buf.append(lf);
+ buf.append(" "+MCAST_ADDRESS_NAME+"=");
+ buf.append(String.valueOf(this.mcastAddress));
+ buf.append(lf);
+ buf.append(" "+MCAST_PORT_NAME+"=");
+ buf.append(String.valueOf(this.mcastPort));
+ buf.append(lf);
+ buf.append(" "+LOCATORS_NAME+"=");
+ buf.append(String.valueOf(this.locators));
+ buf.append(lf);
+ buf.append(" "+MEMBERSHIP_PORT_RANGE_NAME+"=");
+ buf.append(getMembershipPortRange());
+ buf.append(lf);
+ buf.append(" "+BIND_ADDRESS_NAME+"=");
+ buf.append(String.valueOf(this.bindAddress));
+ buf.append(lf);
+ buf.append(" "+TCP_PORT_NAME+"="+this.tcpPort);
+ buf.append(lf);
+ buf.append(" "+DistributionConfig.DISABLE_TCP_NAME+"=");
+ buf.append(String.valueOf(this.disableTcp));
+ buf.append(lf);
+ buf.append(" "+DistributionConfig.DISABLE_AUTO_RECONNECT_NAME+"=");
+ buf.append(String.valueOf(this.disableAutoReconnect));
+ buf.append(lf);
+ buf.append(" "+REMOTE_COMMAND_NAME+"=");
+ buf.append(String.valueOf(this.remoteCommand));
+ buf.append(lf);
+ buf.append(" "+SSL_ENABLED_NAME+"=");
+ buf.append(String.valueOf(this.sslEnabled));
+ buf.append(lf);
+ buf.append(" "+SSL_CIPHERS_NAME+"=");
+ buf.append(String.valueOf(this.sslCiphers));
+ buf.append(lf);
+ buf.append(" "+SSL_PROTOCOLS_NAME+"=");
+ buf.append(String.valueOf(this.sslProtocols));
+ buf.append(lf);
+ buf.append(" "+SSL_REQUIRE_AUTHENTICATION_NAME+"=");
+ buf.append(String.valueOf(this.sslAuthenticationRequired));
+ buf.append(lf);
+ buf.append(" "+LOG_FILE_NAME+"=");
+ buf.append(String.valueOf(this.logFile));
+ buf.append(lf);
+ buf.append(" "+LOG_LEVEL_NAME+"=");
+ buf.append(String.valueOf(this.logLevel));
+ buf.append(lf);
+ buf.append(" "+LOG_DISK_SPACE_LIMIT_NAME+"=");
+ buf.append(String.valueOf(this.logDiskSpaceLimit));
+ buf.append(lf);
+ buf.append(" "+LOG_FILE_SIZE_LIMIT_NAME+"=");
+ buf.append(String.valueOf(this.logFileSizeLimit));
+ buf.append(lf);
+ buf.append(" "+REFRESH_INTERVAL_NAME+"=");
+ buf.append(String.valueOf(this.refreshInterval));
+ buf.append(")");
+ return buf.toString();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthConfigImpl.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthConfigImpl.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthConfigImpl.java
new file mode 100644
index 0000000..3b633f2
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthConfigImpl.java
@@ -0,0 +1,50 @@
+/*=========================================================================
+ * 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.*;
+
+/**
+ * The implementation of <code>DistributedSystemHealthConfig</code>.
+ * Note that because it never leaves the management VM, it is not
+ * <code>Serializable</code> and is not part of the {@link
+ * GemFireHealthConfigImpl} class hierarchy.
+ *
+ * @author David Whitlock
+ *
+ * @since 3.5
+ */
+public class DistributedSystemHealthConfigImpl
+ implements DistributedSystemHealthConfig {
+
+ /** The maximum number of application members that can
+ * unexceptedly leave a healthy the distributed system. */
+ private long maxDepartedApplications =
+ DEFAULT_MAX_DEPARTED_APPLICATIONS;
+
+ ////////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>DistributedSystemHealthConfigImpl</code> with
+ * the default configuration.
+ */
+ protected DistributedSystemHealthConfigImpl() {
+
+ }
+
+ ///////////////////// Instance Methods /////////////////////
+
+ public long getMaxDepartedApplications() {
+ return this.maxDepartedApplications;
+ }
+
+ public void setMaxDepartedApplications(long maxDepartedApplications)
+ {
+ this.maxDepartedApplications = maxDepartedApplications;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthEvaluator.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthEvaluator.java b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthEvaluator.java
new file mode 100644
index 0000000..a131670
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/admin/internal/DistributedSystemHealthEvaluator.java
@@ -0,0 +1,163 @@
+/*=========================================================================
+ * 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.DistributedSystemHealthConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionManager;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.MembershipListener;
+import java.util.*;
+
+import com.gemstone.gemfire.distributed.internal.membership.*;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+/**
+ * Contains the logic for evaluating the health of an entire GemFire
+ * distributed system according to the thresholds provided in a {@link
+ * DistributedSystemHealthConfig}.
+ *
+ * <P>
+ *
+ * Note that unlike other evaluators, the
+ * <code>DistributedSystemHealthEvaluator</code> resides in the
+ * "administrator" VM and not in the member VMs. This is because
+ * there only needs to be one
+ * <code>DistributedSystemHealthEvaluator</code> per distributed
+ * system.
+ *
+ * @author David Whitlock
+ *
+ * @since 3.5
+ * */
+class DistributedSystemHealthEvaluator
+ extends AbstractHealthEvaluator implements MembershipListener {
+
+ /** The config from which we get the evaluation criteria */
+ private DistributedSystemHealthConfig config;
+
+ /** The distribution manager with which this MembershipListener is
+ * registered */
+ private DM dm;
+
+ /** The description of the distributed system being evaluated */
+ private String description;
+
+ /** The number of application members that have unexpectedly left
+ * since the previous evaluation */
+ private int crashedApplications;
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>DistributedSystemHealthEvaluator</code>
+ */
+ DistributedSystemHealthEvaluator(DistributedSystemHealthConfig config,
+ DM dm) {
+ super(null, dm);
+
+ this.config = config;
+ this.dm = dm;
+ this.dm.addMembershipListener(this);
+
+ StringBuffer sb = new StringBuffer();
+ sb.append("Distributed System ");
+
+ String desc = null;
+ if (dm instanceof DistributionManager) {
+ desc =
+ ((DistributionManager) dm).getDistributionConfigDescription();
+ }
+
+ if (desc != null) {
+ sb.append(desc);
+
+ } else {
+ DistributionConfig dsc = dm.getSystem().getConfig();
+ String locators = dsc.getLocators();
+ if (locators == null || locators.equals("")) {
+ sb.append("using multicast ");
+ sb.append(dsc.getMcastAddress());
+ sb.append(":");
+ sb.append(dsc.getMcastPort());
+
+ } else {
+ sb.append("using locators ");
+ sb.append(locators);
+ }
+ }
+
+ this.description = sb.toString();
+ }
+
+ //////////////////// Instance Methods ////////////////////
+
+ @Override
+ protected String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * Checks to make sure that the number of application members of
+ * the distributed system that have left unexpected since the last
+ * evaluation is less than the {@linkplain
+ * DistributedSystemHealthConfig#getMaxDepartedApplications
+ * threshold}. If not, the status is "poor" health.
+ */
+ void checkDepartedApplications(List status) {
+ synchronized (this) {
+ long threshold = this.config.getMaxDepartedApplications();
+ if (this.crashedApplications > threshold) {
+ String s = LocalizedStrings.DistributedSystemHealth_THE_NUMBER_OF_APPLICATIONS_THAT_HAVE_LEFT_THE_DISTRIBUTED_SYSTEM_0_EXCEEDS_THE_THRESHOLD_1.toLocalizedString(new Object[] { Long.valueOf(this.crashedApplications), Long.valueOf(threshold)});
+ status.add(poorHealth(s));
+ }
+ this.crashedApplications = 0;
+ }
+ }
+
+ @Override
+ protected void check(List status) {
+ checkDepartedApplications(status);
+ }
+
+ @Override
+ void close() {
+ this.dm.removeMembershipListener(this);
+ }
+
+ public void memberJoined(InternalDistributedMember id) {
+
+ }
+
+ /**
+ * Keeps track of which members depart unexpectedly
+ */
+ public void memberDeparted(InternalDistributedMember id, boolean crashed) {
+ if (!crashed)
+ return;
+ synchronized (this) {
+ int kind = id.getVmKind();
+ switch (kind) {
+ case DistributionManager.LOCATOR_DM_TYPE:
+ case DistributionManager.NORMAL_DM_TYPE:
+ this.crashedApplications++;
+ break;
+ default:
+ break;
+ }
+ } // synchronized
+ }
+
+ public void quorumLost(Set<InternalDistributedMember> failures, List<InternalDistributedMember> remaining) {
+ }
+
+ public void memberSuspect(InternalDistributedMember id,
+ InternalDistributedMember whoSuspected) {
+ }
+
+}