You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@lucene.apache.org by mi...@apache.org on 2009/02/24 11:40:20 UTC

svn commit: r747328 - in /lucene/java/branches/lucene_2_4: ./ CHANGES.txt src/java/org/apache/lucene/index/IndexWriter.java

Author: mikemccand
Date: Tue Feb 24 10:40:19 2009
New Revision: 747328

URL: http://svn.apache.org/viewvc?rev=747328&view=rev
Log:
LUCENE-1547: fix rare thread hazard in IndexWriter.commit()

Modified:
    lucene/java/branches/lucene_2_4/   (props changed)
    lucene/java/branches/lucene_2_4/CHANGES.txt
    lucene/java/branches/lucene_2_4/src/java/org/apache/lucene/index/IndexWriter.java

Propchange: lucene/java/branches/lucene_2_4/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb 24 10:40:19 2009
@@ -1 +1 @@
-/lucene/java/trunk:708549,709456,712233,718540,719716,723149,734415,735043,746661
+/lucene/java/trunk:708549,709456,712233,718540,719716,723149,734415,735043,746661,747251

Modified: lucene/java/branches/lucene_2_4/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/branches/lucene_2_4/CHANGES.txt?rev=747328&r1=747327&r2=747328&view=diff
==============================================================================
--- lucene/java/branches/lucene_2_4/CHANGES.txt (original)
+++ lucene/java/branches/lucene_2_4/CHANGES.txt Tue Feb 24 10:40:19 2009
@@ -47,6 +47,9 @@
 11. LUCENE-1544: Fix deadlock in IndexWriter.addIndexes(IndexReader[]).
    (Mike McCandless via Doug Sale)
 
+12. LUCENE-1547: Fix rare thread safety issue if two threads call
+    IndexWriter commit() at the same time.  (Mike McCandless)
+
 ======================= Release 2.4.0 2008-10-06 =======================
 
 Changes in backwards compatibility policy

Modified: lucene/java/branches/lucene_2_4/src/java/org/apache/lucene/index/IndexWriter.java
URL: http://svn.apache.org/viewvc/lucene/java/branches/lucene_2_4/src/java/org/apache/lucene/index/IndexWriter.java?rev=747328&r1=747327&r2=747328&view=diff
==============================================================================
--- lucene/java/branches/lucene_2_4/src/java/org/apache/lucene/index/IndexWriter.java (original)
+++ lucene/java/branches/lucene_2_4/src/java/org/apache/lucene/index/IndexWriter.java Tue Feb 24 10:40:19 2009
@@ -3368,20 +3368,6 @@
     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
    * documents) to the index, and syncs all referenced index
@@ -3411,22 +3397,17 @@
 
     ensureOpen();
 
-    // Only let one thread do the prepare/finish at a time
-    waitForCommit();
-
-    try {
+    if (infoStream != null)
       message("commit: start");
 
-      if (autoCommit || pendingCommit == null) {
+    if (autoCommit || pendingCommit == null) {
+      if (infoStream != null)
         message("commit: now prepare");
-        prepareCommit(true);
-      } else
-        message("commit: already prepared");
+      prepareCommit(true);
+    } else if (infoStream != null)
+      message("commit: already prepared");
 
-      finishCommit();
-    } finally {
-      doneCommit();
-    }
+    finishCommit();
   }
 
   private synchronized final void finishCommit() throws CorruptIndexException, IOException {
@@ -3479,8 +3460,6 @@
 
     flushCount++;
 
-    // Make sure no threads are actively adding a document
-
     flushDeletes |= docWriter.deletesFull();
 
     // When autoCommit=true we must always flush deletes
@@ -3489,6 +3468,7 @@
     // from an updateDocument call
     flushDeletes |= autoCommit;
 
+    // Make sure no threads are actively adding a document.
     // Returns true if docWriter is currently aborting, in
     // which case we skip flushing this segment
     if (docWriter.pauseAllThreads()) {
@@ -4635,44 +4615,50 @@
           // since I first started syncing my version, I can
           // safely skip saving myself since I've been
           // superseded:
-          if (myChangeCount > lastCommitChangeCount && (pendingCommit == null || myChangeCount > pendingCommitChangeCount)) {
 
-            // Wait now for any current pending commit to complete:
-            while(pendingCommit != null) {
-              message("wait for existing pendingCommit to finish...");
-              doWait();
-            }
+          while(true) {
+            if (myChangeCount <= lastCommitChangeCount) {
+              if (infoStream != null) {
+                message("sync superseded by newer infos");
+              }
+              break;
+            } else if (pendingCommit == null) {
+              // My turn to commit
 
-            if (segmentInfos.getGeneration() > toSync.getGeneration())
-              toSync.updateGeneration(segmentInfos);
+              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)
+              boolean success = false;
               try {
-                toSync.prepareCommit(directory);
+
+                // 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 {
-                // 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);
+                if (!success && infoStream != null)
+                  message("hit exception committing segments file");
               }
-
-              assert pendingCommit == null;
-              setPending = true;
-              pendingCommit = toSync;
-              pendingCommitChangeCount = myChangeCount;
-              success = true;
-            } finally {
-              if (!success)
-                message("hit exception committing segments file");
+              break;
+            } else {
+              // Must wait for other commit to complete
+              doWait();
             }
-          } else
-            message("sync superseded by newer infos");
+          }
         }
 
         message("done all syncs");