SOLR-12888: Run URP now auto-registers NestedUpdateProcessor before it.
authorDavid Smiley <dsmiley@apache.org>
Wed, 9 Jan 2019 04:23:02 +0000 (23:23 -0500)
committerDavid Smiley <dsmiley@apache.org>
Wed, 9 Jan 2019 04:23:02 +0000 (23:23 -0500)
solr/CHANGES.txt
solr/core/src/java/org/apache/solr/core/SolrCore.java
solr/core/src/java/org/apache/solr/update/processor/LogUpdateProcessorFactory.java
solr/core/src/java/org/apache/solr/update/processor/NoOpDistributingUpdateProcessorFactory.java
solr/core/src/java/org/apache/solr/update/processor/RunUpdateProcessorFactory.java
solr/core/src/java/org/apache/solr/update/processor/UpdateRequestProcessorChain.java
solr/core/src/test-files/solr/collection1/conf/solrconfig-update-processor-chains.xml
solr/core/src/test/org/apache/solr/response/transform/TestChildDocTransformerHierarchy.java
solr/core/src/test/org/apache/solr/update/TestNestedUpdateProcessor.java

index 39c0239..04d71eb 100644 (file)
@@ -136,6 +136,11 @@ Improvements
   'status' field, a 'message' field giving more details on the error, and an optional 'exception' field.  (Shalin Mangar,
   Jason Gerlowski)
 
+* SOLR-12888: The NestedUpdateProcessor (which populates internal fields for nested child docs) is now auto-registered
+  to run immediately prior to RunUpdateProcessor.  If the schema has no _nest_*_ fields then it's a no-op.
+  RunUpdateProcessorFactory looks up a special/internal URP chain "_preRun_" which is implicitly defined but could be
+  defined by an app for customization if desired.  (David Smiley)
+
 Optimizations
 ----------------------
 
index b64a6c6..95342c3 100644 (file)
@@ -152,6 +152,7 @@ import org.apache.solr.update.UpdateHandler;
 import org.apache.solr.update.VersionInfo;
 import org.apache.solr.update.processor.DistributedUpdateProcessorFactory;
 import org.apache.solr.update.processor.LogUpdateProcessorFactory;
+import org.apache.solr.update.processor.NestedUpdateProcessorFactory;
 import org.apache.solr.update.processor.RunUpdateProcessorFactory;
 import org.apache.solr.update.processor.UpdateRequestProcessorChain;
 import org.apache.solr.update.processor.UpdateRequestProcessorChain.ProcessorInfo;
@@ -1434,7 +1435,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
   /**
    * Load the request processors
    */
-   private Map<String,UpdateRequestProcessorChain> loadUpdateProcessorChains() {
+  private Map<String,UpdateRequestProcessorChain> loadUpdateProcessorChains() {
     Map<String, UpdateRequestProcessorChain> map = new HashMap<>();
     UpdateRequestProcessorChain def = initPlugins(map,UpdateRequestProcessorChain.class, UpdateRequestProcessorChain.class.getName());
     if(def == null){
@@ -1452,6 +1453,10 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
     }
     map.put(null, def);
     map.put("", def);
+
+    map.computeIfAbsent(RunUpdateProcessorFactory.PRE_RUN_CHAIN_NAME,
+        k -> new UpdateRequestProcessorChain(Collections.singletonList(new NestedUpdateProcessorFactory()), this));
+
     return map;
   }
 
index 06057f2..a668816 100644 (file)
@@ -62,7 +62,7 @@ public class LogUpdateProcessorFactory extends UpdateRequestProcessorFactory imp
 
   @Override
   public UpdateRequestProcessor getInstance(SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next) {
-    return log.isInfoEnabled() ? new LogUpdateProcessor(req, rsp, this, next) : null;
+    return log.isInfoEnabled() ? new LogUpdateProcessor(req, rsp, this, next) : next;
   }
   
   static class LogUpdateProcessor extends UpdateRequestProcessor {
index 4a0ef6c..da3e142 100644 (file)
@@ -21,7 +21,7 @@ import org.apache.solr.response.SolrQueryResponse;
 
 /**
  * A No-Op implementation of DistributingUpdateProcessorFactory that 
- * allways returns null.
+ * allways returns the next processor instead of inserting a new URP in front of it.
  * <p> 
  * This implementation may be useful for Solr installations in which neither 
  * the <code>{@link DistributedUpdateProcessorFactory}</code> nor any custom 
@@ -34,12 +34,12 @@ public class NoOpDistributingUpdateProcessorFactory
   extends UpdateRequestProcessorFactory 
   implements DistributingUpdateProcessorFactory {    
 
-  /** Returns null 
+  /** Returns the next
    */
   @Override
   public UpdateRequestProcessor getInstance(SolrQueryRequest req, 
                                             SolrQueryResponse rsp, 
                                             UpdateRequestProcessor next ) {
-    return null;
+    return next;
   }
 }
index 6f59abc..d49ab27 100644 (file)
@@ -35,10 +35,19 @@ import org.apache.solr.update.*;
  */
 public class RunUpdateProcessorFactory extends UpdateRequestProcessorFactory 
 {
+
+  public static final String PRE_RUN_CHAIN_NAME = "_preRun_";
+
   @Override
   public UpdateRequestProcessor getInstance(SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next) 
   {
-    return new RunUpdateProcessor(req, next);
+    RunUpdateProcessor runUpdateProcessor = new RunUpdateProcessor(req, next);
+    UpdateRequestProcessorChain preRun = req.getCore().getUpdateProcessingChain(PRE_RUN_CHAIN_NAME);
+    if (preRun != null) {
+      return preRun.createProcessor(req, rsp, false, runUpdateProcessor);
+    } else {
+      return runUpdateProcessor;
+    }
   }
 }
 
index 646c92e..eb3c08b 100644 (file)
@@ -180,7 +180,6 @@ public final class UpdateRequestProcessorChain implements PluginInfoInitialized
     this.solrCore =  solrCore;
   }
 
-
   /**
    * Uses the factories in this chain to creates a new 
    * <code>UpdateRequestProcessor</code> instance specific for this request.  
@@ -193,13 +192,17 @@ public final class UpdateRequestProcessorChain implements PluginInfoInitialized
    * @see DistributingUpdateProcessorFactory#DISTRIB_UPDATE_PARAM
    */
   public UpdateRequestProcessor createProcessor(SolrQueryRequest req, 
-                                                SolrQueryResponse rsp) 
-  {
-    UpdateRequestProcessor processor = null;
-    UpdateRequestProcessor last = null;
-    
+                                                SolrQueryResponse rsp) {
     final String distribPhase = req.getParams().get(DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM);
     final boolean skipToDistrib = distribPhase != null;
+    return createProcessor(req, rsp, skipToDistrib, null);
+  }
+
+  /**
+   * @lucene.internal
+   */
+  public UpdateRequestProcessor createProcessor(SolrQueryRequest req,
+                                                SolrQueryResponse rsp, boolean skipToDistrib, UpdateRequestProcessor last) {
     boolean afterDistrib = true;  // we iterate backwards, so true to start
 
     for (int i = chain.size() - 1; i >= 0; i--) {
@@ -216,8 +219,8 @@ public final class UpdateRequestProcessorChain implements PluginInfoInitialized
         }
       }
 
-      processor = factory.getInstance(req, rsp, last);
-      last = processor == null ? last : processor;
+      // create a new URP with current "last" following it; then replace "last" with this new URP
+      last = factory.getInstance(req, rsp, last);
     }
 
     return last;
@@ -242,7 +245,7 @@ public final class UpdateRequestProcessorChain implements PluginInfoInitialized
     //port-processor is tried to be inserted before RunUpdateProcessor
     insertBefore(urps, post, RunUpdateProcessorFactory.class, urps.size() - 1);
     UpdateRequestProcessorChain result = new UpdateRequestProcessorChain(urps, core);
-    if (log.isInfoEnabled()) {
+    if (log.isDebugEnabled()) {
       ArrayList<String> names = new ArrayList<>(urps.size());
       for (UpdateRequestProcessorFactory urp : urps) names.add(urp.getClass().getSimpleName());
       log.debug("New dynamic chain constructed : " + StrUtils.join(names, '>'));
index 01e1a5f..e22ad69 100644 (file)
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 
-  <updateRequestProcessorChain name="nested">
-    <processor class="solr.NestedUpdateProcessorFactory" />
-    <processor class="solr.RunUpdateProcessorFactory" />
-  </updateRequestProcessorChain>
-
   <updateRequestProcessorChain name="comprehensive">
     <processor class="solr.FieldLengthUpdateProcessorFactory">
       <arr name="typeClass">
index b3d9372..e37f31d 100644 (file)
@@ -48,14 +48,14 @@ public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-update-processor-chains.xml", "schema-nest.xml"); // use "nest" schema
+    initCore("solrconfig-minimal.xml", "schema-nest.xml"); // use "nest" schema
 
     if(random().nextBoolean()) {
       idCounter.set(-100); // start docIDs at -100 for these random docs we don't care about (all less than 0)
       // create random segments
       final int numOfDocs = 10;
       for(int i = 0; i < numOfDocs; ++i) {
-        updateJ(generateDocHierarchy(i), params("update.chain", "nested"));
+        updateJ(generateDocHierarchy(i), null);
         if(random().nextBoolean()) {
           assertU(commit());
         }
@@ -287,7 +287,7 @@ public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
             "}\n" +
           "}\n" +
         "}";
-    updateJ(addDocWoChildren, params("update.chain", "nested"));
+    updateJ(addDocWoChildren, null);
     assertU(commit());
 
     assertJQ(req("q", "type_s:cake",
@@ -299,7 +299,7 @@ public class TestChildDocTransformerHierarchy extends SolrTestCaseJ4 {
 
   private void indexSampleData(int numDocs) throws Exception {
     for(int i = 0; i < numDocs; ++i) {
-      updateJ(generateDocHierarchy(i), params("update.chain", "nested"));
+      updateJ(generateDocHierarchy(i), null);
     }
     assertU(commit());
   }
index b386485..a1aa546 100644 (file)
@@ -90,7 +90,7 @@ public class TestNestedUpdateProcessor extends SolrTestCaseJ4 {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-update-processor-chains.xml", "schema-nest.xml");
+    initCore("solrconfig-minimal.xml", "schema-nest.xml");
   }
 
   @Before
@@ -189,7 +189,7 @@ public class TestNestedUpdateProcessor extends SolrTestCaseJ4 {
   }
 
   private void indexSampleData(String cmd) throws Exception {
-    updateJ(cmd, params("update.chain", "nested"));
+    updateJ(cmd, null);
     assertU(commit());
   }
 }