Property changes on: . ___________________________________________________________________ Modified: svn:mergeinfo Merged /lucene/dev/trunk/lucene:r1043148 Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 1043277) +++ CHANGES.txt (working copy) @@ -116,6 +116,11 @@ * LUCENE-2790: LogMergePolicy.useCompoundFile's logic now factors in noCFSRatio to determine whether the passed in segment should be compound. (Shai Erera, Earwin Burrfoot) + +* LUCENE-2805: IndexWriter now increments the index version on every change to + the index instead of for every commit. Committing or closing the IndexWriter + without any changes to the index will not cause any index version increment. + (Simon Willnauer, Mike Mccandless) API Changes Index: src/test/org/apache/lucene/index/TestIndexWriterReader.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexWriterReader.java (revision 1043277) +++ src/test/org/apache/lucene/index/TestIndexWriterReader.java (working copy) @@ -56,7 +56,54 @@ td.close(); return count; } - + + public void testAddCloseOpen() throws IOException { + Directory dir1 = newDirectory(); + IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new WhitespaceAnalyzer(TEST_VERSION_CURRENT)); + + IndexWriter writer = new IndexWriter(dir1, iwc); + for (int i = 0; i < 97 ; i++) { + IndexReader reader = writer.getReader(); + if (i == 0) { + writer.addDocument(createDocument(i, "x", 1 + random.nextInt(5))); + } else { + int previous = random.nextInt(i); + // a check if the reader is current here could fail since there might be + // merges going on. + switch (random.nextInt(5)) { + case 0: + case 1: + case 2: + writer.addDocument(createDocument(i, "x", 1 + random.nextInt(5))); + break; + case 3: + writer.updateDocument(new Term("id", "" + previous), createDocument( + previous, "x", 1 + random.nextInt(5))); + break; + case 4: + writer.deleteDocuments(new Term("id", "" + previous)); + } + } + assertFalse(reader.isCurrent()); + reader.close(); + } + writer.optimize(); // make sure all merging is done etc. + IndexReader reader = writer.getReader(); + writer.commit(); // no changes that are not visible to the reader + assertTrue(reader.isCurrent()); + writer.close(); + assertTrue(reader.isCurrent()); // all changes are visible to the reader + iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new WhitespaceAnalyzer(TEST_VERSION_CURRENT)); + writer = new IndexWriter(dir1, iwc); + assertTrue(reader.isCurrent()); + writer.addDocument(createDocument(1, "x", 1+random.nextInt(5))); + assertTrue(reader.isCurrent()); // segments in ram but IW is different to the readers one + writer.close(); + assertFalse(reader.isCurrent()); // segments written + reader.close(); + dir1.close(); + } + public void testUpdateDocument() throws Exception { boolean optimize = true; @@ -166,7 +213,7 @@ assertTrue(r1.isCurrent()); writer.commit(); - assertFalse(r1.isCurrent()); + assertTrue(r1.isCurrent()); // we have seen all changes - no change after opening the NRT reader assertEquals(200, r1.maxDoc()); Index: src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfos.java (revision 1043277) +++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -97,7 +97,7 @@ * counts how often the index has been changed by adding or deleting docs. * starting with the current time in milliseconds forces to create unique version numbers. */ - private long version = System.currentTimeMillis(); + long version = System.currentTimeMillis(); private long generation = 0; // generation of the "segments_N" for the next commit private long lastGeneration = 0; // generation of the "segments_N" file we last successfully read @@ -335,8 +335,7 @@ try { segnOutput.writeInt(CURRENT_FORMAT); // write FORMAT - segnOutput.writeLong(++version); // every write changes - // the index + segnOutput.writeLong(version); segnOutput.writeInt(counter); // write counter segnOutput.writeInt(size()); // write infos for (int i = 0; i < size(); i++) { @@ -758,7 +757,6 @@ void updateGeneration(SegmentInfos other) { lastGeneration = other.lastGeneration; generation = other.generation; - version = other.version; } final void rollbackCommit(Directory dir) throws IOException { @@ -789,7 +787,12 @@ * segments file, but writes an invalid checksum at the * end, so that it is not visible to readers. Once this * is called you must call {@link #finishCommit} to complete - * the commit or {@link #rollbackCommit} to abort it. */ + * the commit or {@link #rollbackCommit} to abort it. + *

+ * Note: {@link #changed()} should be called prior to this + * method if changes have been made to this {@link SegmentInfos} instance + *

+ **/ final void prepareCommit(Directory dir) throws IOException { if (pendingSegnOutput != null) throw new IllegalStateException("prepareCommit was already called"); @@ -875,7 +878,12 @@ } /** Writes & syncs to the Directory dir, taking care to - * remove the segments file on exception */ + * remove the segments file on exception + *

+ * Note: {@link #changed()} should be called prior to this + * method if changes have been made to this {@link SegmentInfos} instance + *

+ **/ final void commit(Directory dir) throws IOException { prepareCommit(dir); finishCommit(dir); @@ -926,4 +934,10 @@ } return count; } + + /** Call this before committing if changes have been made to the + * segments. */ + public void changed() { + version++; + } } Index: src/java/org/apache/lucene/index/CheckIndex.java =================================================================== --- src/java/org/apache/lucene/index/CheckIndex.java (revision 1043277) +++ src/java/org/apache/lucene/index/CheckIndex.java (working copy) @@ -766,6 +766,7 @@ public void fixIndex(Status result) throws IOException { if (result.partial) throw new IllegalArgumentException("can only fix an index that was fully checked (this status checked a subset of segments)"); + result.newSegments.changed(); result.newSegments.commit(result.dir); } Index: src/java/org/apache/lucene/index/DirectoryReader.java =================================================================== --- src/java/org/apache/lucene/index/DirectoryReader.java (revision 1043277) +++ src/java/org/apache/lucene/index/DirectoryReader.java (working copy) @@ -765,6 +765,7 @@ deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, segmentInfos, null, null); segmentInfos.updateGeneration(deleter.getLastSegmentInfos()); + segmentInfos.changed(); // Checkpoint the state we are about to change, in // case we have to roll back: @@ -777,7 +778,6 @@ // Sync all files we just wrote directory.sync(segmentInfos.files(directory, false)); - segmentInfos.commit(directory); success = true; } finally { Index: src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriter.java (revision 1043277) +++ src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -1099,6 +1099,7 @@ // Record that we have a change (zero out all // segments) pending: changeCount++; + segmentInfos.changed(); } else { segmentInfos.read(directory); @@ -1115,6 +1116,7 @@ oldInfos.read(directory, commit.getSegmentsFileName()); segmentInfos.replace(oldInfos); changeCount++; + segmentInfos.changed(); if (infoStream != null) message("init: loaded commit \"" + commit.getSegmentsFileName() + "\""); } @@ -1132,12 +1134,14 @@ conf.getIndexDeletionPolicy(), segmentInfos, infoStream, docWriter); - if (deleter.startingCommitDeleted) + if (deleter.startingCommitDeleted) { // 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. changeCount++; + segmentInfos.changed(); + } docWriter.setMaxBufferedDeleteTerms(conf.getMaxBufferedDeleteTerms()); docWriter.setRAMBufferSizeMB(conf.getRAMBufferSizeMB()); @@ -2311,6 +2315,7 @@ // name that was previously returned which can cause // problems at least with ConcurrentMergeScheduler. changeCount++; + segmentInfos.changed(); return "_" + Integer.toString(segmentInfos.counter++, Character.MAX_RADIX); } } @@ -2812,6 +2817,7 @@ // Mark that the index has changed ++changeCount; + segmentInfos.changed(); } catch (OutOfMemoryError oom) { handleOOM(oom, "deleteAll"); } finally { @@ -2893,6 +2899,7 @@ */ private synchronized void checkpoint() throws IOException { changeCount++; + segmentInfos.changed(); deleter.checkpoint(segmentInfos, false); } @@ -4461,6 +4468,7 @@ } toSync.remove(toSync.size()-1); changeCount++; + segmentInfos.changed(); } } assert filesExist(toSync); @@ -4675,17 +4683,7 @@ } synchronized boolean nrtIsCurrent(SegmentInfos infos) { - if (!infos.equals(segmentInfos)) { - // if any structural changes (new segments), we are - // stale - return false; - } else if (infos.getGeneration() != segmentInfos.getGeneration()) { - // if any commit took place since we were opened, we - // are stale - return false; - } else { - return !docWriter.anyChanges(); - } + return infos.version == segmentInfos.version && !docWriter.anyChanges(); } synchronized boolean isClosed() { Index: contrib/misc/src/java/org/apache/lucene/index/IndexSplitter.java =================================================================== --- contrib/misc/src/java/org/apache/lucene/index/IndexSplitter.java (revision 1043277) +++ contrib/misc/src/java/org/apache/lucene/index/IndexSplitter.java (working copy) @@ -125,6 +125,7 @@ int idx = getIdx(n); infos.remove(idx); } + infos.changed(); infos.commit(fsDir); } @@ -143,6 +144,7 @@ copyFile(srcFile, destFile); } } + destInfos.changed(); destInfos.commit(destFSDir); // System.out.println("destDir:"+destDir.getAbsolutePath()); } Index: backwards/src/test/org/apache/lucene/index/TestIndexWriterReader.java =================================================================== --- backwards/src/test/org/apache/lucene/index/TestIndexWriterReader.java (revision 1043277) +++ backwards/src/test/org/apache/lucene/index/TestIndexWriterReader.java (working copy) @@ -165,7 +165,7 @@ assertTrue(r1.isCurrent()); writer.commit(); - assertFalse(r1.isCurrent()); + assertTrue(r1.isCurrent()); assertEquals(200, r1.maxDoc());