Code with Finding: |
class IndexWriter {
private synchronized void setRollbackSegmentInfos(SegmentInfos infos) {
rollbackSegmentInfos = (SegmentInfos) infos.clone();
assert !rollbackSegmentInfos.hasExternalSegments(directory);
rollbackSegments = new HashMap();
final int size = rollbackSegmentInfos.size();
for(int i=0;i<size;i++)
rollbackSegments.put(rollbackSegmentInfos.info(i), new Integer(i));
}
}
class IndexWriter {
/** Just like {@link #optimize(int)}, except you can
* specify whether the call should block until the
* optimize completes. This is only meaningful with a
* {@link MergeScheduler} that is able to run merges in
* background threads.
*
* <p><b>NOTE</b>: if this method hits an OutOfMemoryError
* you should immediately close the writer. See <a
* href="#OOME">above</a> for details.</p>
*/
public void optimize(int maxNumSegments, boolean doWait) throws CorruptIndexException, IOException {
ensureOpen();
if (maxNumSegments < 1)
throw new IllegalArgumentException("maxNumSegments must be >= 1; got " + maxNumSegments);
if (infoStream != null)
message("optimize: index now " + segString());
flush(true, false, true);
synchronized(this) {
resetMergeExceptions();
segmentsToOptimize = new HashSet();
final int numSegments = segmentInfos.size();
for(int i=0;i<numSegments;i++)
segmentsToOptimize.add(segmentInfos.info(i));
// Now mark all pending & running merges as optimize
// merge:
Iterator it = pendingMerges.iterator();
while(it.hasNext()) {
final MergePolicy.OneMerge merge = (MergePolicy.OneMerge) it.next();
merge.optimize = true;
merge.maxNumSegmentsOptimize = maxNumSegments;
}
it = runningMerges.iterator();
while(it.hasNext()) {
final MergePolicy.OneMerge merge = (MergePolicy.OneMerge) it.next();
merge.optimize = true;
merge.maxNumSegmentsOptimize = maxNumSegments;
}
}
maybeMerge(maxNumSegments, true);
if (doWait) {
synchronized(this) {
while(true) {
if (hitOOM) {
throw new IllegalStateException("this writer hit an OutOfMemoryError; cannot complete optimize");
}
if (mergeExceptions.size() > 0) {
// Forward any exceptions in background merge
// threads to the current thread:
final int size = mergeExceptions.size();
for(int i=0;i<size;i++) {
final MergePolicy.OneMerge merge = (MergePolicy.OneMerge) mergeExceptions.get(0);
if (merge.optimize) {
IOException err = new IOException("background merge hit exception: " + merge.segString(directory));
final Throwable t = merge.getException();
if (t != null)
err.initCause(t);
throw err;
}
}
}
if (optimizeMergesPending())
doWait();
else
break;
}
}
// If close is called while we are still
// running, throw an exception so the calling
// thread will know the optimize did not
// complete
ensureOpen();
}
// NOTE: in the ConcurrentMergeScheduler case, when
// doWait is false, we can return immediately while
// background threads accomplish the optimization
}
}
class IndexWriter {
// Apply buffered deletes to all segments.
private final synchronized boolean applyDeletes() throws CorruptIndexException, IOException {
assert testPoint("startApplyDeletes");
SegmentInfos rollback = (SegmentInfos) segmentInfos.clone();
boolean success = false;
boolean changed;
try {
changed = docWriter.applyDeletes(segmentInfos);
success = true;
} finally {
if (!success) {
if (infoStream != null)
message("hit exception flushing deletes");
// Carefully remove any partially written .del
// files
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);
}
}
if (changed)
checkpoint();
return changed;
}
}
|