You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2013/04/11 00:05:47 UTC
svn commit: r1466707 - in /lucene/dev/branches/branch_4x: ./ lucene/
lucene/core/ lucene/core/src/java/org/apache/lucene/index/
lucene/core/src/java/org/apache/lucene/store/
lucene/core/src/test/org/apache/lucene/index/ lucene/test-framework/
lucene/te...
Author: mikemccand
Date: Wed Apr 10 22:05:45 2013
New Revision: 1466707
URL: http://svn.apache.org/r1466707
Log:
LUCENE-4738: simplify DirectoryReader.indexExists; fix IndexWriter with CREATE to succeed on a corrupted index; add random IOExceptions to MockDirectoryWrapper.openInput/createOutput
Added:
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOutOfFileDescriptors.java
- copied unchanged from r1466706, lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterOutOfFileDescriptors.java
Modified:
lucene/dev/branches/branch_4x/ (props changed)
lucene/dev/branches/branch_4x/lucene/ (props changed)
lucene/dev/branches/branch_4x/lucene/CHANGES.txt (contents, props changed)
lucene/dev/branches/branch_4x/lucene/core/ (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java
lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexFileDeleter.java
lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/store/Directory.java
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java
lucene/dev/branches/branch_4x/lucene/test-framework/ (props changed)
lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java
lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
Modified: lucene/dev/branches/branch_4x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/CHANGES.txt?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_4x/lucene/CHANGES.txt Wed Apr 10 22:05:45 2013
@@ -234,6 +234,15 @@ Bug Fixes
and one of the sort fields is the relevance score. Only IndexSearchers created
with an ExecutorService are concerned. (Adrien Grand)
+* LUCENE-4738, LUCENE-2727, LUCENE-2812: Simplified
+ DirectoryReader.indexExists so that it's more robust to transient
+ IOExceptions (e.g. due to issues like file descriptor exhaustion),
+ but this will also cause it to err towards returning true for
+ example if the directory contains a corrupted index or an incomplete
+ initial commit. In addition, IndexWriter with OpenMode.CREATE will
+ now succeed even if the directory contains a corrupted index (Billow
+ Gao, Robert Muir, Mike McCandless)
+
Documentation
* LUCENE-4841: Added example SimpleSortedSetFacetsExample to show how
Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/DirectoryReader.java Wed Apr 10 22:05:45 2013
@@ -23,9 +23,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import org.apache.lucene.index.SegmentInfos.FindSegmentsFile;
import org.apache.lucene.search.SearcherManager; // javadocs
import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.NoSuchDirectoryException;
/** DirectoryReader is an implementation of {@link CompositeReader}
that can read indexes in a {@link Directory}.
@@ -314,34 +314,45 @@ public abstract class DirectoryReader ex
}
/**
- * Returns <code>true</code> if an index exists at the specified directory.
+ * Returns <code>true</code> if an index likely exists at
+ * the specified directory. Note that if a corrupt index
+ * exists, or if an index in the process of committing
* @param directory the directory to check for an index
* @return <code>true</code> if an index exists; <code>false</code> otherwise
*/
- public static boolean indexExists(Directory directory) {
+ public static boolean indexExists(Directory directory) throws IOException {
+ // LUCENE-2812, LUCENE-2727, LUCENE-4738: this logic will
+ // return true in cases that should arguably be false,
+ // such as only IW.prepareCommit has been called, or a
+ // corrupt first commit, but it's too deadly to make
+ // this logic "smarter" and risk accidentally returning
+ // false due to various cases like file description
+ // exhaustion, access denited, etc., because in that
+ // case IndexWriter may delete the entire index. It's
+ // safer to err towards "index exists" than try to be
+ // smart about detecting not-yet-fully-committed or
+ // corrupt indices. This means that IndexWriter will
+ // throw an exception on such indices and the app must
+ // resolve the situation manually:
+ String[] files;
try {
- new FindSegmentsFile(directory) {
- @Override
- protected Object doBody(String segmentFileName) throws IOException {
- try {
- new SegmentInfos().read(directory, segmentFileName);
- } catch (FileNotFoundException ex) {
- if (!directory.fileExists(segmentFileName)) {
- throw ex;
- }
- /* this is ok - we might have run into a access exception here.
- * or even worse like on LUCENE-4870 this is triggered due to
- * too many open files on the system. In that case we rather report
- * a false positive here since wrongly returning false from indexExist
- * can cause data loss since IW relies on this.*/
- }
- return null;
- }
- }.run();
- return true;
- } catch (IOException ioe) {
+ files = directory.listAll();
+ } catch (NoSuchDirectoryException nsde) {
+ // Directory does not exist --> no index exists
return false;
}
+
+ // Defensive: maybe a Directory impl returns null
+ // instead of throwing NoSuchDirectoryException:
+ if (files != null) {
+ String prefix = IndexFileNames.SEGMENTS + "_";
+ for(String file : files) {
+ if (file.startsWith(prefix) || file.equals(IndexFileNames.SEGMENTS_GEN)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexFileDeleter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexFileDeleter.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexFileDeleter.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexFileDeleter.java Wed Apr 10 22:05:45 2013
@@ -123,7 +123,7 @@ final class IndexFileDeleter implements
* @throws IOException if there is a low-level IO error
*/
public IndexFileDeleter(Directory directory, IndexDeletionPolicy policy, SegmentInfos segmentInfos,
- InfoStream infoStream, IndexWriter writer) throws IOException {
+ InfoStream infoStream, IndexWriter writer, boolean initialIndexExists) throws IOException {
this.infoStream = infoStream;
this.writer = writer;
@@ -209,7 +209,7 @@ final class IndexFileDeleter implements
}
}
- if (currentCommitPoint == null && currentSegmentsFile != null) {
+ if (currentCommitPoint == null && currentSegmentsFile != null && initialIndexExists) {
// We did not in fact see the segments_N file
// corresponding to the segmentInfos that was passed
// in. Yet, it must exist, because our caller holds
@@ -221,7 +221,7 @@ final class IndexFileDeleter implements
try {
sis.read(directory, currentSegmentsFile);
} catch (IOException e) {
- throw new CorruptIndexException("failed to locate current segments_N file");
+ throw new CorruptIndexException("failed to locate current segments_N file \"" + currentSegmentsFile + "\"");
}
if (infoStream.isEnabled("IFD")) {
infoStream.message("IFD", "forced open of current segments file " + segmentInfos.getSegmentsFileName());
Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java Wed Apr 10 22:05:45 2013
@@ -661,6 +661,8 @@ public class IndexWriter implements Clos
// IndexFormatTooOldException.
segmentInfos = new SegmentInfos();
+ boolean initialIndexExists = true;
+
if (create) {
// Try to read first. This is to allow create
// against an index that's currently open for
@@ -671,6 +673,7 @@ public class IndexWriter implements Clos
segmentInfos.clear();
} catch (IOException e) {
// Likely this means it's a fresh directory
+ initialIndexExists = false;
}
// Record that we have a change (zero out all
@@ -711,7 +714,8 @@ public class IndexWriter implements Clos
synchronized(this) {
deleter = new IndexFileDeleter(directory,
config.getIndexDeletionPolicy(),
- segmentInfos, infoStream, this);
+ segmentInfos, infoStream, this,
+ initialIndexExists);
}
if (deleter.startingCommitDeleted) {
Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/store/Directory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/store/Directory.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/store/Directory.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/store/Directory.java Wed Apr 10 22:05:45 2013
@@ -184,7 +184,7 @@ public abstract class Directory implemen
* <pre class="prettyprint">
* Directory to; // the directory to copy to
* for (String file : dir.listAll()) {
- * dir.copy(to, file, newFile); // newFile can be either file, or a new name
+ * dir.copy(to, file, newFile, IOContext.DEFAULT); // newFile can be either file, or a new name
* }
* </pre>
* <p>
Modified: lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java Wed Apr 10 22:05:45 2013
@@ -912,19 +912,6 @@ public void testFilesOpenClose() throws
dir.close();
}
- // LUCENE-2812
- public void testIndexExists() throws Exception {
- Directory dir = newDirectory();
- IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())));
- writer.addDocument(new Document());
- writer.prepareCommit();
- assertFalse(DirectoryReader.indexExists(dir));
- writer.commit();
- writer.close();
- assertTrue(DirectoryReader.indexExists(dir));
- dir.close();
- }
-
// Make sure totalTermFreq works correctly in the terms
// dict cache
public void testTotalTermFreqCached() throws Exception {
@@ -1202,4 +1189,12 @@ public void testFilesOpenClose() throws
dir.close();
}
+ public void testIndexExistsOnNonExistentDirectory() throws Exception {
+ File tempDir = _TestUtil.getTempDir("testIndexExistsOnNonExistentDirectory");
+ tempDir.delete();
+ Directory dir = newFSDirectory(tempDir);
+ System.out.println("dir=" + dir);
+ assertFalse(DirectoryReader.indexExists(dir));
+ dir.close();
+ }
}
Modified: lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java Wed Apr 10 22:05:45 2013
@@ -52,7 +52,9 @@ import org.apache.lucene.search.IndexSea
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.AlreadyClosedException;
+import org.apache.lucene.store.BaseDirectoryWrapper;
import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.Lock;
import org.apache.lucene.store.LockFactory;
@@ -1488,7 +1490,7 @@ public class TestIndexWriter extends Luc
}
public void testNoSegmentFile() throws IOException {
- Directory dir = newDirectory();
+ BaseDirectoryWrapper dir = newDirectory();
dir.setLockFactory(NoLockFactory.getNoLockFactory());
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(
TEST_VERSION_CURRENT, new MockAnalyzer(random())).setMaxBufferedDocs(2));
@@ -1508,6 +1510,10 @@ public class TestIndexWriter extends Luc
w2.close();
// If we don't do that, the test fails on Windows
w.rollback();
+
+ // This test leaves only segments.gen, which causes
+ // DirectoryReader.indexExists to return true:
+ dir.setCheckIndexOnClose(false);
dir.close();
}
@@ -2126,5 +2132,52 @@ public class TestIndexWriter extends Luc
}
}
-
+
+ // LUCENE-2727/LUCENE-2812/LUCENE-4738:
+ public void testCorruptFirstCommit() throws Exception {
+ for(int i=0;i<6;i++) {
+ BaseDirectoryWrapper dir = newDirectory();
+ dir.createOutput("segments_0", IOContext.DEFAULT).close();
+ IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()));
+ int mode = i/2;
+ if (mode == 0) {
+ iwc.setOpenMode(OpenMode.CREATE);
+ } else if (mode == 1) {
+ iwc.setOpenMode(OpenMode.APPEND);
+ } else if (mode == 2) {
+ iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);
+ }
+
+ if (VERBOSE) {
+ System.out.println("\nTEST: i=" + i);
+ }
+
+ try {
+ if ((i & 1) == 0) {
+ new IndexWriter(dir, iwc).close();
+ } else {
+ new IndexWriter(dir, iwc).rollback();
+ }
+ if (mode != 0) {
+ fail("expected exception");
+ }
+ } catch (IOException ioe) {
+ // OpenMode.APPEND should throw an exception since no
+ // index exists:
+ if (mode == 0) {
+ // Unexpected
+ throw ioe;
+ }
+ }
+
+ if (VERBOSE) {
+ System.out.println(" at close: " + Arrays.toString(dir.listAll()));
+ }
+
+ if (mode != 0) {
+ dir.setCheckIndexOnClose(false);
+ }
+ dir.close();
+ }
+ }
}
Modified: lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterDelete.java Wed Apr 10 22:05:45 2013
@@ -40,7 +40,6 @@ import org.apache.lucene.search.TermQuer
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.MockDirectoryWrapper;
import org.apache.lucene.store.RAMDirectory;
-import org.apache.lucene.util.Bits;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util._TestUtil;
Modified: lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java Wed Apr 10 22:05:45 2013
@@ -1498,7 +1498,7 @@ public class TestIndexWriterExceptions e
if (doFail && name.startsWith("segments_")) {
StackTraceElement[] trace = new Exception().getStackTrace();
for (int i = 0; i < trace.length; i++) {
- if ("indexExists".equals(trace[i].getMethodName())) {
+ if ("read".equals(trace[i].getMethodName())) {
throw new UnsupportedOperationException("expected UOE");
}
}
@@ -1518,8 +1518,8 @@ public class TestIndexWriterExceptions e
new IndexWriter(d, newIndexWriterConfig(TEST_VERSION_CURRENT, null));
fail("should have gotten a UOE");
} catch (UnsupportedOperationException expected) {
-
}
+
uoe.doFail = false;
d.close();
}
Modified: lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java Wed Apr 10 22:05:45 2013
@@ -181,13 +181,27 @@ public class TestTransactions extends Lu
@Override
public void doWork() throws Throwable {
- IndexReader r1, r2;
+ IndexReader r1=null, r2=null;
synchronized(lock) {
- r1 = DirectoryReader.open(dir1);
- r2 = DirectoryReader.open(dir2);
+ try {
+ r1 = DirectoryReader.open(dir1);
+ r2 = DirectoryReader.open(dir2);
+ } catch (IOException e) {
+ if (!e.getMessage().contains("on purpose")) {
+ throw e;
+ }
+ if (r1 != null) {
+ r1.close();
+ }
+ if (r2 != null) {
+ r2.close();
+ }
+ return;
+ }
}
- if (r1.numDocs() != r2.numDocs())
+ if (r1.numDocs() != r2.numDocs()) {
throw new RuntimeException("doc counts differ: r1=" + r1.numDocs() + " r2=" + r2.numDocs());
+ }
r1.close();
r2.close();
}
Modified: lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java (original)
+++ lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryWrapper.java Wed Apr 10 22:05:45 2013
@@ -20,6 +20,7 @@ package org.apache.lucene.store;
import java.io.IOException;
import java.util.Collection;
+import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.util._TestUtil;
/**
@@ -42,7 +43,7 @@ public class BaseDirectoryWrapper extend
@Override
public void close() throws IOException {
isOpen = false;
- if (checkIndexOnClose && indexPossiblyExists()) {
+ if (checkIndexOnClose && DirectoryReader.indexExists(this)) {
_TestUtil.checkIndex(this, crossCheckTermVectorsOnClose);
}
delegate.close();
@@ -52,27 +53,6 @@ public class BaseDirectoryWrapper extend
return isOpen;
}
- /**
- * don't rely upon DirectoryReader.fileExists to determine if we should
- * checkIndex() or not. It might mask real problems, where we silently
- * don't checkindex at all. instead we look for a segments file.
- */
- protected boolean indexPossiblyExists() {
- String files[];
- try {
- files = listAll();
- } catch (IOException ex) {
- // this means directory doesn't exist, which is ok. return false
- return false;
- }
- for (String f : files) {
- if (f.startsWith("segments_")) {
- return true;
- }
- }
- return false;
- }
-
/**
* Set whether or not checkindex should be run
* on close
Modified: lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java?rev=1466707&r1=1466706&r2=1466707&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java (original)
+++ lucene/dev/branches/branch_4x/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java Wed Apr 10 22:05:45 2013
@@ -67,6 +67,7 @@ public class MockDirectoryWrapper extend
// Max actual bytes used. This is set by MockRAMOutputStream:
long maxUsedSize;
double randomIOExceptionRate;
+ double randomIOExceptionRateOnOpen;
Random randomState;
boolean noDeleteOpenFile = true;
boolean preventDoubleWrite = true;
@@ -322,23 +323,50 @@ public class MockDirectoryWrapper extend
public void setRandomIOExceptionRate(double rate) {
randomIOExceptionRate = rate;
}
+
public double getRandomIOExceptionRate() {
return randomIOExceptionRate;
}
+ /**
+ * If 0.0, no exceptions will be thrown during openInput
+ * and createOutput. Else this should
+ * be a double 0.0 - 1.0 and we will randomly throw an
+ * IOException in openInput and createOutput with
+ * this probability.
+ */
+ public void setRandomIOExceptionRateOnOpen(double rate) {
+ randomIOExceptionRateOnOpen = rate;
+ }
+
+ public double getRandomIOExceptionRateOnOpen() {
+ return randomIOExceptionRateOnOpen;
+ }
+
void maybeThrowIOException() throws IOException {
maybeThrowIOException(null);
}
void maybeThrowIOException(String message) throws IOException {
- if (randomIOExceptionRate > 0.0) {
- int number = Math.abs(randomState.nextInt() % 1000);
- if (number < randomIOExceptionRate*1000) {
- if (LuceneTestCase.VERBOSE) {
- System.out.println(Thread.currentThread().getName() + ": MockDirectoryWrapper: now throw random exception" + (message == null ? "" : " (" + message + ")"));
- new Throwable().printStackTrace(System.out);
- }
- throw new IOException("a random IOException" + (message == null ? "" : "(" + message + ")"));
+ if (randomState.nextDouble() < randomIOExceptionRate) {
+ if (LuceneTestCase.VERBOSE) {
+ System.out.println(Thread.currentThread().getName() + ": MockDirectoryWrapper: now throw random exception" + (message == null ? "" : " (" + message + ")"));
+ new Throwable().printStackTrace(System.out);
+ }
+ throw new IOException("a random IOException" + (message == null ? "" : "(" + message + ")"));
+ }
+ }
+
+ void maybeThrowIOExceptionOnOpen() throws IOException {
+ if (randomState.nextDouble() < randomIOExceptionRateOnOpen) {
+ if (LuceneTestCase.VERBOSE) {
+ System.out.println(Thread.currentThread().getName() + ": MockDirectoryWrapper: now throw random exception during open");
+ new Throwable().printStackTrace(System.out);
+ }
+ if (randomState.nextBoolean()) {
+ throw new IOException("a random IOException");
+ } else {
+ throw new FileNotFoundException("a random IOException");
}
}
}
@@ -403,22 +431,28 @@ public class MockDirectoryWrapper extend
@Override
public synchronized IndexOutput createOutput(String name, IOContext context) throws IOException {
+ maybeThrowDeterministicException();
+ maybeThrowIOExceptionOnOpen();
maybeYield();
if (failOnCreateOutput) {
maybeThrowDeterministicException();
}
- if (crashed)
+ if (crashed) {
throw new IOException("cannot createOutput after crash");
+ }
init();
synchronized(this) {
- if (preventDoubleWrite && createdFiles.contains(name) && !name.equals("segments.gen"))
+ if (preventDoubleWrite && createdFiles.contains(name) && !name.equals("segments.gen")) {
throw new IOException("file \"" + name + "\" was already written to");
+ }
}
- if (noDeleteOpenFile && openFiles.containsKey(name))
+ if (noDeleteOpenFile && openFiles.containsKey(name)) {
throw new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open: cannot overwrite");
+ }
- if (crashed)
+ if (crashed) {
throw new IOException("cannot createOutput after crash");
+ }
unSyncedFiles.add(name);
createdFiles.add(name);
@@ -428,9 +462,9 @@ public class MockDirectoryWrapper extend
RAMFile existing = ramdir.fileMap.get(name);
// Enforce write once:
- if (existing!=null && !name.equals("segments.gen") && preventDoubleWrite)
+ if (existing!=null && !name.equals("segments.gen") && preventDoubleWrite) {
throw new IOException("file " + name + " already exists");
- else {
+ } else {
if (existing!=null) {
ramdir.sizeInBytes.getAndAdd(-existing.sizeInBytes);
existing.directory = null;
@@ -484,6 +518,8 @@ public class MockDirectoryWrapper extend
@Override
public synchronized IndexInput openInput(String name, IOContext context) throws IOException {
+ maybeThrowDeterministicException();
+ maybeThrowIOExceptionOnOpen();
maybeYield();
if (failOnOpenInput) {
maybeThrowDeterministicException();
@@ -587,9 +623,12 @@ public class MockDirectoryWrapper extend
if (noDeleteOpenFile && openLocks.size() > 0) {
throw new RuntimeException("MockDirectoryWrapper: cannot close: there are still open locks: " + openLocks);
}
+
isOpen = false;
if (getCheckIndexOnClose()) {
- if (indexPossiblyExists()) {
+ randomIOExceptionRate = 0.0;
+ randomIOExceptionRateOnOpen = 0.0;
+ if (DirectoryReader.indexExists(this)) {
if (LuceneTestCase.VERBOSE) {
System.out.println("\nNOTE: MockDirectoryWrapper: now crash");
}
@@ -793,7 +832,7 @@ public class MockDirectoryWrapper extend
}
}
}
-
+
@Override
public synchronized String[] listAll() throws IOException {
maybeYield();