return false;
}
try {
SegmentInfo newSegment = null;
final int numDocs = docWriter.getNumDocsInRAM();
// Always flush docs if there are any
boolean flushDocs = numDocs > 0;
// With autoCommit=true we always must flush the doc
// stores when we flush
flushDocStores |= autoCommit;
String docStoreSegment = docWriter.getDocStoreSegment();
if (docStoreSegment == null)
flushDocStores = false;
// Always flush deletes if there are any delete terms.
// TODO: when autoCommit=false we don't have to flush
// deletes with every flushed segment; we can save
// CPU/IO by buffering longer & flushing deletes only
// when they are full or writer is being closed. We
// have to fix the "applyDeletesSelectively" logic to
// apply to more than just the last flushed segment
boolean flushDeletes = docWriter.hasDeletes();
if (infoStream != null) {
message(" flush: segment=" + docWriter.getSegment() +
" docStoreSegment=" + docWriter.getDocStoreSegment() +
" docStoreOffset=" + docWriter.getDocStoreOffset() +
" flushDocs=" + flushDocs +
" flushDeletes=" + flushDeletes +
" flushDocStores=" + flushDocStores +
" numDocs=" + numDocs +
" numBufDelTerms=" + docWriter.getNumBufferedDeleteTerms());
message(" index before flush " + segString());
}
int docStoreOffset = docWriter.getDocStoreOffset();
// docStoreOffset should only be non-zero when
// autoCommit == false
assert !autoCommit || 0 == docStoreOffset;
boolean docStoreIsCompoundFile = false;
// Check if the doc stores must be separately flushed
// because other segments, besides the one we are about
// to flush, reference it
if (flushDocStores && (!flushDocs || !docWriter.getSegment().equals(docWriter.getDocStoreSegment()))) {
// We must separately flush the doc store
if (infoStream != null)
message(" flush shared docStore segment " + docStoreSegment);
docStoreIsCompoundFile = flushDocStores();
flushDocStores = false;
}
String segment = docWriter.getSegment();
// If we are flushing docs, segment must not be null:
assert segment != null || !flushDocs;
if (flushDocs || flushDeletes) {
SegmentInfos rollback = null;
if (flushDeletes)
rollback = (SegmentInfos) segmentInfos.clone();
boolean success = false;
try {
if (flushDocs) {
if (0 == docStoreOffset && flushDocStores) {
// This means we are flushing private doc stores
// with this segment, so it will not be shared
// with other segments
assert docStoreSegment != null;
assert docStoreSegment.equals(segment);
docStoreOffset = -1;
docStoreIsCompoundFile = false;
docStoreSegment = null;
}
int flushedDocCount = docWriter.flush(flushDocStores);
newSegment = new SegmentInfo(segment,
flushedDocCount,
directory, false, true,
docStoreOffset, docStoreSegment,
docStoreIsCompoundFile);
segmentInfos.addElement(newSegment);
}
if (flushDeletes) {
// we should be able to change this so we can
// buffer deletes longer and then flush them to
// multiple flushed segments, when
// autoCommit=false
applyDeletes(flushDocs);
doAfterFlush();
}
checkpoint();
success = true;
} finally {
if (!success) {
if (infoStream != null)
message("hit exception flushing segment " + segment);
if (flushDeletes) {
// Carefully check if any partial .del files
// should be removed:
final int size = rollback.size();
for(int i=0;i<size;i++) {
final String newDelFileName = segmentInfos.info(i).getDelFileName();
final String delFileName = rollback.info(i).getDelFileName();
if (newDelFileName != null && !newDelFileName.equals(delFileName))
deleter.deleteFile(newDelFileName);
}
// Fully replace the segmentInfos since flushed
// deletes could have changed any of the
// SegmentInfo instances:
segmentInfos.clear();
segmentInfos.addAll(rollback);
} else {
// Remove segment we added, if any:
if (newSegment != null &&
segmentInfos.size() > 0 &&
segmentInfos.info(segmentInfos.size()-1) == newSegment)
segmentInfos.remove(segmentInfos.size()-1);
}
if (flushDocs)
docWriter.abort(null);
deletePartialSegmentsFile();
deleter.checkpoint(segmentInfos, false);
if (segment != null)
deleter.refresh(segment);
}
}
deleter.checkpoint(segmentInfos, autoCommit);
if (flushDocs && mergePolicy.useCompoundFile(segmentInfos,
newSegment)) {
success = false;
try {
docWriter.createCompoundFile(segment);
newSegment.setUseCompoundFile(true);
checkpoint();
success = true;
} finally {
if (!success) {
if (infoStream != null)
message("hit exception creating compound file for newly flushed segment " + segment);
newSegment.setUseCompoundFile(false);
deleter.deleteFile(segment + "." + IndexFileNames.COMPOUND_FILE_EXTENSION);
deletePartialSegmentsFile();
}
}