From 0db73761b98b664334602a595464dbe93e077b73 Mon Sep 17 00:00:00 2001 From: John Montgomery Date: Mon, 21 Nov 2022 17:00:39 +0000 Subject: [PATCH] Cache IndexSchema on SchemaSimilarityFactory to avoid NPE with shared schemas Using true means that a single SchemaSimilarityFactory would be shared between multiple cores. Therefore inform(SolrCore) would be called multiple times. This leads to a race condition when the Similarity object is being used for query at the same time as a new core is being loaded. This results in a NullPointerException as the new SolrCore is not yet fully initialised. --- .../similarities/SchemaSimilarityFactory.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java b/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java index e682b9ee5bd8..71d1d29dc174 100644 --- a/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java +++ b/solr/core/src/java/org/apache/solr/search/similarities/SchemaSimilarityFactory.java @@ -26,6 +26,7 @@ import org.apache.solr.common.params.SolrParams; import org.apache.solr.core.SolrCore; import org.apache.solr.schema.FieldType; +import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.SimilarityFactory; import org.apache.solr.util.plugin.SolrCoreAware; @@ -137,14 +138,16 @@ public Similarity getSimilarity() { private class SchemaSimilarity extends PerFieldSimilarityWrapper { private Similarity defaultSimilarity; + private volatile IndexSchema schema; public SchemaSimilarity(Similarity defaultSimilarity) { this.defaultSimilarity = defaultSimilarity; + schema = core.getLatestSchema(); } @Override public Similarity get(String name) { - FieldType fieldType = core.getLatestSchema().getFieldTypeNoEx(name); + FieldType fieldType = getSchema().getFieldTypeNoEx(name); if (fieldType == null) { return defaultSimilarity; } else { @@ -153,6 +156,17 @@ public Similarity get(String name) { } } + private IndexSchema getSchema() { + // if we're using shareSchema in our config we might actually have an uninitialised + // SolrCore, so we cache the old schema to bridge the gap, but otherwise + // defer to the core itself (in case the schema changes) + IndexSchema latestSchema = core.getLatestSchema(); + if (latestSchema != null && schema != latestSchema) { + schema = latestSchema; + } + return schema; + } + @Override public String toString() { return "SchemaSimilarity. Default: " + ((get("") == null) ? "null" : get("").toString());