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

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


The following commit(s) were added to refs/heads/main by this push:
     new 57200fc5cf9 SOLR-18125 Make LukeRequestHandler::getFirstLiveDoc get 
the first live doc (#4157)
57200fc5cf9 is described below

commit 57200fc5cf99d4ab271052658fec2bd21310a24f
Author: Luke Kot-Zaniewski <[email protected]>
AuthorDate: Fri Mar 20 21:22:23 2026 -0400

    SOLR-18125 Make LukeRequestHandler::getFirstLiveDoc get the first live doc 
(#4157)
    
    Fix getFirstLiveDoc so it returns the first live doc. Previously it would 
often return nothing resulting in missing index flags in /admin/luke response.
---
 .../unreleased/PR#4157-fix-getFirstLiveDoc.yml     |  9 ++++
 .../solr/handler/admin/LukeRequestHandler.java     |  4 +-
 .../solr/handler/admin/LukeRequestHandlerTest.java | 55 ++++++++++++++++++++++
 3 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/changelog/unreleased/PR#4157-fix-getFirstLiveDoc.yml 
b/changelog/unreleased/PR#4157-fix-getFirstLiveDoc.yml
new file mode 100644
index 00000000000..9c744a6b83c
--- /dev/null
+++ b/changelog/unreleased/PR#4157-fix-getFirstLiveDoc.yml
@@ -0,0 +1,9 @@
+title: Fix getFirstLiveDoc so it returns the first live doc. Previously it 
would often return nothing resulting in missing index flags in /admin/luke 
response.
+type: fixed # added, changed, fixed, deprecated, removed, dependency_update, 
security, other
+authors:
+  - name: Luke Kot-Zaniewski
+links:
+  - name: SOLR-18125
+    url: https://issues.apache.org/jira/browse/SOLR-18125
+
+
diff --git 
a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java 
b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
index e3d07b1cbca..b5879024d10 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
@@ -472,7 +472,7 @@ public class LukeRequestHandler extends RequestHandlerBase {
     StoredFields storedFields = reader.storedFields();
     // Deal with the chance that the first bunch of terms are in deleted 
documents. Is there a
     // better way?
-    for (int idx = 0; idx < 1000 && postingsEnum == null; ++idx) {
+    for (int idx = 0; idx < 1000; ++idx) {
       text = termsEnum.next();
       // Ran off the end of the terms enum without finding any live docs with 
that field in them.
       if (text == null) {
@@ -481,7 +481,7 @@ public class LukeRequestHandler extends RequestHandlerBase {
       postingsEnum = termsEnum.postings(postingsEnum, PostingsEnum.NONE);
       final Bits liveDocs = reader.getLiveDocs();
       if (postingsEnum.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) {
-        if (liveDocs != null && liveDocs.get(postingsEnum.docID())) {
+        if (liveDocs != null && !liveDocs.get(postingsEnum.docID())) {
           continue;
         }
         return storedFields.document(postingsEnum.docID());
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java 
b/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java
index 02d7066d215..5fa90f325a8 100644
--- 
a/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java
+++ 
b/solr/core/src/test/org/apache/solr/handler/admin/LukeRequestHandlerTest.java
@@ -20,6 +20,7 @@ import java.util.Arrays;
 import java.util.EnumSet;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.luke.FieldFlag;
+import org.apache.solr.index.NoMergePolicyFactory;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.CustomAnalyzerStrField;
 import org.apache.solr.schema.IndexSchema;
@@ -294,4 +295,58 @@ public class LukeRequestHandlerTest extends SolrTestCaseJ4 
{
     deleteCore();
     initCore("solrconfig.xml", "schema12.xml");
   }
+
+  /**
+   * SOLR-18125: Tests that Luke reports index flags for fields even when a 
document has been
+   * deleted. Uses NoMergePolicy so the deleted doc remains in the same 
segment, keeping liveDocs
+   * non-null and exposing the inverted liveDocs check in getFirstLiveDoc.
+   */
+  @Test
+  public void testIndexFlagsWithDeletedDocs() throws Exception {
+    deleteCore();
+    
systemSetPropertySolrTestsMergePolicyFactory(NoMergePolicyFactory.class.getName());
+    try {
+      initCore("solrconfig.xml", "schema12.xml");
+
+      // Three docs in a single commit so they share one segment. Delete the 
middle term
+      // ("bbb") and keep the lexical edges ("aaa" and "ccc") live, so the 
first term
+      // encountered is always a live doc regardless of ascending or 
descending iteration.
+      // The bug's inverted liveDocs check skips live docs, so getFirstLiveDoc 
returns null
+      // and index flags go missing.
+      assertU(adoc("id", "1", "solr_s", "aaa"));
+      assertU(adoc("id", "2", "solr_s", "bbb"));
+      assertU(adoc("id", "3", "solr_s", "ccc"));
+      assertU(commit());
+
+      assertU(delI("2"));
+      assertU(commit());
+
+      assertQ(
+          "index flags should be present for solr_s despite deletion in 
segment",
+          req("qt", "/admin/luke", "fl", "solr_s"),
+          getFieldXPathPrefix("solr_s") + "[@name='index']");
+
+      // Now test the inverse: delete the edges and keep the middle. The first 
term
+      // encountered ("aaa" or "ccc") is deleted, so getFirstLiveDoc must skip 
it and
+      // continue to the live term ("bbb"). This exercises the retry loop — 
without it,
+      // the method gives up after the first deleted term.
+      clearIndex();
+      assertU(adoc("id", "4", "solr_s", "aaa"));
+      assertU(adoc("id", "5", "solr_s", "bbb"));
+      assertU(adoc("id", "6", "solr_s", "ccc"));
+      assertU(commit());
+
+      assertU(delI("4"));
+      assertU(delI("6"));
+      assertU(commit());
+
+      assertQ(
+          "index flags should be present for solr_s when edges are deleted",
+          req("qt", "/admin/luke", "fl", "solr_s"),
+          getFieldXPathPrefix("solr_s") + "[@name='index']");
+    } finally {
+      deleteCore();
+      initCore("solrconfig.xml", "schema12.xml");
+    }
+  }
 }

Reply via email to