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);
+  }
+}