mirror of https://github.com/apache/lucene.git
LUCENE-1547: fix rare thread hazard in IndexWriter.commit()
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@747251 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
90d98045d8
commit
6fc659a345
|
@ -3610,20 +3610,6 @@ public class IndexWriter {
|
||||||
finishCommit();
|
finishCommit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean committing;
|
|
||||||
|
|
||||||
synchronized private void waitForCommit() {
|
|
||||||
// Only allow a single thread to do the commit, at a time:
|
|
||||||
while(committing)
|
|
||||||
doWait();
|
|
||||||
committing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized private void doneCommit() {
|
|
||||||
committing = false;
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Commits all pending updates (added & deleted
|
* <p>Commits all pending updates (added & deleted
|
||||||
* documents) to the index, and syncs all referenced index
|
* documents) to the index, and syncs all referenced index
|
||||||
|
@ -3670,24 +3656,17 @@ public class IndexWriter {
|
||||||
|
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
|
|
||||||
// Only let one thread do the prepare/finish at a time
|
if (infoStream != null)
|
||||||
waitForCommit();
|
message("commit: start");
|
||||||
|
|
||||||
try {
|
if (autoCommit || pendingCommit == null) {
|
||||||
if (infoStream != null)
|
if (infoStream != null)
|
||||||
message("commit: start");
|
message("commit: now prepare");
|
||||||
|
prepareCommit(commitUserData, true);
|
||||||
|
} else if (infoStream != null)
|
||||||
|
message("commit: already prepared");
|
||||||
|
|
||||||
if (autoCommit || pendingCommit == null) {
|
finishCommit();
|
||||||
if (infoStream != null)
|
|
||||||
message("commit: now prepare");
|
|
||||||
prepareCommit(commitUserData, true);
|
|
||||||
} else if (infoStream != null)
|
|
||||||
message("commit: already prepared");
|
|
||||||
|
|
||||||
finishCommit();
|
|
||||||
} finally {
|
|
||||||
doneCommit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized final void finishCommit() throws CorruptIndexException, IOException {
|
private synchronized final void finishCommit() throws CorruptIndexException, IOException {
|
||||||
|
@ -3745,8 +3724,6 @@ public class IndexWriter {
|
||||||
|
|
||||||
flushCount++;
|
flushCount++;
|
||||||
|
|
||||||
// Make sure no threads are actively adding a document
|
|
||||||
|
|
||||||
flushDeletes |= docWriter.deletesFull();
|
flushDeletes |= docWriter.deletesFull();
|
||||||
|
|
||||||
// When autoCommit=true we must always flush deletes
|
// When autoCommit=true we must always flush deletes
|
||||||
|
@ -3755,6 +3732,7 @@ public class IndexWriter {
|
||||||
// from an updateDocument call
|
// from an updateDocument call
|
||||||
flushDeletes |= autoCommit;
|
flushDeletes |= autoCommit;
|
||||||
|
|
||||||
|
// Make sure no threads are actively adding a document.
|
||||||
// Returns true if docWriter is currently aborting, in
|
// Returns true if docWriter is currently aborting, in
|
||||||
// which case we skip flushing this segment
|
// which case we skip flushing this segment
|
||||||
if (docWriter.pauseAllThreads()) {
|
if (docWriter.pauseAllThreads()) {
|
||||||
|
@ -4891,45 +4869,50 @@ public class IndexWriter {
|
||||||
// since I first started syncing my version, I can
|
// since I first started syncing my version, I can
|
||||||
// safely skip saving myself since I've been
|
// safely skip saving myself since I've been
|
||||||
// superseded:
|
// superseded:
|
||||||
if (myChangeCount > lastCommitChangeCount && (pendingCommit == null || myChangeCount > pendingCommitChangeCount)) {
|
|
||||||
|
|
||||||
// Wait now for any current pending commit to complete:
|
while(true) {
|
||||||
while(pendingCommit != null) {
|
if (myChangeCount <= lastCommitChangeCount) {
|
||||||
if (infoStream != null)
|
if (infoStream != null) {
|
||||||
message("wait for existing pendingCommit to finish...");
|
message("sync superseded by newer infos");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (pendingCommit == null) {
|
||||||
|
// My turn to commit
|
||||||
|
|
||||||
|
if (segmentInfos.getGeneration() > toSync.getGeneration())
|
||||||
|
toSync.updateGeneration(segmentInfos);
|
||||||
|
|
||||||
|
boolean success = false;
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Exception here means nothing is prepared
|
||||||
|
// (this method unwinds everything it did on
|
||||||
|
// an exception)
|
||||||
|
try {
|
||||||
|
toSync.prepareCommit(directory);
|
||||||
|
} finally {
|
||||||
|
// Have our master segmentInfos record the
|
||||||
|
// generations we just prepared. We do this
|
||||||
|
// on error or success so we don't
|
||||||
|
// double-write a segments_N file.
|
||||||
|
segmentInfos.updateGeneration(toSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert pendingCommit == null;
|
||||||
|
setPending = true;
|
||||||
|
pendingCommit = toSync;
|
||||||
|
pendingCommitChangeCount = myChangeCount;
|
||||||
|
success = true;
|
||||||
|
} finally {
|
||||||
|
if (!success && infoStream != null)
|
||||||
|
message("hit exception committing segments file");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Must wait for other commit to complete
|
||||||
doWait();
|
doWait();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (segmentInfos.getGeneration() > toSync.getGeneration())
|
|
||||||
toSync.updateGeneration(segmentInfos);
|
|
||||||
|
|
||||||
boolean success = false;
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Exception here means nothing is prepared
|
|
||||||
// (this method unwinds everything it did on
|
|
||||||
// an exception)
|
|
||||||
try {
|
|
||||||
toSync.prepareCommit(directory);
|
|
||||||
} finally {
|
|
||||||
// Have our master segmentInfos record the
|
|
||||||
// generations we just prepared. We do this
|
|
||||||
// on error or success so we don't
|
|
||||||
// double-write a segments_N file.
|
|
||||||
segmentInfos.updateGeneration(toSync);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert pendingCommit == null;
|
|
||||||
setPending = true;
|
|
||||||
pendingCommit = toSync;
|
|
||||||
pendingCommitChangeCount = myChangeCount;
|
|
||||||
success = true;
|
|
||||||
} finally {
|
|
||||||
if (!success && infoStream != null)
|
|
||||||
message("hit exception committing segments file");
|
|
||||||
}
|
|
||||||
} else if (infoStream != null)
|
|
||||||
message("sync superseded by newer infos");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (infoStream != null)
|
if (infoStream != null)
|
||||||
|
|
Loading…
Reference in New Issue