LUCENE-3189: make sure we sync on IW when invoking IFD

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1166821 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael McCandless 2011-09-08 17:33:17 +00:00
parent 31495a1d2c
commit 0d34e80016
4 changed files with 43 additions and 7 deletions

View File

@ -723,7 +723,7 @@ class DirectoryReader extends IndexReader implements Cloneable {
// KeepOnlyLastCommitDeleter:
IndexFileDeleter deleter = new IndexFileDeleter(directory,
deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy,
segmentInfos, null, codecs);
segmentInfos, null, codecs, null);
segmentInfos.updateGeneration(deleter.getLastSegmentInfos());
segmentInfos.changed();

View File

@ -108,6 +108,9 @@ final class IndexFileDeleter {
* infoStream != null */
public static boolean VERBOSE_REF_COUNTS = false;
// Used only for assert
private final IndexWriter writer;
void setInfoStream(PrintStream infoStream) {
this.infoStream = infoStream;
if (infoStream != null) {
@ -121,6 +124,11 @@ final class IndexFileDeleter {
private final FilenameFilter indexFilenameFilter;
// called only from assert
private boolean locked() {
return writer == null || Thread.holdsLock(writer);
}
/**
* Initialize the deleter: find all previous commits in
* the Directory, incref the files they reference, call
@ -129,8 +137,10 @@ final class IndexFileDeleter {
* @throws CorruptIndexException if the index is corrupt
* @throws IOException if there is a low-level IO error
*/
public IndexFileDeleter(Directory directory, IndexDeletionPolicy policy, SegmentInfos segmentInfos, PrintStream infoStream, CodecProvider codecs) throws CorruptIndexException, IOException {
public IndexFileDeleter(Directory directory, IndexDeletionPolicy policy, SegmentInfos segmentInfos,
PrintStream infoStream, CodecProvider codecs, IndexWriter writer) throws CorruptIndexException, IOException {
this.infoStream = infoStream;
this.writer = writer;
final String currentSegmentsFile = segmentInfos.getCurrentSegmentFileName();
@ -347,6 +357,8 @@ final class IndexFileDeleter {
* that segment.
*/
public void refresh(String segmentName) throws IOException {
assert locked();
String[] files = directory.listAll();
String segmentPrefix1;
String segmentPrefix2;
@ -377,12 +389,14 @@ final class IndexFileDeleter {
// Set to null so that we regenerate the list of pending
// files; else we can accumulate same file more than
// once
assert locked();
deletable = null;
refresh(null);
}
public void close() throws IOException {
// DecRef old files from the last checkpoint, if any:
assert locked();
int size = lastFiles.size();
if (size > 0) {
for(int i=0;i<size;i++) {
@ -404,6 +418,7 @@ final class IndexFileDeleter {
* unused commits again.
*/
void revisitPolicy() throws IOException {
assert locked();
if (infoStream != null) {
message("now revisitPolicy");
}
@ -415,6 +430,7 @@ final class IndexFileDeleter {
}
public void deletePendingFiles() throws IOException {
assert locked();
if (deletable != null) {
List<String> oldDeletable = deletable;
deletable = null;
@ -449,6 +465,7 @@ final class IndexFileDeleter {
* removed, we decref their files as well.
*/
public void checkpoint(SegmentInfos segmentInfos, boolean isCommit) throws IOException {
assert locked();
if (infoStream != null) {
message("now checkpoint \"" + segmentInfos.toString(directory) + "\" [" + segmentInfos.size() + " segments " + "; isCommit = " + isCommit + "]");
@ -483,6 +500,7 @@ final class IndexFileDeleter {
}
void incRef(SegmentInfos segmentInfos, boolean isCommit) throws IOException {
assert locked();
// If this is a commit point, also incRef the
// segments_N file:
for( final String fileName: segmentInfos.files(directory, isCommit) ) {
@ -491,12 +509,14 @@ final class IndexFileDeleter {
}
void incRef(Collection<String> files) throws IOException {
assert locked();
for(final String file : files) {
incRef(file);
}
}
void incRef(String fileName) throws IOException {
assert locked();
RefCount rc = getRefCount(fileName);
if (infoStream != null && VERBOSE_REF_COUNTS) {
message(" IncRef \"" + fileName + "\": pre-incr count is " + rc.count);
@ -505,12 +525,14 @@ final class IndexFileDeleter {
}
void decRef(Collection<String> files) throws IOException {
assert locked();
for(final String file : files) {
decRef(file);
}
}
void decRef(String fileName) throws IOException {
assert locked();
RefCount rc = getRefCount(fileName);
if (infoStream != null && VERBOSE_REF_COUNTS) {
message(" DecRef \"" + fileName + "\": pre-decr count is " + rc.count);
@ -524,12 +546,14 @@ final class IndexFileDeleter {
}
void decRef(SegmentInfos segmentInfos) throws IOException {
assert locked();
for (final String file : segmentInfos.files(directory, false)) {
decRef(file);
}
}
public boolean exists(String fileName) {
assert locked();
if (!refCounts.containsKey(fileName)) {
return false;
} else {
@ -538,6 +562,7 @@ final class IndexFileDeleter {
}
private RefCount getRefCount(String fileName) {
assert locked();
RefCount rc;
if (!refCounts.containsKey(fileName)) {
rc = new RefCount(fileName);
@ -549,6 +574,7 @@ final class IndexFileDeleter {
}
void deleteFiles(List<String> files) throws IOException {
assert locked();
for(final String file: files) {
deleteFile(file);
}
@ -557,6 +583,7 @@ final class IndexFileDeleter {
/** Deletes the specified files, but only if they are new
* (have not yet been incref'd). */
void deleteNewFiles(Collection<String> files) throws IOException {
assert locked();
for (final String fileName: files) {
if (!refCounts.containsKey(fileName)) {
if (infoStream != null) {
@ -569,6 +596,7 @@ final class IndexFileDeleter {
void deleteFile(String fileName)
throws IOException {
assert locked();
try {
if (infoStream != null) {
message("delete \"" + fileName + "\"");

View File

@ -910,9 +910,12 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
// Default deleter (for backwards compatibility) is
// KeepOnlyLastCommitDeleter:
deleter = new IndexFileDeleter(directory,
conf.getIndexDeletionPolicy(),
segmentInfos, infoStream, codecs);
synchronized(this) {
deleter = new IndexFileDeleter(directory,
conf.getIndexDeletionPolicy(),
segmentInfos, infoStream,
codecs, this);
}
if (deleter.startingCommitDeleted) {
// Deletion policy deleted the "head" commit point.
@ -2578,7 +2581,9 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
// delete new non cfs files directly: they were never
// registered with IFD
deleter.deleteNewFiles(info.files());
synchronized(this) {
deleter.deleteNewFiles(info.files());
}
info.setUseCompoundFile(true);
}
@ -2804,7 +2809,9 @@ public class IndexWriter implements Closeable, TwoPhaseCommit {
success = true;
} finally {
if (!success) {
deleter.decRef(toCommit);
synchronized (this) {
deleter.decRef(toCommit);
}
}
}

View File

@ -1117,6 +1117,7 @@ public class TestIndexWriter extends LuceneTestCase {
IndexWriterConfig conf = newIndexWriterConfig(
TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2);
w = new IndexWriter(dir, conf);
w.setInfoStream(VERBOSE ? System.out : null);
Document doc = new Document();
doc.add(newField("field", "some text contents", storedTextType));