Return-Path: X-Original-To: apmail-geode-commits-archive@minotaur.apache.org Delivered-To: apmail-geode-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 94721100B4 for ; Tue, 28 Apr 2015 21:41:51 +0000 (UTC) Received: (qmail 75070 invoked by uid 500); 28 Apr 2015 21:41:51 -0000 Delivered-To: apmail-geode-commits-archive@geode.apache.org Received: (qmail 75004 invoked by uid 500); 28 Apr 2015 21:41:51 -0000 Mailing-List: contact commits-help@geode.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.incubator.apache.org Delivered-To: mailing list commits@geode.incubator.apache.org Received: (qmail 74983 invoked by uid 99); 28 Apr 2015 21:41:51 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 Apr 2015 21:41:51 +0000 X-ASF-Spam-Status: No, hits=-0.0 required=5.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: local policy) Received: from [54.164.171.186] (HELO mx1-us-east.apache.org) (54.164.171.186) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 Apr 2015 21:41:43 +0000 Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-east.apache.org (ASF Mail Server at mx1-us-east.apache.org) with SMTP id 14E7443BAD for ; Tue, 28 Apr 2015 21:41:21 +0000 (UTC) Received: (qmail 69046 invoked by uid 99); 28 Apr 2015 21:40:06 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 28 Apr 2015 21:40:06 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id CC932E0A21; Tue, 28 Apr 2015 21:40:06 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rvs@apache.org To: commits@geode.incubator.apache.org Date: Tue, 28 Apr 2015 21:40:46 -0000 Message-Id: <3cb1e51605104e8d8818dfe7fea4da87@git.apache.org> In-Reply-To: <9e9818e7b1254a349e64bb9fdafc5503@git.apache.org> References: <9e9818e7b1254a349e64bb9fdafc5503@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [41/51] [partial] incubator-geode git commit: Init X-Virus-Checked: Checked by ClamAV on apache.org 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> backedUpDiskStores; + private Set offlineDiskStores; + + public BackupStatusImpl( + Map> backedUpDiskStores, + Set offlineDiskStores) { + super(); + this.backedUpDiskStores = backedUpDiskStores; + this.offlineDiskStores = offlineDiskStores; + } + + public Map> getBackedUpDiskStores() { + return backedUpDiskStores; + } + + public Set 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 CacheHealthConfig + * + * @author David Whitlock + * + * @since 3.5 + */ +public abstract class CacheHealthConfigImpl + extends MemberHealthConfigImpl implements CacheHealthConfig { + + /** The maximum number of milliseconds a + * netSearch 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 + * load 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 CacheHealthConfigImpl 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 + * Cache 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 Cache instance. If no cache + * has been created in this VM, this field will be null + */ + 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 CacheHealthEvaluator + */ + 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 netSearch 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 load 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. + * + *

+ * + * The following formula is used to compute the hit ratio: + * + *

+   * hitRatio = (gets - (loadsCompleted + netsearchesCompleted)) / (gets)
+   * 
+ * + * + * @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 CacheVmConfig + * + * @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 CacheServerConfigImpl with the default + * configuration settings. + */ + public CacheServerConfigImpl() { + this.cacheXMLFile = null; + this.classpath = null; + } + + /** + * Creates a new CacheServerConfigImpl 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 CacheServers 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 CacheServerImpl 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 CacheServerImpl 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 ConfigurationParameterImpl. + * + * @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 ConfigurationParameterImpl. + * + * @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 + * AdminDistributedSystem. After a config has been used + * to create an AdminDistributedSystem 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 + * AdminDistributedSystem 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 + * DistributedSystemConfig that are not present in the + * internal DistributionConfig. + * + * @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 DistributedSystemConfigImpl based on + * the configuration stored in a DistributedSystem's + * DistributionConfig. + */ + 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 DistributedSystemConifgImpl whose + * configuration is specified by the given Properties + * object. + */ + protected DistributedSystemConfigImpl(Properties props) { + this(props, false); + } + + /** + * Creates a new DistributedSystemConifgImpl whose configuration + * is specified by the given Properties 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 LogWriterI18n to be used when administering + * the distributed system. Returns null if nothing has been provided via + * setInternalLogWriter. + * + * @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 LogWriterI18n 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 array = new ArrayList(); + 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 DistributedSystemHealthConfig. + * Note that because it never leaves the management VM, it is not + * Serializable 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 DistributedSystemHealthConfigImpl 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}. + * + *

+ * + * Note that unlike other evaluators, the + * DistributedSystemHealthEvaluator resides in the + * "administrator" VM and not in the member VMs. This is because + * there only needs to be one + * DistributedSystemHealthEvaluator 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 DistributedSystemHealthEvaluator + */ + 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 failures, List remaining) { + } + + public void memberSuspect(InternalDistributedMember id, + InternalDistributedMember whoSuspected) { + } + +}