mirror of https://github.com/apache/lucene.git
LUCENE-818: throw AlreadyClosedException when accessing IndexWriter, *Reader, RAMDirectory and FieldsReader after close()
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@518262 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4648912089
commit
9da8211775
|
@ -29,6 +29,11 @@ API Changes
|
|||
share an index over NFS by customizing when prior commits are
|
||||
deleted. (Mike McCandless)
|
||||
|
||||
4. LUCENE-818: changed most public methods of IndexWriter,
|
||||
IndexReader (and its subclasses), FieldsReader and RAMDirectory to
|
||||
throw AlreadyClosedException if they are accessed after being
|
||||
closed. (Mike McCandless)
|
||||
|
||||
Bug fixes
|
||||
|
||||
1. LUCENE-804: Fixed build.xml to pack a fully compilable src dist. (Doron Cohen)
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.lucene.index;
|
|||
import org.apache.lucene.document.*;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.IndexInput;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -46,6 +47,7 @@ final class FieldsReader {
|
|||
|
||||
private final IndexInput indexStream;
|
||||
private int size;
|
||||
private boolean closed;
|
||||
|
||||
private ThreadLocal fieldsStreamTL = new ThreadLocal();
|
||||
|
||||
|
@ -58,6 +60,15 @@ final class FieldsReader {
|
|||
size = (int) (indexStream.length() / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws AlreadyClosedException if this FieldsReader is closed
|
||||
*/
|
||||
protected final void ensureOpen() throws AlreadyClosedException {
|
||||
if (closed) {
|
||||
throw new AlreadyClosedException("this FieldsReader is closed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the underlying {@link org.apache.lucene.store.IndexInput} streams, including any ones associated with a
|
||||
* lazy implementation of a Field. This means that the Fields values will not be accessible.
|
||||
|
@ -65,13 +76,16 @@ final class FieldsReader {
|
|||
* @throws IOException
|
||||
*/
|
||||
final void close() throws IOException {
|
||||
fieldsStream.close();
|
||||
cloneableFieldsStream.close();
|
||||
indexStream.close();
|
||||
IndexInput localFieldsStream = (IndexInput) fieldsStreamTL.get();
|
||||
if (localFieldsStream != null) {
|
||||
localFieldsStream.close();
|
||||
fieldsStreamTL.set(null);
|
||||
if (!closed) {
|
||||
fieldsStream.close();
|
||||
cloneableFieldsStream.close();
|
||||
indexStream.close();
|
||||
IndexInput localFieldsStream = (IndexInput) fieldsStreamTL.get();
|
||||
if (localFieldsStream != null) {
|
||||
localFieldsStream.close();
|
||||
fieldsStreamTL.set(null);
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,6 +337,7 @@ final class FieldsReader {
|
|||
* binaryValue() must be set.
|
||||
*/
|
||||
public byte[] binaryValue() {
|
||||
ensureOpen();
|
||||
if (fieldsData == null) {
|
||||
final byte[] b = new byte[toRead];
|
||||
IndexInput localFieldsStream = getFieldStream();
|
||||
|
@ -349,6 +364,7 @@ final class FieldsReader {
|
|||
* and binaryValue() must be set.
|
||||
*/
|
||||
public Reader readerValue() {
|
||||
ensureOpen();
|
||||
return fieldsData instanceof Reader ? (Reader) fieldsData : null;
|
||||
}
|
||||
|
||||
|
@ -358,6 +374,7 @@ final class FieldsReader {
|
|||
* binaryValue() must be set.
|
||||
*/
|
||||
public String stringValue() {
|
||||
ensureOpen();
|
||||
if (fieldsData == null) {
|
||||
IndexInput localFieldsStream = getFieldStream();
|
||||
try {
|
||||
|
@ -380,18 +397,22 @@ final class FieldsReader {
|
|||
}
|
||||
|
||||
public long getPointer() {
|
||||
ensureOpen();
|
||||
return pointer;
|
||||
}
|
||||
|
||||
public void setPointer(long pointer) {
|
||||
ensureOpen();
|
||||
this.pointer = pointer;
|
||||
}
|
||||
|
||||
public int getToRead() {
|
||||
ensureOpen();
|
||||
return toRead;
|
||||
}
|
||||
|
||||
public void setToRead(int toRead) {
|
||||
ensureOpen();
|
||||
this.toRead = toRead;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,43 +92,84 @@ public class FilterIndexReader extends IndexReader {
|
|||
|
||||
public TermFreqVector[] getTermFreqVectors(int docNumber)
|
||||
throws IOException {
|
||||
ensureOpen();
|
||||
return in.getTermFreqVectors(docNumber);
|
||||
}
|
||||
|
||||
public TermFreqVector getTermFreqVector(int docNumber, String field)
|
||||
throws IOException {
|
||||
ensureOpen();
|
||||
return in.getTermFreqVector(docNumber, field);
|
||||
}
|
||||
|
||||
public int numDocs() { return in.numDocs(); }
|
||||
public int maxDoc() { return in.maxDoc(); }
|
||||
public int numDocs() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return in.numDocs();
|
||||
}
|
||||
|
||||
public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { return in.document(n, fieldSelector); }
|
||||
public int maxDoc() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return in.maxDoc();
|
||||
}
|
||||
|
||||
public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
return in.document(n, fieldSelector);
|
||||
}
|
||||
|
||||
public boolean isDeleted(int n) {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return in.isDeleted(n);
|
||||
}
|
||||
|
||||
public boolean hasDeletions() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return in.hasDeletions();
|
||||
}
|
||||
|
||||
public boolean isDeleted(int n) { return in.isDeleted(n); }
|
||||
public boolean hasDeletions() { return in.hasDeletions(); }
|
||||
protected void doUndeleteAll() throws CorruptIndexException, IOException {in.undeleteAll();}
|
||||
|
||||
public boolean hasNorms(String field) throws IOException {
|
||||
ensureOpen();
|
||||
return in.hasNorms(field);
|
||||
}
|
||||
|
||||
public byte[] norms(String f) throws IOException { return in.norms(f); }
|
||||
public byte[] norms(String f) throws IOException {
|
||||
ensureOpen();
|
||||
return in.norms(f);
|
||||
}
|
||||
|
||||
public void norms(String f, byte[] bytes, int offset) throws IOException {
|
||||
ensureOpen();
|
||||
in.norms(f, bytes, offset);
|
||||
}
|
||||
|
||||
protected void doSetNorm(int d, String f, byte b) throws CorruptIndexException, IOException {
|
||||
in.setNorm(d, f, b);
|
||||
}
|
||||
|
||||
public TermEnum terms() throws IOException { return in.terms(); }
|
||||
public TermEnum terms(Term t) throws IOException { return in.terms(t); }
|
||||
public TermEnum terms() throws IOException {
|
||||
ensureOpen();
|
||||
return in.terms();
|
||||
}
|
||||
|
||||
public int docFreq(Term t) throws IOException { return in.docFreq(t); }
|
||||
public TermEnum terms(Term t) throws IOException {
|
||||
ensureOpen();
|
||||
return in.terms(t);
|
||||
}
|
||||
|
||||
public TermDocs termDocs() throws IOException { return in.termDocs(); }
|
||||
public int docFreq(Term t) throws IOException {
|
||||
ensureOpen();
|
||||
return in.docFreq(t);
|
||||
}
|
||||
|
||||
public TermDocs termDocs() throws IOException {
|
||||
ensureOpen();
|
||||
return in.termDocs();
|
||||
}
|
||||
|
||||
public TermPositions termPositions() throws IOException {
|
||||
ensureOpen();
|
||||
return in.termPositions();
|
||||
}
|
||||
|
||||
|
@ -138,9 +179,17 @@ public class FilterIndexReader extends IndexReader {
|
|||
|
||||
|
||||
public Collection getFieldNames(IndexReader.FieldOption fieldNames) {
|
||||
ensureOpen();
|
||||
return in.getFieldNames(fieldNames);
|
||||
}
|
||||
|
||||
public long getVersion() { return in.getVersion(); }
|
||||
public boolean isCurrent() throws CorruptIndexException, IOException { return in.isCurrent(); }
|
||||
public long getVersion() {
|
||||
ensureOpen();
|
||||
return in.getVersion();
|
||||
}
|
||||
|
||||
public boolean isCurrent() throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
return in.isCurrent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.lucene.store.FSDirectory;
|
|||
import org.apache.lucene.store.IndexInput;
|
||||
import org.apache.lucene.store.Lock;
|
||||
import org.apache.lucene.store.LockObtainFailedException;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -115,7 +116,16 @@ public abstract class IndexReader {
|
|||
private boolean directoryOwner;
|
||||
private boolean closeDirectory;
|
||||
private IndexDeletionPolicy deletionPolicy;
|
||||
private boolean isClosed;
|
||||
private boolean closed;
|
||||
|
||||
/**
|
||||
* @throws AlreadyClosedException if this IndexReader is closed
|
||||
*/
|
||||
protected final void ensureOpen() throws AlreadyClosedException {
|
||||
if (closed) {
|
||||
throw new AlreadyClosedException("this IndexReader is closed");
|
||||
}
|
||||
}
|
||||
|
||||
private SegmentInfos segmentInfos;
|
||||
private Lock writeLock;
|
||||
|
@ -208,8 +218,12 @@ public abstract class IndexReader {
|
|||
}.run();
|
||||
}
|
||||
|
||||
/** Returns the directory this index resides in. */
|
||||
public Directory directory() { return directory; }
|
||||
/** Returns the directory this index resides in.
|
||||
*/
|
||||
public Directory directory() {
|
||||
ensureOpen();
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the index in the named directory was last modified.
|
||||
|
@ -301,6 +315,7 @@ public abstract class IndexReader {
|
|||
* Version number when this IndexReader was opened.
|
||||
*/
|
||||
public long getVersion() {
|
||||
ensureOpen();
|
||||
return segmentInfos.getVersion();
|
||||
}
|
||||
|
||||
|
@ -313,6 +328,7 @@ public abstract class IndexReader {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public boolean isCurrent() throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion();
|
||||
}
|
||||
|
||||
|
@ -321,7 +337,8 @@ public abstract class IndexReader {
|
|||
* @return <code>true</code> if the index is optimized; <code>false</code> otherwise
|
||||
*/
|
||||
public boolean isOptimized() {
|
||||
return segmentInfos.size() == 1 && hasDeletions() == false;
|
||||
ensureOpen();
|
||||
return segmentInfos.size() == 1 && hasDeletions() == false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -407,6 +424,7 @@ public abstract class IndexReader {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public Document document(int n) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
return document(n, null);
|
||||
}
|
||||
|
||||
|
@ -445,6 +463,7 @@ public abstract class IndexReader {
|
|||
public boolean hasNorms(String field) throws IOException {
|
||||
// backward compatible implementation.
|
||||
// SegmentReader has an efficient implementation.
|
||||
ensureOpen();
|
||||
return norms(field) != null;
|
||||
}
|
||||
|
||||
|
@ -477,11 +496,11 @@ public abstract class IndexReader {
|
|||
* @throws LockObtainFailedException if another writer
|
||||
* has this index open (<code>write.lock</code> could not
|
||||
* be obtained)
|
||||
* @throws IOException if this reader was closed already
|
||||
* or there is a low-level IO error
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public final synchronized void setNorm(int doc, String field, byte value)
|
||||
throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
|
||||
ensureOpen();
|
||||
if(directoryOwner)
|
||||
acquireWriteLock();
|
||||
hasChanges = true;
|
||||
|
@ -504,27 +523,31 @@ public abstract class IndexReader {
|
|||
* @throws LockObtainFailedException if another writer
|
||||
* has this index open (<code>write.lock</code> could not
|
||||
* be obtained)
|
||||
* @throws IOException if this reader was closed already
|
||||
* or there is a low-level IO error
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public void setNorm(int doc, String field, float value)
|
||||
throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
|
||||
ensureOpen();
|
||||
setNorm(doc, field, Similarity.encodeNorm(value));
|
||||
}
|
||||
|
||||
/** Returns an enumeration of all the terms in the index.
|
||||
* The enumeration is ordered by Term.compareTo(). Each term
|
||||
* is greater than all that precede it in the enumeration.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public abstract TermEnum terms() throws IOException;
|
||||
|
||||
/** Returns an enumeration of all terms after a given term.
|
||||
* The enumeration is ordered by Term.compareTo(). Each term
|
||||
* is greater than all that precede it in the enumeration.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public abstract TermEnum terms(Term t) throws IOException;
|
||||
|
||||
/** Returns the number of documents containing the term <code>t</code>. */
|
||||
/** Returns the number of documents containing the term <code>t</code>.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public abstract int docFreq(Term t) throws IOException;
|
||||
|
||||
/** Returns an enumeration of all the documents which contain
|
||||
|
@ -536,14 +559,18 @@ public abstract class IndexReader {
|
|||
* </ul>
|
||||
* <p>The enumeration is ordered by document number. Each document number
|
||||
* is greater than all that precede it in the enumeration.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public TermDocs termDocs(Term term) throws IOException {
|
||||
ensureOpen();
|
||||
TermDocs termDocs = termDocs();
|
||||
termDocs.seek(term);
|
||||
return termDocs;
|
||||
}
|
||||
|
||||
/** Returns an unpositioned {@link TermDocs} enumerator. */
|
||||
/** Returns an unpositioned {@link TermDocs} enumerator.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public abstract TermDocs termDocs() throws IOException;
|
||||
|
||||
/** Returns an enumeration of all the documents which contain
|
||||
|
@ -561,14 +588,18 @@ public abstract class IndexReader {
|
|||
* <p> This positional information faciliates phrase and proximity searching.
|
||||
* <p>The enumeration is ordered by document number. Each document number is
|
||||
* greater than all that precede it in the enumeration.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public TermPositions termPositions(Term term) throws IOException {
|
||||
ensureOpen();
|
||||
TermPositions termPositions = termPositions();
|
||||
termPositions.seek(term);
|
||||
return termPositions;
|
||||
}
|
||||
|
||||
/** Returns an unpositioned {@link TermPositions} enumerator. */
|
||||
/** Returns an unpositioned {@link TermPositions} enumerator.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public abstract TermPositions termPositions() throws IOException;
|
||||
|
||||
/**
|
||||
|
@ -584,10 +615,9 @@ public abstract class IndexReader {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
private void acquireWriteLock() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
|
||||
ensureOpen();
|
||||
if (stale)
|
||||
throw new StaleReaderException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations");
|
||||
if (isClosed)
|
||||
throw new IOException("this reader is closed");
|
||||
|
||||
if (writeLock == null) {
|
||||
Lock writeLock = directory.makeLock(IndexWriter.WRITE_LOCK_NAME);
|
||||
|
@ -620,10 +650,10 @@ public abstract class IndexReader {
|
|||
* @throws LockObtainFailedException if another writer
|
||||
* has this index open (<code>write.lock</code> could not
|
||||
* be obtained)
|
||||
* @throws IOException if this reader was closed already
|
||||
* or there is a low-level IO error
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public final synchronized void deleteDocument(int docNum) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
|
||||
ensureOpen();
|
||||
if(directoryOwner)
|
||||
acquireWriteLock();
|
||||
hasChanges = true;
|
||||
|
@ -652,10 +682,10 @@ public abstract class IndexReader {
|
|||
* @throws LockObtainFailedException if another writer
|
||||
* has this index open (<code>write.lock</code> could not
|
||||
* be obtained)
|
||||
* @throws IOException if this reader was closed already
|
||||
* or there is a low-level IO error
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public final int deleteDocuments(Term term) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
|
||||
ensureOpen();
|
||||
TermDocs docs = termDocs(term);
|
||||
if (docs == null) return 0;
|
||||
int n = 0;
|
||||
|
@ -678,10 +708,10 @@ public abstract class IndexReader {
|
|||
* has this index open (<code>write.lock</code> could not
|
||||
* be obtained)
|
||||
* @throws CorruptIndexException if the index is corrupt
|
||||
* @throws IOException if this reader was closed already
|
||||
* or there is a low-level IO error
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public final synchronized void undeleteAll() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
|
||||
ensureOpen();
|
||||
if(directoryOwner)
|
||||
acquireWriteLock();
|
||||
hasChanges = true;
|
||||
|
@ -790,19 +820,16 @@ public abstract class IndexReader {
|
|||
* 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 this reader was closed already
|
||||
* or there is a low-level IO error
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public final synchronized void close() throws IOException {
|
||||
if (directoryOwner && isClosed) {
|
||||
throw new IOException("this reader is already closed");
|
||||
}
|
||||
commit();
|
||||
doClose();
|
||||
if(closeDirectory)
|
||||
directory.close();
|
||||
if (directoryOwner) {
|
||||
isClosed = true;
|
||||
if (!closed) {
|
||||
commit();
|
||||
doClose();
|
||||
if (directoryOwner)
|
||||
closed = true;
|
||||
if(closeDirectory)
|
||||
directory.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.lucene.store.Directory;
|
|||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.Lock;
|
||||
import org.apache.lucene.store.LockObtainFailedException;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -208,6 +209,16 @@ public class IndexWriter {
|
|||
private boolean useCompoundFile = true;
|
||||
|
||||
private boolean closeDir;
|
||||
private boolean closed;
|
||||
|
||||
/**
|
||||
* @throws AlreadyClosedException if this IndexWriter is closed
|
||||
*/
|
||||
protected final void ensureOpen() throws AlreadyClosedException {
|
||||
if (closed) {
|
||||
throw new AlreadyClosedException("this IndexWriter is closed");
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the current setting of whether to use the compound file format.
|
||||
* Note that this just returns the value you set with setUseCompoundFile(boolean)
|
||||
|
@ -215,6 +226,7 @@ public class IndexWriter {
|
|||
* @see #setUseCompoundFile(boolean)
|
||||
*/
|
||||
public boolean getUseCompoundFile() {
|
||||
ensureOpen();
|
||||
return useCompoundFile;
|
||||
}
|
||||
|
||||
|
@ -223,6 +235,7 @@ public class IndexWriter {
|
|||
* is finished. This is done regardless of what directory is in use.
|
||||
*/
|
||||
public void setUseCompoundFile(boolean value) {
|
||||
ensureOpen();
|
||||
useCompoundFile = value;
|
||||
}
|
||||
|
||||
|
@ -231,6 +244,7 @@ public class IndexWriter {
|
|||
* @see Similarity#setDefault(Similarity)
|
||||
*/
|
||||
public void setSimilarity(Similarity similarity) {
|
||||
ensureOpen();
|
||||
this.similarity = similarity;
|
||||
}
|
||||
|
||||
|
@ -239,6 +253,7 @@ public class IndexWriter {
|
|||
* <p>This defaults to the current value of {@link Similarity#getDefault()}.
|
||||
*/
|
||||
public Similarity getSimilarity() {
|
||||
ensureOpen();
|
||||
return this.similarity;
|
||||
}
|
||||
|
||||
|
@ -264,6 +279,7 @@ public class IndexWriter {
|
|||
* @see #DEFAULT_TERM_INDEX_INTERVAL
|
||||
*/
|
||||
public void setTermIndexInterval(int interval) {
|
||||
ensureOpen();
|
||||
this.termIndexInterval = interval;
|
||||
}
|
||||
|
||||
|
@ -271,7 +287,10 @@ public class IndexWriter {
|
|||
*
|
||||
* @see #setTermIndexInterval(int)
|
||||
*/
|
||||
public int getTermIndexInterval() { return termIndexInterval; }
|
||||
public int getTermIndexInterval() {
|
||||
ensureOpen();
|
||||
return termIndexInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an IndexWriter for the index in <code>path</code>.
|
||||
|
@ -580,6 +599,7 @@ public class IndexWriter {
|
|||
* <p>The default value is {@link Integer#MAX_VALUE}.
|
||||
*/
|
||||
public void setMaxMergeDocs(int maxMergeDocs) {
|
||||
ensureOpen();
|
||||
this.maxMergeDocs = maxMergeDocs;
|
||||
}
|
||||
|
||||
|
@ -587,6 +607,7 @@ public class IndexWriter {
|
|||
* @see #setMaxMergeDocs
|
||||
*/
|
||||
public int getMaxMergeDocs() {
|
||||
ensureOpen();
|
||||
return maxMergeDocs;
|
||||
}
|
||||
|
||||
|
@ -603,6 +624,7 @@ public class IndexWriter {
|
|||
* By default, no more than 10,000 terms will be indexed for a field.
|
||||
*/
|
||||
public void setMaxFieldLength(int maxFieldLength) {
|
||||
ensureOpen();
|
||||
this.maxFieldLength = maxFieldLength;
|
||||
}
|
||||
|
||||
|
@ -610,6 +632,7 @@ public class IndexWriter {
|
|||
* @see #setMaxFieldLength
|
||||
*/
|
||||
public int getMaxFieldLength() {
|
||||
ensureOpen();
|
||||
return maxFieldLength;
|
||||
}
|
||||
|
||||
|
@ -624,6 +647,7 @@ public class IndexWriter {
|
|||
* @throws IllegalArgumentException if maxBufferedDocs is smaller than 2
|
||||
*/
|
||||
public void setMaxBufferedDocs(int maxBufferedDocs) {
|
||||
ensureOpen();
|
||||
if (maxBufferedDocs < 2)
|
||||
throw new IllegalArgumentException("maxBufferedDocs must at least be 2");
|
||||
this.minMergeDocs = maxBufferedDocs;
|
||||
|
@ -633,6 +657,7 @@ public class IndexWriter {
|
|||
* @see #setMaxBufferedDocs
|
||||
*/
|
||||
public int getMaxBufferedDocs() {
|
||||
ensureOpen();
|
||||
return minMergeDocs;
|
||||
}
|
||||
|
||||
|
@ -646,6 +671,7 @@ public class IndexWriter {
|
|||
* @throws IllegalArgumentException if maxBufferedDeleteTerms is smaller than 1</p>
|
||||
*/
|
||||
public void setMaxBufferedDeleteTerms(int maxBufferedDeleteTerms) {
|
||||
ensureOpen();
|
||||
if (maxBufferedDeleteTerms < 1)
|
||||
throw new IllegalArgumentException("maxBufferedDeleteTerms must at least be 1");
|
||||
this.maxBufferedDeleteTerms = maxBufferedDeleteTerms;
|
||||
|
@ -655,6 +681,7 @@ public class IndexWriter {
|
|||
* @see #setMaxBufferedDeleteTerms
|
||||
*/
|
||||
public int getMaxBufferedDeleteTerms() {
|
||||
ensureOpen();
|
||||
return maxBufferedDeleteTerms;
|
||||
}
|
||||
|
||||
|
@ -669,6 +696,7 @@ public class IndexWriter {
|
|||
* <p>This must never be less than 2. The default value is 10.
|
||||
*/
|
||||
public void setMergeFactor(int mergeFactor) {
|
||||
ensureOpen();
|
||||
if (mergeFactor < 2)
|
||||
throw new IllegalArgumentException("mergeFactor cannot be less than 2");
|
||||
this.mergeFactor = mergeFactor;
|
||||
|
@ -678,6 +706,7 @@ public class IndexWriter {
|
|||
* @see #setMergeFactor
|
||||
*/
|
||||
public int getMergeFactor() {
|
||||
ensureOpen();
|
||||
return mergeFactor;
|
||||
}
|
||||
|
||||
|
@ -701,6 +730,7 @@ public class IndexWriter {
|
|||
* to this.
|
||||
*/
|
||||
public void setInfoStream(PrintStream infoStream) {
|
||||
ensureOpen();
|
||||
this.infoStream = infoStream;
|
||||
deleter.setInfoStream(infoStream);
|
||||
}
|
||||
|
@ -709,6 +739,7 @@ public class IndexWriter {
|
|||
* @see #setInfoStream
|
||||
*/
|
||||
public PrintStream getInfoStream() {
|
||||
ensureOpen();
|
||||
return infoStream;
|
||||
}
|
||||
|
||||
|
@ -717,6 +748,7 @@ public class IndexWriter {
|
|||
* @see #setDefaultWriteLockTimeout to change the default value for all instances of IndexWriter.
|
||||
*/
|
||||
public void setWriteLockTimeout(long writeLockTimeout) {
|
||||
ensureOpen();
|
||||
this.writeLockTimeout = writeLockTimeout;
|
||||
}
|
||||
|
||||
|
@ -724,6 +756,7 @@ public class IndexWriter {
|
|||
* @see #setWriteLockTimeout
|
||||
*/
|
||||
public long getWriteLockTimeout() {
|
||||
ensureOpen();
|
||||
return writeLockTimeout;
|
||||
}
|
||||
|
||||
|
@ -777,22 +810,26 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public synchronized void close() throws CorruptIndexException, IOException {
|
||||
flushRamSegments();
|
||||
if (!closed) {
|
||||
flushRamSegments();
|
||||
|
||||
if (commitPending) {
|
||||
segmentInfos.write(directory); // now commit changes
|
||||
deleter.checkpoint(segmentInfos, true);
|
||||
commitPending = false;
|
||||
rollbackSegmentInfos = null;
|
||||
}
|
||||
if (commitPending) {
|
||||
segmentInfos.write(directory); // now commit changes
|
||||
deleter.checkpoint(segmentInfos, true);
|
||||
commitPending = false;
|
||||
rollbackSegmentInfos = null;
|
||||
}
|
||||
|
||||
ramDirectory.close();
|
||||
if (writeLock != null) {
|
||||
writeLock.release(); // release write lock
|
||||
writeLock = null;
|
||||
ramDirectory.close();
|
||||
if (writeLock != null) {
|
||||
writeLock.release(); // release write lock
|
||||
writeLock = null;
|
||||
}
|
||||
closed = true;
|
||||
|
||||
if(closeDir)
|
||||
directory.close();
|
||||
}
|
||||
if(closeDir)
|
||||
directory.close();
|
||||
}
|
||||
|
||||
/** Release the write lock, if needed. */
|
||||
|
@ -809,17 +846,20 @@ public class IndexWriter {
|
|||
|
||||
/** Returns the Directory used by this index. */
|
||||
public Directory getDirectory() {
|
||||
return directory;
|
||||
ensureOpen();
|
||||
return directory;
|
||||
}
|
||||
|
||||
/** Returns the analyzer used by this index. */
|
||||
public Analyzer getAnalyzer() {
|
||||
return analyzer;
|
||||
ensureOpen();
|
||||
return analyzer;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the number of documents currently in this index. */
|
||||
public synchronized int docCount() {
|
||||
ensureOpen();
|
||||
int count = ramSegmentInfos.size();
|
||||
for (int i = 0; i < segmentInfos.size(); i++) {
|
||||
SegmentInfo si = segmentInfos.info(i);
|
||||
|
@ -897,6 +937,7 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public void addDocument(Document doc, Analyzer analyzer) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
SegmentInfo newSegmentInfo = buildSingleDocSegment(doc, analyzer);
|
||||
synchronized (this) {
|
||||
ramSegmentInfos.addElement(newSegmentInfo);
|
||||
|
@ -922,6 +963,7 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public synchronized void deleteDocuments(Term term) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
bufferDeleteTerm(term);
|
||||
maybeFlushRamSegments();
|
||||
}
|
||||
|
@ -935,6 +977,7 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public synchronized void deleteDocuments(Term[] terms) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
for (int i = 0; i < terms.length; i++) {
|
||||
bufferDeleteTerm(terms[i]);
|
||||
}
|
||||
|
@ -954,6 +997,7 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public void updateDocument(Term term, Document doc) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
updateDocument(term, doc, getAnalyzer());
|
||||
}
|
||||
|
||||
|
@ -972,6 +1016,7 @@ public class IndexWriter {
|
|||
*/
|
||||
public void updateDocument(Term term, Document doc, Analyzer analyzer)
|
||||
throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
SegmentInfo newSegmentInfo = buildSingleDocSegment(doc, analyzer);
|
||||
synchronized (this) {
|
||||
bufferDeleteTerm(term);
|
||||
|
@ -1107,6 +1152,7 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public synchronized void optimize() throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
flushRamSegments();
|
||||
while (segmentInfos.size() > 1 ||
|
||||
(segmentInfos.size() == 1 &&
|
||||
|
@ -1200,6 +1246,7 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public void abort() throws IOException {
|
||||
ensureOpen();
|
||||
if (!autoCommit) {
|
||||
|
||||
// Keep the same segmentInfos instance but replace all
|
||||
|
@ -1290,6 +1337,7 @@ public class IndexWriter {
|
|||
public synchronized void addIndexes(Directory[] dirs)
|
||||
throws CorruptIndexException, IOException {
|
||||
|
||||
ensureOpen();
|
||||
optimize(); // start with zero or 1 seg
|
||||
|
||||
int start = segmentInfos.size();
|
||||
|
@ -1375,6 +1423,7 @@ public class IndexWriter {
|
|||
|
||||
// 1 flush ram segments
|
||||
|
||||
ensureOpen();
|
||||
flushRamSegments();
|
||||
|
||||
// 2 copy segment infos and find the highest level from dirs
|
||||
|
@ -1479,6 +1528,7 @@ public class IndexWriter {
|
|||
public synchronized void addIndexes(IndexReader[] readers)
|
||||
throws CorruptIndexException, IOException {
|
||||
|
||||
ensureOpen();
|
||||
optimize(); // start with zero or 1 seg
|
||||
|
||||
final String mergedName = newSegmentName();
|
||||
|
@ -1610,6 +1660,7 @@ public class IndexWriter {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public final synchronized void flush() throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
flushRamSegments();
|
||||
}
|
||||
|
||||
|
@ -1617,6 +1668,7 @@ public class IndexWriter {
|
|||
* Useful for size management with flushRamDocs()
|
||||
*/
|
||||
public final long ramSizeInBytes() {
|
||||
ensureOpen();
|
||||
return ramDirectory.sizeInBytes();
|
||||
}
|
||||
|
||||
|
@ -1624,6 +1676,7 @@ public class IndexWriter {
|
|||
* Useful when calling flushRamSegments()
|
||||
*/
|
||||
public final synchronized int numRamDocs() {
|
||||
ensureOpen();
|
||||
return ramSegmentInfos.size();
|
||||
}
|
||||
|
||||
|
|
|
@ -72,24 +72,21 @@ public class MultiReader extends IndexReader {
|
|||
}
|
||||
|
||||
|
||||
/** Return an array of term frequency vectors for the specified document.
|
||||
* The array contains a vector for each vectorized field in the document.
|
||||
* Each vector vector contains term numbers and frequencies for all terms
|
||||
* in a given vectorized field.
|
||||
* If no such fields existed, the method returns null.
|
||||
*/
|
||||
public TermFreqVector[] getTermFreqVectors(int n) throws IOException {
|
||||
ensureOpen();
|
||||
int i = readerIndex(n); // find segment num
|
||||
return subReaders[i].getTermFreqVectors(n - starts[i]); // dispatch to segment
|
||||
}
|
||||
|
||||
public TermFreqVector getTermFreqVector(int n, String field)
|
||||
throws IOException {
|
||||
ensureOpen();
|
||||
int i = readerIndex(n); // find segment num
|
||||
return subReaders[i].getTermFreqVector(n - starts[i], field);
|
||||
}
|
||||
|
||||
public synchronized int numDocs() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
if (numDocs == -1) { // check cache
|
||||
int n = 0; // cache miss--recompute
|
||||
for (int i = 0; i < subReaders.length; i++)
|
||||
|
@ -100,21 +97,27 @@ public class MultiReader extends IndexReader {
|
|||
}
|
||||
|
||||
public int maxDoc() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return maxDoc;
|
||||
}
|
||||
|
||||
// inherit javadoc
|
||||
public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
int i = readerIndex(n); // find segment num
|
||||
return subReaders[i].document(n - starts[i], fieldSelector); // dispatch to segment reader
|
||||
}
|
||||
|
||||
public boolean isDeleted(int n) {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
int i = readerIndex(n); // find segment num
|
||||
return subReaders[i].isDeleted(n - starts[i]); // dispatch to segment reader
|
||||
}
|
||||
|
||||
public boolean hasDeletions() { return hasDeletions; }
|
||||
public boolean hasDeletions() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return hasDeletions;
|
||||
}
|
||||
|
||||
protected void doDelete(int n) throws CorruptIndexException, IOException {
|
||||
numDocs = -1; // invalidate cache
|
||||
|
@ -153,6 +156,7 @@ public class MultiReader extends IndexReader {
|
|||
}
|
||||
|
||||
public boolean hasNorms(String field) throws IOException {
|
||||
ensureOpen();
|
||||
for (int i = 0; i < subReaders.length; i++) {
|
||||
if (subReaders[i].hasNorms(field)) return true;
|
||||
}
|
||||
|
@ -166,6 +170,7 @@ public class MultiReader extends IndexReader {
|
|||
}
|
||||
|
||||
public synchronized byte[] norms(String field) throws IOException {
|
||||
ensureOpen();
|
||||
byte[] bytes = (byte[])normsCache.get(field);
|
||||
if (bytes != null)
|
||||
return bytes; // cache hit
|
||||
|
@ -181,6 +186,7 @@ public class MultiReader extends IndexReader {
|
|||
|
||||
public synchronized void norms(String field, byte[] result, int offset)
|
||||
throws IOException {
|
||||
ensureOpen();
|
||||
byte[] bytes = (byte[])normsCache.get(field);
|
||||
if (bytes==null && !hasNorms(field)) bytes=fakeNorms();
|
||||
if (bytes != null) // cache hit
|
||||
|
@ -198,14 +204,17 @@ public class MultiReader extends IndexReader {
|
|||
}
|
||||
|
||||
public TermEnum terms() throws IOException {
|
||||
ensureOpen();
|
||||
return new MultiTermEnum(subReaders, starts, null);
|
||||
}
|
||||
|
||||
public TermEnum terms(Term term) throws IOException {
|
||||
ensureOpen();
|
||||
return new MultiTermEnum(subReaders, starts, term);
|
||||
}
|
||||
|
||||
public int docFreq(Term t) throws IOException {
|
||||
ensureOpen();
|
||||
int total = 0; // sum freqs in segments
|
||||
for (int i = 0; i < subReaders.length; i++)
|
||||
total += subReaders[i].docFreq(t);
|
||||
|
@ -213,10 +222,12 @@ public class MultiReader extends IndexReader {
|
|||
}
|
||||
|
||||
public TermDocs termDocs() throws IOException {
|
||||
ensureOpen();
|
||||
return new MultiTermDocs(subReaders, starts);
|
||||
}
|
||||
|
||||
public TermPositions termPositions() throws IOException {
|
||||
ensureOpen();
|
||||
return new MultiTermPositions(subReaders, starts);
|
||||
}
|
||||
|
||||
|
@ -244,11 +255,9 @@ public class MultiReader extends IndexReader {
|
|||
subReaders[i].close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IndexReader#getFieldNames(IndexReader.FieldOption)
|
||||
*/
|
||||
public Collection getFieldNames (IndexReader.FieldOption fieldNames) {
|
||||
// maintain a unique set of field names
|
||||
ensureOpen();
|
||||
Set fieldSet = new HashSet();
|
||||
for (int i = 0; i < subReaders.length; i++) {
|
||||
IndexReader reader = subReaders[i];
|
||||
|
|
|
@ -66,8 +66,11 @@ public class ParallelReader extends IndexReader {
|
|||
/** Construct a ParallelReader. */
|
||||
public ParallelReader() throws IOException { super(null); }
|
||||
|
||||
/** Add an IndexReader. */
|
||||
/** Add an IndexReader.
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public void add(IndexReader reader) throws IOException {
|
||||
ensureOpen();
|
||||
add(reader, false);
|
||||
}
|
||||
|
||||
|
@ -79,10 +82,12 @@ public class ParallelReader extends IndexReader {
|
|||
* of documents
|
||||
* @throws IllegalArgumentException if not all indexes have the same value
|
||||
* of {@link IndexReader#maxDoc()}
|
||||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public void add(IndexReader reader, boolean ignoreStoredFields)
|
||||
throws IOException {
|
||||
|
||||
ensureOpen();
|
||||
if (readers.size() == 0) {
|
||||
this.maxDoc = reader.maxDoc();
|
||||
this.numDocs = reader.numDocs();
|
||||
|
@ -110,14 +115,24 @@ public class ParallelReader extends IndexReader {
|
|||
readers.add(reader);
|
||||
}
|
||||
|
||||
public int numDocs() { return numDocs; }
|
||||
public int numDocs() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return numDocs;
|
||||
}
|
||||
|
||||
public int maxDoc() { return maxDoc; }
|
||||
public int maxDoc() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return maxDoc;
|
||||
}
|
||||
|
||||
public boolean hasDeletions() { return hasDeletions; }
|
||||
public boolean hasDeletions() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return hasDeletions;
|
||||
}
|
||||
|
||||
// check first reader
|
||||
public boolean isDeleted(int n) {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
if (readers.size() > 0)
|
||||
return ((IndexReader)readers.get(0)).isDeleted(n);
|
||||
return false;
|
||||
|
@ -141,6 +156,7 @@ public class ParallelReader extends IndexReader {
|
|||
|
||||
// append fields from storedFieldReaders
|
||||
public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
Document result = new Document();
|
||||
for (int i = 0; i < storedFieldReaders.size(); i++) {
|
||||
IndexReader reader = (IndexReader)storedFieldReaders.get(i);
|
||||
|
@ -166,6 +182,7 @@ public class ParallelReader extends IndexReader {
|
|||
|
||||
// get all vectors
|
||||
public TermFreqVector[] getTermFreqVectors(int n) throws IOException {
|
||||
ensureOpen();
|
||||
ArrayList results = new ArrayList();
|
||||
Iterator i = fieldToReader.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
|
@ -182,22 +199,26 @@ public class ParallelReader extends IndexReader {
|
|||
|
||||
public TermFreqVector getTermFreqVector(int n, String field)
|
||||
throws IOException {
|
||||
ensureOpen();
|
||||
IndexReader reader = ((IndexReader)fieldToReader.get(field));
|
||||
return reader==null ? null : reader.getTermFreqVector(n, field);
|
||||
}
|
||||
|
||||
public boolean hasNorms(String field) throws IOException {
|
||||
ensureOpen();
|
||||
IndexReader reader = ((IndexReader)fieldToReader.get(field));
|
||||
return reader==null ? false : reader.hasNorms(field);
|
||||
}
|
||||
|
||||
public byte[] norms(String field) throws IOException {
|
||||
ensureOpen();
|
||||
IndexReader reader = ((IndexReader)fieldToReader.get(field));
|
||||
return reader==null ? null : reader.norms(field);
|
||||
}
|
||||
|
||||
public void norms(String field, byte[] result, int offset)
|
||||
throws IOException {
|
||||
ensureOpen();
|
||||
IndexReader reader = ((IndexReader)fieldToReader.get(field));
|
||||
if (reader!=null)
|
||||
reader.norms(field, result, offset);
|
||||
|
@ -211,31 +232,38 @@ public class ParallelReader extends IndexReader {
|
|||
}
|
||||
|
||||
public TermEnum terms() throws IOException {
|
||||
ensureOpen();
|
||||
return new ParallelTermEnum();
|
||||
}
|
||||
|
||||
public TermEnum terms(Term term) throws IOException {
|
||||
ensureOpen();
|
||||
return new ParallelTermEnum(term);
|
||||
}
|
||||
|
||||
public int docFreq(Term term) throws IOException {
|
||||
ensureOpen();
|
||||
IndexReader reader = ((IndexReader)fieldToReader.get(term.field()));
|
||||
return reader==null ? 0 : reader.docFreq(term);
|
||||
}
|
||||
|
||||
public TermDocs termDocs(Term term) throws IOException {
|
||||
ensureOpen();
|
||||
return new ParallelTermDocs(term);
|
||||
}
|
||||
|
||||
public TermDocs termDocs() throws IOException {
|
||||
ensureOpen();
|
||||
return new ParallelTermDocs();
|
||||
}
|
||||
|
||||
public TermPositions termPositions(Term term) throws IOException {
|
||||
ensureOpen();
|
||||
return new ParallelTermPositions(term);
|
||||
}
|
||||
|
||||
public TermPositions termPositions() throws IOException {
|
||||
ensureOpen();
|
||||
return new ParallelTermPositions();
|
||||
}
|
||||
|
||||
|
@ -251,6 +279,7 @@ public class ParallelReader extends IndexReader {
|
|||
|
||||
|
||||
public Collection getFieldNames (IndexReader.FieldOption fieldNames) {
|
||||
ensureOpen();
|
||||
Set fieldSet = new HashSet();
|
||||
for (int i = 0; i < readers.size(); i++) {
|
||||
IndexReader reader = ((IndexReader)readers.get(i));
|
||||
|
|
|
@ -266,10 +266,12 @@ class SegmentReader extends IndexReader {
|
|||
}
|
||||
|
||||
static boolean hasDeletions(SegmentInfo si) throws IOException {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return si.hasDeletions();
|
||||
}
|
||||
|
||||
public boolean hasDeletions() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return deletedDocs != null;
|
||||
}
|
||||
|
||||
|
@ -300,10 +302,12 @@ class SegmentReader extends IndexReader {
|
|||
}
|
||||
|
||||
public TermEnum terms() {
|
||||
ensureOpen();
|
||||
return tis.terms();
|
||||
}
|
||||
|
||||
public TermEnum terms(Term t) throws IOException {
|
||||
ensureOpen();
|
||||
return tis.terms(t);
|
||||
}
|
||||
|
||||
|
@ -312,6 +316,7 @@ class SegmentReader extends IndexReader {
|
|||
* @throws IOException if there is a low-level IO error
|
||||
*/
|
||||
public synchronized Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
|
||||
ensureOpen();
|
||||
if (isDeleted(n))
|
||||
throw new IllegalArgumentException
|
||||
("attempt to access a deleted document");
|
||||
|
@ -323,14 +328,17 @@ class SegmentReader extends IndexReader {
|
|||
}
|
||||
|
||||
public TermDocs termDocs() throws IOException {
|
||||
ensureOpen();
|
||||
return new SegmentTermDocs(this);
|
||||
}
|
||||
|
||||
public TermPositions termPositions() throws IOException {
|
||||
ensureOpen();
|
||||
return new SegmentTermPositions(this);
|
||||
}
|
||||
|
||||
public int docFreq(Term t) throws IOException {
|
||||
ensureOpen();
|
||||
TermInfo ti = tis.get(t);
|
||||
if (ti != null)
|
||||
return ti.docFreq;
|
||||
|
@ -339,6 +347,7 @@ class SegmentReader extends IndexReader {
|
|||
}
|
||||
|
||||
public int numDocs() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
int n = maxDoc();
|
||||
if (deletedDocs != null)
|
||||
n -= deletedDocs.count();
|
||||
|
@ -346,6 +355,7 @@ class SegmentReader extends IndexReader {
|
|||
}
|
||||
|
||||
public int maxDoc() {
|
||||
// Don't call ensureOpen() here (it could affect performance)
|
||||
return si.docCount;
|
||||
}
|
||||
|
||||
|
@ -353,6 +363,7 @@ class SegmentReader extends IndexReader {
|
|||
* @see IndexReader#getFieldNames(IndexReader.FieldOption fldOption)
|
||||
*/
|
||||
public Collection getFieldNames(IndexReader.FieldOption fieldOption) {
|
||||
ensureOpen();
|
||||
|
||||
Set fieldSet = new HashSet();
|
||||
for (int i = 0; i < fieldInfos.size(); i++) {
|
||||
|
@ -394,6 +405,7 @@ class SegmentReader extends IndexReader {
|
|||
|
||||
|
||||
public synchronized boolean hasNorms(String field) {
|
||||
ensureOpen();
|
||||
return norms.containsKey(field);
|
||||
}
|
||||
|
||||
|
@ -426,6 +438,7 @@ class SegmentReader extends IndexReader {
|
|||
|
||||
// returns fake norms if norms aren't available
|
||||
public synchronized byte[] norms(String field) throws IOException {
|
||||
ensureOpen();
|
||||
byte[] bytes = getNorms(field);
|
||||
if (bytes==null) bytes=fakeNorms();
|
||||
return bytes;
|
||||
|
@ -447,6 +460,7 @@ class SegmentReader extends IndexReader {
|
|||
public synchronized void norms(String field, byte[] bytes, int offset)
|
||||
throws IOException {
|
||||
|
||||
ensureOpen();
|
||||
Norm norm = (Norm) norms.get(field);
|
||||
if (norm == null) {
|
||||
System.arraycopy(fakeNorms(), 0, bytes, offset, maxDoc());
|
||||
|
@ -537,6 +551,7 @@ class SegmentReader extends IndexReader {
|
|||
*/
|
||||
public TermFreqVector getTermFreqVector(int docNumber, String field) throws IOException {
|
||||
// Check if this field is invalid or has no stored term vector
|
||||
ensureOpen();
|
||||
FieldInfo fi = fieldInfos.fieldInfo(field);
|
||||
if (fi == null || !fi.storeTermVector || termVectorsReaderOrig == null)
|
||||
return null;
|
||||
|
@ -557,6 +572,7 @@ class SegmentReader extends IndexReader {
|
|||
* @throws IOException
|
||||
*/
|
||||
public TermFreqVector[] getTermFreqVectors(int docNumber) throws IOException {
|
||||
ensureOpen();
|
||||
if (termVectorsReaderOrig == null)
|
||||
return null;
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package org.apache.lucene.store;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This exception is thrown when there is an attempt to
|
||||
* access something that has already been closed.
|
||||
*/
|
||||
public class AlreadyClosedException extends IllegalStateException {
|
||||
public AlreadyClosedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -97,6 +97,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
|
||||
/** Returns an array of strings, one for each file in the directory. */
|
||||
public synchronized final String[] list() {
|
||||
ensureOpen();
|
||||
Set fileNames = fileMap.keySet();
|
||||
String[] result = new String[fileNames.size()];
|
||||
int i = 0;
|
||||
|
@ -108,6 +109,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
|
||||
/** Returns true iff the named file exists in this directory. */
|
||||
public final boolean fileExists(String name) {
|
||||
ensureOpen();
|
||||
RAMFile file;
|
||||
synchronized (this) {
|
||||
file = (RAMFile)fileMap.get(name);
|
||||
|
@ -119,6 +121,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
* @throws IOException if the file does not exist
|
||||
*/
|
||||
public final long fileModified(String name) throws IOException {
|
||||
ensureOpen();
|
||||
RAMFile file;
|
||||
synchronized (this) {
|
||||
file = (RAMFile)fileMap.get(name);
|
||||
|
@ -132,6 +135,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
* @throws IOException if the file does not exist
|
||||
*/
|
||||
public void touchFile(String name) throws IOException {
|
||||
ensureOpen();
|
||||
RAMFile file;
|
||||
synchronized (this) {
|
||||
file = (RAMFile)fileMap.get(name);
|
||||
|
@ -154,6 +158,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
* @throws IOException if the file does not exist
|
||||
*/
|
||||
public final long fileLength(String name) throws IOException {
|
||||
ensureOpen();
|
||||
RAMFile file;
|
||||
synchronized (this) {
|
||||
file = (RAMFile)fileMap.get(name);
|
||||
|
@ -167,6 +172,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
* directory. This is currently quantized to
|
||||
* BufferedIndexOutput.BUFFER_SIZE. */
|
||||
public synchronized final long sizeInBytes() {
|
||||
ensureOpen();
|
||||
return sizeInBytes;
|
||||
}
|
||||
|
||||
|
@ -174,6 +180,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
* @throws IOException if the file does not exist
|
||||
*/
|
||||
public synchronized void deleteFile(String name) throws IOException {
|
||||
ensureOpen();
|
||||
RAMFile file = (RAMFile)fileMap.get(name);
|
||||
if (file!=null) {
|
||||
fileMap.remove(name);
|
||||
|
@ -188,6 +195,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
* @deprecated
|
||||
*/
|
||||
public synchronized final void renameFile(String from, String to) throws IOException {
|
||||
ensureOpen();
|
||||
RAMFile fromFile = (RAMFile)fileMap.get(from);
|
||||
if (fromFile==null)
|
||||
throw new FileNotFoundException(from);
|
||||
|
@ -202,6 +210,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
|
||||
/** Creates a new, empty file in the directory with the given name. Returns a stream writing this file. */
|
||||
public IndexOutput createOutput(String name) {
|
||||
ensureOpen();
|
||||
RAMFile file = new RAMFile(this);
|
||||
synchronized (this) {
|
||||
RAMFile existing = (RAMFile)fileMap.get(name);
|
||||
|
@ -216,6 +225,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
|
||||
/** Returns a stream reading an existing file. */
|
||||
public IndexInput openInput(String name) throws IOException {
|
||||
ensureOpen();
|
||||
RAMFile file;
|
||||
synchronized (this) {
|
||||
file = (RAMFile)fileMap.get(name);
|
||||
|
@ -230,4 +240,12 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
fileMap = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws AlreadyClosedException if this IndexReader is closed
|
||||
*/
|
||||
protected final void ensureOpen() throws AlreadyClosedException {
|
||||
if (fileMap == null) {
|
||||
throw new AlreadyClosedException("this RAMDirectory is closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.lucene.document.*;
|
|||
import org.apache.lucene.search.Similarity;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
import org.apache.lucene.util._TestUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -133,6 +134,36 @@ public class TestFieldsReader extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testLazyFieldsAfterClose() throws Exception {
|
||||
assertTrue(dir != null);
|
||||
assertTrue(fieldInfos != null);
|
||||
FieldsReader reader = new FieldsReader(dir, "test", fieldInfos);
|
||||
assertTrue(reader != null);
|
||||
assertTrue(reader.size() == 1);
|
||||
Set loadFieldNames = new HashSet();
|
||||
loadFieldNames.add(DocHelper.TEXT_FIELD_1_KEY);
|
||||
loadFieldNames.add(DocHelper.TEXT_FIELD_UTF1_KEY);
|
||||
Set lazyFieldNames = new HashSet();
|
||||
lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
|
||||
lazyFieldNames.add(DocHelper.LAZY_FIELD_KEY);
|
||||
lazyFieldNames.add(DocHelper.LAZY_FIELD_BINARY_KEY);
|
||||
lazyFieldNames.add(DocHelper.TEXT_FIELD_UTF2_KEY);
|
||||
lazyFieldNames.add(DocHelper.COMPRESSED_TEXT_FIELD_2_KEY);
|
||||
SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames);
|
||||
Document doc = reader.doc(0, fieldSelector);
|
||||
assertTrue("doc is null and it shouldn't be", doc != null);
|
||||
Fieldable field = doc.getFieldable(DocHelper.LAZY_FIELD_KEY);
|
||||
assertTrue("field is null and it shouldn't be", field != null);
|
||||
assertTrue("field is not lazy and it should be", field.isLazy());
|
||||
reader.close();
|
||||
try {
|
||||
String value = field.stringValue();
|
||||
fail("did not hit AlreadyClosedException as expected");
|
||||
} catch (AlreadyClosedException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testLoadFirst() throws Exception {
|
||||
assertTrue(dir != null);
|
||||
assertTrue(fieldInfos != null);
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.lucene.store.Directory;
|
|||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.LockObtainFailedException;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -279,21 +280,21 @@ public class TestIndexReader extends TestCase
|
|||
try {
|
||||
reader.deleteDocument(4);
|
||||
fail("deleteDocument after close failed to throw IOException");
|
||||
} catch (IOException e) {
|
||||
} catch (AlreadyClosedException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
reader.setNorm(5, "aaa", 2.0f);
|
||||
fail("setNorm after close failed to throw IOException");
|
||||
} catch (IOException e) {
|
||||
} catch (AlreadyClosedException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
reader.undeleteAll();
|
||||
fail("undeleteAll after close failed to throw IOException");
|
||||
} catch (IOException e) {
|
||||
} catch (AlreadyClosedException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.apache.lucene.store.FSDirectory;
|
|||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.store.IndexInput;
|
||||
import org.apache.lucene.store.IndexOutput;
|
||||
import org.apache.lucene.store.AlreadyClosedException;
|
||||
|
||||
import org.apache.lucene.store.MockRAMDirectory;
|
||||
import org.apache.lucene.store.LockFactory;
|
||||
|
@ -724,6 +725,25 @@ public class TestIndexWriter extends TestCase
|
|||
}
|
||||
}
|
||||
|
||||
public void testChangesAfterClose() throws IOException {
|
||||
Directory dir = new RAMDirectory();
|
||||
|
||||
IndexWriter writer = null;
|
||||
|
||||
writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true);
|
||||
addDoc(writer);
|
||||
|
||||
// close
|
||||
writer.close();
|
||||
try {
|
||||
addDoc(writer);
|
||||
fail("did not hit AlreadyClosedException");
|
||||
} catch (AlreadyClosedException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Simulate a corrupt index by removing one of the cfs
|
||||
// files and make sure we get an IOException trying to
|
||||
// open the index:
|
||||
|
|
Loading…
Reference in New Issue