Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   package org.apache.lucene.index;

Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
  
  
  import java.io.Closeable;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
An IndexWriter creates and maintains an index.

The create argument to the constructor determines whether a new index is created, or whether an existing index is opened. Note that you can open an index with create=true even while readers are using the index. The old readers will continue to search the "point in time" snapshot they had opened, and won't see the newly created index until they re-open. There are also constructors with no create argument which will create a new index if there is not already an index at the provided path and otherwise open the existing index.

In either case, documents are added with addDocument and removed with deleteDocuments(org.apache.lucene.index.Term) or deleteDocuments(org.apache.lucene.search.Query). A document can be updated with updateDocument (which just deletes and then adds the entire document). When finished adding, deleting and updating documents, close should be called.

These changes are buffered in memory and periodically flushed to the org.apache.lucene.store.Directory (during the above method calls). A flush is triggered when there are enough buffered deletes (see setMaxBufferedDeleteTerms(int)) or enough added documents since the last flush, whichever is sooner. For the added documents, flushing is triggered either by RAM usage of the documents (see setRAMBufferSizeMB(double)) or the number of added documents. The default is to flush when RAM usage hits 16 MB. For best indexing speed you should flush by RAM usage with a large RAM buffer. Note that flushing just moves the internal buffered state in IndexWriter into the index, but these changes are not visible to IndexReader until either commit() or close() is called. A flush may also trigger one or more segment merges which by default run with a background thread so as not to block the addDocument calls (see below for changing the org.apache.lucene.index.MergeScheduler).

Opening an IndexWriter creates a lock file for the directory in use. Trying to open another IndexWriter on the same directory will lead to a org.apache.lucene.store.LockObtainFailedException. The org.apache.lucene.store.LockObtainFailedException is also thrown if an IndexReader on the same directory is used to delete documents from the index.

Expert: IndexWriter allows an optional org.apache.lucene.index.IndexDeletionPolicy implementation to be specified. You can use this to control when prior commits are deleted from the index. The default policy is org.apache.lucene.index.KeepOnlyLastCommitDeletionPolicy which removes all prior commits as soon as a new commit is done (this matches behavior before 2.2). Creating your own policy can allow you to explicitly keep previous "point in time" commits alive in the index for some time, to allow readers to refresh to the new commit without having the old commit deleted out from under them. This is necessary on filesystems like NFS that do not support "delete on last close" semantics, which Lucene's "point in time" search normally relies on.

Expert: IndexWriter allows you to separately change the org.apache.lucene.index.MergePolicy and the org.apache.lucene.index.MergeScheduler. The org.apache.lucene.index.MergePolicy is invoked whenever there are changes to the segments in the index. Its role is to select which merges to do, if any, and return a org.apache.lucene.index.MergePolicy.MergeSpecification describing the merges. The default is org.apache.lucene.index.LogByteSizeMergePolicy. Then, the org.apache.lucene.index.MergeScheduler is invoked with the requested merges and it decides when and how to run the merges. The default is org.apache.lucene.index.ConcurrentMergeScheduler.

NOTE: if you hit an OutOfMemoryError then IndexWriter will quietly record this fact and block all future segment commits. This is a defensive measure in case any internal state (buffered documents and deletions) were corrupted. Any subsequent calls to commit() will throw an IllegalStateException. The only course of action is to call close(), which internally will call rollback(), to undo any changes to the index since the last commit. You can also just call rollback() directly.

NOTE: IndexWriter instances are completely thread safe, meaning multiple threads can call any of its methods, concurrently. If your application requires external synchronization, you should not synchronize on the IndexWriter instance as this may cause deadlock; use your own (non-Lucene) objects instead.

NOTE: If you call Thread.interrupt() on a thread that's within IndexWriter, IndexWriter will try to catch this (eg, if it's in a wait() or Thread.sleep()), and will then throw the unchecked exception org.apache.lucene.util.ThreadInterruptedException and clear the interrupt status on the thread.

 
 
 /*
  * Clarification: Check Points (and commits)
  * IndexWriter writes new index files to the directory without writing a new segments_N
  * file which references these new files. It also means that the state of 
  * the in memory SegmentInfos object is different than the most recent
  * segments_N file written to the directory.
  * 
  * Each time the SegmentInfos is changed, and matches the (possibly 
  * modified) directory files, we have a new "check point". 
  * If the modified/new SegmentInfos is written to disk - as a new 
  * (generation of) segments_N file - this check point is also an 
  * IndexCommit.
  * 
  * A new checkpoint always replaces the previous checkpoint and 
  * becomes the new "front" of the index. This allows the IndexFileDeleter 
  * to delete files that are referenced only by stale checkpoints.
  * (files that were created since the last commit, but are no longer
  * referenced by the "front" of the index). For this, IndexFileDeleter 
  * keeps track of the last non commit checkpoint.
  */
 public class IndexWriter implements CloseableTwoPhaseCommit {

  
Default value for the write lock timeout (1,000).

 
 
   private long writeLockTimeout;

  
Name of the write lock in the index.
 
   public static final String WRITE_LOCK_NAME = "write.lock";

  
Value to denote a flush trigger is disabled

 
   public final static int DISABLE_AUTO_FLUSH = .;

  
Disabled by default (because IndexWriter flushes by RAM usage by default). Change using setMaxBufferedDocs(int).

 
Default value is 16 MB (which means flush when buffered docs consume 16 MB RAM). Change using setRAMBufferSizeMB(double).

 
   public final static double DEFAULT_RAM_BUFFER_SIZE_MB = .;

  
Disabled by default (because IndexWriter flushes by RAM usage by default). Change using setMaxBufferedDeleteTerms(int).

 
Default value is 10,000. Change using setMaxFieldLength(int).

 
   public final static int DEFAULT_MAX_FIELD_LENGTH = ..getLimit();

  
 
Absolute hard maximum length for a term. If a term arrives from the analyzer longer than this length, it is skipped and a message is printed to infoStream, if set (see setInfoStream(java.io.PrintStream)).
 
   public final static int MAX_TERM_LENGTH = .;
 
   // The normal read buffer size defaults to 1024, but
   // increasing this during merging seems to yield
   // performance gains.  However we don't want to increase
   // it too much because there are quite a few
   // BufferedIndexInputs created during merging.  See
   // LUCENE-888 for details.
   private final static int MERGE_READ_BUFFER_SIZE = 4096;
 
   // Used for printing messages
   private static final AtomicInteger MESSAGE_ID = new AtomicInteger();
   private int messageID = .getAndIncrement();
   volatile private boolean hitOOM;
 
   private final Directory directory;  // where this index resides
   private final Analyzer analyzer;    // how to analyze text
 
   // TODO 4.0: this should be made final once the setter is out
   private /*final*/Similarity similarity = Similarity.getDefault(); // how to normalize
 
   private volatile long changeCount// increments every time a change is completed
   private long lastCommitChangeCount// last changeCount that was committed
 
   private List<SegmentInforollbackSegments;      // list of segmentInfo we will fallback to if the commit fails
 
   volatile SegmentInfos pendingCommit;            // set when a commit is pending (after prepareCommit() & before commit())
   volatile long pendingCommitChangeCount;
 
   final SegmentInfos segmentInfos = new SegmentInfos();       // the segments
 
   private DocumentsWriter docWriter;
   private IndexFileDeleter deleter;
 
   // used by forceMerge to note those needing merging
   private int mergeMaxNumSegments;
 
   private Lock writeLock;
 
   private volatile boolean closed;
   private volatile boolean closing;
 
   // Holds all SegmentInfo instances currently involved in
   // merges
 
   private MergePolicy mergePolicy;
   // TODO 4.0: this should be made final once the setter is removed
   private /*final*/MergeScheduler mergeScheduler;
   private long mergeGen;
   private boolean stopMerges;
 
   private final AtomicInteger flushCount = new AtomicInteger();
   private final AtomicInteger flushDeletesCount = new AtomicInteger();
 
   final ReaderPool readerPool = new ReaderPool();
   
   // This is a "write once" variable (like the organic dye
   // on a DVD-R that may or may not be heated by a laser and
   // then cooled to permanently record the event): it's
   // false, until getReader() is called for the first time,
   // at which point it's switched to true and never changes
   // back to false.  Once this is true, we hold open and
   // reuse SegmentReader instances internally for applying
   // deletes, doing merges, and reopening near real-time
   // readers.
   private volatile boolean poolReaders;
 
   // The instance that was passed to the constructor. It is saved only in order
   // to allow users to query an IndexWriter settings.
   private final IndexWriterConfig config;
 
   // The PayloadProcessorProvider to use when segments are merged
 
   // for testing
   boolean anyNonBulkMerges;

  
Expert: returns a readonly reader, covering all committed as well as un-committed changes to the index. This provides "near real-time" searching, in that changes made during an IndexWriter session can be quickly made available for searching without closing the writer nor calling commit().

Note that this is functionally equivalent to calling {#flush} and then using org.apache.lucene.index.IndexReader.open(org.apache.lucene.store.Directory) to open a new reader. But the turarnound time of this method should be faster since it avoids the potentially costly commit().

You must close the org.apache.lucene.index.IndexReader returned by this method once you are done using it.

It's near real-time because there is no hard guarantee on how quickly you can get a new reader after making changes with IndexWriter. You'll have to experiment in your situation to determine if it's fast enough. As this is a new and experimental feature, please report back on your findings so we can learn, improve and iterate.

The resulting reader supports org.apache.lucene.index.IndexReader.reopen(), but that call will simply forward back to this method (though this may change in the future).

The very first time this method is called, this writer instance will make every effort to pool the readers that it opens for doing merges, applying deletes, etc. This means additional resources (RAM, file descriptors, CPU time) will be consumed.

For lower latency on reopening a reader, you should call setMergedSegmentWarmer(org.apache.lucene.index.IndexWriter.IndexReaderWarmer) to pre-warm a newly merged segment before it's committed to the index. This is important for minimizing index-to-search delay after a large merge.

If an addIndexes* call is running in another thread, then this reader will only search those segments from the foreign index that have been successfully copied over, so far

.

NOTE: Once the writer is closed, any outstanding readers may continue to be used. However, if you attempt to reopen any of those readers, you'll hit an org.apache.lucene.store.AlreadyClosedException.

Deprecated:
Please use org.apache.lucene.index.IndexReader.open(org.apache.lucene.index.IndexWriter,boolean) instead.
Returns:
IndexReader that covers entire index plus all changes made so far by this IndexWriter instance
Throws:
java.io.IOException
Lucene.experimental:
 
   public IndexReader getReader() throws IOException {
     return getReader(.getReaderTermsIndexDivisor(), true);
   }
 
   IndexReader getReader(boolean applyAllDeletesthrows IOException {
     return getReader(.getReaderTermsIndexDivisor(), applyAllDeletes);
   }

  
Expert: like getReader(), except you can specify which termInfosIndexDivisor should be used for any newly opened readers.

Deprecated:
Please use org.apache.lucene.index.IndexReader.open(org.apache.lucene.index.IndexWriter,boolean) instead. Furthermore, this method cannot guarantee the reader (and its sub-readers) will be opened with the termInfosIndexDivisor setting because some of them may have already been opened according to org.apache.lucene.index.IndexWriterConfig.setReaderTermsIndexDivisor(int). You should set the requested termInfosIndexDivisor through org.apache.lucene.index.IndexWriterConfig.setReaderTermsIndexDivisor(int) and use getReader().
Parameters:
termInfosIndexDivisor Subsamples which indexed terms are loaded into RAM. This has the same effect as setTermIndexInterval(int) except that setting must be done at indexing time while this setting can be set per reader. When set to N, then one in every N*termIndexInterval terms in the index is loaded into memory. By setting this to a value > 1 you can reduce memory usage, at the expense of higher latency when loading a TermInfo. The default value is 1. Set this to -1 to skip loading the terms index entirely.
 
   public IndexReader getReader(int termInfosIndexDivisorthrows IOException {
     return getReader(termInfosIndexDivisortrue);
   }
 
   IndexReader getReader(int termInfosIndexDivisorboolean applyAllDeletesthrows IOException {
     ensureOpen();
     
     final long tStart = System.currentTimeMillis();
 
     if ( != null) {
       message("flush at getReader");
     }
 
     // Do this up front before flushing so that the readers
     // obtained during this flush are pooled, the first time
     // this method is called:
      = true;
 
     // Prevent segmentInfos from changing while opening the
     // reader; in theory we could do similar retry logic,
     // just like we do when loading segments_N
     IndexReader r;
     synchronized(this) {
       flush(falseapplyAllDeletes);
       r = new ReadOnlyDirectoryReader(thistermInfosIndexDivisorapplyAllDeletes);
       if ( != null) {
         message("return reader version=" + r.getVersion() + " reader=" + r);
       }
     }
 
     maybeMerge();
 
     if ( != null) {
       message("getReader took " + (System.currentTimeMillis() - tStart) + " msec");
     }
     return r;
   }
 
   // Used for all SegmentReaders we open
 
     return ;
   }

  
Holds shared SegmentReader instances. IndexWriter uses SegmentReaders for 1) applying deletes, 2) doing merges, 3) handing out a real-time reader. This pool reuses instances of the SegmentReaders in all these places if it is in "near real-time mode" (getReader() has been called on this instance).
 
 
   class ReaderPool {
 
     private final Map<SegmentInfo,SegmentReaderreaderMap = new HashMap<SegmentInfo,SegmentReader>();

    
Forcefully clear changes for the specified segments. This is called on successful merge.
 
     synchronized void clear(List<SegmentInfoinfosthrows IOException {
       if (infos == null) {
         for (Map.Entry<SegmentInfo,SegmentReaderent.entrySet()) {
           ent.getValue(). = false;
         }
       } else {
         for (final SegmentInfo infoinfos) {
           final SegmentReader r = .get(info);
           if (r != null) {
             r.hasChanges = false;
           }
         }     
       }
     }
     
     // used only by asserts
     public synchronized boolean infoIsLive(SegmentInfo info) {
       int idx = .indexOf(info);
       assert idx != -1: "info=" + info + " isn't in pool";
       assert .info(idx) == info"info=" + info + " doesn't match live info in segmentInfos";
       return true;
     }
 
     public synchronized SegmentInfo mapToLive(SegmentInfo info) {
       int idx = .indexOf(info);
       if (idx != -1) {
         info = .info(idx);
       }
       return info;
     }
    
    
Release the segment reader (i.e. decRef it and close if there are no more references.

Parameters:
sr
Returns:
true if this release altered the index (eg the SegmentReader had pending changes to del docs and was closed). Caller must call checkpoint() if so.
Throws:
java.io.IOException
 
     public synchronized boolean release(SegmentReader srthrows IOException {
       return release(srfalse);
     }
    
    
Release the segment reader (i.e. decRef it and close if there are no more references.

Parameters:
sr
Returns:
true if this release altered the index (eg the SegmentReader had pending changes to del docs and was closed). Caller must call checkpoint() if so.
Throws:
java.io.IOException
 
     public synchronized boolean release(SegmentReader srboolean dropthrows IOException {
 
       final boolean pooled = .containsKey(sr.getSegmentInfo());
 
       assert !pooled || .get(sr.getSegmentInfo()) == sr;
 
       // Drop caller's ref; for an external reader (not
       // pooled), this decRef will close it
       sr.decRef();
 
       if (pooled && (drop || (! && sr.getRefCount() == 1))) {
 
         // We invoke deleter.checkpoint below, so we must be
         // sync'd on IW if there are changes:
         assert !sr.hasChanges || Thread.holdsLock(IndexWriter.this);
 
         // Discard (don't save) changes when we are dropping
         // the reader; this is used only on the sub-readers
         // after a successful merge.
         sr.hasChanges &= !drop;
 
         final boolean hasChanges = sr.hasChanges;
 
         // Drop our ref -- this will commit any pending
         // changes to the dir
         sr.close();
 
         // We are the last ref to this reader; since we're
         // not pooling readers, we release it:
         .remove(sr.getSegmentInfo());
 
         return hasChanges;
       }
 
       return false;
     }
 
     public synchronized void drop(List<SegmentInfoinfosthrows IOException {
       for(SegmentInfo info : infos) {
         drop(info);
       }
     }
 
     public synchronized void drop(SegmentInfo infothrows IOException {
       final SegmentReader sr = .get(info);
       if (sr != null) {
         sr.hasChanges = false;
         .remove(info);
         sr.close();
       }
     }
     
     public synchronized void dropAll() throws IOException {
       for(SegmentReader reader : .values()) {
         reader.hasChanges = false;
 
         // NOTE: it is allowed that this decRef does not
         // actually close the SR; this can happen when a
         // near real-time reader using this SR is still open
         reader.decRef();
       }
       .clear();
     }

    
Remove all our references to readers, and commits any pending changes.
 
     synchronized void close() throws IOException {
       // We invoke deleter.checkpoint below, so we must be
       // sync'd on IW:
       assert Thread.holdsLock(IndexWriter.this);
 
       for(Map.Entry<SegmentInfo,SegmentReaderent : .entrySet()) {
         
         SegmentReader sr = ent.getValue();
         if (sr.hasChanges) {
           assert infoIsLive(sr.getSegmentInfo());
           sr.doCommit(null);
 
           // Must checkpoint w/ deleter, because this
           // segment reader will have created new _X_N.del
           // file.
           .checkpoint(false);
         }
 
         // NOTE: it is allowed that this decRef does not
         // actually close the SR; this can happen when a
         // near real-time reader is kept open after the
         // IndexWriter instance is closed
         sr.decRef();
       }
 
       .clear();
     }
    
    
Commit all segment reader in the pool.

 
     synchronized void commit(SegmentInfos infosthrows IOException {
 
       // We invoke deleter.checkpoint below, so we must be
       // sync'd on IW:
       assert Thread.holdsLock(IndexWriter.this);
 
       for (SegmentInfo info : infos) {
 
         final SegmentReader sr = .get(info);
         if (sr != null && sr.hasChanges) {
           assert infoIsLive(info);
           sr.doCommit(null);
           // Must checkpoint w/ deleter, because this
           // segment reader will have created new _X_N.del
           // file.
           .checkpoint(false);
         }
       }
     }
    
    
Returns a ref to a clone. NOTE: this clone is not enrolled in the pool, so you should simply close() it when you're done (ie, do not call release()).
 
     public synchronized SegmentReader getReadOnlyClone(SegmentInfo infoboolean doOpenStoresint termInfosIndexDivisorthrows IOException {
       SegmentReader sr = get(infodoOpenStores.termInfosIndexDivisor);
       try {
         return (SegmentReadersr.clone(true);
       } finally {
         sr.decRef();
       }
     }
   
    
Obtain a SegmentReader from the readerPool. The reader must be returned by calling release(org.apache.lucene.index.SegmentReader)

Parameters:
info
doOpenStores
Throws:
java.io.IOException
See also:
release(org.apache.lucene.index.SegmentReader)
 
     public synchronized SegmentReader get(SegmentInfo infoboolean doOpenStoresthrows IOException {
       return get(infodoOpenStores..getReaderTermsIndexDivisor());
     }

    
Obtain a SegmentReader from the readerPool. The reader must be returned by calling release(org.apache.lucene.index.SegmentReader)

Parameters:
info
doOpenStores
readBufferSize
termsIndexDivisor
Throws:
java.io.IOException
See also:
release(org.apache.lucene.index.SegmentReader)
 
     public synchronized SegmentReader get(SegmentInfo infoboolean doOpenStoresint readBufferSizeint termsIndexDivisorthrows IOException {
 
       if () {
         readBufferSize = .;
       }
 
       SegmentReader sr = .get(info);
       if (sr == null) {
         // TODO: we may want to avoid doing this while
         // synchronized
         // Returns a ref, which we xfer to readerMap:
         sr = SegmentReader.get(falseinfo.dirinforeadBufferSizedoOpenStorestermsIndexDivisor);
         sr.readerFinishedListeners = ;
 
         if (info.dir == ) {
           // Only pool if reader is not external
           .put(infosr);
         }
       } else {
         if (doOpenStores) {
           sr.openDocStores();
         }
         if (termsIndexDivisor != -1 && !sr.termsIndexLoaded()) {
           // If this reader was originally opened because we
           // needed to merge it, we didn't load the terms
           // index.  But now, if the caller wants the terms
           // index (eg because it's doing deletes, or an NRT
           // reader is being opened) we ask the reader to
           // load its terms index.
           sr.loadTermsIndex(termsIndexDivisor);
         }
       }
 
       // Return a ref to our caller
       if (info.dir == ) {
         // Only incRef if we pooled (reader is not external)
         sr.incRef();
       }
       return sr;
     }
 
     // Returns a ref
     public synchronized SegmentReader getIfExists(SegmentInfo infothrows IOException {
       SegmentReader sr = .get(info);
       if (sr != null) {
         sr.incRef();
       }
       return sr;
     }
   }
  
  
  
  
Obtain the number of deleted docs for a pooled reader. If the reader isn't being pooled, the segmentInfo's delCount is returned.
 
   public int numDeletedDocs(SegmentInfo infothrows IOException {
     ensureOpen(false);
     SegmentReader reader = .getIfExists(info);
     try {
       if (reader != null) {
         return reader.numDeletedDocs();
       } else {
         return info.getDelCount();
       }
     } finally {
       if (reader != null) {
         .release(reader);
       }
     }
   }
  
  
Used internally to throw an org.apache.lucene.store.AlreadyClosedException if this IndexWriter has been closed.

Throws:
org.apache.lucene.store.AlreadyClosedException if this IndexWriter is closed
 
   protected final void ensureOpen(boolean includePendingClosethrows AlreadyClosedException {
     if ( || (includePendingClose && )) {
       throw new AlreadyClosedException("this IndexWriter is closed");
     }
   }
 
   protected final void ensureOpen() throws AlreadyClosedException {
     ensureOpen(true);
   }

  
Prints a message to the infoStream (if non-null), prefixed with the identifying information for this writer and the thread that's calling it.
 
   public void message(String message) {
     if ( != null)
       .println("IW " +  + " [" + new Date() + "; " + Thread.currentThread().getName() + "]: " + message);
   }

  
Casts current mergePolicy to LogMergePolicy, and throws an exception if the mergePolicy is not a LogMergePolicy.
 
     if ( instanceof LogMergePolicy)
       return (LogMergePolicy;
     else
       throw new IllegalArgumentException("this method can only be called when the merge policy is the default LogMergePolicy");
   }

  

Get the current setting of whether newly flushed segments will use the compound file format. Note that this just returns the value previously set with setUseCompoundFile(boolean), or the default value (true). You cannot use this to query the status of previously flushed segments.

Note that this method is a convenience method: it just calls mergePolicy.getUseCompoundFile as long as mergePolicy is an instance of org.apache.lucene.index.LogMergePolicy. Otherwise an IllegalArgumentException is thrown.

 
   public boolean getUseCompoundFile() {
   }

  

Setting to turn on usage of a compound file. When on, multiple files for each segment are merged into a single file when a new segment is flushed.

Note that this method is a convenience method: it just calls mergePolicy.setUseCompoundFile as long as mergePolicy is an instance of org.apache.lucene.index.LogMergePolicy. Otherwise an IllegalArgumentException is thrown.

 
   public void setUseCompoundFile(boolean value) {
   }

  
 
   public void setSimilarity(Similarity similarity) {
     ensureOpen();
     this. = similarity;
     .setSimilarity(similarity);
     // Required so config.getSimilarity returns the right value. But this will
     // go away together with the method in 4.0.
     .setSimilarity(similarity);
   }

  
Expert: Return the Similarity implementation used by this IndexWriter.

This defaults to the current value of org.apache.lucene.search.Similarity.getDefault().

 
   public Similarity getSimilarity() {
     ensureOpen();
     return ;
   }

  
Expert: Set the interval between indexed terms. Large values cause less memory to be used by IndexReader, but slow random-access to terms. Small values cause more memory to be used by an IndexReader, and speed random-access to terms. This parameter determines the amount of computation required per query term, regardless of the number of documents that contain that term. In particular, it is the maximum number of other terms that must be scanned before a term is located and its frequency and position information may be processed. In a large index with user-entered query terms, query processing time is likely to be dominated not by term lookup but rather by the processing of frequency and positional data. In a small index or when many uncommon query terms are generated (e.g., by wildcard queries) term lookup may become a dominant cost. In particular, numUniqueTerms/interval terms are read into memory by an IndexReader, and, on average, interval/2 terms must be scanned for each random term access.

 
   public void setTermIndexInterval(int interval) {
     ensureOpen();
     .setTermIndexInterval(interval);
   }

  
Expert: Return the interval between indexed terms.

 
   public int getTermIndexInterval() {
     // We pass false because this method is called by SegmentMerger while we are in the process of closing
     ensureOpen(false);
     return .getTermIndexInterval();
   }

  
Constructs an IndexWriter for the index in d. Text will be analyzed with a. If create is true, then a new, empty index will be created in d, replacing the index already there, if any.

Deprecated:
use IndexWriter(org.apache.lucene.store.Directory,org.apache.lucene.index.IndexWriterConfig) instead
Parameters:
d the index directory
a the analyzer to use
create true to create the index or overwrite the existing one; false to append to the existing index
mfl Maximum field length in number of terms/tokens: LIMITED, UNLIMITED, or user-specified via the MaxFieldLength constructor.
Throws:
org.apache.lucene.index.CorruptIndexException if the index is corrupt
org.apache.lucene.store.LockObtainFailedException if another writer has this index open (write.lock could not be obtained)
java.io.IOException if the directory cannot be read/written to, or if it does not exist and create is false or if there is any other low-level IO error
 
   public IndexWriter(Directory dAnalyzer aboolean createMaxFieldLength mfl)
         create ? . : .));
     setMaxFieldLength(mfl.getLimit());
   }

  
Constructs an IndexWriter for the index in d, first creating it if it does not already exist. Text will be analyzed with a.

Deprecated:
use IndexWriter(org.apache.lucene.store.Directory,org.apache.lucene.index.IndexWriterConfig) instead
Parameters:
d the index directory
a the analyzer to use
mfl Maximum field length in number of terms/tokens: LIMITED, UNLIMITED, or user-specified via the MaxFieldLength constructor.
Throws:
org.apache.lucene.index.CorruptIndexException if the index is corrupt
org.apache.lucene.store.LockObtainFailedException if another writer has this index open (write.lock could not be obtained)
java.io.IOException if the directory cannot be read/written to or if there is any other low-level IO error
 
   public IndexWriter(Directory dAnalyzer aMaxFieldLength mfl)
     this(dnew IndexWriterConfig(.a));
     setMaxFieldLength(mfl.getLimit());
   }

  
Expert: constructs an IndexWriter with a custom org.apache.lucene.index.IndexDeletionPolicy, for the index in d, first creating it if it does not already exist. Text will be analyzed with a.

Deprecated:
use IndexWriter(org.apache.lucene.store.Directory,org.apache.lucene.index.IndexWriterConfig) instead
Parameters:
d the index directory
a the analyzer to use
deletionPolicy see above
mfl whether or not to limit field lengths
Throws:
org.apache.lucene.index.CorruptIndexException if the index is corrupt
org.apache.lucene.store.LockObtainFailedException if another writer has this index open (write.lock could not be obtained)
java.io.IOException if the directory cannot be read/written to or if there is any other low-level IO error
 
   public IndexWriter(Directory dAnalyzer aIndexDeletionPolicy deletionPolicyMaxFieldLength mfl)
     this(dnew IndexWriterConfig(.a).setIndexDeletionPolicy(deletionPolicy));
     setMaxFieldLength(mfl.getLimit());
   }

  
Expert: constructs an IndexWriter with a custom org.apache.lucene.index.IndexDeletionPolicy, for the index in d. Text will be analyzed with a. If create is true, then a new, empty index will be created in d, replacing the index already there, if any.

Deprecated:
use IndexWriter(org.apache.lucene.store.Directory,org.apache.lucene.index.IndexWriterConfig) instead
Parameters:
d the index directory
a the analyzer to use
create true to create the index or overwrite the existing one; false to append to the existing index
deletionPolicy see above
mfl IndexWriter.MaxFieldLength, whether or not to limit field lengths. Value is in number of terms/tokens
Throws:
org.apache.lucene.index.CorruptIndexException if the index is corrupt
org.apache.lucene.store.LockObtainFailedException if another writer has this index open (write.lock could not be obtained)
java.io.IOException if the directory cannot be read/written to, or if it does not exist and create is false or if there is any other low-level IO error
  public IndexWriter(Directory dAnalyzer aboolean createIndexDeletionPolicy deletionPolicyMaxFieldLength mfl)
        create ? . : .).setIndexDeletionPolicy(deletionPolicy));
  }
  
  
Expert: constructs an IndexWriter on specific commit point, with a custom org.apache.lucene.index.IndexDeletionPolicy, for the index in d. Text will be analyzed with a.

This is only meaningful if you've used a org.apache.lucene.index.IndexDeletionPolicy in that past that keeps more than just the last commit.

This operation is similar to rollback(), except that method can only rollback what's been done with the current instance of IndexWriter since its last commit, whereas this method can rollback to an arbitrary commit point from the past, assuming the org.apache.lucene.index.IndexDeletionPolicy has preserved past commits.

Deprecated:
use IndexWriter(org.apache.lucene.store.Directory,org.apache.lucene.index.IndexWriterConfig) instead
Parameters:
d the index directory
a the analyzer to use
deletionPolicy see above
mfl whether or not to limit field lengths, value is in number of terms/tokens. See IndexWriter.MaxFieldLength.
commit which commit to open
Throws:
org.apache.lucene.index.CorruptIndexException if the index is corrupt
org.apache.lucene.store.LockObtainFailedException if another writer has this index open (write.lock could not be obtained)
java.io.IOException if the directory cannot be read/written to, or if it does not exist and create is false or if there is any other low-level IO error
  public IndexWriter(Directory dAnalyzer aIndexDeletionPolicy deletionPolicyMaxFieldLength mflIndexCommit commit)
    this(dnew IndexWriterConfig(.a)
        .setOpenMode(.).setIndexDeletionPolicy(deletionPolicy).setIndexCommit(commit));
  }

  
Constructs a new IndexWriter per the settings given in conf. Note that the passed in org.apache.lucene.index.IndexWriterConfig is privately cloned; if you need to make subsequent "live" changes to the configuration use getConfig().

Parameters:
d the index directory. The index is either created or appended according conf.getOpenMode().
conf the configuration settings according to which IndexWriter should be initialized.
Throws:
org.apache.lucene.index.CorruptIndexException if the index is corrupt
org.apache.lucene.store.LockObtainFailedException if another writer has this index open (write.lock could not be obtained)
java.io.IOException if the directory cannot be read/written to, or if it does not exist and conf.getOpenMode() is OpenMode.APPEND or if there is any other low-level IO error
     = (IndexWriterConfigconf.clone();
     = d;
     = conf.getAnalyzer();
     = conf.getSimilarity();
     = conf.getMergePolicy();
     = conf.getReaderPooling();
    if (!.obtain()) // obtain write lock
      throw new LockObtainFailedException("Index locked for write: " + );
    OpenMode mode = conf.getOpenMode();
    boolean create;
    if (mode == .) {
      create = true;
    } else if (mode == .) {
      create = false;
    } else {
      // CREATE_OR_APPEND - create only if an index does not exist
      create = !IndexReader.indexExists();
    }
    
    boolean success = false;
    // TODO: we should check whether this index is too old,
    // and throw an IndexFormatTooOldExc up front, here,
    // instead of later when merge, applyDeletes, getReader
    // is attempted.  I think to do this we should store the
    // oldest segment's version in segments_N.
    try {
      if (create) {
        // Try to read first.  This is to allow create
        // against an index that's currently open for
        // searching.  In this case we write the next
        // segments_N file with no segments:
        try {
          .read();
          .clear();
        } catch (IOException e) {
          // Likely this means it's a fresh directory
        }
        // Record that we have a change (zero out all
        // segments) pending:
        ++;
        .changed();
      } else {
        .read();
        IndexCommit commit = conf.getIndexCommit();
        if (commit != null) {
          // Swap out all segments, but, keep metadata in
          // SegmentInfos, like version & generation, to
          // preserve write-once.  This is important if
          // readers are open against the future commit
          // points.
          if (commit.getDirectory() != )
            throw new IllegalArgumentException("IndexCommit's directory doesn't match my directory");
          SegmentInfos oldInfos = new SegmentInfos();
          oldInfos.read(commit.getSegmentsFileName());
          .replace(oldInfos);
          ++;
          .changed();
          if ( != null)
            message("init: loaded commit \"" + commit.getSegmentsFileName() + "\"");
        }
      }
      // Default deleter (for backwards compatibility) is
      // KeepOnlyLastCommitDeleter:
      synchronized(this) {
         = new IndexFileDeleter(,
                                       conf.getIndexDeletionPolicy(),
                                       ,
                                       this);
      }
      if (.) {
        // Deletion policy deleted the "head" commit point.
        // We have to mark ourself as changed so that if we
        // are closed w/o any further changes we write a new
        // segments_N file.
        ++;
        .changed();
      }
      if ( != null) {
        messageState();
      }
      success = true;
    } finally {
      if (!success) {
        if ( != null) {
          message("init: hit exception on init; releasing write lock");
        }
        try {
          .release();
        } catch (Throwable t) {
          // don't mask the original exception
        }
         = null;
      }
    }
  }
  private FieldInfos getFieldInfos(SegmentInfo infothrows IOException {
    Directory cfsDir = null;
    try {
      if (info.getUseCompoundFile()) {
        cfsDir = new CompoundFileReader(, IndexFileNames.segmentFileName(info.name.));
      } else {
        cfsDir = ;
      }
      return new FieldInfos(cfsDir, IndexFileNames.segmentFileName(info.name.));
    } finally {
      if (info.getUseCompoundFile() && cfsDir != null) {
        cfsDir.close();
      }
    }
  }
  private FieldInfos getCurrentFieldInfos() throws IOException {
    final FieldInfos fieldInfos;
    if (.size() > 0) {
        // Pre-3.1 index.  In this case we sweep all
        // segments, merging their FieldInfos:
        fieldInfos = new FieldInfos();
        for(SegmentInfo info : ) {
          final FieldInfos segFieldInfos = getFieldInfos(info);
          final int fieldCount = segFieldInfos.size();
          for(int fieldNumber=0;fieldNumber<fieldCount;fieldNumber++) {
            fieldInfos.add(segFieldInfos.fieldInfo(fieldNumber));
          }
        }
      } else {
        // Already a 3.1 index; just seed the FieldInfos
        // from the last segment
        fieldInfos = getFieldInfos(.info(.size()-1));
      }
    } else {
      fieldInfos = new FieldInfos();
    }
    return fieldInfos;
  }

  
Returns the private org.apache.lucene.index.IndexWriterConfig, cloned from the org.apache.lucene.index.IndexWriterConfig passed to IndexWriter(org.apache.lucene.store.Directory,org.apache.lucene.index.IndexWriterConfig).

NOTE: some settings may be changed on the returned org.apache.lucene.index.IndexWriterConfig, and will take effect in the current IndexWriter instance. See the javadocs for the specific setters in org.apache.lucene.index.IndexWriterConfig for details.

    ensureOpen(false);
    return ;
  }
  
  
Expert: set the merge policy used by this writer.

  public void setMergePolicy(MergePolicy mp) {
    ensureOpen();
    if (mp == null)
      throw new NullPointerException("MergePolicy must be non-null");
    if ( != mp)
      .close();
     = mp;
    if ( != null)
      message("setMergePolicy " + mp);
    // Required so config.getMergePolicy returns the right value. But this will
    // go away together with the method in 4.0.
  }

  
Expert: returns the current MergePolicy in use by this writer.

    ensureOpen();
    return ;
  }

  
Expert: set the merge scheduler used by this writer.

  synchronized public void setMergeScheduler(MergeScheduler mergeSchedulerthrows CorruptIndexExceptionIOException {
    ensureOpen();
    if (mergeScheduler == null)
      throw new NullPointerException("MergeScheduler must be non-null");
    if (this. != mergeScheduler) {
      finishMerges(true);
      this..close();
    }
    this. = mergeScheduler;
    if ( != null)
      message("setMergeScheduler " + mergeScheduler);
    // Required so config.getMergeScheduler returns the right value. But this will
    // go away together with the method in 4.0.
    .setMergeScheduler(mergeScheduler);
  }

  
Expert: returns the current MergeScheduler in use by this writer.

    ensureOpen();
    return ;
  }

  

Determines the largest segment (measured by document count) that may be merged with other segments. Small values (e.g., less than 10,000) are best for interactive indexing, as this limits the length of pauses while indexing to a few seconds. Larger values are best for batched indexing and speedier searches.

The default value is java.lang.Integer.MAX_VALUE.

Note that this method is a convenience method: it just calls mergePolicy.setMaxMergeDocs as long as mergePolicy is an instance of org.apache.lucene.index.LogMergePolicy. Otherwise an IllegalArgumentException is thrown.

The default merge policy (org.apache.lucene.index.LogByteSizeMergePolicy) also allows you to set this limit by net size (in MB) of the segment, using org.apache.lucene.index.LogByteSizeMergePolicy.setMaxMergeMB(double).

  public void setMaxMergeDocs(int maxMergeDocs) {
    getLogMergePolicy().setMaxMergeDocs(maxMergeDocs);
  }

  

Returns the largest segment (measured by document count) that may be merged with other segments.

Note that this method is a convenience method: it just calls mergePolicy.getMaxMergeDocs as long as mergePolicy is an instance of org.apache.lucene.index.LogMergePolicy. Otherwise an IllegalArgumentException is thrown.

  public int getMaxMergeDocs() {
  }

  
The maximum number of terms that will be indexed for a single field in a document. This limits the amount of memory required for indexing, so that collections with very large files will not crash the indexing process by running out of memory. This setting refers to the number of running terms, not to the number of different terms.

Note: this silently truncates large documents, excluding from the index all terms that occur further in the document. If you know your source documents are large, be sure to set this value high enough to accomodate the expected size. If you set it to Integer.MAX_VALUE, then the only limit is your memory, but you should anticipate an OutOfMemoryError.

By default, no more than DEFAULT_MAX_FIELD_LENGTH terms will be indexed for a field.

Deprecated:
use org.apache.lucene.analysis.LimitTokenCountAnalyzer instead. Note that the behvaior slightly changed - the analyzer limits the number of tokens per token stream created, while this setting limits the total number of tokens to index. This only matters if you index many multi-valued fields though.
  public void setMaxFieldLength(int maxFieldLength) {
    ensureOpen();
    this. = maxFieldLength;
    .setMaxFieldLength(maxFieldLength);
    if ( != null)
      message("setMaxFieldLength " + maxFieldLength);
  }

  
Returns the maximum number of terms that will be indexed for a single field in a document.

Deprecated:
use org.apache.lucene.analysis.LimitTokenCountAnalyzer to limit number of tokens.
See also:
setMaxFieldLength(int)
  public int getMaxFieldLength() {
    ensureOpen();
    return ;
  }

  
  public void setReaderTermsIndexDivisor(int divisor) {
    ensureOpen();
    if ( != null) {
      message("setReaderTermsIndexDivisor " + divisor);
    }
  }

  
  public int getReaderTermsIndexDivisor() {
    ensureOpen();
  }

  
Determines the minimal number of documents required before the buffered in-memory documents are flushed as a new Segment. Large values generally gives faster indexing.

When this is set, the writer will flush every maxBufferedDocs added documents. Pass in DISABLE_AUTO_FLUSH to prevent triggering a flush due to number of buffered documents. Note that if flushing by RAM usage is also enabled, then the flush will be triggered by whichever comes first.

Disabled by default (writer flushes by RAM usage).

Deprecated:
use org.apache.lucene.index.IndexWriterConfig.setMaxBufferedDocs(int) instead.
Throws:
java.lang.IllegalArgumentException if maxBufferedDocs is enabled but smaller than 2, or it disables maxBufferedDocs when ramBufferSize is already disabled
See also:
setRAMBufferSizeMB(double)
  public void setMaxBufferedDocs(int maxBufferedDocs) {
    ensureOpen();
    if ( != null) {
      message("setMaxBufferedDocs " + maxBufferedDocs);
    }
    // Required so config.getMaxBufferedDocs returns the right value. But this
    // will go away together with the method in 4.0.
    .setMaxBufferedDocs(maxBufferedDocs);
  }

  
If we are flushing by doc count (not by RAM usage), and using LogDocMergePolicy then push maxBufferedDocs down as its minMergeDocs, to keep backwards compatibility.
  private void pushMaxBufferedDocs() {
      final MergePolicy mp = ;
      if (mp instanceof LogDocMergePolicy) {
        LogDocMergePolicy lmp = (LogDocMergePolicymp;
        final int maxBufferedDocs = .getMaxBufferedDocs();
        if (lmp.getMinMergeDocs() != maxBufferedDocs) {
          if ( != null)
            message("now push maxBufferedDocs " + maxBufferedDocs + " to LogDocMergePolicy");
          lmp.setMinMergeDocs(maxBufferedDocs);
        }
      }
    }
  }

  
Returns the number of buffered added documents that will trigger a flush if enabled.

  public int getMaxBufferedDocs() {
    ensureOpen();
    return .getMaxBufferedDocs();
  }

  
Determines the amount of RAM that may be used for buffering added documents and deletions before they are flushed to the Directory. Generally for faster indexing performance it's best to flush by RAM usage instead of document count and use as large a RAM buffer as you can.

When this is set, the writer will flush whenever buffered documents and deletions use this much RAM. Pass in DISABLE_AUTO_FLUSH to prevent triggering a flush due to RAM usage. Note that if flushing by document count is also enabled, then the flush will be triggered by whichever comes first.

NOTE: the account of RAM usage for pending deletions is only approximate. Specifically, if you delete by Query, Lucene currently has no way to measure the RAM usage if individual Queries so the accounting will under-estimate and you should compensate by either calling commit() periodically yourself, or by using setMaxBufferedDeleteTerms(int) to flush by count instead of RAM usage (each buffered delete Query counts as one).

NOTE: because IndexWriter uses ints when managing its internal storage, the absolute maximum value for this setting is somewhat less than 2048 MB. The precise limit depends on various factors, such as how large your documents are, how many fields have norms, etc., so it's best to set this value comfortably under 2048.

The default value is DEFAULT_RAM_BUFFER_SIZE_MB.

Deprecated:
use org.apache.lucene.index.IndexWriterConfig.setRAMBufferSizeMB(double) instead.
Throws:
java.lang.IllegalArgumentException if ramBufferSize is enabled but non-positive, or it disables ramBufferSize when maxBufferedDocs is already disabled
  public void setRAMBufferSizeMB(double mb) {
    if ( != null) {
      message("setRAMBufferSizeMB " + mb);
    }
    // Required so config.getRAMBufferSizeMB returns the right value. But this
    // will go away together with the method in 4.0.
  }

  
Returns the value set by setRAMBufferSizeMB(double) if enabled.

  public double getRAMBufferSizeMB() {
    return .getRAMBufferSizeMB();
  }

  

Determines the minimal number of delete terms required before the buffered in-memory delete terms are applied and flushed. If there are documents buffered in memory at the time, they are merged and a new segment is created.

Disabled by default (writer flushes by RAM usage).

Deprecated:
use org.apache.lucene.index.IndexWriterConfig.setMaxBufferedDeleteTerms(int) instead.
Throws:
java.lang.IllegalArgumentException if maxBufferedDeleteTerms is enabled but smaller than 1
See also:
setRAMBufferSizeMB(double)
  public void setMaxBufferedDeleteTerms(int maxBufferedDeleteTerms) {
    ensureOpen();
    if ( != null)
      message("setMaxBufferedDeleteTerms " + maxBufferedDeleteTerms);
    // Required so config.getMaxBufferedDeleteTerms returns the right value. But
    // this will go away together with the method in 4.0.
    .setMaxBufferedDeleteTerms(maxBufferedDeleteTerms);
  }

  
Returns the number of buffered deleted terms that will trigger a flush if enabled.

  public int getMaxBufferedDeleteTerms() {
    ensureOpen();
  }

  
Determines how often segment indices are merged by addDocument(). With smaller values, less RAM is used while indexing, and searches on unoptimized indices are faster, but indexing speed is slower. With larger values, more RAM is used during indexing, and while searches on unoptimized indices are slower, indexing is faster. Thus larger values (> 10) are best for batch index creation, and smaller values (< 10) for indices that are interactively maintained.

Note that this method is a convenience method: it just calls mergePolicy.setMergeFactor as long as mergePolicy is an instance of org.apache.lucene.index.LogMergePolicy. Otherwise an IllegalArgumentException is thrown.

This must never be less than 2. The default value is 10.

  public void setMergeFactor(int mergeFactor) {
    getLogMergePolicy().setMergeFactor(mergeFactor);
  }

  

Returns the number of segments that are merged at once and also controls the total number of segments allowed to accumulate in the index.

Note that this method is a convenience method: it just calls mergePolicy.getMergeFactor as long as mergePolicy is an instance of org.apache.lucene.index.LogMergePolicy. Otherwise an IllegalArgumentException is thrown.

  public int getMergeFactor() {
  }

  
If non-null, this will be the default infoStream used by a newly instantiated IndexWriter.

  public static void setDefaultInfoStream(PrintStream infoStream) {
    . = infoStream;
  }

  
Returns the current default infoStream for newly instantiated IndexWriters.

  public static PrintStream getDefaultInfoStream() {
  }

  
If non-null, information about merges, deletes and a message when maxFieldLength is reached will be printed to this.
  public void setInfoStream(PrintStream infoStreamthrows IOException {
    ensureOpen();
    this. = infoStream;
    .setInfoStream(infoStream);
    .setInfoStream(infoStream);
    if (infoStream != null)
      messageState();
  }
  private void messageState() throws IOException {
    message("\ndir=" +  + "\n" +
            "index=" + segString() + "\n" +
            "version=" + . + "\n" +
            .toString());
  }

  
Returns the current infoStream in use by this writer.

  public PrintStream getInfoStream() {
    ensureOpen();
    return ;
  }

  
Returns true if verbosing is enabled (i.e., infoStream != null).
  public boolean verbose() {
    return  != null;
  }
  
  
Sets the maximum time to wait for a write lock (in milliseconds) for this instance of IndexWriter.

Deprecated:
use org.apache.lucene.index.IndexWriterConfig.setWriteLockTimeout(long) instead
See also:
setDefaultWriteLockTimeout(long) to change the default value for all instances of IndexWriter.
  public void setWriteLockTimeout(long writeLockTimeout) {
    ensureOpen();
    this. = writeLockTimeout;
    // Required so config.getWriteLockTimeout returns the right value. But this
    // will go away together with the method in 4.0.
    .setWriteLockTimeout(writeLockTimeout);
  }

  
Returns allowed timeout when acquiring the write lock.

  public long getWriteLockTimeout() {
    ensureOpen();
    return ;
  }

  
Sets the default (for any instance of IndexWriter) maximum time to wait for a write lock (in milliseconds).

  public static void setDefaultWriteLockTimeout(long writeLockTimeout) {
    IndexWriterConfig.setDefaultWriteLockTimeout(writeLockTimeout);
  }

  
Returns default write lock timeout for newly instantiated IndexWriters.

  public static long getDefaultWriteLockTimeout() {
    return IndexWriterConfig.getDefaultWriteLockTimeout();
  }

  
Commits all changes to an index and closes all associated files. Note that this may be a costly operation, so, try to re-use a single writer instead of closing and opening a new one. See commit() for caveats about write caching done by some IO devices.

If an Exception is hit during close, eg due to disk full or some other reason, then both the on-disk index and the internal state of the IndexWriter instance will be consistent. However, the close will not be complete even though part of it (flushing buffered documents) may have succeeded, so the write lock will still be held.

If you can correct the underlying cause (eg free up some disk space) then you can call close() again. Failing that, if you want to force the write lock to be released (dangerous, because you may then lose buffered docs in the IndexWriter instance) then you can do something like this:

 try {
   writer.close();
 } finally {
   if (IndexWriter.isLocked(directory)) {
     IndexWriter.unlock(directory);
   }
 }
 
after which, you must be certain not to use the writer instance anymore.

NOTE: if this method hits an OutOfMemoryError you should immediately close the writer, again. See above for details.

Throws:
org.apache.lucene.index.CorruptIndexException if the index is corrupt
java.io.IOException if there is a low-level IO error
  public void close() throws CorruptIndexExceptionIOException {
    close(true);
  }

  
Closes the index with or without waiting for currently running merges to finish. This is only meaningful when using a MergeScheduler that runs merges in background threads.

NOTE: if this method hits an OutOfMemoryError you should immediately close the writer, again. See above for details.

NOTE: it is dangerous to always call close(false), especially when IndexWriter is not open for very long, because this can result in "merge starvation" whereby long merges will never have a chance to finish. This will cause too many segments in your index over time.

Parameters:
waitForMerges if true, this call will block until all merges complete; else, it will ask all running merges to abort, wait until those merges have finished (which should be at most a few seconds), and then return.
  public void close(boolean waitForMergesthrows CorruptIndexExceptionIOException {
    // Ensure that only one thread actually gets to do the closing:
    if (shouldClose()) {
      // If any methods have hit OutOfMemoryError, then abort
      // on close, in case the internal state of IndexWriter
      // or DocumentsWriter is corrupt
      if ()