You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/09/21 17:21:42 UTC

svn commit: r999461 - /subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c

Author: danielsh
Date: Tue Sep 21 15:21:29 2010
New Revision: 999461

URL: http://svn.apache.org/viewvc?rev=999461&view=rev
Log:
On the atomic-revprops branch:

In svnrdump, grab the lock atomically, if possible.
(This was done for svnsync in r999421.)

* subversion/svnsync/main.c
  (is_atomicity_error): New helper.
  (get_lock):
    Take advantage of SVN_RA_CAPABILITY_ATOMIC_REVPROPS if present.
    Grow output LOCK_STRING_P parameter.
  (drive_dumpstream_loader):
    Remove the lock atomically.

Modified:
    subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c

Modified: subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c?rev=999461&r1=999460&r2=999461&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/atomic-revprop/subversion/svnrdump/load_editor.c Tue Sep 21 15:21:29 2010
@@ -56,6 +56,12 @@ commit_callback(const svn_commit_info_t 
   return SVN_NO_ERROR;
 }
 
+/* See subversion/svnsync/main.c for docstring */
+static svn_boolean_t is_atomicity_error(svn_error_t *err)
+{
+  return svn_error_has_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH);
+}
+
 /* Acquire a lock (of sorts) on the repository associated with the
  * given RA SESSION. This lock is just a revprop change attempt in a
  * time-delay loop. This function is duplicated by svnsync in main.c.
@@ -65,14 +71,21 @@ commit_callback(const svn_commit_info_t 
  * applications to avoid duplication.
  */
 static svn_error_t *
-get_lock(svn_ra_session_t *session, apr_pool_t *pool)
+get_lock(const svn_string_t **lock_string_p,
+         svn_ra_session_t *session,
+         apr_pool_t *pool)
 {
   char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
   svn_string_t *mylocktoken, *reposlocktoken;
   apr_status_t apr_err;
+  svn_boolean_t be_atomic;
   apr_pool_t *subpool;
   int i;
 
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
+
   apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
   if (apr_err)
     return svn_error_wrap_apr(apr_err, _("Can't get local hostname"));
@@ -80,10 +93,15 @@ get_lock(svn_ra_session_t *session, apr_
   mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
                                    svn_uuid_generate(pool));
 
+  /* If we succeed, this is what the property will be set to. */
+  *lock_string_p = mylocktoken;
+
   subpool = svn_pool_create(pool);
 
   for (i = 0; i < LOCK_RETRIES; ++i)
     {
+      svn_error_t *err;
+
       svn_pool_clear(subpool);
 
       SVN_ERR(svn_ra_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, &reposlocktoken,
@@ -106,9 +124,27 @@ get_lock(svn_ra_session_t *session, apr_
         }
       else if (i < LOCK_RETRIES - 1)
         {
+          const svn_string_t *unset = NULL;
+
           /* Except in the very last iteration, try to set the lock. */
-          SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK,
-                                         mylocktoken, subpool));
+          err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+                                        be_atomic ? &unset : NULL,
+                                        mylocktoken, subpool);
+
+          if (be_atomic && err && is_atomicity_error(err))
+            /* Someone else has the lock.  Let's loop. */
+            svn_error_clear(err);
+          else if (be_atomic && err == SVN_NO_ERROR)
+            /* We have the lock. 
+
+               However, for compatibility with concurrent svnsync's that don't
+               support atomicity, loop anyway to double-check that they haven't
+               overwritten our lock.
+             */
+            continue;
+          else
+            /* Genuine error, or we aren't atomic and need to loop. */
+            SVN_ERR(err);
         }
     }
 
@@ -602,14 +638,25 @@ drive_dumpstream_loader(svn_stream_t *st
                         svn_ra_session_t *session,
                         apr_pool_t *pool)
 {
-  struct parse_baton *pb;
-  pb = parse_baton;
+  struct parse_baton *pb = parse_baton;
+  const svn_string_t *lock_string;
+  svn_boolean_t be_atomic;
+  svn_error_t *err;
+
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
 
-  SVN_ERR(get_lock(session, pool));
+  SVN_ERR(get_lock(&lock_string, session, pool));
   SVN_ERR(svn_ra_get_repos_root2(session, &(pb->root_url), pool));
   SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, parse_baton,
                                       NULL, NULL, pool));
-  SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, NULL, pool));
+  err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+                                 be_atomic ? &lock_string : NULL, NULL, pool);
+  if (is_atomicity_error(err))
+    return svn_error_quick_wrap(err,
+                                _("\"svnrdump load\"'s lock was stolen; "
+                                  "can't remove it"));
 
   return SVN_NO_ERROR;
 }