Index: src/java/org/apache/lucene/index/DirectoryReader.java =================================================================== --- src/java/org/apache/lucene/index/DirectoryReader.java (revision 794127) +++ src/java/org/apache/lucene/index/DirectoryReader.java (working copy) @@ -143,9 +143,9 @@ boolean success = false; try { final SegmentInfo info = infos.info(upto); - if (info.dir == dir) { + //if (info.dir == dir) { readers[upto++] = writer.readerPool.getReadOnlyClone(info, true, termInfosIndexDivisor); - } + //} success = true; } finally { if (!success) { Index: src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriter.java (revision 794127) +++ src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -2091,7 +2091,17 @@ return false; } } - + + private void printAllFiles(String name) throws IOException { + Collection files = segmentInfos.files(directory, true); + Iterator it = files.iterator(); + System.out.println(name); + while (it.hasNext()) { + String f = (String)it.next(); + System.out.println(" "+f); + } + } + private void closeInternal(boolean waitForMerges) throws CorruptIndexException, IOException { docWriter.pauseAllThreads(); @@ -2107,7 +2117,9 @@ if (!hitOOM) { flush(waitForMerges, true, true); } - + printAllFiles("beforeResolve"); + resolveExternalSegments(); + printAllFiles("afterResolve"); if (waitForMerges) // Give merge scheduler last chance to run, in case // any pending merges are waiting: @@ -3649,7 +3661,83 @@ } } } + + /** + * Lazily copies the indexes in the given directories to this + * directory by allowing the natural merge process to occur. + * Whereas the other addIndexes* methods do not allow documents to + * be added or deleted while it is proceeding, this method does. + * Also getReader may be called immediately after and will include + * the added indexes. + * + * @param dirs + * @throws CorruptIndexException + * @throws IOException + */ + public void addIndexesLazyCopy(Directory[] dirs) throws CorruptIndexException, IOException { + ensureOpen(); + noDupDirs(dirs); + + try { + if (infoStream != null) + message("flush at addIndexesNoCommit"); + boolean success = false; + + try { + int docCount = 0; + synchronized(this) { + ensureOpen(); + + for (int i = 0; i < dirs.length; i++) { + if (directory == dirs[i]) { + // cannot add this index: segments may be deleted in merge before added + throw new IllegalArgumentException("Cannot add this index to itself"); + } + + SegmentInfos sis = new SegmentInfos(); // read infos from dir + sis.read(dirs[i]); + for (int j = 0; j < sis.size(); j++) { + SegmentInfo info = sis.info(j); + assert !segmentInfos.contains(info): "dup info dir=" + info.dir + " name=" + info.name; + docCount += info.docCount; + segmentInfos.add(info); // add each info + } + } + } + + // Notify DocumentsWriter that the flushed count just increased + docWriter.updateFlushedDocCount(docCount); + + maybeMerge(); + + ensureOpen(); + + // If after merging there remain segments in the index + // that are in a different directory, just copy these + // over into our index. This is necessary (before + // finishing the transaction) to avoid leaving the + // index in an unusable (inconsistent) state. + //resolveExternalSegments(); + + ensureOpen(); + + success = true; + + } finally { + /** + if (success) { + commitTransaction(); + } else { + rollbackTransaction(); + } + **/ + } + } catch (OutOfMemoryError oom) { + handleOOM(oom, "addIndexesNoCommit"); + } + } + private boolean hasExternalSegments() { return segmentInfos.hasExternalSegments(directory); } @@ -5295,7 +5383,9 @@ if (sizeInBytes > 0) syncPause(sizeInBytes); - + + if (!stopMerges) resolveExternalSegments(); + SegmentInfos toSync = null; final long myChangeCount; Index: src/test/org/apache/lucene/index/TestAddIndexesLazy.java =================================================================== --- src/test/org/apache/lucene/index/TestAddIndexesLazy.java (revision 0) +++ src/test/org/apache/lucene/index/TestAddIndexesLazy.java (revision 0) @@ -0,0 +1,28 @@ +package org.apache.lucene.index; + +import org.apache.lucene.analysis.WhitespaceAnalyzer; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.MockRAMDirectory; +import org.apache.lucene.util.LuceneTestCase; + +public class TestAddIndexesLazy extends LuceneTestCase { + public void test() throws Exception { + Directory dir = new MockRAMDirectory(); + IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), + IndexWriter.MaxFieldLength.LIMITED); + writer.setMergePolicy(new LogDocMergePolicy()); + + TestAddIndexesNoOptimize.addDocs(writer, 200); + + Directory addDir = new MockRAMDirectory(); + TestIndexWriterReader.createIndex(addDir, "beingAdded", true); + + writer.addIndexesLazyCopy(new Directory[] {addDir}); + + IndexReader reader = writer.getReader(); + assertEquals(300, reader.numDocs()); + reader.close(); + writer.close(); + dir.close(); + } +} Index: src/test/org/apache/lucene/index/TestAddIndexesNoOptimize.java =================================================================== --- src/test/org/apache/lucene/index/TestAddIndexesNoOptimize.java (revision 794127) +++ src/test/org/apache/lucene/index/TestAddIndexesNoOptimize.java (working copy) @@ -430,7 +430,7 @@ return writer; } - private void addDocs(IndexWriter writer, int numDocs) throws IOException { + public static void addDocs(IndexWriter writer, int numDocs) throws IOException { for (int i = 0; i < numDocs; i++) { Document doc = new Document(); doc.add(new Field("content", "aaa", Field.Store.NO,