Index: lucene/core/src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java (revision 1364784) +++ lucene/core/src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java (working copy) @@ -243,27 +243,34 @@ sync(); } - /** Wait for any running merge threads to finish */ + /** Wait for any running merge threads to finish. This call is not interruptible as used by {@link #close()}. */ public void sync() { - while (true) { - MergeThread toSync = null; - synchronized (this) { - for (MergeThread t : mergeThreads) { - if (t.isAlive()) { - toSync = t; - break; + boolean interrupted = Thread.interrupted(); + try { + while (true) { + MergeThread toSync = null; + synchronized (this) { + for (MergeThread t : mergeThreads) { + if (t.isAlive()) { + toSync = t; + break; + } } } - } - if (toSync != null) { - try { - toSync.join(); - } catch (InterruptedException ie) { - throw new ThreadInterruptedException(ie); + if (toSync != null) { + try { + toSync.join(); + } catch (InterruptedException ie) { + // ignore this Exception, we will retry until all threads are dead + interrupted = true; + } + } else { + break; } - } else { - break; } + } finally { + // finally, restore original interrupt status: + if (interrupted) Thread.currentThread().interrupt(); } } Index: lucene/core/src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (revision 1364784) +++ lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -842,7 +842,7 @@ if (hitOOM) { rollbackInternal(); } else { - closeInternal(waitForMerges, !hitOOM); + closeInternal(waitForMerges, true); } } } @@ -870,7 +870,7 @@ } private void closeInternal(boolean waitForMerges, boolean doFlush) throws IOException { - + boolean interrupted = Thread.interrupted(); try { if (pendingCommit != null) { @@ -891,17 +891,35 @@ docWriter.abort(); // already closed } - if (waitForMerges) - // Give merge scheduler last chance to run, in case - // any pending merges are waiting: - mergeScheduler.merge(this); - + if (waitForMerges) { + try { + // Give merge scheduler last chance to run, in case + // any pending merges are waiting: + mergeScheduler.merge(this); + } catch (ThreadInterruptedException tie) { + // ignore any interruption, does not matter + interrupted = true; + } + } + mergePolicy.close(); synchronized(this) { - finishMerges(waitForMerges); + for (;;) { + try { + finishMerges(waitForMerges && !interrupted); + break; + } catch (ThreadInterruptedException tie) { + // by setting the interrupted status, the + // next call to finishMerges will pass false, + // so it will not wait + interrupted = true; + } + } stopMerges = true; } + + // shutdown scheduler and all threads (this call is not interruptible): mergeScheduler.close(); if (infoStream.isEnabled("IW")) { @@ -943,6 +961,8 @@ } } } + // finally, restore original interrupt status: + if (interrupted) Thread.currentThread().interrupt(); } } Index: lucene/core/src/java/org/apache/lucene/index/MergeScheduler.java =================================================================== --- lucene/core/src/java/org/apache/lucene/index/MergeScheduler.java (revision 1364784) +++ lucene/core/src/java/org/apache/lucene/index/MergeScheduler.java (working copy) @@ -17,6 +17,7 @@ * limitations under the License. */ +import java.io.Closeable; import java.io.IOException; /**
Expert: {@link IndexWriter} uses an instance @@ -26,7 +27,7 @@ * * @lucene.experimental */ -public abstract class MergeScheduler { +public abstract class MergeScheduler implements Closeable { /** Run the merges provided by {@link IndexWriter#getNextMerge()}. */ public abstract void merge(IndexWriter writer) throws IOException;