LUCENE-9405: Ensure IndexWriter only closes merge readers once. (#1580)

IndexWriter incorrectly calls closeMergeReaders twice when the
merged segment is 100% deleted ie. would produce a fully deleted
segment.
This commit is contained in:
Simon Willnauer 2020-06-15 22:02:15 +02:00 committed by GitHub
parent fabc704748
commit 47cffbcdd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 0 deletions

View File

@ -266,6 +266,9 @@ Bug Fixes
* LUCENE-9362: Fix equality check in ExpressionValueSource#rewrite. This fixes rewriting of inner value sources.
(Dmitry Emets)
* LUCENE-9405: IndexWriter incorrectly calls closeMergeReaders twice when the merged segment is 100% deleted.
(Michael Froh, Simon Willnauer, Mike Mccandless, Mike Sokolov)
Other
---------------------

View File

@ -4483,6 +4483,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit, Accountable,
// Merge would produce a 0-doc segment, so we do nothing except commit the merge to remove all the 0-doc segments that we "merged":
assert merge.info.info.maxDoc() == 0;
commitMerge(merge, mergeState);
success = true;
return 0;
}

View File

@ -4167,4 +4167,38 @@ public class TestIndexWriter extends LuceneTestCase {
}
}
}
public void testMergeZeroDocsMergeIsClosedOnce() throws IOException {
LogDocMergePolicy keepAllSegments = new LogDocMergePolicy() {
@Override
public boolean keepFullyDeletedSegment(IOSupplier<CodecReader> readerIOSupplier) {
return true;
}
};
try (Directory dir = newDirectory()) {
try (IndexWriter writer = new IndexWriter(dir,
new IndexWriterConfig().setMergePolicy(new OneMergeWrappingMergePolicy(keepAllSegments, merge -> {
SetOnce<Boolean> onlyFinishOnce = new SetOnce<>();
return new MergePolicy.OneMerge(merge.segments) {
@Override
public void mergeFinished() {
onlyFinishOnce.set(true);
}
};
})))) {
Document doc = new Document();
doc.add(new StringField("id", "1", Field.Store.NO));
writer.addDocument(doc);
writer.flush();
writer.addDocument(doc);
writer.flush();
writer.deleteDocuments(new Term("id", "1"));
writer.flush();
assertEquals(2, writer.getSegmentCount());
assertEquals(0, writer.getDocStats().numDocs);
assertEquals(2, writer.getDocStats().maxDoc);
writer.forceMerge(1);
}
}
}
}