Return-Path: X-Original-To: apmail-lucene-commits-archive@www.apache.org Delivered-To: apmail-lucene-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CDBD39671 for ; Sat, 21 Jan 2012 23:23:24 +0000 (UTC) Received: (qmail 62984 invoked by uid 500); 21 Jan 2012 23:23:24 -0000 Mailing-List: contact commits-help@lucene.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@lucene.apache.org Delivered-To: mailing list commits@lucene.apache.org Received: (qmail 62977 invoked by uid 99); 21 Jan 2012 23:23:24 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 21 Jan 2012 23:23:24 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 21 Jan 2012 23:23:16 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id B7DAA238889B; Sat, 21 Jan 2012 23:22:53 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1234441 [1/3] - in /lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene: codecs/ codecs/lucene40/ codecs/simpletext/ index/ search/ util/ Date: Sat, 21 Jan 2012 23:22:51 -0000 To: commits@lucene.apache.org From: uschindler@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120121232253.B7DAA238889B@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: uschindler Date: Sat Jan 21 23:22:50 2012 New Revision: 1234441 URL: http://svn.apache.org/viewvc?rev=1234441&view=rev Log: LUCENE-2858: First steps, still incomplete. No tests pass or even compile, but core code now compiles. See issue! Added: lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/AtomicIndexReader.java - copied, changed from r1234311, lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/IndexReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/CompositeIndexReader.java - copied, changed from r1234311, lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/IndexReader.java Modified: lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/lucene40/Lucene40NormsFormat.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/BaseMultiReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/BufferedDeletesStream.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/DirectoryReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/FilterIndexReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/IndexReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/IndexWriter.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/MergeState.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/MultiDocValues.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/MultiFields.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/MultiReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/ParallelReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/SegmentMerger.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/SegmentReader.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/SlowMultiReaderWrapper.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/CachingWrapperFilter.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/FieldCache.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/FieldCacheImpl.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/MultiTermQueryWrapperFilter.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/PhraseQuery.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/QueryWrapperFilter.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/ScoringRewrite.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/SearcherLifetimeManager.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/SearcherManager.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/TermQuery.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/search/TopTermsRewrite.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/util/FieldCacheSanityChecker.java lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/util/ReaderUtil.java Modified: lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java?rev=1234441&r1=1234440&r2=1234441&view=diff ============================================================================== --- lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java (original) +++ lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java Sat Jan 21 23:22:50 2012 @@ -20,7 +20,7 @@ import java.io.IOException; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.DocValues; -import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.AtomicIndexReader; import org.apache.lucene.index.MergeState; import org.apache.lucene.index.DocValues.Type; @@ -65,13 +65,13 @@ public abstract class PerDocConsumer imp /** * Returns a {@link DocValues} instance for merging from the given reader for the given * {@link FieldInfo}. This method is used for merging and uses - * {@link IndexReader#docValues(String)} by default. + * {@link AtomicIndexReader#docValues(String)} by default. *

* To enable {@link DocValues} merging for different {@link DocValues} than * the default override this method accordingly. *

*/ - protected DocValues getDocValuesForMerge(IndexReader reader, FieldInfo info) throws IOException { + protected DocValues getDocValuesForMerge(AtomicIndexReader reader, FieldInfo info) throws IOException { return reader.docValues(info.name); } Modified: lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/lucene40/Lucene40NormsFormat.java URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/lucene40/Lucene40NormsFormat.java?rev=1234441&r1=1234440&r2=1234441&view=diff ============================================================================== --- lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/lucene40/Lucene40NormsFormat.java (original) +++ lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/lucene40/Lucene40NormsFormat.java Sat Jan 21 23:22:50 2012 @@ -26,7 +26,7 @@ import org.apache.lucene.index.DocValues import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.FieldInfos; import org.apache.lucene.index.IndexFileNames; -import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.AtomicIndexReader; import org.apache.lucene.index.PerDocWriteState; import org.apache.lucene.index.SegmentInfo; import org.apache.lucene.index.SegmentReadState; @@ -95,7 +95,7 @@ public class Lucene40NormsFormat extends } @Override - protected DocValues getDocValuesForMerge(IndexReader reader, FieldInfo info) + protected DocValues getDocValuesForMerge(AtomicIndexReader reader, FieldInfo info) throws IOException { return reader.normValues(info.name); } Modified: lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java?rev=1234441&r1=1234440&r2=1234441&view=diff ============================================================================== --- lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java (original) +++ lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java Sat Jan 21 23:22:50 2012 @@ -28,7 +28,7 @@ import org.apache.lucene.index.DocValues import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.FieldInfos; import org.apache.lucene.index.IndexFileNames; -import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.AtomicIndexReader; import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.SegmentInfo; import org.apache.lucene.store.Directory; @@ -87,7 +87,7 @@ public class SimpleTextNormsConsumer ext } @Override - protected DocValues getDocValuesForMerge(IndexReader reader, FieldInfo info) + protected DocValues getDocValuesForMerge(AtomicIndexReader reader, FieldInfo info) throws IOException { return reader.normValues(info.name); } Copied: lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/AtomicIndexReader.java (from r1234311, lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/IndexReader.java) URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/AtomicIndexReader.java?p2=lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/AtomicIndexReader.java&p1=lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/IndexReader.java&r1=1234311&r2=1234441&rev=1234441&view=diff ============================================================================== --- lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/IndexReader.java (original) +++ lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/AtomicIndexReader.java Sat Jan 21 23:22:50 2012 @@ -24,7 +24,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; import org.apache.lucene.document.Document; import org.apache.lucene.document.DocumentStoredFieldVisitor; @@ -66,626 +65,14 @@ import org.apache.lucene.util.ReaderUtil IndexReader instance; use your own (non-Lucene) objects instead. */ -public abstract class IndexReader implements Closeable { +public abstract class AtomicIndexReader extends IndexReader { - /** - * 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()); - - /** 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 */ - public final void removeReaderClosedListener(ReaderClosedListener listener) { - ensureOpen(); - readerClosedListeners.remove(listener); - } - - private final void notifyReaderClosedListeners() { - synchronized(readerClosedListeners) { - for(ReaderClosedListener listener : readerClosedListeners) { - listener.onClose(this); - } - } - } - - private volatile boolean closed; - - private final AtomicInteger refCount = new AtomicInteger(); - - static int DEFAULT_TERMS_INDEX_DIVISOR = 1; - - /** Expert: returns the current refCount for this reader */ - public final int getRefCount() { - // NOTE: don't ensureOpen, so that callers can see - // refCount is 0 (reader is closed) - return refCount.get(); - } - - /** - * 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 - */ - public final void incRef() { - ensureOpen(); - refCount.incrementAndGet(); - } - - /** - * 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. - * - * @see #decRef - * @see #incRef - */ - public final boolean tryIncRef() { - int count; - while ((count = refCount.get()) > 0) { - if (refCount.compareAndSet(count, count+1)) { - return true; - } - } - return false; + protected AtomicIndexReader() { + super(); } - /** {@inheritDoc} */ @Override - public String toString() { - final StringBuilder buffer = new StringBuilder(); - buffer.append(getClass().getSimpleName()); - buffer.append('('); - final IndexReader[] subReaders = getSequentialSubReaders(); - if ((subReaders != null) && (subReaders.length > 0)) { - buffer.append(subReaders[0]); - for (int i = 1; i < subReaders.length; ++i) { - buffer.append(" ").append(subReaders[i]); - } - } - buffer.append(')'); - return buffer.toString(); - } - - /** - * 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 { - ensureOpen(); - final int rc = refCount.decrementAndGet(); - if (rc == 0) { - boolean success = false; - try { - doClose(); - success = true; - } finally { - if (!success) { - // Put reference back on failure - refCount.incrementAndGet(); - } - } - notifyReaderClosedListeners(); - } else if (rc < 0) { - throw new IllegalStateException("too many decRef calls: refCount is " + rc + " after decrement"); - } - } - - protected IndexReader() { - refCount.set(1); - } - - /** - * @throws AlreadyClosedException if this IndexReader is closed - */ - protected final void ensureOpen() throws AlreadyClosedException { - if (refCount.get() <= 0) { - throw new AlreadyClosedException("this IndexReader is closed"); - } - } - - /** 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 - */ - public static IndexReader open(final Directory directory) throws CorruptIndexException, IOException { - return DirectoryReader.open(directory, null, DEFAULT_TERMS_INDEX_DIVISOR); - } - - /** 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 - */ - public static IndexReader open(final Directory directory, int termInfosIndexDivisor) throws CorruptIndexException, IOException { - return DirectoryReader.open(directory, null, 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. - * @return The new IndexReader - * @throws CorruptIndexException - * @throws IOException if there is a low-level IO error - * - * @see #openIfChanged(IndexReader,IndexWriter,boolean) - * - * @lucene.experimental - */ - public static IndexReader open(final IndexWriter writer, boolean applyAllDeletes) throws CorruptIndexException, IOException { - return writer.getReader(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 - */ - public static IndexReader open(final IndexCommit commit) throws CorruptIndexException, IOException { - return DirectoryReader.open(commit.getDirectory(), commit, DEFAULT_TERMS_INDEX_DIVISOR); - } - - - /** 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 - */ - public static IndexReader open(final IndexCommit commit, int termInfosIndexDivisor) throws CorruptIndexException, IOException { - return DirectoryReader.open(commit.getDirectory(), commit, termInfosIndexDivisor); - } - - /** - * If the index has changed since the provided reader was - * opened, open and return a new reader; else, return - * null. The new reader, if not null, will be the same - * type of reader as the previous one, ie an NRT reader - * will open a new NRT reader, a MultiReader will open a - * new MultiReader, etc. - * - *

This method is typically far less costly than opening a - * fully new IndexReader as it shares - * resources (for example sub-readers) with the provided - * IndexReader, when possible. - * - *

The provided reader is not closed (you are responsible - * for doing so); if a new reader is returned you also - * must eventually close it. Be sure to never close a - * reader while other threads are still using it; see - * {@link SearcherManager} to simplify managing this. - * - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error - * @return null if there are no changes; else, a new - * IndexReader instance which you must eventually close - */ - public static IndexReader openIfChanged(IndexReader oldReader) throws IOException { - final IndexReader newReader = oldReader.doOpenIfChanged(); - assert newReader != oldReader; - return newReader; - } - - /** - * If the IndexCommit differs from what the - * provided reader is searching, open and return a new - * reader; else, return null. - * - * @see #openIfChanged(IndexReader) - */ - public static IndexReader openIfChanged(IndexReader oldReader, IndexCommit commit) throws IOException { - final IndexReader newReader = oldReader.doOpenIfChanged(commit); - assert newReader != oldReader; - return newReader; - } - - /** - * Expert: If there changes (committed or not) in the - * {@link IndexWriter} versus what the provided reader is - * searching, then open and return a new - * IndexReader searching both committed and uncommitted - * changes from the writer; else, return null (though, the - * current implementation never returns null). - * - *

This provides "near real-time" searching, in that - * changes made during an {@link IndexWriter} session can be - * quickly made available for searching without closing - * the writer nor calling {@link IndexWriter#commit}. - * - *

It's near real-time because there is no hard - * guarantee on how quickly you can get a new reader after - * making changes with IndexWriter. You'll have to - * experiment in your situation to determine if it's - * fast enough. As this is a new and experimental - * feature, please report back on your findings so we can - * learn, improve and iterate.

- * - *

The very first time this method is called, this - * writer instance will make every effort to pool the - * readers that it opens for doing merges, applying - * deletes, etc. This means additional resources (RAM, - * file descriptors, CPU time) will be consumed.

- * - *

For lower latency on reopening a reader, you should - * call {@link IndexWriterConfig#setMergedSegmentWarmer} to - * pre-warm a newly merged segment before it's committed - * to the index. This is important for minimizing - * index-to-search delay after a large merge.

- * - *

If an addIndexes* call is running in another thread, - * then this reader will only search those segments from - * the foreign index that have been successfully copied - * over, so far.

- * - *

NOTE: Once the writer is closed, any - * outstanding readers may continue to be used. However, - * if you attempt to reopen any of those readers, you'll - * hit an {@link AlreadyClosedException}.

- * - * @return IndexReader that covers entire index plus all - * changes made so far by this IndexWriter instance, or - * null if there are no new changes - * - * @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. - * - * @throws IOException - * - * @lucene.experimental - */ - public static IndexReader openIfChanged(IndexReader oldReader, IndexWriter writer, boolean applyAllDeletes) throws IOException { - final IndexReader newReader = oldReader.doOpenIfChanged(writer, applyAllDeletes); - assert newReader != oldReader; - return newReader; - } - - /** - * If the index has changed since it was opened, open and return a new reader; - * else, return {@code null}. - * - * @see #openIfChanged(IndexReader) - */ - protected IndexReader doOpenIfChanged() throws CorruptIndexException, IOException { - throw new UnsupportedOperationException("This reader does not support reopen()."); - } - - /** - * If the index has changed since it was opened, open and return a new reader; - * else, return {@code null}. - * - * @see #openIfChanged(IndexReader, IndexCommit) - */ - protected IndexReader doOpenIfChanged(final IndexCommit commit) throws CorruptIndexException, IOException { - throw new UnsupportedOperationException("This reader does not support reopen(IndexCommit)."); - } - - /** - * If the index has changed since it was opened, open and return a new reader; - * else, return {@code null}. - * - * @see #openIfChanged(IndexReader, IndexWriter, boolean) - */ - protected IndexReader doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes) throws CorruptIndexException, IOException { - return writer.getReader(applyAllDeletes); - } - - /** - * Returns the directory associated with this index. The Default - * implementation returns the directory specified by subclasses when - * delegating to the IndexReader(Directory) constructor, or throws an - * UnsupportedOperationException if one was not specified. - * @throws UnsupportedOperationException if no directory - */ - public Directory directory() { - ensureOpen(); - throw new UnsupportedOperationException("This reader does not support this method."); - } - - /** - * Returns the time the index in the named directory was last modified. - * Do not use this to check whether the reader is still up-to-date, use - * {@link #isCurrent()} instead. - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error - */ - public static long lastModified(final Directory directory2) throws CorruptIndexException, IOException { - return ((Long) new SegmentInfos.FindSegmentsFile(directory2) { - @Override - public Object doBody(String segmentFileName) throws IOException { - return Long.valueOf(directory2.fileModified(segmentFileName)); - } - }.run()).longValue(); - } - - /** - * Reads version number from segments files. The version number is - * initialized with a timestamp and then increased by one for each change of - * the index. - * - * @param directory where the index resides. - * @return version number. - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error - */ - public static long getCurrentVersion(Directory directory) throws CorruptIndexException, IOException { - return SegmentInfos.readCurrentVersion(directory); - } - - /** - * Reads commitUserData, previously passed to {@link - * IndexWriter#commit(Map)}, from current index - * segments file. This will return null if {@link - * IndexWriter#commit(Map)} has never been called for - * this index. - * - * @param directory where the index resides. - * @return commit userData. - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error - * - * @see #getCommitUserData() - */ - public static Map getCommitUserData(Directory directory) throws CorruptIndexException, IOException { - return SegmentInfos.readCurrentUserData(directory); - } - - /** - * Version number when this IndexReader was opened. Not - * implemented in the IndexReader base class. - * - *

If this reader is based on a Directory (ie, was - * created by calling {@link #open}, or {@link #openIfChanged} on - * a reader based on a Directory), then this method - * returns the version recorded in the commit that the - * reader opened. This version is advanced every time - * {@link IndexWriter#commit} is called.

- * - *

If instead this reader is a near real-time reader - * (ie, obtained by a call to {@link - * IndexWriter#getReader}, or by calling {@link #openIfChanged} - * on a near real-time reader), then this method returns - * the version of the last commit done by the writer. - * Note that even as further changes are made with the - * writer, the version will not changed until a commit is - * completed. Thus, you should not rely on this method to - * determine when a near real-time reader should be - * opened. Use {@link #isCurrent} instead.

- * - * @throws UnsupportedOperationException unless overridden in subclass - */ - public long getVersion() { - throw new UnsupportedOperationException("This reader does not support this method."); - } - - /** - * Retrieve the String userData optionally passed to - * IndexWriter#commit. This will return null if {@link - * IndexWriter#commit(Map)} has never been called for - * this index. - * - * @see #getCommitUserData(Directory) - */ - public Map getCommitUserData() { - throw new UnsupportedOperationException("This reader does not support this method."); - } - - - /** - * Check whether any new changes have occurred to the - * index since this reader was opened. - * - *

If this reader is based on a Directory (ie, was - * created by calling {@link #open}, or {@link #openIfChanged} on - * a reader based on a Directory), then this method checks - * if any further commits (see {@link IndexWriter#commit} - * have occurred in that directory).

- * - *

If instead this reader is a near real-time reader - * (ie, obtained by a call to {@link - * IndexWriter#getReader}, or by calling {@link #openIfChanged} - * on a near real-time reader), then this method checks if - * either a new commit has occurred, or any new - * uncommitted changes have taken place via the writer. - * Note that even if the writer has only performed - * merging, this method will still return false.

- * - *

In any event, if this returns false, you should call - * {@link #openIfChanged} to get a new reader that sees the - * changes.

- * - * @throws CorruptIndexException if the index is corrupt - * @throws IOException if there is a low-level IO error - * @throws UnsupportedOperationException unless overridden in subclass - */ - public boolean isCurrent() throws CorruptIndexException, IOException { - throw new UnsupportedOperationException("This reader does not support this method."); - } - - /** 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 true if an index exists at the specified directory. - * @param directory the directory to check for an index - * @return true if an index exists; false otherwise - * @throws IOException if there is a problem with accessing the index - */ - public static boolean indexExists(Directory directory) throws IOException { - try { - new SegmentInfos().read(directory); - return true; - } catch (IOException ioe) { - return false; - } - } - - /** 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. - */ - 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; - - /** - * Returns the stored fields of the nth - * 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. - * - * @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 { - ensureOpen(); - 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)}. - */ - public final Document 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(); + public abstract AtomicReaderContext getTopReaderContext(); /** Returns true if there are norms stored for this field. */ public boolean hasNorms(String field) throws IOException { @@ -847,131 +234,6 @@ public abstract class IndexReader implem return null; } - /** - * 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) { - decRef(); - closed = true; - } - } - - /** Implements close. */ - protected abstract void doClose() throws IOException; - - /** - * Get the {@link FieldInfos} describing all fields in - * this reader. NOTE: do not make any changes to the - * returned FieldInfos! - * - * @lucene.experimental - */ - public abstract FieldInfos getFieldInfos(); - - /** Returns the {@link Bits} representing live (not - * deleted) docs. A set bit indicates the doc ID has not - * been deleted. If this method returns null it means - * there are no deleted documents (all documents are - * live). - * - * The returned instance has been safely published for - * use by multiple threads without additional - * synchronization. - * @lucene.experimental */ - public abstract Bits getLiveDocs(); - - /** - * Expert: return the IndexCommit that this reader has - * opened. This method is only implemented by those - * readers that correspond to a Directory with its own - * segments_N file. - * - * @lucene.experimental - */ - public IndexCommit getIndexCommit() throws IOException { - throw new UnsupportedOperationException("This reader does not support this method."); - } - - /** Returns all commit points that exist in the Directory. - * Normally, because the default is {@link - * KeepOnlyLastCommitDeletionPolicy}, there would be only - * one commit point. But if you're using a custom {@link - * IndexDeletionPolicy} then there could be many commits. - * Once you have a given commit, you can open a reader on - * it by calling {@link IndexReader#open(IndexCommit)} - * There must be at least one commit in - * the Directory, else this method throws {@link - * IndexNotFoundException}. Note that if a commit is in - * progress while this method is running, that commit - * may or may not be returned. - * - * @return a sorted list of {@link IndexCommit}s, from oldest - * to latest. */ - public static List listCommits(Directory dir) throws IOException { - return DirectoryReader.listCommits(dir); - } - - /** Expert: returns the sequential sub readers that this - * reader is logically composed of. If this reader is not composed - * of sequential child readers, it should return null. - * If this method returns an empty array, that means this - * reader is a null reader (for example a MultiReader - * that has no sub readers). - *

- * NOTE: You should not try using sub-readers returned by - * this method to make any changes (deleteDocument, - * etc.). While this might succeed for one composite reader - * (like MultiReader), it will most likely lead to index - * corruption for other readers (like DirectoryReader obtained - * through {@link #open}. Use the parent reader directly. */ - public IndexReader[] getSequentialSubReaders() { - ensureOpen(); - return null; - } - - /** - * Expert: Returns a the root {@link ReaderContext} 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 ReaderContext} 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. - * - * @lucene.experimental - */ - public abstract ReaderContext 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". */ - 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". */ - public Object getCombinedCoreAndDeletesKey() { - // Don't can ensureOpen since FC calls this (to evict) - // on close - return this; - } - /** Returns the number of unique terms (across all fields) * in this reader. * @@ -981,24 +243,12 @@ public abstract class IndexReader implem * #getSequentialSubReaders} and ask each sub reader for * its unique term count. */ public final long getUniqueTermCount() throws IOException { - if (!getTopReaderContext().isAtomic) { - return -1; - } final Fields fields = fields(); if (fields == null) { return 0; } return fields.getUniqueTermCount(); } - - /** For IndexReader implementations that use - * TermInfosReader to read terms, this returns the - * current indexDivisor as specified when the reader was - * opened. - */ - public int getTermInfosIndexDivisor() { - throw new UnsupportedOperationException("This reader does not support this method."); - } /** * Returns {@link DocValues} for this field. @@ -1017,145 +267,25 @@ public abstract class IndexReader implem public abstract DocValues normValues(String field) throws IOException; - private volatile Fields fields; - - /** @lucene.internal */ - void storeFields(Fields fields) { - ensureOpen(); - this.fields = fields; - } - - /** @lucene.internal */ - Fields retrieveFields() { - ensureOpen(); - return fields; - } - /** - * A struct like class that represents a hierarchical relationship between - * {@link IndexReader} instances. + * Get the {@link FieldInfos} describing all fields in + * this reader. NOTE: do not make any changes to the + * returned FieldInfos! + * * @lucene.experimental */ - public static abstract class ReaderContext { - /** The reader context for this reader's immediate parent, or null if none */ - public final ReaderContext parent; - /** The actual reader */ - public final IndexReader reader; - /** true iff the reader is an atomic reader */ - public final boolean isAtomic; - /** true if this context struct represents the top level reader within the hierarchical context */ - public final boolean isTopLevel; - /** the doc base for this reader in the parent, 0 if parent is null */ - public final int docBaseInParent; - /** the ord for this reader in the parent, 0 if parent is null */ - public final int ordInParent; - - ReaderContext(ReaderContext parent, IndexReader reader, - boolean isAtomic, int ordInParent, int docBaseInParent) { - this.parent = parent; - this.reader = reader; - this.isAtomic = isAtomic; - this.docBaseInParent = docBaseInParent; - this.ordInParent = ordInParent; - this.isTopLevel = parent==null; - } - - /** - * Returns the context's leaves if this context is a top-level context - * otherwise null. - *

- * Note: this is convenience method since leaves can always be obtained by - * walking the context tree. - */ - public AtomicReaderContext[] leaves() { - return null; - } - - /** - * Returns the context's children iff this context is a composite context - * otherwise null. - *

- * Note: this method is a convenience method to prevent - * instanceof checks and type-casts to - * {@link CompositeReaderContext}. - */ - public ReaderContext[] children() { - return null; - } - } + public abstract FieldInfos getFieldInfos(); - /** - * {@link ReaderContext} for composite {@link IndexReader} instance. - * @lucene.experimental + /** Returns the {@link Bits} representing live (not + * deleted) docs. A set bit indicates the doc ID has not + * been deleted. If this method returns null it means + * there are no deleted documents (all documents are + * live). + * + * The returned instance has been safely published for + * use by multiple threads without additional + * synchronization. */ - public static final class CompositeReaderContext extends ReaderContext { - /** the composite readers immediate children */ - public final ReaderContext[] children; - /** the composite readers leaf reader contexts if this is the top level reader in this context */ - public final AtomicReaderContext[] leaves; - - /** - * Creates a {@link CompositeReaderContext} for intermediate readers that aren't - * not top-level readers in the current context - */ - public CompositeReaderContext(ReaderContext parent, IndexReader reader, - int ordInParent, int docbaseInParent, ReaderContext[] children) { - this(parent, reader, ordInParent, docbaseInParent, children, null); - } - - /** - * Creates a {@link CompositeReaderContext} for top-level readers with parent set to null - */ - public CompositeReaderContext(IndexReader reader, ReaderContext[] children, AtomicReaderContext[] leaves) { - this(null, reader, 0, 0, children, leaves); - } - - private CompositeReaderContext(ReaderContext parent, IndexReader reader, - int ordInParent, int docbaseInParent, ReaderContext[] children, - AtomicReaderContext[] leaves) { - super(parent, reader, false, ordInParent, docbaseInParent); - this.children = children; - this.leaves = leaves; - } - - @Override - public AtomicReaderContext[] leaves() { - return leaves; - } - - - @Override - public ReaderContext[] children() { - return children; - } - } + public abstract Bits getLiveDocs(); - /** - * {@link ReaderContext} for atomic {@link IndexReader} instances - * @lucene.experimental - */ - public static final class AtomicReaderContext extends ReaderContext { - /** The readers ord in the top-level's leaves array */ - public final int ord; - /** The readers absolute doc base */ - public final int docBase; - /** - * Creates a new {@link AtomicReaderContext} - */ - public AtomicReaderContext(ReaderContext parent, IndexReader reader, - int ord, int docBase, int leafOrd, int leafDocBase) { - super(parent, reader, true, ord, docBase); - assert reader.getSequentialSubReaders() == null : "Atomic readers must not have subreaders"; - this.ord = leafOrd; - this.docBase = leafDocBase; - } - - /** - * Creates a new {@link AtomicReaderContext} for a atomic reader without an immediate - * parent. - */ - public AtomicReaderContext(IndexReader atomicReader) { - this(null, atomicReader, 0, 0, 0, 0); - } - } } Modified: lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/BaseMultiReader.java URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/BaseMultiReader.java?rev=1234441&r1=1234440&r2=1234441&view=diff ============================================================================== --- lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/BaseMultiReader.java (original) +++ lucene/dev/branches/lucene2858/lucene/src/java/org/apache/lucene/index/BaseMultiReader.java Sat Jan 21 23:22:50 2012 @@ -23,10 +23,10 @@ import org.apache.lucene.util.Bits; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.ReaderUtil; -abstract class BaseMultiReader extends IndexReader { +abstract class BaseMultiReader extends CompositeIndexReader { protected final R[] subReaders; protected final int[] starts; // 1st docno for each segment - private final ReaderContext topLevelContext; + private final CompositeReaderContext topLevelContext; private final int maxDoc; private final int numDocs; private final boolean hasDeletions; @@ -49,26 +49,11 @@ abstract class BaseMultiReader queriesIter, IndexWriter.ReadersAndLiveDocs rld, SegmentReader reader) throws IOException { + private static long applyQueryDeletes(Iterable queriesIter, IndexWriter.ReadersAndLiveDocs rld, final SegmentReader reader) throws IOException { long delCount = 0; - final AtomicReaderContext readerContext = (AtomicReaderContext) reader.getTopReaderContext(); + final AtomicReaderContext readerContext = reader.getTopReaderContext(); boolean any = false; for (QueryAndLimit ent : queriesIter) { Query query = ent.query; int limit = ent.limit; - final DocIdSet docs = new QueryWrapperFilter(query).getDocIdSet(readerContext, readerContext.reader.getLiveDocs()); + final DocIdSet docs = new QueryWrapperFilter(query).getDocIdSet(readerContext, reader.getLiveDocs()); if (docs != null) { final DocIdSetIterator it = docs.iterator(); if (it != null) {