You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2016/10/26 22:11:40 UTC
[18/42] incubator-geode git commit: GEODE-288: move admin package to
internal
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemConfigImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemConfigImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemConfigImpl.java
new file mode 100755
index 0000000..be83024
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemConfigImpl.java
@@ -0,0 +1,1135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.internal.admin.api.impl;
+
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.DistributionConfigImpl;
+import org.apache.geode.internal.admin.api.AdminXmlException;
+import org.apache.geode.internal.admin.api.CacheServerConfig;
+import org.apache.geode.internal.admin.api.CacheVmConfig;
+import org.apache.geode.internal.admin.api.DistributedSystemConfig;
+import org.apache.geode.internal.admin.api.DistributionLocator;
+import org.apache.geode.internal.admin.api.DistributionLocatorConfig;
+import org.apache.geode.internal.i18n.LocalizedStrings;
+import org.apache.geode.internal.logging.InternalLogWriter;
+import org.apache.geode.internal.logging.LogConfig;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.internal.logging.LogWriterImpl;
+import org.apache.logging.log4j.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+
+import static org.apache.geode.distributed.ConfigurationProperties.*;
+
+/**
+ * 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 GemFire 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 GemFire 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 GemFire 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.getClusterSSLEnabled();
+ this.sslCiphers = distConfig.getClusterSSLCiphers();
+ this.sslProtocols = distConfig.getClusterSSLProtocols();
+ this.sslAuthenticationRequired = distConfig.getClusterSSLRequireAuthentication();
+
+ 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 GemFire 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 GemFire 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 GemFire 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 GemFire 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 GemFire 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(DistributionConfig.GEMFIRE_PREFIX + "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 GemFire 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 GemFire 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 GemFire 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 GemFire 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 GemFire 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 + "=");
+ buf.append(String.valueOf(this.mcastAddress));
+ buf.append(lf);
+ buf.append(" " + MCAST_PORT + "=");
+ buf.append(String.valueOf(this.mcastPort));
+ buf.append(lf);
+ buf.append(" " + LOCATORS + "=");
+ 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 + "=");
+ buf.append(String.valueOf(this.bindAddress));
+ buf.append(lf);
+ buf.append(" " + TCP_PORT + "=" + this.tcpPort);
+ buf.append(lf);
+ buf.append(" " + DISABLE_TCP + "=");
+ buf.append(String.valueOf(this.disableTcp));
+ buf.append(lf);
+ buf.append(" " + DISABLE_AUTO_RECONNECT + "=");
+ 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(" " + CLUSTER_SSL_ENABLED + "=");
+ buf.append(String.valueOf(this.sslEnabled));
+ buf.append(lf);
+ buf.append(" " + CLUSTER_SSL_CIPHERS + "=");
+ buf.append(String.valueOf(this.sslCiphers));
+ buf.append(lf);
+ buf.append(" " + CLUSTER_SSL_PROTOCOLS + "=");
+ buf.append(String.valueOf(this.sslProtocols));
+ buf.append(lf);
+ buf.append(" " + CLUSTER_SSL_REQUIRE_AUTHENTICATION + "=");
+ 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/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthConfigImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthConfigImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthConfigImpl.java
new file mode 100644
index 0000000..9d3f5e6
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthConfigImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.internal.admin.api.impl;
+
+import org.apache.geode.internal.admin.api.DistributedSystemHealthConfig;
+
+/**
+ * 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.
+ *
+ *
+ * @since GemFire 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/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthEvaluator.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthEvaluator.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthEvaluator.java
new file mode 100644
index 0000000..ac47ddc
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthEvaluator.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.internal.admin.api.impl;
+
+import org.apache.geode.internal.admin.api.DistributedSystemHealthConfig;
+import org.apache.geode.distributed.internal.DM;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.distributed.internal.MembershipListener;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.i18n.LocalizedStrings;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 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.
+ *
+ *
+ * @since GemFire 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, String reason) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthMonitor.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthMonitor.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthMonitor.java
new file mode 100644
index 0000000..3ce8bcc
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributedSystemHealthMonitor.java
@@ -0,0 +1,436 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.internal.admin.api.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.SystemFailure;
+import org.apache.geode.internal.admin.api.AdminException;
+import org.apache.geode.internal.admin.api.GemFireHealth;
+import org.apache.geode.internal.admin.api.GemFireHealthConfig;
+import org.apache.geode.internal.admin.api.GemFireMemberStatus;
+import org.apache.geode.internal.admin.api.RegionSubRegionSnapshot;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionAttributes;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.Assert;
+import org.apache.geode.internal.Config;
+import org.apache.geode.internal.net.SocketCreator;
+import org.apache.geode.internal.admin.AdminBridgeServer;
+import org.apache.geode.internal.admin.CacheInfo;
+import org.apache.geode.internal.admin.DLockInfo;
+import org.apache.geode.internal.admin.GemFireVM;
+import org.apache.geode.internal.admin.GfManagerAgent;
+import org.apache.geode.internal.admin.HealthListener;
+import org.apache.geode.internal.admin.Stat;
+import org.apache.geode.internal.admin.StatAlertDefinition;
+import org.apache.geode.internal.admin.StatListener;
+import org.apache.geode.internal.admin.StatResource;
+import org.apache.geode.internal.i18n.LocalizedStrings;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.internal.logging.LoggingThreadGroup;
+import org.apache.geode.internal.logging.log4j.LocalizedMessage;
+
+/**
+ * A thread that monitors the health of the distributed system. It is
+ * kind of like a {@link
+ * org.apache.geode.distributed.internal.HealthMonitorImpl}. In
+ * order to get it to place nice with the rest of the health
+ * monitoring APIs, this class pretends that it is a
+ * <code>GemFireVM</code>. Kind of hokey, but it beats a bunch of
+ * special-case code.
+ *
+ *
+ * @since GemFire 3.5
+ * */
+class DistributedSystemHealthMonitor implements Runnable, GemFireVM {
+
+ private static final Logger logger = LogService.getLogger();
+
+ /** Evaluates the health of the distributed system */
+ private DistributedSystemHealthEvaluator eval;
+
+ /** Notified when the health of the distributed system changes */
+ private GemFireHealthImpl healthImpl;
+
+ /** The number of seconds between health checks */
+ private int interval;
+
+ /** The thread in which the monitoring occurs */
+ private Thread thread;
+
+ /** Has this monitor been asked to stop? */
+ private volatile boolean stopRequested = false;
+
+ /** The health of the distributed system the last time we checked. */
+ private GemFireHealth.Health prevHealth = GemFireHealth.GOOD_HEALTH;
+
+ /** The most recent <code>OKAY_HEALTH</code> diagnoses of the
+ * GemFire system */
+ private List okayDiagnoses;
+
+ /** The most recent <code>POOR_HEALTH</code> diagnoses of the
+ * GemFire system */
+ private List poorDiagnoses;
+
+ ////////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>DistributedSystemHealthMonitor</code> that
+ * evaluates the health of the distributed system against the given
+ * thresholds once every <code>interval</code> seconds.
+ *
+ * @param eval
+ * Used to evaluate the health of the distributed system
+ * @param healthImpl
+ * Receives callbacks when the health of the distributed
+ * system changes
+ * @param interval
+ * How often the health is checked
+ */
+ DistributedSystemHealthMonitor(DistributedSystemHealthEvaluator eval,
+ GemFireHealthImpl healthImpl,
+ int interval) {
+ this.eval = eval;
+ this.healthImpl = healthImpl;
+ this.interval = interval;
+ this.okayDiagnoses = new ArrayList();
+ this.poorDiagnoses = new ArrayList();
+
+ ThreadGroup group =
+ LoggingThreadGroup.createThreadGroup(LocalizedStrings.DistributedSystemHealthMonitor_HEALTH_MONITORS.toLocalizedString(), logger);
+ String name = LocalizedStrings.DistributedSystemHealthMonitor_HEALTH_MONITOR_FOR_0.toLocalizedString(eval.getDescription());
+ this.thread = new Thread(group, this, name);
+ this.thread.setDaemon(true);
+ }
+
+ /**
+ * Does the work of monitoring the health of the distributed
+ * system.
+ */
+ public void run() {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Monitoring health of {} every {} seconds", this.eval.getDescription(), interval);
+ }
+
+ while (!this.stopRequested) {
+ SystemFailure.checkFailure();
+ try {
+ Thread.sleep(interval * 1000);
+ List status = new ArrayList();
+ eval.evaluate(status);
+
+ GemFireHealth.Health overallHealth = GemFireHealth.GOOD_HEALTH;
+ this.okayDiagnoses.clear();
+ this.poorDiagnoses.clear();
+
+ for (Iterator iter = status.iterator(); iter.hasNext(); ) {
+ AbstractHealthEvaluator.HealthStatus health =
+ (AbstractHealthEvaluator.HealthStatus) iter.next();
+ if (overallHealth == GemFireHealth.GOOD_HEALTH) {
+ if ((health.getHealthCode() != GemFireHealth.GOOD_HEALTH)) {
+ overallHealth = health.getHealthCode();
+ }
+
+ } else if (overallHealth == GemFireHealth.OKAY_HEALTH) {
+ if (health.getHealthCode() == GemFireHealth.POOR_HEALTH) {
+ overallHealth = GemFireHealth.POOR_HEALTH;
+ }
+ }
+
+ GemFireHealth.Health healthCode = health.getHealthCode();
+ if (healthCode == GemFireHealth.OKAY_HEALTH) {
+ this.okayDiagnoses.add(health.getDiagnosis());
+
+ } else if (healthCode == GemFireHealth.POOR_HEALTH) {
+ this.poorDiagnoses.add(health.getDiagnosis());
+ break;
+ }
+ }
+
+ if (overallHealth != prevHealth) {
+ healthImpl.healthChanged(this, overallHealth);
+ this.prevHealth = overallHealth;
+ }
+
+ } catch (InterruptedException ex) {
+ // We're all done
+ // No need to reset the interrupted flag, since we're going to exit.
+ break;
+ }
+ }
+
+ eval.close();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Stopped checking for distributed system health");
+ }
+ }
+
+ /**
+ * Starts this <code>DistributedSystemHealthMonitor</code>
+ */
+ void start(){
+ this.thread.start();
+ }
+
+ /**
+ * Stops this <code>DistributedSystemHealthMonitor</code>
+ */
+ void stop() {
+ if (this.thread.isAlive()) {
+ this.stopRequested = true;
+ this.thread.interrupt();
+ this.healthImpl.nodeLeft(null, this);
+
+ try {
+ this.thread.join();
+ }
+ catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ logger.warn(LocalizedMessage.create(LocalizedStrings.DistributedSystemHealthMonitor_INTERRUPTED_WHILE_STOPPING_HEALTH_MONITOR_THREAD), ex);
+ }
+ }
+ }
+
+ ////////////////////// GemFireVM Methods //////////////////////
+
+ public java.net.InetAddress getHost() {
+ try {
+ return SocketCreator.getLocalHost();
+
+ } catch (Exception ex) {
+ throw new org.apache.geode.InternalGemFireException(LocalizedStrings.DistributedSystemHealthMonitor_COULD_NOT_GET_LOCALHOST.toLocalizedString());
+ }
+ }
+
+ public String getName() {
+// return getId().toString();
+ throw new UnsupportedOperationException("Not a real GemFireVM");
+ }
+
+ public java.io.File getWorkingDirectory() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public java.io.File getGemFireDir() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public java.util.Date getBirthDate() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Properties getLicenseInfo(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public GemFireMemberStatus getSnapshot() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public RegionSubRegionSnapshot getRegionSnapshot() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public StatResource[] getStats(String statisticsTypeName){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public StatResource[] getAllStats(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public DLockInfo[] getDistributedLockInfo(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void addStatListener(StatListener observer,
+ StatResource observedResource,
+ Stat observedStat){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void removeStatListener(StatListener observer){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void addHealthListener(HealthListener observer,
+ GemFireHealthConfig cfg){
+
+ }
+
+ public void removeHealthListener(){
+
+ }
+
+ public void resetHealthStatus(){
+ this.prevHealth = GemFireHealth.GOOD_HEALTH;
+ }
+
+ public String[] getHealthDiagnosis(GemFireHealth.Health healthCode){
+ if (healthCode == GemFireHealth.GOOD_HEALTH) {
+ return new String[0];
+
+ } else if (healthCode == GemFireHealth.OKAY_HEALTH) {
+ String[] array = new String[this.okayDiagnoses.size()];
+ this.okayDiagnoses.toArray(array);
+ return array;
+
+ } else {
+ Assert.assertTrue(healthCode == GemFireHealth.POOR_HEALTH);
+ String[] array = new String[this.poorDiagnoses.size()];
+ this.poorDiagnoses.toArray(array);
+ return array;
+ }
+ }
+
+ public Config getConfig(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void setConfig(Config cfg){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public GfManagerAgent getManagerAgent(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public String[] getSystemLogs(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void setInspectionClasspath(String classpath){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public String getInspectionClasspath(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region[] getRootRegions(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region getRegion(CacheInfo c, String path) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region createVMRootRegion(CacheInfo c, String name,
+ RegionAttributes attrs) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public Region createSubregion(CacheInfo c, String parentPath,
+ String name, RegionAttributes attrs) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void setCacheInspectionMode(int mode) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public int getCacheInspectionMode(){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public void takeRegionSnapshot(String regionName, int snapshotId){
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public InternalDistributedMember getId() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo getCacheInfo() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public String getVersionInfo() {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo setCacheLockTimeout(CacheInfo c, int v) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo setCacheLockLease(CacheInfo c, int v) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public CacheInfo setCacheSearchTimeout(CacheInfo c, int v) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer addCacheServer(CacheInfo cache)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer getBridgeInfo(CacheInfo cache,
+ int id)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer startBridgeServer(CacheInfo cache,
+ AdminBridgeServer bridge)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ public AdminBridgeServer stopBridgeServer(CacheInfo cache,
+ AdminBridgeServer bridge)
+ throws AdminException {
+
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ /**
+ * This operation is not supported for this object. Will throw
+ * UnsupportedOperationException if invoked.
+ */
+ public void setAlertsManager(StatAlertDefinition[] alertDefs,
+ long refreshInterval, boolean setRemotely) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ /**
+ * This operation is not supported for this object. Will throw
+ * UnsupportedOperationException if invoked.
+ */
+ public void setRefreshInterval(long refreshInterval) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+
+ /**
+ * This operation is not supported for this object. Will throw
+ * UnsupportedOperationException if invoked.
+ */
+ public void updateAlertDefinitions(StatAlertDefinition[] alertDefs,
+ int actionCode) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributedSystemHealthMonitor_NOT_A_REAL_GEMFIREVM.toLocalizedString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorConfigImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorConfigImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorConfigImpl.java
new file mode 100644
index 0000000..5b40d64
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorConfigImpl.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.internal.admin.api.impl;
+
+import org.apache.geode.internal.admin.api.DistributionLocator;
+import org.apache.geode.internal.admin.api.DistributionLocatorConfig;
+import org.apache.geode.distributed.internal.tcpserver.*;
+import org.apache.geode.internal.i18n.LocalizedStrings;
+
+import java.net.InetAddress;
+import java.util.Properties;
+
+import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
+
+/**
+ * Provides an implementation of
+ * <code>DistributionLocatorConfig</code>.
+ *
+ * @since GemFire 4.0
+ */
+public class DistributionLocatorConfigImpl
+ extends ManagedEntityConfigImpl
+ implements DistributionLocatorConfig {
+
+ /** The minimum networking port (0) */
+ public static final int MIN_PORT = 0;
+
+ /** The maximum networking port (65535) */
+ public static final int MAX_PORT = 65535;
+
+ ////////////////////// Instance Fields //////////////////////
+
+ /** The port on which this locator listens */
+ private int port;
+
+ /** The address to bind to on a multi-homed host */
+ private String bindAddress;
+
+ /** The properties used to configure the DistributionLocator's
+ DistributedSystem */
+ private Properties dsProperties;
+
+ /** The DistributionLocator that was created with this config */
+ private DistributionLocator locator;
+
+ ////////////////////// Static Methods //////////////////////
+
+ /**
+ * Contacts a distribution locator on the given host and port and
+ * creates a <code>DistributionLocatorConfig</code> for it.
+ *
+ * @see TcpClient#getLocatorInfo
+ *
+ * @return <code>null</code> if the locator cannot be contacted
+ */
+ static DistributionLocatorConfig
+ createConfigFor(String host, int port, InetAddress bindAddress) {
+ TcpClient client = new TcpClient();
+ String[] info = null;
+ if (bindAddress != null) {
+ info = client.getInfo(bindAddress, port);
+ }
+ else {
+ info = client.getInfo(InetAddressUtil.toInetAddress(host), port);
+ }
+ if (info == null) {
+ return null;
+ }
+
+ DistributionLocatorConfigImpl config =
+ new DistributionLocatorConfigImpl();
+ config.setHost(host);
+ config.setPort(port);
+ if (bindAddress != null) {
+ config.setBindAddress(bindAddress.getHostAddress());
+ }
+ config.setWorkingDirectory(info[0]);
+ config.setProductDirectory(info[1]);
+
+ return config;
+ }
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>DistributionLocatorConfigImpl</code> with the
+ * default settings.
+ */
+ public DistributionLocatorConfigImpl() {
+ this.port = 0;
+ this.bindAddress = null;
+ this.locator = null;
+ this.dsProperties = new java.util.Properties();
+ this.dsProperties.setProperty(MCAST_PORT, "0");
+ }
+
+ ///////////////////// Instance Methods /////////////////////
+
+ /**
+ * Sets the locator that was configured with this
+ * <Code>DistributionLocatorConfigImpl</code>.
+ */
+ void setLocator(DistributionLocator locator) {
+ this.locator = locator;
+ }
+
+ @Override
+ protected boolean isReadOnly() {
+ return this.locator != null && this.locator.isRunning();
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ public void setPort(int port) {
+ checkReadOnly();
+ this.port = port;
+ configChanged();
+ }
+
+ public String getBindAddress() {
+ return this.bindAddress;
+ }
+
+ public void setBindAddress(String bindAddress) {
+ checkReadOnly();
+ this.bindAddress = bindAddress;
+ configChanged();
+ }
+
+ public void setDistributedSystemProperties(Properties props) {
+ this.dsProperties = props;
+ }
+
+ public Properties getDistributedSystemProperties() {
+ return this.dsProperties;
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+
+ if (port < MIN_PORT || port > MAX_PORT) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributionLocatorConfigImpl_PORT_0_MUST_BE_AN_INTEGER_BETWEEN_1_AND_2.toLocalizedString(new Object[] {Integer.valueOf(port), Integer.valueOf(MIN_PORT), Integer.valueOf(MAX_PORT)}));
+ }
+
+ if (this.bindAddress != null &&
+ InetAddressUtil.validateHost(this.bindAddress) == null) {
+ throw new IllegalArgumentException(LocalizedStrings.DistributionLocatorConfigImpl_INVALID_HOST_0.toLocalizedString(this.bindAddress));
+ }
+ }
+
+ /**
+ * Currently, listeners are not supported on the locator config.
+ */
+ @Override
+ protected void configChanged() {
+
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ DistributionLocatorConfigImpl clone =
+ (DistributionLocatorConfigImpl) super.clone();
+ clone.locator = null;
+ return clone;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("DistributionLocatorConfig: host=").append(getHost());
+ sb.append(", bindAddress=").append(getBindAddress());
+ sb.append(", port=").append(getPort());
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorImpl.java
new file mode 100755
index 0000000..0e5db21
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DistributionLocatorImpl.java
@@ -0,0 +1,336 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geode.internal.admin.api.impl;
+
+import org.apache.geode.internal.admin.api.AdminDistributedSystem;
+import org.apache.geode.internal.admin.api.DistributionLocator;
+import org.apache.geode.internal.admin.api.DistributionLocatorConfig;
+import org.apache.geode.internal.admin.api.ManagedEntityConfig;
+import org.apache.geode.distributed.internal.DM;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.admin.remote.DistributionLocatorId;
+import org.apache.geode.internal.i18n.LocalizedStrings;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.internal.logging.log4j.LocalizedMessage;
+import org.apache.logging.log4j.Logger;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
+
+/**
+ * Default administrative implementation of a DistributionLocator.
+ *
+ * @since GemFire 3.5
+ */
+public class DistributionLocatorImpl
+ implements DistributionLocator, InternalManagedEntity {
+
+ private static final Logger logger = LogService.getLogger();
+
+ /**
+ * How many new <code>DistributionLocator</code>s have been created?
+ */
+ private static int newLocators = 0;
+
+ //////////////////// Instance Fields ////////////////////
+
+ /**
+ * The configuration object for this locator
+ */
+ private final DistributionLocatorConfigImpl config;
+
+ /**
+ * The id of this distribution locator
+ */
+ private final String id;
+
+ /**
+ * Used to control the actual DistributionLocator service
+ */
+ private ManagedEntityController controller;
+
+ /**
+ * The system that this locator is a part of
+ */
+ private AdminDistributedSystemImpl system;
+
+ // -------------------------------------------------------------------------
+ // constructor(s)...
+ // -------------------------------------------------------------------------
+
+ /**
+ * Constructs new instance of <code>DistributionLocatorImpl</code>
+ * that is a member of the given distributed system.
+ */
+ public DistributionLocatorImpl(DistributionLocatorConfig config,
+ AdminDistributedSystemImpl system) {
+ this.config = (DistributionLocatorConfigImpl) config;
+ this.config.validate();
+ this.config.setManagedEntity(this);
+ this.id = getNewId();
+ this.controller = system.getEntityController();
+ this.system = system;
+ }
+
+ // -------------------------------------------------------------------------
+ // Attribute accessors/mutators...
+ // -------------------------------------------------------------------------
+
+ public String getId() {
+ return this.id;
+ }
+
+ public String getNewId() {
+ synchronized (DistributionLocatorImpl.class) {
+ return "Locator" + (++newLocators);
+ }
+ }
+
+ /**
+ * Returns the configuration object for this locator.
+ *
+ * @since GemFire 4.0
+ */
+ public DistributionLocatorConfig getConfig() {
+ return this.config;
+ }
+
+ public AdminDistributedSystem getDistributedSystem() {
+ return this.system;
+ }
+
+ /**
+ * Unfortunately, it doesn't make much sense to maintain the state
+ * of a locator. The admin API does not receive notification when
+ * the locator actually starts and stops. If we try to guess, we'll
+ * just end up with race conditions galore. So, we can't fix bug
+ * 32455 for locators.
+ */
+ public int setState(int state) {
+ throw new UnsupportedOperationException(LocalizedStrings.DistributionLocatorImpl_CAN_NOT_SET_THE_STATE_OF_A_LOCATOR.toLocalizedString());
+ }
+
+ // -------------------------------------------------------------------------
+ // Operations...
+ // -------------------------------------------------------------------------
+
+ /**
+ * Polls to determine whether or not this managed entity has
+ * started.
+ */
+ public boolean waitToStart(long timeout)
+ throws InterruptedException {
+
+ if (Thread.interrupted())
+ throw new InterruptedException();
+
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() - start < timeout) {
+ if (this.isRunning()) {
+ return true;
+
+ } else {
+ Thread.sleep(100);
+ }
+ }
+
+ logger.info(LocalizedMessage.create(
+ LocalizedStrings.DistributionLocatorImpl_DONE_WAITING_FOR_LOCATOR));
+ return this.isRunning();
+ }
+
+ /**
+ * Polls to determine whether or not this managed entity has
+ * stopped.
+ */
+ public boolean waitToStop(long timeout)
+ throws InterruptedException {
+
+ if (Thread.interrupted())
+ throw new InterruptedException();
+
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() - start < timeout) {
+ if (!this.isRunning()) {
+ return true;
+
+ } else {
+ Thread.sleep(100);
+ }
+ }
+
+ return !this.isRunning();
+ }
+
+ public boolean isRunning() {
+ DM dm = ((AdminDistributedSystemImpl) getDistributedSystem()).getDistributionManager();
+ if (dm == null) {
+ try {
+ return this.controller.isRunning(this);
+ } catch (IllegalStateException e) {
+ return false;
+ }
+ }
+
+ String host = getConfig().getHost();
+ int port = getConfig().getPort();
+ String bindAddress = getConfig().getBindAddress();
+
+ boolean found = false;
+ Map<InternalDistributedMember, Collection<String>> hostedLocators = dm.getAllHostedLocators();
+ for (Iterator<InternalDistributedMember> memberIter = hostedLocators.keySet().iterator(); memberIter.hasNext(); ) {
+ for (Iterator<String> locatorIter = hostedLocators.get(memberIter.next()).iterator(); locatorIter.hasNext(); ) {
+ DistributionLocatorId locator = new DistributionLocatorId(locatorIter.next());
+ found = found || locator.getHost().getHostAddress().equals(host);
+ found = found || locator.getHost().getHostName().equals(host);
+ if (!found && !host.contains(".")) {
+ try {
+ InetAddress inetAddr = InetAddress.getByName(host);
+ found = locator.getHost().getHostName().equals(inetAddr.getHostName());
+ if (!found) {
+ found = locator.getHost().getHostAddress().equals(inetAddr.getHostAddress());
+ }
+ } catch (UnknownHostException e) {
+ // try config host as if it is an IP address instead of host name
+ }
+ }
+ if (locator.getBindAddress() != null && !locator.getBindAddress().isEmpty()
+ && bindAddress != null && !bindAddress.isEmpty()) {
+ found = found && locator.getBindAddress().equals(bindAddress);
+ }
+ found = found && locator.getPort() == port;
+ if (found) {
+ return true;
+ }
+ }
+ }
+ return found;
+ }
+
+ public void start() {
+ this.config.validate();
+ this.controller.start(this);
+ this.config.setLocator(this);
+ this.system.updateLocatorsString();
+ }
+
+ public void stop() {
+ this.controller.stop(this);
+ this.config.setLocator(null);
+ }
+
+ public String getLog() {
+ return this.controller.getLog(this);
+ }
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return a string representation of the object
+ */
+ @Override
+ public String toString() {
+ return "DistributionLocator " + getId();
+ }
+
+ //////////////////////// Command execution ////////////////////////
+
+ public ManagedEntityConfig getEntityConfig() {
+ return this.getConfig();
+ }
+
+ public String getEntityType() {
+ return "Locator";
+ }
+
+ public String getStartCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" start-locator -q -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+ sb.append(" -port=");
+ sb.append(this.getConfig().getPort());
+ Properties props = config.getDistributedSystemProperties();
+ Enumeration en = props.propertyNames();
+ while (en.hasMoreElements()) {
+ String pn = (String) en.nextElement();
+ sb.append(" -D" + DistributionConfig.GEMFIRE_PREFIX + "" + pn + "=" + props.getProperty(pn));
+ }
+
+ String bindAddress = this.getConfig().getBindAddress();
+ if (bindAddress != null && bindAddress.length() > 0) {
+ sb.append(" -address=");
+ sb.append(this.getConfig().getBindAddress());
+ }
+ sb.append(" ");
+
+ String sslArgs =
+ this.controller.buildSSLArguments(this.system.getConfig());
+ if (sslArgs != null) {
+ sb.append(sslArgs);
+ }
+
+ return sb.toString().trim();
+ }
+
+ public String getStopCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" stop-locator -q -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+ sb.append(" -port=");
+ sb.append(this.getConfig().getPort());
+
+ String bindAddress = this.getConfig().getBindAddress();
+ if (bindAddress != null && bindAddress.length() > 0) {
+ sb.append(" -address=");
+ sb.append(this.getConfig().getBindAddress());
+ }
+ sb.append(" ");
+
+ String sslArgs =
+ this.controller.buildSSLArguments(this.system.getConfig());
+ if (sslArgs != null) {
+ sb.append(sslArgs);
+ }
+
+ return sb.toString().trim();
+ }
+
+ public String getIsRunningCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" status-locator -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ return sb.toString().trim();
+ }
+
+ public String getLogCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "gemfire"));
+ sb.append(" tail-locator-log -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ return sb.toString().trim();
+ }
+
+}
+