diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
index ab56cd5..2874eb6 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
@@ -34,15 +34,15 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.codecs.Codec;
-import org.apache.lucene.index.DocumentsWriterPerThread.FlushedSegment;
 import org.apache.lucene.index.FieldInfos.FieldNumbers;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.index.MergePolicy.MergeCause;
+import org.apache.lucene.index.MergePolicy.MergeContext;
 import org.apache.lucene.index.MergeState.CheckAbort;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.CompoundFileDirectory;
 import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.FlushInfo;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.Lock;
 import org.apache.lucene.store.LockObtainFailedException;
@@ -52,7 +52,6 @@ import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.Constants;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.InfoStream;
-import org.apache.lucene.util.MutableBits;
 import org.apache.lucene.util.ThreadInterruptedException;
 
 /**
@@ -380,7 +379,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
       }
     }
     if (anySegmentFlushed) {
-      maybeMerge();
+      maybeMerge(MergeCause.AFTER_FULL_FLUSH, MergeContext.SEGMENTS_UNBOUNDED);
     }
     if (infoStream.isEnabled("IW")) {
       infoStream.message("IW", "getReader took " + (System.currentTimeMillis() - tStart) + " msec");
@@ -1229,7 +1228,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
         }
       }
       if (anySegmentFlushed) {
-        maybeMerge();
+        maybeMerge(MergeCause.AFTER_SEGMENT_FLUSH, MergeContext.SEGMENTS_UNBOUNDED);
       }
     } catch (OutOfMemoryError oom) {
       handleOOM(oom, "updateDocuments");
@@ -1451,7 +1450,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
       }
 
       if (anySegmentFlushed) {
-        maybeMerge();
+        maybeMerge(MergeCause.AFTER_SEGMENT_FLUSH, MergeContext.SEGMENTS_UNBOUNDED);
       }
     } catch (OutOfMemoryError oom) {
       handleOOM(oom, "updateDocument");
@@ -1624,7 +1623,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
       }
     }
 
-    maybeMerge(maxNumSegments);
+    maybeMerge(MergeCause.FORCED_MERGE, maxNumSegments);
 
     if (doWait) {
       synchronized(this) {
@@ -1713,7 +1712,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
     MergePolicy.MergeSpecification spec;
 
     synchronized(this) {
-      spec = mergePolicy.findForcedDeletesMerges(segmentInfos);
+      spec = mergePolicy.findMerges(new MergeContext(segmentInfos, MergeCause.FORCED_DELETES_MERGE));
       if (spec != null) {
         final int numMerges = spec.merges.size();
         for(int i=0;i<numMerges;i++)
@@ -1805,16 +1804,16 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
    * href="#OOME">above</a> for details.</p>
    */
   public final void maybeMerge() throws IOException {
-    maybeMerge(-1);
+    maybeMerge(MergeCause.UNKOWN, MergeContext.SEGMENTS_UNBOUNDED);
   }
 
-  private final void maybeMerge(int maxNumSegments) throws IOException {
+  private final void maybeMerge(MergeCause cause, int maxNumSegments) throws IOException {
     ensureOpen(false);
-    updatePendingMerges(maxNumSegments);
+    updatePendingMerges(cause, maxNumSegments);
     mergeScheduler.merge(this);
   }
 
-  private synchronized void updatePendingMerges(int maxNumSegments)
+  private synchronized void updatePendingMerges(MergeCause cause, int maxNumSegments)
     throws IOException {
     assert maxNumSegments == -1 || maxNumSegments > 0;
 
@@ -1828,8 +1827,9 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
     }
 
     final MergePolicy.MergeSpecification spec;
-    if (maxNumSegments != -1) {
-      spec = mergePolicy.findForcedMerges(segmentInfos, maxNumSegments, Collections.unmodifiableMap(segmentsToMerge));
+    if (maxNumSegments != MergeContext.SEGMENTS_UNBOUNDED) {
+      MergeContext context = new MergeContext(Collections.unmodifiableMap(segmentsToMerge), segmentInfos, maxNumSegments, cause);
+      spec = mergePolicy.findMerges(context);
       if (spec != null) {
         final int numMerges = spec.merges.size();
         for(int i=0;i<numMerges;i++) {
@@ -1839,7 +1839,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
       }
 
     } else {
-      spec = mergePolicy.findMerges(segmentInfos);
+      spec = mergePolicy.findMerges(new MergeContext(segmentInfos, cause));
     }
 
     if (spec != null) {
@@ -2656,7 +2656,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
       boolean success = false;
       try {
         if (anySegmentsFlushed) {
-          maybeMerge();
+          maybeMerge(MergeCause.AFTER_FULL_FLUSH, MergeContext.SEGMENTS_UNBOUNDED);
         }
         success = true;
       } finally {
@@ -2812,7 +2812,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
     // We can be called during close, when closing==true, so we must pass false to ensureOpen:
     ensureOpen(false);
     if (doFlush(applyAllDeletes) && triggerMerge) {
-      maybeMerge();
+      maybeMerge(MergeCause.AFTER_FULL_FLUSH, MergeContext.SEGMENTS_UNBOUNDED);
     }
   }
 
@@ -3245,7 +3245,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
           // segments) may now enable new merges, so we call
           // merge policy & update pending merges.
           if (success && !merge.isAborted() && (merge.maxNumSegments != -1 || (!closed && !closing))) {
-            updatePendingMerges(merge.maxNumSegments);
+            updatePendingMerges(MergeCause.AFTER_MERGE, merge.maxNumSegments);
           }
         }
       }
diff --git a/lucene/core/src/java/org/apache/lucene/index/MergePolicy.java b/lucene/core/src/java/org/apache/lucene/index/MergePolicy.java
index e0a2333..dfeefc1 100644
--- a/lucene/core/src/java/org/apache/lucene/index/MergePolicy.java
+++ b/lucene/core/src/java/org/apache/lucene/index/MergePolicy.java
@@ -19,6 +19,7 @@ package org.apache.lucene.index;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -379,9 +380,77 @@ public abstract class MergePolicy implements java.io.Closeable, Cloneable {
    * Release all resources for the policy.
    */
   public abstract void close();
+  
+  
+  /**
+  // nocommit add javadocs
+   */
+  public MergeSpecification findMerges(MergeContext ctx) throws IOException {
+    /*
+     * nocommit: this is just a delegate based on the context. We could remove all the
+     * other find* methods and just delegate in the implementations but it seems more
+     * reasonable to have this predefined distinction.
+     */
+    switch(ctx.cause) {
+      case AFTER_FULL_FLUSH:
+      case AFTER_SEGMENT_FLUSH:
+      case INDEX_ADDED:
+      case UNKOWN:
+        assert ctx.maxSegmentCount == MergeContext.SEGMENTS_UNBOUNDED;
+        return findMerges(ctx.segmentInfos);
+      case AFTER_MERGE:
+        if (ctx.maxSegmentCount != MergeContext.SEGMENTS_UNBOUNDED) {
+          return findForcedMerges(ctx.segmentInfos, ctx.maxSegmentCount, ctx.segmentsToMerge);
+        } else {
+          return findMerges(ctx.segmentInfos);
+        }
+      case FORCED_MERGE:
+        assert ctx.maxSegmentCount >= 0;
+        return findForcedMerges(ctx.segmentInfos, ctx.maxSegmentCount, ctx.segmentsToMerge);
+      case FORCED_DELETES_MERGE:
+        assert ctx.maxSegmentCount == MergeContext.SEGMENTS_UNBOUNDED;
+        return findForcedDeletesMerges(ctx.segmentInfos);
+      default:
+        throw new IllegalArgumentException("unknown merge cause: [" + ctx.cause + "]");
+    }
+  }
 
   /**
    * Returns true if a new segment (regardless of its origin) should use the compound file format.
    */
   public abstract boolean useCompoundFile(SegmentInfos segments, SegmentInfoPerCommit newSegment) throws IOException;
+  
+  public static class MergeContext {
+    private static final Map<SegmentInfoPerCommit,Boolean> EMPTY_FOCED_SEGMENTS = Collections.emptyMap();
+    public static final int SEGMENTS_UNBOUNDED = -1;
+    public final Map<SegmentInfoPerCommit,Boolean> segmentsToMerge;
+    public SegmentInfos segmentInfos;
+    public int maxSegmentCount;
+    public MergeCause cause;
+    
+    public MergeContext(SegmentInfos segmentInfos, MergeCause cause) {
+      this(EMPTY_FOCED_SEGMENTS, segmentInfos, SEGMENTS_UNBOUNDED, cause);
+    }
+    
+    public MergeContext(Map<SegmentInfoPerCommit,Boolean> segmentsToMerge,
+        SegmentInfos segmentInfos, int maxSegmentCount, MergeCause cause) {
+      if (cause == null) {
+        throw new IllegalArgumentException("MergeCause must not be null");
+      }
+      this.segmentsToMerge = segmentsToMerge;
+      this.segmentInfos = segmentInfos;
+      this.maxSegmentCount = maxSegmentCount;
+      this.cause = cause;
+    }
+  }
+  
+  public static enum MergeCause {
+    UNKOWN, 
+    AFTER_SEGMENT_FLUSH, 
+    AFTER_FULL_FLUSH,
+    FORCED_MERGE,
+    FORCED_DELETES_MERGE,
+    INDEX_ADDED,
+    AFTER_MERGE
+  }
 }
diff --git a/lucene/core/src/java/org/apache/lucene/index/NoMergePolicy.java b/lucene/core/src/java/org/apache/lucene/index/NoMergePolicy.java
index 9d83e35..8108bc0 100644
--- a/lucene/core/src/java/org/apache/lucene/index/NoMergePolicy.java
+++ b/lucene/core/src/java/org/apache/lucene/index/NoMergePolicy.java
@@ -17,8 +17,12 @@ package org.apache.lucene.index;
  * limitations under the License.
  */
 
+import java.io.IOException;
 import java.util.Map;
 
+import org.apache.lucene.index.MergePolicy.MergeContext;
+import org.apache.lucene.index.MergePolicy.MergeSpecification;
+
 /**
  * A {@link MergePolicy} which never returns merges to execute (hence it's
  * name). It is also a singleton and can be accessed through
@@ -63,6 +67,9 @@ public final class NoMergePolicy extends MergePolicy {
   public MergeSpecification findForcedDeletesMerges(SegmentInfos segmentInfos) { return null; }
 
   @Override
+  public MergeSpecification findMerges(MergeContext ctx) throws IOException { return null;  }
+
+  @Override
   public boolean useCompoundFile(SegmentInfos segments, SegmentInfoPerCommit newSegment) { return useCompoundFile; }
 
   @Override
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestNoMergePolicy.java b/lucene/core/src/test/org/apache/lucene/index/TestNoMergePolicy.java
index 4014cf3..0103ed0 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestNoMergePolicy.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestNoMergePolicy.java
@@ -30,7 +30,7 @@ public class TestNoMergePolicy extends LuceneTestCase {
   @Test
   public void testNoMergePolicy() throws Exception {
     MergePolicy mp = NoMergePolicy.NO_COMPOUND_FILES;
-    assertNull(mp.findMerges(null));
+    assertNull(mp.findMerges((SegmentInfos)null));
     assertNull(mp.findForcedMerges(null, 0, null));
     assertNull(mp.findForcedDeletesMerges(null));
     assertFalse(mp.useCompoundFile(null, null));
diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
index eaefa92..64c123a 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
@@ -763,7 +763,6 @@ public abstract class LuceneTestCase extends Assert {
     } else {
       c.setMergePolicy(newLogMergePolicy());
     }
-
     c.setReaderPooling(r.nextBoolean());
     c.setReaderTermsIndexDivisor(_TestUtil.nextInt(r, 1, 4));
     return c;
