This is an automated email from the ASF dual-hosted git repository.

gerlowskija pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new a15e6f42785 SOLR-17413: ulog replay should copy SolrQueryRequest 
(#2765)
a15e6f42785 is described below

commit a15e6f4278523f2a23ad35246fe7e34bf531e12f
Author: Jason Gerlowski <[email protected]>
AuthorDate: Mon Oct 28 11:12:18 2024 -0700

    SOLR-17413: ulog replay should copy SolrQueryRequest (#2765)
    
    SolrQueryRequest is a non-threadsafe type, but was being shared across
    executor threads during UpdateLog replay.  This introduces a number of
    issues, not the least being a ConcurrentModificationException if
    multiple threads happen to tweak the request 'context' simultaneously.
    
    This commit fixes this issue by giving each executor thread a unique
    LocalSolrQueryRequest instance to use.
---
 solr/CHANGES.txt                                      |  2 ++
 .../src/java/org/apache/solr/update/UpdateLog.java    | 19 ++++++++++++++-----
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index f8dc0b18a98..7adc0afa5c8 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -81,6 +81,8 @@ Bug Fixes
 
 * SOLR-17464: Fixed Http2SolrClient bug in that 'requestAsync' triggered NPE 
when using a shared Jetty client (Jason Gerlowski, James Dyer)
 
+* SOLR-17413: Fixed UpdateLog replay bug that shared thread-unsafe 
SolrQueryRequest objects across threads (Jason Gerlowski, David Smiley, Houston 
Putman)
+
 Dependency Upgrades
 ---------------------
 (No changes)
diff --git a/solr/core/src/java/org/apache/solr/update/UpdateLog.java 
b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
index 9bc685f276b..d1c430bceee 100644
--- a/solr/core/src/java/org/apache/solr/update/UpdateLog.java
+++ b/solr/core/src/java/org/apache/solr/update/UpdateLog.java
@@ -63,6 +63,7 @@ import org.apache.solr.common.SolrDocumentBase;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.CollectionUtil;
@@ -1998,6 +1999,14 @@ public class UpdateLog implements PluginInfoInitialized, 
SolrMetricProducer {
   protected RecoveryInfo recoveryInfo;
 
   class LogReplayer implements Runnable {
+    private final SolrParams BASE_REPLAY_PARAMS =
+        new MapSolrParams(
+            Map.of(
+                DISTRIB_UPDATE_PARAM,
+                FROMLEADER.toString(),
+                DistributedUpdateProcessor.LOG_REPLAY,
+                "true"));
+
     private Logger loglog = log; // set to something different?
 
     Deque<TransactionLog> translogs;
@@ -2024,10 +2033,7 @@ public class UpdateLog implements PluginInfoInitialized, 
SolrMetricProducer {
 
     @Override
     public void run() {
-      ModifiableSolrParams params = new ModifiableSolrParams();
-      params.set(DISTRIB_UPDATE_PARAM, FROMLEADER.toString());
-      params.set(DistributedUpdateProcessor.LOG_REPLAY, "true");
-      req = new LocalSolrQueryRequest(uhandler.core, params);
+      req = new LocalSolrQueryRequest(uhandler.core, BASE_REPLAY_PARAMS);
       rsp = new SolrQueryResponse();
       // setting request info will help logging
       SolrRequestInfo.setRequestInfo(new SolrRequestInfo(req, rsp));
@@ -2100,7 +2106,10 @@ public class UpdateLog implements PluginInfoInitialized, 
SolrMetricProducer {
         ThreadLocal<UpdateRequestProcessor> procThreadLocal =
             ThreadLocal.withInitial(
                 () -> {
-                  var proc = processorChain.createProcessor(req, rsp);
+                  // SolrQueryRequest is not thread-safe, so use a copy when 
creating URPs
+                  final var localRequest =
+                      new LocalSolrQueryRequest(uhandler.core, 
BASE_REPLAY_PARAMS);
+                  var proc = processorChain.createProcessor(localRequest, rsp);
                   procPool.add(proc);
                   return proc;
                 });

Reply via email to