From a4ff429ab0b770e9dd3bcc275257f0478b6a1b35 Mon Sep 17 00:00:00 2001 From: Andrzej Bialecki Date: Wed, 14 Aug 2019 15:58:39 +0200 Subject: [PATCH] SOLR-13693: Use strongly-typed setters for cache parameters. --- solr/CHANGES.txt | 2 +- .../org/apache/solr/search/FastLRUCache.java | 135 ++++++------------ .../java/org/apache/solr/search/LFUCache.java | 130 ++++++----------- .../java/org/apache/solr/search/LRUCache.java | 90 +++++------- .../org/apache/solr/search/SolrCache.java | 32 +++-- .../apache/solr/search/SolrCacheHolder.java | 18 ++- .../apache/solr/search/TestFastLRUCache.java | 8 +- .../org/apache/solr/search/TestLFUCache.java | 4 +- .../org/apache/solr/search/TestLRUCache.java | 8 +- 9 files changed, 172 insertions(+), 255 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 5e421e3e0c8..cff9eb2a118 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -117,7 +117,7 @@ Improvements * SOLR-12368: Support InPlace DV updates for a field that does not yet exist in any documents (hossman, Simon Willnauer, Adrien Grand, Munendra S N) -* SOLR-13558: Allow dynamic resizing of SolrCache-s. (ab) +* SOLR-13558, SOLR-13693: Allow dynamic resizing of SolrCache-s. (ab) * SOLR-6305: Ability to set the replication factor for index files created by HDFSDirectoryFactory (Boris Pasko via Kevin Risden) diff --git a/solr/core/src/java/org/apache/solr/search/FastLRUCache.java b/solr/core/src/java/org/apache/solr/search/FastLRUCache.java index 8f1972945d2..6c16783f433 100644 --- a/solr/core/src/java/org/apache/solr/search/FastLRUCache.java +++ b/solr/core/src/java/org/apache/solr/search/FastLRUCache.java @@ -27,7 +27,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.invoke.MethodHandles; -import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.List; import java.util.Map; @@ -69,7 +68,7 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, private int showItems = 0; private long maxRamBytes; - private int sizeLimit; + private int maxSize; private int minSizeLimit; private int initialSize; private int acceptableSize; @@ -84,10 +83,10 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, public Object init(Map args, Object persistence, CacheRegenerator regenerator) { super.init(args, regenerator); String str = (String) args.get(SIZE_PARAM); - sizeLimit = str == null ? 1024 : Integer.parseInt(str); + maxSize = str == null ? 1024 : Integer.parseInt(str); str = (String) args.get(MIN_SIZE_PARAM); if (str == null) { - minSizeLimit = (int) (sizeLimit * 0.9); + minSizeLimit = (int) (maxSize * 0.9); } else { minSizeLimit = Integer.parseInt(str); } @@ -95,7 +94,7 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, str = (String) args.get(ACCEPTABLE_SIZE_PARAM); if (str == null) { - acceptableSize = (int) (sizeLimit * 0.95); + acceptableSize = (int) (maxSize * 0.95); } else { acceptableSize = Integer.parseInt(str); } @@ -103,7 +102,7 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, acceptableSize = Math.max(minSizeLimit, acceptableSize); str = (String) args.get(INITIAL_SIZE_PARAM); - initialSize = str == null ? sizeLimit : Integer.parseInt(str); + initialSize = str == null ? maxSize : Integer.parseInt(str); str = (String) args.get(CLEANUP_THREAD_PARAM); cleanupThread = str == null ? false : Boolean.parseBoolean(str); @@ -119,8 +118,8 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, cache = new ConcurrentLRUCache<>(ramLowerWatermark, maxRamBytes, cleanupThread, null); } else { ramLowerWatermark = -1L; - description = generateDescription(sizeLimit, initialSize, minSizeLimit, acceptableSize, cleanupThread); - cache = new ConcurrentLRUCache<>(sizeLimit, minSizeLimit, acceptableSize, initialSize, cleanupThread, false, null); + description = generateDescription(maxSize, initialSize, minSizeLimit, acceptableSize, cleanupThread); + cache = new ConcurrentLRUCache<>(maxSize, minSizeLimit, acceptableSize, initialSize, cleanupThread, false, null); } cache.setAlive(false); @@ -143,7 +142,7 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, if (maxRamBytes != Long.MAX_VALUE) { return generateDescription(maxRamBytes, ramLowerWatermark, cleanupThread); } else { - return generateDescription(sizeLimit, initialSize, minSizeLimit, acceptableSize, cleanupThread); + return generateDescription(maxSize, initialSize, minSizeLimit, acceptableSize, cleanupThread); } } @@ -273,15 +272,15 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, cevictions += statistiscs.getCumulativeEvictions(); } - map.put("lookups", lookups); - map.put("hits", hits); - map.put("hitratio", calcHitRatio(lookups, hits)); - map.put("inserts", inserts); - map.put("evictions", evictions); - map.put("size", size); + map.put(LOOKUPS_PARAM, lookups); + map.put(HITS_PARAM, hits); + map.put(HIT_RATIO_PARAM, calcHitRatio(lookups, hits)); + map.put(INSERTS_PARAM, inserts); + map.put(EVICTIONS_PARAM, evictions); + map.put(SIZE_PARAM, size); map.put("cleanupThread", cleanupThread); - map.put("ramBytesUsed", ramBytesUsed()); - map.put("maxRamMB", maxRamBytes != Long.MAX_VALUE ? maxRamBytes / 1024L / 1024L : -1L); + map.put(RAM_BYTES_USED_PARAM, ramBytesUsed()); + map.put(MAX_RAM_MB_PARAM, getMaxRamMB()); map.put("warmupTime", warmupTime); map.put("cumulative_lookups", clookups); @@ -331,88 +330,48 @@ public class FastLRUCache extends SolrCacheBase implements SolrCache, } @Override - public Map getResourceLimits() { - Map limits = new HashMap<>(); - limits.put(SIZE_PARAM, cache.getStats().getCurrentSize()); - limits.put(MIN_SIZE_PARAM, minSizeLimit); - limits.put(ACCEPTABLE_SIZE_PARAM, acceptableSize); - limits.put(CLEANUP_THREAD_PARAM, cleanupThread); - limits.put(SHOW_ITEMS_PARAM, showItems); - limits.put(MAX_RAM_MB_PARAM, maxRamBytes != Long.MAX_VALUE ? maxRamBytes / 1024L / 1024L : -1L); - return limits; + public int getMaxSize() { + return maxSize != Integer.MAX_VALUE ? maxSize : -1; } @Override - public void setResourceLimit(String limitName, Object val) { - if (CLEANUP_THREAD_PARAM.equals(limitName)) { - Boolean value; - try { - value = Boolean.parseBoolean(val.toString()); - cleanupThread = value; - cache.setRunCleanupThread(cleanupThread); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid new value for boolean limit '" + limitName + "': " + val); - } + public void setMaxSize(int maxSize) { + if (maxSize > 0) { + this.maxSize = maxSize; + } else { + this.maxSize = Integer.MAX_VALUE; } - Number value; - try { - value = Long.parseLong(String.valueOf(val)); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid new value for numeric limit '" + limitName +"': " + val); - } - if (!limitName.equals(MAX_RAM_MB_PARAM)) { - if (value.intValue() <= 1) { - throw new IllegalArgumentException("Invalid new value for numeric limit '" + limitName +"': " + value); - } - } - if (value.longValue() > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Invalid new value for numeric limit '" + limitName +"': " + value); - } - switch (limitName) { - case SIZE_PARAM: - sizeLimit = value.intValue(); - checkAndAdjustLimits(); - cache.setUpperWaterMark(sizeLimit); - cache.setLowerWaterMark(minSizeLimit); - break; - case MIN_SIZE_PARAM: - minSizeLimit = value.intValue(); - checkAndAdjustLimits(); - cache.setUpperWaterMark(sizeLimit); - cache.setLowerWaterMark(minSizeLimit); - break; - case ACCEPTABLE_SIZE_PARAM: - acceptableSize = value.intValue(); - acceptableSize = Math.max(minSizeLimit, acceptableSize); - cache.setAcceptableWaterMark(acceptableSize); - break; - case MAX_RAM_MB_PARAM: - long maxRamMB = value.intValue(); - maxRamBytes = maxRamMB < 0 ? Long.MAX_VALUE : maxRamMB * 1024L * 1024L; - if (maxRamMB < 0) { - ramLowerWatermark = Long.MIN_VALUE; - } else { - ramLowerWatermark = Math.round(maxRamBytes * 0.8); - } - cache.setRamUpperWatermark(maxRamBytes); - cache.setRamLowerWatermark(ramLowerWatermark); - break; - case SHOW_ITEMS_PARAM: - showItems = value.intValue(); - break; - default: - throw new IllegalArgumentException("Unsupported limit '" + limitName + "'"); + checkAndAdjustLimits(); + cache.setUpperWaterMark(maxSize); + cache.setLowerWaterMark(minSizeLimit); + description = generateDescription(); + } + + @Override + public int getMaxRamMB() { + return maxRamBytes != Long.MAX_VALUE ? (int) (maxRamBytes / 1024L / 1024L) : -1; + } + + @Override + public void setMaxRamMB(int maxRamMB) { + maxRamBytes = maxRamMB < 0 ? Long.MAX_VALUE : maxRamMB * 1024L * 1024L; + if (maxRamMB < 0) { + ramLowerWatermark = Long.MIN_VALUE; + } else { + ramLowerWatermark = Math.round(maxRamBytes * 0.8); } + cache.setRamUpperWatermark(maxRamBytes); + cache.setRamLowerWatermark(ramLowerWatermark); description = generateDescription(); } private void checkAndAdjustLimits() { if (minSizeLimit <= 0) minSizeLimit = 1; - if (sizeLimit <= minSizeLimit) { - if (sizeLimit > 1) { - minSizeLimit = sizeLimit - 1; + if (maxSize <= minSizeLimit) { + if (maxSize > 1) { + minSizeLimit = maxSize - 1; } else { - sizeLimit = minSizeLimit + 1; + maxSize = minSizeLimit + 1; } } } diff --git a/solr/core/src/java/org/apache/solr/search/LFUCache.java b/solr/core/src/java/org/apache/solr/search/LFUCache.java index 37ef4c6013d..f1c30d057c4 100644 --- a/solr/core/src/java/org/apache/solr/search/LFUCache.java +++ b/solr/core/src/java/org/apache/solr/search/LFUCache.java @@ -17,7 +17,6 @@ package org.apache.solr.search; import java.lang.invoke.MethodHandles; -import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.List; import java.util.Map; @@ -81,7 +80,7 @@ public class LFUCache implements SolrCache, Accountable { private Set metricNames = ConcurrentHashMap.newKeySet(); private MetricRegistry registry; - private int sizeLimit; + private int maxSize; private int minSizeLimit; private int initialSize; private int acceptableSize; @@ -93,10 +92,10 @@ public class LFUCache implements SolrCache, Accountable { this.regenerator = regenerator; name = (String) args.get(NAME); String str = (String) args.get(SIZE_PARAM); - sizeLimit = str == null ? 1024 : Integer.parseInt(str); + maxSize = str == null ? 1024 : Integer.parseInt(str); str = (String) args.get(MIN_SIZE_PARAM); if (str == null) { - minSizeLimit = (int) (sizeLimit * 0.9); + minSizeLimit = (int) (maxSize * 0.9); } else { minSizeLimit = Integer.parseInt(str); } @@ -104,7 +103,7 @@ public class LFUCache implements SolrCache, Accountable { str = (String) args.get(ACCEPTABLE_SIZE_PARAM); if (str == null) { - acceptableSize = (int) (sizeLimit * 0.95); + acceptableSize = (int) (maxSize * 0.95); } else { acceptableSize = Integer.parseInt(str); } @@ -112,7 +111,7 @@ public class LFUCache implements SolrCache, Accountable { acceptableSize = Math.max(minSizeLimit, acceptableSize); str = (String) args.get(INITIAL_SIZE_PARAM); - initialSize = str == null ? sizeLimit : Integer.parseInt(str); + initialSize = str == null ? maxSize : Integer.parseInt(str); str = (String) args.get(AUTOWARM_COUNT_PARAM); autowarmCount = str == null ? 0 : Integer.parseInt(str); str = (String) args.get(CLEANUP_THREAD_PARAM); @@ -127,7 +126,7 @@ public class LFUCache implements SolrCache, Accountable { description = generateDescription(); - cache = new ConcurrentLFUCache<>(sizeLimit, minSizeLimit, acceptableSize, initialSize, cleanupThread, false, null, timeDecay); + cache = new ConcurrentLFUCache<>(maxSize, minSizeLimit, acceptableSize, initialSize, cleanupThread, false, null, timeDecay); cache.setAlive(false); statsList = (List) persistence; @@ -145,7 +144,7 @@ public class LFUCache implements SolrCache, Accountable { } private String generateDescription() { - String descr = "Concurrent LFU Cache(maxSize=" + sizeLimit + ", initialSize=" + initialSize + + String descr = "Concurrent LFU Cache(maxSize=" + maxSize + ", initialSize=" + initialSize + ", minSize=" + minSizeLimit + ", acceptableSize=" + acceptableSize + ", cleanupThread=" + cleanupThread + ", timeDecay=" + Boolean.toString(timeDecay); if (autowarmCount > 0) { @@ -266,16 +265,22 @@ public class LFUCache implements SolrCache, Accountable { long evictions = stats.getCumulativeEvictions(); long size = stats.getCurrentSize(); - map.put("lookups", lookups); - map.put("hits", hits); - map.put("hitratio", calcHitRatio(lookups, hits)); - map.put("inserts", inserts); - map.put("evictions", evictions); - map.put("size", size); + map.put(LOOKUPS_PARAM, lookups); + map.put(HITS_PARAM, hits); + map.put(HIT_RATIO_PARAM, calcHitRatio(lookups, hits)); + map.put(INSERTS_PARAM, inserts); + map.put(EVICTIONS_PARAM, evictions); + map.put(SIZE_PARAM, size); + map.put(MAX_SIZE_PARAM, maxSize); + map.put(MIN_SIZE_PARAM, minSizeLimit); + map.put(ACCEPTABLE_SIZE_PARAM, acceptableSize); + map.put(AUTOWARM_COUNT_PARAM, autowarmCount); + map.put(CLEANUP_THREAD_PARAM, cleanupThread); + map.put(SHOW_ITEMS_PARAM, showItems); + map.put(TIME_DECAY_PARAM, timeDecay); + map.put("warmupTime", warmupTime); - map.put("timeDecay", timeDecay); - map.put("cleanupThread", cleanupThread); long clookups = 0; long chits = 0; @@ -294,7 +299,7 @@ public class LFUCache implements SolrCache, Accountable { map.put("cumulative_hitratio", calcHitRatio(clookups, chits)); map.put("cumulative_inserts", cinserts); map.put("cumulative_evictions", cevictions); - map.put("ramBytesUsed", ramBytesUsed()); + map.put(RAM_BYTES_USED_PARAM, ramBytesUsed()); if (detailed && showItems != 0) { Map items = cache.getMostUsedItems(showItems == -1 ? Integer.MAX_VALUE : showItems); @@ -346,85 +351,40 @@ public class LFUCache implements SolrCache, Accountable { } @Override - public Map getResourceLimits() { - Map limits = new HashMap<>(); - limits.put(SIZE_PARAM, cache.getStats().getCurrentSize()); - limits.put(MIN_SIZE_PARAM, minSizeLimit); - limits.put(ACCEPTABLE_SIZE_PARAM, acceptableSize); - limits.put(AUTOWARM_COUNT_PARAM, autowarmCount); - limits.put(CLEANUP_THREAD_PARAM, cleanupThread); - limits.put(SHOW_ITEMS_PARAM, showItems); - limits.put(TIME_DECAY_PARAM, timeDecay); - return limits; + public int getMaxSize() { + return maxSize != Integer.MAX_VALUE ? maxSize : -1; } @Override - public synchronized void setResourceLimit(String limitName, Object val) { - if (TIME_DECAY_PARAM.equals(limitName) || CLEANUP_THREAD_PARAM.equals(limitName)) { - Boolean value; - try { - value = Boolean.parseBoolean(String.valueOf(val)); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid value of boolean limit '" + limitName + "': " + val); - } - switch (limitName) { - case TIME_DECAY_PARAM: - timeDecay = value; - cache.setTimeDecay(timeDecay); - break; - case CLEANUP_THREAD_PARAM: - cleanupThread = value; - cache.setRunCleanupThread(cleanupThread); - break; - } + public void setMaxSize(int maxSize) { + if (maxSize > 0) { + this.maxSize = maxSize; } else { - Number value; - try { - value = Long.parseLong(String.valueOf(val)); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid new value for numeric limit '" + limitName +"': " + val); - } - if (value.intValue() <= 1 || value.longValue() > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Out of range new value for numeric limit '" + limitName +"': " + value); - } - switch (limitName) { - case SIZE_PARAM: - sizeLimit = value.intValue(); - checkAndAdjustLimits(); - cache.setUpperWaterMark(sizeLimit); - cache.setLowerWaterMark(minSizeLimit); - break; - case MIN_SIZE_PARAM: - minSizeLimit = value.intValue(); - checkAndAdjustLimits(); - cache.setUpperWaterMark(sizeLimit); - cache.setLowerWaterMark(minSizeLimit); - break; - case ACCEPTABLE_SIZE_PARAM: - acceptableSize = value.intValue(); - acceptableSize = Math.max(minSizeLimit, acceptableSize); - cache.setAcceptableWaterMark(acceptableSize); - break; - case AUTOWARM_COUNT_PARAM: - autowarmCount = value.intValue(); - break; - case SHOW_ITEMS_PARAM: - showItems = value.intValue(); - break; - default: - throw new IllegalArgumentException("Unsupported numeric limit '" + limitName + "'"); - } + this.maxSize = Integer.MAX_VALUE; } + checkAndAdjustLimits(); + cache.setUpperWaterMark(maxSize); + cache.setLowerWaterMark(minSizeLimit); description = generateDescription(); } + @Override + public int getMaxRamMB() { + return -1; + } + + @Override + public void setMaxRamMB(int maxRamMB) { + // no-op + } + private void checkAndAdjustLimits() { if (minSizeLimit <= 0) minSizeLimit = 1; - if (sizeLimit <= minSizeLimit) { - if (sizeLimit > 1) { - minSizeLimit = sizeLimit - 1; + if (maxSize <= minSizeLimit) { + if (maxSize > 1) { + minSizeLimit = maxSize - 1; } else { - sizeLimit = minSizeLimit + 1; + maxSize = minSizeLimit + 1; } } } diff --git a/solr/core/src/java/org/apache/solr/search/LRUCache.java b/solr/core/src/java/org/apache/solr/search/LRUCache.java index 3bd5f005b50..82e2700a516 100644 --- a/solr/core/src/java/org/apache/solr/search/LRUCache.java +++ b/solr/core/src/java/org/apache/solr/search/LRUCache.java @@ -18,7 +18,6 @@ package org.apache.solr.search; import java.lang.invoke.MethodHandles; import java.util.Collection; -import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -76,7 +75,7 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco private MetricsMap cacheMap; private Set metricNames = ConcurrentHashMap.newKeySet(); private MetricRegistry registry; - private int sizeLimit; + private int maxSize; private int initialSize; private long maxRamBytes = Long.MAX_VALUE; @@ -88,9 +87,9 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco public Object init(Map args, Object persistence, CacheRegenerator regenerator) { super.init(args, regenerator); String str = (String)args.get(SIZE_PARAM); - this.sizeLimit = str==null ? 1024 : Integer.parseInt(str); + this.maxSize = str==null ? 1024 : Integer.parseInt(str); str = (String)args.get("initialSize"); - initialSize = Math.min(str==null ? 1024 : Integer.parseInt(str), sizeLimit); + initialSize = Math.min(str==null ? 1024 : Integer.parseInt(str), maxSize); str = (String) args.get(MAX_RAM_MB_PARAM); this.maxRamBytes = str == null ? Long.MAX_VALUE : (long) (Double.parseDouble(str) * 1024L * 1024L); description = generateDescription(); @@ -115,7 +114,7 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco // must return false according to javadocs of removeEldestEntry if we're modifying // the map ourselves return false; - } else if (size() > getSizeLimit()) { + } else if (size() > getMaxSize()) { Iterator> iterator = entrySet().iterator(); do { Map.Entry entry = iterator.next(); @@ -129,7 +128,7 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco iterator.remove(); evictions++; stats.evictions.increment(); - } while (iterator.hasNext() && size() > getSizeLimit()); + } while (iterator.hasNext() && size() > getMaxSize()); // must return false according to javadocs of removeEldestEntry if we're modifying // the map ourselves return false; @@ -149,10 +148,6 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco return persistence; } - public int getSizeLimit() { - return sizeLimit; - } - public long getMaxRamBytes() { return maxRamBytes; } @@ -162,7 +157,7 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco * @return Returns the description of this cache. */ private String generateDescription() { - String description = "LRU Cache(maxSize=" + getSizeLimit() + ", initialSize=" + initialSize; + String description = "LRU Cache(maxSize=" + getMaxSize() + ", initialSize=" + initialSize; if (isAutowarmingOn()) { description += ", " + getAutowarmDescription(); } @@ -182,7 +177,7 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco @Override public V put(K key, V value) { - if (sizeLimit == Integer.MAX_VALUE && maxRamBytes == Long.MAX_VALUE) { + if (maxSize == Integer.MAX_VALUE && maxRamBytes == Long.MAX_VALUE) { throw new IllegalStateException("Cache: " + getName() + " has neither size nor RAM limit!"); } synchronized (map) { @@ -313,14 +308,15 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco registry = manager.registry(registryName); cacheMap = new MetricsMap((detailed, res) -> { synchronized (map) { - res.put("lookups", lookups); - res.put("hits", hits); - res.put("hitratio", calcHitRatio(lookups,hits)); - res.put("inserts", inserts); - res.put("evictions", evictions); - res.put("size", map.size()); - res.put("ramBytesUsed", ramBytesUsed()); - res.put("maxRamMB", maxRamBytes != Long.MAX_VALUE ? maxRamBytes / 1024L / 1024L : -1L); + res.put(LOOKUPS_PARAM, lookups); + res.put(HITS_PARAM, hits); + res.put(HIT_RATIO_PARAM, calcHitRatio(lookups,hits)); + res.put(INSERTS_PARAM, inserts); + res.put(EVICTIONS_PARAM, evictions); + res.put(SIZE_PARAM, map.size()); + res.put(RAM_BYTES_USED_PARAM, ramBytesUsed()); + res.put(MAX_RAM_MB_PARAM, getMaxRamMB()); + res.put(MAX_SIZE_PARAM, maxSize); res.put("evictionsRamUsage", evictionsRamUsage); } res.put("warmupTime", warmupTime); @@ -367,43 +363,31 @@ public class LRUCache extends SolrCacheBase implements SolrCache, Acco } @Override - public Map getResourceLimits() { - Map limits = new HashMap<>(); - limits.put(SIZE_PARAM, sizeLimit); - limits.put(MAX_RAM_MB_PARAM, maxRamBytes != Long.MAX_VALUE ? maxRamBytes / 1024L / 1024L : -1L); - return limits; + public int getMaxSize() { + return maxSize != Integer.MAX_VALUE ? maxSize : -1; } @Override - public void setResourceLimit(String limitName, Object val) { - if (!(val instanceof Number)) { - try { - val = Long.parseLong(String.valueOf(val)); - } catch (Exception e) { - throw new IllegalArgumentException("Unsupported value type (not a number) for limit '" + limitName + "': " + val + " (" + val.getClass().getName() + ")"); - } + public void setMaxSize(int maxSize) { + if (maxSize > 0) { + this.maxSize = maxSize; + } else { + this.maxSize = Integer.MAX_VALUE; } - Number value = (Number)val; - if (value.longValue() > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Invalid new value for limit '" + limitName +"': " + value); - } - switch (limitName) { - case SIZE_PARAM: - if (value.intValue() > 0) { - sizeLimit = value.intValue(); - } else { - sizeLimit = Integer.MAX_VALUE; - } - break; - case MAX_RAM_MB_PARAM: - if (value.intValue() > 0) { - maxRamBytes = value.intValue() * 1024L * 1024L; - } else { - maxRamBytes = Long.MAX_VALUE; - } - break; - default: - throw new IllegalArgumentException("Unsupported limit name '" + limitName + "'"); + description = generateDescription(); + } + + @Override + public int getMaxRamMB() { + return maxRamBytes != Long.MAX_VALUE ? (int) (maxRamBytes / 1024L / 1024L) : -1; + } + + @Override + public void setMaxRamMB(int maxRamMB) { + if (maxRamMB > 0) { + maxRamBytes = maxRamMB * 1024L * 1024L; + } else { + maxRamBytes = Long.MAX_VALUE; } description = generateDescription(); } diff --git a/solr/core/src/java/org/apache/solr/search/SolrCache.java b/solr/core/src/java/org/apache/solr/search/SolrCache.java index 2cf49da5c25..b96cb133a74 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrCache.java +++ b/solr/core/src/java/org/apache/solr/search/SolrCache.java @@ -27,7 +27,14 @@ import java.util.Map; */ public interface SolrCache extends SolrInfoBean, SolrMetricProducer { + String HIT_RATIO_PARAM = "hitratio"; + String HITS_PARAM = "hits"; + String INSERTS_PARAM = "inserts"; + String EVICTIONS_PARAM = "evictions"; + String LOOKUPS_PARAM = "lookups"; String SIZE_PARAM = "size"; + String MAX_SIZE_PARAM = "maxSize"; + String RAM_BYTES_USED_PARAM = "ramBytesUsed"; String MAX_RAM_MB_PARAM = "maxRamMB"; /** @@ -129,20 +136,19 @@ public interface SolrCache extends SolrInfoBean, SolrMetricProducer { /** Frees any non-memory resources */ public void close(); - /** Report current resource limits. */ - public Map getResourceLimits(); + /** Returns maximum size limit (number of items) if set and supported, -1 otherwise. */ + int getMaxSize(); - /** Set resource limits. */ - default void setResourceLimits(Map limits) throws Exception { - if (limits == null || limits.isEmpty()) { - return; - } - for (Map.Entry entry : limits.entrySet()) { - setResourceLimit(entry.getKey(), entry.getValue()); - } - } + /** Set maximum size limit (number of items), or -1 for unlimited. Note: this has effect + * only on implementations that support it, it's a no-op otherwise + */ + void setMaxSize(int maxSize); - /** Set a named resource limit. */ - public void setResourceLimit(String limitName, Object value) throws Exception; + /** Returns maximum size limit (in MB) if set and supported, -1 otherwise. */ + int getMaxRamMB(); + /** Set maximum size limit (in MB), or -1 for unlimited. Note: this has effect + * only on implementations that support it, it's a no-op otherwise. + */ + void setMaxRamMB(int maxRamMB); } diff --git a/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java b/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java index 29dab923b8a..82a882c94d3 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java +++ b/solr/core/src/java/org/apache/solr/search/SolrCacheHolder.java @@ -81,16 +81,24 @@ public class SolrCacheHolder implements SolrCache { } @Override - public Map getResourceLimits() { - return delegate.getResourceLimits(); + public int getMaxSize() { + return delegate.getMaxSize(); } @Override - public void setResourceLimit(String limitName, Object value) throws Exception { - delegate.setResourceLimit(limitName, value); - + public void setMaxSize(int maxSize) { + delegate.setMaxSize(maxSize); } + @Override + public int getMaxRamMB() { + return delegate.getMaxRamMB(); + } + + @Override + public void setMaxRamMB(int maxRamMB) { + delegate.setMaxRamMB(maxRamMB); + } public void warm(SolrIndexSearcher searcher, SolrCacheHolder src) { delegate.warm(searcher, src.get()); diff --git a/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java b/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java index 3159e3e13d9..0fb17651618 100644 --- a/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java +++ b/solr/core/src/test/org/apache/solr/search/TestFastLRUCache.java @@ -346,7 +346,7 @@ public class TestFastLRUCache extends SolrTestCase { // no evictions yet assertEquals(6, cache.size()); // this also sets minLimit = 4 - cache.setResourceLimit(SolrCache.SIZE_PARAM, 5); + cache.setMaxSize(5); // should not happen yet - evictions are triggered by put assertEquals(6, cache.size()); cache.put("6", new Accountable() { @@ -359,7 +359,7 @@ public class TestFastLRUCache extends SolrTestCase { assertEquals(4, cache.size()); // modify ram limit - cache.setResourceLimit(SolrCache.MAX_RAM_MB_PARAM, 3); + cache.setMaxRamMB(3); // should not happen yet - evictions are triggered by put assertEquals(4, cache.size()); // this evicts down to 3MB * 0.8, ie. ramLowerWaterMark @@ -376,7 +376,7 @@ public class TestFastLRUCache extends SolrTestCase { // scale up - cache.setResourceLimit(SolrCache.MAX_RAM_MB_PARAM, 4); + cache.setMaxRamMB(4); cache.put("8", new Accountable() { @Override public long ramBytesUsed() { @@ -385,7 +385,7 @@ public class TestFastLRUCache extends SolrTestCase { }); assertEquals(4, cache.size()); - cache.setResourceLimit(SolrCache.SIZE_PARAM, 10); + cache.setMaxSize(10); for (int i = 0; i < 6; i++) { cache.put("new" + i, new Accountable() { @Override diff --git a/solr/core/src/test/org/apache/solr/search/TestLFUCache.java b/solr/core/src/test/org/apache/solr/search/TestLFUCache.java index 324d7f4c71d..beac366cd4c 100644 --- a/solr/core/src/test/org/apache/solr/search/TestLFUCache.java +++ b/solr/core/src/test/org/apache/solr/search/TestLFUCache.java @@ -472,7 +472,7 @@ public class TestLFUCache extends SolrTestCaseJ4 { // no evictions yet assertEquals(6, cache.size()); // this sets minSize = 4, evictions will target minSize - cache.setResourceLimit(SolrCache.SIZE_PARAM, 5); + cache.setMaxSize(5); // should not happen yet - evictions are triggered by put assertEquals(6, cache.size()); cache.put("6", "foo 6"); @@ -487,7 +487,7 @@ public class TestLFUCache extends SolrTestCaseJ4 { // scale up - cache.setResourceLimit(SolrCache.SIZE_PARAM, 10); + cache.setMaxSize(10); for (int i = 0; i < 6; i++) { cache.put("new" + i, "bar " + i); } diff --git a/solr/core/src/test/org/apache/solr/search/TestLRUCache.java b/solr/core/src/test/org/apache/solr/search/TestLRUCache.java index 3c33e27f67c..f9cd0dba842 100644 --- a/solr/core/src/test/org/apache/solr/search/TestLRUCache.java +++ b/solr/core/src/test/org/apache/solr/search/TestLRUCache.java @@ -206,7 +206,7 @@ public class TestLRUCache extends SolrTestCase { } // no evictions yet assertEquals(6, cache.size()); - cache.setResourceLimit(SolrCache.SIZE_PARAM, 5); + cache.setMaxSize(5); // should not happen yet - evictions are triggered by put assertEquals(6, cache.size()); cache.put("6", new Accountable() { @@ -219,7 +219,7 @@ public class TestLRUCache extends SolrTestCase { assertEquals(5, cache.size()); // modify ram limit - cache.setResourceLimit(SolrCache.MAX_RAM_MB_PARAM, 3); + cache.setMaxRamMB(3); // should not happen yet - evictions are triggered by put assertEquals(5, cache.size()); cache.put("7", new Accountable() { @@ -235,7 +235,7 @@ public class TestLRUCache extends SolrTestCase { // scale up - cache.setResourceLimit(SolrCache.MAX_RAM_MB_PARAM, 4); + cache.setMaxRamMB(4); cache.put("8", new Accountable() { @Override public long ramBytesUsed() { @@ -244,7 +244,7 @@ public class TestLRUCache extends SolrTestCase { }); assertEquals(4, cache.size()); - cache.setResourceLimit(SolrCache.SIZE_PARAM, 10); + cache.setMaxSize(10); for (int i = 0; i < 6; i++) { cache.put("new" + i, new Accountable() { @Override