You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2010/11/12 12:01:21 UTC

svn commit: r1034342 - /lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/SegmentInfos.java

Author: mikemccand
Date: Fri Nov 12 11:01:21 2010
New Revision: 1034342

URL: http://svn.apache.org/viewvc?rev=1034342&view=rev
Log:
LUCENE-2576: change segments_N retry logic to re-list the directory before falling back to segments_(N-1)

Modified:
    lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/SegmentInfos.java

Modified: lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/SegmentInfos.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/SegmentInfos.java?rev=1034342&r1=1034341&r2=1034342&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/SegmentInfos.java (original)
+++ lucene/dev/trunk/lucene/src/java/org/apache/lucene/index/SegmentInfos.java Fri Nov 12 11:01:21 2010
@@ -470,9 +470,9 @@ public final class SegmentInfos extends 
       long gen = 0;
       int genLookaheadCount = 0;
       IOException exc = null;
-      boolean retry = false;
+      int retryCount = 0;
 
-      int method = 0;
+      boolean useFirstMethod = true;
 
       // Loop until we succeed in calling doBody() without
       // hitting an IOException.  An IOException most likely
@@ -486,14 +486,15 @@ public final class SegmentInfos extends 
       // it.
       
       // We have three methods for determining the current
-      // generation.  We try the first two in parallel, and
-      // fall back to the third when necessary.
+      // generation.  We try the first two in parallel (when
+      // useFirstMethod is true), and fall back to the third
+      // when necessary.
 
       while(true) {
 
-        if (0 == method) {
+        if (useFirstMethod) {
 
-          // Method 1: list the directory and use the highest
+          // List the directory and use the highest
           // segments_N file.  This method works well as long
           // as there is no stale caching on the directory
           // contents (NOTE: NFS clients often have such stale
@@ -504,14 +505,15 @@ public final class SegmentInfos extends 
 
           files = directory.listAll();
           
-          if (files != null)
+          if (files != null) {
             genA = getCurrentSegmentGeneration(files);
-
+          }
+          
           if (infoStream != null) {
             message("directory listing genA=" + genA);
           }
 
-          // Method 2: open segments.gen and read its
+          // Also open segments.gen and read its
           // contents.  Then we take the larger of the two
           // gens.  This way, if either approach is hitting
           // a stale cache (NFS) we have a better chance of
@@ -573,51 +575,42 @@ public final class SegmentInfos extends 
 
           // Pick the larger of the two gen's:
           gen = Math.max(genA, genB);
-          
+
           if (gen == -1) {
             // Neither approach found a generation
             throw new IndexNotFoundException("no segments* file found in " + directory + ": files: " + Arrays.toString(files));
           }
         }
 
-        // Third method (fallback if first & second methods
-        // are not reliable): since both directory cache and
+        if (useFirstMethod && lastGen == gen && retryCount >= 2) {
+          // Give up on first method -- this is 3rd cycle on
+          // listing directory and checking gen file to
+          // attempt to locate the segments file.
+          useFirstMethod = false;
+        }
+
+        // Second method: since both directory cache and
         // file contents cache seem to be stale, just
         // advance the generation.
-        if (1 == method || (0 == method && lastGen == gen && retry)) {
-
-          method = 1;
-
+        if (!useFirstMethod) {
           if (genLookaheadCount < defaultGenLookaheadCount) {
             gen++;
             genLookaheadCount++;
             if (infoStream != null) {
               message("look ahead increment gen to " + gen);
             }
-          }
-        }
-
-        if (lastGen == gen) {
-
-          // This means we're about to try the same
-          // segments_N last tried.  This is allowed,
-          // exactly once, because writer could have been in
-          // the process of writing segments_N last time.
-
-          if (retry) {
-            // OK, we've tried the same segments_N file
-            // twice in a row, so this must be a real
-            // error.  We throw the original exception we
-            // got.
-            throw exc;
           } else {
-            retry = true;
+            // All attempts have failed -- throw first exc:
+            throw exc;
           }
-
-        } else if (0 == method) {
-          // Segment file has advanced since our last loop, so
-          // reset retry:
-          retry = false;
+        } else if (lastGen == gen) {
+          // This means we're about to try the same
+          // segments_N last tried.
+          retryCount++;
+        } else {
+          // Segment file has advanced since our last loop
+          // (we made "progress"), so reset retryCount:
+          retryCount = 0;
         }
 
         lastGen = gen;
@@ -640,13 +633,13 @@ public final class SegmentInfos extends 
           }
 
           if (infoStream != null) {
-            message("primary Exception on '" + segmentFileName + "': " + err + "'; will retry: retry=" + retry + "; gen = " + gen);
+            message("primary Exception on '" + segmentFileName + "': " + err + "'; will retry: retryCount=" + retryCount + "; gen = " + gen);
           }
 
-          if (!retry && gen > 1) {
+          if (gen > 1 && useFirstMethod && retryCount == 1) {
 
-            // This is our first time trying this segments
-            // file (because retry is false), and, there is
+            // This is our second time trying this same segments
+            // file (because retryCount is 1), and, there is
             // possibly a segments_(N-1) (because gen > 1).
             // So, check if the segments_(N-1) exists and
             // try it if so:
@@ -719,7 +712,7 @@ public final class SegmentInfos extends 
       // since lastGeneration isn't incremented:
       try {
         final String segmentFileName = IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
-                                                                             "",
+                                                                              "",
                                                                              generation);
         dir.deleteFile(segmentFileName);
       } catch (Throwable t) {