blob: eb7027ed39d34708ae978c48d93ff653f5e10bc4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.index;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.MockDirectoryWrapper;
import org.apache.lucene.util.LineFileDocs;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.PrintStreamInfoStream;
import org.apache.lucene.util.TestUtil;
public class TestIndexWriterOutOfFileDescriptors extends LuceneTestCase {
public void test() throws Exception {
MockDirectoryWrapper dir = newMockFSDirectory(createTempDir("TestIndexWriterOutOfFileDescriptors"));
double rate = random().nextDouble()*0.01;
//System.out.println("rate=" + rate);
dir.setRandomIOExceptionRateOnOpen(rate);
int iters = atLeast(20);
LineFileDocs docs = new LineFileDocs(random());
DirectoryReader r = null;
DirectoryReader r2 = null;
boolean any = false;
MockDirectoryWrapper dirCopy = null;
int lastNumDocs = 0;
for(int iter=0;iter<iters;iter++) {
IndexWriter w = null;
if (VERBOSE) {
System.out.println("TEST: iter=" + iter);
}
try {
MockAnalyzer analyzer = new MockAnalyzer(random());
analyzer.setMaxTokenLength(TestUtil.nextInt(random(), 1, IndexWriter.MAX_TERM_LENGTH));
IndexWriterConfig iwc = newIndexWriterConfig(analyzer);
if (VERBOSE) {
// Do this ourselves instead of relying on LTC so
// we see incrementing messageID:
iwc.setInfoStream(new PrintStreamInfoStream(System.out));
}
MergeScheduler ms = iwc.getMergeScheduler();
if (ms instanceof ConcurrentMergeScheduler) {
((ConcurrentMergeScheduler) ms).setSuppressExceptions();
}
w = new IndexWriter(dir, iwc);
if (r != null && random().nextInt(5) == 3) {
if (random().nextBoolean()) {
if (VERBOSE) {
System.out.println("TEST: addIndexes LR[]");
}
TestUtil.addIndexesSlowly(w, r);
} else {
if (VERBOSE) {
System.out.println("TEST: addIndexes Directory[]");
}
w.addIndexes(new Directory[] {dirCopy});
}
} else {
if (VERBOSE) {
System.out.println("TEST: addDocument");
}
w.addDocument(docs.nextDoc());
}
dir.setRandomIOExceptionRateOnOpen(0.0);
if (ms instanceof ConcurrentMergeScheduler) {
((ConcurrentMergeScheduler) ms).sync();
}
// If exc hit CMS then writer will be tragically closed:
if (w.getTragicException() == null) {
w.close();
}
w = null;
// NOTE: This is O(N^2)! Only enable for temporary debugging:
//dir.setRandomIOExceptionRateOnOpen(0.0);
//_TestUtil.checkIndex(dir);
//dir.setRandomIOExceptionRateOnOpen(rate);
// Verify numDocs only increases, to catch IndexWriter
// accidentally deleting the index:
dir.setRandomIOExceptionRateOnOpen(0.0);
assertTrue(DirectoryReader.indexExists(dir));
if (r2 == null) {
r2 = DirectoryReader.open(dir);
} else {
DirectoryReader r3 = DirectoryReader.openIfChanged(r2);
if (r3 != null) {
r2.close();
r2 = r3;
}
}
assertTrue("before=" + lastNumDocs + " after=" + r2.numDocs(), r2.numDocs() >= lastNumDocs);
lastNumDocs = r2.numDocs();
//System.out.println("numDocs=" + lastNumDocs);
dir.setRandomIOExceptionRateOnOpen(rate);
any = true;
if (VERBOSE) {
System.out.println("TEST: iter=" + iter + ": success");
}
} catch (AssertionError | IOException ioe) {
if (VERBOSE) {
System.out.println("TEST: iter=" + iter + ": exception");
ioe.printStackTrace();
}
if (w != null) {
// NOTE: leave random IO exceptions enabled here,
// to verify that rollback does not try to write
// anything:
w.rollback();
}
}
if (any && r == null && random().nextBoolean()) {
// Make a copy of a non-empty index so we can use
// it to addIndexes later:
dir.setRandomIOExceptionRateOnOpen(0.0);
r = DirectoryReader.open(dir);
dirCopy = newMockFSDirectory(createTempDir("TestIndexWriterOutOfFileDescriptors.copy"));
Set<String> files = new HashSet<>();
for (String file : dir.listAll()) {
if (file.startsWith(IndexFileNames.SEGMENTS) || IndexFileNames.CODEC_FILE_PATTERN.matcher(file).matches()) {
dirCopy.copyFrom(dir, file, file, IOContext.DEFAULT);
files.add(file);
}
}
dirCopy.sync(files);
// Have IW kiss the dir so we remove any leftover
// files ... we can easily have leftover files at
// the time we take a copy because we are holding
// open a reader:
new IndexWriter(dirCopy, newIndexWriterConfig(new MockAnalyzer(random()))).close();
dirCopy.setRandomIOExceptionRate(rate);
dir.setRandomIOExceptionRateOnOpen(rate);
}
}
if (r2 != null) {
r2.close();
}
if (r != null) {
r.close();
dirCopy.close();
}
dir.close();
}
}