You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by jp...@apache.org on 2017/03/30 13:45:59 UTC

[1/3] lucene-solr:master: LUCENE-7755: Join queries should not reference IndexReaders.

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_6_5 4d3e94bef -> 3a0c2a691
  refs/heads/branch_6x 09373aaa0 -> bd2ec8e40
  refs/heads/master edcdc3052 -> edafcbad1


LUCENE-7755: Join queries should not reference IndexReaders.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/edafcbad
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/edafcbad
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/edafcbad

Branch: refs/heads/master
Commit: edafcbad14482f3cd2f072fdca0c89600e72885d
Parents: edcdc30
Author: Adrien Grand <jp...@gmail.com>
Authored: Thu Mar 30 15:11:52 2017 +0200
Committer: Adrien Grand <jp...@gmail.com>
Committed: Thu Mar 30 15:11:52 2017 +0200

----------------------------------------------------------------------
 lucene/CHANGES.txt                                  |  7 +++++++
 .../org/apache/lucene/index/IndexReaderContext.java | 10 +++++++++-
 .../lucene/search/join/GlobalOrdinalsQuery.java     | 16 ++++++++++------
 .../search/join/GlobalOrdinalsWithScoreQuery.java   | 16 ++++++++++------
 .../org/apache/lucene/search/join/JoinUtil.java     |  8 +++-----
 5 files changed, 39 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/edafcbad/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 92f01a9..da643ff 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -93,6 +93,13 @@ Other
 * LUCENE-7743: Never call new String(String).
   (Daniel Jelinski via Adrien Grand)
 
+======================= Lucene 6.5.1 =======================
+
+Bug Fixes
+
+* LUCENE-7755: Fixed join queries to not reference IndexReaders, as it could
+  cause leaks if they are cached. (Adrien Grand)
+
 ======================= Lucene 6.5.0 =======================
 
 API Changes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/edafcbad/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java b/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
index dada3ff..bca7a14 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
@@ -46,7 +46,15 @@ public abstract class IndexReaderContext {
     this.ordInParent = ordInParent;
     this.isTopLevel = parent==null;
   }
-  
+
+  /** Expert: Return an {@link Object} that uniquely identifies this context.
+   *  The returned object does neither reference this {@link IndexReaderContext}
+   *  nor the wrapped {@link IndexReader}.
+   *  @lucene.experimental */
+  public Object id() {
+    return identity;
+  }
+
   /** Returns the {@link IndexReader}, this context represents. */
   public abstract IndexReader reader();
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/edafcbad/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
index 93edcc0..5aaca1a 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.util.Set;
 
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.SortedDocValues;
@@ -48,19 +48,23 @@ final class GlobalOrdinalsQuery extends Query {
 
   // just for hashcode and equals:
   private final Query fromQuery;
-  private final IndexReader indexReader;
+  // id of the context rather than the context itself in order not to hold references to index readers
+  private final Object indexReaderContextId;
 
-  GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReader indexReader) {
+  GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReaderContext context) {
     this.foundOrds = foundOrds;
     this.joinField = joinField;
     this.globalOrds = globalOrds;
     this.toQuery = toQuery;
     this.fromQuery = fromQuery;
-    this.indexReader = indexReader;
+    this.indexReaderContextId = context.id();
   }
 
   @Override
   public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+    if (searcher.getTopReaderContext().id() != indexReaderContextId) {
+      throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
+    }
     return new W(this, toQuery.createWeight(searcher, false, 1f), boost);
   }
 
@@ -74,7 +78,7 @@ final class GlobalOrdinalsQuery extends Query {
     return fromQuery.equals(other.fromQuery) &&
            joinField.equals(other.joinField) &&
            toQuery.equals(other.toQuery) &&
-           indexReader.equals(other.indexReader);
+           indexReaderContextId.equals(other.indexReaderContextId);
   }
 
   @Override
@@ -83,7 +87,7 @@ final class GlobalOrdinalsQuery extends Query {
     result = 31 * result + joinField.hashCode();
     result = 31 * result + toQuery.hashCode();
     result = 31 * result + fromQuery.hashCode();
-    result = 31 * result + indexReader.hashCode();
+    result = 31 * result + indexReaderContextId.hashCode();
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/edafcbad/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
index 0aedf35..5e614ea 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.util.Set;
 
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.SortedDocValues;
@@ -48,9 +48,10 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
   private final Query fromQuery;
   private final int min;
   private final int max;
-  private final IndexReader indexReader;
+  // id of the context rather than the context itself in order not to hold references to index readers
+  private final Object indexReaderContextId;
 
-  GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReader indexReader) {
+  GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReaderContext context) {
     this.collector = collector;
     this.joinField = joinField;
     this.globalOrds = globalOrds;
@@ -58,11 +59,14 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
     this.fromQuery = fromQuery;
     this.min = min;
     this.max = max;
-    this.indexReader = indexReader;
+    this.indexReaderContextId = context.id();
   }
 
   @Override
   public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+    if (searcher.getTopReaderContext().id() != indexReaderContextId) {
+      throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
+    }
     return new W(this, toQuery.createWeight(searcher, false, 1f));
   }
 
@@ -78,7 +82,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
            joinField.equals(other.joinField) &&
            fromQuery.equals(other.fromQuery) &&
            toQuery.equals(other.toQuery) &&
-           indexReader.equals(other.indexReader);
+           indexReaderContextId.equals(other.indexReaderContextId);
   }
 
   @Override
@@ -89,7 +93,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
     result = 31 * result + fromQuery.hashCode();
     result = 31 * result + min;
     result = 31 * result + max;
-    result = 31 * result + indexReader.hashCode();
+    result = 31 * result + indexReaderContextId.hashCode();
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/edafcbad/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
index bfc1f9b..537b224 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
@@ -32,7 +32,6 @@ import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.index.BinaryDocValues;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.DocValuesType;
-import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
@@ -467,8 +466,7 @@ public final class JoinUtil {
                                       MultiDocValues.OrdinalMap ordinalMap,
                                       int min,
                                       int max) throws IOException {
-    IndexReader indexReader = searcher.getIndexReader();
-    int numSegments = indexReader.leaves().size();
+    int numSegments = searcher.getIndexReader().leaves().size();
     final long valueCount;
     if (numSegments == 0) {
       return new MatchNoDocsQuery("JoinUtil.createJoinQuery with no segments");
@@ -509,7 +507,7 @@ public final class JoinUtil {
         if (min <= 0 && max == Integer.MAX_VALUE) {
           GlobalOrdinalsCollector globalOrdinalsCollector = new GlobalOrdinalsCollector(joinField, ordinalMap, valueCount);
           searcher.search(rewrittenFromQuery, globalOrdinalsCollector);
-          return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, indexReader);
+          return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, searcher.getTopReaderContext());
         } else {
           globalOrdinalsWithScoreCollector = new GlobalOrdinalsWithScoreCollector.NoScore(joinField, ordinalMap, valueCount, min, max);
           break;
@@ -518,7 +516,7 @@ public final class JoinUtil {
         throw new IllegalArgumentException(String.format(Locale.ROOT, "Score mode %s isn't supported.", scoreMode));
     }
     searcher.search(rewrittenFromQuery, globalOrdinalsWithScoreCollector);
-    return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, indexReader);
+    return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, searcher.getTopReaderContext());
   }
 
 }


[3/3] lucene-solr:branch_6_5: LUCENE-7755: Join queries should not reference IndexReaders.

Posted by jp...@apache.org.
LUCENE-7755: Join queries should not reference IndexReaders.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/3a0c2a69
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/3a0c2a69
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/3a0c2a69

Branch: refs/heads/branch_6_5
Commit: 3a0c2a691d4fea1670b3d071032fc54c716b5d1a
Parents: 4d3e94b
Author: Adrien Grand <jp...@gmail.com>
Authored: Thu Mar 30 15:11:52 2017 +0200
Committer: Adrien Grand <jp...@gmail.com>
Committed: Thu Mar 30 15:44:48 2017 +0200

----------------------------------------------------------------------
 lucene/CHANGES.txt                                  |  7 +++++++
 .../org/apache/lucene/index/IndexReaderContext.java | 10 +++++++++-
 .../lucene/search/join/GlobalOrdinalsQuery.java     | 16 ++++++++++------
 .../search/join/GlobalOrdinalsWithScoreQuery.java   | 16 ++++++++++------
 .../org/apache/lucene/search/join/JoinUtil.java     |  8 +++-----
 5 files changed, 39 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3a0c2a69/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 8bc0ff3..eb64d42 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -3,6 +3,13 @@ Lucene Change Log
 For more information on past and future Lucene versions, please see:
 http://s.apache.org/luceneversions
 
+======================= Lucene 6.5.1 =======================
+
+Bug Fixes
+
+* LUCENE-7755: Fixed join queries to not reference IndexReaders, as it could
+  cause leaks if they are cached. (Adrien Grand)
+
 ======================= Lucene 6.5.0 =======================
 
 API Changes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3a0c2a69/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java b/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
index dada3ff..bca7a14 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
@@ -46,7 +46,15 @@ public abstract class IndexReaderContext {
     this.ordInParent = ordInParent;
     this.isTopLevel = parent==null;
   }
-  
+
+  /** Expert: Return an {@link Object} that uniquely identifies this context.
+   *  The returned object does neither reference this {@link IndexReaderContext}
+   *  nor the wrapped {@link IndexReader}.
+   *  @lucene.experimental */
+  public Object id() {
+    return identity;
+  }
+
   /** Returns the {@link IndexReader}, this context represents. */
   public abstract IndexReader reader();
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3a0c2a69/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
index 6c380b4..00c7ae0 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.util.Set;
 
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.SortedDocValues;
@@ -48,19 +48,23 @@ final class GlobalOrdinalsQuery extends Query {
 
   // just for hashcode and equals:
   private final Query fromQuery;
-  private final IndexReader indexReader;
+  // id of the context rather than the context itself in order not to hold references to index readers
+  private final Object indexReaderContextId;
 
-  GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReader indexReader) {
+  GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReaderContext context) {
     this.foundOrds = foundOrds;
     this.joinField = joinField;
     this.globalOrds = globalOrds;
     this.toQuery = toQuery;
     this.fromQuery = fromQuery;
-    this.indexReader = indexReader;
+    this.indexReaderContextId = context.id();
   }
 
   @Override
   public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
+    if (searcher.getTopReaderContext().id() != indexReaderContextId) {
+      throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
+    }
     return new W(this, toQuery.createWeight(searcher, false));
   }
 
@@ -74,7 +78,7 @@ final class GlobalOrdinalsQuery extends Query {
     return fromQuery.equals(other.fromQuery) &&
            joinField.equals(other.joinField) &&
            toQuery.equals(other.toQuery) &&
-           indexReader.equals(other.indexReader);
+           indexReaderContextId.equals(other.indexReaderContextId);
   }
 
   @Override
@@ -83,7 +87,7 @@ final class GlobalOrdinalsQuery extends Query {
     result = 31 * result + joinField.hashCode();
     result = 31 * result + toQuery.hashCode();
     result = 31 * result + fromQuery.hashCode();
-    result = 31 * result + indexReader.hashCode();
+    result = 31 * result + indexReaderContextId.hashCode();
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3a0c2a69/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
index 6089531..7e54921 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
@@ -17,7 +17,7 @@
 package org.apache.lucene.search.join;
 
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.SortedDocValues;
@@ -48,9 +48,10 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
   private final Query fromQuery;
   private final int min;
   private final int max;
-  private final IndexReader indexReader;
+  // id of the context rather than the context itself in order not to hold references to index readers
+  private final Object indexReaderContextId;
 
-  GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReader indexReader) {
+  GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReaderContext context) {
     this.collector = collector;
     this.joinField = joinField;
     this.globalOrds = globalOrds;
@@ -58,11 +59,14 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
     this.fromQuery = fromQuery;
     this.min = min;
     this.max = max;
-    this.indexReader = indexReader;
+    this.indexReaderContextId = context.id();
   }
 
   @Override
   public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
+    if (searcher.getTopReaderContext().id() != indexReaderContextId) {
+      throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
+    }
     return new W(this, toQuery.createWeight(searcher, false));
   }
 
@@ -78,7 +82,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
            joinField.equals(other.joinField) &&
            fromQuery.equals(other.fromQuery) &&
            toQuery.equals(other.toQuery) &&
-           indexReader.equals(other.indexReader);
+           indexReaderContextId.equals(other.indexReaderContextId);
   }
 
   @Override
@@ -89,7 +93,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
     result = 31 * result + fromQuery.hashCode();
     result = 31 * result + min;
     result = 31 * result + max;
-    result = 31 * result + indexReader.hashCode();
+    result = 31 * result + indexReaderContextId.hashCode();
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3a0c2a69/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
index b0133e5..bca5f61 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
@@ -33,7 +33,6 @@ import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.index.BinaryDocValues;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.DocValuesType;
-import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
@@ -490,8 +489,7 @@ public final class JoinUtil {
                                       MultiDocValues.OrdinalMap ordinalMap,
                                       int min,
                                       int max) throws IOException {
-    IndexReader indexReader = searcher.getIndexReader();
-    int numSegments = indexReader.leaves().size();
+    int numSegments = searcher.getIndexReader().leaves().size();
     final long valueCount;
     if (numSegments == 0) {
       return new MatchNoDocsQuery("JoinUtil.createJoinQuery with no segments");
@@ -532,7 +530,7 @@ public final class JoinUtil {
         if (min <= 0 && max == Integer.MAX_VALUE) {
           GlobalOrdinalsCollector globalOrdinalsCollector = new GlobalOrdinalsCollector(joinField, ordinalMap, valueCount);
           searcher.search(rewrittenFromQuery, globalOrdinalsCollector);
-          return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, indexReader);
+          return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, searcher.getTopReaderContext());
         } else {
           globalOrdinalsWithScoreCollector = new GlobalOrdinalsWithScoreCollector.NoScore(joinField, ordinalMap, valueCount, min, max);
           break;
@@ -541,7 +539,7 @@ public final class JoinUtil {
         throw new IllegalArgumentException(String.format(Locale.ROOT, "Score mode %s isn't supported.", scoreMode));
     }
     searcher.search(rewrittenFromQuery, globalOrdinalsWithScoreCollector);
-    return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, indexReader);
+    return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, searcher.getTopReaderContext());
   }
 
 }


[2/3] lucene-solr:branch_6x: LUCENE-7755: Join queries should not reference IndexReaders.

Posted by jp...@apache.org.
LUCENE-7755: Join queries should not reference IndexReaders.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/bd2ec8e4
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/bd2ec8e4
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/bd2ec8e4

Branch: refs/heads/branch_6x
Commit: bd2ec8e40e83e4712062c37ed121132054409918
Parents: 09373aa
Author: Adrien Grand <jp...@gmail.com>
Authored: Thu Mar 30 15:11:52 2017 +0200
Committer: Adrien Grand <jp...@gmail.com>
Committed: Thu Mar 30 15:43:05 2017 +0200

----------------------------------------------------------------------
 lucene/CHANGES.txt                                  |  7 +++++++
 .../org/apache/lucene/index/IndexReaderContext.java | 10 +++++++++-
 .../lucene/search/join/GlobalOrdinalsQuery.java     | 16 ++++++++++------
 .../search/join/GlobalOrdinalsWithScoreQuery.java   | 16 ++++++++++------
 .../org/apache/lucene/search/join/JoinUtil.java     |  8 +++-----
 5 files changed, 39 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bd2ec8e4/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 70fbe67..f9ee8f4 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -16,6 +16,13 @@ Other
 * LUCENE-7743: Never call new String(String).
   (Daniel Jelinski via Adrien Grand)
 
+======================= Lucene 6.5.1 =======================
+
+Bug Fixes
+
+* LUCENE-7755: Fixed join queries to not reference IndexReaders, as it could
+  cause leaks if they are cached. (Adrien Grand)
+
 ======================= Lucene 6.5.0 =======================
 
 API Changes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bd2ec8e4/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java b/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
index dada3ff..bca7a14 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexReaderContext.java
@@ -46,7 +46,15 @@ public abstract class IndexReaderContext {
     this.ordInParent = ordInParent;
     this.isTopLevel = parent==null;
   }
-  
+
+  /** Expert: Return an {@link Object} that uniquely identifies this context.
+   *  The returned object does neither reference this {@link IndexReaderContext}
+   *  nor the wrapped {@link IndexReader}.
+   *  @lucene.experimental */
+  public Object id() {
+    return identity;
+  }
+
   /** Returns the {@link IndexReader}, this context represents. */
   public abstract IndexReader reader();
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bd2ec8e4/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
index 6c380b4..00c7ae0 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
@@ -20,7 +20,7 @@ import java.io.IOException;
 import java.util.Set;
 
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.SortedDocValues;
@@ -48,19 +48,23 @@ final class GlobalOrdinalsQuery extends Query {
 
   // just for hashcode and equals:
   private final Query fromQuery;
-  private final IndexReader indexReader;
+  // id of the context rather than the context itself in order not to hold references to index readers
+  private final Object indexReaderContextId;
 
-  GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReader indexReader) {
+  GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReaderContext context) {
     this.foundOrds = foundOrds;
     this.joinField = joinField;
     this.globalOrds = globalOrds;
     this.toQuery = toQuery;
     this.fromQuery = fromQuery;
-    this.indexReader = indexReader;
+    this.indexReaderContextId = context.id();
   }
 
   @Override
   public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
+    if (searcher.getTopReaderContext().id() != indexReaderContextId) {
+      throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
+    }
     return new W(this, toQuery.createWeight(searcher, false));
   }
 
@@ -74,7 +78,7 @@ final class GlobalOrdinalsQuery extends Query {
     return fromQuery.equals(other.fromQuery) &&
            joinField.equals(other.joinField) &&
            toQuery.equals(other.toQuery) &&
-           indexReader.equals(other.indexReader);
+           indexReaderContextId.equals(other.indexReaderContextId);
   }
 
   @Override
@@ -83,7 +87,7 @@ final class GlobalOrdinalsQuery extends Query {
     result = 31 * result + joinField.hashCode();
     result = 31 * result + toQuery.hashCode();
     result = 31 * result + fromQuery.hashCode();
-    result = 31 * result + indexReader.hashCode();
+    result = 31 * result + indexReaderContextId.hashCode();
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bd2ec8e4/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
index 6089531..7e54921 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
@@ -17,7 +17,7 @@
 package org.apache.lucene.search.join;
 
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.SortedDocValues;
@@ -48,9 +48,10 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
   private final Query fromQuery;
   private final int min;
   private final int max;
-  private final IndexReader indexReader;
+  // id of the context rather than the context itself in order not to hold references to index readers
+  private final Object indexReaderContextId;
 
-  GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReader indexReader) {
+  GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReaderContext context) {
     this.collector = collector;
     this.joinField = joinField;
     this.globalOrds = globalOrds;
@@ -58,11 +59,14 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
     this.fromQuery = fromQuery;
     this.min = min;
     this.max = max;
-    this.indexReader = indexReader;
+    this.indexReaderContextId = context.id();
   }
 
   @Override
   public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
+    if (searcher.getTopReaderContext().id() != indexReaderContextId) {
+      throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
+    }
     return new W(this, toQuery.createWeight(searcher, false));
   }
 
@@ -78,7 +82,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
            joinField.equals(other.joinField) &&
            fromQuery.equals(other.fromQuery) &&
            toQuery.equals(other.toQuery) &&
-           indexReader.equals(other.indexReader);
+           indexReaderContextId.equals(other.indexReaderContextId);
   }
 
   @Override
@@ -89,7 +93,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
     result = 31 * result + fromQuery.hashCode();
     result = 31 * result + min;
     result = 31 * result + max;
-    result = 31 * result + indexReader.hashCode();
+    result = 31 * result + indexReaderContextId.hashCode();
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bd2ec8e4/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
index b0133e5..bca5f61 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/JoinUtil.java
@@ -33,7 +33,6 @@ import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.index.BinaryDocValues;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.DocValuesType;
-import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
@@ -490,8 +489,7 @@ public final class JoinUtil {
                                       MultiDocValues.OrdinalMap ordinalMap,
                                       int min,
                                       int max) throws IOException {
-    IndexReader indexReader = searcher.getIndexReader();
-    int numSegments = indexReader.leaves().size();
+    int numSegments = searcher.getIndexReader().leaves().size();
     final long valueCount;
     if (numSegments == 0) {
       return new MatchNoDocsQuery("JoinUtil.createJoinQuery with no segments");
@@ -532,7 +530,7 @@ public final class JoinUtil {
         if (min <= 0 && max == Integer.MAX_VALUE) {
           GlobalOrdinalsCollector globalOrdinalsCollector = new GlobalOrdinalsCollector(joinField, ordinalMap, valueCount);
           searcher.search(rewrittenFromQuery, globalOrdinalsCollector);
-          return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, indexReader);
+          return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, searcher.getTopReaderContext());
         } else {
           globalOrdinalsWithScoreCollector = new GlobalOrdinalsWithScoreCollector.NoScore(joinField, ordinalMap, valueCount, min, max);
           break;
@@ -541,7 +539,7 @@ public final class JoinUtil {
         throw new IllegalArgumentException(String.format(Locale.ROOT, "Score mode %s isn't supported.", scoreMode));
     }
     searcher.search(rewrittenFromQuery, globalOrdinalsWithScoreCollector);
-    return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, indexReader);
+    return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, searcher.getTopReaderContext());
   }
 
 }