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");
+ }
+ }
}