void ConcurrentMergeScheduler::merge(const IndexWriterPtr& writer) {
    BOOST_ASSERT(!writer->holdsLock());

    this->_writer = writer;

    initMergeThreadPriority();

    dir = writer->getDirectory();

    // 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.
    message(L"now merge");
    message(L"  index: " + writer->segString());

    // Iterate, pulling from the IndexWriter's queue of pending merges, until it's empty
    while (true) {
        OneMergePtr merge(writer->getNextMerge());
        if (!merge) {
            message(L"  no more merges pending; now return");
            return;
        }

        // We do this with the primary thread to keep deterministic assignment of segment names
        writer->mergeInit(merge);

        bool success = false;
        LuceneException finally;
        try {
            SyncLock syncLock(this);
            MergeThreadPtr merger;
            while (mergeThreadCount() >= maxThreadCount) {
                message(L"    too many merge threads running; stalling...");
                wait(1000);
            }

            message(L"  consider merge " + merge->segString(dir));

            BOOST_ASSERT(mergeThreadCount() < maxThreadCount);

            // OK to spawn a new merge thread to handle this merge
            merger = getMergeThread(writer, merge);
            mergeThreads.add(merger);
            message(L"    launch new thread");

            merger->start();
            success = true;
        } catch (LuceneException& e) {
            finally = e;
        }
        if (!success) {
            writer->mergeFinish(merge);
        }
        finally.throwException();
    }
}
void SerialMergeScheduler::merge(const IndexWriterPtr& writer) {
    SyncLock syncLock(this);
    while (true) {
        OneMergePtr merge(writer->getNextMerge());
        if (!merge) {
            break;
        }
        writer->merge(merge);
    }
}