diff --git a/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java b/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java index 83a20e03ffe..384331c2d9e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java @@ -94,7 +94,6 @@ public abstract class Mapper implements ToXContent, Iterable { private final ParseFieldMatcher parseFieldMatcher; private final Supplier queryShardContextSupplier; - private QueryShardContext queryShardContext; public ParserContext(String type, IndexAnalyzers indexAnalyzers, Function similarityLookupService, MapperService mapperService, Function typeParsers, @@ -138,12 +137,8 @@ public abstract class Mapper implements ToXContent, Iterable { return parseFieldMatcher; } - public QueryShardContext queryShardContext() { - // No need for synchronization, this class must be used in a single thread - if (queryShardContext == null) { - queryShardContext = queryShardContextSupplier.get(); - } - return queryShardContext; + public Supplier queryShardContextSupplier() { + return queryShardContextSupplier; } public boolean isWithinMultiField() { return false; } @@ -161,7 +156,7 @@ public abstract class Mapper implements ToXContent, Iterable { static class MultiFieldParserContext extends ParserContext { MultiFieldParserContext(ParserContext in) { - super(in.type(), in.indexAnalyzers, in.similarityLookupService(), in.mapperService(), in.typeParsers(), in.indexVersionCreated(), in.parseFieldMatcher(), in::queryShardContext); + super(in.type(), in.indexAnalyzers, in.similarityLookupService(), in.mapperService(), in.typeParsers(), in.indexVersionCreated(), in.parseFieldMatcher(), in.queryShardContextSupplier()); } } diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java index 8fcf40d8dcc..dd148e8d6d7 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java @@ -69,6 +69,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Supplier; public class PercolatorFieldMapper extends FieldMapper { @@ -89,9 +90,9 @@ public class PercolatorFieldMapper extends FieldMapper { public static class Builder extends FieldMapper.Builder { - private final QueryShardContext queryShardContext; + private final Supplier queryShardContext; - public Builder(String fieldName, QueryShardContext queryShardContext) { + public Builder(String fieldName, Supplier queryShardContext) { super(fieldName, FIELD_TYPE, FIELD_TYPE); this.queryShardContext = queryShardContext; } @@ -136,7 +137,7 @@ public class PercolatorFieldMapper extends FieldMapper { @Override public Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - return new Builder(name, parserContext.queryShardContext()); + return new Builder(name, parserContext.queryShardContextSupplier()); } } @@ -222,23 +223,44 @@ public class PercolatorFieldMapper extends FieldMapper { } private final boolean mapUnmappedFieldAsString; - private final QueryShardContext queryShardContext; + private final Supplier queryShardContext; private KeywordFieldMapper queryTermsField; private KeywordFieldMapper extractionResultField; private BinaryFieldMapper queryBuilderField; public PercolatorFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType, - Settings indexSettings, MultiFields multiFields, CopyTo copyTo, QueryShardContext queryShardContext, + Settings indexSettings, MultiFields multiFields, CopyTo copyTo, + Supplier queryShardContext, KeywordFieldMapper queryTermsField, KeywordFieldMapper extractionResultField, BinaryFieldMapper queryBuilderField) { super(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, copyTo); - this.queryShardContext = queryShardContext; + this.queryShardContext = new QueryShardContextSupplierCache(queryShardContext); this.queryTermsField = queryTermsField; this.extractionResultField = extractionResultField; this.queryBuilderField = queryBuilderField; this.mapUnmappedFieldAsString = INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING.get(indexSettings); } + private static class QueryShardContextSupplierCache implements Supplier { + private final Supplier supplier; + private volatile QueryShardContext context; + + QueryShardContextSupplierCache(Supplier supplier) { + this.supplier = supplier; + } + + @Override + public QueryShardContext get() { + QueryShardContext context = this.context; + if (context == null) { + context = this.context = supplier.get(); + } + // return a copy + return new QueryShardContext(context); + } + + } + @Override public FieldMapper updateFieldType(Map fullNameToFieldType) { PercolatorFieldMapper updated = (PercolatorFieldMapper) super.updateFieldType(fullNameToFieldType); @@ -261,7 +283,7 @@ public class PercolatorFieldMapper extends FieldMapper { @Override public Mapper parse(ParseContext context) throws IOException { - QueryShardContext queryShardContext = new QueryShardContext(this.queryShardContext); + QueryShardContext queryShardContext = this.queryShardContext.get(); if (context.doc().getField(queryBuilderField.name()) != null) { // If a percolator query has been defined in an array object then multiple percolator queries // could be provided. In order to prevent this we fail if we try to parse more than one query