@Override
  public synchronized void merge(IndexWriter writer, MergeTrigger trigger, boolean newMergesFound)
      throws IOException {

    assert !Thread.holdsLock(writer);

    initDynamicDefaults(writer);

    if (trigger == MergeTrigger.CLOSING) {
      // Disable throttling on close:
      targetMBPerSec = MAX_MERGE_MB_PER_SEC;
      updateMergeThreads();
    }

    // First, quickly run through the newly proposed merges
    // and add any orthogonal merges (ie a merge not
    // involving segments already pending to be merged) to
    // the queue.  If we are way behind on merging, many of
    // these newly proposed merges will likely already be
    // registered.

    if (verbose()) {
      message("now merge");
      message("  index: " + writer.segString());
    }

    // Iterate, pulling from the IndexWriter's queue of
    // pending merges, until it's empty:
    while (true) {

      if (maybeStall(writer) == false) {
        break;
      }

      OneMerge merge = writer.getNextMerge();
      if (merge == null) {
        if (verbose()) {
          message("  no more merges pending; now return");
        }
        return;
      }

      updateIOThrottle(merge);

      boolean success = false;
      try {
        if (verbose()) {
          message("  consider merge " + writer.segString(merge.segments));
        }

        // OK to spawn a new merge thread to handle this
        // merge:
        final MergeThread merger = getMergeThread(writer, merge);
        mergeThreads.add(merger);

        if (verbose()) {
          message("    launch new thread [" + merger.getName() + "]");
        }

        merger.start();
        updateMergeThreads();

        success = true;
      } finally {
        if (!success) {
          writer.mergeFinish(merge);
        }
      }
    }
  }
 /**
  * Turn on dynamic IO throttling, to adaptively rate limit writes bytes/sec to the minimal rate
  * necessary so merges do not fall behind. By default this is enabled.
  */
 public synchronized void enableAutoIOThrottle() {
   doAutoIOThrottle = true;
   targetMBPerSec = START_MB_PER_SEC;
   updateMergeThreads();
 }
 /**
  * Turn off auto IO throttling.
  *
  * @see #enableAutoIOThrottle
  */
 public synchronized void disableAutoIOThrottle() {
   doAutoIOThrottle = false;
   updateMergeThreads();
 }
 /**
  * Set the per-merge IO throttle rate for forced merges (default: {@code
  * Double.POSITIVE_INFINITY}).
  */
 public synchronized void setForceMergeMBPerSec(double v) {
   forceMergeMBPerSec = v;
   updateMergeThreads();
 }