Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 758608) +++ CHANGES.txt (working copy) @@ -101,6 +101,12 @@ 7. LUCENE-1327: Fix TermSpans#skipTo() to behave as specified in javadocs of Terms#skipTo(). (Michael Busch) +8. LUCENE-1573: Do not ignore InterruptedException (caused by + Thread.interrupt()) nor enter deadlock/spin loop. Now, an interrupt + will cause a RuntimeException to be thrown. In 3.0 we will change + public APIs to throw InterruptedException. (Jeremy Volkman vai + Mike McCandless) + New features 1. LUCENE-1411: Added expert API to open an IndexWriter on a prior Index: src/test/org/apache/lucene/TestSnapshotDeletionPolicy.java =================================================================== --- src/test/org/apache/lucene/TestSnapshotDeletionPolicy.java (revision 758608) +++ src/test/org/apache/lucene/TestSnapshotDeletionPolicy.java (working copy) @@ -49,7 +49,7 @@ { public static final String INDEX_PATH = "test.snapshots"; - public void testSnapshotDeletionPolicy() throws IOException { + public void testSnapshotDeletionPolicy() throws Exception { File dir = new File(System.getProperty("tempDir"), INDEX_PATH); try { Directory fsDir = FSDirectory.getDirectory(dir); @@ -63,7 +63,7 @@ runTest(dir2); } - public void testReuseAcrossWriters() throws IOException { + public void testReuseAcrossWriters() throws Exception { Directory dir = new MockRAMDirectory(); SnapshotDeletionPolicy dp = new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy()); @@ -98,7 +98,7 @@ dir.close(); } - private void runTest(Directory dir) throws IOException { + private void runTest(Directory dir) throws Exception { // Run for ~7 seconds final long stopTime = System.currentTimeMillis() + 7000; @@ -125,6 +125,7 @@ Thread.sleep(1); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } @@ -136,20 +137,12 @@ // backups: while(System.currentTimeMillis() < stopTime) { backupIndex(dir, dp); - try { - Thread.sleep(20); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } + Thread.sleep(20); if (!t.isAlive()) break; } - try { - t.join(); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } + t.join(); // Add one more document to force writer to commit a // final segment, so deletion policy has a chance to @@ -169,7 +162,7 @@ * backup; instead, it reads every byte of every file * just to test that the files indeed exist and are * readable even while the index is changing. */ - public void backupIndex(Directory dir, SnapshotDeletionPolicy dp) throws IOException { + public void backupIndex(Directory dir, SnapshotDeletionPolicy dp) throws Exception { // To backup an index we first take a snapshot: try { copyFiles(dir, (IndexCommit) dp.snapshot()); @@ -181,7 +174,7 @@ } } - private void copyFiles(Directory dir, IndexCommit cp) throws IOException { + private void copyFiles(Directory dir, IndexCommit cp) throws Exception { // While we hold the snapshot, and nomatter how long // we take to do the backup, the IndexWriter will @@ -202,7 +195,7 @@ byte[] buffer = new byte[4096]; - private void readFile(Directory dir, String name) throws IOException { + private void readFile(Directory dir, String name) throws Exception { IndexInput input = dir.openInput(name); try { long size = dir.fileLength(name); @@ -221,11 +214,7 @@ // make sure we are exercising the fact that the // IndexWriter should not delete this file even when I // take my time reading it. - try { - Thread.sleep(1); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } + Thread.sleep(1); } finally { input.close(); } Index: src/test/org/apache/lucene/store/TestLockFactory.java =================================================================== --- src/test/org/apache/lucene/store/TestLockFactory.java (revision 758608) +++ src/test/org/apache/lucene/store/TestLockFactory.java (working copy) @@ -326,7 +326,7 @@ // Verify: do stress test, by opening IndexReaders and // IndexWriters over & over in 2 threads and making sure // no unexpected exceptions are raised: - public void testStressLocks() throws IOException { + public void testStressLocks() throws Exception { _testStressLocks(null, "index.TestLockFactory6"); } @@ -334,11 +334,11 @@ // IndexWriters over & over in 2 threads and making sure // no unexpected exceptions are raised, but use // NativeFSLockFactory: - public void testStressLocksNativeFSLockFactory() throws IOException { + public void testStressLocksNativeFSLockFactory() throws Exception { _testStressLocks(new NativeFSLockFactory("index.TestLockFactory7"), "index.TestLockFactory7"); } - public void _testStressLocks(LockFactory lockFactory, String indexDirName) throws IOException { + public void _testStressLocks(LockFactory lockFactory, String indexDirName) throws Exception { FSDirectory fs1 = FSDirectory.getDirectory(indexDirName, lockFactory); // First create a 1 doc index: @@ -353,10 +353,7 @@ searcher.start(); while(writer.isAlive() || searcher.isAlive()) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } + Thread.sleep(1000); } assertTrue("IndexWriter hit unexpected exceptions", !writer.hitException); Index: src/test/org/apache/lucene/search/TestTimeLimitedCollector.java =================================================================== --- src/test/org/apache/lucene/search/TestTimeLimitedCollector.java (revision 758608) +++ src/test/org/apache/lucene/search/TestTimeLimitedCollector.java (working copy) @@ -248,18 +248,18 @@ /** * Test correctness with multiple searching threads. */ - public void testSearchMultiThreaded() { + public void testSearchMultiThreaded() throws Exception { doTestMultiThreads(false); } /** * Test correctness with multiple searching threads. */ - public void testTimeoutMultiThreaded() { + public void testTimeoutMultiThreaded() throws Exception { doTestMultiThreads(true); } - private void doTestMultiThreads(final boolean withTimeout) { + private void doTestMultiThreads(final boolean withTimeout) throws Exception { Thread [] threadArray = new Thread[N_THREADS]; final BitSet success = new BitSet(N_THREADS); for( int i = 0; i < threadArray.length; ++i ) { @@ -280,17 +280,9 @@ for( int i = 0; i < threadArray.length; ++i ) { threadArray[i].start(); } - boolean interrupted = false; for( int i = 0; i < threadArray.length; ++i ) { - try { - threadArray[i].join(); - } catch (InterruptedException e) { - interrupted = true; - } + threadArray[i].join(); } - if (interrupted) { - Thread.currentThread().interrupt(); - } assertEquals("some threads failed!", N_THREADS,success.cardinality()); } @@ -314,10 +306,10 @@ if( slowdown > 0 ) { try { Thread.sleep(slowdown); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } - catch(InterruptedException x) { - System.out.println("caught " + x); - } } assert docId >= 0: " base=" + docBase + " doc=" + doc; bits.set( docId ); Index: src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java =================================================================== --- src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java (revision 758608) +++ src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java (working copy) @@ -57,7 +57,7 @@ } - public void test() { + public void test() throws Exception { IndexReader reader = null; @@ -83,7 +83,7 @@ } } - public void testTermPositionVectors(final IndexReader reader, int threadCount) { + public void testTermPositionVectors(final IndexReader reader, int threadCount) throws Exception { MultiThreadTermVectorsReader[] mtr = new MultiThreadTermVectorsReader[threadCount]; for (int i = 0; i < threadCount; i++) { mtr[i] = new MultiThreadTermVectorsReader(); @@ -94,7 +94,6 @@ /** run until all threads finished */ int threadsAlive = mtr.length; while (threadsAlive > 0) { - try { //System.out.println("Threads alive"); Thread.sleep(10); threadsAlive = mtr.length; @@ -104,10 +103,7 @@ } threadsAlive--; - - } - - } catch (InterruptedException ie) {} + } } long totalTime = 0L; Index: src/test/org/apache/lucene/index/TestIndexReader.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexReader.java (revision 758608) +++ src/test/org/apache/lucene/index/TestIndexReader.java (working copy) @@ -750,7 +750,7 @@ _TestUtil.rmDir(dirFile); } - public void testLastModified() throws IOException { + public void testLastModified() throws Exception { assertFalse(IndexReader.indexExists("there_is_no_such_index")); final File fileDir = new File(System.getProperty("tempDir"), "testIndex"); for(int i=0;i<2;i++) { @@ -776,14 +776,7 @@ reader.close(); // modify index and check version has been // incremented: - while(true) { - try { - Thread.sleep(1000); - break; - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } - } + Thread.sleep(1000); writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); addDocumentWithFields(writer); Index: src/test/org/apache/lucene/index/TestIndexWriter.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexWriter.java (revision 758608) +++ src/test/org/apache/lucene/index/TestIndexWriter.java (working copy) @@ -2010,7 +2010,7 @@ } } - public void testDocumentsWriterExceptionThreads() throws IOException { + public void testDocumentsWriterExceptionThreads() throws Exception { Analyzer analyzer = new Analyzer() { public TokenStream tokenStream(String fieldName, Reader reader) { return new CrashingFilter(fieldName, new WhitespaceTokenizer(reader)); @@ -2070,13 +2070,7 @@ } for(int t=0;t= 5) break; @@ -2337,7 +2325,7 @@ // threads are trying to add documents. Strictly // speaking, this isn't valid us of Lucene's APIs, but we // still want to be robust to this case: - public void testCloseWithThreads() throws IOException { + public void testCloseWithThreads() throws Exception { int NUM_THREADS = 3; for(int iter=0;iter<20;iter++) { @@ -2362,11 +2350,7 @@ boolean done = false; while(!done) { - try { - Thread.sleep(100); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } + Thread.sleep(100); for(int i=0;i 0) { @@ -2379,16 +2363,9 @@ // Make sure threads that are adding docs are not hung: for(int i=0;i 0) { + rand = random.nextInt(maxWait); + //System.out.println("waiting " + rand + "ms"); try { - rand = random.nextInt(maxWait); - //System.out.println("waiting " + rand + "ms"); Thread.sleep(rand); - } catch (InterruptedException e) { - throw new RuntimeException(e); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } Index: src/java/org/apache/lucene/search/FilterManager.java =================================================================== --- src/java/org/apache/lucene/search/FilterManager.java (revision 758608) +++ src/java/org/apache/lucene/search/FilterManager.java (working copy) @@ -195,8 +195,9 @@ // take a nap try { Thread.sleep(cleanSleepTime); - } catch (InterruptedException e) { - // just keep going + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } Index: src/java/org/apache/lucene/search/TimeLimitedCollector.java =================================================================== --- src/java/org/apache/lucene/search/TimeLimitedCollector.java (revision 758608) +++ src/java/org/apache/lucene/search/TimeLimitedCollector.java (working copy) @@ -72,21 +72,14 @@ } public void run() { - boolean interrupted = false; - try { - while( true ) { - // TODO: Use System.nanoTime() when Lucene moves to Java SE 5. - time += resolution; - try { - Thread.sleep( resolution ); - } catch( final InterruptedException e ) { - interrupted = true; - } - } - } - finally { - if( interrupted ) { + while( true ) { + // TODO: Use System.nanoTime() when Lucene moves to Java SE 5. + time += resolution; + try { + Thread.sleep( resolution ); + } catch (InterruptedException ie) { Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } Index: src/java/org/apache/lucene/search/ParallelMultiSearcher.java =================================================================== --- src/java/org/apache/lucene/search/ParallelMultiSearcher.java (revision 758608) +++ src/java/org/apache/lucene/search/ParallelMultiSearcher.java (working copy) @@ -77,7 +77,10 @@ try { msta[i].join(); } catch (InterruptedException ie) { - ; // TODO: what should we do with this??? + // In 3.0 we will change this to throw + // InterruptedException instead + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } IOException ioe = msta[i].getIOException(); if (ioe == null) { @@ -130,7 +133,10 @@ try { msta[i].join(); } catch (InterruptedException ie) { - ; // TODO: what should we do with this??? + // In 3.0 we will change this to throw + // InterruptedException instead + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } IOException ioe = msta[i].getIOException(); if (ioe == null) { Index: src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfos.java (revision 758608) +++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -613,8 +613,11 @@ } try { Thread.sleep(defaultGenFileRetryPauseMsec); - } catch (InterruptedException e) { - // will retry + } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } Index: src/java/org/apache/lucene/index/CheckIndex.java =================================================================== --- src/java/org/apache/lucene/index/CheckIndex.java (revision 758608) +++ src/java/org/apache/lucene/index/CheckIndex.java (working copy) @@ -611,7 +611,7 @@ This tool exits with exit code 1 if the index cannot be opened or has any corruption, else 0. */ - public static void main(String[] args) throws IOException { + public static void main(String[] args) throws IOException, InterruptedException { boolean doFix = false; List onlySegments = new ArrayList(); @@ -695,13 +695,7 @@ System.out.println("WARNING: " + result.totLoseDocCount + " documents will be lost\n"); System.out.println("NOTE: will write new segments file in 5 seconds; this will remove " + result.totLoseDocCount + " docs from the index. THIS IS YOUR LAST CHANCE TO CTRL+C!"); for(int s=0;s<5;s++) { - try { - Thread.sleep(1000); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - s--; - continue; - } + Thread.sleep(1000); System.out.println(" " + (5-s) + "..."); } System.out.println("Writing..."); Index: src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java =================================================================== --- src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java (revision 758608) +++ src/java/org/apache/lucene/index/ConcurrentMergeScheduler.java (working copy) @@ -129,10 +129,15 @@ try { wait(); - } catch (InterruptedException e) { + } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } + private synchronized int mergeThreadCount() { int count = 0; final int numThreads = mergeThreads.size(); @@ -185,29 +190,42 @@ // deterministic assignment of segment names writer.mergeInit(merge); - synchronized(this) { - while (mergeThreadCount() >= maxThreadCount) { - if (verbose()) - message(" too many merge threads running; stalling..."); - try { - wait(); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); + boolean success = false; + try { + synchronized(this) { + final MergeThread merger; + while (mergeThreadCount() >= maxThreadCount) { + if (verbose()) + message(" too many merge threads running; stalling..."); + try { + wait(); + } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); + } } - } - if (verbose()) - message(" consider merge " + merge.segString(dir)); + if (verbose()) + message(" consider merge " + merge.segString(dir)); - assert mergeThreadCount() < maxThreadCount; + assert mergeThreadCount() < maxThreadCount; - // OK to spawn a new merge thread to handle this - // merge: - final MergeThread merger = getMergeThread(writer, merge); - mergeThreads.add(merger); - if (verbose()) - message(" launch new thread [" + merger.getName() + "]"); - merger.start(); + // OK to spawn a new merge thread to handle this + // merge: + merger = getMergeThread(writer, merge); + mergeThreads.add(merger); + if (verbose()) + message(" launch new thread [" + merger.getName() + "]"); + + merger.start(); + success = true; + } + } finally { + if (!success) { + writer.mergeFinish(merge); + } } } } Index: src/java/org/apache/lucene/index/DocumentsWriter.java =================================================================== --- src/java/org/apache/lucene/index/DocumentsWriter.java (revision 758608) +++ src/java/org/apache/lucene/index/DocumentsWriter.java (working copy) @@ -509,8 +509,11 @@ while(!allThreadsIdle()) { try { wait(); - } catch (InterruptedException e) { + } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } @@ -837,8 +840,11 @@ while (!closed && ((state != null && !state.isIdle) || pauseThreads != 0 || flushPending || aborting)) { try { wait(); - } catch (InterruptedException e) { + } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } @@ -1083,8 +1089,11 @@ do { try { wait(); - } catch (InterruptedException e) { + } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } while (!waitQueue.doResume()); } Index: src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriter.java (revision 758608) +++ src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -4147,25 +4147,20 @@ } } finally { synchronized(this) { - try { + mergeFinish(merge); - mergeFinish(merge); + if (!success) { + if (infoStream != null) + message("hit exception during merge"); + if (merge.info != null && !segmentInfos.contains(merge.info)) + deleter.refresh(merge.info.name); + } - if (!success) { - if (infoStream != null) - message("hit exception during merge"); - if (merge.info != null && !segmentInfos.contains(merge.info)) - deleter.refresh(merge.info.name); - } - - // This merge (and, generally, any change to the - // segments) may now enable new merges, so we call - // merge policy & update pending merges. - if (success && !merge.isAborted() && !closed && !closing) - updatePendingMerges(merge.maxNumSegmentsOptimize, merge.optimize); - } finally { - runningMerges.remove(merge); - } + // This merge (and, generally, any change to the + // segments) may now enable new merges, so we call + // merge policy & update pending merges. + if (success && !merge.isAborted() && !closed && !closing) + updatePendingMerges(merge.maxNumSegmentsOptimize, merge.optimize); } } } catch (OutOfMemoryError oom) { @@ -4234,7 +4229,6 @@ } finally { if (!success) { mergeFinish(merge); - runningMerges.remove(merge); } } } @@ -4439,6 +4433,8 @@ mergingSegments.remove(merge.info); merge.registerDone = false; } + + runningMerges.remove(merge); } /** Does the actual (time-consuming) work of the merge, @@ -4700,7 +4696,10 @@ try { synced.wait(); } catch (InterruptedException ie) { - continue; + // In 3.0 we will change this to throw + // InterruptedException instead + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } @@ -4731,23 +4730,29 @@ try { Thread.sleep(100); } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } } } private synchronized void doWait() { + // NOTE: the callers of this method should in theory + // be able to do simply wait(), but, as a defense + // against thread timing hazards where notifyAll() + // falls to be called, we wait for at most 1 second + // and then return so caller can check if wait + // conditions are satisified: try { - // NOTE: the callers of this method should in theory - // be able to do simply wait(), but, as a defense - // against thread timing hazards where notifyAll() - // falls to be called, we wait for at most 1 second - // and then return so caller can check if wait - // conditions are satisified: wait(1000); } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } @@ -4819,6 +4824,13 @@ deleter.incRef(toSync, false); myChangeCount = changeCount; + + Iterator it = toSync.files(directory, false).iterator(); + while(it.hasNext()) { + String fileName = (String) it.next(); + assert directory.fileExists(fileName): "file " + fileName + " does not exist"; + } + } finally { resumeAddIndexes(); } Index: src/java/org/apache/lucene/store/RAMDirectory.java =================================================================== --- src/java/org/apache/lucene/store/RAMDirectory.java (revision 758608) +++ src/java/org/apache/lucene/store/RAMDirectory.java (working copy) @@ -150,7 +150,12 @@ do { try { Thread.sleep(0, 1); - } catch (InterruptedException e) {} + } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead + Thread.currentThread().interrupt(); + throw new RuntimeException(ie); + } ts2 = System.currentTimeMillis(); } while(ts1 == ts2); Index: src/java/org/apache/lucene/store/Lock.java =================================================================== --- src/java/org/apache/lucene/store/Lock.java (revision 758608) +++ src/java/org/apache/lucene/store/Lock.java (working copy) @@ -91,6 +91,8 @@ try { Thread.sleep(LOCK_POLL_INTERVAL); } catch (InterruptedException e) { + // In 3.0 we will change this to throw + // InterruptedException instead throw new IOException(e.toString()); } locked = obtain(); Index: src/java/org/apache/lucene/store/FSDirectory.java =================================================================== --- src/java/org/apache/lucene/store/FSDirectory.java (revision 758608) +++ src/java/org/apache/lucene/store/FSDirectory.java (working copy) @@ -538,7 +538,10 @@ // Pause 5 msec Thread.sleep(5); } catch (InterruptedException ie) { + // In 3.0 we will change this to throw + // InterruptedException instead Thread.currentThread().interrupt(); + throw new RuntimeException(ie); } } }