diff options
Diffstat (limited to 'core')
22 files changed, 144 insertions, 231 deletions
diff --git a/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java b/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java index c88b604e8c..c62c391ac7 100644 --- a/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java +++ b/core/src/main/java/org/elasticsearch/action/update/UpdateHelper.java @@ -44,7 +44,6 @@ import org.elasticsearch.index.mapper.ParentFieldMapper; import org.elasticsearch.index.mapper.RoutingFieldMapper; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; @@ -301,8 +300,8 @@ public class UpdateHelper extends AbstractComponent { private Map<String, Object> executeScript(Script script, Map<String, Object> ctx) { try { if (scriptService != null) { - CompiledScript compiledScript = scriptService.compile(script, ScriptContext.UPDATE); - ExecutableScript executableScript = scriptService.executable(compiledScript, script.getParams()); + ExecutableScript.Compiled compiledScript = scriptService.compile(script, ScriptContext.UPDATE); + ExecutableScript executableScript = compiledScript.newInstance(script.getParams()); executableScript.setNextVar(ContextFields.CTX, ctx); executableScript.run(); } diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java b/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java index 37473710e2..dcad54d52c 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java @@ -20,13 +20,10 @@ package org.elasticsearch.index.query; import org.apache.lucene.index.IndexReader; import org.elasticsearch.client.Client; -import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.script.CompiledScript; -import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptService; @@ -106,7 +103,7 @@ public class QueryRewriteContext { } public String getTemplateBytes(Script template) { - CompiledTemplate compiledTemplate = scriptService.compileTemplate(template, ScriptContext.SEARCH); + CompiledTemplate compiledTemplate = scriptService.compileTemplate(template, ScriptContext.EXECUTABLE); return compiledTemplate.run(template.getParams()); } } diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java b/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java index 31b2a71846..c4093be5dd 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java @@ -32,7 +32,6 @@ import org.elasticsearch.client.Client; import org.elasticsearch.common.CheckedFunction; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.index.Index; @@ -50,7 +49,6 @@ import org.elasticsearch.index.mapper.ObjectMapper; import org.elasticsearch.index.mapper.TextFieldMapper; import org.elasticsearch.index.query.support.NestedScope; import org.elasticsearch.index.similarity.SimilarityService; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; @@ -331,39 +329,43 @@ public class QueryShardContext extends QueryRewriteContext { * Compiles (or retrieves from cache) and binds the parameters to the * provided script */ - public final SearchScript getSearchScript(Script script, ScriptContext context) { + public final SearchScript getSearchScript(Script script, ScriptContext<SearchScript, SearchScript.Compiled> context) { failIfFrozen(); - CompiledScript compile = scriptService.compile(script, context); - return scriptService.search(lookup(), compile, script.getParams()); + SearchScript.Compiled compiled = scriptService.compile(script, context); + return compiled.newInstance(script.getParams(), lookup()); } /** * Returns a lazily created {@link SearchScript} that is compiled immediately but can be pulled later once all * parameters are available. */ - public final Function<Map<String, Object>, SearchScript> getLazySearchScript(Script script, ScriptContext context) { + public final Function<Map<String, Object>, SearchScript> getLazySearchScript( + Script script, ScriptContext<SearchScript, SearchScript.Compiled> context) { + // TODO: this "lazy" binding can be removed once scripted metric aggs have their own contexts, which take _agg/_aggs as a parameter failIfFrozen(); - CompiledScript compile = scriptService.compile(script, context); - return (p) -> scriptService.search(lookup(), compile, p); + SearchScript.Compiled compiled = scriptService.compile(script, context); + return (p) -> compiled.newInstance(p, lookup()); } /** * Compiles (or retrieves from cache) and binds the parameters to the * provided script */ - public final ExecutableScript getExecutableScript(Script script, ScriptContext context) { + public final ExecutableScript getExecutableScript(Script script, ScriptContext<ExecutableScript, ExecutableScript.Compiled> context) { failIfFrozen(); - CompiledScript compiledScript = scriptService.compile(script, context); - return scriptService.executable(compiledScript, script.getParams()); + ExecutableScript.Compiled compiled = scriptService.compile(script, context); + return compiled.newInstance(script.getParams()); } /** * Returns a lazily created {@link ExecutableScript} that is compiled immediately but can be pulled later once all * parameters are available. */ - public final Function<Map<String, Object>, ExecutableScript> getLazyExecutableScript(Script script, ScriptContext context) { + public final Function<Map<String, Object>, ExecutableScript> getLazyExecutableScript( + Script script, ScriptContext<ExecutableScript, ExecutableScript.Compiled> context) { + // TODO: this "lazy" binding can be removed once scripted metric aggs have their own contexts, which take _agg/_aggs as a parameter failIfFrozen(); - CompiledScript executable = scriptService.compile(script, context); - return (p) -> scriptService.executable(executable, p); + ExecutableScript.Compiled compiled = scriptService.compile(script, context); + return compiled::newInstance; } /** diff --git a/core/src/main/java/org/elasticsearch/script/CompiledScript.java b/core/src/main/java/org/elasticsearch/script/CompiledScript.java deleted file mode 100644 index 818971f0f8..0000000000 --- a/core/src/main/java/org/elasticsearch/script/CompiledScript.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.script; - -/** - * CompiledScript holds all the parameters necessary to execute a previously compiled script. - */ -public class CompiledScript { - - private final ScriptType type; - private final String name; - private final String lang; - private final Object compiled; - - /** - * Constructor for CompiledScript. - * @param type The type of script to be executed. - * @param name The name of the script to be executed. - * @param lang The language of the script to be executed. - * @param compiled The compiled script Object that is executable. - */ - public CompiledScript(ScriptType type, String name, String lang, Object compiled) { - this.type = type; - this.name = name; - this.lang = lang; - this.compiled = compiled; - } - - /** - * Method to get the type of language. - * @return The type of language the script was compiled in. - */ - public ScriptType type() { - return type; - } - - /** - * Method to get the name of the script. - * @return The name of the script to be executed. - */ - public String name() { - return name; - } - - /** - * Method to get the language. - * @return The language of the script to be executed. - */ - public String lang() { - return lang; - } - - /** - * Method to get the compiled script object. - * @return The compiled script Object that is executable. - */ - public Object compiled() { - return compiled; - } - - /** - * @return A string composed of type, lang, and name to describe the CompiledScript. - */ - @Override - public String toString() { - return type + " script [" + name + "] using lang [" + lang + "]"; - } -} diff --git a/core/src/main/java/org/elasticsearch/script/ExecutableScript.java b/core/src/main/java/org/elasticsearch/script/ExecutableScript.java index e3f8eb4744..0d025c020e 100644 --- a/core/src/main/java/org/elasticsearch/script/ExecutableScript.java +++ b/core/src/main/java/org/elasticsearch/script/ExecutableScript.java @@ -19,6 +19,8 @@ package org.elasticsearch.script; +import java.util.Map; + /** * An executable script, can't be used concurrently. */ @@ -38,4 +40,8 @@ public interface ExecutableScript { * Executes the script. */ Object run(); + + interface Compiled { + ExecutableScript newInstance(Map<String, Object> params); + } } diff --git a/core/src/main/java/org/elasticsearch/script/ScriptContext.java b/core/src/main/java/org/elasticsearch/script/ScriptContext.java index cd3bff3379..03bcb376e5 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptContext.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptContext.java @@ -24,30 +24,65 @@ import java.util.HashMap; import java.util.Map; /** - * A holder for information about a context in which a script is compiled and run. + * The information necessary to compile and run a script. + * + * A {@link ScriptContext} contains the information related to a single use case and the interfaces + * and methods necessary for a {@link ScriptEngine} to implement. + * <p> + * There are two related classes which must be supplied to construct a {@link ScriptContext}. + * <p> + * The <i>InstanceType</i> is a class, possibly stateful, that is an instance of a script. Instances of + * the <i>InstanceType</i> may be executed multiple times by a caller with different arguments. This + * class must have an abstract method named <i>execute</i> which {@link ScriptEngine} implementations + * will define. + * <p> + * The <i>CompiledType</i> is a factory class for constructing instances of a script. The + * {@link ScriptService} returns an instance of <i>CompiledType</i> when compiling a script. This class + * must be stateless so it is cacheable by the {@link ScriptService}. It must have an abstract method + * named <i>newInstance</i> which returns <i>InstanceType</i> which {@link ScriptEngine} implementations + * will define. */ -public final class ScriptContext { +public final class ScriptContext<InstanceType, CompiledType> { - public static final ScriptContext AGGS = new ScriptContext("aggs"); - public static final ScriptContext SEARCH = new ScriptContext("search"); - public static final ScriptContext UPDATE = new ScriptContext("update"); - public static final ScriptContext INGEST = new ScriptContext("ingest"); + public static final ScriptContext<SearchScript, SearchScript.Compiled> AGGS = + new ScriptContext<>("aggs", SearchScript.class, SearchScript.Compiled.class); + public static final ScriptContext<SearchScript, SearchScript.Compiled> SEARCH = + new ScriptContext<>("search", SearchScript.class, SearchScript.Compiled.class); + // TODO: remove this once each agg calling scripts has its own context + public static final ScriptContext<ExecutableScript, ExecutableScript.Compiled> AGGS_EXECUTABLE = + new ScriptContext<>("aggs_executable", ExecutableScript.class, ExecutableScript.Compiled.class); + public static final ScriptContext<ExecutableScript, ExecutableScript.Compiled> UPDATE = + new ScriptContext<>("update", ExecutableScript.class, ExecutableScript.Compiled.class); + public static final ScriptContext<ExecutableScript, ExecutableScript.Compiled> INGEST = + new ScriptContext<>("ingest", ExecutableScript.class, ExecutableScript.Compiled.class); + public static final ScriptContext<ExecutableScript, ExecutableScript.Compiled> EXECUTABLE = + new ScriptContext<>("executable", ExecutableScript.class, ExecutableScript.Compiled.class); - public static final Map<String, ScriptContext> BUILTINS; + public static final Map<String, ScriptContext<?, ?>> BUILTINS; static { - Map<String, ScriptContext> builtins = new HashMap<>(); + Map<String, ScriptContext<?, ?>> builtins = new HashMap<>(); builtins.put(AGGS.name, AGGS); builtins.put(SEARCH.name, SEARCH); + builtins.put(AGGS_EXECUTABLE.name, AGGS_EXECUTABLE); builtins.put(UPDATE.name, UPDATE); builtins.put(INGEST.name, INGEST); + builtins.put(EXECUTABLE.name, EXECUTABLE); BUILTINS = Collections.unmodifiableMap(builtins); } /** A unique identifier for this context. */ public final String name; - // pkg private ctor, only created by script module - public ScriptContext(String name) { + /** A class that is an instance of a script. */ + public final Class<InstanceType> instanceClazz; + + /** A factory class for constructing instances of a script. */ + public final Class<CompiledType> compiledClazz; + + /** Construct a context with the related instance and compiled classes. */ + public ScriptContext(String name, Class<InstanceType> instanceClazz, Class<CompiledType> compiledClazz) { this.name = name; + this.instanceClazz = instanceClazz; + this.compiledClazz = compiledClazz; } } diff --git a/core/src/main/java/org/elasticsearch/script/ScriptEngine.java b/core/src/main/java/org/elasticsearch/script/ScriptEngine.java index 2256ecbb26..396ed73d90 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptEngine.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptEngine.java @@ -45,9 +45,9 @@ public interface ScriptEngine extends Closeable { */ Object compile(String name, String code, Map<String, String> params); - ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars); - - SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars); + ExecutableScript executable(Object compiledScript, @Nullable Map<String, Object> vars); + + SearchScript search(Object compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars); @Override default void close() throws IOException {} diff --git a/core/src/main/java/org/elasticsearch/script/ScriptModule.java b/core/src/main/java/org/elasticsearch/script/ScriptModule.java index b29a199c3a..8fd17d4e1b 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptModule.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptModule.java @@ -36,7 +36,7 @@ public class ScriptModule { public ScriptModule(Settings settings, List<ScriptPlugin> scriptPlugins) { Map<String, ScriptEngine> engines = new HashMap<>(); - Map<String, ScriptContext> contexts = new HashMap<>(ScriptContext.BUILTINS); + Map<String, ScriptContext<?, ?>> contexts = new HashMap<>(ScriptContext.BUILTINS); for (ScriptPlugin plugin : scriptPlugins) { for (ScriptContext context : plugin.getContexts()) { ScriptContext oldContext = contexts.put(context.name, context); diff --git a/core/src/main/java/org/elasticsearch/script/ScriptService.java b/core/src/main/java/org/elasticsearch/script/ScriptService.java index e5892ef1dc..3ce1c89d04 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptService.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptService.java @@ -45,7 +45,6 @@ import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.template.CompiledTemplate; import java.io.Closeable; @@ -82,9 +81,9 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust private final Set<String> contextsAllowed; private final Map<String, ScriptEngine> engines; - private final Map<String, ScriptContext> contexts; + private final Map<String, ScriptContext<?,?>> contexts; - private final Cache<CacheKey, CompiledScript> cache; + private final Cache<CacheKey, Object> cache; private final ScriptMetrics scriptMetrics = new ScriptMetrics(); @@ -95,7 +94,7 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust private double scriptsPerMinCounter; private double compilesAllowedPerNano; - public ScriptService(Settings settings, Map<String, ScriptEngine> engines, Map<String, ScriptContext> contexts) { + public ScriptService(Settings settings, Map<String, ScriptEngine> engines, Map<String, ScriptContext<?,?>> contexts) { super(settings); Objects.requireNonNull(settings); @@ -176,7 +175,7 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust int cacheMaxSize = SCRIPT_CACHE_SIZE_SETTING.get(settings); - CacheBuilder<CacheKey, CompiledScript> cacheBuilder = CacheBuilder.builder(); + CacheBuilder<CacheKey, Object> cacheBuilder = CacheBuilder.builder(); if (cacheMaxSize >= 0) { cacheBuilder.setMaximumWeight(cacheMaxSize); } @@ -218,9 +217,11 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust } /** - * Checks if a script can be executed and compiles it if needed, or returns the previously compiled and cached script. + * Compiles a script using the given context. + * + * @return a compiled script which may be used to construct instances of a script for the given context */ - public CompiledScript compile(Script script, ScriptContext context) { + public <InstanceType, CompiledType> CompiledType compile(Script script, ScriptContext<InstanceType, CompiledType> context) { Objects.requireNonNull(script); Objects.requireNonNull(context); @@ -287,11 +288,11 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust logger.trace("compiling lang: [{}] type: [{}] script: {}", lang, type, idOrCode); } - CacheKey cacheKey = new CacheKey(lang, idOrCode, options); - CompiledScript compiledScript = cache.get(cacheKey); + CacheKey cacheKey = new CacheKey(lang, idOrCode, context.name, options); + Object compiledScript = cache.get(cacheKey); if (compiledScript != null) { - return compiledScript; + return context.compiledClazz.cast(compiledScript); } // Synchronize so we don't compile scripts many times during multiple shards all compiling a script @@ -311,7 +312,14 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust } // Check whether too many compilations have happened checkCompilationLimit(); - compiledScript = new CompiledScript(type, id, lang, scriptEngine.compile(id, idOrCode, options)); + Object engineCompiled = scriptEngine.compile(id, idOrCode, options); + if (context.instanceClazz == ExecutableScript.class) { + compiledScript = (ExecutableScript.Compiled) params -> scriptEngine.executable(engineCompiled, params); + } else if (context.instanceClazz == SearchScript.class) { + compiledScript = (SearchScript.Compiled) (params, lookup) -> scriptEngine.search(engineCompiled, lookup, params); + } else { + throw new IllegalArgumentException("Script context [" + context.name + "] not supported"); + } } catch (ScriptException good) { // TODO: remove this try-catch completely, when all script engines have good exceptions! throw good; // its already good @@ -325,14 +333,14 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust cache.put(cacheKey, compiledScript); } - return compiledScript; + return context.compiledClazz.cast(compiledScript); } } /** Compiles a template. Note this will be moved to a separate TemplateService in the future. */ - public CompiledTemplate compileTemplate(Script script, ScriptContext scriptContext) { - CompiledScript compiledScript = compile(script, scriptContext); - return params -> (String)executable(compiledScript, params).run(); + public CompiledTemplate compileTemplate(Script script, ScriptContext<ExecutableScript, ExecutableScript.Compiled> scriptContext) { + ExecutableScript.Compiled compiledScript = compile(script, scriptContext); + return params -> (String)compiledScript.newInstance(params).run(); } /** @@ -498,21 +506,6 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust } } - /** - * Executes a previously compiled script provided as an argument - */ - public ExecutableScript executable(CompiledScript compiledScript, Map<String, Object> params) { - return getEngine(compiledScript.lang()).executable(compiledScript, params); - } - - /** - * Binds provided parameters to a compiled script returning a - * {@link SearchScript} ready for execution - */ - public SearchScript search(SearchLookup lookup, CompiledScript compiledScript, Map<String, Object> params) { - return getEngine(compiledScript.lang()).search(compiledScript, lookup, params); - } - public ScriptStats stats() { return scriptMetrics.stats(); } @@ -527,9 +520,9 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust * {@code ScriptEngine}'s {@code scriptRemoved} method when the * script has been removed from the cache */ - private class ScriptCacheRemovalListener implements RemovalListener<CacheKey, CompiledScript> { + private class ScriptCacheRemovalListener implements RemovalListener<CacheKey, Object> { @Override - public void onRemoval(RemovalNotification<CacheKey, CompiledScript> notification) { + public void onRemoval(RemovalNotification<CacheKey, Object> notification) { if (logger.isDebugEnabled()) { logger.debug("removed {} from cache, reason: {}", notification.getValue(), notification.getRemovalReason()); } @@ -540,11 +533,13 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust private static final class CacheKey { final String lang; final String idOrCode; + final String context; final Map<String, String> options; - private CacheKey(String lang, String idOrCode, Map<String, String> options) { + private CacheKey(String lang, String idOrCode, String context, Map<String, String> options) { this.lang = lang; this.idOrCode = idOrCode; + this.context = context; this.options = options; } @@ -552,21 +547,16 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - - CacheKey cacheKey = (CacheKey)o; - - if (lang != null ? !lang.equals(cacheKey.lang) : cacheKey.lang != null) return false; - if (!idOrCode.equals(cacheKey.idOrCode)) return false; - return options != null ? options.equals(cacheKey.options) : cacheKey.options == null; - + CacheKey cacheKey = (CacheKey) o; + return Objects.equals(lang, cacheKey.lang) && + Objects.equals(idOrCode, cacheKey.idOrCode) && + Objects.equals(context, cacheKey.context) && + Objects.equals(options, cacheKey.options); } @Override public int hashCode() { - int result = lang != null ? lang.hashCode() : 0; - result = 31 * result + idOrCode.hashCode(); - result = 31 * result + (options != null ? options.hashCode() : 0); - return result; + return Objects.hash(lang, idOrCode, context, options); } } } diff --git a/core/src/main/java/org/elasticsearch/script/SearchScript.java b/core/src/main/java/org/elasticsearch/script/SearchScript.java index 5d5f218763..5758209a48 100644 --- a/core/src/main/java/org/elasticsearch/script/SearchScript.java +++ b/core/src/main/java/org/elasticsearch/script/SearchScript.java @@ -19,8 +19,10 @@ package org.elasticsearch.script; import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.search.lookup.SearchLookup; import java.io.IOException; +import java.util.Map; /** * A search script. @@ -36,4 +38,7 @@ public interface SearchScript { */ boolean needsScores(); + interface Compiled { + SearchScript newInstance(Map<String, Object> params, SearchLookup lookup); + } }
\ No newline at end of file diff --git a/core/src/main/java/org/elasticsearch/search/SearchService.java b/core/src/main/java/org/elasticsearch/search/SearchService.java index a5ad038fd5..7f98a876e9 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchService.java +++ b/core/src/main/java/org/elasticsearch/search/SearchService.java @@ -48,7 +48,6 @@ import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.SearchOperationListener; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.SearchScript; @@ -686,8 +685,8 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv } if (source.scriptFields() != null) { for (org.elasticsearch.search.builder.SearchSourceBuilder.ScriptField field : source.scriptFields()) { - CompiledScript compile = scriptService.compile(field.script(), ScriptContext.SEARCH); - SearchScript searchScript = scriptService.search(context.lookup(), compile, field.script().getParams()); + SearchScript.Compiled compiled = scriptService.compile(field.script(), ScriptContext.SEARCH); + SearchScript searchScript = compiled.newInstance(field.script().getParams(), context.lookup()); context.scriptFields().add(new ScriptField(field.fieldName(), searchScript, field.ignoreFailure())); } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java index b3df54247b..70ccf53200 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java @@ -28,7 +28,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryShardException; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; @@ -93,13 +92,14 @@ public class ScriptHeuristic extends SignificanceHeuristic { @Override public SignificanceHeuristic rewrite(InternalAggregation.ReduceContext context) { - CompiledScript compiledScript = context.scriptService().compile(script, ScriptContext.AGGS); - return new ExecutableScriptHeuristic(script, context.scriptService().executable(compiledScript, script.getParams())); + ExecutableScript.Compiled compiled = context.scriptService().compile(script, ScriptContext.AGGS_EXECUTABLE); + return new ExecutableScriptHeuristic(script, compiled.newInstance(script.getParams())); } @Override public SignificanceHeuristic rewrite(SearchContext context) { - return new ExecutableScriptHeuristic(script, context.getQueryShardContext().getExecutableScript(script, ScriptContext.AGGS)); + return new ExecutableScriptHeuristic(script, + context.getQueryShardContext().getExecutableScript(script, ScriptContext.AGGS_EXECUTABLE)); } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/InternalScriptedMetric.java b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/InternalScriptedMetric.java index 2bedd16ebf..b0a4836a69 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/InternalScriptedMetric.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/InternalScriptedMetric.java @@ -22,7 +22,6 @@ package org.elasticsearch.search.aggregations.metrics.scripted; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; @@ -96,9 +95,9 @@ public class InternalScriptedMetric extends InternalAggregation implements Scrip if (firstAggregation.reduceScript.getParams() != null) { vars.putAll(firstAggregation.reduceScript.getParams()); } - CompiledScript compiledScript = reduceContext.scriptService().compile( - firstAggregation.reduceScript, ScriptContext.AGGS); - ExecutableScript script = reduceContext.scriptService().executable(compiledScript, vars); + ExecutableScript.Compiled compiled = reduceContext.scriptService().compile( + firstAggregation.reduceScript, ScriptContext.AGGS_EXECUTABLE); + ExecutableScript script = compiled.newInstance(vars); aggregation = Collections.singletonList(script.run()); } else if (reduceContext.isFinalReduce()) { aggregation = Collections.singletonList(aggregationObjects); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/ScriptedMetricAggregationBuilder.java b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/ScriptedMetricAggregationBuilder.java index 6d8c297eeb..6865d6a211 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/ScriptedMetricAggregationBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/scripted/ScriptedMetricAggregationBuilder.java @@ -186,15 +186,14 @@ public class ScriptedMetricAggregationBuilder extends AbstractAggregationBuilder QueryShardContext queryShardContext = context.getQueryShardContext(); Function<Map<String, Object>, ExecutableScript> executableInitScript; if (initScript != null) { - executableInitScript = queryShardContext.getLazyExecutableScript(initScript, ScriptContext.AGGS); + executableInitScript = queryShardContext.getLazyExecutableScript(initScript, ScriptContext.AGGS_EXECUTABLE); } else { executableInitScript = (p) -> null; } - Function<Map<String, Object>, SearchScript> searchMapScript = queryShardContext.getLazySearchScript(mapScript, - ScriptContext.AGGS); + Function<Map<String, Object>, SearchScript> searchMapScript = queryShardContext.getLazySearchScript(mapScript, ScriptContext.AGGS); Function<Map<String, Object>, ExecutableScript> executableCombineScript; if (combineScript != null) { - executableCombineScript = queryShardContext.getLazyExecutableScript(combineScript, ScriptContext.AGGS); + executableCombineScript = queryShardContext.getLazyExecutableScript(combineScript, ScriptContext.AGGS_EXECUTABLE); } else { executableCombineScript = (p) -> null; } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketscript/BucketScriptPipelineAggregator.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketscript/BucketScriptPipelineAggregator.java index 46f4fbb237..e81bae2044 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketscript/BucketScriptPipelineAggregator.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketscript/BucketScriptPipelineAggregator.java @@ -21,7 +21,6 @@ package org.elasticsearch.search.aggregations.pipeline.bucketscript; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; @@ -91,7 +90,7 @@ public class BucketScriptPipelineAggregator extends PipelineAggregator { (InternalMultiBucketAggregation<InternalMultiBucketAggregation, InternalMultiBucketAggregation.InternalBucket>) aggregation; List<? extends InternalMultiBucketAggregation.InternalBucket> buckets = originalAgg.getBuckets(); - CompiledScript compiledScript = reduceContext.scriptService().compile(script, ScriptContext.AGGS); + ExecutableScript.Compiled compiledScript = reduceContext.scriptService().compile(script, ScriptContext.AGGS_EXECUTABLE); List<InternalMultiBucketAggregation.InternalBucket> newBuckets = new ArrayList<>(); for (InternalMultiBucketAggregation.InternalBucket bucket : buckets) { Map<String, Object> vars = new HashMap<>(); @@ -112,7 +111,7 @@ public class BucketScriptPipelineAggregator extends PipelineAggregator { if (skipBucket) { newBuckets.add(bucket); } else { - ExecutableScript executableScript = reduceContext.scriptService().executable(compiledScript, vars); + ExecutableScript executableScript = compiledScript.newInstance(vars); Object returned = executableScript.run(); if (returned == null) { newBuckets.add(bucket); diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketselector/BucketSelectorPipelineAggregator.java b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketselector/BucketSelectorPipelineAggregator.java index f5bc5cc4ad..95d371c474 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketselector/BucketSelectorPipelineAggregator.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketselector/BucketSelectorPipelineAggregator.java @@ -22,7 +22,6 @@ package org.elasticsearch.search.aggregations.pipeline.bucketselector; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; @@ -84,7 +83,7 @@ public class BucketSelectorPipelineAggregator extends PipelineAggregator { (InternalMultiBucketAggregation<InternalMultiBucketAggregation, InternalMultiBucketAggregation.InternalBucket>) aggregation; List<? extends InternalMultiBucketAggregation.InternalBucket> buckets = originalAgg.getBuckets(); - CompiledScript compiledScript = reduceContext.scriptService().compile(script, ScriptContext.AGGS); + ExecutableScript.Compiled compiledScript = reduceContext.scriptService().compile(script, ScriptContext.AGGS_EXECUTABLE); List<InternalMultiBucketAggregation.InternalBucket> newBuckets = new ArrayList<>(); for (InternalMultiBucketAggregation.InternalBucket bucket : buckets) { Map<String, Object> vars = new HashMap<>(); @@ -97,7 +96,8 @@ public class BucketSelectorPipelineAggregator extends PipelineAggregator { Double value = resolveBucketValue(originalAgg, bucket, bucketsPath, gapPolicy); vars.put(varName, value); } - ExecutableScript executableScript = reduceContext.scriptService().executable(compiledScript, vars); + // TODO: can we use one instance of the script for all buckets? it should be stateless? + ExecutableScript executableScript = compiledScript.newInstance(vars); Object scriptReturnValue = executableScript.run(); final boolean keepBucket; // TODO: WTF!!!!! diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java index f5a6eca35b..1319679f1a 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java @@ -631,7 +631,7 @@ public class PhraseSuggestionBuilder extends SuggestionBuilder<PhraseSuggestionB if (this.collateQuery != null) { Function<Map<String, Object>, ExecutableScript> compiledScript = context.getLazyExecutableScript(this.collateQuery, - ScriptContext.SEARCH); + ScriptContext.EXECUTABLE); suggestionContext.setCollateQueryScript(compiledScript); if (this.collateParams != null) { suggestionContext.setCollateScriptParams(this.collateParams); diff --git a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java index 99e2e18496..31dcc22bec 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionContext.java @@ -23,7 +23,6 @@ import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Terms; import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.search.suggest.DirectSpellcheckerSettings; import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext; diff --git a/core/src/main/java/org/elasticsearch/template/CompiledTemplate.java b/core/src/main/java/org/elasticsearch/template/CompiledTemplate.java index 380c36a590..d03993583c 100644 --- a/core/src/main/java/org/elasticsearch/template/CompiledTemplate.java +++ b/core/src/main/java/org/elasticsearch/template/CompiledTemplate.java @@ -21,10 +21,6 @@ package org.elasticsearch.template; import java.util.Map; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.script.CompiledScript; -import org.elasticsearch.script.ScriptType; - /** * A template that may be executed. */ diff --git a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java index cdd939cf60..79241781b0 100644 --- a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java +++ b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java @@ -51,7 +51,7 @@ public class ScriptServiceTests extends ESTestCase { private ScriptEngine scriptEngine; private Map<String, ScriptEngine> engines; - private Map<String, ScriptContext> contexts; + private Map<String, ScriptContext<?,?>> contexts; private ScriptService scriptService; private Settings baseSettings; @@ -123,11 +123,10 @@ public class ScriptServiceTests extends ESTestCase { public void testInlineScriptCompiledOnceCache() throws IOException { buildScriptService(Settings.EMPTY); - CompiledScript compiledScript1 = scriptService.compile(new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()), - randomFrom(contexts.values())); - CompiledScript compiledScript2 = scriptService.compile(new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()), - randomFrom(contexts.values())); - assertThat(compiledScript1.compiled(), sameInstance(compiledScript2.compiled())); + Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()); + SearchScript.Compiled compiledScript1 = scriptService.compile(script, ScriptContext.SEARCH); + SearchScript.Compiled compiledScript2 = scriptService.compile(script, ScriptContext.SEARCH); + assertThat(compiledScript1, sameInstance(compiledScript2)); } public void testAllowAllScriptTypeSettings() throws IOException { @@ -199,22 +198,6 @@ public class ScriptServiceTests extends ESTestCase { assertEquals(1L, scriptService.stats().getCompilations()); } - public void testExecutableCountedInCompilationStats() throws IOException { - buildScriptService(Settings.EMPTY); - Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()); - CompiledScript compiledScript = scriptService.compile(script, randomFrom(contexts.values())); - scriptService.executable(compiledScript, script.getParams()); - assertEquals(1L, scriptService.stats().getCompilations()); - } - - public void testSearchCountedInCompilationStats() throws IOException { - buildScriptService(Settings.EMPTY); - Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()); - CompiledScript compile = scriptService.compile(script, randomFrom(contexts.values())); - scriptService.search(null, compile, script.getParams()); - assertEquals(1L, scriptService.stats().getCompilations()); - } - public void testMultipleCompilationsCountedInCompilationStats() throws IOException { buildScriptService(Settings.EMPTY); int numberOfCompilations = randomIntBetween(1, 20); @@ -230,8 +213,9 @@ public class ScriptServiceTests extends ESTestCase { builder.put(ScriptService.SCRIPT_CACHE_SIZE_SETTING.getKey(), 1); buildScriptService(builder.build()); Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()); - scriptService.compile(script, randomFrom(contexts.values())); - scriptService.compile(script, randomFrom(contexts.values())); + ScriptContext<?, ?> context = randomFrom(contexts.values()); + scriptService.compile(script, context); + scriptService.compile(script, context); assertEquals(1L, scriptService.stats().getCompilations()); } @@ -251,14 +235,6 @@ public class ScriptServiceTests extends ESTestCase { assertEquals(1L, scriptService.stats().getCacheEvictions()); } - public void testDefaultLanguage() throws IOException { - Settings.Builder builder = Settings.builder(); - buildScriptService(builder.build()); - CompiledScript script = scriptService.compile( - new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG, "1+1", Collections.emptyMap()), randomFrom(contexts.values())); - assertEquals(script.lang(), Script.DEFAULT_SCRIPT_LANG); - } - public void testStoreScript() throws Exception { BytesReference script = XContentFactory.jsonBuilder().startObject() .field("script", "abc") diff --git a/core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java b/core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java index 8711e9ef3d..d27a297926 100644 --- a/core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java +++ b/core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java @@ -30,7 +30,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.ScriptPlugin; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ExplainableSearchScript; import org.elasticsearch.script.LeafSearchScript; @@ -84,12 +83,12 @@ public class ExplainableScriptIT extends ESIntegTestCase { } @Override - public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) { + public ExecutableScript executable(Object compiledScript, @Nullable Map<String, Object> vars) { throw new UnsupportedOperationException(); } @Override - public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars) { + public SearchScript search(Object compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars) { return new SearchScript() { @Override public LeafSearchScript getLeafSearchScript(LeafReaderContext context) throws IOException { diff --git a/core/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java b/core/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java index b11d6ce07a..1327af8f3e 100644 --- a/core/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java +++ b/core/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java @@ -25,13 +25,11 @@ import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.search.SearchPhaseExecutionException; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.ScriptPlugin; -import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ScriptEngine; import org.elasticsearch.script.SearchScript; @@ -1032,8 +1030,8 @@ public class SuggestSearchIT extends ESIntegTestCase { } @Override - public ExecutableScript executable(CompiledScript compiledScript, Map<String, Object> params) { - String script = (String) compiledScript.compiled(); + public ExecutableScript executable(Object compiledScript, Map<String, Object> params) { + String script = (String) compiledScript; for (Entry<String, Object> entry : params.entrySet()) { script = script.replace("{{" + entry.getKey() + "}}", String.valueOf(entry.getValue())); } @@ -1052,7 +1050,7 @@ public class SuggestSearchIT extends ESIntegTestCase { } @Override - public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, Map<String, Object> vars) { + public SearchScript search(Object compiledScript, SearchLookup lookup, Map<String, Object> vars) { throw new UnsupportedOperationException("search script not supported"); } } |