LUCENE-962: fixed case where unhandled exception in addDocument or updateDocument could fail to delete unreferenced files in the index

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@557082 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael McCandless 2007-07-17 23:22:56 +00:00
parent 52b5113a04
commit aae68e0ba6
3 changed files with 91 additions and 4 deletions

View File

@ -35,6 +35,11 @@ Bug fixes
IndexWriter's methods could cause deletes to be lost. IndexWriter's methods could cause deletes to be lost.
(Steven Parkes via Mike McCandless) (Steven Parkes via Mike McCandless)
4. LUCENE-962: Fixed case where an unhandled exception in
IndexWriter.addDocument or IndexWriter.updateDocument could cause
unreferenced files in the index to not be deleted
(Steven Parkes via Mike McCandless)
New features New features
1. LUCENE-906: Elision filter for French. 1. LUCENE-906: Elision filter for French.

View File

@ -1112,7 +1112,14 @@ public class IndexWriter {
*/ */
public void addDocument(Document doc, Analyzer analyzer) throws CorruptIndexException, IOException { public void addDocument(Document doc, Analyzer analyzer) throws CorruptIndexException, IOException {
ensureOpen(); ensureOpen();
if (docWriter.addDocument(doc, analyzer)) boolean success = false;
try {
success = docWriter.addDocument(doc, analyzer);
} catch (IOException ioe) {
deleter.refresh();
throw ioe;
}
if (success)
flush(true, false); flush(true, false);
} }
@ -1180,7 +1187,14 @@ public class IndexWriter {
synchronized (this) { synchronized (this) {
bufferDeleteTerm(term); bufferDeleteTerm(term);
} }
if (docWriter.addDocument(doc, analyzer)) boolean success = false;
try {
success = docWriter.addDocument(doc, analyzer);
} catch (IOException ioe) {
deleter.refresh();
throw ioe;
}
if (success)
flush(true, false); flush(true, false);
else else
maybeFlush(); maybeFlush();

View File

@ -576,8 +576,7 @@ public class TestIndexWriterDelete extends TestCase {
for(int pass=0;pass<2;pass++) { for(int pass=0;pass<2;pass++) {
boolean autoCommit = (0==pass); boolean autoCommit = (0==pass);
Directory ramDir = new RAMDirectory(); MockRAMDirectory dir = new MockRAMDirectory();
MockRAMDirectory dir = new MockRAMDirectory(ramDir);
IndexWriter modifier = new IndexWriter(dir, autoCommit, IndexWriter modifier = new IndexWriter(dir, autoCommit,
new WhitespaceAnalyzer(), true); new WhitespaceAnalyzer(), true);
modifier.setUseCompoundFile(true); modifier.setUseCompoundFile(true);
@ -675,6 +674,75 @@ public class TestIndexWriterDelete extends TestCase {
} }
} }
// This test tests that the files created by the docs writer before
// a segment is written are cleaned up if there's an i/o error
public void testErrorInDocsWriterAdd() throws IOException {
MockRAMDirectory.Failure failure = new MockRAMDirectory.Failure() {
boolean failed = false;
public MockRAMDirectory.Failure reset() {
failed = false;
return this;
}
public void eval(MockRAMDirectory dir) throws IOException {
if (!failed) {
throw new IOException("fail in add doc");
}
}
};
// create a couple of files
String[] keywords = { "1", "2" };
String[] unindexed = { "Netherlands", "Italy" };
String[] unstored = { "Amsterdam has lots of bridges",
"Venice has lots of canals" };
String[] text = { "Amsterdam", "Venice" };
for(int pass=0;pass<2;pass++) {
boolean autoCommit = (0==pass);
MockRAMDirectory dir = new MockRAMDirectory();
IndexWriter modifier = new IndexWriter(dir, autoCommit,
new WhitespaceAnalyzer(), true);
dir.failOn(failure.reset());
for (int i = 0; i < keywords.length; i++) {
Document doc = new Document();
doc.add(new Field("id", keywords[i], Field.Store.YES,
Field.Index.UN_TOKENIZED));
doc.add(new Field("country", unindexed[i], Field.Store.YES,
Field.Index.NO));
doc.add(new Field("contents", unstored[i], Field.Store.NO,
Field.Index.TOKENIZED));
doc.add(new Field("city", text[i], Field.Store.YES,
Field.Index.TOKENIZED));
try {
modifier.addDocument(doc);
} catch (IOException io) {
break;
}
}
String[] startFiles = dir.list();
SegmentInfos infos = new SegmentInfos();
infos.read(dir);
IndexFileDeleter d = new IndexFileDeleter(dir, new KeepOnlyLastCommitDeletionPolicy(), infos, null, null);
String[] endFiles = dir.list();
if (!Arrays.equals(startFiles, endFiles)) {
fail("docswriter abort() failed to delete unreferenced files:\n before delete:\n "
+ arrayToString(startFiles) + "\n after delete:\n "
+ arrayToString(endFiles));
}
modifier.close();
}
}
private String arrayToString(String[] l) { private String arrayToString(String[] l) {
String s = ""; String s = "";
for (int i = 0; i < l.length; i++) { for (int i = 0; i < l.length; i++) {