Author: stefan2
Date: Wed Dec  1 00:15:11 2010
New Revision: 1040832

URL: http://svn.apache.org/viewvc?rev=1040832&view=rev
Log:
Port (not merge) a fix for a FSFS packing race condition from the
performance branch to /trunk: There is a slight time window
between finding the name of a rev file and actually open it. If
the revision in question gets packed just within this window,
we will find the new (and final) file name with just one retry.

* subversion/libsvn_fs_fs/fs_fs.c
  (open_pack_or_rev_file): retry once upon "missing file" error

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c?rev=1040832&r1=1040831&r2=1040832&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c Wed Dec  1 00:15:11 2010
@@ -1903,21 +1903,42 @@ open_pack_or_rev_file(apr_file_t **file,
 {
   svn_error_t *err;
   const char *path;
+  svn_boolean_t retry = FALSE;
 
-  err = svn_fs_fs__path_rev_absolute(&path, fs, rev, pool);
+  do
+    {
+      err = svn_fs_fs__path_rev_absolute(&path, fs, rev, pool);
 
-  if (! err)
-    err = svn_io_file_open(file, path,
-                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
+      /* open the revision file in buffered r/o mode */
+      if (! err)
+        err = svn_io_file_open(file, path,
+                              APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
 
-  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
-    {
-      svn_error_clear(err);
-      return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
-                               _("No such revision %ld"), rev);
+      if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+        {
+          /* Could not open the file. This may happen if the
+           * file once existed but got packed later. */
+          svn_error_clear(err);
+
+          /* if that was our 2nd attempt, leave it at that. */
+          if (retry)
+            return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+                                    _("No such revision %ld"), rev);
+
+          /* we failed for the first time. Refresh cache & retry. */
+          SVN_ERR(update_min_unpacked_rev(fs, pool));
+
+          retry = TRUE;
+        }
+      else
+        {
+          /* the file exists but something prevented us from opnening it */
+          return svn_error_return(err);
+        }
     }
+  while (err);
 
-  return svn_error_return(err);
+  return SVN_NO_ERROR;
 }
 
 /* Given REV in FS, set *REV_OFFSET to REV's offset in the packed file.


Reply via email to