Index: src/java/org/apache/lucene/index/IndexWriter.java
===================================================================
--- src/java/org/apache/lucene/index/IndexWriter.java	(revision 834628)
+++ src/java/org/apache/lucene/index/IndexWriter.java	(working copy)
@@ -28,10 +28,12 @@
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.BufferedIndexInput;
 import org.apache.lucene.util.Constants;
+import org.apache.lucene.util.ReaderUtil;
 
 import java.io.IOException;
 import java.io.Closeable;
 import java.io.PrintStream;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Collection;
 import java.util.ArrayList;
@@ -572,6 +574,11 @@
     public synchronized SegmentReader get(SegmentInfo info, boolean doOpenStores) throws IOException {
       return get(info, doOpenStores, BufferedIndexInput.BUFFER_SIZE, IndexReader.DEFAULT_TERMS_INDEX_DIVISOR);
     }
+    
+    public synchronized void add(SegmentReader reader) {
+      readerMap.put(reader.getSegmentInfo(), reader);
+    }
+    
     /**
      * Obtain a SegmentReader from the readerPool.  The reader
      * must be returned by calling {@link #release(SegmentReader)}
@@ -3056,7 +3063,104 @@
       }
     }
   }
+  
+  public void addIndexesNoOptimize(IndexReader... readers)
+    throws CorruptIndexException, IOException {
+    // separate out the segment readers
+    // assert they're all read only
+    List<IndexReader> subReaders = new ArrayList<IndexReader>(); 
+    for (IndexReader reader : readers) {
+      if (reader instanceof ReadOnlyDirectoryReader 
+          || reader instanceof ReadOnlySegmentReader) {
+        ReaderUtil.gatherSubReaders(subReaders, reader);
+      } else {
+        throw new IOException("readers need to be read only");
+      }
+    }
+    SegmentReader[] segmentReaders = new SegmentReader[subReaders.size()];
+    for (int x=0; x < subReaders.size(); x++) {
+      assert subReaders.get(x) instanceof SegmentReader;
+      segmentReaders[x] = (SegmentReader)subReaders.get(x);
+    }
+    addIndexesNoOptimize(segmentReaders);
+  }
+  
+  protected void addIndexesNoOptimize(SegmentReader... readers)
+    throws CorruptIndexException, IOException {
 
+    ensureOpen();
+
+    //noDupDirs(dirs);
+
+    // Do not allow add docs or deletes while we are running:
+    docWriter.pauseAllThreads();
+
+    try {
+      if (infoStream != null)
+        message("flush at addIndexesNoOptimize");
+      flush(true, false, true);
+
+      boolean success = false;
+
+      startTransaction(false);
+      boolean[] addedToPool = new boolean[readers.length];
+      Arrays.fill(addedToPool, false);
+      try {
+
+        int docCount = 0;
+        synchronized(this) {
+          ensureOpen();
+
+          for (int j = 0; j < readers.length; j++) {
+            SegmentInfo info = readers[j].getSegmentInfo();
+            assert !segmentInfos.contains(info): "dup info dir=" + info.dir + " name=" + info.name;
+            docCount += info.docCount;
+            readerPool.add(readers[j]);
+            readers[j].incRef();
+            addedToPool[j] = true;
+            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 {
+        for (int x=0; x < addedToPool.length; x++) {
+          if (addedToPool[x]) {
+            readers[x].decRef();
+          }
+        }
+        if (success) {
+          commitTransaction();
+        } else {
+          rollbackTransaction();
+        }
+      }
+    } catch (OutOfMemoryError oom) {
+      handleOOM(oom, "addIndexesNoOptimize");
+    } finally {
+      if (docWriter != null) {
+        docWriter.resumeAllThreads();
+      }
+    }
+  }
+  
   private boolean hasExternalSegments() {
     return segmentInfos.hasExternalSegments(directory);
   }
