mirror of https://github.com/apache/lucene.git
LUCENE-1184: allow SnapshotDeletionPolicy to be re-used across close/open of IndexWriter
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@631223 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6302172390
commit
d7d1d680f2
|
@ -101,6 +101,10 @@ New features
|
||||||
huge index might not stop within the specified time.
|
huge index might not stop within the specified time.
|
||||||
(Sean Timm via Doron Cohen)
|
(Sean Timm via Doron Cohen)
|
||||||
|
|
||||||
|
8. LUCENE-1184: Allow SnapshotDeletionPolicy to be re-used across
|
||||||
|
close/re-open of IndexWriter while still protecting an open
|
||||||
|
snapshot (Tim Brennan via Mike McCandless)
|
||||||
|
|
||||||
Optimizations
|
Optimizations
|
||||||
|
|
||||||
1. LUCENE-705: When building a compound file, use
|
1. LUCENE-705: When building a compound file, use
|
||||||
|
|
|
@ -187,7 +187,7 @@ final class IndexFileDeleter {
|
||||||
sis = null;
|
sis = null;
|
||||||
}
|
}
|
||||||
if (sis != null) {
|
if (sis != null) {
|
||||||
CommitPoint commitPoint = new CommitPoint(sis);
|
CommitPoint commitPoint = new CommitPoint(commitsToDelete, directory, sis);
|
||||||
if (sis.getGeneration() == segmentInfos.getGeneration()) {
|
if (sis.getGeneration() == segmentInfos.getGeneration()) {
|
||||||
currentCommitPoint = commitPoint;
|
currentCommitPoint = commitPoint;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ final class IndexFileDeleter {
|
||||||
}
|
}
|
||||||
if (infoStream != null)
|
if (infoStream != null)
|
||||||
message("forced open of current segments file " + segmentInfos.getCurrentSegmentFileName());
|
message("forced open of current segments file " + segmentInfos.getCurrentSegmentFileName());
|
||||||
currentCommitPoint = new CommitPoint(sis);
|
currentCommitPoint = new CommitPoint(commitsToDelete, directory, sis);
|
||||||
commits.add(currentCommitPoint);
|
commits.add(currentCommitPoint);
|
||||||
incRef(sis, true);
|
incRef(sis, true);
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@ final class IndexFileDeleter {
|
||||||
|
|
||||||
if (isCommit) {
|
if (isCommit) {
|
||||||
// Append to our commits list:
|
// Append to our commits list:
|
||||||
commits.add(new CommitPoint(segmentInfos));
|
commits.add(new CommitPoint(commitsToDelete, directory, segmentInfos));
|
||||||
|
|
||||||
// Tell policy so it can remove commits:
|
// Tell policy so it can remove commits:
|
||||||
policy.onCommit(commits);
|
policy.onCommit(commits);
|
||||||
|
@ -569,14 +569,18 @@ final class IndexFileDeleter {
|
||||||
* equals.
|
* equals.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final private class CommitPoint implements Comparable, IndexCommitPoint {
|
final private static class CommitPoint implements Comparable, IndexCommitPoint {
|
||||||
|
|
||||||
long gen;
|
long gen;
|
||||||
List files;
|
List files;
|
||||||
String segmentsFileName;
|
String segmentsFileName;
|
||||||
boolean deleted;
|
boolean deleted;
|
||||||
|
Directory directory;
|
||||||
|
Collection commitsToDelete;
|
||||||
|
|
||||||
public CommitPoint(SegmentInfos segmentInfos) throws IOException {
|
public CommitPoint(Collection commitsToDelete, Directory directory, SegmentInfos segmentInfos) throws IOException {
|
||||||
|
this.directory = directory;
|
||||||
|
this.commitsToDelete = commitsToDelete;
|
||||||
segmentsFileName = segmentInfos.getCurrentSegmentFileName();
|
segmentsFileName = segmentInfos.getCurrentSegmentFileName();
|
||||||
int size = segmentInfos.size();
|
int size = segmentInfos.size();
|
||||||
files = new ArrayList(size);
|
files = new ArrayList(size);
|
||||||
|
|
|
@ -31,13 +31,17 @@ import java.io.IOException;
|
||||||
* we wrap another arbitrary {@link IndexDeletionPolicy}, this
|
* we wrap another arbitrary {@link IndexDeletionPolicy}, this
|
||||||
* gives you the freedom to continue using whatever {@link
|
* gives you the freedom to continue using whatever {@link
|
||||||
* IndexDeletionPolicy} you would normally want to use with your
|
* IndexDeletionPolicy} you would normally want to use with your
|
||||||
* index. */
|
* index. Note that you can re-use a single instance of
|
||||||
|
* SnapshotDeletionPolicy across multiple writers as long
|
||||||
|
* as they are against the same index Directory. Any
|
||||||
|
* snapshot held when a writer is closed will "survive"
|
||||||
|
* when the next writer is opened. */
|
||||||
|
|
||||||
public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
|
public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
|
||||||
|
|
||||||
private IndexCommitPoint lastCommit;
|
private IndexCommitPoint lastCommit;
|
||||||
private IndexDeletionPolicy primary;
|
private IndexDeletionPolicy primary;
|
||||||
private IndexCommitPoint snapshot;
|
private String snapshot;
|
||||||
|
|
||||||
public SnapshotDeletionPolicy(IndexDeletionPolicy primary) {
|
public SnapshotDeletionPolicy(IndexDeletionPolicy primary) {
|
||||||
this.primary = primary;
|
this.primary = primary;
|
||||||
|
@ -64,10 +68,10 @@ public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
|
||||||
* you release the snapshot. */
|
* you release the snapshot. */
|
||||||
public synchronized IndexCommitPoint snapshot() {
|
public synchronized IndexCommitPoint snapshot() {
|
||||||
if (snapshot == null)
|
if (snapshot == null)
|
||||||
snapshot = lastCommit;
|
snapshot = lastCommit.getSegmentsFileName();
|
||||||
else
|
else
|
||||||
throw new IllegalStateException("snapshot is already set; please call release() first");
|
throw new IllegalStateException("snapshot is already set; please call release() first");
|
||||||
return snapshot;
|
return lastCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Release the currently held snapshot. */
|
/** Release the currently held snapshot. */
|
||||||
|
@ -93,7 +97,7 @@ public class SnapshotDeletionPolicy implements IndexDeletionPolicy {
|
||||||
synchronized(SnapshotDeletionPolicy.this) {
|
synchronized(SnapshotDeletionPolicy.this) {
|
||||||
// Suppress the delete request if this commit point is
|
// Suppress the delete request if this commit point is
|
||||||
// our current snapshot.
|
// our current snapshot.
|
||||||
if (snapshot != cp)
|
if (snapshot == null || !snapshot.equals(getSegmentsFileName()))
|
||||||
cp.delete();
|
cp.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,44 @@ public class TestSnapshotDeletionPolicy extends LuceneTestCase
|
||||||
runTest(dir2);
|
runTest(dir2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testReuseAcrossWriters() throws IOException {
|
||||||
|
Directory dir = new MockRAMDirectory();
|
||||||
|
|
||||||
|
SnapshotDeletionPolicy dp = new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy());
|
||||||
|
IndexWriter writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp,
|
||||||
|
IndexWriter.MaxFieldLength.LIMITED);
|
||||||
|
// Force frequent commits
|
||||||
|
writer.setMaxBufferedDocs(2);
|
||||||
|
Document doc = new Document();
|
||||||
|
doc.add(new Field("content", "aaa", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
|
||||||
|
for(int i=0;i<7;i++)
|
||||||
|
writer.addDocument(doc);
|
||||||
|
IndexCommitPoint cp = dp.snapshot();
|
||||||
|
copyFiles(dir, dp, cp);
|
||||||
|
writer.close();
|
||||||
|
copyFiles(dir, dp, cp);
|
||||||
|
|
||||||
|
writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp,
|
||||||
|
IndexWriter.MaxFieldLength.LIMITED);
|
||||||
|
copyFiles(dir, dp, cp);
|
||||||
|
for(int i=0;i<7;i++)
|
||||||
|
writer.addDocument(doc);
|
||||||
|
copyFiles(dir, dp, cp);
|
||||||
|
writer.close();
|
||||||
|
copyFiles(dir, dp, cp);
|
||||||
|
dp.release();
|
||||||
|
writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp,
|
||||||
|
IndexWriter.MaxFieldLength.LIMITED);
|
||||||
|
writer.close();
|
||||||
|
try {
|
||||||
|
copyFiles(dir, dp, cp);
|
||||||
|
fail("did not hit expected IOException");
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
dir.close();
|
||||||
|
}
|
||||||
|
|
||||||
private void runTest(Directory dir) throws IOException {
|
private void runTest(Directory dir) throws IOException {
|
||||||
// Run for ~7 seconds
|
// Run for ~7 seconds
|
||||||
final long stopTime = System.currentTimeMillis() + 7000;
|
final long stopTime = System.currentTimeMillis() + 7000;
|
||||||
|
@ -82,9 +120,9 @@ public class TestSnapshotDeletionPolicy extends LuceneTestCase
|
||||||
for(int i=0;i<27;i++) {
|
for(int i=0;i<27;i++) {
|
||||||
try {
|
try {
|
||||||
writer.addDocument(doc);
|
writer.addDocument(doc);
|
||||||
} catch (IOException cie) {
|
} catch (Throwable t) {
|
||||||
RuntimeException re = new RuntimeException("addDocument failed");
|
RuntimeException re = new RuntimeException("addDocument failed");
|
||||||
re.initCause(cie);
|
re.initCause(t);
|
||||||
throw re;
|
throw re;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,27 +175,9 @@ public class TestSnapshotDeletionPolicy extends LuceneTestCase
|
||||||
* just to test that the files indeed exist and are
|
* just to test that the files indeed exist and are
|
||||||
* readable even while the index is changing. */
|
* readable even while the index is changing. */
|
||||||
public void backupIndex(Directory dir, SnapshotDeletionPolicy dp) throws IOException {
|
public void backupIndex(Directory dir, SnapshotDeletionPolicy dp) throws IOException {
|
||||||
|
|
||||||
// To backup an index we first take a snapshot:
|
// To backup an index we first take a snapshot:
|
||||||
IndexCommitPoint cp = dp.snapshot();
|
|
||||||
try {
|
try {
|
||||||
|
copyFiles(dir, dp, dp.snapshot());
|
||||||
// While we hold the snapshot, and nomatter how long
|
|
||||||
// we take to do the backup, the IndexWriter will
|
|
||||||
// never delete the files in the snapshot:
|
|
||||||
Collection files = cp.getFileNames();
|
|
||||||
Iterator it = files.iterator();
|
|
||||||
while(it.hasNext()) {
|
|
||||||
final String fileName = (String) it.next();
|
|
||||||
// NOTE: in a real backup you would not use
|
|
||||||
// readFile; you would need to use something else
|
|
||||||
// that copies the file to a backup location. This
|
|
||||||
// could even be a spawned shell process (eg "tar",
|
|
||||||
// "zip") that takes the list of files and builds a
|
|
||||||
// backup.
|
|
||||||
readFile(dir, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
// Make sure to release the snapshot, otherwise these
|
// Make sure to release the snapshot, otherwise these
|
||||||
// files will never be deleted during this IndexWriter
|
// files will never be deleted during this IndexWriter
|
||||||
|
@ -166,6 +186,25 @@ public class TestSnapshotDeletionPolicy extends LuceneTestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyFiles(Directory dir, SnapshotDeletionPolicy dp, IndexCommitPoint cp) throws IOException {
|
||||||
|
|
||||||
|
// While we hold the snapshot, and nomatter how long
|
||||||
|
// we take to do the backup, the IndexWriter will
|
||||||
|
// never delete the files in the snapshot:
|
||||||
|
Collection files = cp.getFileNames();
|
||||||
|
Iterator it = files.iterator();
|
||||||
|
while(it.hasNext()) {
|
||||||
|
final String fileName = (String) it.next();
|
||||||
|
// NOTE: in a real backup you would not use
|
||||||
|
// readFile; you would need to use something else
|
||||||
|
// that copies the file to a backup location. This
|
||||||
|
// could even be a spawned shell process (eg "tar",
|
||||||
|
// "zip") that takes the list of files and builds a
|
||||||
|
// backup.
|
||||||
|
readFile(dir, fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
|
|
||||||
private void readFile(Directory dir, String name) throws IOException {
|
private void readFile(Directory dir, String name) throws IOException {
|
||||||
|
|
Loading…
Reference in New Issue