blob: d6411e910003c370c2e2b044410ac31bc91bf84c [file] [log] [blame]
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<files.length;i++) {
+
+ final String fileName = files[i];
+
+ if (fileName.startsWith(IndexFileNames.SEGMENTS) &&
+ !fileName.equals(IndexFileNames.SEGMENTS_GEN) &&
+ SegmentInfos.generationFromSegmentsFileName(fileName) < currentGen) {
+
+ SegmentInfos sis = new SegmentInfos();
+ try {
+ // IOException allowed to throw there, in case
+ // segments_N is corrupt
+ sis.read(dir, fileName);
+ } catch (FileNotFoundException fnfe) {
+ // LUCENE-948: on NFS (and maybe others), if
+ // you have writers switching back and forth
+ // between machines, it's very likely that the
+ // dir listing will be stale and will claim a
+ // file segments_X exists when in fact it
+ // doesn't. So, we catch this and handle it
+ // as if the file does not exist
+ sis = null;
+ }
+
+ if (sis != null)
+ commits.add(new ReaderCommit(sis, dir));
+ }
+ }
+
+ return commits;
+ }
}
Index: src/java/org/apache/lucene/index/IndexCommit.java
===================================================================
--- src/java/org/apache/lucene/index/IndexCommit.java (revision 669847)
+++ src/java/org/apache/lucene/index/IndexCommit.java (working copy)
@@ -75,8 +75,7 @@
}
/**
- * Two IndexCommits are equal if both their Directory and
- * segmentsFileName are equal.
+ * Two IndexCommits are equal if both their Directory and versions are equal.
*/
public boolean equals(Object other) {
if (other instanceof IndexCommit) {
Index: src/java/org/apache/lucene/index/IndexReader.java
===================================================================
--- src/java/org/apache/lucene/index/IndexReader.java (revision 669847)
+++ src/java/org/apache/lucene/index/IndexReader.java (working copy)
@@ -170,7 +170,7 @@
* @throws IOException if there is a low-level IO error
* @param path the path to the index directory */
public static IndexReader open(String path) throws CorruptIndexException, IOException {
- return open(FSDirectory.getDirectory(path), true, null);
+ return open(FSDirectory.getDirectory(path), true, null, null);
}
/** Returns an IndexReader reading the index in an FSDirectory in the named
@@ -180,7 +180,7 @@
* @throws IOException if there is a low-level IO error
*/
public static IndexReader open(File path) throws CorruptIndexException, IOException {
- return open(FSDirectory.getDirectory(path), true, null);
+ return open(FSDirectory.getDirectory(path), true, null, null);
}
/** Returns an IndexReader reading the index in the given Directory.
@@ -189,10 +189,20 @@
* @throws IOException if there is a low-level IO error
*/
public static IndexReader open(final Directory directory) throws CorruptIndexException, IOException {
- return open(directory, false, null);
+ return open(directory, false, null, null);
}
/** Expert: returns an IndexReader reading the index in the given
+ * {@link IndexCommit}.
+ * @param commit the commit point to open
+ * @throws CorruptIndexException if the index is corrupt
+ * @throws IOException if there is a low-level IO error
+ */
+ public static IndexReader open(final IndexCommit commit) throws CorruptIndexException, IOException {
+ return open(commit.getDirectory(), false, null, commit);
+ }
+
+ /** Expert: returns an IndexReader reading the index in the given
* Directory, with a custom {@link IndexDeletionPolicy}.
* @param directory the index directory
* @param deletionPolicy a custom deletion policy (only used
@@ -202,13 +212,28 @@
* @throws IOException if there is a low-level IO error
*/
public static IndexReader open(final Directory directory, IndexDeletionPolicy deletionPolicy) throws CorruptIndexException, IOException {
- return open(directory, false, deletionPolicy);
+ return open(directory, false, deletionPolicy, null);
}
- private static IndexReader open(final Directory directory, final boolean closeDirectory, final IndexDeletionPolicy deletionPolicy) throws CorruptIndexException, IOException {
- return DirectoryIndexReader.open(directory, closeDirectory, deletionPolicy);
+ /** Expert: returns an IndexReader reading the index in the given
+ * Directory, using a specific commit and with a custom {@link IndexDeletionPolicy}.
+ * @param commit the specific {@link IndexCommit} to open;
+ * see {@link IndexReader#listCommits} to list all commits
+ * in a directory
+ * @param deletionPolicy a custom deletion policy (only used
+ * if you use this reader to perform deletes or to set
+ * norms); see {@link IndexWriter} for details.
+ * @throws CorruptIndexException if the index is corrupt
+ * @throws IOException if there is a low-level IO error
+ */
+ public static IndexReader open(final IndexCommit commit, IndexDeletionPolicy deletionPolicy) throws CorruptIndexException, IOException {
+ return open(commit.getDirectory(), false, deletionPolicy, commit);
}
+ private static IndexReader open(final Directory directory, final boolean closeDirectory, final IndexDeletionPolicy deletionPolicy, final IndexCommit commit) throws CorruptIndexException, IOException {
+ return DirectoryIndexReader.open(directory, closeDirectory, deletionPolicy, commit);
+ }
+
/**
* Refreshes an IndexReader if the index has changed since this instance
* was (re)opened.
@@ -975,4 +1000,20 @@
}
}
}
+
+ /** Returns all commit points that exist in the Directory.
+ * Normally, because the default is {@link
+ * KeepOnlyLastCommitDeletionPolicy}, there would be only
+ * one commit point. But if you're using a custom {@link
+ * DeletionPolicy} then there could be many commits.
+ * Once you have a given commit, you can open a reader on
+ * it by calling {@link IndexReader#open(Directory,
+ * IndexCommit)}. There must be at least one commit in
+ * the Directory, else this method throws {@link
+ * java.io.IOException}. Note that if a commit is in
+ * progress while this method is running, that commit
+ * may or may not be returned array. */
+ public static Collection listCommits(Directory dir) throws IOException {
+ return DirectoryIndexReader.listCommits(dir);
+ }
}