You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2019/12/18 16:38:47 UTC

[lucene-solr] 09/36: Refactoring + updates.

This is an automated email from the ASF dual-hosted git repository.

ab pushed a commit to branch jira/solr-13579
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git

commit 6f2ccb27589745c3702b2f96ebb8466a109c5f43
Author: Andrzej Bialecki <ab...@apache.org>
AuthorDate: Thu Jul 4 14:27:40 2019 +0200

    Refactoring + updates.
---
 .../managed/AbstractResourceManagerPlugin.java     | 16 +++++++
 .../solr/managed/DefaultResourceManager.java       | 18 +++++++
 .../DefaultResourceManagerPluginFactory.java       | 18 ++++++-
 .../apache/solr/managed/ManagedMetricProducer.java | 20 +++++++-
 .../org/apache/solr/managed/ManagedResource.java   | 37 +++++++++++----
 .../org/apache/solr/managed/ResourceManager.java   | 55 ++++++++++++++++++++--
 .../apache/solr/managed/ResourceManagerPlugin.java | 32 ++++++++++++-
 .../solr/managed/ResourceManagerPluginFactory.java | 23 ++++++++-
 .../apache/solr/managed/ResourceManagerPool.java   | 28 ++++++++---
 .../java/org/apache/solr/managed/package-info.java | 21 +++++++++
 .../solr/managed/plugins/CacheManagerPlugin.java   | 35 ++++++++++----
 .../apache/solr/managed/plugins/package-info.java  | 21 +++++++++
 12 files changed, 288 insertions(+), 36 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/managed/AbstractResourceManagerPlugin.java b/solr/core/src/java/org/apache/solr/managed/AbstractResourceManagerPlugin.java
index f75d104..1e630b1 100644
--- a/solr/core/src/java/org/apache/solr/managed/AbstractResourceManagerPlugin.java
+++ b/solr/core/src/java/org/apache/solr/managed/AbstractResourceManagerPlugin.java
@@ -1,3 +1,19 @@
+/*
+ * 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.solr.managed;
 
 /**
diff --git a/solr/core/src/java/org/apache/solr/managed/DefaultResourceManager.java b/solr/core/src/java/org/apache/solr/managed/DefaultResourceManager.java
index 3f51897..e6005c8 100644
--- a/solr/core/src/java/org/apache/solr/managed/DefaultResourceManager.java
+++ b/solr/core/src/java/org/apache/solr/managed/DefaultResourceManager.java
@@ -1,3 +1,19 @@
+/*
+ * 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.solr.managed;
 
 import java.io.IOException;
@@ -19,6 +35,8 @@ import org.slf4j.LoggerFactory;
 
 /**
  * Default implementation of {@link ResourceManager}.
+ * <p>Resource pools managed by this implementation are run periodically, each according to
+ * its schedule defined by {@link #SCHEDULE_DELAY_SECONDS_PARAM} parameter during the pool creation.</p>
  */
 public class DefaultResourceManager extends ResourceManager {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
diff --git a/solr/core/src/java/org/apache/solr/managed/DefaultResourceManagerPluginFactory.java b/solr/core/src/java/org/apache/solr/managed/DefaultResourceManagerPluginFactory.java
index 3967c87..ab6be81 100644
--- a/solr/core/src/java/org/apache/solr/managed/DefaultResourceManagerPluginFactory.java
+++ b/solr/core/src/java/org/apache/solr/managed/DefaultResourceManagerPluginFactory.java
@@ -1,3 +1,19 @@
+/*
+ * 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.solr.managed;
 
 import java.util.HashMap;
@@ -7,7 +23,7 @@ import org.apache.solr.core.SolrResourceLoader;
 import org.apache.solr.managed.plugins.CacheManagerPlugin;
 
 /**
- *
+ * Default implementation of {@link ResourceManagerPluginFactory}.
  */
 public class DefaultResourceManagerPluginFactory implements ResourceManagerPluginFactory {
 
diff --git a/solr/core/src/java/org/apache/solr/managed/ManagedMetricProducer.java b/solr/core/src/java/org/apache/solr/managed/ManagedMetricProducer.java
index 9f48702..7885d0f 100644
--- a/solr/core/src/java/org/apache/solr/managed/ManagedMetricProducer.java
+++ b/solr/core/src/java/org/apache/solr/managed/ManagedMetricProducer.java
@@ -1,3 +1,19 @@
+/*
+ * 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.solr.managed;
 
 import java.util.Collection;
@@ -8,12 +24,12 @@ import java.util.Map;
 import org.apache.solr.core.SolrInfoBean;
 
 /**
- *
+ * Convenience interface for {@link SolrInfoBean}-s that need to be managed.
  */
 public interface ManagedMetricProducer extends SolrInfoBean, ManagedResource {
 
   @Override
-  default Map<String, Float> getManagedValues(Collection<String> tags) {
+  default Map<String, Float> getMonitoredValues(Collection<String> tags) {
     Map<String, Object> metrics = getMetricsSnapshot();
     if (metrics == null) {
       return Collections.emptyMap();
diff --git a/solr/core/src/java/org/apache/solr/managed/ManagedResource.java b/solr/core/src/java/org/apache/solr/managed/ManagedResource.java
index 1351a76..0f18028 100644
--- a/solr/core/src/java/org/apache/solr/managed/ManagedResource.java
+++ b/solr/core/src/java/org/apache/solr/managed/ManagedResource.java
@@ -1,3 +1,19 @@
+/*
+ * 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.solr.managed;
 
 import java.lang.invoke.MethodHandles;
@@ -8,7 +24,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- *
+ * A managed resource.
  */
 public interface ManagedResource {
   Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -19,13 +35,13 @@ public interface ManagedResource {
   String getResourceName();
 
   /**
-   * Returns types of management schemes supported by this resource. This always
-   * returns a non-null collection with at least one entry.
+   * Returns types of management plugins supported by this resource. This must always
+   * return a non-null collection with at least one entry.
    */
   Collection<String> getManagedResourceTypes();
 
   /**
-   * Set current managed limits.
+   * Set values of managed limits.
    * @param limits map of limit names and values
    */
   default void setManagedLimits(Map<String, Float> limits) {
@@ -43,21 +59,22 @@ public interface ManagedResource {
   }
 
   /**
-   * Set a managed limit.
+   * Set value of a managed limit.
    * @param key limit name
    * @param value limit value
    */
   void setManagedLimit(String key, float value) throws Exception;
 
   /**
-   * Returns current managed limits.
+   * Returns current values of managed limits.
+   * @return map where keys are controlled tags and values are current limits
    */
   Map<String, Float> getManagedLimits();
 
   /**
-   * Returns monitored values that are used for calculating optimal setting of managed limits.
-   * @param tags value names
-   * @return map of names to current values.
+   * Returns monitored values that are used for calculating optimal settings of managed limits.
+   * @param tags monitored tags
+   * @return map of tags to current values.
    */
-  Map<String, Float> getManagedValues(Collection<String> tags) throws Exception;
+  Map<String, Float> getMonitoredValues(Collection<String> tags) throws Exception;
 }
diff --git a/solr/core/src/java/org/apache/solr/managed/ResourceManager.java b/solr/core/src/java/org/apache/solr/managed/ResourceManager.java
index a49f5d7..867e3f9 100644
--- a/solr/core/src/java/org/apache/solr/managed/ResourceManager.java
+++ b/solr/core/src/java/org/apache/solr/managed/ResourceManager.java
@@ -1,3 +1,19 @@
+/*
+ * 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.solr.managed;
 
 import java.lang.invoke.MethodHandles;
@@ -17,9 +33,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Base class for resource management. It represents a flat model where there are named
- * resource pools of a given type, each pool with its own defined limits. Resources can be added
- * to a pool for management of a specific aspect of that resource using {@link ResourceManagerPlugin}.
+ * Base class for a resource managemer. It uses a flat model where there are named
+ * resource pools of a given type, each pool with its own defined resource limits. Resources can be added
+ * to a pool for the management of a specific aspect of that resource using {@link ResourceManagerPlugin}.
  */
 public abstract class ResourceManager implements SolrCloseable, PluginInfoInitialized {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -65,19 +81,48 @@ public abstract class ResourceManager implements SolrCloseable, PluginInfoInitia
 
   protected abstract void doInit() throws Exception;
 
+  /**
+   * Create a named resource management pool.
+   * @param name pool name
+   * @param type pool type (one of the supported {@link ResourceManagerPlugin} types)
+   * @param poolLimits pool limits
+   * @param params other parameters. These are also used for creating a {@link ResourceManagerPlugin}
+   */
   public abstract void createPool(String name, String type, Map<String, Float> poolLimits, Map<String, Object> params) throws Exception;
 
+  /**
+   * Modify pool limits.
+   * @param name existing pool name
+   * @param poolLimits new pool limits
+   */
   public abstract void modifyPoolLimits(String name, Map<String, Float> poolLimits) throws Exception;
 
+  /**
+   * Remove pool. This also stops the management of resources registered with that pool.
+   * @param name existing pool name
+   */
   public abstract void removePool(String name) throws Exception;
 
-  public void addResources(String pool, Collection<ManagedResource> managedResource) throws Exception {
+  /**
+   * Add managed resources to a pool.
+   * @param pool existing pool name.
+   * @param managedResources resources to add
+   */
+  public void addResources(String pool, Collection<ManagedResource> managedResources) throws Exception {
     ensureNotClosed();
-    for (ManagedResource resource : managedResource) {
+    for (ManagedResource resource : managedResources) {
       addResource(pool, resource);
     }
   }
 
+  /**
+   * Add a managed resource to a pool.
+   * @param pool existing pool name.
+   * @param managedResource managed resource. The resource must support the management type
+   *                        (in its {@link ManagedResource#getManagedResourceTypes()}) used
+   *                        in the selected pool. The resource must not be already managed by
+   *                        another pool of the same type.
+   */
   public abstract void addResource(String pool, ManagedResource managedResource) throws Exception;
 
   protected void ensureNotClosed() {
diff --git a/solr/core/src/java/org/apache/solr/managed/ResourceManagerPlugin.java b/solr/core/src/java/org/apache/solr/managed/ResourceManagerPlugin.java
index 0b00198..feb35a1 100644
--- a/solr/core/src/java/org/apache/solr/managed/ResourceManagerPlugin.java
+++ b/solr/core/src/java/org/apache/solr/managed/ResourceManagerPlugin.java
@@ -1,20 +1,50 @@
+/*
+ * 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.solr.managed;
 
 import java.util.Collection;
 import java.util.Map;
 
 /**
- *
+ * A plugin that implements an algorithm for managing a pool of resources of a given type.
  */
 public interface ResourceManagerPlugin {
 
+  /** Plugin type. */
   String getType();
 
   void init(Map<String, Object> params);
 
+  /**
+   * Name of monitored parameters that {@link ManagedResource}-s managed by this plugin
+   * are expected to support.
+   */
   Collection<String> getMonitoredTags();
+  /**
+   * Name of controlled parameters that {@link ManagedResource}-s managed by this plugin
+   * are expected to support.
+   */
   Collection<String> getControlledTags();
 
+  /**
+   * Manage resources in a pool. This method is called periodically by {@link ResourceManager},
+   * according to a schedule defined by the pool.
+   * @param pool pool instance.
+   */
   void manage(ResourceManagerPool pool) throws Exception;
 
 }
diff --git a/solr/core/src/java/org/apache/solr/managed/ResourceManagerPluginFactory.java b/solr/core/src/java/org/apache/solr/managed/ResourceManagerPluginFactory.java
index b4e1a54..6c8578a 100644
--- a/solr/core/src/java/org/apache/solr/managed/ResourceManagerPluginFactory.java
+++ b/solr/core/src/java/org/apache/solr/managed/ResourceManagerPluginFactory.java
@@ -1,11 +1,32 @@
+/*
+ * 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.solr.managed;
 
 import java.util.Map;
 
 /**
- *
+ * Factory for creating instances of {@link ResourceManagerPlugin}-s.
  */
 public interface ResourceManagerPluginFactory {
 
+  /**
+   * Create a plugin of a given type.
+   * @param type plugin type
+   * @param params plugin parameters
+   */
   ResourceManagerPlugin create(String type, Map<String, Object> params) throws Exception;
 }
diff --git a/solr/core/src/java/org/apache/solr/managed/ResourceManagerPool.java b/solr/core/src/java/org/apache/solr/managed/ResourceManagerPool.java
index a1c437a..bfb1b8c 100644
--- a/solr/core/src/java/org/apache/solr/managed/ResourceManagerPool.java
+++ b/solr/core/src/java/org/apache/solr/managed/ResourceManagerPool.java
@@ -1,3 +1,19 @@
+/*
+ * 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.solr.managed;
 
 import java.io.Closeable;
@@ -16,8 +32,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * A pool of resources of the same type, which use the same {@link ResourceManagerPlugin} for managing their
- * resource use.
+ * This class manages a pool of resources of the same type, which use the same
+ * {@link ResourceManagerPlugin} for managing their resource limits.
  */
 public class ResourceManagerPool implements Runnable, Closeable {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -75,7 +91,7 @@ public class ResourceManagerPool implements Runnable, Closeable {
   }
 
   /**
-   * Get the current values from all resources. Result is a map with resource names as keys,
+   * Get the current monitored values from all resources. Result is a map with resource names as keys,
    * and tag/value maps as values.
    */
   public Map<String, Map<String, Float>> getCurrentValues() throws InterruptedException {
@@ -85,7 +101,7 @@ public class ResourceManagerPool implements Runnable, Closeable {
       Map<String, Map<String, Float>> currentValues = new HashMap<>();
       for (ManagedResource resource : resources.values()) {
         try {
-          currentValues.put(resource.getResourceName(), resource.getManagedValues(resourceManagerPlugin.getMonitoredTags()));
+          currentValues.put(resource.getResourceName(), resource.getMonitoredValues(resourceManagerPlugin.getMonitoredTags()));
         } catch (Exception e) {
           log.warn("Error getting managed values from " + resource.getResourceName(), e);
         }
@@ -108,8 +124,8 @@ public class ResourceManagerPool implements Runnable, Closeable {
   }
 
   /**
-   * This returns cumulative values of all resources. NOTE:
-   * you must call {@link #getCurrentValues()} first!
+   * This returns cumulative monitored values of all resources.
+   * <p>NOTE: you must call {@link #getCurrentValues()} first!</p>
    */
   public Map<String, Float> getTotalValues() throws InterruptedException {
     updateLock.lockInterruptibly();
diff --git a/solr/core/src/java/org/apache/solr/managed/package-info.java b/solr/core/src/java/org/apache/solr/managed/package-info.java
new file mode 100644
index 0000000..fd6bf00
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/managed/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * API and implementation of a resource manager.
+ */
+package org.apache.solr.managed;
diff --git a/solr/core/src/java/org/apache/solr/managed/plugins/CacheManagerPlugin.java b/solr/core/src/java/org/apache/solr/managed/plugins/CacheManagerPlugin.java
index 345dae4..8783334 100644
--- a/solr/core/src/java/org/apache/solr/managed/plugins/CacheManagerPlugin.java
+++ b/solr/core/src/java/org/apache/solr/managed/plugins/CacheManagerPlugin.java
@@ -12,7 +12,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- *
+ * An implementation of {@link org.apache.solr.managed.ResourceManagerPlugin} specific to
+ * the management of {@link org.apache.solr.search.SolrCache} instances.
+ * <p>This plugin calculates the total size and maxRamMB of all registered cache instances
+ * and adjusts each cache's limits so that the aggregated values again fit within the pool limits.</p>
+ * <p>In order to avoid thrashing the plugin uses a dead zone (by default {@link #DEFAULT_DEAD_ZONE}),
+ * which can be adjusted using configuration parameter {@link #DEAD_ZONE}. If monitored values don't
+ * exceed the limits +/- the dead zone no action is taken.</p>
  */
 public class CacheManagerPlugin extends AbstractResourceManagerPlugin {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@@ -24,6 +30,9 @@ public class CacheManagerPlugin extends AbstractResourceManagerPlugin {
   public static final String RAM_BYTES_USED_TAG = "ramBytesUsed";
   public static final String MAX_RAM_MB_TAG = "maxRamMB";
 
+  public static final String DEAD_ZONE = "deadZone";
+  public static final float DEFAULT_DEAD_ZONE = 0.1f;
+
   private static final Map<String, String> controlledToMonitored = new HashMap<>();
 
   static {
@@ -37,16 +46,18 @@ public class CacheManagerPlugin extends AbstractResourceManagerPlugin {
       RAM_BYTES_USED_TAG
   );
 
-  @Override
-  public Collection<String> getMonitoredTags() {
-    return MONITORED_TAGS;
-  }
-
   private static final Collection<String> CONTROLLED_TAGS = Arrays.asList(
       MAX_RAM_MB_TAG,
       SIZE_TAG
   );
 
+  private float deadZone = DEFAULT_DEAD_ZONE;
+
+  @Override
+  public Collection<String> getMonitoredTags() {
+    return MONITORED_TAGS;
+  }
+
   @Override
   public Collection<String> getControlledTags() {
     return CONTROLLED_TAGS;
@@ -59,7 +70,12 @@ public class CacheManagerPlugin extends AbstractResourceManagerPlugin {
 
   @Override
   public void init(Map<String, Object> params) {
-
+    String deadZoneStr = String.valueOf(params.getOrDefault(DEAD_ZONE, DEFAULT_DEAD_ZONE));
+    try {
+      deadZone = Float.parseFloat(deadZoneStr);
+    } catch (Exception e) {
+      log.warn("Invalid deadZone parameter value '" + deadZoneStr + "', using default " + DEFAULT_DEAD_ZONE);
+    }
   }
 
   @Override
@@ -81,9 +97,8 @@ public class CacheManagerPlugin extends AbstractResourceManagerPlugin {
       }
       float totalDelta = poolLimitValue - totalValue;
 
-      // 10% hysteresis to avoid thrashing
-      // TODO: make the threshold configurable
-      if (Math.abs(totalDelta / poolLimitValue) < 0.1f) {
+      // dead zone to avoid thrashing
+      if (Math.abs(totalDelta / poolLimitValue) < deadZone) {
         return;
       }
 
diff --git a/solr/core/src/java/org/apache/solr/managed/plugins/package-info.java b/solr/core/src/java/org/apache/solr/managed/plugins/package-info.java
new file mode 100644
index 0000000..5b4ff61
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/managed/plugins/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementations of {@link org.apache.solr.managed.ResourceManagerPlugin}.
+ */
+package org.apache.solr.managed.plugins;