|
@@ -299,6 +299,14 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
|
|
|
return SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings).equals(USE_CONTEXT_RATE_VALUE);
|
|
|
}
|
|
|
|
|
|
+ public static boolean isImplicitContextCacheSet(Settings settings) {
|
|
|
+ return new ScriptService.ContextSettings(settings).implicitContextCache();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String contextDeprecationMessage(Settings settings) {
|
|
|
+ return new ScriptService.ContextSettings(settings).deprecationMessage();
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* This is overridden in tests to disable compilation rate limiting.
|
|
|
*/
|
|
@@ -345,53 +353,26 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
|
|
|
* when using the general cache.
|
|
|
*/
|
|
|
void validateCacheSettings(Settings settings) {
|
|
|
- boolean useContext = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings).equals(USE_CONTEXT_RATE_VALUE);
|
|
|
- if (useContext) {
|
|
|
+ ContextSettings contextSettings = new ContextSettings(settings, contexts.keySet());
|
|
|
+ if (contextSettings.useContextSet) {
|
|
|
deprecationLogger.warn(DeprecationCategory.SCRIPTING, "scripting-context-cache", USE_CONTEXT_RATE_KEY_DEPRECATION_MESSAGE);
|
|
|
+ } else if (contextSettings.hasContextSettings()) {
|
|
|
+ deprecationLogger.warn(DeprecationCategory.SCRIPTING, "scripting-context-cache", contextSettings.deprecationMessage());
|
|
|
}
|
|
|
- List<Setting.AffixSetting<?>> affixes = Arrays.asList(
|
|
|
- SCRIPT_MAX_COMPILATIONS_RATE_SETTING,
|
|
|
- SCRIPT_CACHE_EXPIRE_SETTING,
|
|
|
- SCRIPT_CACHE_SIZE_SETTING
|
|
|
- );
|
|
|
- List<String> customRates = new ArrayList<>();
|
|
|
- List<String> keys = new ArrayList<>();
|
|
|
- for (Setting.AffixSetting<?> affix : affixes) {
|
|
|
- for (String context : affix.getAsMap(settings).keySet()) {
|
|
|
- String s = affix.getConcreteSettingForNamespace(context).getKey();
|
|
|
- if (contexts.containsKey(context) == false) {
|
|
|
- throw new IllegalArgumentException("Context [" + context + "] doesn't exist for setting [" + s + "]");
|
|
|
- }
|
|
|
- keys.add(s);
|
|
|
- if (affix.equals(SCRIPT_MAX_COMPILATIONS_RATE_SETTING)) {
|
|
|
- customRates.add(s);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (useContext == false && keys.isEmpty() == false) {
|
|
|
- keys.sort(Comparator.naturalOrder());
|
|
|
- throw new IllegalArgumentException(
|
|
|
- "Context cache settings ["
|
|
|
- + String.join(", ", keys)
|
|
|
- + "] requires ["
|
|
|
- + SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
|
|
|
- + "] to be ["
|
|
|
- + USE_CONTEXT_RATE_KEY
|
|
|
- + "]"
|
|
|
- );
|
|
|
+ if (contextSettings.incompatibleSettings()) {
|
|
|
+ throw new IllegalArgumentException(contextSettings.incompatibleSettingsMessage());
|
|
|
}
|
|
|
if (SCRIPT_DISABLE_MAX_COMPILATIONS_RATE_SETTING.get(settings)) {
|
|
|
- if (customRates.size() > 0) {
|
|
|
- customRates.sort(Comparator.naturalOrder());
|
|
|
+ if (contextSettings.compilationContexts.size() > 0) {
|
|
|
throw new IllegalArgumentException(
|
|
|
"Cannot set custom context compilation rates ["
|
|
|
- + String.join(", ", customRates)
|
|
|
+ + String.join(", ", contextSettings.contextCompilationKeys())
|
|
|
+ "] if compile rates disabled via ["
|
|
|
+ SCRIPT_DISABLE_MAX_COMPILATIONS_RATE_SETTING.getKey()
|
|
|
+ "]"
|
|
|
);
|
|
|
}
|
|
|
- if (useContext == false && SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.exists(settings)) {
|
|
|
+ if (contextSettings.useContextSet == false && contextSettings.isGeneralCompilationRateSet) {
|
|
|
throw new IllegalArgumentException(
|
|
|
"Cannot set custom general compilation rates ["
|
|
|
+ SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
|
|
@@ -405,6 +386,144 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Collect settings related to script context and general caches.
|
|
|
+ *
|
|
|
+ * The general cache is used by default.
|
|
|
+ * The context cache is used if {@code script.max_compilations_rate} is {@code "use-context"}, a deprecated value.
|
|
|
+ * The context cache is used implicitly if {@code script.max_compilations_rate} is unset and any of the context
|
|
|
+ * cache family of settings is used:
|
|
|
+ * {@code script.context.*.max_compilations_rate}, {@link ScriptService#SCRIPT_MAX_COMPILATIONS_RATE_SETTING}
|
|
|
+ * {@code script.context.*.cache_max_size}, {@link ScriptService#SCRIPT_CACHE_SIZE_SETTING}
|
|
|
+ * {@code script.context.*.cache_expire}, {@link ScriptService#SCRIPT_CACHE_EXPIRE_SETTING}
|
|
|
+ */
|
|
|
+ public static class ContextSettings {
|
|
|
+ public final Settings settings;
|
|
|
+ public final boolean useContextSet;
|
|
|
+ public final boolean isGeneralCompilationRateSet;
|
|
|
+ public final ScriptCache.CompilationRate generalCompilationRate;
|
|
|
+ public final List<String> compilationContexts;
|
|
|
+ public final List<String> sizeContexts;
|
|
|
+ public final List<String> expireContexts;
|
|
|
+
|
|
|
+ public ContextSettings(Settings settings, Set<String> contexts) {
|
|
|
+ this.settings = settings;
|
|
|
+ generalCompilationRate = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings);
|
|
|
+ useContextSet = generalCompilationRate.equals(USE_CONTEXT_RATE_VALUE);
|
|
|
+ isGeneralCompilationRateSet = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.exists(settings);
|
|
|
+ compilationContexts = getContexts(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, settings, contexts);
|
|
|
+ sizeContexts = getContexts(SCRIPT_CACHE_SIZE_SETTING, settings, contexts);
|
|
|
+ expireContexts = getContexts(SCRIPT_CACHE_EXPIRE_SETTING, settings, contexts);
|
|
|
+ }
|
|
|
+
|
|
|
+ public ContextSettings(Settings settings) {
|
|
|
+ this(settings, Collections.emptySet());
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static List<String> getContexts(Setting.AffixSetting<?> setting, Settings settings, Set<String> contexts) {
|
|
|
+ List<String> contextSettings = new ArrayList<>();
|
|
|
+ for (String context : setting.getAsMap(settings).keySet()) {
|
|
|
+ if (contexts.isEmpty() == false && contexts.contains(context) == false) {
|
|
|
+ String settingKey = setting.getConcreteSettingForNamespace(context).getKey();
|
|
|
+ throw new IllegalArgumentException("Context [" + context + "] doesn't exist for setting [" + settingKey + "]");
|
|
|
+ }
|
|
|
+ contextSettings.add(context);
|
|
|
+ }
|
|
|
+ contextSettings.sort(Comparator.naturalOrder());
|
|
|
+ return contextSettings;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Are there any context specific settings */
|
|
|
+ public boolean hasContextSettings() {
|
|
|
+ return compilationContexts.isEmpty() == false || expireContexts.isEmpty() == false || sizeContexts.isEmpty() == false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** deprecation message for implicitly using the context cache */
|
|
|
+ public String deprecationMessage() {
|
|
|
+ // Implicitly using the script context cache is deprecated, remove the following deprecated settings to use the script general
|
|
|
+ // cache.
|
|
|
+ if (hasContextSettings() == false) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ List<String> settingsKeys = new ArrayList<>();
|
|
|
+ settingsKeys.addAll(fullKeys(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, compilationContexts));
|
|
|
+ settingsKeys.addAll(fullKeys(SCRIPT_CACHE_SIZE_SETTING, sizeContexts));
|
|
|
+ settingsKeys.addAll(fullKeys(SCRIPT_CACHE_EXPIRE_SETTING, expireContexts));
|
|
|
+ settingsKeys.sort(Comparator.naturalOrder());
|
|
|
+ return "Implicitly using the script context cache is deprecated, remove settings "
|
|
|
+ + "["
|
|
|
+ + String.join(", ", settingsKeys)
|
|
|
+ + "] to use the script general cache.";
|
|
|
+ }
|
|
|
+
|
|
|
+ /** the context specific max compilation keys */
|
|
|
+ public List<String> contextCompilationKeys() {
|
|
|
+ return fullKeys(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, compilationContexts);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** the full keys for the contexts in the context affix setting */
|
|
|
+ protected static List<String> fullKeys(Setting.AffixSetting<?> affix, List<String> contexts) {
|
|
|
+ return contexts.stream().map(ctx -> affix.getConcreteSettingForNamespace(ctx).getKey()).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Should the context cache be used? This is true if "use-context" is set explicitly or implicitly, see above for implicit
|
|
|
+ * definition.
|
|
|
+ */
|
|
|
+ public boolean useContextCache() {
|
|
|
+ return useContextSet || implicitContextCache();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implicitly use the script context cache. False if context cache is explicitly used as well as context cache is unused.
|
|
|
+ */
|
|
|
+ public boolean implicitContextCache() {
|
|
|
+ return useContextSet == false && hasContextSettings() && isGeneralCompilationRateSet == false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Is the set of settings incompatible? This is the case if:
|
|
|
+ * 1) {@code script.max_compilations_rate}, {@link ScriptService#SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING} is set but not
|
|
|
+ * set to "use-context".
|
|
|
+ * 2) Any of the context cache family of settings is set.
|
|
|
+ */
|
|
|
+ public boolean incompatibleSettings() {
|
|
|
+ return useContextSet == false && hasContextSettings() && isGeneralCompilationRateSet;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * All context specific settings
|
|
|
+ */
|
|
|
+ public List<String> contextSettings() {
|
|
|
+ List<String> contextSettings = fullKeys(SCRIPT_MAX_COMPILATIONS_RATE_SETTING, compilationContexts);
|
|
|
+ contextSettings.addAll(fullKeys(SCRIPT_CACHE_SIZE_SETTING, sizeContexts));
|
|
|
+ contextSettings.addAll(fullKeys(SCRIPT_CACHE_EXPIRE_SETTING, expireContexts));
|
|
|
+ return contextSettings;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Error message if there are incompatible settings.
|
|
|
+ */
|
|
|
+ public String incompatibleSettingsMessage() {
|
|
|
+ if (incompatibleSettings() == false) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ List<String> incompatible = contextSettings();
|
|
|
+ return "Context cache settings ["
|
|
|
+ + String.join(",", incompatible)
|
|
|
+ + "] are incompatible with ["
|
|
|
+ + SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
|
|
|
+ + "] set to non-default value ["
|
|
|
+ + generalCompilationRate
|
|
|
+ + "]."
|
|
|
+ + " Either remove the incompatible settings (recommended) or set ["
|
|
|
+ + SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.getKey()
|
|
|
+ + "] to ["
|
|
|
+ + USE_CONTEXT_RATE_KEY
|
|
|
+ + "] to use per-context settings";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
|
IOUtils.close(engines.values());
|
|
@@ -692,10 +811,10 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
|
|
|
|
|
|
void setCacheHolder(Settings settings) {
|
|
|
CacheHolder current = cacheHolder.get();
|
|
|
- boolean useContext = SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING.get(settings).equals(USE_CONTEXT_RATE_VALUE);
|
|
|
+ ContextSettings contextSettings = new ContextSettings(settings, contexts.keySet());
|
|
|
|
|
|
if (current == null) {
|
|
|
- if (useContext) {
|
|
|
+ if (contextSettings.useContextCache()) {
|
|
|
cacheHolder.set(contextCacheHolder(settings));
|
|
|
} else {
|
|
|
cacheHolder.set(generalCacheHolder(settings));
|
|
@@ -704,7 +823,7 @@ public class ScriptService implements Closeable, ClusterStateApplier, ScriptComp
|
|
|
}
|
|
|
|
|
|
// Update
|
|
|
- if (useContext) {
|
|
|
+ if (contextSettings.useContextCache()) {
|
|
|
if (current.general != null) {
|
|
|
// Flipping to context specific
|
|
|
cacheHolder.set(contextCacheHolder(settings));
|