diff --git a/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java b/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
index 6f1869329ed..c38a9b7f52d 100644
--- a/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
+++ b/lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
@@ -40,8 +40,8 @@ import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.index.FieldInvertState;
import org.apache.lucene.index.Fields;
import org.apache.lucene.index.FieldsEnum;
-import org.apache.lucene.index.PerDocValues;
import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.OrdTermState;
import org.apache.lucene.index.StoredFieldVisitor;
@@ -1159,7 +1159,7 @@ public class MemoryIndex {
}
@Override
- public PerDocValues perDocValues() throws IOException {
+ public DocValues docValues(String field) throws IOException {
return null;
}
}
diff --git a/lucene/src/java/org/apache/lucene/index/CheckIndex.java b/lucene/src/java/org/apache/lucene/index/CheckIndex.java
index 2e6c7002396..6be57d5c09a 100644
--- a/lucene/src/java/org/apache/lucene/index/CheckIndex.java
+++ b/lucene/src/java/org/apache/lucene/index/CheckIndex.java
@@ -27,6 +27,8 @@ import org.apache.lucene.store.IndexInput;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DocValues.Source;
import org.apache.lucene.index.codecs.Codec;
+import org.apache.lucene.index.codecs.PerDocProducer;
+
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
@@ -1130,8 +1132,7 @@ public class CheckIndex {
for (FieldInfo fieldInfo : fieldInfos) {
if (fieldInfo.hasDocValues()) {
status.totalValueFields++;
- final PerDocValues perDocValues = reader.perDocValues();
- final DocValues docValues = perDocValues.docValues(fieldInfo.name);
+ final DocValues docValues = reader.docValues(fieldInfo.name);
if (docValues == null) {
continue;
}
diff --git a/lucene/src/java/org/apache/lucene/index/DirectoryReader.java b/lucene/src/java/org/apache/lucene/index/DirectoryReader.java
index e1468b75624..64c02c837b4 100644
--- a/lucene/src/java/org/apache/lucene/index/DirectoryReader.java
+++ b/lucene/src/java/org/apache/lucene/index/DirectoryReader.java
@@ -31,11 +31,8 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
-import org.apache.lucene.store.Lock;
-import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.InfoStream;
import org.apache.lucene.util.MapBackedSet;
/**
@@ -716,7 +713,7 @@ class DirectoryReader extends IndexReader implements Cloneable {
}
@Override
- public PerDocValues perDocValues() throws IOException {
- throw new UnsupportedOperationException("please use MultiPerDocValues#getPerDocs, or wrap your IndexReader with SlowMultiReaderWrapper, if you really need a top level Fields");
+ public DocValues docValues(String field) throws IOException {
+ throw new UnsupportedOperationException("please use MultiDocValues#getDocValues, or wrap your IndexReader with SlowMultiReaderWrapper, if you really need a top level DocValues");
}
}
diff --git a/lucene/src/java/org/apache/lucene/index/FilterIndexReader.java b/lucene/src/java/org/apache/lucene/index/FilterIndexReader.java
index 3c64cbeccd7..cdeb70c91fa 100644
--- a/lucene/src/java/org/apache/lucene/index/FilterIndexReader.java
+++ b/lucene/src/java/org/apache/lucene/index/FilterIndexReader.java
@@ -421,9 +421,9 @@ public class FilterIndexReader extends IndexReader {
}
@Override
- public PerDocValues perDocValues() throws IOException {
+ public DocValues docValues(String field) throws IOException {
ensureOpen();
- return in.perDocValues();
+ return in.docValues(field);
}
@Override
diff --git a/lucene/src/java/org/apache/lucene/index/IndexReader.java b/lucene/src/java/org/apache/lucene/index/IndexReader.java
index 592e66dd09e..edc2142927c 100644
--- a/lucene/src/java/org/apache/lucene/index/IndexReader.java
+++ b/lucene/src/java/org/apache/lucene/index/IndexReader.java
@@ -773,21 +773,6 @@ public abstract class IndexReader implements Cloneable,Closeable {
* through them yourself. */
public abstract Fields fields() throws IOException;
- /**
- * Returns {@link PerDocValues} for this reader.
- * This method may return null if the reader has no per-document
- * values stored.
- *
- *
NOTE: if this is a multi reader ({@link
- * #getSequentialSubReaders} is not null) then this
- * method will throw UnsupportedOperationException. If
- * you really need {@link PerDocValues} for such a reader,
- * use {@link MultiPerDocValues#getPerDocs(IndexReader)}. However, for
- * performance reasons, it's best to get all sub-readers
- * using {@link ReaderUtil#gatherSubReaders} and iterate
- * through them yourself. */
- public abstract PerDocValues perDocValues() throws IOException;
-
public final int docFreq(Term term) throws IOException {
return docFreq(term.field(), term.bytes());
}
@@ -1146,14 +1131,20 @@ public abstract class IndexReader implements Cloneable,Closeable {
throw new UnsupportedOperationException("This reader does not support this method.");
}
- public final DocValues docValues(String field) throws IOException {
- ensureOpen();
- final PerDocValues perDoc = perDocValues();
- if (perDoc == null) {
- return null;
- }
- return perDoc.docValues(field);
- }
+ /**
+ * Returns {@link DocValues} for this field.
+ * This method may return null if the reader has no per-document
+ * values stored.
+ *
+ *
NOTE: if this is a multi reader ({@link
+ * #getSequentialSubReaders} is not null) then this
+ * method will throw UnsupportedOperationException. If
+ * you really need {@link DocValues} for such a reader,
+ * use {@link MultiDocValues#getDocValues(IndexReader,String)}. However, for
+ * performance reasons, it's best to get all sub-readers
+ * using {@link ReaderUtil#gatherSubReaders} and iterate
+ * through them yourself. */
+ public abstract DocValues docValues(String field) throws IOException;
private volatile Fields fields;
@@ -1169,21 +1160,6 @@ public abstract class IndexReader implements Cloneable,Closeable {
return fields;
}
- private volatile PerDocValues perDocValues;
-
- /** @lucene.internal */
- void storePerDoc(PerDocValues perDocValues) {
- ensureOpen();
- this.perDocValues = perDocValues;
- }
-
- /** @lucene.internal */
- PerDocValues retrievePerDoc() {
- ensureOpen();
- return perDocValues;
- }
-
-
/**
* A struct like class that represents a hierarchical relationship between
* {@link IndexReader} instances.
diff --git a/lucene/src/java/org/apache/lucene/index/MultiDocValues.java b/lucene/src/java/org/apache/lucene/index/MultiDocValues.java
index 529058e8362..9f1d16fa2a5 100644
--- a/lucene/src/java/org/apache/lucene/index/MultiDocValues.java
+++ b/lucene/src/java/org/apache/lucene/index/MultiDocValues.java
@@ -17,10 +17,13 @@ package org.apache.lucene.index;
* limitations under the License.
*/
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.ReaderUtil.Gather;
/**
* A wrapper for compound IndexReader providing access to per segment
@@ -31,59 +34,92 @@ import org.apache.lucene.util.ReaderUtil;
*/
public class MultiDocValues extends DocValues {
- public static class DocValuesIndex {
- public final static DocValuesIndex[] EMPTY_ARRAY = new DocValuesIndex[0];
+ public static class DocValuesSlice {
+ public final static DocValuesSlice[] EMPTY_ARRAY = new DocValuesSlice[0];
final int start;
final int length;
- final DocValues docValues;
+ DocValues docValues;
- public DocValuesIndex(DocValues docValues, int start, int length) {
+ public DocValuesSlice(DocValues docValues, int start, int length) {
this.docValues = docValues;
this.start = start;
this.length = length;
}
}
- private DocValuesIndex[] docValuesIdx;
+ private DocValuesSlice[] slices;
private int[] starts;
private Type type;
private int valueSize;
- public MultiDocValues() {
- starts = new int[0];
- docValuesIdx = new DocValuesIndex[0];
+ private MultiDocValues(DocValuesSlice[] slices, int[] starts, TypePromoter promotedType) {
+ this.starts = starts;
+ this.slices = slices;
+ this.type = promotedType.type();
+ this.valueSize = promotedType.getValueSize();
}
-
- public MultiDocValues(DocValuesIndex[] docValuesIdx) {
- reset(docValuesIdx);
+
+ /**
+ * Returns a single {@link DocValues} instance for this field, merging
+ * their values on the fly.
+ *
+ *
+ * NOTE: this is a slow way to access DocValues. It's better to get the
+ * sub-readers (using {@link Gather}) and iterate through them yourself.
+ */
+ public static DocValues getDocValues(IndexReader r, final String field) throws IOException {
+ final IndexReader[] subs = r.getSequentialSubReaders();
+ if (subs == null) {
+ // already an atomic reader
+ return r.docValues(field);
+ } else if (subs.length == 0) {
+ // no fields
+ return null;
+ } else if (subs.length == 1) {
+ return getDocValues(subs[0], field);
+ } else {
+ final List slices = new ArrayList();
+
+ final TypePromoter promotedType[] = new TypePromoter[1];
+ promotedType[0] = TypePromoter.getIdentityPromoter();
+
+ // gather all docvalues fields, accumulating a promoted type across
+ // potentially incompatible types
+
+ new ReaderUtil.Gather(r) {
+ @Override
+ protected void add(int base, IndexReader r) throws IOException {
+ final DocValues d = r.docValues(field);
+ if (d != null) {
+ TypePromoter incoming = TypePromoter.create(d.type(), d.getValueSize());
+ promotedType[0] = promotedType[0].promote(incoming);
+ }
+ slices.add(new DocValuesSlice(d, base, r.maxDoc()));
+ }
+ }.run();
+
+ // return null if no docvalues encountered anywhere
+ if (promotedType[0] == TypePromoter.getIdentityPromoter()) {
+ return null;
+ }
+
+ // populate starts and fill gaps with empty docvalues
+ int starts[] = new int[slices.size()];
+ for (int i = 0; i < slices.size(); i++) {
+ DocValuesSlice slice = slices.get(i);
+ starts[i] = slice.start;
+ if (slice.docValues == null) {
+ slice.docValues = new EmptyDocValues(slice.length, promotedType[0].type());
+ }
+ }
+
+ return new MultiDocValues(slices.toArray(new DocValuesSlice[slices.size()]), starts, promotedType[0]);
+ }
}
@Override
public Source load() throws IOException {
- return new MultiSource(docValuesIdx, starts, false);
- }
-
- public DocValues reset(DocValuesIndex[] docValuesIdx) {
- final int[] start = new int[docValuesIdx.length];
- TypePromoter promoter = TypePromoter.getIdentityPromoter();
- for (int i = 0; i < docValuesIdx.length; i++) {
- start[i] = docValuesIdx[i].start;
- if (!(docValuesIdx[i].docValues instanceof EmptyDocValues)) {
- // only promote if not a dummy
- final TypePromoter incomingPromoter = TypePromoter.create(
- docValuesIdx[i].docValues.type(),
- docValuesIdx[i].docValues.getValueSize());
- promoter = promoter.promote(incomingPromoter);
- if (promoter == null) {
- throw new IllegalStateException("Can not promote " + incomingPromoter);
- }
- }
- }
- this.type = promoter.type();
- this.valueSize = promoter.getValueSize();
- this.starts = start;
- this.docValuesIdx = docValuesIdx;
- return this;
+ return new MultiSource(slices, starts, false, type);
}
public static class EmptyDocValues extends DocValues {
@@ -117,14 +153,14 @@ public class MultiDocValues extends DocValues {
private int start = 0;
private Source current;
private final int[] starts;
- private final DocValuesIndex[] docValuesIdx;
+ private final DocValuesSlice[] slices;
private boolean direct;
- public MultiSource(DocValuesIndex[] docValuesIdx, int[] starts, boolean direct) {
- super(docValuesIdx[0].docValues.type());
- this.docValuesIdx = docValuesIdx;
+ public MultiSource(DocValuesSlice[] slices, int[] starts, boolean direct, Type type) {
+ super(type);
+ this.slices = slices;
this.starts = starts;
- assert docValuesIdx.length != 0;
+ assert slices.length != 0;
this.direct = direct;
}
@@ -138,22 +174,22 @@ public class MultiDocValues extends DocValues {
return docID - start;
} else {
final int idx = ReaderUtil.subIndex(docID, starts);
- assert idx >= 0 && idx < docValuesIdx.length : "idx was " + idx
+ assert idx >= 0 && idx < slices.length : "idx was " + idx
+ " for doc id: " + docID + " slices : " + Arrays.toString(starts);
- assert docValuesIdx[idx] != null;
+ assert slices[idx] != null;
try {
if (direct) {
- current = docValuesIdx[idx].docValues.getDirectSource();
+ current = slices[idx].docValues.getDirectSource();
} else {
- current = docValuesIdx[idx].docValues.getSource();
+ current = slices[idx].docValues.getSource();
}
} catch (IOException e) {
throw new RuntimeException("load failed", e); // TODO how should we
// handle this
}
- start = docValuesIdx[idx].start;
- numDocs = docValuesIdx[idx].length;
+ start = slices[idx].start;
+ numDocs = slices[idx].length;
return docID - start;
}
}
@@ -206,6 +242,6 @@ public class MultiDocValues extends DocValues {
@Override
public Source getDirectSource() throws IOException {
- return new MultiSource(docValuesIdx, starts, true);
+ return new MultiSource(slices, starts, true, type);
}
}
diff --git a/lucene/src/java/org/apache/lucene/index/MultiFieldsEnum.java b/lucene/src/java/org/apache/lucene/index/MultiFieldsEnum.java
index 2411f5dca63..7db5f02fac5 100644
--- a/lucene/src/java/org/apache/lucene/index/MultiFieldsEnum.java
+++ b/lucene/src/java/org/apache/lucene/index/MultiFieldsEnum.java
@@ -38,14 +38,9 @@ public final class MultiFieldsEnum extends FieldsEnum {
// Holds sub-readers containing field we are currently
// on, popped from queue.
private final FieldsEnumWithSlice[] top;
- private final FieldsEnumWithSlice[] enumWithSlices;
private int numTop;
- // Re-used TermsEnum
- private final MultiTermsEnum terms;
- private final MultiDocValues docValues;
-
private final Fields fields;
private String currentField;
@@ -54,9 +49,7 @@ public final class MultiFieldsEnum extends FieldsEnum {
* (ie, {@link FieldsEnum#next} has not been called. */
public MultiFieldsEnum(MultiFields fields, FieldsEnum[] subs, ReaderUtil.Slice[] subSlices) throws IOException {
this.fields = fields;
- terms = new MultiTermsEnum(subSlices);
queue = new FieldMergeQueue(subs.length);
- docValues = new MultiDocValues();
top = new FieldsEnumWithSlice[subs.length];
List enumWithSlices = new ArrayList();
@@ -72,8 +65,6 @@ public final class MultiFieldsEnum extends FieldsEnum {
queue.add(sub);
}
}
- this.enumWithSlices = enumWithSlices.toArray(FieldsEnumWithSlice.EMPTY_ARRAY);
-
}
@Override
diff --git a/lucene/src/java/org/apache/lucene/index/MultiPerDocValues.java b/lucene/src/java/org/apache/lucene/index/MultiPerDocValues.java
deleted file mode 100644
index 8f7a6a7d9e7..00000000000
--- a/lucene/src/java/org/apache/lucene/index/MultiPerDocValues.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package org.apache.lucene.index;
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.lucene.index.MultiDocValues.DocValuesIndex;
-import org.apache.lucene.index.DocValues;
-import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.ReaderUtil;
-import org.apache.lucene.util.ReaderUtil.Gather;
-
-/**
- * Exposes per-document values, merged from per-document values API of
- * sub-segments. This is useful when you're interacting with an {@link IndexReader}
- * implementation that consists of sequential sub-readers (eg DirectoryReader
- * or {@link MultiReader}).
- *
- *
- * NOTE: for multi readers, you'll get better performance by gathering
- * the sub readers using {@link ReaderUtil#gatherSubReaders} and then operate
- * per-reader, instead of using this class.
- *
- * @lucene.experimental
- */
-public class MultiPerDocValues extends PerDocValues {
- private final PerDocValues[] subs;
- private final ReaderUtil.Slice[] subSlices;
- private final Map docValues = new ConcurrentHashMap();
-
- public MultiPerDocValues(PerDocValues[] subs, ReaderUtil.Slice[] subSlices) {
- this.subs = subs;
- this.subSlices = subSlices;
- }
-
- /**
- * Returns a single {@link PerDocValues} instance for this reader, merging
- * their values on the fly. This method will not return null
.
- *
- *
- * NOTE: this is a slow way to access postings. It's better to get the
- * sub-readers (using {@link Gather}) and iterate through them yourself.
- */
- public static PerDocValues getPerDocs(IndexReader r) throws IOException {
- final IndexReader[] subs = r.getSequentialSubReaders();
- if (subs == null) {
- // already an atomic reader
- return r.perDocValues();
- } else if (subs.length == 0) {
- // no fields
- return null;
- } else if (subs.length == 1) {
- return getPerDocs(subs[0]);
- }
- PerDocValues perDocValues = r.retrievePerDoc();
- if (perDocValues == null) {
-
- final List producer = new ArrayList();
- final List slices = new ArrayList();
-
- new ReaderUtil.Gather(r) {
- @Override
- protected void add(int base, IndexReader r) throws IOException {
- final PerDocValues f = r.perDocValues();
- if (f != null) {
- producer.add(f);
- slices
- .add(new ReaderUtil.Slice(base, r.maxDoc(), producer.size() - 1));
- }
- }
- }.run();
-
- if (producer.size() == 0) {
- return null;
- } else if (producer.size() == 1) {
- perDocValues = producer.get(0);
- } else {
- perDocValues = new MultiPerDocValues(
- producer.toArray(PerDocValues.EMPTY_ARRAY),
- slices.toArray(ReaderUtil.Slice.EMPTY_ARRAY));
- }
- r.storePerDoc(perDocValues);
- }
- return perDocValues;
- }
-
- public DocValues docValues(String field) throws IOException {
- DocValues result = docValues.get(field);
- if (result == null) {
- // Lazy init: first time this field is requested, we
- // create & add to docValues:
- final List docValuesIndex = new ArrayList();
- int docsUpto = 0;
- DocValues.Type type = null;
- // Gather all sub-readers that share this field
- for (int i = 0; i < subs.length; i++) {
- DocValues values = subs[i].docValues(field);
- final int start = subSlices[i].start;
- final int length = subSlices[i].length;
- if (values != null) {
- if (docsUpto != start) {
- type = values.type();
- docValuesIndex.add(new MultiDocValues.DocValuesIndex(
- new MultiDocValues.EmptyDocValues(start, type), docsUpto, start
- - docsUpto));
- }
- docValuesIndex.add(new MultiDocValues.DocValuesIndex(values, start,
- length));
- docsUpto = start + length;
-
- } else if (i + 1 == subs.length && !docValuesIndex.isEmpty()) {
- docValuesIndex.add(new MultiDocValues.DocValuesIndex(
- new MultiDocValues.EmptyDocValues(start, type), docsUpto, start
- - docsUpto));
- }
- }
- if (docValuesIndex.isEmpty()) {
- return null;
- }
- result = new MultiDocValues(
- docValuesIndex.toArray(DocValuesIndex.EMPTY_ARRAY));
- docValues.put(field, result);
- }
- return result;
- }
-
- public void close() throws IOException {
- IOUtils.close(this.subs);
- }
-}
diff --git a/lucene/src/java/org/apache/lucene/index/MultiReader.java b/lucene/src/java/org/apache/lucene/index/MultiReader.java
index 6eb41266918..21d075ee8cd 100644
--- a/lucene/src/java/org/apache/lucene/index/MultiReader.java
+++ b/lucene/src/java/org/apache/lucene/index/MultiReader.java
@@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.lucene.index.codecs.PerDocProducer;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.ReaderUtil;
@@ -330,7 +331,7 @@ public class MultiReader extends IndexReader implements Cloneable {
}
@Override
- public PerDocValues perDocValues() throws IOException {
- throw new UnsupportedOperationException("please use MultiPerDocValues#getPerDocs, or wrap your IndexReader with SlowMultiReaderWrapper, if you really need a top level Fields");
+ public DocValues docValues(String field) throws IOException {
+ throw new UnsupportedOperationException("please use MultiDocValues#getDocValues, or wrap your IndexReader with SlowMultiReaderWrapper, if you really need a top level DocValues");
}
}
diff --git a/lucene/src/java/org/apache/lucene/index/ParallelReader.java b/lucene/src/java/org/apache/lucene/index/ParallelReader.java
index 6b3d9eaf9f8..6582b65b4bd 100644
--- a/lucene/src/java/org/apache/lucene/index/ParallelReader.java
+++ b/lucene/src/java/org/apache/lucene/index/ParallelReader.java
@@ -57,7 +57,6 @@ public class ParallelReader extends IndexReader {
private boolean hasDeletions;
private final ParallelFields fields = new ParallelFields();
- private final ParallelPerDocs perDocs = new ParallelPerDocs();
/** Construct a ParallelReader.
* Note that all subreaders are closed if this ParallelReader is closed.
@@ -130,7 +129,6 @@ public class ParallelReader extends IndexReader {
if (fieldToReader.get(field) == null) {
fieldToReader.put(field, reader);
this.fields.addField(field, MultiFields.getFields(reader).terms(field));
- this.perDocs.addField(field, reader);
}
}
@@ -463,35 +461,8 @@ public class ParallelReader extends IndexReader {
}
@Override
- public PerDocValues perDocValues() throws IOException {
- ensureOpen();
- return perDocs;
- }
-
- // Single instance of this, per ParallelReader instance
- private static final class ParallelPerDocs extends PerDocValues {
- final TreeMap fields = new TreeMap();
-
- void addField(String field, IndexReader r) throws IOException {
- PerDocValues perDocs = MultiPerDocValues.getPerDocs(r);
- if (perDocs != null) {
- fields.put(field, perDocs.docValues(field));
- }
- }
-
- @Override
- public void close() throws IOException {
- // nothing to do here
- }
-
- @Override
- public DocValues docValues(String field) throws IOException {
- return fields.get(field);
- }
+ public DocValues docValues(String field) throws IOException {
+ IndexReader reader = fieldToReader.get(field);
+ return reader == null ? null : reader.docValues(field);
}
}
-
-
-
-
-
diff --git a/lucene/src/java/org/apache/lucene/index/SegmentCoreReaders.java b/lucene/src/java/org/apache/lucene/index/SegmentCoreReaders.java
index 65755b43a28..6f6d7d1cf88 100644
--- a/lucene/src/java/org/apache/lucene/index/SegmentCoreReaders.java
+++ b/lucene/src/java/org/apache/lucene/index/SegmentCoreReaders.java
@@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.lucene.index.codecs.Codec;
import org.apache.lucene.index.codecs.NormsReader;
+import org.apache.lucene.index.codecs.PerDocProducer;
import org.apache.lucene.index.codecs.PostingsFormat;
import org.apache.lucene.index.codecs.FieldsProducer;
import org.apache.lucene.index.codecs.StoredFieldsReader;
@@ -47,7 +48,7 @@ final class SegmentCoreReaders {
final FieldInfos fieldInfos;
final FieldsProducer fields;
- final PerDocValues perDocProducer;
+ final PerDocProducer perDocProducer;
final NormsReader norms;
final Directory dir;
diff --git a/lucene/src/java/org/apache/lucene/index/SegmentReader.java b/lucene/src/java/org/apache/lucene/index/SegmentReader.java
index 7eb54687616..2b26fc6f57a 100644
--- a/lucene/src/java/org/apache/lucene/index/SegmentReader.java
+++ b/lucene/src/java/org/apache/lucene/index/SegmentReader.java
@@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.lucene.store.Directory;
import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.codecs.PerDocProducer;
import org.apache.lucene.index.codecs.StoredFieldsReader;
import org.apache.lucene.index.codecs.TermVectorsReader;
import org.apache.lucene.store.IOContext;
@@ -424,9 +425,13 @@ public final class SegmentReader extends IndexReader implements Cloneable {
}
@Override
- public PerDocValues perDocValues() throws IOException {
+ public DocValues docValues(String field) throws IOException {
ensureOpen();
- return core.perDocProducer;
+ final PerDocProducer perDoc = core.perDocProducer;
+ if (perDoc == null) {
+ return null;
+ }
+ return perDoc.docValues(field);
}
/**
diff --git a/lucene/src/java/org/apache/lucene/index/SlowMultiReaderWrapper.java b/lucene/src/java/org/apache/lucene/index/SlowMultiReaderWrapper.java
index f945f5e4976..1d021db3579 100644
--- a/lucene/src/java/org/apache/lucene/index/SlowMultiReaderWrapper.java
+++ b/lucene/src/java/org/apache/lucene/index/SlowMultiReaderWrapper.java
@@ -34,11 +34,12 @@ import org.apache.lucene.index.MultiReader; // javadoc
* IndexReader#getSequentialSubReaders}) to emulate an
* atomic reader. This requires implementing the postings
* APIs on-the-fly, using the static methods in {@link
- * MultiFields}, by stepping through the sub-readers to
- * merge fields/terms, appending docs, etc.
+ * MultiFields}, {@link MultiNorms}, {@link MultiDocValues},
+ * by stepping through the sub-readers to merge fields/terms,
+ * appending docs, etc.
*
* If you ever hit an UnsupportedOperationException saying
- * "please use MultiFields.XXX instead", the simple
+ * "please use MultiXXX.YYY instead", the simple
* but non-performant workaround is to wrap your reader
* using this class.
*
@@ -71,9 +72,9 @@ public final class SlowMultiReaderWrapper extends FilterIndexReader {
}
@Override
- public PerDocValues perDocValues() throws IOException {
+ public DocValues docValues(String field) throws IOException {
ensureOpen();
- return MultiPerDocValues.getPerDocs(in);
+ return MultiDocValues.getDocValues(in, field);
}
@Override
diff --git a/lucene/src/java/org/apache/lucene/index/codecs/DocValuesFormat.java b/lucene/src/java/org/apache/lucene/index/codecs/DocValuesFormat.java
index 1e269470e9d..466f458a653 100644
--- a/lucene/src/java/org/apache/lucene/index/codecs/DocValuesFormat.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/DocValuesFormat.java
@@ -20,7 +20,6 @@ package org.apache.lucene.index.codecs;
import java.io.IOException;
import java.util.Set;
-import org.apache.lucene.index.PerDocValues;
import org.apache.lucene.index.PerDocWriteState;
import org.apache.lucene.index.SegmentInfo;
import org.apache.lucene.index.SegmentReadState;
@@ -28,6 +27,6 @@ import org.apache.lucene.store.Directory;
public abstract class DocValuesFormat {
public abstract PerDocConsumer docsConsumer(PerDocWriteState state) throws IOException;
- public abstract PerDocValues docsProducer(SegmentReadState state) throws IOException;
+ public abstract PerDocProducer docsProducer(SegmentReadState state) throws IOException;
public abstract void files(Directory dir, SegmentInfo info, Set files) throws IOException;
}
diff --git a/lucene/src/java/org/apache/lucene/index/codecs/DocValuesReaderBase.java b/lucene/src/java/org/apache/lucene/index/codecs/DocValuesReaderBase.java
index 4530acf99aa..92f07b2b161 100644
--- a/lucene/src/java/org/apache/lucene/index/codecs/DocValuesReaderBase.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/DocValuesReaderBase.java
@@ -28,7 +28,6 @@ import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.FieldInfos;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.DocValues.Type; // javadocs
-import org.apache.lucene.index.PerDocValues;
import org.apache.lucene.index.codecs.lucene40.values.Bytes;
import org.apache.lucene.index.codecs.lucene40.values.Floats;
import org.apache.lucene.index.codecs.lucene40.values.Ints;
@@ -37,11 +36,11 @@ import org.apache.lucene.store.IOContext;
import org.apache.lucene.util.BytesRef;
/**
- * Abstract base class for PerDocValues implementations
+ * Abstract base class for PerDocProducer implementations
* @lucene.experimental
*/
// TODO: this needs to go under lucene40 codec (its specific to its impl)
-public abstract class DocValuesReaderBase extends PerDocValues {
+public abstract class DocValuesReaderBase extends PerDocProducer {
protected abstract void closeInternal(Collection extends Closeable> closeables) throws IOException;
protected abstract Map docValues();
diff --git a/lucene/src/java/org/apache/lucene/index/codecs/PerDocConsumer.java b/lucene/src/java/org/apache/lucene/index/codecs/PerDocConsumer.java
index f2d1f814be9..5b99ce062c3 100644
--- a/lucene/src/java/org/apache/lucene/index/codecs/PerDocConsumer.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/PerDocConsumer.java
@@ -21,7 +21,6 @@ import java.io.IOException;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.MergeState;
-import org.apache.lucene.index.PerDocValues;
/**
* Abstract API that consumes per document values. Concrete implementations of
@@ -39,30 +38,22 @@ public abstract class PerDocConsumer implements Closeable{
throws IOException;
/**
- * Consumes and merges the given {@link PerDocValues} producer
+ * Consumes and merges the given {@link PerDocProducer} producer
* into this consumers format.
*/
public void merge(MergeState mergeState) throws IOException {
final DocValues[] docValues = new DocValues[mergeState.readers.size()];
- final PerDocValues[] perDocValues = new PerDocValues[mergeState.readers.size()];
- // pull all PerDocValues
- for (int i = 0; i < perDocValues.length; i++) {
- perDocValues[i] = mergeState.readers.get(i).reader.perDocValues();
- }
+
for (FieldInfo fieldInfo : mergeState.fieldInfos) {
mergeState.fieldInfo = fieldInfo; // set the field we are merging
if (fieldInfo.hasDocValues()) {
- for (int i = 0; i < perDocValues.length; i++) {
- if (perDocValues[i] != null) { // get all IDV to merge
- docValues[i] = perDocValues[i].docValues(fieldInfo.name);
- }
+ for (int i = 0; i < docValues.length; i++) {
+ docValues[i] = mergeState.readers.get(i).reader.docValues(fieldInfo.name);
}
final DocValuesConsumer docValuesConsumer = addValuesField(fieldInfo.getDocValuesType(), fieldInfo);
assert docValuesConsumer != null;
docValuesConsumer.merge(mergeState, docValues);
}
}
- /* NOTE: don't close the perDocProducers here since they are private segment producers
- * and will be closed once the SegmentReader goes out of scope */
}
}
diff --git a/lucene/src/java/org/apache/lucene/index/PerDocValues.java b/lucene/src/java/org/apache/lucene/index/codecs/PerDocProducer.java
similarity index 83%
rename from lucene/src/java/org/apache/lucene/index/PerDocValues.java
rename to lucene/src/java/org/apache/lucene/index/codecs/PerDocProducer.java
index 08a91577d02..ff2827d8c72 100644
--- a/lucene/src/java/org/apache/lucene/index/PerDocValues.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/PerDocProducer.java
@@ -1,4 +1,4 @@
-package org.apache.lucene.index;
+package org.apache.lucene.index.codecs;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,8 +18,7 @@ package org.apache.lucene.index;
import java.io.Closeable;
import java.io.IOException;
-import org.apache.lucene.index.codecs.PerDocConsumer;
-import org.apache.lucene.index.codecs.PostingsFormat;
+import org.apache.lucene.index.DocValues;
/**
* Abstract API that provides access to one or more per-document storage
@@ -27,13 +26,13 @@ import org.apache.lucene.index.codecs.PostingsFormat;
* storage on a per-document basis corresponding to their actual
* {@link PerDocConsumer} counterpart.
*
- * The {@link PerDocValues} API is accessible through the
+ * The {@link PerDocProducer} API is accessible through the
* {@link PostingsFormat} - API providing per field consumers and producers for inverted
* data (terms, postings) as well as per-document data.
*
* @lucene.experimental
*/
-public abstract class PerDocValues implements Closeable {
+public abstract class PerDocProducer implements Closeable {
/**
* Returns {@link DocValues} for the current field.
*
@@ -45,5 +44,5 @@ public abstract class PerDocValues implements Closeable {
*/
public abstract DocValues docValues(String field) throws IOException;
- public static final PerDocValues[] EMPTY_ARRAY = new PerDocValues[0];
+ public static final PerDocProducer[] EMPTY_ARRAY = new PerDocProducer[0];
}
diff --git a/lucene/src/java/org/apache/lucene/index/codecs/lucene3x/Lucene3xCodec.java b/lucene/src/java/org/apache/lucene/index/codecs/lucene3x/Lucene3xCodec.java
index 19689788375..4ad0b8b4e9d 100644
--- a/lucene/src/java/org/apache/lucene/index/codecs/lucene3x/Lucene3xCodec.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/lucene3x/Lucene3xCodec.java
@@ -20,7 +20,6 @@ package org.apache.lucene.index.codecs.lucene3x;
import java.io.IOException;
import java.util.Set;
-import org.apache.lucene.index.PerDocValues;
import org.apache.lucene.index.PerDocWriteState;
import org.apache.lucene.index.SegmentInfo;
import org.apache.lucene.index.SegmentReadState;
@@ -28,6 +27,7 @@ import org.apache.lucene.index.codecs.Codec;
import org.apache.lucene.index.codecs.DocValuesFormat;
import org.apache.lucene.index.codecs.FieldInfosFormat;
import org.apache.lucene.index.codecs.NormsFormat;
+import org.apache.lucene.index.codecs.PerDocProducer;
import org.apache.lucene.index.codecs.StoredFieldsFormat;
import org.apache.lucene.index.codecs.PerDocConsumer;
import org.apache.lucene.index.codecs.PostingsFormat;
@@ -75,7 +75,7 @@ public class Lucene3xCodec extends Codec {
}
@Override
- public PerDocValues docsProducer(SegmentReadState state) throws IOException {
+ public PerDocProducer docsProducer(SegmentReadState state) throws IOException {
return null;
}
diff --git a/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesFormat.java b/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesFormat.java
index 0257e8ba9bf..28bd0b25362 100644
--- a/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesFormat.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesFormat.java
@@ -20,12 +20,12 @@ package org.apache.lucene.index.codecs.lucene40;
import java.io.IOException;
import java.util.Set;
-import org.apache.lucene.index.PerDocValues;
import org.apache.lucene.index.PerDocWriteState;
import org.apache.lucene.index.SegmentInfo;
import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.codecs.DocValuesFormat;
import org.apache.lucene.index.codecs.PerDocConsumer;
+import org.apache.lucene.index.codecs.PerDocProducer;
import org.apache.lucene.store.Directory;
public class Lucene40DocValuesFormat extends DocValuesFormat {
@@ -36,7 +36,7 @@ public class Lucene40DocValuesFormat extends DocValuesFormat {
}
@Override
- public PerDocValues docsProducer(SegmentReadState state) throws IOException {
+ public PerDocProducer docsProducer(SegmentReadState state) throws IOException {
return new Lucene40DocValuesProducer(state);
}
diff --git a/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesProducer.java b/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesProducer.java
index c737486d610..c9baf1fa505 100644
--- a/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesProducer.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/lucene40/Lucene40DocValuesProducer.java
@@ -33,7 +33,7 @@ import org.apache.lucene.store.Directory;
import org.apache.lucene.util.IOUtils;
/**
- * Default PerDocValues implementation that uses compound file.
+ * Default PerDocProducer implementation that uses compound file.
* @lucene.experimental
*/
public class Lucene40DocValuesProducer extends DocValuesReaderBase {
diff --git a/lucene/src/java/org/apache/lucene/index/codecs/sep/SepDocValuesProducer.java b/lucene/src/java/org/apache/lucene/index/codecs/sep/SepDocValuesProducer.java
index 82daa2ee41e..349417effc1 100644
--- a/lucene/src/java/org/apache/lucene/index/codecs/sep/SepDocValuesProducer.java
+++ b/lucene/src/java/org/apache/lucene/index/codecs/sep/SepDocValuesProducer.java
@@ -28,7 +28,7 @@ import org.apache.lucene.index.codecs.DocValuesReaderBase;
import org.apache.lucene.util.IOUtils;
/**
- * Implementation of PerDocValues that uses separate files.
+ * Implementation of PerDocProducer that uses separate files.
* @lucene.experimental
*/
public class SepDocValuesProducer extends DocValuesReaderBase {
diff --git a/lucene/src/test-framework/java/org/apache/lucene/index/codecs/mocksep/MockSepDocValuesFormat.java b/lucene/src/test-framework/java/org/apache/lucene/index/codecs/mocksep/MockSepDocValuesFormat.java
index 698b8bf37ca..595f6b6c770 100644
--- a/lucene/src/test-framework/java/org/apache/lucene/index/codecs/mocksep/MockSepDocValuesFormat.java
+++ b/lucene/src/test-framework/java/org/apache/lucene/index/codecs/mocksep/MockSepDocValuesFormat.java
@@ -20,12 +20,12 @@ package org.apache.lucene.index.codecs.mocksep;
import java.io.IOException;
import java.util.Set;
-import org.apache.lucene.index.PerDocValues;
import org.apache.lucene.index.PerDocWriteState;
import org.apache.lucene.index.SegmentInfo;
import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.codecs.DocValuesFormat;
import org.apache.lucene.index.codecs.PerDocConsumer;
+import org.apache.lucene.index.codecs.PerDocProducer;
import org.apache.lucene.index.codecs.sep.SepDocValuesConsumer;
import org.apache.lucene.index.codecs.sep.SepDocValuesProducer;
import org.apache.lucene.store.Directory;
@@ -43,7 +43,7 @@ public class MockSepDocValuesFormat extends DocValuesFormat {
}
@Override
- public PerDocValues docsProducer(SegmentReadState state) throws IOException {
+ public PerDocProducer docsProducer(SegmentReadState state) throws IOException {
return new SepDocValuesProducer(state);
}
diff --git a/lucene/src/test/org/apache/lucene/index/TestAddIndexes.java b/lucene/src/test/org/apache/lucene/index/TestAddIndexes.java
index ab0b586a36e..0ab5a28657d 100755
--- a/lucene/src/test/org/apache/lucene/index/TestAddIndexes.java
+++ b/lucene/src/test/org/apache/lucene/index/TestAddIndexes.java
@@ -1284,7 +1284,7 @@ public class TestAddIndexes extends LuceneTestCase {
w.close();
IndexReader sr = getOnlySegmentReader(r3);
assertEquals(2, sr.numDocs());
- DocValues docValues = sr.perDocValues().docValues("dv");
+ DocValues docValues = sr.docValues("dv");
assertNotNull(docValues);
r3.close();
d3.close();
diff --git a/lucene/src/test/org/apache/lucene/index/TestDuelingCodecs.java b/lucene/src/test/org/apache/lucene/index/TestDuelingCodecs.java
index b9313fce97e..e7b483b8a96 100644
--- a/lucene/src/test/org/apache/lucene/index/TestDuelingCodecs.java
+++ b/lucene/src/test/org/apache/lucene/index/TestDuelingCodecs.java
@@ -18,12 +18,15 @@ package org.apache.lucene.index;
*/
import java.io.IOException;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
+import java.util.Set;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexReader.FieldOption;
import org.apache.lucene.index.codecs.Codec;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.store.Directory;
@@ -516,29 +519,15 @@ public class TestDuelingCodecs extends LuceneTestCase {
* checks that docvalues across all fields are equivalent
*/
public void assertDocValues(IndexReader leftReader, IndexReader rightReader) throws Exception {
- PerDocValues leftPerDoc = MultiPerDocValues.getPerDocs(leftReader);
- PerDocValues rightPerDoc = MultiPerDocValues.getPerDocs(rightReader);
-
- Fields leftFields = MultiFields.getFields(leftReader);
- Fields rightFields = MultiFields.getFields(rightReader);
- // Fields could be null if there are no postings,
- // but then it must be null for both
- if (leftFields == null || rightFields == null) {
- assertNull(info, leftFields);
- assertNull(info, rightFields);
- return;
- }
-
- FieldsEnum fieldsEnum = leftFields.iterator();
- String field;
- while ((field = fieldsEnum.next()) != null) {
- DocValues leftDocValues = leftPerDoc.docValues(field);
- DocValues rightDocValues = rightPerDoc.docValues(field);
- if (leftDocValues == null || rightDocValues == null) {
- assertNull(info, leftDocValues);
- assertNull(info, rightDocValues);
- continue;
- }
+ Set leftValues = new HashSet(leftReader.getFieldNames(FieldOption.DOC_VALUES));
+ Set rightValues = new HashSet(rightReader.getFieldNames(FieldOption.DOC_VALUES));
+ assertEquals(info, leftValues, rightValues);
+
+ for (String field : leftValues) {
+ DocValues leftDocValues = MultiDocValues.getDocValues(leftReader, field);
+ DocValues rightDocValues = MultiDocValues.getDocValues(rightReader, field);
+ assertNotNull(info, leftDocValues);
+ assertNotNull(info, rightDocValues);
assertDocValuesSource(leftDocValues.getDirectSource(), rightDocValues.getDirectSource());
assertDocValuesSource(leftDocValues.getSource(), rightDocValues.getSource());
}
diff --git a/lucene/src/test/org/apache/lucene/index/values/TestDocValuesIndexing.java b/lucene/src/test/org/apache/lucene/index/values/TestDocValuesIndexing.java
index ac867ace604..35fa90f4c10 100644
--- a/lucene/src/test/org/apache/lucene/index/values/TestDocValuesIndexing.java
+++ b/lucene/src/test/org/apache/lucene/index/values/TestDocValuesIndexing.java
@@ -37,13 +37,13 @@ import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LogDocMergePolicy;
import org.apache.lucene.index.LogMergePolicy;
-import org.apache.lucene.index.MultiPerDocValues;
-import org.apache.lucene.index.PerDocValues;
+import org.apache.lucene.index.MultiDocValues;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.DocValues.Source;
import org.apache.lucene.index.DocValues.Type;
import org.apache.lucene.index.codecs.Codec;
+import org.apache.lucene.index.codecs.PerDocProducer;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
@@ -104,7 +104,7 @@ public class TestDocValuesIndexing extends LuceneTestCase {
TopDocs search = searcher.search(query, 10);
assertEquals(5, search.totalHits);
ScoreDoc[] scoreDocs = search.scoreDocs;
- DocValues docValues = MultiPerDocValues.getPerDocs(reader).docValues("docId");
+ DocValues docValues = MultiDocValues.getDocValues(reader, "docId");
Source source = docValues.getSource();
for (int i = 0; i < scoreDocs.length; i++) {
assertEquals(i, scoreDocs[i].doc);
@@ -418,24 +418,8 @@ public class TestDocValuesIndexing extends LuceneTestCase {
d.close();
}
- private DocValues getDocValues(IndexReader reader, String field)
- throws IOException {
- boolean singleSeg = reader.getSequentialSubReaders().length == 1;
- PerDocValues perDoc = singleSeg ? reader.getSequentialSubReaders()[0].perDocValues()
- : MultiPerDocValues.getPerDocs(reader);
- switch (random.nextInt(singleSeg ? 3 : 2)) { // case 2 only if single seg
- case 0:
- return perDoc.docValues(field);
- case 1:
- DocValues docValues = perDoc.docValues(field);
- if (docValues != null) {
- return docValues;
- }
- throw new RuntimeException("no such field " + field);
- case 2:// this only works if we are on a single seg index!
- return reader.getSequentialSubReaders()[0].docValues(field);
- }
- throw new RuntimeException();
+ private DocValues getDocValues(IndexReader reader, String field) throws IOException {
+ return MultiDocValues.getDocValues(reader, field);
}
private Source getSource(DocValues values) throws IOException {
@@ -570,7 +554,7 @@ public class TestDocValuesIndexing extends LuceneTestCase {
w.forceMerge(1);
IndexReader r = w.getReader();
w.close();
- assertEquals(17, r.getSequentialSubReaders()[0].perDocValues().docValues("field").load().getInt(0));
+ assertEquals(17, r.getSequentialSubReaders()[0].docValues("field").load().getInt(0));
r.close();
d.close();
}
@@ -600,7 +584,7 @@ public class TestDocValuesIndexing extends LuceneTestCase {
w.forceMerge(1);
IndexReader r = w.getReader();
w.close();
- assertEquals(17, r.getSequentialSubReaders()[0].perDocValues().docValues("field").load().getInt(0));
+ assertEquals(17, r.getSequentialSubReaders()[0].docValues("field").load().getInt(0));
r.close();
d.close();
}