LUCENE-1918: fix corner cases (resulting in exceptions) when passing ParallelReader to IndexWriter.addIndexes

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@816602 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael McCandless 2009-09-18 12:33:51 +00:00
parent 7c757a03c1
commit 0cb96adf12
4 changed files with 156 additions and 6 deletions

View File

@ -559,6 +559,13 @@ Bug fixes
OpenBitSet, due to an inefficiency in how the underlying storage is
reallocated. (Nadav Har'El via Mike McCandless)
* LUCENE-1918: Fixed cases where a ParallelReader would
generate exceptions on being passed to
IndexWriter.addIndexes(IndexReader[]). First case was when the
ParallelReader was empty. Second case was when the ParallelReader
used to contain documents with TermVectors, but all such documents
have been deleted. (Christian Kohlschütter via Mike McCandless)
New features
* LUCENE-1411: Added expert API to open an IndexWriter on a prior

View File

@ -472,7 +472,12 @@ public class ParallelReader extends IndexReader {
private TermEnum termEnum;
public ParallelTermEnum() throws IOException {
field = (String)fieldToReader.firstKey();
try {
field = (String)fieldToReader.firstKey();
} catch(NoSuchElementException e) {
// No fields, so keep field == null, termEnum == null
return;
}
if (field != null)
termEnum = ((IndexReader)fieldToReader.get(field)).terms();
}

View File

@ -156,11 +156,13 @@ final class TermVectorsWriter {
}
// 2nd pass: write field pointers to tvd
long lastFieldPointer = fieldPointers[0];
for (int i=1; i<numFields; i++) {
final long fieldPointer = fieldPointers[i];
tvd.writeVLong(fieldPointer-lastFieldPointer);
lastFieldPointer = fieldPointer;
if (numFields > 1) {
long lastFieldPointer = fieldPointers[0];
for (int i=1; i<numFields; i++) {
final long fieldPointer = fieldPointers[i];
tvd.writeVLong(fieldPointer-lastFieldPointer);
lastFieldPointer = fieldPointer;
}
}
} else
tvd.writeVInt(0);

View File

@ -0,0 +1,136 @@
package org.apache.lucene.index;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util._TestUtil;
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.Field.TermVector;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.store.MockRAMDirectory;
import org.apache.lucene.store.RAMDirectory;
/**
* Some tests for {@link ParallelReader}s with empty indexes
*
* @author Christian Kohlschuetter
*/
public class TestParallelReaderEmptyIndex extends LuceneTestCase {
/**
* Creates two empty indexes and wraps a ParallelReader around. Adding this
* reader to a new index should not throw any exception.
*
* @throws IOException
*/
public void testEmptyIndex() throws IOException {
RAMDirectory rd1 = new MockRAMDirectory();
IndexWriter iw = new IndexWriter(rd1, new SimpleAnalyzer(), true,
MaxFieldLength.UNLIMITED);
iw.close();
RAMDirectory rd2 = new MockRAMDirectory(rd1);
RAMDirectory rdOut = new MockRAMDirectory();
IndexWriter iwOut = new IndexWriter(rdOut, new SimpleAnalyzer(), true,
MaxFieldLength.UNLIMITED);
ParallelReader pr = new ParallelReader();
pr.add(IndexReader.open(rd1,true));
pr.add(IndexReader.open(rd2,true));
// When unpatched, Lucene crashes here with a NoSuchElementException (caused by ParallelTermEnum)
iwOut.addIndexes(new IndexReader[] { pr });
iwOut.optimize();
iwOut.close();
_TestUtil.checkIndex(rdOut);
rdOut.close();
rd1.close();
rd2.close();
}
/**
* This method creates an empty index (numFields=0, numDocs=0) but is marked
* to have TermVectors. Adding this index to another index should not throw
* any exception.
*/
public void testEmptyIndexWithVectors() throws IOException {
RAMDirectory rd1 = new MockRAMDirectory();
{
IndexWriter iw = new IndexWriter(rd1, new SimpleAnalyzer(), true,
MaxFieldLength.UNLIMITED);
Document doc = new Document();
doc.add(new Field("test", "", Store.NO, Index.ANALYZED,
TermVector.YES));
iw.addDocument(doc);
doc.add(new Field("test", "", Store.NO, Index.ANALYZED,
TermVector.NO));
iw.addDocument(doc);
iw.close();
IndexReader ir = IndexReader.open(rd1,false);
ir.deleteDocument(0);
ir.close();
iw = new IndexWriter(rd1, new SimpleAnalyzer(), false,
MaxFieldLength.UNLIMITED);
iw.optimize();
iw.close();
}
RAMDirectory rd2 = new MockRAMDirectory();
{
IndexWriter iw = new IndexWriter(rd2, new SimpleAnalyzer(), true,
MaxFieldLength.UNLIMITED);
Document doc = new Document();
iw.addDocument(doc);
iw.close();
}
RAMDirectory rdOut = new MockRAMDirectory();
IndexWriter iwOut = new IndexWriter(rdOut, new SimpleAnalyzer(), true,
MaxFieldLength.UNLIMITED);
ParallelReader pr = new ParallelReader();
pr.add(IndexReader.open(rd1,true));
pr.add(IndexReader.open(rd2,true));
// When unpatched, Lucene crashes here with an ArrayIndexOutOfBoundsException (caused by TermVectorsWriter)
iwOut.addIndexes(new IndexReader[] { pr });
// ParallelReader closes any IndexReader you added to it:
pr.close();
rd1.close();
rd2.close();
iwOut.optimize();
iwOut.close();
_TestUtil.checkIndex(rdOut);
rdOut.close();
}
}