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 02:30:35 UTC

svn commit: r747251 - /lucene/java/trunk/src/java/org/apache/lucene/index/IndexWriter.java

Author: mikemccand
Date: Tue Feb 24 01:30:35 2009
New Revision: 747251

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

Modified:
    lucene/java/trunk/src/java/org/apache/lucene/index/IndexWriter.java

Modified: lucene/java/trunk/src/java/org/apache/lucene/index/IndexWriter.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/index/IndexWriter.java?rev=747251&r1=747250&r2=747251&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/index/IndexWriter.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/index/IndexWriter.java Tue Feb 24 01:30:35 2009
@@ -3610,20 +3610,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
@@ -3670,24 +3656,17 @@
 
     ensureOpen();
 
-    // Only let one thread do the prepare/finish at a time
-    waitForCommit();
+    if (infoStream != null)
+      message("commit: start");
 
-    try {
+    if (autoCommit || pendingCommit == null) {
       if (infoStream != null)
-        message("commit: start");
-
-      if (autoCommit || pendingCommit == null) {
-        if (infoStream != null)
-          message("commit: now prepare");
-        prepareCommit(commitUserData, true);
-      } else if (infoStream != null)
-        message("commit: already prepared");
+        message("commit: now prepare");
+      prepareCommit(commitUserData, true);
+    } else if (infoStream != null)
+      message("commit: already prepared");
 
-      finishCommit();
-    } finally {
-      doneCommit();
-    }
+    finishCommit();
   }
 
   private synchronized final void finishCommit() throws CorruptIndexException, IOException {
@@ -3745,8 +3724,6 @@
 
     flushCount++;
 
-    // Make sure no threads are actively adding a document
-
     flushDeletes |= docWriter.deletesFull();
 
     // When autoCommit=true we must always flush deletes
@@ -3755,6 +3732,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()) {
@@ -4891,45 +4869,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) {
-              if (infoStream != null)
-                message("wait for existing pendingCommit to finish...");
-              doWait();
-            }
-
-            if (segmentInfos.getGeneration() > toSync.getGeneration())
-              toSync.updateGeneration(segmentInfos);
+          while(true) {
+            if (myChangeCount <= lastCommitChangeCount) {
+              if (infoStream != null) {
+                message("sync superseded by newer infos");
+              }
+              break;
+            } else if (pendingCommit == null) {
+              // My turn to commit
 
-            boolean success = false;
-            try {
+              if (segmentInfos.getGeneration() > toSync.getGeneration())
+                toSync.updateGeneration(segmentInfos);
 
-              // 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 && infoStream != null)
-                message("hit exception committing segments file");
+              break;
+            } else {
+              // Must wait for other commit to complete
+              doWait();
             }
-          } else if (infoStream != null)
-            message("sync superseded by newer infos");
+          }
         }
 
         if (infoStream != null)