Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 918874) +++ CHANGES.txt (working copy) @@ -76,6 +76,15 @@ use by external code. In addition it offers a matchExtension method which callers can use to query whether a certain file matches a certain extension. (Shai Erera via Mike McCandless) + +* LUCENE-2294: IndexWriter constructors have been deprecated in favor of a + single ctor which accepts IndexWriterConfig and a Directory. You can set all + the parameters related to IndexWriter on IndexWriterConfig. The different + setter/getter methods were deprecated as well. One should call + writer.getConfig().getXYZ() to query for a parameter XYZ. + Additionally, the setter/getter related to MergePolicy were deprecated as + well. One should interact with the MergePolicy directly. + (Shai Erera via ?) Bug fixes Index: src/java/org/apache/lucene/index/DocumentsWriter.java =================================================================== --- src/java/org/apache/lucene/index/DocumentsWriter.java (revision 918874) +++ src/java/org/apache/lucene/index/DocumentsWriter.java (working copy) @@ -182,7 +182,7 @@ abstract DocConsumer getChain(DocumentsWriter documentsWriter); } - static final IndexingChain DefaultIndexingChain = new IndexingChain() { + static final IndexingChain defaultIndexingChain = new IndexingChain() { @Override DocConsumer getChain(DocumentsWriter documentsWriter) { @@ -260,13 +260,13 @@ private boolean closed; - DocumentsWriter(Directory directory, IndexWriter writer, IndexingChain indexingChain) throws IOException { + DocumentsWriter(Directory directory, IndexWriter writer) throws IOException { this.directory = directory; this.writer = writer; this.similarity = writer.getSimilarity(); flushedDocCount = writer.maxDoc(); - consumer = indexingChain.getChain(this); + consumer = defaultIndexingChain.getChain(this); if (consumer instanceof DocFieldProcessor) { docFieldProcessor = (DocFieldProcessor) consumer; } Index: src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriter.java (revision 918874) +++ src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -19,7 +19,7 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; -import org.apache.lucene.index.DocumentsWriter.IndexingChain; +import org.apache.lucene.index.IndexWriterConfig.OpenMode; import org.apache.lucene.search.Similarity; import org.apache.lucene.search.Query; import org.apache.lucene.store.Directory; @@ -29,6 +29,7 @@ import org.apache.lucene.store.BufferedIndexInput; import org.apache.lucene.util.Constants; import org.apache.lucene.util.ThreadInterruptedException; +import org.apache.lucene.util.Version; import java.io.IOException; import java.io.Closeable; @@ -179,10 +180,11 @@ /** * Default value for the write lock timeout (1,000). * @see #setDefaultWriteLockTimeout + * @deprecated use {@link IndexWriterConfig#WRITE_LOCK_TIMEOUT} instead */ - public static long WRITE_LOCK_TIMEOUT = 1000; + public static long WRITE_LOCK_TIMEOUT = IndexWriterConfig.WRITE_LOCK_TIMEOUT; - private long writeLockTimeout = WRITE_LOCK_TIMEOUT; + private long writeLockTimeout; /** * Name of the write lock in the index. @@ -191,36 +193,43 @@ /** * Value to denote a flush trigger is disabled + * @deprecated use {@link IndexWriterConfig#DISABLE_AUTO_FLUSH} instead */ - public final static int DISABLE_AUTO_FLUSH = -1; + public final static int DISABLE_AUTO_FLUSH = IndexWriterConfig.DISABLE_AUTO_FLUSH; /** * Disabled by default (because IndexWriter flushes by RAM usage * by default). Change using {@link #setMaxBufferedDocs(int)}. + * @deprecated use {@link IndexWriterConfig#DEFAULT_MAX_BUFFERED_DOCS} instead. */ - public final static int DEFAULT_MAX_BUFFERED_DOCS = DISABLE_AUTO_FLUSH; + public final static int DEFAULT_MAX_BUFFERED_DOCS = IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS; /** * Default value is 16 MB (which means flush when buffered * docs consume 16 MB RAM). Change using {@link #setRAMBufferSizeMB}. + * @deprecated use {@link IndexWriterConfig#DEFAULT_RAM_BUFFER_SIZE_MB} instead. */ - public final static double DEFAULT_RAM_BUFFER_SIZE_MB = 16.0; + public final static double DEFAULT_RAM_BUFFER_SIZE_MB = IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB; /** * Disabled by default (because IndexWriter flushes by RAM usage * by default). Change using {@link #setMaxBufferedDeleteTerms(int)}. + * @deprecated use {@link IndexWriterConfig#DEFAULT_MAX_BUFFERED_DELETE_TERMS} instead */ - public final static int DEFAULT_MAX_BUFFERED_DELETE_TERMS = DISABLE_AUTO_FLUSH; + public final static int DEFAULT_MAX_BUFFERED_DELETE_TERMS = IndexWriterConfig.DEFAULT_MAX_BUFFERED_DELETE_TERMS; /** * Default value is 10,000. Change using {@link #setMaxFieldLength(int)}. + * + * @deprecated see {@link IndexWriterConfig} */ public final static int DEFAULT_MAX_FIELD_LENGTH = 10000; /** * Default value is 128. Change using {@link #setTermIndexInterval(int)}. + * @deprecated use {@link IndexWriterConfig#DEFAULT_TERM_INDEX_INTERVAL} instead. */ - public final static int DEFAULT_TERM_INDEX_INTERVAL = 128; + public final static int DEFAULT_TERM_INDEX_INTERVAL = IndexWriterConfig.DEFAULT_TERM_INDEX_INTERVAL; /** * Absolute hard maximum length for a term. If a term @@ -244,10 +253,11 @@ private int messageID = -1; volatile private boolean hitOOM; - private Directory directory; // where this index resides - private Analyzer analyzer; // how to analyze text + private final Directory directory; // where this index resides + private final Analyzer analyzer; // how to analyze text - private Similarity similarity = Similarity.getDefault(); // how to normalize + // 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 @@ -270,7 +280,8 @@ private Lock writeLock; - private int termIndexInterval = DEFAULT_TERM_INDEX_INTERVAL; + // TODO (4.0): this should be made final once the setter is out + private /*final*/int termIndexInterval; private boolean closed; private boolean closing; @@ -280,7 +291,8 @@ private HashSet mergingSegments = new HashSet(); private MergePolicy mergePolicy = new LogByteSizeMergePolicy(this); - private MergeScheduler mergeScheduler = new ConcurrentMergeScheduler(); + // TODO (4.0): this should be made final once the setter is removed + private /*final*/MergeScheduler mergeScheduler; private LinkedList pendingMerges = new LinkedList(); private Set runningMerges = new HashSet(); private List mergeExceptions = new ArrayList(); @@ -307,7 +319,11 @@ // 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; + /** * Expert: returns a readonly reader, covering all * committed as well as un-committed changes to the index. @@ -769,6 +785,8 @@ * Otherwise an IllegalArgumentException is thrown.

* * @see #setUseCompoundFile(boolean) + * @deprecated use {@link LogMergePolicy#getUseCompoundDocStore()} and + * {@link LogMergePolicy#getUseCompoundFile()} directly. */ public boolean getUseCompoundFile() { return getLogMergePolicy().getUseCompoundFile(); @@ -782,6 +800,8 @@ * just calls mergePolicy.setUseCompoundFile as long as * mergePolicy is an instance of {@link LogMergePolicy}. * Otherwise an IllegalArgumentException is thrown.

+ * @deprecated use {@link LogMergePolicy#setUseCompoundDocStore(boolean)} + * and {@link LogMergePolicy#setUseCompoundFile(boolean)} directly. */ public void setUseCompoundFile(boolean value) { getLogMergePolicy().setUseCompoundFile(value); @@ -791,20 +811,25 @@ /** Expert: Set the Similarity implementation used by this IndexWriter. * * @see Similarity#setDefault(Similarity) + * @deprecated use {@link IndexWriterConfig#setSimilarity(Similarity)} instead */ public void setSimilarity(Similarity similarity) { ensureOpen(); this.similarity = similarity; docWriter.setSimilarity(similarity); + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setSimilarity(similarity); } /** Expert: Return the Similarity implementation used by this IndexWriter. * *

This defaults to the current value of {@link Similarity#getDefault()}. + * @deprecated use {@link IndexWriterConfig#getSimilarity()} instead */ public Similarity getSimilarity() { ensureOpen(); - return this.similarity; + return similarity; } /** Expert: Set the interval between indexed terms. Large values cause less @@ -827,15 +852,20 @@ * must be scanned for each random term access. * * @see #DEFAULT_TERM_INDEX_INTERVAL + * @deprecated use {@link IndexWriterConfig#setTermIndexInterval(int)} */ public void setTermIndexInterval(int interval) { ensureOpen(); this.termIndexInterval = interval; + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setTermIndexInterval(interval); } /** Expert: Return the interval between indexed terms. * * @see #setTermIndexInterval(int) + * @deprecated use {@link IndexWriterConfig#getTermIndexInterval()} */ public int getTermIndexInterval() { // We pass false because this method is called by SegmentMerger while we are in the process of closing @@ -864,10 +894,13 @@ * if it does not exist and create is * false or if there is any other low-level * IO error + * @deprecated use {@link #IndexWriter(Directory, IndexWriterConfig)} instead */ public IndexWriter(Directory d, Analyzer a, boolean create, MaxFieldLength mfl) throws CorruptIndexException, LockObtainFailedException, IOException { - init(d, a, create, null, mfl.getLimit(), null, null); + this(d, new IndexWriterConfig(Version.LUCENE_31).setAnalyzer(a).setOpenMode( + create ? OpenMode.CREATE : OpenMode.APPEND).setMaxFieldLength( + mfl.getLimit())); } /** @@ -887,10 +920,12 @@ * @throws IOException if the directory cannot be * read/written to or if there is any other low-level * IO error + * @deprecated use {@link #IndexWriter(Directory, IndexWriterConfig)} instead */ public IndexWriter(Directory d, Analyzer a, MaxFieldLength mfl) throws CorruptIndexException, LockObtainFailedException, IOException { - init(d, a, null, mfl.getLimit(), null, null); + this(d, new IndexWriterConfig(Version.LUCENE_31).setAnalyzer(a) + .setMaxFieldLength(mfl.getLimit())); } /** @@ -910,10 +945,13 @@ * @throws IOException if the directory cannot be * read/written to or if there is any other low-level * IO error + * @deprecated use {@link #IndexWriter(Directory, IndexWriterConfig)} instead */ public IndexWriter(Directory d, Analyzer a, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl) throws CorruptIndexException, LockObtainFailedException, IOException { - init(d, a, deletionPolicy, mfl.getLimit(), null, null); + this(d, new IndexWriterConfig(Version.LUCENE_31).setAnalyzer(a) + .setMaxFieldLength(mfl.getLimit()).setIndexDeletionPolicy( + deletionPolicy)); } /** @@ -939,46 +977,16 @@ * if it does not exist and create is * false or if there is any other low-level * IO error + * @deprecated use {@link #IndexWriter(Directory, IndexWriterConfig)} instead */ public IndexWriter(Directory d, Analyzer a, boolean create, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl) throws CorruptIndexException, LockObtainFailedException, IOException { - init(d, a, create, deletionPolicy, mfl.getLimit(), null, null); + this(d, new IndexWriterConfig(Version.LUCENE_31).setAnalyzer(a).setOpenMode( + create ? OpenMode.CREATE : OpenMode.APPEND).setMaxFieldLength( + mfl.getLimit()).setIndexDeletionPolicy(deletionPolicy)); } /** - * Expert: constructs an IndexWriter with a custom {@link - * IndexDeletionPolicy} and {@link IndexingChain}, - * 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. - * - * @param d the index directory - * @param a the analyzer to use - * @param create true to create the index or overwrite - * the existing one; false to append to the existing - * index - * @param deletionPolicy see above - * @param mfl whether or not to limit field lengths, value is in number of terms/tokens. See {@link org.apache.lucene.index.IndexWriter.MaxFieldLength}. - * @param indexingChain the {@link DocConsumer} chain to be used to - * process documents - * @param commit which commit to open - * @throws CorruptIndexException if the index is corrupt - * @throws LockObtainFailedException if another writer - * has this index open (write.lock could not - * be obtained) - * @throws 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 - */ - IndexWriter(Directory d, Analyzer a, boolean create, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl, IndexingChain indexingChain, IndexCommit commit) - throws CorruptIndexException, LockObtainFailedException, IOException { - init(d, a, create, deletionPolicy, mfl.getLimit(), indexingChain, commit); - } - - /** * Expert: constructs an IndexWriter on specific commit * point, with a custom {@link IndexDeletionPolicy}, for * the index in d. Text will be analyzed @@ -1009,44 +1017,45 @@ * if it does not exist and create is * false or if there is any other low-level * IO error + * @deprecated use {@link #IndexWriter(Directory, IndexWriterConfig)} instead */ public IndexWriter(Directory d, Analyzer a, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl, IndexCommit commit) throws CorruptIndexException, LockObtainFailedException, IOException { - init(d, a, false, deletionPolicy, mfl.getLimit(), null, commit); + this(d, new IndexWriterConfig(Version.LUCENE_31).setAnalyzer(a) + .setOpenMode(OpenMode.APPEND).setMaxFieldLength(mfl.getLimit()) + .setIndexDeletionPolicy(deletionPolicy).setIndexCommit(commit)); } - private void init(Directory d, Analyzer a, IndexDeletionPolicy deletionPolicy, - int maxFieldLength, IndexingChain indexingChain, IndexCommit commit) - throws CorruptIndexException, LockObtainFailedException, IOException { - if (IndexReader.indexExists(d)) { - init(d, a, false, deletionPolicy, maxFieldLength, indexingChain, commit); - } else { - init(d, a, true, deletionPolicy, maxFieldLength, indexingChain, commit); - } - } - - private void init(Directory d, Analyzer a, final boolean create, - IndexDeletionPolicy deletionPolicy, int maxFieldLength, - IndexingChain indexingChain, IndexCommit commit) - throws CorruptIndexException, LockObtainFailedException, IOException { - + public IndexWriter(Directory d, IndexWriterConfig conf) throws CorruptIndexException, LockObtainFailedException, IOException { + config = conf; directory = d; - analyzer = a; + analyzer = conf.getAnalyzer(); setMessageID(defaultInfoStream); - this.maxFieldLength = maxFieldLength; + maxFieldLength = conf.getMaxFieldLength(); + termIndexInterval = conf.getTermIndexInterval(); + writeLockTimeout = conf.getWriteLockTimeout(); + similarity = conf.getSimilarity(); + mergeScheduler = conf.getMergeScheduler(); - if (indexingChain == null) - indexingChain = DocumentsWriter.DefaultIndexingChain; + OpenMode mode = conf.getOpenMode(); + boolean create; + if (mode == OpenMode.CREATE) { + create = true; + } else if (mode == OpenMode.APPEND) { + create = false; + } else { + // CREATE_OR_APPEND - create only if an index does not exist + create = !IndexReader.indexExists(directory); + } if (create) { // Clear the write lock in case it's leftover: directory.clearLock(WRITE_LOCK_NAME); } - Lock writeLock = directory.makeLock(WRITE_LOCK_NAME); + writeLock = directory.makeLock(WRITE_LOCK_NAME); if (!writeLock.obtain(writeLockTimeout)) // obtain write lock throw new LockObtainFailedException("Index locked for write: " + writeLock); - this.writeLock = writeLock; // save it try { if (create) { @@ -1077,6 +1086,7 @@ } else { segmentInfos.read(directory); + IndexCommit commit = conf.getIndexCommit(); if (commit != null) { // Swap out all segments, but, keep metadata in // SegmentInfos, like version & generation, to @@ -1100,14 +1110,14 @@ setRollbackSegmentInfos(segmentInfos); - docWriter = new DocumentsWriter(directory, this, indexingChain); + docWriter = new DocumentsWriter(directory, this); docWriter.setInfoStream(infoStream); docWriter.setMaxFieldLength(maxFieldLength); // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: deleter = new IndexFileDeleter(directory, - deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, + conf.getIndexDeletionPolicy(), segmentInfos, infoStream, docWriter); if (deleter.startingCommitDeleted) @@ -1117,20 +1127,22 @@ // segments_N file. changeCount++; + docWriter.setMaxBufferedDeleteTerms(conf.getMaxBufferedDeleteTerms()); + docWriter.setRAMBufferSizeMB(conf.getRAMBufferSizeMB()); + docWriter.setMaxBufferedDocs(conf.getMaxBufferedDocs()); pushMaxBufferedDocs(); if (infoStream != null) { - message("init: create=" + create); messageState(); } } catch (IOException e) { - this.writeLock.release(); - this.writeLock = null; + writeLock.release(); + writeLock = null; throw e; } } - + private synchronized void setRollbackSegmentInfos(SegmentInfos infos) { rollbackSegmentInfos = (SegmentInfos) infos.clone(); assert !rollbackSegmentInfos.hasExternalSegments(directory); @@ -1141,6 +1153,20 @@ } /** + * Returns the {@link IndexWriterConfig} that was passed to + * {@link #IndexWriter(Directory, IndexWriterConfig)}. This allows querying + * IndexWriter's settings. + *

+ * NOTE: setting any parameter on the returned instance has not effect + * on the IndexWriter instance. If you need to change those settings after + * IndexWriter has been created, you need to instantiate a new IndexWriter. + */ + public IndexWriterConfig getConfig() { + ensureOpen(); + return config; + } + + /** * Expert: set the merge policy used by this writer. */ public void setMergePolicy(MergePolicy mp) { @@ -1167,6 +1193,7 @@ /** * Expert: set the merge scheduler used by this writer. + * @deprecated use {@link IndexWriterConfig#setMergeScheduler(MergeScheduler)} instead */ synchronized public void setMergeScheduler(MergeScheduler mergeScheduler) throws CorruptIndexException, IOException { ensureOpen(); @@ -1180,12 +1207,16 @@ this.mergeScheduler = mergeScheduler; if (infoStream != null) message("setMergeScheduler " + mergeScheduler); + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setMergeScheduler(mergeScheduler); } /** - * Expert: returns the current MergePolicy in use by this + * Expert: returns the current MergeScheduler in use by this * writer. - * @see #setMergePolicy + * @see #setMergeScheduler(MergeScheduler) + * @deprecated use {@link IndexWriterConfig#getMergeScheduler()} instead */ public MergeScheduler getMergeScheduler() { ensureOpen(); @@ -1211,6 +1242,7 @@ * LogByteSizeMergePolicy}) also allows you to set this * limit by net size (in MB) of the segment, using {@link * LogByteSizeMergePolicy#setMaxMergeMB}.

+ * @deprecated use {@link LogMergePolicy#setMaxMergeDocs(int)} directly. */ public void setMaxMergeDocs(int maxMergeDocs) { getLogMergePolicy().setMaxMergeDocs(maxMergeDocs); @@ -1226,6 +1258,7 @@ * Otherwise an IllegalArgumentException is thrown.

* * @see #setMaxMergeDocs + * @deprecated use {@link LogMergePolicy#getMaxMergeDocs()} directly. */ public int getMaxMergeDocs() { return getLogMergePolicy().getMaxMergeDocs(); @@ -1244,6 +1277,7 @@ * is your memory, but you should anticipate an OutOfMemoryError.

* By default, no more than {@link #DEFAULT_MAX_FIELD_LENGTH} terms * will be indexed for a field. + * @deprecated use {@link IndexWriterConfig#setMaxFieldLength(int)} instead */ public void setMaxFieldLength(int maxFieldLength) { ensureOpen(); @@ -1251,12 +1285,16 @@ docWriter.setMaxFieldLength(maxFieldLength); if (infoStream != null) message("setMaxFieldLength " + maxFieldLength); + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setMaxFieldLength(maxFieldLength); } /** * Returns the maximum number of terms that will be * indexed for a single field in a document. * @see #setMaxFieldLength + * @deprecated use {@link IndexWriterConfig#getMaxFieldLength()} instead */ public int getMaxFieldLength() { ensureOpen(); @@ -1281,6 +1319,7 @@ * enabled but smaller than 2, or it disables maxBufferedDocs * when ramBufferSize is already disabled * @see #setRAMBufferSizeMB + * @deprecated use {@link IndexWriterConfig#setMaxBufferedDocs(int)} instead. */ public void setMaxBufferedDocs(int maxBufferedDocs) { ensureOpen(); @@ -1295,6 +1334,9 @@ pushMaxBufferedDocs(); if (infoStream != null) message("setMaxBufferedDocs " + maxBufferedDocs); + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setMaxBufferedDocs(maxBufferedDocs); } /** @@ -1321,6 +1363,7 @@ * Returns the number of buffered added documents that will * trigger a flush if enabled. * @see #setMaxBufferedDocs + * @deprecated use {@link IndexWriterConfig#getMaxBufferedDocs()} instead. */ public int getMaxBufferedDocs() { ensureOpen(); @@ -1364,6 +1407,7 @@ * @throws IllegalArgumentException if ramBufferSize is * enabled but non-positive, or it disables ramBufferSize * when maxBufferedDocs is already disabled + * @deprecated use {@link IndexWriterConfig#setRAMBufferSizeMB(double)} instead. */ public void setRAMBufferSizeMB(double mb) { if (mb > 2048.0) { @@ -1378,10 +1422,14 @@ docWriter.setRAMBufferSizeMB(mb); if (infoStream != null) message("setRAMBufferSizeMB " + mb); + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setRAMBufferSizeMB(mb); } /** * Returns the value set by {@link #setRAMBufferSizeMB} if enabled. + * @deprecated use {@link IndexWriterConfig#getRAMBufferSizeMB()} instead. */ public double getRAMBufferSizeMB() { return docWriter.getRAMBufferSizeMB(); @@ -1398,6 +1446,7 @@ * @throws IllegalArgumentException if maxBufferedDeleteTerms * is enabled but smaller than 1 * @see #setRAMBufferSizeMB + * @deprecated use {@link IndexWriterConfig#setMaxBufferedDeleteTerms(int)} instead. */ public void setMaxBufferedDeleteTerms(int maxBufferedDeleteTerms) { ensureOpen(); @@ -1408,12 +1457,16 @@ docWriter.setMaxBufferedDeleteTerms(maxBufferedDeleteTerms); if (infoStream != null) message("setMaxBufferedDeleteTerms " + maxBufferedDeleteTerms); + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setMaxBufferedDeleteTerms(maxBufferedDeleteTerms); } /** * Returns the number of buffered deleted terms that will * trigger a flush if enabled. * @see #setMaxBufferedDeleteTerms + * @deprecated use {@link IndexWriterConfig#getMaxBufferedDeleteTerms()} instead */ public int getMaxBufferedDeleteTerms() { ensureOpen(); @@ -1434,6 +1487,7 @@ * Otherwise an IllegalArgumentException is thrown.

* *

This must never be less than 2. The default value is 10. + * @deprecated use {@link LogMergePolicy#setMergeFactor(int)} directly. */ public void setMergeFactor(int mergeFactor) { getLogMergePolicy().setMergeFactor(mergeFactor); @@ -1450,6 +1504,7 @@ * Otherwise an IllegalArgumentException is thrown.

* * @see #setMergeFactor + * @deprecated use {@link LogMergePolicy#getMergeFactor()} directly. */ public int getMergeFactor() { return getLogMergePolicy().getMergeFactor(); @@ -1486,15 +1541,11 @@ } private void messageState() { - message("setInfoStream: dir=" + directory + + message("dir=" + directory + " mergePolicy=" + mergePolicy + - " mergeScheduler=" + mergeScheduler + - " ramBufferSizeMB=" + docWriter.getRAMBufferSizeMB() + - " maxBufferedDocs=" + docWriter.getMaxBufferedDocs() + - " maxBuffereDeleteTerms=" + docWriter.getMaxBufferedDeleteTerms() + - " maxFieldLength=" + maxFieldLength + " index=" + segString() + - " version=" + Constants.LUCENE_VERSION); + " version=" + Constants.LUCENE_VERSION + + " config=" + config.toString()); } /** @@ -1514,15 +1565,20 @@ /** * Sets the maximum time to wait for a write lock (in milliseconds) for this instance of IndexWriter. @see * @see #setDefaultWriteLockTimeout to change the default value for all instances of IndexWriter. + * @deprecated use {@link IndexWriterConfig#setWriteLockTimeout(long)} instead */ public void setWriteLockTimeout(long writeLockTimeout) { ensureOpen(); this.writeLockTimeout = writeLockTimeout; + // Required so config.getSimilarity returns the right value. But this will + // go away together with the method in 4.0. + config.setWriteLockTimeout(writeLockTimeout); } /** * Returns allowed timeout when acquiring the write lock. * @see #setWriteLockTimeout + * @deprecated use {@link IndexWriterConfig#getWriteLockTimeout()} */ public long getWriteLockTimeout() { ensureOpen(); @@ -1532,18 +1588,20 @@ /** * Sets the default (for any instance of IndexWriter) maximum time to wait for a write lock (in * milliseconds). + * @deprecated use {@link IndexWriterConfig#setDefaultWriteLockTimeout(long)} instead */ public static void setDefaultWriteLockTimeout(long writeLockTimeout) { - IndexWriter.WRITE_LOCK_TIMEOUT = writeLockTimeout; + IndexWriterConfig.setDefaultWriteLockTimeout(writeLockTimeout); } /** * Returns default write lock timeout for newly * instantiated IndexWriters. * @see #setDefaultWriteLockTimeout + * @deprecated use {@link IndexWriterConfig#getDefaultWriteLockTimeout()} instead */ public static long getDefaultWriteLockTimeout() { - return IndexWriter.WRITE_LOCK_TIMEOUT; + return IndexWriterConfig.getDefaultWriteLockTimeout(); } /** @@ -4777,9 +4835,13 @@ } /** - * Specifies maximum field length (in number of tokens/terms) in {@link IndexWriter} constructors. - * {@link #setMaxFieldLength(int)} overrides the value set by - * the constructor. + * Specifies maximum field length (in number of tokens/terms) in + * {@link IndexWriter} constructors. {@link #setMaxFieldLength(int)} overrides + * the value set by the constructor. + * + * @deprecated use {@link IndexWriterConfig} and pass + * {@link IndexWriterConfig#UNLIMITED_FIELD_LENGTH} or your own + * value. */ public static final class MaxFieldLength { Index: src/java/org/apache/lucene/index/IndexWriterConfig.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriterConfig.java (revision 0) +++ src/java/org/apache/lucene/index/IndexWriterConfig.java (revision 0) @@ -0,0 +1,493 @@ +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 org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.WhitespaceAnalyzer; +import org.apache.lucene.search.Similarity; +import org.apache.lucene.util.Version; + +/** + * Holds all the configuration of {@link IndexWriter}. This object is only used + * while constructing a new IndexWriter. Those settings cannot be changed + * afterwards, except instantiating a new IndexWriter. + *

+ * All setter methods return {@link IndexWriterConfig} to allow chaining + * settings conveniently. Thus someone can do: + * + *

+ * IndexWriterConfig conf = new IndexWriterConfig(analyzer);
+ * conf.setter1().setter2();
+ * 
+ */ +public final class IndexWriterConfig implements Cloneable { + + public static final int UNLIMITED_FIELD_LENGTH = Integer.MAX_VALUE; + + /** + * Specifies the open mode for {@link IndexWriter}: + *
    + * {@link #CREATE} - creates a new index or overwrites an existing one. + * {@link #CREATE_OR_APPEND} - creates a new index if one does not exist, + * otherwise it opens the index and documents will be appended. + * {@link #APPEND} - opens an existing index. + *
+ */ + public static enum OpenMode { CREATE, APPEND, CREATE_OR_APPEND } + + /** Default value is 128. Change using {@link #setTermIndexInterval(int)}. */ + public static final int DEFAULT_TERM_INDEX_INTERVAL = 128; + + /** Denotes a flush trigger is disabled. */ + public final static int DISABLE_AUTO_FLUSH = -1; + + /** Disabled by default (because IndexWriter flushes by RAM usage by default). */ + public final static int DEFAULT_MAX_BUFFERED_DELETE_TERMS = DISABLE_AUTO_FLUSH; + + /** Disabled by default (because IndexWriter flushes by RAM usage by default). */ + public final static int DEFAULT_MAX_BUFFERED_DOCS = DISABLE_AUTO_FLUSH; + + /** + * Default value is 16 MB (which means flush when buffered docs consume + * approximately 16 MB RAM). + */ + public final static double DEFAULT_RAM_BUFFER_SIZE_MB = 16.0; + + /** + * Default value for the write lock timeout (1,000 ms). + * + * @see #setDefaultWriteLockTimeout(long) + */ + public static long WRITE_LOCK_TIMEOUT = 1000; + + /** + * Sets the default (for any instance) maximum time to wait for a write lock + * (in milliseconds). + */ + public static void setDefaultWriteLockTimeout(long writeLockTimeout) { + WRITE_LOCK_TIMEOUT = writeLockTimeout; + } + + /** + * Returns the default write lock timeout for newly instantiated + * IndexWriterConfigs. + * + * @see #setDefaultWriteLockTimeout(long) + */ + public static long getDefaultWriteLockTimeout() { + return WRITE_LOCK_TIMEOUT; + } + + private Analyzer analyzer; + private IndexDeletionPolicy delPolicy; + private IndexCommit commit; + private OpenMode openMode; + private int maxFieldLength; + private Similarity similarity; + private int termIndexInterval; + private MergeScheduler scheduler; + private long writeLockTimeout; + private int maxBufferedDeleteTerms; + private double ramBufferSizeMB; + private int maxBufferedDocs; + + // required for clone + private Version matchVersion; + + /** Creates a new config that with defaults that match the specified {@link Version}. */ + public IndexWriterConfig(Version matchVersion) { + // A placeholder for future changes. The default settings are relevant to + // 3.1 (and before it). If a different Version is passed, the relevant + // settings should change here. + this.matchVersion = matchVersion; + analyzer = new WhitespaceAnalyzer(matchVersion); + delPolicy = new KeepOnlyLastCommitDeletionPolicy(); + commit = null; + openMode = OpenMode.CREATE_OR_APPEND; + maxFieldLength = UNLIMITED_FIELD_LENGTH; + similarity = Similarity.getDefault(); + termIndexInterval = DEFAULT_TERM_INDEX_INTERVAL; + scheduler = new ConcurrentMergeScheduler(); + writeLockTimeout = WRITE_LOCK_TIMEOUT; + maxBufferedDeleteTerms = DEFAULT_MAX_BUFFERED_DELETE_TERMS; + ramBufferSizeMB = DEFAULT_RAM_BUFFER_SIZE_MB; + maxBufferedDocs = DEFAULT_MAX_BUFFERED_DOCS; + } + + @Override + public Object clone() throws CloneNotSupportedException { + // Shallow clone is the only thing that's possible, since parameters like + // analyzer, index commit etc. do not implemnt Cloneable. + return super.clone(); + } + + /** + * Sets the default {@link Analyzer} to be used when indexing documents. The + * default {@link WhitespaceAnalyzer} is set for convenience (e.g. for test + * purposes or when the analyzer used does not make a difference) and it's + * recommended to override the default setting if you care about the tokens + * that end up in your index. + *

+ * NOTE: the analyzer cannot be null. If null is passed, + * the analyzer will be set to the default. + */ + public IndexWriterConfig setAnalyzer(Analyzer analyzer) { + this.analyzer = analyzer == null ? new WhitespaceAnalyzer(matchVersion) : analyzer; + return this; + } + + /** Returns the default analyzer to use for indexing documents. */ + public Analyzer getAnalyzer() { + return analyzer; + } + + /** Specifies {@link OpenMode} of that index. */ + public IndexWriterConfig setOpenMode(OpenMode openMode) { + this.openMode = openMode; + return this; + } + + /** Returns the {@link OpenMode} set by {@link #setOpenMode(OpenMode)}. */ + public OpenMode getOpenMode() { + return openMode; + } + + /** + * Expert: allows an optional {@link IndexDeletionPolicy} implementation to be + * specified. You can use this to control when prior commits are deleted from + * the index. The default policy is {@link 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. + *

+ * NOTE: the deletion policy cannot be null. If null is + * passed, the deletion policy will be set to the default. + */ + public IndexWriterConfig setIndexDeletionPolicy(IndexDeletionPolicy delPolicy) { + this.delPolicy = delPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : delPolicy; + return this; + } + + /** + * Returns the {@link IndexDeletionPolicy} specified in + * {@link #setIndexDeletionPolicy(IndexDeletionPolicy)} or the default + * {@link KeepOnlyLastCommitDeletionPolicy}/ + */ + public IndexDeletionPolicy getIndexDeletionPolicy() { + return delPolicy; + } + + /** + * 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 {@link #UNLIMITED_FIELD_LENGTH}, then the + * only limit is your memory, but you should anticipate an OutOfMemoryError. + *

+ * By default it is set to {@link #UNLIMITED_FIELD_LENGTH}. + */ + public IndexWriterConfig setMaxFieldLength(int maxFieldLength) { + this.maxFieldLength = maxFieldLength; + return this; + } + + /** + * Returns the maximum number of terms that will be indexed for a single field + * in a document. + * + * @see #setMaxFieldLength(int) + */ + public int getMaxFieldLength() { + return maxFieldLength; + } + + /** + * Expert: allows to open a certain commit point. The default is null which + * opens the latest commit point. + */ + public IndexWriterConfig setIndexCommit(IndexCommit commit) { + this.commit = commit; + return this; + } + + /** + * Returns the {@link IndexCommit} as specified in + * {@link #setIndexCommit(IndexCommit)} or the default, null + * which specifies to open the latest index commit point. + */ + public IndexCommit getIndexCommit() { + return commit; + } + + /** + * Expert: set the {@link Similarity} implementation used by this IndexWriter. + *

+ * NOTE: the similarity cannot be null. If null is passed, + * the similarity will be set to the default. + * + * @see Similarity#setDefault(Similarity) + */ + public IndexWriterConfig setSimilarity(Similarity similarity) { + this.similarity = similarity == null ? Similarity.getDefault() : similarity; + return this; + } + + /** + * Expert: returns the {@link Similarity} implementation used by this + * IndexWriter. This defaults to the current value of + * {@link Similarity#getDefault()}. + */ + public Similarity getSimilarity() { + return similarity; + } + + /** + * 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. + * + * @see #DEFAULT_TERM_INDEX_INTERVAL + */ + public IndexWriterConfig setTermIndexInterval(int interval) { + this.termIndexInterval = interval; + return this; + } + + /** + * Returns the interval between indexed terms. + * + * @see #setTermIndexInterval(int) + */ + public int getTermIndexInterval() { + return termIndexInterval; + } + + /** + * Expert: sets the merge scheduler used by this writer. The default is + * {@link ConcurrentMergeScheduler}. + *

+ * NOTE: the merge scheduler cannot be null. If null is + * passed, the merge scheduler will be set to the default. + */ + public IndexWriterConfig setMergeScheduler(MergeScheduler scheduler) { + this.scheduler = scheduler == null ? new ConcurrentMergeScheduler() : scheduler; + return this; + } + + /** + * Returns the {@link MergeScheduler} that was set by + * {@link #setMergeScheduler(MergeScheduler)} + */ + public MergeScheduler getMergeScheduler() { + return scheduler; + } + + /** + * Sets the maximum time to wait for a write lock (in milliseconds) for this + * instance. You can change the default value for all instances by calling + * {@link #setDefaultWriteLockTimeout(long)}. + */ + public IndexWriterConfig setWriteLockTimeout(long writeLockTimeout) { + this.writeLockTimeout = writeLockTimeout; + return this; + } + + /** + * Returns allowed timeout when acquiring the write lock. + * + * @see #setWriteLockTimeout(long) + */ + public long getWriteLockTimeout() { + return writeLockTimeout; + } + + /** + * 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). + * + * @throws IllegalArgumentException if maxBufferedDeleteTerms + * is enabled but smaller than 1 + * @see #setRAMBufferSizeMB + */ + public IndexWriterConfig setMaxBufferedDeleteTerms(int maxBufferedDeleteTerms) { + if (maxBufferedDeleteTerms != DISABLE_AUTO_FLUSH + && maxBufferedDeleteTerms < 1) + throw new IllegalArgumentException( + "maxBufferedDeleteTerms must at least be 1 when enabled"); + this.maxBufferedDeleteTerms = maxBufferedDeleteTerms; + return this; + } + + /** + * Returns the number of buffered deleted terms that will trigger a flush if + * enabled. + * + * @see #setMaxBufferedDeleteTerms(int) + */ + public int getMaxBufferedDeleteTerms() { + return maxBufferedDeleteTerms; + } + + /** + * 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 {@link #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 of individual Queries so the accounting will + * under-estimate and you should compensate by either calling commit() + * periodically yourself, or by using {@link #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 {@link #DEFAULT_RAM_BUFFER_SIZE_MB}. + * + * @throws IllegalArgumentException + * if ramBufferSize is enabled but non-positive, or it disables + * ramBufferSize when maxBufferedDocs is already disabled + */ + public IndexWriterConfig setRAMBufferSizeMB(double ramBufferSizeMB) { + if (ramBufferSizeMB > 2048.0) { + throw new IllegalArgumentException("ramBufferSize " + ramBufferSizeMB + + " is too large; should be comfortably less than 2048"); + } + if (ramBufferSizeMB != DISABLE_AUTO_FLUSH && ramBufferSizeMB <= 0.0) + throw new IllegalArgumentException( + "ramBufferSize should be > 0.0 MB when enabled"); + if (ramBufferSizeMB == DISABLE_AUTO_FLUSH && maxBufferedDocs == DISABLE_AUTO_FLUSH) + throw new IllegalArgumentException( + "at least one of ramBufferSize and maxBufferedDocs must be enabled"); + this.ramBufferSizeMB = ramBufferSizeMB; + return this; + } + + /** Returns the value set by {@link #setRAMBufferSizeMB(double)} if enabled. */ + public double getRAMBufferSizeMB() { + return ramBufferSizeMB; + } + + /** + * Determines the minimal number of documents required before the buffered + * in-memory documents are flushed as a new Segment. Large values generally + * give faster indexing. + * + *

+ * When this is set, the writer will flush every maxBufferedDocs added + * documents. Pass in {@link #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). + * + * @see #setRAMBufferSizeMB(double) + * + * @throws IllegalArgumentException + * if maxBufferedDocs is enabled but smaller than 2, or it disables + * maxBufferedDocs when ramBufferSize is already disabled + */ + public IndexWriterConfig setMaxBufferedDocs(int maxBufferedDocs) { + if (maxBufferedDocs != DISABLE_AUTO_FLUSH && maxBufferedDocs < 2) + throw new IllegalArgumentException( + "maxBufferedDocs must at least be 2 when enabled"); + if (maxBufferedDocs == DISABLE_AUTO_FLUSH + && ramBufferSizeMB == DISABLE_AUTO_FLUSH) + throw new IllegalArgumentException( + "at least one of ramBufferSize and maxBufferedDocs must be enabled"); + this.maxBufferedDocs = maxBufferedDocs; + return this; + } + + /** + * Returns the number of buffered added documents that will trigger a flush if + * enabled. + * + * @see #setMaxBufferedDocs(int) + */ + public int getMaxBufferedDocs() { + return maxBufferedDocs; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("matchVersion=").append(matchVersion).append("\n"); + sb.append("analyzer=").append(analyzer.getClass().getName()).append("\n"); + sb.append("delPolicy=").append(delPolicy.getClass().getName()).append("\n"); + sb.append("commit=").append(commit == null ? "null" : commit.getClass().getName()).append("\n"); + sb.append("openMode=").append(openMode).append("\n"); + sb.append("maxFieldLength=").append(maxFieldLength).append("\n"); + sb.append("similarity=").append(similarity.getClass().getName()).append("\n"); + sb.append("termIndexInterval=").append(termIndexInterval).append("\n"); + sb.append("scheduler=").append(scheduler.getClass().getName()).append("\n"); + sb.append("default WRITE_LOCK_TIMEOUT=").append(WRITE_LOCK_TIMEOUT).append("\n"); + sb.append("writeLockTimeout=").append(writeLockTimeout).append("\n"); + sb.append("maxBufferedDeleteTerms=").append(maxBufferedDeleteTerms).append("\n"); + sb.append("ramBufferSizeMB=").append(ramBufferSizeMB).append("\n"); + sb.append("maxBufferedDocs=").append(maxBufferedDocs).append("\n"); + return sb.toString(); + } +} Property changes on: src\java\org\apache\lucene\index\IndexWriterConfig.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Index: src/test/org/apache/lucene/index/TestIndexWriterConfig.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexWriterConfig.java (revision 0) +++ src/test/org/apache/lucene/index/TestIndexWriterConfig.java (revision 0) @@ -0,0 +1,239 @@ +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 static org.junit.Assert.*; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Set; + +import org.apache.lucene.analysis.SimpleAnalyzer; +import org.apache.lucene.analysis.WhitespaceAnalyzer; +import org.apache.lucene.index.IndexWriterConfig.OpenMode; +import org.apache.lucene.search.DefaultSimilarity; +import org.apache.lucene.search.Similarity; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; +import org.apache.lucene.util.LuceneTestCaseJ4; +import org.junit.Test; + +public class TestIndexWriterConfig extends LuceneTestCaseJ4 { + + private static final class MySimilarity extends DefaultSimilarity { + // Does not implement anything - used only for type checking on IndexWriterConfig. + } + + @Test + public void testDefaults() throws Exception { + IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT); + assertEquals(WhitespaceAnalyzer.class, conf.getAnalyzer().getClass()); + assertNull(conf.getIndexCommit()); + assertEquals(KeepOnlyLastCommitDeletionPolicy.class, conf.getIndexDeletionPolicy().getClass()); + assertEquals(IndexWriterConfig.UNLIMITED_FIELD_LENGTH, conf.getMaxFieldLength()); + assertEquals(ConcurrentMergeScheduler.class, conf.getMergeScheduler().getClass()); + assertEquals(OpenMode.CREATE_OR_APPEND, conf.getOpenMode()); + assertTrue(Similarity.getDefault() == conf.getSimilarity()); + assertEquals(IndexWriterConfig.DEFAULT_TERM_INDEX_INTERVAL, conf.getTermIndexInterval()); + assertEquals(IndexWriterConfig.getDefaultWriteLockTimeout(), conf.getWriteLockTimeout()); + assertEquals(IndexWriterConfig.WRITE_LOCK_TIMEOUT, IndexWriterConfig.getDefaultWriteLockTimeout()); + assertEquals(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DELETE_TERMS, conf.getMaxBufferedDeleteTerms()); + assertEquals(IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB, conf.getRAMBufferSizeMB(), 0.0); + assertEquals(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS, conf.getMaxBufferedDocs()); + + // Sanity check - validate that all getters are covered. + Set getters = new HashSet(); + getters.add("getAnalyzer"); + getters.add("getIndexCommit"); + getters.add("getIndexDeletionPolicy"); + getters.add("getMaxFieldLength"); + getters.add("getMergeScheduler"); + getters.add("getOpenMode"); + getters.add("getSimilarity"); + getters.add("getTermIndexInterval"); + getters.add("getWriteLockTimeout"); + getters.add("getDefaultWriteLockTimeout"); + getters.add("getMaxBufferedDeleteTerms"); + getters.add("getRAMBufferSizeMB"); + getters.add("getMaxBufferedDocs"); + for (Method m : IndexWriterConfig.class.getMethods()) { + if (m.getDeclaringClass() == IndexWriterConfig.class && m.getName().startsWith("get")) { + assertTrue("method " + m.getName() + " is not tested for defaults", getters.contains(m.getName())); + } + } + } + + @Test + public void testSettersChaining() throws Exception { + // Ensures that every setter returns IndexWriterConfig to enable easy + // chaining. + for (Method m : IndexWriterConfig.class.getMethods()) { + if (m.getDeclaringClass() == IndexWriterConfig.class + && m.getName().startsWith("set") + && !Modifier.isStatic(m.getModifiers())) { + assertEquals("method " + m.getName() + " does not return IndexWriterConfig", + IndexWriterConfig.class, m.getReturnType()); + } + } + } + + @Test + public void testConstants() throws Exception { + // Tests that the values of the constants does not change + assertEquals(1000, IndexWriterConfig.WRITE_LOCK_TIMEOUT); + assertEquals(128, IndexWriterConfig.DEFAULT_TERM_INDEX_INTERVAL); + assertEquals(Integer.MAX_VALUE, IndexWriterConfig.UNLIMITED_FIELD_LENGTH); + assertEquals(-1, IndexWriterConfig.DISABLE_AUTO_FLUSH); + assertEquals(IndexWriterConfig.DISABLE_AUTO_FLUSH, IndexWriterConfig.DEFAULT_MAX_BUFFERED_DELETE_TERMS); + assertEquals(IndexWriterConfig.DISABLE_AUTO_FLUSH, IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS); + assertEquals(16.0, IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB, 0.0); + } + + @Test + public void testToString() throws Exception { + String str = new IndexWriterConfig(TEST_VERSION_CURRENT).toString(); + for (Field f : IndexWriterConfig.class.getDeclaredFields()) { + int modifiers = f.getModifiers(); + if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { + // Skip static final fields, they are only constants + continue; + } + assertTrue(f.getName() + " not found in toString", str.indexOf(f.getName()) != -1); + } + } + + @Test + public void testClone() throws Exception { + IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT); + IndexWriterConfig clone = (IndexWriterConfig) conf.clone(); + + // Clone is shallow since not all parameters are cloneable. + assertTrue(conf.getIndexDeletionPolicy() == clone.getIndexDeletionPolicy()); + + conf.setMergeScheduler(new SerialMergeScheduler()); + assertEquals(ConcurrentMergeScheduler.class, clone.getMergeScheduler().getClass()); + } + + @Test + public void testInvalidValues() throws Exception { + IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT); + + // Test Analyzer + assertEquals(WhitespaceAnalyzer.class, conf.getAnalyzer().getClass()); + conf.setAnalyzer(new SimpleAnalyzer(TEST_VERSION_CURRENT)); + assertEquals(SimpleAnalyzer.class, conf.getAnalyzer().getClass()); + conf.setAnalyzer(null); + assertEquals(WhitespaceAnalyzer.class, conf.getAnalyzer().getClass()); + + // Test IndexDeletionPolicy + assertEquals(KeepOnlyLastCommitDeletionPolicy.class, conf.getIndexDeletionPolicy().getClass()); + conf.setIndexDeletionPolicy(new SnapshotDeletionPolicy(null)); + assertEquals(SnapshotDeletionPolicy.class, conf.getIndexDeletionPolicy().getClass()); + conf.setIndexDeletionPolicy(null); + assertEquals(KeepOnlyLastCommitDeletionPolicy.class, conf.getIndexDeletionPolicy().getClass()); + + // Test MergeScheduler + assertEquals(ConcurrentMergeScheduler.class, conf.getMergeScheduler().getClass()); + conf.setMergeScheduler(new SerialMergeScheduler()); + assertEquals(SerialMergeScheduler.class, conf.getMergeScheduler().getClass()); + conf.setMergeScheduler(null); + assertEquals(ConcurrentMergeScheduler.class, conf.getMergeScheduler().getClass()); + + // Test Similarity + assertEquals(Similarity.getDefault().getClass(), conf.getSimilarity().getClass()); + conf.setSimilarity(new MySimilarity()); + assertEquals(MySimilarity.class, conf.getSimilarity().getClass()); + conf.setSimilarity(null); + assertEquals(Similarity.getDefault().getClass(), conf.getSimilarity().getClass()); + + try { + conf.setMaxBufferedDeleteTerms(0); + fail("should not have succeeded to set maxBufferedDeleteTerms to 0"); + } catch (IllegalArgumentException e) { + // this is expected + } + + try { + conf.setMaxBufferedDocs(1); + fail("should not have succeeded to set maxBufferedDocs to 1"); + } catch (IllegalArgumentException e) { + // this is expected + } + + try { + // Disable both MAX_BUF_DOCS and RAM_SIZE_MB + conf.setMaxBufferedDocs(4); + conf.setRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH); + conf.setMaxBufferedDocs(IndexWriterConfig.DISABLE_AUTO_FLUSH); + fail("should not have succeeded to disable maxBufferedDocs when ramBufferSizeMB is disabled as well"); + } catch (IllegalArgumentException e) { + // this is expected + } + + conf.setRAMBufferSizeMB(IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB); + conf.setMaxBufferedDocs(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS); + try { + conf.setRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH); + fail("should not have succeeded to disable ramBufferSizeMB when maxBufferedDocs is disabled as well"); + } catch (IllegalArgumentException e) { + // this is expected + } + + } + + /** + * @deprecated should be removed once all the deprecated setters are removed + * from IndexWriter. + */ + @Test + public void testIndexWriterSetters() throws Exception { + // This test intentionally tests deprecated methods. The purpose is to pass + // whatever the user set on IW to IWC, so that if the user calls + // iw.getConfig().getXYZ(), he'll get the same value he passed to + // iw.setXYZ(). + IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT); + Directory dir = new RAMDirectory(); + IndexWriter writer = new IndexWriter(dir, conf); + + writer.setSimilarity(new MySimilarity()); + assertEquals(MySimilarity.class, writer.getConfig().getSimilarity().getClass()); + + writer.setMaxBufferedDeleteTerms(4); + assertEquals(4, writer.getConfig().getMaxBufferedDeleteTerms()); + + writer.setMaxBufferedDocs(10); + assertEquals(10, writer.getConfig().getMaxBufferedDocs()); + + writer.setMaxFieldLength(10); + assertEquals(10, writer.getConfig().getMaxFieldLength()); + + writer.setMergeScheduler(new SerialMergeScheduler()); + assertEquals(SerialMergeScheduler.class, writer.getConfig().getMergeScheduler().getClass()); + + writer.setRAMBufferSizeMB(1.5); + assertEquals(1.5, writer.getConfig().getRAMBufferSizeMB(), 0.0); + + writer.setTermIndexInterval(40); + assertEquals(40, writer.getConfig().getTermIndexInterval()); + + writer.setWriteLockTimeout(100); + assertEquals(100, writer.getConfig().getWriteLockTimeout()); + } +} Property changes on: src\test\org\apache\lucene\index\TestIndexWriterConfig.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native