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:41 UTC
[19/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/BackupDataStoreHelper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupDataStoreHelper.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupDataStoreHelper.java
new file mode 100644
index 0000000..8410d9b
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupDataStoreHelper.java
@@ -0,0 +1,76 @@
+/*
+ * 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.io.File;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.geode.cache.persistence.PersistentID;
+import org.apache.geode.distributed.DistributedLockService;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.internal.DM;
+import org.apache.geode.internal.Assert;
+
+public class BackupDataStoreHelper {
+
+ public static String LOCK_SERVICE_NAME = BackupDataStoreHelper.class.getSimpleName();
+
+ private static String LOCK_NAME = LOCK_SERVICE_NAME + "_token";
+
+ private static Object LOCK_SYNC = new Object();
+
+ @SuppressWarnings("rawtypes")
+ public static BackupDataStoreResult backupAllMembers(
+ DM dm, Set recipients, File targetDir, File baselineDir) {
+ FlushToDiskRequest.send(dm, recipients);
+
+ boolean abort= true;
+ Map<DistributedMember, Set<PersistentID>> successfulMembers;
+ Map<DistributedMember, Set<PersistentID>> existingDataStores;
+ try {
+ existingDataStores = PrepareBackupRequest.send(dm, recipients);
+ abort = false;
+ } finally {
+ successfulMembers = FinishBackupRequest.send(dm, recipients, targetDir, baselineDir, abort);
+ }
+ return new BackupDataStoreResult(existingDataStores, successfulMembers);
+ }
+
+ private static DistributedLockService getLockService(DM dm) {
+ DistributedLockService dls = DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME);
+ if (dls == null) {
+ synchronized (LOCK_SYNC) {
+ dls = DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME);
+ if (dls == null) {
+ // Create the DistributedLockService
+ dls = DistributedLockService.create(LOCK_SERVICE_NAME, dm.getSystem());
+ }
+ }
+ }
+ Assert.assertTrue(dls != null);
+ return dls;
+ }
+
+ public static boolean obtainLock(DM dm) {
+ return getLockService(dm).lock(LOCK_NAME, 0, -1);
+ }
+
+ public static void releaseLock(DM dm) {
+ getLockService(dm).unlock(LOCK_NAME);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupDataStoreResult.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupDataStoreResult.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupDataStoreResult.java
new file mode 100644
index 0000000..ae425d2
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupDataStoreResult.java
@@ -0,0 +1,57 @@
+/*
+ * 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.Map;
+import java.util.Set;
+
+import org.apache.geode.cache.persistence.PersistentID;
+import org.apache.geode.distributed.DistributedMember;
+
+public class BackupDataStoreResult {
+
+ private Map<DistributedMember, Set<PersistentID>> existingDataStores;
+
+ private Map<DistributedMember, Set<PersistentID>> successfulMembers;
+
+ public BackupDataStoreResult(
+ Map<DistributedMember, Set<PersistentID>> existingDataStores,
+ Map<DistributedMember, Set<PersistentID>> successfulMembers) {
+ this.existingDataStores = existingDataStores;
+ this.successfulMembers = successfulMembers;
+ }
+
+ public Map<DistributedMember, Set<PersistentID>> getExistingDataStores() {
+ return this.existingDataStores;
+ }
+
+ public Map<DistributedMember, Set<PersistentID>> getSuccessfulMembers() {
+ return this.successfulMembers;
+ }
+
+ public String toString() {
+ return new StringBuilder()
+ .append(getClass().getSimpleName())
+ .append("[")
+ .append("existingDataStores=")
+ .append(this.existingDataStores)
+ .append("; successfulMembers=")
+ .append(this.successfulMembers)
+ .append("]")
+ .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/BackupStatusImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupStatusImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupStatusImpl.java
new file mode 100644
index 0000000..e4ff89d
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/BackupStatusImpl.java
@@ -0,0 +1,61 @@
+/*
+ * 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.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.geode.internal.admin.api.BackupStatus;
+import org.apache.geode.cache.persistence.PersistentID;
+import org.apache.geode.distributed.DistributedMember;
+
+/**
+ * Holds the result of a backup operation.
+ *
+ *
+ */
+public class BackupStatusImpl implements BackupStatus, Serializable {
+ private static final long serialVersionUID = 3704162840296921840L;
+
+ private Map<DistributedMember, Set<PersistentID>> backedUpDiskStores;
+ private Set<PersistentID> offlineDiskStores;
+
+ public BackupStatusImpl(
+ Map<DistributedMember, Set<PersistentID>> backedUpDiskStores,
+ Set<PersistentID> offlineDiskStores) {
+ super();
+ this.backedUpDiskStores = backedUpDiskStores;
+ this.offlineDiskStores = offlineDiskStores;
+ }
+
+ public Map<DistributedMember, Set<PersistentID>> getBackedUpDiskStores() {
+ return backedUpDiskStores;
+ }
+
+ public Set<PersistentID> getOfflineDiskStores() {
+ return offlineDiskStores;
+ }
+
+ @Override
+ public String toString() {
+ return "BackupStatus[backedUpDiskStores=" + backedUpDiskStores + ", offlineDiskStores=" + offlineDiskStores + "]";
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthConfigImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthConfigImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthConfigImpl.java
new file mode 100644
index 0000000..b0afdb4
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthConfigImpl.java
@@ -0,0 +1,91 @@
+/*
+ * 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.CacheHealthConfig;
+
+/**
+ * The implementation of <code>CacheHealthConfig</code>
+ *
+ *
+ * @since GemFire 3.5
+ */
+public abstract class CacheHealthConfigImpl
+ extends MemberHealthConfigImpl implements CacheHealthConfig {
+
+ /** The maximum number of milliseconds a
+ * <code>netSearch</code> operation can take before the cache member
+ * is considered to be unhealthy. */
+ private long maxNetSearchTime = DEFAULT_MAX_NET_SEARCH_TIME;
+
+ /** The maximum mumber of milliseconds a cache
+ * <code>load</code> operation can take before the cache member is
+ * considered to be unhealthy. */
+ private long maxLoadTime = DEFAULT_MAX_LOAD_TIME;
+
+ /** The minimum hit ratio of a healthy cache member. */
+ private double minHitRatio = DEFAULT_MIN_HIT_RATIO;
+
+ /** The maximum number of entries in the event delivery queue
+ * of a healthy cache member. */
+ private long maxEventQueueSize = DEFAULT_MAX_EVENT_QUEUE_SIZE;
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>CacheHealthConfigImpl</code> with the default
+ * configuration.
+ */
+ CacheHealthConfigImpl() {
+
+ }
+
+ ////////////////////// Instance Methods /////////////////////
+
+ public long getMaxNetSearchTime() {
+ return this.maxNetSearchTime;
+ }
+
+ public void setMaxNetSearchTime(long maxNetSearchTime) {
+ this.maxNetSearchTime = maxNetSearchTime;
+ }
+
+ public long getMaxLoadTime() {
+ return this.maxLoadTime;
+ }
+
+ public void setMaxLoadTime(long maxLoadTime) {
+ this.maxLoadTime = maxLoadTime;
+ }
+
+ public double getMinHitRatio() {
+ return this.minHitRatio;
+ }
+
+ public void setMinHitRatio(double minHitRatio) {
+ this.minHitRatio = minHitRatio;
+ }
+
+ public long getMaxEventQueueSize() {
+ return this.maxEventQueueSize;
+ }
+
+ public void setMaxEventQueueSize(long maxEventQueueSize) {
+ this.maxEventQueueSize = maxEventQueueSize;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthEvaluator.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthEvaluator.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthEvaluator.java
new file mode 100644
index 0000000..9f105d9
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheHealthEvaluator.java
@@ -0,0 +1,323 @@
+/*
+ * 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.List;
+
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.CancelException;
+import org.apache.geode.internal.admin.api.CacheHealthConfig;
+import org.apache.geode.internal.admin.api.GemFireHealthConfig;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.distributed.internal.DM;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.internal.OSProcess;
+import org.apache.geode.internal.cache.CacheLifecycleListener;
+import org.apache.geode.internal.cache.CachePerfStats;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.internal.i18n.LocalizedStrings;
+import org.apache.geode.internal.logging.LogService;
+
+/**
+ * Contains the logic for evaluating the health of a GemFire
+ * <code>Cache</code> instance according to the thresholds provided in
+ * a {@link CacheHealthConfig}.
+ *
+ *
+ * @since GemFire 3.5
+ */
+class CacheHealthEvaluator extends AbstractHealthEvaluator
+ implements CacheLifecycleListener {
+
+ private static final Logger logger = LogService.getLogger();
+
+ /** The config from which we get the evaulation criteria */
+ private CacheHealthConfig config;
+
+ /** The description of the cache being evaluated */
+ private String description;
+
+ /** Statistics about the <code>Cache</code> instance. If no cache
+ * has been created in this VM, this field will be <code>null</code>
+ */
+ private CachePerfStats cacheStats;
+
+ /** The previous value of the netsearchTime stat (in nanoseconds) */
+ private long prevNetsearchTime;
+
+ /** The previous value of the netsearchedCompleted stat */
+ private long prevNetsearchesCompleted;
+
+ /** The previous value of the loadTime stat (in nanoseconds) */
+ private long prevLoadTime;
+
+ /** The previous value of the loadedCompleted stat */
+ private long prevLoadsCompleted;
+
+ /** The previous value of the gets stat */
+ private long prevGets;
+
+ ////////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>CacheHealthEvaluator</code>
+ */
+ CacheHealthEvaluator(GemFireHealthConfig config,
+ DM dm) {
+ super(config, dm);
+
+ this.config = config;
+ InternalDistributedSystem system = dm.getSystem();
+ GemFireCacheImpl cache;
+ try {
+ cache = (GemFireCacheImpl) CacheFactory.getInstance(system);
+
+ } catch (CancelException ex) {
+ // No cache in this VM
+ cache = null;
+ }
+
+ initialize(cache, dm);
+ GemFireCacheImpl.addCacheLifecycleListener(this);
+ }
+
+ //////////////////// Instance Methods ////////////////////
+
+ @Override
+ protected String getDescription() {
+ return this.description;
+ }
+
+ /**
+ * Initializes the state of this evaluator based on the given cache
+ * instance.
+ */
+ private void initialize(GemFireCacheImpl cache, DM dm) {
+ StringBuffer sb = new StringBuffer();
+ if (cache != null) {
+ this.cacheStats = cache.getCachePerfStats();
+
+ sb.append("Cache \"");
+ sb.append(cache.getName());
+ sb.append("\"");
+
+ } else {
+ sb.append("No Cache");
+ }
+
+ sb.append(" in member ");
+ sb.append(dm.getId());
+ int pid = OSProcess.getId();
+ if (pid != 0) {
+ sb.append(" with pid ");
+ sb.append(pid);
+ }
+ this.description = sb.toString();
+ }
+
+ public void cacheCreated(GemFireCacheImpl cache) {
+ InternalDistributedSystem system =
+ (InternalDistributedSystem) cache.getDistributedSystem();
+ DM dm = system.getDistributionManager();
+ initialize(cache, dm);
+ }
+
+ /**
+ * Checks to make sure that the average <code>netSearch</code> time
+ * during the previous health check interval is less than the
+ * {@linkplain CacheHealthConfig#getMaxNetSearchTime threshold}. If
+ * not, the status is "okay" health.
+ *
+ * @see CachePerfStats#getNetsearchTime
+ * @see CachePerfStats#getNetsearchesCompleted
+ */
+ void checkNetSearchTime(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ long deltaNetsearchTime =
+ this.cacheStats.getNetsearchTime() - this.prevNetsearchTime;
+ long deltaNetsearchesCompleted =
+ this.cacheStats.getNetsearchesCompleted() -
+ this.prevNetsearchesCompleted;
+
+ if (deltaNetsearchesCompleted != 0) {
+ long ratio = deltaNetsearchTime / deltaNetsearchesCompleted;
+ ratio /= 1000000;
+ long threshold = this.config.getMaxNetSearchTime();
+
+ if (ratio > threshold) {
+ String s = LocalizedStrings.CacheHealthEvaluator_THE_AVERAGE_DURATION_OF_A_CACHE_NETSEARCH_0_MS_EXCEEDS_THE_THRESHOLD_1_MS.toLocalizedString(new Object[] { ratio, threshold });
+ status.add(okayHealth(s));
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure that the average <code>load</code> time
+ * during the previous health check interval is less than the
+ * {@linkplain CacheHealthConfig#getMaxLoadTime threshold}. If
+ * not, the status is "okay" health.
+ *
+ * @see CachePerfStats#getLoadTime
+ * @see CachePerfStats#getLoadsCompleted
+ */
+ void checkLoadTime(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ if (!isFirstEvaluation()) {
+ long deltaLoadTime =
+ this.cacheStats.getLoadTime() - this.prevLoadTime;
+ long deltaLoadsCompleted =
+ this.cacheStats.getLoadsCompleted() -
+ this.prevLoadsCompleted;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Completed {} loads in {} ms", deltaLoadsCompleted, (deltaLoadTime / 1000000));
+ }
+
+ if (deltaLoadsCompleted != 0) {
+ long ratio = deltaLoadTime / deltaLoadsCompleted;
+ ratio /= 1000000;
+ long threshold = this.config.getMaxLoadTime();
+
+ if (ratio > threshold) {
+ String s = LocalizedStrings.CacheHealthEvaluator_THE_AVERAGE_DURATION_OF_A_CACHE_LOAD_0_MS_EXCEEDS_THE_THRESHOLD_1_MS.toLocalizedString(new Object[] { ratio, threshold });
+ if (logger.isDebugEnabled()) {
+ logger.debug(s);
+ }
+ status.add(okayHealth(s));
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure that the cache hit ratio during the previous
+ * health check interval is less than the {@linkplain
+ * CacheHealthConfig#getMinHitRatio threshold}. If not, the status
+ * is "okay" health.
+ *
+ * <P>
+ *
+ * The following formula is used to compute the hit ratio:
+ *
+ * <PRE>
+ * hitRatio = (gets - (loadsCompleted + netsearchesCompleted)) / (gets)
+ * </PRE>
+ *
+ *
+ * @see CachePerfStats#getGets
+ * @see CachePerfStats#getLoadsCompleted
+ * @see CachePerfStats#getNetsearchesCompleted
+ */
+ void checkHitRatio(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ long deltaGets = this.cacheStats.getGets() - this.prevGets;
+ if (deltaGets != 0) {
+ long deltaLoadsCompleted =
+ this.cacheStats.getLoadsCompleted() - this.prevLoadsCompleted;
+ long deltaNetsearchesCompleted =
+ this.cacheStats.getNetsearchesCompleted() -
+ this.prevNetsearchesCompleted;
+
+ double hits =
+ (deltaGets -
+ (deltaLoadsCompleted + deltaNetsearchesCompleted));
+ double hitRatio = hits / deltaGets;
+ double threshold = this.config.getMinHitRatio();
+ if (hitRatio < threshold) {
+ String s = "The hit ratio of this Cache (" + hitRatio +
+ ") is below the threshold (" + threshold + ")";
+ status.add(okayHealth(s));
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure that the {@linkplain
+ * CachePerfStats#getEventQueueSize cache event queue size} does
+ * not exceed the {@linkplain CacheHealthConfig#getMaxEventQueueSize
+ * threshold}. If it does, the status is "okay" health.
+ */
+ void checkEventQueueSize(List status) {
+ if (this.cacheStats == null || isFirstEvaluation() ||
+ this.cacheStats.isClosed()) {
+ return;
+ }
+
+ long eventQueueSize = this.cacheStats.getEventQueueSize();
+ long threshold = this.config.getMaxEventQueueSize();
+ if (eventQueueSize > threshold) {
+ String s = LocalizedStrings.CacheHealthEvaluator_THE_SIZE_OF_THE_CACHE_EVENT_QUEUE_0_MS_EXCEEDS_THE_THRESHOLD_1_MS.toLocalizedString(new Object[] { Long.valueOf(eventQueueSize), Long.valueOf(threshold) });
+ status.add(okayHealth(s));
+ }
+ }
+
+
+ /**
+ * Updates the previous values of statistics
+ */
+ private void updatePrevious() {
+ if (this.cacheStats != null && !this.cacheStats.isClosed()) {
+ this.prevLoadTime = this.cacheStats.getLoadTime();
+ this.prevLoadsCompleted = this.cacheStats.getLoadsCompleted();
+ this.prevNetsearchTime = this.cacheStats.getNetsearchTime();
+ this.prevNetsearchesCompleted =
+ this.cacheStats.getNetsearchesCompleted();
+ this.prevGets = this.cacheStats.getGets();
+
+ } else {
+ this.prevLoadTime = 0L;
+ this.prevLoadsCompleted = 0L;
+ this.prevNetsearchTime = 0L;
+ this.prevNetsearchesCompleted = 0L;
+ this.prevGets = 0L;
+ }
+ }
+
+ @Override
+ protected void check(List status) {
+
+ checkNetSearchTime(status);
+ checkLoadTime(status);
+ checkHitRatio(status);
+ checkEventQueueSize(status);
+
+ updatePrevious();
+ }
+
+ @Override
+ public void close() {
+ GemFireCacheImpl.removeCacheLifecycleListener(this);
+ }
+
+ @Override
+ public void cacheClosed(GemFireCacheImpl cache) {
+ // do nothing
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerConfigImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerConfigImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerConfigImpl.java
new file mode 100644
index 0000000..7e4ef15
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerConfigImpl.java
@@ -0,0 +1,136 @@
+/*
+ * 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.CacheServerConfig;
+import org.apache.geode.internal.admin.api.CacheVmConfig;
+import org.apache.geode.internal.admin.GemFireVM;
+
+import static org.apache.geode.distributed.ConfigurationProperties.*;
+
+/**
+ * An implementation of <code>CacheVmConfig</code>
+ *
+ * @since GemFire 4.0
+ */
+public class CacheServerConfigImpl extends ManagedEntityConfigImpl
+ implements CacheVmConfig, CacheServerConfig {
+
+ /** Declarative caching XML file that is used to initialize the
+ * Cache in the cache server. */
+ private String cacheXMLFile;
+
+ /** Extra classpath for the cache server */
+ private String classpath;
+
+ /////////////////////// Constructors ///////////////////////
+
+ /**
+ * Creates a new <code>CacheServerConfigImpl</code> with the default
+ * configuration settings.
+ */
+ public CacheServerConfigImpl() {
+ this.cacheXMLFile = null;
+ this.classpath = null;
+ }
+
+ /**
+ * Creates a new <code>CacheServerConfigImpl</code> for a running
+ * cache server.
+ */
+ public CacheServerConfigImpl(GemFireVM vm) {
+ super(vm);
+
+ String name = CACHE_XML_FILE;
+ 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/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerImpl.java
new file mode 100644
index 0000000..8046406
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/CacheServerImpl.java
@@ -0,0 +1,205 @@
+/*
+ * 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.DM;
+import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.internal.admin.GemFireVM;
+import org.apache.geode.internal.admin.api.AdminException;
+import org.apache.geode.internal.admin.api.CacheServer;
+import org.apache.geode.internal.admin.api.CacheServerConfig;
+import org.apache.geode.internal.admin.api.CacheVm;
+import org.apache.geode.internal.admin.api.CacheVmConfig;
+import org.apache.geode.internal.admin.api.ManagedEntityConfig;
+import org.apache.geode.internal.admin.api.SystemMemberType;
+import org.apache.geode.internal.admin.remote.RemoteApplicationVM;
+
+import static org.apache.geode.distributed.ConfigurationProperties.*;
+
+/**
+ * Implements the administrative interface to a cache server.
+ *
+ * @since GemFire 3.5
+ */
+public class CacheServerImpl extends ManagedSystemMemberImpl
+ implements CacheVm, CacheServer {
+
+ /** How many new <code>CacheServer</code>s have been created? */
+ private static int newCacheServers = 0;
+
+ /////////////////////// Instance Fields ///////////////////////
+
+ /** The configuration object for this cache server */
+ private final CacheServerConfigImpl config;
+
+ ///////////////////////// Constructors ////////////////////////
+
+ /**
+ * Creates a new <code>CacheServerImpl</code> that represents a
+ * non-existsing (unstarted) cache server in a given distributed
+ * system.
+ */
+ public CacheServerImpl(AdminDistributedSystemImpl system,
+ CacheVmConfig config)
+ throws AdminException {
+
+ super(system, config);
+
+ this.config = (CacheServerConfigImpl) config;
+ this.config.setManagedEntity(this);
+ }
+
+ /**
+ * Creates a new <code>CacheServerImpl</code> that represents an
+ * existing dedicated cache server in a given distributed system.
+ */
+ public CacheServerImpl(AdminDistributedSystemImpl system,
+ GemFireVM vm)
+ throws AdminException {
+
+ super(system, vm);
+ this.config = new CacheServerConfigImpl(vm);
+ }
+
+ ////////////////////// Instance Methods //////////////////////
+
+ @Override
+ public SystemMemberType getType() {
+ return SystemMemberType.CACHE_VM;
+ }
+
+ public String getNewId() {
+ synchronized (CacheServerImpl.class) {
+ return "CacheVm" + (++newCacheServers);
+ }
+ }
+
+ public void start() throws AdminException {
+ if (!needToStart()) {
+ return;
+ }
+
+ this.config.validate();
+ this.controller.start(this);
+ this.config.setManagedEntity(this);
+ }
+
+ public void stop() {
+ if (!needToStop()) {
+ return;
+ }
+
+ this.controller.stop(this);
+ // NOTE: DistributedSystem nodeLeft will then set this.manager to null
+ this.config.setManagedEntity(null);
+ }
+
+ public boolean isRunning() {
+ DM dm = ((AdminDistributedSystemImpl)getDistributedSystem()).getDistributionManager();
+ if(dm == null) {
+ try {
+ return this.controller.isRunning(this);
+ }
+ catch (IllegalStateException e) {
+ return false;
+ }
+ }
+ return ((DistributionManager)dm).getDistributionManagerIdsIncludingAdmin().contains(getDistributedMember());
+ }
+
+ public CacheServerConfig getConfig() {
+ return this.config;
+ }
+
+ public CacheVmConfig getVmConfig() {
+ return this.config;
+ }
+
+ //////////////////////// Command execution ////////////////////////
+
+ public ManagedEntityConfig getEntityConfig() {
+ return this.getConfig();
+ }
+
+ public String getEntityType() {
+ // Fix bug 32564
+ return "Cache Vm";
+ }
+
+ public String getStartCommand() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(this.controller.getProductExecutable(this, "cacheserver"));
+ sb.append(" start -dir=");
+ sb.append(this.getConfig().getWorkingDirectory());
+
+ String file = this.getConfig().getCacheXMLFile();
+ if (file != null && file.length() > 0) {
+ sb.append(" ");
+ sb.append(CACHE_XML_FILE);
+ 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 GemFire 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/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterImpl.java
new file mode 100755
index 0000000..fe61760
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterImpl.java
@@ -0,0 +1,280 @@
+/*
+ * 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.ConfigurationParameter;
+import org.apache.geode.internal.admin.api.UnmodifiableConfigurationException;
+import org.apache.geode.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.
+ *
+ * @since GemFire 3.5
+ *
+ */
+public class ConfigurationParameterImpl
+implements ConfigurationParameter {
+
+ /** Identifying name of this configuration parameter */
+ protected String name;
+ /** Full description of this configuration parameter */
+ protected String description;
+ /** The current value */
+ protected Object value;
+ /** Class type of the value */
+ protected Class type;
+ /** True if this is modifiable; false if read-only */
+ protected boolean userModifiable;
+ /** List of listeners to notify when value changes */
+ private final List listeners = new ArrayList();
+
+ // -------------------------------------------------------------------------
+ // Constructor(s)
+ // -------------------------------------------------------------------------
+
+ /**
+ * Constructs new <code>ConfigurationParameterImpl</code>.
+ *
+ * @param name the name of this parameter which cannot change
+ * @param description full description to use
+ * @param value the value of this parameter
+ * @param type the class type of the value
+ * @param userModifiable true if this is modifiable; false if read-only
+ */
+ protected ConfigurationParameterImpl(String name,
+ String description,
+ Object value,
+ Class type,
+ boolean userModifiable) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_CONFIGURATIONPARAMETER_NAME_MUST_BE_SPECIFIED.toLocalizedString());
+ }
+
+ this.name = name;
+ setInternalState(description, value, type, userModifiable);
+ }
+
+ /**
+ * Constructs new <code>ConfigurationParameterImpl</code>.
+ *
+ * @param name the name of this parameter which cannot change
+ * @param value the value of this parameter
+ */
+ protected ConfigurationParameterImpl(String name,
+ Object value) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_CONFIGURATIONPARAMETER_NAME_MUST_BE_SPECIFIED.toLocalizedString());
+ }
+
+ this.name = name;
+ setInternalState(name, value, value.getClass(), true);
+ }
+
+ /** Constructor to allow serialization by subclass */
+ protected ConfigurationParameterImpl() {}
+
+ // -------------------------------------------------------------------------
+ // Attribute accessors and mutators
+ // -------------------------------------------------------------------------
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public Object getValue() {
+ return this.value;
+ }
+
+ public String getValueAsString() {
+ if (isString()) {
+ return (String) this.value;
+ }
+ else if (isInetAddress()) {
+ return InetAddressUtil.toString(this.value);
+ }
+ else if (isFile()) {
+ return this.value.toString();
+ }
+ else if (isOctal()) {
+ String strVal = Integer.toOctalString(((Integer) this.value).intValue());
+ if (!strVal.startsWith("0")) {
+ strVal = "0" + strVal;
+ }
+ return strVal;
+ }
+ else if (isArray()) {
+ List list = Arrays.asList((Object[]) this.value);
+ return list.toString();
+ }
+ else {
+ return this.value.toString();
+ }
+ }
+
+ public Class getValueType() {
+ return this.type;
+ }
+
+ public boolean isModifiable() {
+ return this.userModifiable;
+ }
+
+ public boolean isArray() {
+ return "manager-parameters".equals(this.name) ||
+ "manager-classpaths".equals(this.name);
+ }
+ public boolean isInetAddress() {
+ return java.net.InetAddress.class.isAssignableFrom(this.type);
+ }
+ public boolean isFile() {
+ return java.io.File.class.equals(this.type);
+ }
+ public boolean isOctal() {
+ return "shared-memory-permissions".equals(this.name);
+ }
+ public boolean isString() {
+ return java.lang.String.class.equals(this.type);
+ }
+
+ public void setValue(Object value) throws UnmodifiableConfigurationException {
+ if (!isModifiable()) {
+ throw new UnmodifiableConfigurationException(LocalizedStrings.ConfigurationParameterImpl_0_IS_NOT_A_MODIFIABLE_CONFIGURATION_PARAMETER.toLocalizedString(getName()));
+ }
+ if (value == null) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_0_TO_NULL_VALUE.toLocalizedString(getName()));
+ }
+ if (!getValueType().equals(value.getClass())) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_TYPE_0_WITH_TYPE_1.toLocalizedString(new Object[] {getValueType().getName(), value.getClass().getName()}));
+ }
+
+ if (value instanceof String && !isString()) {
+ // we need to check what the type should be and convert to it...
+ setValueFromString((String) value);
+ }
+ else {
+ this.value = value;
+ }
+ fireConfigurationParameterValueChanged(this);
+ }
+
+ // -------------------------------------------------------------------------
+ // Operations for handling the registration of listeners
+ // Note: this is only for use within impl pkg and subclass pkgs
+ // -------------------------------------------------------------------------
+
+ /** Adds the listener for any changes to this configuration parameter. */
+ public void addConfigurationParameterListener(ConfigurationParameterListener listener) {
+ if (!this.listeners.contains(listener)) {
+ this.listeners.add(listener);
+ }
+ }
+
+ /** Removes the listener if it's currently registered. */
+ public void removeConfigurationParameterListener(ConfigurationParameterListener listener) {
+ if (this.listeners.contains(listener)) {
+ this.listeners.remove(listener);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation methods
+ // -------------------------------------------------------------------------
+
+ protected void setValueFromString(String newValue) {
+ if (newValue == null) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_0_TO_NULL_VALUE.toLocalizedString(getName()));
+ }
+
+ if (isInetAddress()) {
+ this.value = InetAddressUtil.toInetAddress(newValue);
+ }
+ else if (isFile()) {
+ this.value = new File(newValue);
+ }
+ else if (isOctal()) {
+ if (!newValue.startsWith("0")) {
+ newValue = "0" + newValue;
+ }
+ this.value = Integer.valueOf(Integer.parseInt(newValue, 8));
+ }
+ else if (isArray()) {
+ // parse it TODO
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_SETTING_ARRAY_VALUE_FROM_DELIMITED_STRING_IS_NOT_SUPPORTED.toLocalizedString());
+ }
+ else {
+ this.value = newValue;
+ }
+ }
+
+ /**
+ * Fires changed configuration parameter to registered listeners.
+ *
+ * @param parm the configuration parameter the changed
+ */
+ protected void fireConfigurationParameterValueChanged(ConfigurationParameter parm) {
+ ConfigurationParameterListener[] listeners =
+ (ConfigurationParameterListener[]) this.listeners.toArray(
+ new ConfigurationParameterListener[0]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].configurationParameterValueChanged(parm);
+ }
+ }
+
+ /**
+ * Sets the internal state of this configuration parameter.
+ *
+ * @param description full description to use
+ * @param value the value of this parameter
+ * @param type the class type of the value
+ * @param userModifiable true if this is modifiable; false if read-only
+ */
+ protected void setInternalState(String description,
+ Object value,
+ Class type,
+ boolean userModifiable) {
+ if (description == null || description.length() == 0) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_CONFIGURATIONPARAMETER_DESCRIPTION_MUST_BE_SPECIFIED.toLocalizedString());
+ }
+ this.description = description;
+ this.type = type;
+ this.userModifiable = userModifiable;
+
+ if (value == null) {
+ throw new IllegalArgumentException(LocalizedStrings.ConfigurationParameterImpl_UNABLE_TO_SET_0_TO_NULL_VALUE.toLocalizedString(getName()));
+ }
+
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterListener.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterListener.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterListener.java
new file mode 100755
index 0000000..7508da9
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ConfigurationParameterListener.java
@@ -0,0 +1,34 @@
+/*
+ * 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.ConfigurationParameter;
+
+/**
+ * Listens to value changes of a
+ * {@link ConfigurationParameter}. This is for
+ * internal use only to allow a {@link SystemMemberImpl} to keep track of
+ * configuration changes made through
+ * {@link ConfigurationParameterImpl#setValue}.
+ *
+ * @since GemFire 3.5
+ *
+ */
+public interface ConfigurationParameterListener {
+ public void configurationParameterValueChanged(ConfigurationParameter parm);
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DisabledManagedEntityController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DisabledManagedEntityController.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DisabledManagedEntityController.java
new file mode 100755
index 0000000..f9044a3
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/DisabledManagedEntityController.java
@@ -0,0 +1,91 @@
+/*
+ * 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.logging.log4j.Logger;
+
+import org.apache.geode.internal.admin.api.DistributedSystemConfig;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.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.
+ *
+ */
+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);
+ }
+}