blob: 2a60602dcbc6ecae6d267db75217e975c97ecd2d [file] [log] [blame]
Index: CHANGES.txt
===================================================================
--- CHANGES.txt (revision 513819)
+++ CHANGES.txt (working copy)
@@ -20,6 +20,10 @@
classes, package-private again (they were unnecessarily made public
as part of LUCENE-701). (Mike McCandless)
+ 3. LUCENE-818: changed public methods of IndexWriter, IndexReader
+ (and its subclasses), FieldsReader 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)
Index: src/test/org/apache/lucene/search/TestMultiSearcher.java
===================================================================
--- src/test/org/apache/lucene/search/TestMultiSearcher.java (revision 513819)
+++ src/test/org/apache/lucene/search/TestMultiSearcher.java (working copy)
@@ -149,7 +149,6 @@
// no exception should happen at this point
Document d = hits2.doc(i);
}
- mSearcher2.close();
// test the subSearcher() method:
Query subSearcherQuery = parser.parse("id:doc1");
@@ -161,6 +160,7 @@
hits2 = mSearcher2.search(subSearcherQuery);
assertEquals(1, hits2.length());
assertEquals(1, mSearcher2.subSearcher(hits2.id(0))); // hit from searchers2[1]
+ mSearcher2.close();
//--------------------------------------------------------------------
// scenario 3
Index: src/test/org/apache/lucene/index/TestMultiReader.java
===================================================================
--- src/test/org/apache/lucene/index/TestMultiReader.java (revision 513819)
+++ src/test/org/apache/lucene/index/TestMultiReader.java (working copy)
@@ -85,15 +85,18 @@
assertEquals( 2, reader.numDocs() );
// Ensure undeleteAll survives commit/close/reopen:
- reader.commit();
reader.close();
sis.read(dir);
+
+ // Must re-open the readers from setUp():
+ readers[0] = SegmentReader.get(new SegmentInfo("seg-1", 1, dir));
+ readers[1] = SegmentReader.get(new SegmentInfo("seg-2", 1, dir));
+
reader = new MultiReader(dir, sis, false, readers);
assertEquals( 2, reader.numDocs() );
reader.deleteDocument(0);
assertEquals( 1, reader.numDocs() );
- reader.commit();
reader.close();
sis.read(dir);
reader = new MultiReader(dir, sis, false, readers);
Index: src/test/org/apache/lucene/index/TestFieldsReader.java
===================================================================
--- src/test/org/apache/lucene/index/TestFieldsReader.java (revision 513819)
+++ src/test/org/apache/lucene/index/TestFieldsReader.java (working copy)
@@ -23,6 +23,7 @@
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 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);
Index: src/test/org/apache/lucene/index/TestIndexReader.java
===================================================================
--- src/test/org/apache/lucene/index/TestIndexReader.java (revision 513819)
+++ src/test/org/apache/lucene/index/TestIndexReader.java (working copy)
@@ -26,6 +26,7 @@
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;
@@ -273,21 +274,21 @@
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
}
}
Index: src/test/org/apache/lucene/index/TestIndexWriter.java
===================================================================
--- src/test/org/apache/lucene/index/TestIndexWriter.java (revision 513819)
+++ src/test/org/apache/lucene/index/TestIndexWriter.java (working copy)
@@ -19,6 +19,7 @@
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;
@@ -653,6 +654,25 @@
}
}
+ 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:
@@ -722,7 +742,6 @@
IndexSearcher searcher = new IndexSearcher(dir);
Hits hits = searcher.search(new TermQuery(searchTerm));
assertEquals("did not get right number of hits", 100, hits.length());
- writer.close();
writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true);
writer.close();
Index: src/java/org/apache/lucene/index/MultiReader.java
===================================================================
--- src/java/org/apache/lucene/index/MultiReader.java (revision 513819)
+++ src/java/org/apache/lucene/index/MultiReader.java (working copy)
@@ -20,6 +20,7 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.document.FieldSelector;
import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.AlreadyClosedException;
import java.io.IOException;
import java.util.Collection;
@@ -72,24 +73,21 @@
}
- /** 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 {
+ public TermFreqVector[] getTermFreqVectors(int n) throws IOException, AlreadyClosedException {
+ 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 {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
int i = readerIndex(n); // find segment num
return subReaders[i].getTermFreqVector(n - starts[i], field);
}
- public synchronized int numDocs() {
+ public synchronized int numDocs() throws AlreadyClosedException {
+ ensureOpen();
if (numDocs == -1) { // check cache
int n = 0; // cache miss--recompute
for (int i = 0; i < subReaders.length; i++)
@@ -99,22 +97,28 @@
return numDocs;
}
- public int maxDoc() {
+ public int maxDoc() throws AlreadyClosedException {
+ ensureOpen();
return maxDoc;
}
// inherit javadoc
- public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+ public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException, AlreadyClosedException {
+ 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) {
+ public boolean isDeleted(int n) throws AlreadyClosedException {
+ ensureOpen();
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() throws AlreadyClosedException {
+ ensureOpen();
+ return hasDeletions;
+ }
protected void doDelete(int n) throws CorruptIndexException, IOException {
numDocs = -1; // invalidate cache
@@ -152,7 +156,8 @@
return hi;
}
- public boolean hasNorms(String field) throws IOException {
+ public boolean hasNorms(String field) throws IOException, AlreadyClosedException {
+ ensureOpen();
for (int i = 0; i < subReaders.length; i++) {
if (subReaders[i].hasNorms(field)) return true;
}
@@ -165,7 +170,8 @@
return ones;
}
- public synchronized byte[] norms(String field) throws IOException {
+ public synchronized byte[] norms(String field) throws IOException, AlreadyClosedException {
+ ensureOpen();
byte[] bytes = (byte[])normsCache.get(field);
if (bytes != null)
return bytes; // cache hit
@@ -180,7 +186,8 @@
}
public synchronized void norms(String field, byte[] result, int offset)
- throws IOException {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
byte[] bytes = (byte[])normsCache.get(field);
if (bytes==null && !hasNorms(field)) bytes=fakeNorms();
if (bytes != null) // cache hit
@@ -197,26 +204,31 @@
subReaders[i].setNorm(n-starts[i], field, value); // dispatch
}
- public TermEnum terms() throws IOException {
+ public TermEnum terms() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new MultiTermEnum(subReaders, starts, null);
}
- public TermEnum terms(Term term) throws IOException {
+ public TermEnum terms(Term term) throws IOException, AlreadyClosedException {
+ ensureOpen();
return new MultiTermEnum(subReaders, starts, term);
}
- public int docFreq(Term t) throws IOException {
+ public int docFreq(Term t) throws IOException, AlreadyClosedException {
+ ensureOpen();
int total = 0; // sum freqs in segments
for (int i = 0; i < subReaders.length; i++)
total += subReaders[i].docFreq(t);
return total;
}
- public TermDocs termDocs() throws IOException {
+ public TermDocs termDocs() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new MultiTermDocs(subReaders, starts);
}
- public TermPositions termPositions() throws IOException {
+ public TermPositions termPositions() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new MultiTermPositions(subReaders, starts);
}
@@ -251,11 +263,9 @@
subReaders[i].close();
}
- /**
- * @see IndexReader#getFieldNames(IndexReader.FieldOption)
- */
- public Collection getFieldNames (IndexReader.FieldOption fieldNames) {
+ public Collection getFieldNames (IndexReader.FieldOption fieldNames) throws AlreadyClosedException {
// maintain a unique set of field names
+ ensureOpen();
Set fieldSet = new HashSet();
for (int i = 0; i < subReaders.length; i++) {
IndexReader reader = subReaders[i];
Index: src/java/org/apache/lucene/index/FieldsReader.java
===================================================================
--- src/java/org/apache/lucene/index/FieldsReader.java (revision 513819)
+++ src/java/org/apache/lucene/index/FieldsReader.java (working copy)
@@ -20,6 +20,7 @@
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 @@
private final IndexInput indexStream;
private int size;
+ private boolean closed;
private ThreadLocal fieldsStreamTL = new ThreadLocal();
@@ -59,19 +61,31 @@
}
/**
+ * @throws AlreadyClosedException if this FieldsReader is closed
+ */
+ protected 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.
*
* @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;
}
}
@@ -321,8 +335,10 @@
* The value of the field in Binary, or null. If null, the Reader or
* String value is used. Exactly one of stringValue(), readerValue() and
* binaryValue() must be set.
+ * @throws AlreadyClosedException if this FieldsReader is closed
*/
- public byte[] binaryValue() {
+ public byte[] binaryValue() throws AlreadyClosedException {
+ ensureOpen();
if (fieldsData == null) {
final byte[] b = new byte[toRead];
IndexInput localFieldsStream = getFieldStream();
@@ -347,8 +363,10 @@
* The value of the field as a Reader, or null. If null, the String value
* or binary value is used. Exactly one of stringValue(), readerValue(),
* and binaryValue() must be set.
+ * @throws AlreadyClosedException if this FieldsReader is closed
*/
- public Reader readerValue() {
+ public Reader readerValue() throws AlreadyClosedException {
+ ensureOpen();
return fieldsData instanceof Reader ? (Reader) fieldsData : null;
}
@@ -356,8 +374,10 @@
* The value of the field as a String, or null. If null, the Reader value
* or binary value is used. Exactly one of stringValue(), readerValue(), and
* binaryValue() must be set.
+ * @throws AlreadyClosedException if this FieldsReader is closed
*/
- public String stringValue() {
+ public String stringValue() throws AlreadyClosedException {
+ ensureOpen();
if (fieldsData == null) {
IndexInput localFieldsStream = getFieldStream();
try {
@@ -379,19 +399,35 @@
return fieldsData instanceof String ? (String) fieldsData : null;
}
- public long getPointer() {
+ /**
+ * @throws AlreadyClosedException if this FieldsReader is closed
+ */
+ public long getPointer() throws AlreadyClosedException {
+ ensureOpen();
return pointer;
}
- public void setPointer(long pointer) {
+ /**
+ * @throws AlreadyClosedException if this FieldsReader is closed
+ */
+ public void setPointer(long pointer) throws AlreadyClosedException {
+ ensureOpen();
this.pointer = pointer;
}
- public int getToRead() {
+ /**
+ * @throws AlreadyClosedException if this FieldsReader is closed
+ */
+ public int getToRead() throws AlreadyClosedException {
+ ensureOpen();
return toRead;
}
- public void setToRead(int toRead) {
+ /**
+ * @throws AlreadyClosedException if this FieldsReader is closed
+ */
+ public void setToRead(int toRead) throws AlreadyClosedException {
+ ensureOpen();
this.toRead = toRead;
}
}
Index: src/java/org/apache/lucene/index/IndexReader.java
===================================================================
--- src/java/org/apache/lucene/index/IndexReader.java (revision 513819)
+++ src/java/org/apache/lucene/index/IndexReader.java (working copy)
@@ -25,6 +25,7 @@
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,8 +116,17 @@
private boolean directoryOwner;
private boolean closeDirectory;
protected IndexFileDeleter deleter;
- private boolean isClosed;
+ private boolean closed;
+ /**
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ protected void ensureOpen() throws AlreadyClosedException {
+ if (closed) {
+ throw new AlreadyClosedException("this IndexReader is closed");
+ }
+ }
+
private SegmentInfos segmentInfos;
private Lock writeLock;
private boolean stale;
@@ -190,8 +200,13 @@
}.run();
}
- /** Returns the directory this index resides in. */
- public Directory directory() { return directory; }
+ /** Returns the directory this index resides in.
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public Directory directory() throws AlreadyClosedException {
+ ensureOpen();
+ return directory;
+ }
/**
* Returns the time the index in the named directory was last modified.
@@ -281,8 +296,10 @@
/**
* Version number when this IndexReader was opened.
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public long getVersion() {
+ public long getVersion() throws AlreadyClosedException {
+ ensureOpen();
return segmentInfos.getVersion();
}
@@ -293,17 +310,21 @@
*
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public boolean isCurrent() throws CorruptIndexException, IOException {
+ public boolean isCurrent() throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion();
}
/**
* Checks is the index is optimized (if it has a single segment and no deletions)
* @return <code>true</code> if the index is optimized; <code>false</code> otherwise
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public boolean isOptimized() {
- return segmentInfos.size() == 1 && hasDeletions() == false;
+ public boolean isOptimized() throws AlreadyClosedException {
+ ensureOpen();
+ return segmentInfos.size() == 1 && hasDeletions() == false;
}
/**
@@ -318,10 +339,11 @@
* @return array of term frequency vectors. May be null if no term vectors have been
* stored for the specified document.
* @throws IOException if index cannot be accessed
+ * @throws AlreadyClosedException if this IndexReader is closed
* @see org.apache.lucene.document.Field.TermVector
*/
abstract public TermFreqVector[] getTermFreqVectors(int docNumber)
- throws IOException;
+ throws IOException, AlreadyClosedException;
/**
@@ -336,10 +358,11 @@
* @return term frequency vector May be null if field does not exist in the specified
* document or term vector was not stored.
* @throws IOException if index cannot be accessed
+ * @throws AlreadyClosedException if this IndexReader is closed
* @see org.apache.lucene.document.Field.TermVector
*/
abstract public TermFreqVector getTermFreqVector(int docNumber, String field)
- throws IOException;
+ throws IOException, AlreadyClosedException;
/**
* Returns <code>true</code> if an index exists at the specified directory.
@@ -374,21 +397,26 @@
return SegmentInfos.getCurrentSegmentGeneration(directory) != -1;
}
- /** Returns the number of documents in this index. */
- public abstract int numDocs();
+ /** Returns the number of documents in this index.
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public abstract int numDocs() throws AlreadyClosedException;
/** 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.
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public abstract int maxDoc();
+ public abstract int maxDoc() throws AlreadyClosedException;
/** Returns the stored fields of the <code>n</code><sup>th</sup>
<code>Document</code> in this index.
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public Document document(int n) throws CorruptIndexException, IOException {
+ public Document document(int n) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
return document(n, null);
}
@@ -411,22 +439,30 @@
* @see org.apache.lucene.document.FieldSelector
* @see org.apache.lucene.document.SetBasedFieldSelector
* @see org.apache.lucene.document.LoadFirstFieldSelector
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
//When we convert to JDK 1.5 make this Set<String>
- public abstract Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException;
+ public abstract Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException, AlreadyClosedException;
- /** Returns true if document <i>n</i> has been deleted */
- public abstract boolean isDeleted(int n);
+ /** Returns true if document <i>n</i> has been deleted
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public abstract boolean isDeleted(int n) throws AlreadyClosedException;
- /** Returns true if any documents have been deleted */
- public abstract boolean hasDeletions();
+ /** Returns true if any documents have been deleted
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public abstract boolean hasDeletions() throws AlreadyClosedException;
- /** Returns true if there are norms stored for this field. */
- public boolean hasNorms(String field) throws IOException {
+ /** Returns true if there are norms stored for this field.
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public boolean hasNorms(String field) throws IOException, AlreadyClosedException {
// backward compatible implementation.
// SegmentReader has an efficient implementation.
+ ensureOpen();
return norms(field) != null;
}
@@ -434,16 +470,18 @@
* every document. This is used by the search code to score documents.
*
* @see org.apache.lucene.document.Field#setBoost(float)
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public abstract byte[] norms(String field) throws IOException;
+ public abstract byte[] norms(String field) throws IOException, AlreadyClosedException;
/** Reads the byte-encoded normalization factor for the named field of every
* document. This is used by the search code to score documents.
*
* @see org.apache.lucene.document.Field#setBoost(float)
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
public abstract void norms(String field, byte[] bytes, int offset)
- throws IOException;
+ throws IOException, AlreadyClosedException;
/** Expert: Resets the normalization factor for the named field of the named
* document. The norm represents the product of the field's {@link
@@ -459,11 +497,12 @@
* @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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
public final synchronized void setNorm(int doc, String field, byte value)
- throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
+ throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException, AlreadyClosedException {
+ ensureOpen();
if(directoryOwner)
acquireWriteLock();
hasChanges = true;
@@ -486,28 +525,36 @@
* @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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
public void setNorm(int doc, String field, float value)
- throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
+ throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException, AlreadyClosedException {
+ 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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public abstract TermEnum terms() throws IOException;
+ public abstract TermEnum terms() throws IOException, AlreadyClosedException;
/** 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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public abstract TermEnum terms(Term t) throws IOException;
+ public abstract TermEnum terms(Term t) throws IOException, AlreadyClosedException;
- /** Returns the number of documents containing the term <code>t</code>. */
- public abstract int docFreq(Term t) throws IOException;
+ /** Returns the number of documents containing the term <code>t</code>.
+ * @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public abstract int docFreq(Term t) throws IOException, AlreadyClosedException;
/** Returns an enumeration of all the documents which contain
* <code>term</code>. For each document, the document number, the frequency of
@@ -518,15 +565,21 @@
* </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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public TermDocs termDocs(Term term) throws IOException {
+ public TermDocs termDocs(Term term) throws IOException, AlreadyClosedException {
+ ensureOpen();
TermDocs termDocs = termDocs();
termDocs.seek(term);
return termDocs;
}
- /** Returns an unpositioned {@link TermDocs} enumerator. */
- public abstract TermDocs termDocs() throws IOException;
+ /** Returns an unpositioned {@link TermDocs} enumerator.
+ * @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public abstract TermDocs termDocs() throws IOException, AlreadyClosedException;
/** Returns an enumeration of all the documents which contain
* <code>term</code>. For each document, in addition to the document number
@@ -543,15 +596,21 @@
* <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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public TermPositions termPositions(Term term) throws IOException {
+ public TermPositions termPositions(Term term) throws IOException, AlreadyClosedException {
+ ensureOpen();
TermPositions termPositions = termPositions();
termPositions.seek(term);
return termPositions;
}
- /** Returns an unpositioned {@link TermPositions} enumerator. */
- public abstract TermPositions termPositions() throws IOException;
+ /** Returns an unpositioned {@link TermPositions} enumerator.
+ * @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public abstract TermPositions termPositions() throws IOException, AlreadyClosedException;
/**
* Tries to acquire the WriteLock on this directory.
@@ -564,12 +623,12 @@
* has this index open (<code>write.lock</code> could not
* be obtained)
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- private void acquireWriteLock() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
+ private void acquireWriteLock() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException, AlreadyClosedException {
+ 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);
@@ -602,10 +661,11 @@
* @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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public final synchronized void deleteDocument(int docNum) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
+ public final synchronized void deleteDocument(int docNum) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException, AlreadyClosedException {
+ ensureOpen();
if(directoryOwner)
acquireWriteLock();
hasChanges = true;
@@ -634,10 +694,11 @@
* @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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public final int deleteDocuments(Term term) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
+ public final int deleteDocuments(Term term) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException, AlreadyClosedException {
+ ensureOpen();
TermDocs docs = termDocs(term);
if (docs == null) return 0;
int n = 0;
@@ -660,10 +721,11 @@
* 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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public final synchronized void undeleteAll() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
+ public final synchronized void undeleteAll() throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException, AlreadyClosedException {
+ ensureOpen();
if(directoryOwner)
acquireWriteLock();
hasChanges = true;
@@ -793,20 +855,18 @@
* 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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
public final synchronized void close() throws IOException {
- if (directoryOwner && isClosed) {
- throw new IOException("this reader is already closed");
+ if (!closed) {
+ commit();
+ doClose();
+ if (directoryOwner)
+ closed = true;
+ if(closeDirectory)
+ directory.close();
}
- commit();
- doClose();
- if(closeDirectory)
- directory.close();
- if (directoryOwner) {
- isClosed = true;
- }
}
/** Implements close. */
@@ -831,8 +891,9 @@
* @param fldOption specifies which field option should be available for the returned fields
* @return Collection of Strings indicating the names of the fields.
* @see IndexReader.FieldOption
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
- public abstract Collection getFieldNames(FieldOption fldOption);
+ public abstract Collection getFieldNames(FieldOption fldOption) throws AlreadyClosedException;
/**
* Returns <code>true</code> iff the index in the named directory is
Index: src/java/org/apache/lucene/index/FilterIndexReader.java
===================================================================
--- src/java/org/apache/lucene/index/FilterIndexReader.java (revision 513819)
+++ src/java/org/apache/lucene/index/FilterIndexReader.java (working copy)
@@ -19,6 +19,7 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.store.AlreadyClosedException;
import java.io.IOException;
@@ -91,44 +92,85 @@
}
public TermFreqVector[] getTermFreqVectors(int docNumber)
- throws IOException {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
return in.getTermFreqVectors(docNumber);
}
public TermFreqVector getTermFreqVector(int docNumber, String field)
- throws IOException {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
return in.getTermFreqVector(docNumber, field);
}
- public int numDocs() { return in.numDocs(); }
- public int maxDoc() { return in.maxDoc(); }
+ public int numDocs() throws AlreadyClosedException {
+ ensureOpen();
+ return in.numDocs();
+ }
- public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { return in.document(n, fieldSelector); }
+ public int maxDoc() throws AlreadyClosedException {
+ ensureOpen();
+ return in.maxDoc();
+ }
- public boolean isDeleted(int n) { return in.isDeleted(n); }
- public boolean hasDeletions() { return in.hasDeletions(); }
+ public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
+ return in.document(n, fieldSelector);
+ }
+
+ public boolean isDeleted(int n) throws AlreadyClosedException {
+ ensureOpen();
+ return in.isDeleted(n);
+ }
+
+ public boolean hasDeletions() throws AlreadyClosedException {
+ ensureOpen();
+ return in.hasDeletions();
+ }
+
protected void doUndeleteAll() throws CorruptIndexException, IOException {in.undeleteAll();}
- public boolean hasNorms(String field) throws IOException {
+ public boolean hasNorms(String field) throws IOException, AlreadyClosedException {
+ ensureOpen();
return in.hasNorms(field);
}
- public byte[] norms(String f) throws IOException { return in.norms(f); }
- public void norms(String f, byte[] bytes, int offset) throws IOException {
+ public byte[] norms(String f) throws IOException, AlreadyClosedException {
+ ensureOpen();
+ return in.norms(f);
+ }
+
+ public void norms(String f, byte[] bytes, int offset) throws IOException, AlreadyClosedException {
+ 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, AlreadyClosedException {
+ ensureOpen();
+ return in.terms();
+ }
- public int docFreq(Term t) throws IOException { return in.docFreq(t); }
+ public TermEnum terms(Term t) throws IOException, AlreadyClosedException {
+ ensureOpen();
+ return in.terms(t);
+ }
- public TermDocs termDocs() throws IOException { return in.termDocs(); }
+ public int docFreq(Term t) throws IOException, AlreadyClosedException {
+ ensureOpen();
+ return in.docFreq(t);
+ }
- public TermPositions termPositions() throws IOException {
+ public TermDocs termDocs() throws IOException, AlreadyClosedException {
+ ensureOpen();
+ return in.termDocs();
+ }
+
+ public TermPositions termPositions() throws IOException, AlreadyClosedException {
+ ensureOpen();
return in.termPositions();
}
@@ -137,10 +179,18 @@
protected void doClose() throws IOException { in.close(); }
- public Collection getFieldNames(IndexReader.FieldOption fieldNames) {
+ public Collection getFieldNames(IndexReader.FieldOption fieldNames) throws AlreadyClosedException {
+ ensureOpen();
return in.getFieldNames(fieldNames);
}
- public long getVersion() { return in.getVersion(); }
- public boolean isCurrent() throws CorruptIndexException, IOException { return in.isCurrent(); }
+ public long getVersion() throws AlreadyClosedException {
+ ensureOpen();
+ return in.getVersion();
+ }
+
+ public boolean isCurrent() throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
+ return in.isCurrent();
+ }
}
Index: src/java/org/apache/lucene/index/IndexWriter.java
===================================================================
--- src/java/org/apache/lucene/index/IndexWriter.java (revision 513819)
+++ src/java/org/apache/lucene/index/IndexWriter.java (working copy)
@@ -24,6 +24,7 @@
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;
@@ -151,37 +152,55 @@
private boolean useCompoundFile = true;
private boolean closeDir;
+ private boolean closed;
+ /**
+ * @throws AlreadyClosedException if this IndexWriter is closed
+ */
+ protected 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)
* or the default. You cannot use this to query the status of an existing index.
* @see #setUseCompoundFile(boolean)
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public boolean getUseCompoundFile() {
+ public boolean getUseCompoundFile() throws AlreadyClosedException {
+ ensureOpen();
return useCompoundFile;
}
/** Setting to turn on usage of a compound file. When on, multiple files
* for each segment are merged into a single file once the segment creation
* is finished. This is done regardless of what directory is in use.
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setUseCompoundFile(boolean value) {
+ public void setUseCompoundFile(boolean value) throws AlreadyClosedException {
+ ensureOpen();
useCompoundFile = value;
}
/** Expert: Set the Similarity implementation used by this IndexWriter.
*
* @see Similarity#setDefault(Similarity)
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setSimilarity(Similarity similarity) {
+ public void setSimilarity(Similarity similarity) throws AlreadyClosedException {
+ ensureOpen();
this.similarity = similarity;
}
/** Expert: Return the Similarity implementation used by this IndexWriter.
*
* <p>This defaults to the current value of {@link Similarity#getDefault()}.
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public Similarity getSimilarity() {
+ public Similarity getSimilarity() throws AlreadyClosedException {
+ ensureOpen();
return this.similarity;
}
@@ -205,16 +224,22 @@
* must be scanned for each random term access.
*
* @see #DEFAULT_TERM_INDEX_INTERVAL
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setTermIndexInterval(int interval) {
+ public void setTermIndexInterval(int interval) throws AlreadyClosedException {
+ ensureOpen();
this.termIndexInterval = interval;
}
/** Expert: Return the interval between indexed terms.
*
* @see #setTermIndexInterval(int)
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public int getTermIndexInterval() { return termIndexInterval; }
+ public int getTermIndexInterval() throws AlreadyClosedException {
+ ensureOpen();
+ return termIndexInterval;
+ }
/**
* Constructs an IndexWriter for the index in <code>path</code>.
@@ -430,15 +455,19 @@
* Larger values are best for batched indexing and speedier searches.
*
* <p>The default value is {@link Integer#MAX_VALUE}.
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setMaxMergeDocs(int maxMergeDocs) {
+ public void setMaxMergeDocs(int maxMergeDocs) throws AlreadyClosedException {
+ ensureOpen();
this.maxMergeDocs = maxMergeDocs;
}
/**
* @see #setMaxMergeDocs
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public int getMaxMergeDocs() {
+ public int getMaxMergeDocs() throws AlreadyClosedException {
+ ensureOpen();
return maxMergeDocs;
}
@@ -453,15 +482,19 @@
* the expected size. If you set it to Integer.MAX_VALUE, then the only limit
* is your memory, but you should anticipate an OutOfMemoryError.<p/>
* By default, no more than 10,000 terms will be indexed for a field.
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setMaxFieldLength(int maxFieldLength) {
+ public void setMaxFieldLength(int maxFieldLength) throws AlreadyClosedException {
+ ensureOpen();
this.maxFieldLength = maxFieldLength;
}
/**
* @see #setMaxFieldLength
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public int getMaxFieldLength() {
+ public int getMaxFieldLength() throws AlreadyClosedException {
+ ensureOpen();
return maxFieldLength;
}
@@ -474,8 +507,10 @@
* <p> The default value is 10.
*
* @throws IllegalArgumentException if maxBufferedDocs is smaller than 2
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setMaxBufferedDocs(int maxBufferedDocs) {
+ public void setMaxBufferedDocs(int maxBufferedDocs) throws AlreadyClosedException {
+ ensureOpen();
if (maxBufferedDocs < 2)
throw new IllegalArgumentException("maxBufferedDocs must at least be 2");
this.minMergeDocs = maxBufferedDocs;
@@ -483,8 +518,10 @@
/**
* @see #setMaxBufferedDocs
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public int getMaxBufferedDocs() {
+ public int getMaxBufferedDocs() throws AlreadyClosedException {
+ ensureOpen();
return minMergeDocs;
}
@@ -496,8 +533,10 @@
* <p>The default value is {@link #DEFAULT_MAX_BUFFERED_DELETE_TERMS}.
* @throws IllegalArgumentException if maxBufferedDeleteTerms is smaller than 1</p>
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setMaxBufferedDeleteTerms(int maxBufferedDeleteTerms) {
+ public void setMaxBufferedDeleteTerms(int maxBufferedDeleteTerms) throws AlreadyClosedException {
+ ensureOpen();
if (maxBufferedDeleteTerms < 1)
throw new IllegalArgumentException("maxBufferedDeleteTerms must at least be 1");
this.maxBufferedDeleteTerms = maxBufferedDeleteTerms;
@@ -505,8 +544,10 @@
/**
* @see #setMaxBufferedDeleteTerms
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public int getMaxBufferedDeleteTerms() {
+ public int getMaxBufferedDeleteTerms() throws AlreadyClosedException {
+ ensureOpen();
return maxBufferedDeleteTerms;
}
@@ -519,8 +560,10 @@
* interactively maintained.
*
* <p>This must never be less than 2. The default value is 10.
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setMergeFactor(int mergeFactor) {
+ public void setMergeFactor(int mergeFactor) throws AlreadyClosedException {
+ ensureOpen();
if (mergeFactor < 2)
throw new IllegalArgumentException("mergeFactor cannot be less than 2");
this.mergeFactor = mergeFactor;
@@ -528,37 +571,47 @@
/**
* @see #setMergeFactor
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public int getMergeFactor() {
+ public int getMergeFactor() throws AlreadyClosedException {
+ ensureOpen();
return mergeFactor;
}
/** If non-null, information about merges and a message when
* maxFieldLength is reached will be printed to this.
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setInfoStream(PrintStream infoStream) {
+ public void setInfoStream(PrintStream infoStream) throws AlreadyClosedException {
+ ensureOpen();
this.infoStream = infoStream;
}
/**
* @see #setInfoStream
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public PrintStream getInfoStream() {
+ public PrintStream getInfoStream() throws AlreadyClosedException {
+ ensureOpen();
return infoStream;
}
/**
* Sets the maximum time to wait for a write lock (in milliseconds) for this instance of IndexWriter. @see
* @see #setDefaultWriteLockTimeout to change the default value for all instances of IndexWriter.
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void setWriteLockTimeout(long writeLockTimeout) {
+ public void setWriteLockTimeout(long writeLockTimeout) throws AlreadyClosedException {
+ ensureOpen();
this.writeLockTimeout = writeLockTimeout;
}
/**
* @see #setWriteLockTimeout
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public long getWriteLockTimeout() {
+ public long getWriteLockTimeout() throws AlreadyClosedException {
+ ensureOpen();
return writeLockTimeout;
}
@@ -612,14 +665,17 @@
* @throws IOException if there is a low-level IO error
*/
public synchronized void close() throws CorruptIndexException, IOException {
- flushRamSegments();
- ramDirectory.close();
- if (writeLock != null) {
- writeLock.release(); // release write lock
- writeLock = null;
+ if (!closed) {
+ flushRamSegments();
+ ramDirectory.close();
+ closed = true;
+ if (writeLock != null) {
+ writeLock.release(); // release write lock
+ writeLock = null;
+ }
+ if(closeDir)
+ directory.close();
}
- if(closeDir)
- directory.close();
}
/** Release the write lock, if needed. */
@@ -634,19 +690,32 @@
}
}
- /** Returns the Directory used by this index. */
- public Directory getDirectory() {
- return directory;
+ /**
+ * Returns the Directory used by this index.
+ * @throws AlreadyClosedException if this IndexWriter is closed
+ */
+ public Directory getDirectory() throws AlreadyClosedException {
+ ensureOpen();
+ return directory;
}
- /** Returns the analyzer used by this index. */
- public Analyzer getAnalyzer() {
- return analyzer;
+ /**
+ * Returns the analyzer used by this index.
+ * @throws AlreadyClosedException if this IndexWriter is closed
+ */
+ public Analyzer getAnalyzer() throws AlreadyClosedException {
+ ensureOpen();
+ return analyzer;
}
- /** Returns the number of documents currently in this index. */
- public synchronized int docCount() {
+ /**
+ * Returns the number of documents currently in this
+ * index.
+ * @throws AlreadyClosedException if this IndexWriter is closed
+ */
+ public synchronized int docCount() throws AlreadyClosedException {
+ ensureOpen();
int count = ramSegmentInfos.size();
for (int i = 0; i < segmentInfos.size(); i++) {
SegmentInfo si = segmentInfos.info(i);
@@ -722,8 +791,10 @@
*
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void addDocument(Document doc, Analyzer analyzer) throws CorruptIndexException, IOException {
+ public void addDocument(Document doc, Analyzer analyzer) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
SegmentInfo newSegmentInfo = buildSingleDocSegment(doc, analyzer);
synchronized (this) {
ramSegmentInfos.addElement(newSegmentInfo);
@@ -745,8 +816,10 @@
* @param term the term to identify the documents to be deleted
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public synchronized void deleteDocuments(Term term) throws CorruptIndexException, IOException {
+ public synchronized void deleteDocuments(Term term) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
bufferDeleteTerm(term);
maybeFlushRamSegments();
}
@@ -758,8 +831,10 @@
* to be deleted
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public synchronized void deleteDocuments(Term[] terms) throws CorruptIndexException, IOException {
+ public synchronized void deleteDocuments(Term[] terms) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
for (int i = 0; i < terms.length; i++) {
bufferDeleteTerm(terms[i]);
}
@@ -777,8 +852,10 @@
* @param doc the document to be added
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public void updateDocument(Term term, Document doc) throws CorruptIndexException, IOException {
+ public void updateDocument(Term term, Document doc) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
updateDocument(term, doc, getAnalyzer());
}
@@ -794,9 +871,11 @@
* @param analyzer the analyzer to use when analyzing the document
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
public void updateDocument(Term term, Document doc, Analyzer analyzer)
- throws CorruptIndexException, IOException {
+ throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
SegmentInfo newSegmentInfo = buildSingleDocSegment(doc, analyzer);
synchronized (this) {
bufferDeleteTerm(term);
@@ -929,8 +1008,10 @@
* compound format.</p>
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public synchronized void optimize() throws CorruptIndexException, IOException {
+ public synchronized void optimize() throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
flushRamSegments();
while (segmentInfos.size() > 1 ||
(segmentInfos.size() == 1 &&
@@ -1068,10 +1149,12 @@
* for details.</p>
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
public synchronized void addIndexes(Directory[] dirs)
- throws CorruptIndexException, IOException {
+ throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
optimize(); // start with zero or 1 seg
int start = segmentInfos.size();
@@ -1126,9 +1209,10 @@
* on an Exception.</p>
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
public synchronized void addIndexesNoOptimize(Directory[] dirs)
- throws CorruptIndexException, IOException {
+ throws CorruptIndexException, IOException, AlreadyClosedException {
// Adding indexes can be viewed as adding a sequence of segments S to
// a sequence of segments T. Segments in T follow the invariants but
// segments in S may not since they could come from multiple indexes.
@@ -1157,6 +1241,7 @@
// 1 flush ram segments
+ ensureOpen();
flushRamSegments();
// 2 copy segment infos and find the highest level from dirs
@@ -1264,10 +1349,12 @@
* on an Exception.</p>
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
public synchronized void addIndexes(IndexReader[] readers)
- throws CorruptIndexException, IOException {
+ throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
optimize(); // start with zero or 1 seg
final String mergedName = newSegmentName();
@@ -1407,22 +1494,28 @@
* to the Directory.
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public final synchronized void flush() throws CorruptIndexException, IOException {
+ public final synchronized void flush() throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
flushRamSegments();
}
/** Expert: Return the total size of all index files currently cached in memory.
* Useful for size management with flushRamDocs()
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public final long ramSizeInBytes() {
+ public final long ramSizeInBytes() throws AlreadyClosedException {
+ ensureOpen();
return ramDirectory.sizeInBytes();
}
/** Expert: Return the number of documents whose segments are currently cached in memory.
* Useful when calling flushRamSegments()
+ * @throws AlreadyClosedException if this IndexWriter is closed
*/
- public final synchronized int numRamDocs() {
+ public final synchronized int numRamDocs() throws AlreadyClosedException {
+ ensureOpen();
return ramSegmentInfos.size();
}
Index: src/java/org/apache/lucene/index/ParallelReader.java
===================================================================
--- src/java/org/apache/lucene/index/ParallelReader.java (revision 513819)
+++ src/java/org/apache/lucene/index/ParallelReader.java (working copy)
@@ -21,6 +21,7 @@
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.document.FieldSelector;
import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.store.AlreadyClosedException;
import java.io.IOException;
import java.util.SortedMap;
@@ -66,8 +67,12 @@
/** Construct a ParallelReader. */
public ParallelReader() throws IOException { super(null); }
- /** Add an IndexReader. */
- public void add(IndexReader reader) throws IOException {
+ /** Add an IndexReader.
+ * @throws IOException if there is a low-level IO error
+ * @throws AlreadyClosedException if this IndexReader is closed
+ */
+ public void add(IndexReader reader) throws IOException, AlreadyClosedException {
+ ensureOpen();
add(reader, false);
}
@@ -79,10 +84,13 @@
* 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
+ * @throws AlreadyClosedException if this IndexReader is closed
*/
public void add(IndexReader reader, boolean ignoreStoredFields)
- throws IOException {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
if (readers.size() == 0) {
this.maxDoc = reader.maxDoc();
this.numDocs = reader.numDocs();
@@ -110,14 +118,24 @@
readers.add(reader);
}
- public int numDocs() { return numDocs; }
+ public int numDocs() throws AlreadyClosedException {
+ ensureOpen();
+ return numDocs;
+ }
- public int maxDoc() { return maxDoc; }
+ public int maxDoc() throws AlreadyClosedException {
+ ensureOpen();
+ return maxDoc;
+ }
- public boolean hasDeletions() { return hasDeletions; }
+ public boolean hasDeletions() throws AlreadyClosedException {
+ ensureOpen();
+ return hasDeletions;
+ }
// check first reader
- public boolean isDeleted(int n) {
+ public boolean isDeleted(int n) throws AlreadyClosedException {
+ ensureOpen();
if (readers.size() > 0)
return ((IndexReader)readers.get(0)).isDeleted(n);
return false;
@@ -140,7 +158,8 @@
}
// append fields from storedFieldReaders
- public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+ public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
Document result = new Document();
for (int i = 0; i < storedFieldReaders.size(); i++) {
IndexReader reader = (IndexReader)storedFieldReaders.get(i);
@@ -165,7 +184,8 @@
}
// get all vectors
- public TermFreqVector[] getTermFreqVectors(int n) throws IOException {
+ public TermFreqVector[] getTermFreqVectors(int n) throws IOException, AlreadyClosedException {
+ ensureOpen();
ArrayList results = new ArrayList();
Iterator i = fieldToReader.entrySet().iterator();
while (i.hasNext()) {
@@ -181,23 +201,27 @@
}
public TermFreqVector getTermFreqVector(int n, String field)
- throws IOException {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
IndexReader reader = ((IndexReader)fieldToReader.get(field));
return reader==null ? null : reader.getTermFreqVector(n, field);
}
- public boolean hasNorms(String field) throws IOException {
+ public boolean hasNorms(String field) throws IOException, AlreadyClosedException {
+ ensureOpen();
IndexReader reader = ((IndexReader)fieldToReader.get(field));
return reader==null ? false : reader.hasNorms(field);
}
- public byte[] norms(String field) throws IOException {
+ public byte[] norms(String field) throws IOException, AlreadyClosedException {
+ 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 {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
IndexReader reader = ((IndexReader)fieldToReader.get(field));
if (reader!=null)
reader.norms(field, result, offset);
@@ -210,32 +234,39 @@
reader.doSetNorm(n, field, value);
}
- public TermEnum terms() throws IOException {
+ public TermEnum terms() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new ParallelTermEnum();
}
- public TermEnum terms(Term term) throws IOException {
+ public TermEnum terms(Term term) throws IOException, AlreadyClosedException {
+ ensureOpen();
return new ParallelTermEnum(term);
}
- public int docFreq(Term term) throws IOException {
+ public int docFreq(Term term) throws IOException, AlreadyClosedException {
+ ensureOpen();
IndexReader reader = ((IndexReader)fieldToReader.get(term.field()));
return reader==null ? 0 : reader.docFreq(term);
}
- public TermDocs termDocs(Term term) throws IOException {
+ public TermDocs termDocs(Term term) throws IOException, AlreadyClosedException {
+ ensureOpen();
return new ParallelTermDocs(term);
}
- public TermDocs termDocs() throws IOException {
+ public TermDocs termDocs() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new ParallelTermDocs();
}
- public TermPositions termPositions(Term term) throws IOException {
+ public TermPositions termPositions(Term term) throws IOException, AlreadyClosedException {
+ ensureOpen();
return new ParallelTermPositions(term);
}
- public TermPositions termPositions() throws IOException {
+ public TermPositions termPositions() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new ParallelTermPositions();
}
@@ -250,7 +281,8 @@
}
- public Collection getFieldNames (IndexReader.FieldOption fieldNames) {
+ public Collection getFieldNames (IndexReader.FieldOption fieldNames) throws AlreadyClosedException {
+ ensureOpen();
Set fieldSet = new HashSet();
for (int i = 0; i < readers.size(); i++) {
IndexReader reader = ((IndexReader)readers.get(i));
Index: src/java/org/apache/lucene/index/SegmentReader.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentReader.java (revision 513819)
+++ src/java/org/apache/lucene/index/SegmentReader.java (working copy)
@@ -23,6 +23,7 @@
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
+import org.apache.lucene.store.AlreadyClosedException;
import org.apache.lucene.util.BitVector;
import java.io.IOException;
@@ -279,7 +280,8 @@
return si.hasDeletions();
}
- public boolean hasDeletions() {
+ public boolean hasDeletions() throws AlreadyClosedException {
+ ensureOpen();
return deletedDocs != null;
}
@@ -339,11 +341,13 @@
return files;
}
- public TermEnum terms() {
+ public TermEnum terms() throws AlreadyClosedException {
+ ensureOpen();
return tis.terms();
}
- public TermEnum terms(Term t) throws IOException {
+ public TermEnum terms(Term t) throws IOException, AlreadyClosedException {
+ ensureOpen();
return tis.terms(t);
}
@@ -351,26 +355,31 @@
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
*/
- public synchronized Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+ public synchronized Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException, AlreadyClosedException {
+ ensureOpen();
if (isDeleted(n))
throw new IllegalArgumentException
("attempt to access a deleted document");
return fieldsReader.doc(n, fieldSelector);
}
- public synchronized boolean isDeleted(int n) {
+ public synchronized boolean isDeleted(int n) throws AlreadyClosedException {
+ ensureOpen();
return (deletedDocs != null && deletedDocs.get(n));
}
- public TermDocs termDocs() throws IOException {
+ public TermDocs termDocs() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new SegmentTermDocs(this);
}
- public TermPositions termPositions() throws IOException {
+ public TermPositions termPositions() throws IOException, AlreadyClosedException {
+ ensureOpen();
return new SegmentTermPositions(this);
}
- public int docFreq(Term t) throws IOException {
+ public int docFreq(Term t) throws IOException, AlreadyClosedException {
+ ensureOpen();
TermInfo ti = tis.get(t);
if (ti != null)
return ti.docFreq;
@@ -378,21 +387,24 @@
return 0;
}
- public int numDocs() {
+ public int numDocs() throws AlreadyClosedException {
+ ensureOpen();
int n = maxDoc();
if (deletedDocs != null)
n -= deletedDocs.count();
return n;
}
- public int maxDoc() {
+ public int maxDoc() throws AlreadyClosedException {
+ ensureOpen();
return si.docCount;
}
/**
* @see IndexReader#getFieldNames(IndexReader.FieldOption fldOption)
*/
- public Collection getFieldNames(IndexReader.FieldOption fieldOption) {
+ public Collection getFieldNames(IndexReader.FieldOption fieldOption) throws AlreadyClosedException {
+ ensureOpen();
Set fieldSet = new HashSet();
for (int i = 0; i < fieldInfos.size(); i++) {
@@ -433,7 +445,8 @@
}
- public synchronized boolean hasNorms(String field) {
+ public synchronized boolean hasNorms(String field) throws AlreadyClosedException {
+ ensureOpen();
return norms.containsKey(field);
}
@@ -462,7 +475,8 @@
}
// returns fake norms if norms aren't available
- public synchronized byte[] norms(String field) throws IOException {
+ public synchronized byte[] norms(String field) throws IOException, AlreadyClosedException {
+ ensureOpen();
byte[] bytes = getNorms(field);
if (bytes==null) bytes=fakeNorms();
return bytes;
@@ -481,8 +495,9 @@
/** Read norms into a pre-allocated array. */
public synchronized void norms(String field, byte[] bytes, int offset)
- throws IOException {
+ throws IOException, AlreadyClosedException {
+ ensureOpen();
Norm norm = (Norm) norms.get(field);
if (norm == null) {
System.arraycopy(fakeNorms(), 0, bytes, offset, maxDoc());
@@ -551,8 +566,9 @@
* flag set. If the flag was not set, the method returns null.
* @throws IOException
*/
- public TermFreqVector getTermFreqVector(int docNumber, String field) throws IOException {
+ public TermFreqVector getTermFreqVector(int docNumber, String field) throws IOException, AlreadyClosedException {
// 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;
@@ -572,7 +588,8 @@
* If no such fields existed, the method returns null.
* @throws IOException
*/
- public TermFreqVector[] getTermFreqVectors(int docNumber) throws IOException {
+ public TermFreqVector[] getTermFreqVectors(int docNumber) throws IOException, AlreadyClosedException {
+ ensureOpen();
if (termVectorsReaderOrig == null)
return null;
Index: src/java/org/apache/lucene/store/AlreadyClosedException.java
===================================================================
--- src/java/org/apache/lucene/store/AlreadyClosedException.java (revision 0)
+++ src/java/org/apache/lucene/store/AlreadyClosedException.java (revision 0)
@@ -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);
+ }
+}
Property changes on: src/java/org/apache/lucene/store/AlreadyClosedException.java
___________________________________________________________________
Name: svn:eol-style
+ native