Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 669847) +++ CHANGES.txt (working copy) @@ -76,6 +76,13 @@ returns when the reader is opened on the same commit. (Jason Rutherglen via Mike McCandless) +11. LUCENE-1311: Added IndexReader.listCommits(Directory) static + method to list all commits in a Directory, plus IndexReader.open + methods that accept an IndexCommit and open the index as of that + commit. These methods are only useful if you implement a custom + DeletionPolicy that keeps more than the last commit around. + (Jason Rutherglen via Mike McCandless) + Bug fixes 1. LUCENE-1134: Fixed BooleanQuery.rewrite to only optimize a single Index: src/test/org/apache/lucene/index/TestDeletionPolicy.java =================================================================== --- src/test/org/apache/lucene/index/TestDeletionPolicy.java (revision 669847) +++ src/test/org/apache/lucene/index/TestDeletionPolicy.java (working copy) @@ -22,6 +22,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.Collection; import org.apache.lucene.analysis.WhitespaceAnalyzer; import org.apache.lucene.document.Document; @@ -258,6 +259,7 @@ boolean autoCommit = pass < 2; boolean useCompoundFile = (pass % 2) > 0; + // Never deletes a commit KeepAllDeletionPolicy policy = new KeepAllDeletionPolicy(); Directory dir = new RAMDirectory(); @@ -267,6 +269,8 @@ writer.setUseCompoundFile(useCompoundFile); for(int i=0;i<107;i++) { addDoc(writer); + if (autoCommit && i%10 == 0) + writer.commit(); } writer.close(); @@ -281,6 +285,24 @@ // be exactly 2 commits (one per close above): assertEquals(2, policy.numOnCommit); + // Test listCommits + Collection commits = IndexReader.listCommits(dir); + if (!autoCommit) + // 1 from opening writer + 2 from closing writer + assertEquals(3, commits.size()); + else + // 1 from opening writer + 2 from closing writer + + // 11 from calling writer.commit() explicitly above + assertEquals(14, commits.size()); + + Iterator it = commits.iterator(); + // Make sure we can open a reader on each commit: + while(it.hasNext()) { + IndexCommit commit = (IndexCommit) it.next(); + IndexReader r = IndexReader.open(commit, null); + r.close(); + } + // Simplistic check: just verify all segments_N's still // exist, and, I can open a reader on each: dir.deleteFile(IndexFileNames.SEGMENTS_GEN); Index: src/java/org/apache/lucene/index/DirectoryIndexReader.java =================================================================== --- src/java/org/apache/lucene/index/DirectoryIndexReader.java (revision 669847) +++ src/java/org/apache/lucene/index/DirectoryIndexReader.java (working copy) @@ -18,6 +18,7 @@ */ import java.io.IOException; +import java.io.FileNotFoundException; import java.util.HashSet; import java.util.Collection; @@ -77,9 +78,13 @@ } static DirectoryIndexReader open(final Directory directory, final boolean closeDirectory, final IndexDeletionPolicy deletionPolicy) throws CorruptIndexException, IOException { + return open(directory, closeDirectory, deletionPolicy, null); + } - return (DirectoryIndexReader) new SegmentInfos.FindSegmentsFile(directory) { + static DirectoryIndexReader open(final Directory directory, final boolean closeDirectory, final IndexDeletionPolicy deletionPolicy, final IndexCommit commit) throws CorruptIndexException, IOException { + SegmentInfos.FindSegmentsFile finder = new SegmentInfos.FindSegmentsFile(directory) { + protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException { SegmentInfos infos = new SegmentInfos(); @@ -95,7 +100,17 @@ reader.setDeletionPolicy(deletionPolicy); return reader; } - }.run(); + }; + + if (commit == null) + return (DirectoryIndexReader) finder.run(); + else { + if (directory != commit.getDirectory()) + throw new IOException("the specified commit does not match the specified Directory"); + // This can & will directly throw IOException if the + // specified commit point has been deleted: + return (DirectoryIndexReader) finder.doBody(commit.getSegmentsFileName()); + } } public final synchronized IndexReader reopen() throws CorruptIndexException, IOException { @@ -192,7 +207,7 @@ * @throws IOException if there is a low-level IO error */ protected void doCommit() throws IOException { - if(hasChanges){ + if (hasChanges) { if (segmentInfos != null) { // Default deleter (for backwards compatibility) is @@ -387,4 +402,51 @@ public IndexCommit getIndexCommit() throws IOException { return new ReaderCommit(segmentInfos, directory); } + + /** @see IndexReader#listCommits */ + public static Collection listCommits(Directory dir) throws IOException { + + final String[] files = dir.list(); + if (files == null) + throw new IOException("cannot read directory " + dir + ": list() returned null"); + + Collection commits = new ArrayList(); + + SegmentInfos latest = new SegmentInfos(); + latest.read(dir); + final long currentGen = latest.getGeneration(); + + commits.add(new ReaderCommit(latest, dir)); + + for(int i=0;i