Index: lucene/contrib/misc/src/java/org/apache/lucene/index/MultiPassIndexSplitter.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/index/MultiPassIndexSplitter.java (revision 1238713)
+++ lucene/contrib/misc/src/java/org/apache/lucene/index/MultiPassIndexSplitter.java (working copy)
@@ -100,7 +100,8 @@
null)
.setOpenMode(OpenMode.CREATE));
System.err.println("Writing part " + (i + 1) + " ...");
- w.addIndexes(input);
+ // pass the subreaders directly, as our wrapper's numDocs/hasDeletetions are not up-to-date
+ w.addIndexes(input.getSequentialSubReaders());
w.close();
}
System.err.println("Done.");
@@ -204,23 +205,8 @@
}
}
- // override this as MultiReader precalculates the number of deletions
- // (this method is never used by MultiPassIndexSplitter)
- @Override
- public int numDocs() {
- int n = 0;
- for (int i = 0; i < subReaders.length; i++)
- n += subReaders[i].numDocs();
- return n;
- }
-
- // override this as MultiReader precalculates the number of deletions
- // (this method is never used by MultiPassIndexSplitter)
- @Override
- public boolean hasDeletions() {
- return (maxDoc() != numDocs());
- }
-
+ // no need to override numDocs/hasDeletions,
+ // as we pass the subreaders directly to IW.addIndexes().
}
private static final class FakeDeleteAtomicIndexReader extends FilterIndexReader {
Index: lucene/src/java/org/apache/lucene/index/BaseMultiReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/BaseMultiReader.java (revision 1238713)
+++ lucene/src/java/org/apache/lucene/index/BaseMultiReader.java (working copy)
@@ -19,13 +19,12 @@
import java.io.IOException;
-import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.ReaderUtil;
abstract class BaseMultiReader extends CompositeReader {
protected final R[] subReaders;
- protected final int[] starts; // 1st docno for each segment
+ protected final int[] starts; // 1st docno for each reader
private final int maxDoc;
private final int numDocs;
private final boolean hasDeletions;
@@ -50,14 +49,14 @@
}
@Override
- public Fields getTermVectors(int docID) throws IOException {
+ public final Fields getTermVectors(int docID) throws IOException {
ensureOpen();
final int i = readerIndex(docID); // find segment num
return subReaders[i].getTermVectors(docID - starts[i]); // dispatch to segment
}
@Override
- public int numDocs() {
+ public final int numDocs() {
// Don't call ensureOpen() here (it could affect performance)
return numDocs;
}
@@ -69,20 +68,20 @@
}
@Override
- public void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
+ public final void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
ensureOpen();
final int i = readerIndex(docID); // find segment num
subReaders[i].document(docID - starts[i], visitor); // dispatch to segment reader
}
@Override
- public boolean hasDeletions() {
+ public final boolean hasDeletions() {
// Don't call ensureOpen() here (it could affect performance)
return hasDeletions;
}
@Override
- public int docFreq(String field, BytesRef t) throws IOException {
+ public final int docFreq(String field, BytesRef t) throws IOException {
ensureOpen();
int total = 0; // sum freqs in segments
for (int i = 0; i < subReaders.length; i++) {
@@ -100,7 +99,7 @@
}
@Override
- public IndexReader[] getSequentialSubReaders() {
+ public final R[] getSequentialSubReaders() {
return subReaders;
}
}
Index: lucene/src/java/org/apache/lucene/index/DirectoryReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DirectoryReader.java (revision 1238713)
+++ lucene/src/java/org/apache/lucene/index/DirectoryReader.java (working copy)
@@ -20,16 +20,12 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.lucene.search.SearcherManager; // javadocs
import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.IOContext;
-import org.apache.lucene.util.IOUtils;
/** DirectoryReader is an implementation of {@link CompositeReader}
that can read indexes in a {@link Directory}.
@@ -53,14 +49,10 @@
IndexReader instance; use your own
(non-Lucene) objects instead.
*/
-public final class DirectoryReader extends BaseMultiReader {
- static int DEFAULT_TERMS_INDEX_DIVISOR = 1;
+public abstract class DirectoryReader extends BaseMultiReader {
+ public static final int DEFAULT_TERMS_INDEX_DIVISOR = 1;
protected final Directory directory;
- private final IndexWriter writer;
- private final SegmentInfos segmentInfos;
- private final int termInfosIndexDivisor;
- private final boolean applyAllDeletes;
/** Returns a IndexReader reading the index in the given
* Directory
@@ -69,7 +61,7 @@
* @throws IOException if there is a low-level IO error
*/
public static DirectoryReader open(final Directory directory) throws CorruptIndexException, IOException {
- return open(directory, null, DEFAULT_TERMS_INDEX_DIVISOR);
+ return StandardDirectoryReader.open(directory, null, DEFAULT_TERMS_INDEX_DIVISOR);
}
/** Expert: Returns a IndexReader reading the index in the given
@@ -89,7 +81,7 @@
* @throws IOException if there is a low-level IO error
*/
public static DirectoryReader open(final Directory directory, int termInfosIndexDivisor) throws CorruptIndexException, IOException {
- return open(directory, null, termInfosIndexDivisor);
+ return StandardDirectoryReader.open(directory, null, termInfosIndexDivisor);
}
/**
@@ -122,10 +114,9 @@
* @throws IOException if there is a low-level IO error
*/
public static DirectoryReader open(final IndexCommit commit) throws CorruptIndexException, IOException {
- return open(commit.getDirectory(), commit, DEFAULT_TERMS_INDEX_DIVISOR);
+ return StandardDirectoryReader.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
@@ -143,171 +134,9 @@
* @throws IOException if there is a low-level IO error
*/
public static DirectoryReader open(final IndexCommit commit, int termInfosIndexDivisor) throws CorruptIndexException, IOException {
- return open(commit.getDirectory(), commit, termInfosIndexDivisor);
+ return StandardDirectoryReader.open(commit.getDirectory(), commit, termInfosIndexDivisor);
}
- DirectoryReader(SegmentReader[] readers, Directory directory, IndexWriter writer,
- SegmentInfos sis, int termInfosIndexDivisor, boolean applyAllDeletes) throws IOException {
- super(readers);
- this.directory = directory;
- this.writer = writer;
- this.segmentInfos = sis;
- this.termInfosIndexDivisor = termInfosIndexDivisor;
- this.applyAllDeletes = applyAllDeletes;
- }
-
- private static DirectoryReader open(final Directory directory, final IndexCommit commit,
- final int termInfosIndexDivisor) throws CorruptIndexException, IOException {
- return (DirectoryReader) new SegmentInfos.FindSegmentsFile(directory) {
- @Override
- protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException {
- SegmentInfos sis = new SegmentInfos();
- sis.read(directory, segmentFileName);
- final SegmentReader[] readers = new SegmentReader[sis.size()];
- for (int i = sis.size()-1; i >= 0; i--) {
- IOException prior = null;
- boolean success = false;
- try {
- readers[i] = new SegmentReader(sis.info(i), termInfosIndexDivisor, IOContext.READ);
- success = true;
- } catch(IOException ex) {
- prior = ex;
- } finally {
- if (!success)
- IOUtils.closeWhileHandlingException(prior, readers);
- }
- }
- return new DirectoryReader(readers, directory, null, sis, termInfosIndexDivisor, false);
- }
- }.run(commit);
- }
-
- // Used by near real-time search
- static DirectoryReader open(IndexWriter writer, SegmentInfos infos, boolean applyAllDeletes) throws IOException {
- // IndexWriter synchronizes externally before calling
- // us, which ensures infos will not change; so there's
- // no need to process segments in reverse order
- final int numSegments = infos.size();
-
- List readers = new ArrayList();
- final Directory dir = writer.getDirectory();
-
- final SegmentInfos segmentInfos = (SegmentInfos) infos.clone();
- int infosUpto = 0;
- for (int i=0;i 0 || writer.getKeepFullyDeletedSegments()) {
- readers.add(reader);
- infosUpto++;
- } else {
- reader.close();
- segmentInfos.remove(infosUpto);
- }
- success = true;
- } catch(IOException ex) {
- prior = ex;
- } finally {
- if (!success)
- IOUtils.closeWhileHandlingException(prior, readers);
- }
- }
- return new DirectoryReader(readers.toArray(new SegmentReader[readers.size()]),
- dir, writer, segmentInfos, writer.getConfig().getReaderTermsIndexDivisor(), applyAllDeletes);
- }
-
- /** This constructor is only used for {@link #doOpenIfChanged()} */
- private static DirectoryReader open(Directory directory, IndexWriter writer, SegmentInfos infos, SegmentReader[] oldReaders,
- int termInfosIndexDivisor) throws IOException {
- // we put the old SegmentReaders in a map, that allows us
- // to lookup a reader using its segment name
- final Map segmentReaders = new HashMap();
-
- if (oldReaders != null) {
- // create a Map SegmentName->SegmentReader
- for (int i = 0; i < oldReaders.length; i++) {
- segmentReaders.put(oldReaders[i].getSegmentName(), Integer.valueOf(i));
- }
- }
-
- SegmentReader[] newReaders = new SegmentReader[infos.size()];
-
- // remember which readers are shared between the old and the re-opened
- // DirectoryReader - we have to incRef those readers
- boolean[] readerShared = new boolean[infos.size()];
-
- for (int i = infos.size() - 1; i>=0; i--) {
- // find SegmentReader for this segment
- Integer oldReaderIndex = segmentReaders.get(infos.info(i).name);
- if (oldReaderIndex == null) {
- // this is a new segment, no old SegmentReader can be reused
- newReaders[i] = null;
- } else {
- // there is an old reader for this segment - we'll try to reopen it
- newReaders[i] = oldReaders[oldReaderIndex.intValue()];
- }
-
- boolean success = false;
- IOException prior = null;
- try {
- SegmentReader newReader;
- if (newReaders[i] == null || infos.info(i).getUseCompoundFile() != newReaders[i].getSegmentInfo().getUseCompoundFile()) {
-
- // this is a new reader; in case we hit an exception we can close it safely
- newReader = new SegmentReader(infos.info(i), termInfosIndexDivisor, IOContext.READ);
- readerShared[i] = false;
- newReaders[i] = newReader;
- } else {
- if (newReaders[i].getSegmentInfo().getDelGen() == infos.info(i).getDelGen()) {
- // No change; this reader will be shared between
- // the old and the new one, so we must incRef
- // it:
- readerShared[i] = true;
- newReaders[i].incRef();
- } else {
- readerShared[i] = false;
- // Steal the ref returned by SegmentReader ctor:
- assert infos.info(i).dir == newReaders[i].getSegmentInfo().dir;
- assert infos.info(i).hasDeletions();
- newReaders[i] = new SegmentReader(infos.info(i), newReaders[i].core, IOContext.READ);
- }
- }
- success = true;
- } catch (IOException ex) {
- prior = ex;
- } finally {
- if (!success) {
- for (i++; i < infos.size(); i++) {
- if (newReaders[i] != null) {
- try {
- if (!readerShared[i]) {
- // this is a new subReader that is not used by the old one,
- // we can close it
- newReaders[i].close();
- } else {
- // this subReader is also used by the old reader, so instead
- // closing we must decRef it
- newReaders[i].decRef();
- }
- } catch (IOException ex) {
- if (prior == null) prior = ex;
- }
- }
- }
- }
- // throw the first exception
- if (prior != null) throw prior;
- }
- }
- return new DirectoryReader(newReaders, directory, writer,
- infos, termInfosIndexDivisor, false);
- }
-
/**
* If the index has changed since the provided reader was
* opened, open and return a new reader; else, return
@@ -418,209 +247,6 @@
return newReader;
}
- /** {@inheritDoc} */
- @Override
- public String toString() {
- final StringBuilder buffer = new StringBuilder();
- buffer.append(getClass().getSimpleName());
- buffer.append('(');
- final String segmentsFile = segmentInfos.getCurrentSegmentFileName();
- if (segmentsFile != null) {
- buffer.append(segmentsFile).append(":").append(segmentInfos.getVersion());
- }
- if (writer != null) {
- buffer.append(":nrt");
- }
- for(int i=0;iThis method
- * returns the version recorded in the commit that the
- * reader opened. This version is advanced every time
- * a change is made with {@link IndexWriter}.
- */
- public long getVersion() {
- ensureOpen();
- return segmentInfos.getVersion();
- }
-
- /**
- * 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.
- */
- public Map getCommitUserData() {
- ensureOpen();
- return segmentInfos.getUserData();
- }
-
- /**
- * Check whether any new changes have occurred to the
- * index since this reader was opened.
- *
- * If this reader was created by calling {@link #open},
- * then this method checks if any further commits
- * (see {@link IndexWriter#commit}) have occurred in the
- * 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 commmit 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
- */
- public boolean isCurrent() throws CorruptIndexException, IOException {
- ensureOpen();
- if (writer == null || writer.isClosed()) {
- // we loaded SegmentInfos from the directory
- return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion();
- } else {
- return writer.nrtIsCurrent(segmentInfos);
- }
- }
-
- @Override
- protected synchronized void doClose() throws IOException {
- IOException ioe = null;
- for (int i = 0; i < subReaders.length; i++) {
- // try to close each reader, even if an exception is thrown
- try {
- subReaders[i].decRef();
- } catch (IOException e) {
- if (ioe == null) ioe = e;
- }
- }
-
- if (writer != null) {
- // Since we just closed, writer may now be able to
- // delete unused files:
- writer.deletePendingFiles();
- }
-
- // throw the first exception
- if (ioe != null) throw ioe;
- }
-
- /** Returns the directory this index resides in. */
- public Directory directory() {
- // Don't ensureOpen here -- in certain cases, when a
- // cloned/reopened reader needs to commit, it may call
- // this method on the closed original reader
- return directory;
- }
-
- /** This returns the current indexDivisor as
- * specified when the reader was opened.
- */
- public int getTermInfosIndexDivisor() {
- ensureOpen();
- return termInfosIndexDivisor;
- }
-
- /**
- * Expert: return the IndexCommit that this reader has opened.
- *
- * @lucene.experimental
- */
- public IndexCommit getIndexCommit() throws IOException {
- ensureOpen();
- return new ReaderCommit(segmentInfos, directory);
- }
-
/** Returns all commit points that exist in the Directory.
* Normally, because the default is {@link
* KeepOnlyLastCommitDeletionPolicy}, there would be only
@@ -645,7 +271,7 @@
latest.read(dir);
final long currentGen = latest.getGeneration();
- commits.add(new ReaderCommit(latest, dir));
+ commits.add(new StandardDirectoryReader.ReaderCommit(latest, dir));
for(int i=0;i files;
- Directory dir;
- long generation;
- final Map userData;
- private final int segmentCount;
+ protected DirectoryReader(Directory directory, AtomicReader[] readers) throws CorruptIndexException, IOException {
+ super(readers);
+ this.directory = directory;
+ }
+
+ /** Returns the directory this index resides in. */
+ public final Directory directory() {
+ // Don't ensureOpen here -- in certain cases, when a
+ // cloned/reopened reader needs to commit, it may call
+ // this method on the closed original reader
+ return directory;
+ }
- ReaderCommit(SegmentInfos infos, Directory dir) throws IOException {
- segmentsFileName = infos.getCurrentSegmentFileName();
- this.dir = dir;
- userData = infos.getUserData();
- files = Collections.unmodifiableCollection(infos.files(dir, true));
- generation = infos.getGeneration();
- segmentCount = infos.size();
- }
+ /** Implement this method to support {@link #openIfChanged(DirectoryReader)}.
+ * If this reader does not support reopen, return {@code null}, so
+ * client code is happy. This should be consistent with {@link #isCurrent}
+ * (should always return {@code true}) if reopen is not supported.
+ * @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
+ * DirectoryReader instance.
+ */
+ protected abstract DirectoryReader doOpenIfChanged() throws CorruptIndexException, IOException;
- @Override
- public String toString() {
- return "DirectoryReader.ReaderCommit(" + segmentsFileName + ")";
- }
+ /** Implement this method to support {@link #openIfChanged(DirectoryReader,IndexCommit)}.
+ * If this reader does not support reopen from a specific {@link IndexCommit},
+ * throw {@link UnsupportedOperationException}.
+ * @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
+ * DirectoryReader instance.
+ */
+ protected abstract DirectoryReader doOpenIfChanged(final IndexCommit commit) throws CorruptIndexException, IOException;
- @Override
- public int getSegmentCount() {
- return segmentCount;
- }
+ /** Implement this method to support {@link #openIfChanged(DirectoryReader,IndexWriter,boolean)}.
+ * If this reader does not support reopen from {@link IndexWriter},
+ * throw {@link UnsupportedOperationException}.
+ * @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
+ * DirectoryReader instance.
+ */
+ protected abstract DirectoryReader doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes) throws CorruptIndexException, IOException;
- @Override
- public String getSegmentsFileName() {
- return segmentsFileName;
- }
+ /**
+ * Version number when this IndexReader was opened.
+ *
+ * This method
+ * returns the version recorded in the commit that the
+ * reader opened. This version is advanced every time
+ * a change is made with {@link IndexWriter}.
+ */
+ public abstract long getVersion();
- @Override
- public Collection getFileNames() {
- return files;
- }
+ /**
+ * 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.
+ */
+ public abstract Map getCommitUserData();
- @Override
- public Directory getDirectory() {
- return dir;
- }
+ /**
+ * Check whether any new changes have occurred to the
+ * index since this reader was opened.
+ *
+ * If this reader was created by calling {@link #open},
+ * then this method checks if any further commits
+ * (see {@link IndexWriter#commit}) have occurred in the
+ * 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 commmit 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
+ */
+ public abstract boolean isCurrent() throws CorruptIndexException, IOException;
- @Override
- public long getGeneration() {
- return generation;
- }
+ /**
+ * Expert: return the IndexCommit that this reader has opened.
+ *
+ * @lucene.experimental
+ */
+ public abstract IndexCommit getIndexCommit() throws CorruptIndexException, IOException;
- @Override
- public boolean isDeleted() {
- return false;
- }
-
- @Override
- public Map getUserData() {
- return userData;
- }
-
- @Override
- public void delete() {
- throw new UnsupportedOperationException("This IndexCommit does not support deletions");
- }
- }
}
Index: lucene/src/java/org/apache/lucene/index/IndexWriter.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/IndexWriter.java (revision 1238713)
+++ lucene/src/java/org/apache/lucene/index/IndexWriter.java (working copy)
@@ -364,7 +364,7 @@
// just like we do when loading segments_N
synchronized(this) {
maybeApplyDeletes(applyAllDeletes);
- r = DirectoryReader.open(this, segmentInfos, applyAllDeletes);
+ r = StandardDirectoryReader.open(this, segmentInfos, applyAllDeletes);
if (infoStream.isEnabled("IW")) {
infoStream.message("IW", "return reader version=" + r.getVersion() + " reader=" + r);
}
Index: lucene/src/java/org/apache/lucene/index/StandardDirectoryReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/StandardDirectoryReader.java (revision 0)
+++ lucene/src/java/org/apache/lucene/index/StandardDirectoryReader.java (working copy)
@@ -0,0 +1,411 @@
+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.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
+import org.apache.lucene.util.IOUtils;
+
+final class StandardDirectoryReader extends DirectoryReader {
+
+ private final IndexWriter writer;
+ private final SegmentInfos segmentInfos;
+ private final int termInfosIndexDivisor;
+ private final boolean applyAllDeletes;
+
+ /** called only from static open() methods */
+ StandardDirectoryReader(Directory directory, AtomicReader[] readers, IndexWriter writer,
+ SegmentInfos sis, int termInfosIndexDivisor, boolean applyAllDeletes) throws IOException {
+ super(directory, readers);
+ this.writer = writer;
+ this.segmentInfos = sis;
+ this.termInfosIndexDivisor = termInfosIndexDivisor;
+ this.applyAllDeletes = applyAllDeletes;
+ }
+
+ /** called from DirectoryReader.open(...) methods */
+ static DirectoryReader open(final Directory directory, final IndexCommit commit,
+ final int termInfosIndexDivisor) throws CorruptIndexException, IOException {
+ return (DirectoryReader) new SegmentInfos.FindSegmentsFile(directory) {
+ @Override
+ protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException {
+ SegmentInfos sis = new SegmentInfos();
+ sis.read(directory, segmentFileName);
+ final SegmentReader[] readers = new SegmentReader[sis.size()];
+ for (int i = sis.size()-1; i >= 0; i--) {
+ IOException prior = null;
+ boolean success = false;
+ try {
+ readers[i] = new SegmentReader(sis.info(i), termInfosIndexDivisor, IOContext.READ);
+ success = true;
+ } catch(IOException ex) {
+ prior = ex;
+ } finally {
+ if (!success)
+ IOUtils.closeWhileHandlingException(prior, readers);
+ }
+ }
+ return new StandardDirectoryReader(directory, readers, null, sis, termInfosIndexDivisor, false);
+ }
+ }.run(commit);
+ }
+
+ /** Used by near real-time search */
+ static DirectoryReader open(IndexWriter writer, SegmentInfos infos, boolean applyAllDeletes) throws IOException {
+ // IndexWriter synchronizes externally before calling
+ // us, which ensures infos will not change; so there's
+ // no need to process segments in reverse order
+ final int numSegments = infos.size();
+
+ List readers = new ArrayList();
+ final Directory dir = writer.getDirectory();
+
+ final SegmentInfos segmentInfos = (SegmentInfos) infos.clone();
+ int infosUpto = 0;
+ for (int i=0;i 0 || writer.getKeepFullyDeletedSegments()) {
+ readers.add(reader);
+ infosUpto++;
+ } else {
+ reader.close();
+ segmentInfos.remove(infosUpto);
+ }
+ success = true;
+ } catch(IOException ex) {
+ prior = ex;
+ } finally {
+ if (!success)
+ IOUtils.closeWhileHandlingException(prior, readers);
+ }
+ }
+ return new StandardDirectoryReader(dir, readers.toArray(new SegmentReader[readers.size()]),
+ writer, segmentInfos, writer.getConfig().getReaderTermsIndexDivisor(), applyAllDeletes);
+ }
+
+ /** This constructor is only used for {@link #doOpenIfChanged()} */
+ private static DirectoryReader open(Directory directory, IndexWriter writer, SegmentInfos infos, AtomicReader[] oldReaders,
+ int termInfosIndexDivisor) throws IOException {
+ // we put the old SegmentReaders in a map, that allows us
+ // to lookup a reader using its segment name
+ final Map segmentReaders = new HashMap();
+
+ if (oldReaders != null) {
+ // create a Map SegmentName->SegmentReader
+ for (int i = 0; i < oldReaders.length; i++) {
+ segmentReaders.put(((SegmentReader) oldReaders[i]).getSegmentName(), Integer.valueOf(i));
+ }
+ }
+
+ SegmentReader[] newReaders = new SegmentReader[infos.size()];
+
+ // remember which readers are shared between the old and the re-opened
+ // DirectoryReader - we have to incRef those readers
+ boolean[] readerShared = new boolean[infos.size()];
+
+ for (int i = infos.size() - 1; i>=0; i--) {
+ // find SegmentReader for this segment
+ Integer oldReaderIndex = segmentReaders.get(infos.info(i).name);
+ if (oldReaderIndex == null) {
+ // this is a new segment, no old SegmentReader can be reused
+ newReaders[i] = null;
+ } else {
+ // there is an old reader for this segment - we'll try to reopen it
+ newReaders[i] = (SegmentReader) oldReaders[oldReaderIndex.intValue()];
+ }
+
+ boolean success = false;
+ IOException prior = null;
+ try {
+ SegmentReader newReader;
+ if (newReaders[i] == null || infos.info(i).getUseCompoundFile() != newReaders[i].getSegmentInfo().getUseCompoundFile()) {
+
+ // this is a new reader; in case we hit an exception we can close it safely
+ newReader = new SegmentReader(infos.info(i), termInfosIndexDivisor, IOContext.READ);
+ readerShared[i] = false;
+ newReaders[i] = newReader;
+ } else {
+ if (newReaders[i].getSegmentInfo().getDelGen() == infos.info(i).getDelGen()) {
+ // No change; this reader will be shared between
+ // the old and the new one, so we must incRef
+ // it:
+ readerShared[i] = true;
+ newReaders[i].incRef();
+ } else {
+ readerShared[i] = false;
+ // Steal the ref returned by SegmentReader ctor:
+ assert infos.info(i).dir == newReaders[i].getSegmentInfo().dir;
+ assert infos.info(i).hasDeletions();
+ newReaders[i] = new SegmentReader(infos.info(i), newReaders[i].core, IOContext.READ);
+ }
+ }
+ success = true;
+ } catch (IOException ex) {
+ prior = ex;
+ } finally {
+ if (!success) {
+ for (i++; i < infos.size(); i++) {
+ if (newReaders[i] != null) {
+ try {
+ if (!readerShared[i]) {
+ // this is a new subReader that is not used by the old one,
+ // we can close it
+ newReaders[i].close();
+ } else {
+ // this subReader is also used by the old reader, so instead
+ // closing we must decRef it
+ newReaders[i].decRef();
+ }
+ } catch (IOException ex) {
+ if (prior == null) prior = ex;
+ }
+ }
+ }
+ }
+ // throw the first exception
+ if (prior != null) throw prior;
+ }
+ }
+ return new StandardDirectoryReader(directory, newReaders, writer, infos, termInfosIndexDivisor, false);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder();
+ buffer.append(getClass().getSimpleName());
+ buffer.append('(');
+ final String segmentsFile = segmentInfos.getCurrentSegmentFileName();
+ if (segmentsFile != null) {
+ buffer.append(segmentsFile).append(":").append(segmentInfos.getVersion());
+ }
+ if (writer != null) {
+ buffer.append(":nrt");
+ }
+ for(int i=0;i getCommitUserData() {
+ ensureOpen();
+ return segmentInfos.getUserData();
+ }
+
+ @Override
+ public boolean isCurrent() throws CorruptIndexException, IOException {
+ ensureOpen();
+ if (writer == null || writer.isClosed()) {
+ // we loaded SegmentInfos from the directory
+ return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion();
+ } else {
+ return writer.nrtIsCurrent(segmentInfos);
+ }
+ }
+
+ @Override
+ protected synchronized void doClose() throws IOException {
+ IOException ioe = null;
+ for (int i = 0; i < subReaders.length; i++) {
+ // try to close each reader, even if an exception is thrown
+ try {
+ subReaders[i].decRef();
+ } catch (IOException e) {
+ if (ioe == null) ioe = e;
+ }
+ }
+
+ if (writer != null) {
+ // Since we just closed, writer may now be able to
+ // delete unused files:
+ writer.deletePendingFiles();
+ }
+
+ // throw the first exception
+ if (ioe != null) throw ioe;
+ }
+
+ @Override
+ public IndexCommit getIndexCommit() throws IOException {
+ ensureOpen();
+ return new ReaderCommit(segmentInfos, directory);
+ }
+
+ static final class ReaderCommit extends IndexCommit {
+ private String segmentsFileName;
+ Collection files;
+ Directory dir;
+ long generation;
+ final Map userData;
+ private final int segmentCount;
+
+ ReaderCommit(SegmentInfos infos, Directory dir) throws IOException {
+ segmentsFileName = infos.getCurrentSegmentFileName();
+ this.dir = dir;
+ userData = infos.getUserData();
+ files = Collections.unmodifiableCollection(infos.files(dir, true));
+ generation = infos.getGeneration();
+ segmentCount = infos.size();
+ }
+
+ @Override
+ public String toString() {
+ return "DirectoryReader.ReaderCommit(" + segmentsFileName + ")";
+ }
+
+ @Override
+ public int getSegmentCount() {
+ return segmentCount;
+ }
+
+ @Override
+ public String getSegmentsFileName() {
+ return segmentsFileName;
+ }
+
+ @Override
+ public Collection getFileNames() {
+ return files;
+ }
+
+ @Override
+ public Directory getDirectory() {
+ return dir;
+ }
+
+ @Override
+ public long getGeneration() {
+ return generation;
+ }
+
+ @Override
+ public boolean isDeleted() {
+ return false;
+ }
+
+ @Override
+ public Map getUserData() {
+ return userData;
+ }
+
+ @Override
+ public void delete() {
+ throw new UnsupportedOperationException("This IndexCommit does not support deletions");
+ }
+ }
+}
Index: lucene/src/java/org/apache/lucene/index/StandardDirectoryReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/StandardDirectoryReader.java (revision 1238503)
+++ lucene/src/java/org/apache/lucene/index/StandardDirectoryReader.java (working copy)
Property changes on: lucene/src/java/org/apache/lucene/index/StandardDirectoryReader.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
Index: lucene/src/test/org/apache/lucene/index/TestDocValuesIndexing.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDocValuesIndexing.java (revision 1238713)
+++ lucene/src/test/org/apache/lucene/index/TestDocValuesIndexing.java (working copy)
@@ -696,7 +696,7 @@
w.forceMerge(1);
DirectoryReader r = w.getReader();
w.close();
- assertEquals(17, ((AtomicReader) r.getSequentialSubReaders()[0]).docValues("field").load().getInt(0));
+ assertEquals(17, r.getSequentialSubReaders()[0].docValues("field").load().getInt(0));
r.close();
d.close();
}
Index: lucene/src/test/org/apache/lucene/index/TestIndexReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexReader.java (revision 1238713)
+++ lucene/src/test/org/apache/lucene/index/TestIndexReader.java (working copy)
@@ -700,7 +700,7 @@
DirectoryReader r2 = DirectoryReader.openIfChanged(r);
assertNotNull(r2);
r.close();
- AtomicReader sub0 = (AtomicReader) r2.getSequentialSubReaders()[0];
+ AtomicReader sub0 = r2.getSequentialSubReaders()[0];
final int[] ints2 = FieldCache.DEFAULT.getInts(sub0, "number", false);
r2.close();
assertTrue(ints == ints2);
Index: solr/core/src/test/org/apache/solr/core/TestConfig.java
===================================================================
--- solr/core/src/test/org/apache/solr/core/TestConfig.java (revision 1238713)
+++ solr/core/src/test/org/apache/solr/core/TestConfig.java (working copy)
@@ -126,9 +126,6 @@
IndexReaderFactory irf = h.getCore().getIndexReaderFactory();
StandardIndexReaderFactory sirf = (StandardIndexReaderFactory) irf;
assertEquals(12, sirf.termInfosIndexDivisor);
- SolrQueryRequest req = req();
- assertEquals(12, req.getSearcher().getIndexReader().getTermInfosIndexDivisor());
- req.close();
}