package org.apache.lucene.index; /* * 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. */ 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(TestUtil.getTempDir("TestIndexWriterOutOfFileDescriptors")); dir.setPreventDoubleWrite(false); double rate = random().nextDouble()*0.01; //System.out.println("rate=" + rate); dir.setRandomIOExceptionRateOnOpen(rate); int iters = atLeast(20); LineFileDocs docs = new LineFileDocs(random()); IndexReader 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(TEST_VERSION_CURRENT, 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 IR[]"); } w.addIndexes(new IndexReader[] {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()); } 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 (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(TestUtil.getTempDir("TestIndexWriterOutOfFileDescriptors.copy")); Set<String> files = new HashSet<>(); for (String file : dir.listAll()) { dir.copy(dirCopy, 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(TEST_VERSION_CURRENT, new MockAnalyzer(random()))).close(); dirCopy.setRandomIOExceptionRate(rate); dir.setRandomIOExceptionRateOnOpen(rate); } } if (r2 != null) { r2.close(); } if (r != null) { r.close(); dirCopy.close(); } dir.close(); } }