boolean success = false;
int start;
try {
SegmentInfos sourceSegmentsClone = merge.segmentsClone;
SegmentInfos sourceSegments = merge.segments;
start = ensureContiguousMerge(merge);
if (infoStream != null)
message("commitMerge " + merge.segString(directory));
// Carefully merge deletes that occurred after we
// started merging:
BitVector deletes = null;
int docUpto = 0;
final int numSegmentsToMerge = sourceSegments.size();
for(int i=0;i<numSegmentsToMerge;i++) {
final SegmentInfo previousInfo = sourceSegmentsClone.info(i);
final SegmentInfo currentInfo = sourceSegments.info(i);
assert currentInfo.docCount == previousInfo.docCount;
final int docCount = currentInfo.docCount;
if (previousInfo.hasDeletions()) {
// There were deletes on this segment when the merge
// started. The merge has collapsed away those
// deletes, but, if new deletes were flushed since
// the merge started, we must now carefully keep any
// newly flushed deletes but mapping them to the new
// docIDs.
assert currentInfo.hasDeletions();
// Load deletes present @ start of merge, for this segment:
BitVector previousDeletes = new BitVector(previousInfo.dir, previousInfo.getDelFileName());
if (!currentInfo.getDelFileName().equals(previousInfo.getDelFileName())) {
// This means this segment has had new deletes
// committed since we started the merge, so we
// must merge them:
if (deletes == null)
deletes = new BitVector(merge.info.docCount);
BitVector currentDeletes = new BitVector(currentInfo.dir, currentInfo.getDelFileName());
for(int j=0;j<docCount;j++) {
if (previousDeletes.get(j))
assert currentDeletes.get(j);
else {
if (currentDeletes.get(j))
deletes.set(docUpto);
docUpto++;
}
}
} else
docUpto += docCount - previousDeletes.count();
} else if (currentInfo.hasDeletions()) {
// This segment had no deletes before but now it
// does:
if (deletes == null)
deletes = new BitVector(merge.info.docCount);
BitVector currentDeletes = new BitVector(directory, currentInfo.getDelFileName());
for(int j=0;j<docCount;j++) {
if (currentDeletes.get(j))
deletes.set(docUpto);
docUpto++;
}
} else
// No deletes before or after
docUpto += currentInfo.docCount;
merge.checkAborted(directory);
}
if (deletes != null) {
merge.info.advanceDelGen();
deletes.write(directory, merge.info.getDelFileName());
}
success = true;
} finally {
if (!success) {
if (infoStream != null)
message("hit exception creating merged deletes file");
deleter.refresh(merge.info.name);
}
}
// Simple optimization: if the doc store we are using
// has been closed and is in now compound format (but
// wasn't when we started), then we will switch to the
// compound format as well:
final String mergeDocStoreSegment = merge.info.getDocStoreSegment();
if (mergeDocStoreSegment != null && !merge.info.getDocStoreIsCompoundFile()) {
final int size = segmentInfos.size();
for(int i=0;i<size;i++) {
final SegmentInfo info = segmentInfos.info(i);
final String docStoreSegment = info.getDocStoreSegment();
if (docStoreSegment != null &&
docStoreSegment.equals(mergeDocStoreSegment) &&
info.getDocStoreIsCompoundFile()) {
merge.info.setDocStoreIsCompoundFile(true);
break;
}
}
}
success = false;
SegmentInfos rollback = null;
try {
rollback = (SegmentInfos) segmentInfos.clone();
segmentInfos.subList(start, start + merge.segments.size()).clear();
segmentInfos.add(start, merge.info);
checkpoint();