Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40StoredFieldsWriter.java =================================================================== --- lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40StoredFieldsWriter.java (revision 1340366) +++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40StoredFieldsWriter.java (working copy) @@ -21,6 +21,7 @@ import org.apache.lucene.codecs.StoredFieldsReader; import org.apache.lucene.codecs.StoredFieldsWriter; import org.apache.lucene.document.Document; +import org.apache.lucene.document.StoredDocument; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.IndexFileNames; @@ -297,7 +298,7 @@ // on the fly? // NOTE: it's very important to first assign to doc then pass it to // fieldsWriter.addDocument; see LUCENE-1282 - Document doc = reader.reader.document(j); + StoredDocument doc = reader.reader.document(j); addDocument(doc, mergeState.fieldInfos); docCount++; mergeState.checkAbort.work(300); @@ -324,7 +325,7 @@ for (; docCount < maxDoc; docCount++) { // NOTE: it's very important to first assign to doc then pass it to // fieldsWriter.addDocument; see LUCENE-1282 - Document doc = reader.reader.document(docCount); + StoredDocument doc = reader.reader.document(docCount); addDocument(doc, mergeState.fieldInfos); mergeState.checkAbort.work(300); } Index: lucene/core/src/java/org/apache/lucene/codecs/StoredFieldsWriter.java =================================================================== --- lucene/core/src/java/org/apache/lucene/codecs/StoredFieldsWriter.java (revision 1340366) +++ lucene/core/src/java/org/apache/lucene/codecs/StoredFieldsWriter.java (working copy) @@ -4,6 +4,7 @@ import java.io.IOException; import org.apache.lucene.document.Document; +import org.apache.lucene.document.StoredDocument; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.FieldInfos; import org.apache.lucene.index.IndexableField; @@ -88,7 +89,7 @@ // on the fly? // NOTE: it's very important to first assign to doc then pass it to // fieldsWriter.addDocument; see LUCENE-1282 - Document doc = reader.reader.document(i); + StoredDocument doc = reader.reader.document(i); addDocument(doc, mergeState.fieldInfos); docCount++; mergeState.checkAbort.work(300); Index: lucene/core/src/java/org/apache/lucene/document/DocumentStoredFieldVisitor.java =================================================================== --- lucene/core/src/java/org/apache/lucene/document/DocumentStoredFieldVisitor.java (revision 1340366) +++ lucene/core/src/java/org/apache/lucene/document/DocumentStoredFieldVisitor.java (working copy) @@ -34,7 +34,7 @@ * @lucene.experimental */ public class DocumentStoredFieldVisitor extends StoredFieldVisitor { - private final Document doc = new Document(); + private final StoredDocument doc = new StoredDocument(); private final Set fieldsToAdd; /** Load only fields named in the provided Set<String>. */ @@ -96,7 +96,7 @@ return fieldsToAdd == null || fieldsToAdd.contains(fieldInfo.name) ? Status.YES : Status.NO; } - public Document getDocument() { + public StoredDocument getDocument() { return doc; } } Index: lucene/core/src/java/org/apache/lucene/document/StoredDocument.java =================================================================== --- lucene/core/src/java/org/apache/lucene/document/StoredDocument.java (revision 0) +++ lucene/core/src/java/org/apache/lucene/document/StoredDocument.java (working copy) @@ -0,0 +1,76 @@ +package org.apache.lucene.document; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.search.IndexSearcher; + +/** + * 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. + */ + +public class StoredDocument implements Iterable{ + + private final List fields = new ArrayList(); + + + public final void add(IndexableField field) { + fields.add(field); + } + + public IndexableField[] getFields(String name) { + List result = new ArrayList(); + for (IndexableField field : fields) { + if (field.name().equals(name)) { + result.add(field); + } + } + + return result.toArray(new IndexableField[result.size()]); + } + + public final IndexableField getField(String name) { + for (IndexableField field : fields) { + if (field.name().equals(name)) { + return field; + } + } + return null; + } + + public final void removeField(String name) { + Iterator it = fields.iterator(); + while (it.hasNext()) { + IndexableField field = it.next(); + if (field.name().equals(name)) { + it.remove(); + return; + } + } + } + + public final List getFields() { + return fields; + } + + @Override + public Iterator iterator() { + return this.fields.iterator(); + } +} Index: lucene/core/src/java/org/apache/lucene/index/CheckIndex.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/CheckIndex.java (revision 1340366) +++ lucene/core/src/java/org/apache/lucene/index/CheckIndex.java (working copy) @@ -31,6 +31,7 @@ import org.apache.lucene.codecs.Codec; import org.apache.lucene.document.Document; import org.apache.lucene.document.FieldType; // for javadocs +import org.apache.lucene.document.StoredDocument; import org.apache.lucene.index.DocValues.SortedSource; import org.apache.lucene.index.DocValues.Source; import org.apache.lucene.search.DocIdSetIterator; @@ -1199,7 +1200,7 @@ for (int j = 0; j < info.docCount; ++j) { // Intentionally pull even deleted documents to // make sure they too are not corrupt: - Document doc = reader.document(j); + StoredDocument doc = reader.document(j); if (liveDocs == null || liveDocs.get(j)) { status.docCount++; status.totFields += doc.getFields().size(); Index: lucene/core/src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/IndexReader.java (revision 1340366) +++ lucene/core/src/java/org/apache/lucene/index/IndexReader.java (working copy) @@ -27,116 +27,130 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.DocumentStoredFieldVisitor; +import org.apache.lucene.document.StoredDocument; import org.apache.lucene.search.SearcherManager; // javadocs import org.apache.lucene.store.*; import org.apache.lucene.util.Bits; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.ReaderUtil; // for javadocs -/** IndexReader is an abstract class, providing an interface for accessing an - index. Search of an index is done entirely through this abstract interface, - so that any subclass which implements it is searchable. - -

There are two different types of IndexReaders: -

    -
  • {@link AtomicReader}: These indexes do not consist of several sub-readers, - they are atomic. They support retrieval of stored fields, doc values, terms, - and postings. -
  • {@link CompositeReader}: Instances (like {@link DirectoryReader}) - of this reader can only - be used to get stored fields from the underlying AtomicReaders, - but it is not possible to directly retrieve postings. To do that, get - the sub-readers via {@link CompositeReader#getSequentialSubReaders}. - Alternatively, you can mimic an {@link AtomicReader} (with a serious slowdown), - by wrapping composite readers with {@link SlowCompositeReaderWrapper}. -
- -

IndexReader instances for indexes on disk are usually constructed - with a call to one of the static DirectoryReader,open() methods, - e.g. {@link DirectoryReader#open(Directory)}. {@link DirectoryReader} implements - the {@link CompositeReader} interface, it is not possible to directly get postings. - -

For efficiency, in this API documents are often referred to via - document numbers, non-negative integers which each name a unique - document in the index. These document numbers are ephemeral -- they may change - as documents are added to and deleted from an index. Clients should thus not - rely on a given document having the same number between sessions. - -

-

NOTE: {@link - IndexReader} instances are completely thread - safe, meaning multiple threads can call any of its methods, - concurrently. If your application requires external - synchronization, you should not synchronize on the - IndexReader instance; use your own - (non-Lucene) objects instead. -*/ +/** + * IndexReader is an abstract class, providing an interface for accessing an + * index. Search of an index is done entirely through this abstract interface, + * so that any subclass which implements it is searchable. + * + *

+ * There are two different types of IndexReaders: + *

    + *
  • {@link AtomicReader}: These indexes do not consist of several + * sub-readers, they are atomic. They support retrieval of stored fields, doc + * values, terms, and postings. + *
  • {@link CompositeReader}: Instances (like {@link DirectoryReader}) of this + * reader can only be used to get stored fields from the underlying + * AtomicReaders, but it is not possible to directly retrieve postings. To do + * that, get the sub-readers via {@link CompositeReader#getSequentialSubReaders} + * . Alternatively, you can mimic an {@link AtomicReader} (with a serious + * slowdown), by wrapping composite readers with + * {@link SlowCompositeReaderWrapper}. + *
+ * + *

+ * IndexReader instances for indexes on disk are usually constructed with a call + * to one of the static DirectoryReader,open() methods, e.g. + * {@link DirectoryReader#open(Directory)}. {@link DirectoryReader} implements + * the {@link CompositeReader} interface, it is not possible to directly get + * postings. + * + *

+ * For efficiency, in this API documents are often referred to via document + * numbers, non-negative integers which each name a unique document in the + * index. These document numbers are ephemeral -- they may change as documents + * are added to and deleted from an index. Clients should thus not rely on a + * given document having the same number between sessions. + * + *

+ * + *

+ * NOTE: {@link IndexReader} instances are completely thread safe, + * meaning multiple threads can call any of its methods, concurrently. If your + * application requires external synchronization, you should not + * synchronize on the IndexReader instance; use your own + * (non-Lucene) objects instead. + */ public abstract class IndexReader implements Closeable { private boolean closed = false; private boolean closedByChild = false; private final AtomicInteger refCount = new AtomicInteger(1); - + IndexReader() { - if (!(this instanceof CompositeReader || this instanceof AtomicReader)) - throw new Error("IndexReader should never be directly extended, subclass AtomicReader or CompositeReader instead."); + if (!(this instanceof CompositeReader || this instanceof AtomicReader)) throw new Error( + "IndexReader should never be directly extended, subclass AtomicReader or CompositeReader instead."); } /** - * A custom listener that's invoked when the IndexReader - * is closed. - * + * A custom listener that's invoked when the IndexReader is closed. + * * @lucene.experimental */ public static interface ReaderClosedListener { public void onClose(IndexReader reader); } - - private final Set readerClosedListeners = - Collections.synchronizedSet(new LinkedHashSet()); - - private final Set parentReaders = - Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap())); - - /** Expert: adds a {@link ReaderClosedListener}. The - * provided listener will be invoked when this reader is closed. - * - * @lucene.experimental */ + + private final Set readerClosedListeners = Collections + .synchronizedSet(new LinkedHashSet()); + + private final Set parentReaders = Collections + .synchronizedSet(Collections + .newSetFromMap(new WeakHashMap())); + + /** + * Expert: adds a {@link ReaderClosedListener}. The provided listener will be + * invoked when this reader is closed. + * + * @lucene.experimental + */ public final void addReaderClosedListener(ReaderClosedListener listener) { ensureOpen(); readerClosedListeners.add(listener); } - - /** Expert: remove a previously added {@link ReaderClosedListener}. - * - * @lucene.experimental */ + + /** + * Expert: remove a previously added {@link ReaderClosedListener}. + * + * @lucene.experimental + */ public final void removeReaderClosedListener(ReaderClosedListener listener) { ensureOpen(); readerClosedListeners.remove(listener); } - /** Expert: This method is called by {@code IndexReader}s which wrap other readers - * (e.g. {@link CompositeReader} or {@link FilterAtomicReader}) to register the parent - * at the child (this reader) on construction of the parent. When this reader is closed, - * it will mark all registered parents as closed, too. The references to parent readers - * are weak only, so they can be GCed once they are no longer in use. - * @lucene.experimental */ + /** + * Expert: This method is called by {@code IndexReader}s which wrap other + * readers (e.g. {@link CompositeReader} or {@link FilterAtomicReader}) to + * register the parent at the child (this reader) on construction of the + * parent. When this reader is closed, it will mark all registered parents as + * closed, too. The references to parent readers are weak only, so they can be + * GCed once they are no longer in use. + * + * @lucene.experimental + */ public final void registerParentReader(IndexReader reader) { ensureOpen(); parentReaders.add(reader); } - + private void notifyReaderClosedListeners() { - synchronized(readerClosedListeners) { - for(ReaderClosedListener listener : readerClosedListeners) { + synchronized (readerClosedListeners) { + for (ReaderClosedListener listener : readerClosedListeners) { listener.onClose(this); } } } - + private void reportCloseToParentReaders() { - synchronized(parentReaders) { - for(IndexReader parent : parentReaders) { + synchronized (parentReaders) { + for (IndexReader parent : parentReaders) { parent.closedByChild = true; // cross memory barrier by a fake write: parent.refCount.addAndGet(0); @@ -145,7 +159,7 @@ } } } - + /** Expert: returns the current refCount for this reader */ public final int getRefCount() { // NOTE: don't ensureOpen, so that callers can see @@ -154,17 +168,14 @@ } /** - * Expert: increments the refCount of this IndexReader - * instance. RefCounts are used to determine when a - * reader can be closed safely, i.e. as soon as there are - * no more references. Be sure to always call a - * corresponding {@link #decRef}, in a finally clause; - * otherwise the reader may never be closed. Note that - * {@link #close} simply calls decRef(), which means that - * the IndexReader will not really be closed until {@link - * #decRef} has been called for all outstanding - * references. - * + * Expert: increments the refCount of this IndexReader instance. RefCounts are + * used to determine when a reader can be closed safely, i.e. as soon as there + * are no more references. Be sure to always call a corresponding + * {@link #decRef}, in a finally clause; otherwise the reader may never be + * closed. Note that {@link #close} simply calls decRef(), which means that + * the IndexReader will not really be closed until {@link #decRef} has been + * called for all outstanding references. + * * @see #decRef * @see #tryIncRef */ @@ -174,46 +185,41 @@ } /** - * Expert: increments the refCount of this IndexReader - * instance only if the IndexReader has not been closed yet - * and returns true iff the refCount was - * successfully incremented, otherwise false. - * If this method returns false the reader is either - * already closed or is currently been closed. Either way this - * reader instance shouldn't be used by an application unless - * true is returned. + * Expert: increments the refCount of this IndexReader instance only if the + * IndexReader has not been closed yet and returns true iff the + * refCount was successfully incremented, otherwise false. If + * this method returns false the reader is either already closed + * or is currently been closed. Either way this reader instance shouldn't be + * used by an application unless true is returned. *

- * RefCounts are used to determine when a - * reader can be closed safely, i.e. as soon as there are - * no more references. Be sure to always call a - * corresponding {@link #decRef}, in a finally clause; - * otherwise the reader may never be closed. Note that - * {@link #close} simply calls decRef(), which means that - * the IndexReader will not really be closed until {@link - * #decRef} has been called for all outstanding - * references. - * + * RefCounts are used to determine when a reader can be closed safely, i.e. as + * soon as there are no more references. Be sure to always call a + * corresponding {@link #decRef}, in a finally clause; otherwise the reader + * may never be closed. Note that {@link #close} simply calls decRef(), which + * means that the IndexReader will not really be closed until {@link #decRef} + * has been called for all outstanding references. + * * @see #decRef * @see #incRef */ public final boolean tryIncRef() { int count; while ((count = refCount.get()) > 0) { - if (refCount.compareAndSet(count, count+1)) { + if (refCount.compareAndSet(count, count + 1)) { return true; } } return false; } - + /** - * Expert: decreases the refCount of this IndexReader - * instance. If the refCount drops to 0, then this - * reader is closed. If an exception is hit, the refCount - * is unchanged. - * - * @throws IOException in case an IOException occurs in doClose() - * + * Expert: decreases the refCount of this IndexReader instance. If the + * refCount drops to 0, then this reader is closed. If an exception is hit, + * the refCount is unchanged. + * + * @throws IOException + * in case an IOException occurs in doClose() + * * @see #incRef */ public final void decRef() throws IOException { @@ -238,28 +244,34 @@ reportCloseToParentReaders(); notifyReaderClosedListeners(); } else if (rc < 0) { - throw new IllegalStateException("too many decRef calls: refCount is " + rc + " after decrement"); + throw new IllegalStateException("too many decRef calls: refCount is " + + rc + " after decrement"); } } /** - * @throws AlreadyClosedException if this IndexReader is closed + * @throws AlreadyClosedException + * if this IndexReader is closed */ protected final void ensureOpen() throws AlreadyClosedException { if (refCount.get() <= 0) { throw new AlreadyClosedException("this IndexReader is closed"); } - // the happens before rule on reading the refCount, which must be after the fake write, + // the happens before rule on reading the refCount, which must be after the + // fake write, // ensures that we see the value: if (closedByChild) { - throw new AlreadyClosedException("this IndexReader cannot be used anymore as one of its child readers was closed"); + throw new AlreadyClosedException( + "this IndexReader cannot be used anymore as one of its child readers was closed"); } } - /** {@inheritDoc} - *

For caching purposes, {@code IndexReader} subclasses are not allowed - * to implement equals/hashCode, so methods are declared final. - * To lookup instances from caches use {@link #getCoreCacheKey} and + /** + * {@inheritDoc} + *

+ * For caching purposes, {@code IndexReader} subclasses are not allowed to + * implement equals/hashCode, so methods are declared final. To lookup + * instances from caches use {@link #getCoreCacheKey} and * {@link #getCombinedCoreAndDeletesKey}. */ @Override @@ -267,10 +279,12 @@ return (this == obj); } - /** {@inheritDoc} - *

For caching purposes, {@code IndexReader} subclasses are not allowed - * to implement equals/hashCode, so methods are declared final. - * To lookup instances from caches use {@link #getCoreCacheKey} and + /** + * {@inheritDoc} + *

+ * For caching purposes, {@code IndexReader} subclasses are not allowed to + * implement equals/hashCode, so methods are declared final. To lookup + * instances from caches use {@link #getCoreCacheKey} and * {@link #getCombinedCoreAndDeletesKey}. */ @Override @@ -278,188 +292,222 @@ return System.identityHashCode(this); } - /** Returns a IndexReader reading the index in the given - * Directory - * @param directory the index directory - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error + /** + * Returns a IndexReader reading the index in the given Directory + * + * @param directory + * the index directory + * @throws CorruptIndexException + * if the index is corrupt + * @throws IOException + * if there is a low-level IO error * @deprecated Use {@link DirectoryReader#open(Directory)} */ @Deprecated - public static DirectoryReader open(final Directory directory) throws CorruptIndexException, IOException { + public static DirectoryReader open(final Directory directory) + throws CorruptIndexException, IOException { return DirectoryReader.open(directory); } - /** Expert: Returns a IndexReader reading the index in the given - * Directory with the given termInfosIndexDivisor. - * @param directory the index directory - * @param termInfosIndexDivisor Subsamples which indexed - * terms are loaded into RAM. This has the same effect as {@link - * IndexWriterConfig#setTermIndexInterval} except that setting - * must be done at indexing time while this setting can be - * set per reader. When set to N, then one in every - * N*termIndexInterval terms in the index is loaded into - * memory. By setting this to a value > 1 you can reduce - * memory usage, at the expense of higher latency when - * loading a TermInfo. The default value is 1. Set this - * to -1 to skip loading the terms index entirely. - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error + /** + * Expert: Returns a IndexReader reading the index in the given Directory with + * the given termInfosIndexDivisor. + * + * @param directory + * the index directory + * @param termInfosIndexDivisor + * Subsamples which indexed terms are loaded into RAM. This has the + * same effect as {@link IndexWriterConfig#setTermIndexInterval} + * except that setting must be done at indexing time while this + * setting can be set per reader. When set to N, then one in every + * N*termIndexInterval terms in the index is loaded into memory. By + * setting this to a value > 1 you can reduce memory usage, at the + * expense of higher latency when loading a TermInfo. The default + * value is 1. Set this to -1 to skip loading the terms index + * entirely. + * @throws CorruptIndexException + * if the index is corrupt + * @throws IOException + * if there is a low-level IO error * @deprecated Use {@link DirectoryReader#open(Directory,int)} */ @Deprecated - public static DirectoryReader open(final Directory directory, int termInfosIndexDivisor) throws CorruptIndexException, IOException { + public static DirectoryReader open(final Directory directory, + int termInfosIndexDivisor) throws CorruptIndexException, IOException { return DirectoryReader.open(directory, termInfosIndexDivisor); } /** - * Open a near real time IndexReader from the {@link org.apache.lucene.index.IndexWriter}. - * - * @param writer The IndexWriter to open from - * @param applyAllDeletes If true, all buffered deletes will - * be applied (made visible) in the returned reader. If - * false, the deletes are not applied but remain buffered - * (in IndexWriter) so that they will be applied in the - * future. Applying deletes can be costly, so if your app - * can tolerate deleted documents being returned you might - * gain some performance by passing false. + * Open a near real time IndexReader from the + * {@link org.apache.lucene.index.IndexWriter}. + * + * @param writer + * The IndexWriter to open from + * @param applyAllDeletes + * If true, all buffered deletes will be applied (made visible) in + * the returned reader. If false, the deletes are not applied but + * remain buffered (in IndexWriter) so that they will be applied in + * the future. Applying deletes can be costly, so if your app can + * tolerate deleted documents being returned you might gain some + * performance by passing false. * @return The new IndexReader * @throws CorruptIndexException - * @throws IOException if there is a low-level IO error - * + * @throws IOException + * if there is a low-level IO error + * * @see DirectoryReader#openIfChanged(DirectoryReader,IndexWriter,boolean) - * + * * @lucene.experimental * @deprecated Use {@link DirectoryReader#open(IndexWriter,boolean)} */ @Deprecated - public static DirectoryReader open(final IndexWriter writer, boolean applyAllDeletes) throws CorruptIndexException, IOException { + public static DirectoryReader open(final IndexWriter writer, + boolean applyAllDeletes) throws CorruptIndexException, IOException { return DirectoryReader.open(writer, applyAllDeletes); } - - /** Expert: returns an IndexReader reading the index in the given - * {@link IndexCommit}. - * @param commit the commit point to open - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error + + /** + * Expert: returns an IndexReader reading the index in the given + * {@link IndexCommit}. + * + * @param commit + * the commit point to open + * @throws CorruptIndexException + * if the index is corrupt + * @throws IOException + * if there is a low-level IO error * @deprecated Use {@link DirectoryReader#open(IndexCommit)} */ @Deprecated - public static DirectoryReader open(final IndexCommit commit) throws CorruptIndexException, IOException { + public static DirectoryReader open(final IndexCommit commit) + throws CorruptIndexException, IOException { return DirectoryReader.open(commit); } - - - /** Expert: returns an IndexReader reading the index in the given - * {@link IndexCommit} and termInfosIndexDivisor. - * @param commit the commit point to open - * @param termInfosIndexDivisor Subsamples which indexed - * terms are loaded into RAM. This has the same effect as {@link - * IndexWriterConfig#setTermIndexInterval} except that setting - * must be done at indexing time while this setting can be - * set per reader. When set to N, then one in every - * N*termIndexInterval terms in the index is loaded into - * memory. By setting this to a value > 1 you can reduce - * memory usage, at the expense of higher latency when - * loading a TermInfo. The default value is 1. Set this - * to -1 to skip loading the terms index entirely. - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error + + /** + * Expert: returns an IndexReader reading the index in the given + * {@link IndexCommit} and termInfosIndexDivisor. + * + * @param commit + * the commit point to open + * @param termInfosIndexDivisor + * Subsamples which indexed terms are loaded into RAM. This has the + * same effect as {@link IndexWriterConfig#setTermIndexInterval} + * except that setting must be done at indexing time while this + * setting can be set per reader. When set to N, then one in every + * N*termIndexInterval terms in the index is loaded into memory. By + * setting this to a value > 1 you can reduce memory usage, at the + * expense of higher latency when loading a TermInfo. The default + * value is 1. Set this to -1 to skip loading the terms index + * entirely. + * @throws CorruptIndexException + * if the index is corrupt + * @throws IOException + * if there is a low-level IO error * @deprecated Use {@link DirectoryReader#open(IndexCommit,int)} */ @Deprecated - public static DirectoryReader open(final IndexCommit commit, int termInfosIndexDivisor) throws CorruptIndexException, IOException { + public static DirectoryReader open(final IndexCommit commit, + int termInfosIndexDivisor) throws CorruptIndexException, IOException { return DirectoryReader.open(commit, termInfosIndexDivisor); } - - /** Retrieve term vectors for this document, or null if - * term vectors were not indexed. The returned Fields - * instance acts like a single-document inverted index - * (the docID will be 0). */ - public abstract Fields getTermVectors(int docID) - throws IOException; - - /** Retrieve term vector for this document and field, or - * null if term vectors were not indexed. The returned - * Fields instance acts like a single-document inverted - * index (the docID will be 0). */ - public final Terms getTermVector(int docID, String field) - throws IOException { + + /** + * Retrieve term vectors for this document, or null if term vectors were not + * indexed. The returned Fields instance acts like a single-document inverted + * index (the docID will be 0). + */ + public abstract Fields getTermVectors(int docID) throws IOException; + + /** + * Retrieve term vector for this document and field, or null if term vectors + * were not indexed. The returned Fields instance acts like a single-document + * inverted index (the docID will be 0). + */ + public final Terms getTermVector(int docID, String field) throws IOException { Fields vectors = getTermVectors(docID); if (vectors == null) { return null; } return vectors.terms(field); } - + /** Returns the number of documents in this index. */ public abstract int numDocs(); - - /** Returns one greater than the largest possible document number. - * This may be used to, e.g., determine how big to allocate an array which - * will have an element for every document number in an index. + + /** + * Returns one greater than the largest possible document number. This may be + * used to, e.g., determine how big to allocate an array which will have an + * element for every document number in an index. */ public abstract int maxDoc(); - + /** Returns the number of deleted documents. */ public final int numDeletedDocs() { return maxDoc() - numDocs(); } - - /** Expert: visits the fields of a stored document, for - * custom processing/loading of each field. If you - * simply want to load all fields, use {@link - * #document(int)}. If you want to load a subset, use - * {@link DocumentStoredFieldVisitor}. */ - public abstract void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException; /** + * Expert: visits the fields of a stored document, for custom + * processing/loading of each field. If you simply want to load all fields, + * use {@link #document(int)}. If you want to load a subset, use + * {@link DocumentStoredFieldVisitor}. + */ + public abstract void document(int docID, StoredFieldVisitor visitor) + throws CorruptIndexException, IOException; + + /** * Returns the stored fields of the nth - * Document in this index. This is just - * sugar for using {@link DocumentStoredFieldVisitor}. + * Document in this index. This is just sugar for using + * {@link DocumentStoredFieldVisitor}. *

* NOTE: for performance reasons, this method does not check if the * requested document is deleted, and therefore asking for a deleted document * may yield unspecified results. Usually this is not required, however you - * can test if the doc is deleted by checking the {@link - * Bits} returned from {@link MultiFields#getLiveDocs}. - * - * NOTE: only the content of a field is returned, - * if that field was stored during indexing. Metadata - * like boost, omitNorm, IndexOptions, tokenized, etc., - * are not preserved. + * can test if the doc is deleted by checking the {@link Bits} returned from + * {@link MultiFields#getLiveDocs}. * - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error + * NOTE: only the content of a field is returned, if that field was + * stored during indexing. Metadata like boost, omitNorm, IndexOptions, + * tokenized, etc., are not preserved. + * + * @throws CorruptIndexException + * if the index is corrupt + * @throws IOException + * if there is a low-level IO error */ // TODO: we need a separate StoredField, so that the // Document returned here contains that class not // IndexableField - public final Document document(int docID) throws CorruptIndexException, IOException { + public final StoredDocument document(int docID) throws CorruptIndexException, + IOException { final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(); document(docID, visitor); return visitor.getDocument(); } - + /** - * Like {@link #document(int)} but only loads the specified - * fields. Note that this is simply sugar for {@link - * DocumentStoredFieldVisitor#DocumentStoredFieldVisitor(Set)}. + * Like {@link #document(int)} but only loads the specified fields. Note that + * this is simply sugar for + * {@link DocumentStoredFieldVisitor#DocumentStoredFieldVisitor(Set)}. */ - public final Document document(int docID, Set fieldsToLoad) throws CorruptIndexException, IOException { - final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(fieldsToLoad); + public final StoredDocument document(int docID, Set fieldsToLoad) + throws CorruptIndexException, IOException { + final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor( + fieldsToLoad); document(docID, visitor); return visitor.getDocument(); } - + /** Returns true if any documents have been deleted */ public abstract boolean hasDeletions(); - + /** - * Closes files associated with this index. - * Also saves any new deletions to disk. - * No other methods should be called after this has been called. - * @throws IOException if there is a low-level IO error + * Closes files associated with this index. Also saves any new deletions to + * disk. No other methods should be called after this has been called. + * + * @throws IOException + * if there is a low-level IO error */ public final synchronized void close() throws IOException { if (!closed) { @@ -470,59 +518,65 @@ /** Implements close. */ protected abstract void doClose() throws IOException; - + /** * Expert: Returns a the root {@link IndexReaderContext} for this * {@link IndexReader}'s sub-reader tree. Iff this reader is composed of sub * readers ,ie. this reader being a composite reader, this method returns a - * {@link CompositeReaderContext} holding the reader's direct children as well as a - * view of the reader tree's atomic leaf contexts. All sub- + * {@link CompositeReaderContext} holding the reader's direct children as well + * as a view of the reader tree's atomic leaf contexts. All sub- * {@link IndexReaderContext} instances referenced from this readers top-level * context are private to this reader and are not shared with another context * tree. For example, IndexSearcher uses this API to drive searching by one * atomic leaf reader at a time. If this reader is not composed of child * readers, this method returns an {@link AtomicReaderContext}. *

- * Note: Any of the sub-{@link CompositeReaderContext} instances reference from this - * top-level context holds a null {@link CompositeReaderContext#leaves()} - * reference. Only the top-level context maintains the convenience leaf-view - * for performance reasons. + * Note: Any of the sub-{@link CompositeReaderContext} instances reference + * from this top-level context holds a null + * {@link CompositeReaderContext#leaves()} reference. Only the top-level + * context maintains the convenience leaf-view for performance reasons. * * @lucene.experimental */ public abstract IndexReaderContext getTopReaderContext(); - - /** Expert: Returns a key for this IndexReader, so FieldCache/CachingWrapperFilter can find - * it again. - * This key must not have equals()/hashCode() methods, so "equals" means "identical". */ + + /** + * Expert: Returns a key for this IndexReader, so + * FieldCache/CachingWrapperFilter can find it again. This key must not have + * equals()/hashCode() methods, so "equals" means + * "identical". + */ public Object getCoreCacheKey() { // Don't can ensureOpen since FC calls this (to evict) // on close return this; } - - /** Expert: Returns a key for this IndexReader that also includes deletions, - * so FieldCache/CachingWrapperFilter can find it again. - * This key must not have equals()/hashCode() methods, so "equals" means "identical". */ + + /** + * Expert: Returns a key for this IndexReader that also includes deletions, so + * FieldCache/CachingWrapperFilter can find it again. This key must not have + * equals()/hashCode() methods, so "equals" means + * "identical". + */ public Object getCombinedCoreAndDeletesKey() { // Don't can ensureOpen since FC calls this (to evict) // on close return this; } - /** Returns the number of documents containing the - * term. This method returns 0 if the term or - * field does not exists. This method does not take into - * account deleted documents that have not yet been merged - * away. */ + /** + * Returns the number of documents containing the term. This + * method returns 0 if the term or field does not exists. This method does not + * take into account deleted documents that have not yet been merged away. + */ public final int docFreq(Term term) throws IOException { return docFreq(term.field(), term.bytes()); } - - /** Returns the number of documents containing the - * term. This method returns 0 if the term or - * field does not exists. This method does not take into - * account deleted documents that have not yet been merged - * away. */ + + /** + * Returns the number of documents containing the term. This + * method returns 0 if the term or field does not exists. This method does not + * take into account deleted documents that have not yet been merged away. + */ public abstract int docFreq(String field, BytesRef term) throws IOException; } Index: lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java (revision 1340366) +++ lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java (working copy) @@ -26,6 +26,7 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; +import org.apache.lucene.document.StoredDocument; import org.apache.lucene.index.IndexWriterConfig.OpenMode; import org.apache.lucene.store.Directory; import org.apache.lucene.store.LockObtainFailedException; @@ -68,7 +69,7 @@ int numDocs = r.numDocs(); // index is allowed to have exactly one document or 0. if (numDocs == 1) { - Document doc = r.document(r.maxDoc() - 1); + StoredDocument doc = r.document(r.maxDoc() - 1); if (doc.getField(SNAPSHOTS_ID) == null) { throw new IllegalStateException("directory is not a valid snapshots store!"); } Index: lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java =================================================================== --- lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java (revision 1340366) +++ lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java (working copy) @@ -31,6 +31,7 @@ import java.util.concurrent.locks.ReentrantLock; import org.apache.lucene.document.Document; +import org.apache.lucene.document.StoredDocument; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.DirectoryReader; // javadocs @@ -180,7 +181,7 @@ } /** Sugar for .getIndexReader().document(docID) */ - public Document doc(int docID) throws CorruptIndexException, IOException { + public StoredDocument doc(int docID) throws CorruptIndexException, IOException { return reader.document(docID); } @@ -190,7 +191,7 @@ } /** Sugar for .getIndexReader().document(docID, fieldsToLoad) */ - public final Document document(int docID, Set fieldsToLoad) throws CorruptIndexException, IOException { + public final StoredDocument document(int docID, Set fieldsToLoad) throws CorruptIndexException, IOException { return reader.document(docID, fieldsToLoad); }