You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2012/06/01 22:55:31 UTC

svn commit: r1345346 - in /subversion/trunk/subversion/libsvn_wc: copy.c wc_db.h wc_db_pristine.c

Author: rhuijben
Date: Fri Jun  1 20:55:31 2012
New Revision: 1345346

URL: http://svn.apache.org/viewvc?rev=1345346&view=rev
Log:
Following up on r1345317, move the pristine transfer between working copies
in the wc_db pristine api, to allow using just two sqlite locks instead of
the four that it used to take.

* subversion/libsvn_wc/copy.c
  (copy_pristine_text_if_necessary): Remove function.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_pristine_transfer): New function.

* subversion/libsvn_wc/wc_db_pristine.c
  (pristine_transfer_baton): New struct.
  (pristine_transfer): New function.
  (svn_wc__db_pristine_transfer): New function.

Modified:
    subversion/trunk/subversion/libsvn_wc/copy.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h
    subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c

Modified: subversion/trunk/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/copy.c?rev=1345346&r1=1345345&r2=1345346&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/copy.c (original)
+++ subversion/trunk/subversion/libsvn_wc/copy.c Fri Jun  1 20:55:31 2012
@@ -119,57 +119,6 @@ copy_to_tmpdir(const char **dst_abspath,
   return SVN_NO_ERROR;
 }
 
-
-/* If SRC_ABSPATH and DST_ABSPATH use different pristine stores, copy the
-   pristine text of SRC_ABSPATH (if there is one) into the pristine text
-   store connected to DST_ABSPATH.  This will only happen when copying into
-   a separate WC such as an external directory.
- */
-static svn_error_t *
-copy_pristine_text_if_necessary(svn_wc__db_t *db,
-                                const char *src_abspath,
-                                const char *dst_abspath,
-                                const char *tmpdir_abspath,
-                                const svn_checksum_t *checksum,
-                                svn_cancel_func_t cancel_func,
-                                void *cancel_baton,
-                                apr_pool_t *scratch_pool)
-{
-  svn_boolean_t present;
-  svn_stream_t *src_pristine, *tmp_pristine;
-  const char *tmp_pristine_abspath;
-  const svn_checksum_t *sha1_checksum, *md5_checksum;
-
-  SVN_ERR_ASSERT(checksum->kind == svn_checksum_sha1);
-
-  /* If it's already in DST_ABSPATH's pristine store, we're done. */
-  SVN_ERR(svn_wc__db_pristine_check(&present, db, dst_abspath, checksum,
-                                    scratch_pool));
-  if (present)
-    return SVN_NO_ERROR;
-
-  sha1_checksum = checksum;
-  SVN_ERR(svn_wc__db_pristine_get_md5(&md5_checksum, db,
-                                      src_abspath, checksum,
-                                      scratch_pool, scratch_pool));
-
-  SVN_ERR(svn_wc__db_pristine_read(&src_pristine, NULL, db,
-                                   src_abspath, sha1_checksum,
-                                   scratch_pool, scratch_pool));
-  SVN_ERR(svn_stream_open_unique(&tmp_pristine, &tmp_pristine_abspath,
-                                 tmpdir_abspath, svn_io_file_del_none,
-                                 scratch_pool, scratch_pool));
-  SVN_ERR(svn_stream_copy3(src_pristine, tmp_pristine,
-                           cancel_func, cancel_baton,
-                           scratch_pool));
-  SVN_ERR(svn_wc__db_pristine_install(db, tmp_pristine_abspath,
-                                      sha1_checksum, md5_checksum,
-                                      scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Copy the versioned file SRC_ABSPATH in DB to the path DST_ABSPATH in DB.
    If METADATA_ONLY is true, copy only the versioned metadata,
    otherwise copy both the versioned metadata and the filesystem node (even
@@ -210,23 +159,10 @@ copy_versioned_file(svn_wc__db_t *db,
      ensure the destination WC has a copy of the pristine text. */
 
   if (copy_pristine_file)
-    {
-      const svn_checksum_t *checksum;
-      SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, &checksum, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   db, src_abspath,
-                                   scratch_pool, scratch_pool));
-
-      /* Checksum is NULL for local additions, but that should be handled
-         by our caller*/
-      if (checksum != NULL)
-        SVN_ERR(copy_pristine_text_if_necessary(db, src_abspath, dst_abspath,
-                                                tmpdir_abspath, checksum,
-                                                cancel_func, cancel_baton,
-                                                scratch_pool));
-    }
+    SVN_ERR(svn_wc__db_pristine_transfer(db, src_abspath, NULL,
+                                         dst_op_root_abspath,
+                                         cancel_func, cancel_baton,
+                                         scratch_pool));
 
   /* Prepare a temp copy of the filesystem node.  It is usually a file, but
      copy recursively if it's a dir. */

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1345346&r1=1345345&r2=1345346&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Fri Jun  1 20:55:31 2012
@@ -941,6 +941,18 @@ svn_wc__db_pristine_get_sha1(const svn_c
                              apr_pool_t *scratch_pool);
 
 
+/* If necessary transfers the PRISTINE file of SRC_LOCAL_ABSPATH to the
+   working copy identified by DST_WRI_ABSPATH. If CHECKSUM is not NULL, use
+   CHECKSUM to identify which pristine file to transfer. */
+svn_error_t *
+svn_wc__db_pristine_transfer(svn_wc__db_t *db,
+                             const char *src_local_abspath,
+                             const svn_checksum_t *checksum,
+                             const char *dst_wri_abspath,
+                             svn_cancel_func_t cancel_func,
+                             void *cancel_baton,
+                             apr_pool_t *scratch_pool);
+
 /* Remove the pristine text with SHA-1 checksum SHA1_CHECKSUM from the
  * pristine store, iff it is not referenced by any of the (other) WC DB
  * tables. */

Modified: subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c?rev=1345346&r1=1345345&r2=1345346&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c Fri Jun  1 20:55:31 2012
@@ -523,6 +523,176 @@ svn_wc__db_pristine_get_sha1(const svn_c
   return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
+/* Baton for pristine_transfer() */
+struct pristine_transfer_baton
+{
+  svn_wc__db_wcroot_t *src_wcroot;
+  svn_wc__db_wcroot_t *dst_wcroot;
+  svn_cancel_func_t cancel_func;
+  void * cancel_baton;
+
+  /* pristine install baton, filled from pristine_transfer() */
+  struct pristine_install_baton_t ib;
+};
+
+/* Transaction implementation of svn_wc__db_pristine_transfer().
+   Calls itself again to obtain locks in both working copies */
+static svn_error_t *
+pristine_transfer(void *baton, svn_wc__db_wcroot_t *wcroot,
+                  const char *local_relpath, apr_pool_t *scratch_pool)
+{
+  struct pristine_transfer_baton *tb = baton;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  /* Is this the initial call or the recursive call? */
+  if (wcroot == tb->dst_wcroot)
+    {
+      /* The initial call: */
+
+      /* Get all the info within a src wcroot lock */
+      SVN_ERR(svn_wc__db_with_txn(tb->src_wcroot, local_relpath,
+                                  pristine_transfer, tb, scratch_pool));
+
+      /* And do the final install, while we still have the dst lock */
+      if (tb->ib.tempfile_abspath)
+        SVN_ERR(pristine_install_txn(&(tb->ib), tb->dst_wcroot->sdb,
+                                     scratch_pool));
+      return SVN_NO_ERROR;
+    }
+
+  /* We have a lock on tb->dst_wcroot and tb->src_wcroot */
+
+  /* Get the right checksum if it wasn't passed */
+  if (!tb->ib.sha1_checksum)
+    {
+      SVN_ERR(svn_sqlite__get_statement(&stmt, tb->src_wcroot->sdb,
+                                        STMT_SELECT_NODE_INFO));
+
+      SVN_ERR(svn_sqlite__bindf(stmt, "is",
+                                 tb->src_wcroot->wc_id, local_relpath));
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+      if (have_row)
+        SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.sha1_checksum), stmt, 6,
+                                            scratch_pool));
+
+      SVN_ERR(svn_sqlite__reset(stmt));
+
+      if (!tb->ib.sha1_checksum)
+        return SVN_NO_ERROR; /* Nothing to transfer */
+    }
+
+  /* Check if we have the pristine in the destination wcroot */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, tb->dst_wcroot->sdb,
+                                    STMT_SELECT_PRISTINE));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->ib.sha1_checksum,
+                                    scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  /* Destination repository already has this pristine. We're done */
+  if (have_row)
+    return SVN_NO_ERROR;
+
+  /* Verify if the pristine actually exists and get the MD5 in one query */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, tb->src_wcroot->sdb,
+                                    STMT_SELECT_PRISTINE));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->ib.sha1_checksum,
+                                    scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (!have_row)
+    {
+      return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
+                               _("The pristine text with checksum '%s' was "
+                                 "not found"),
+                               svn_checksum_to_cstring_display(
+                                        tb->ib.sha1_checksum, scratch_pool));
+    }
+  SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.md5_checksum), stmt, 0,
+                                      scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  /* We now have read locks in both working copies, so we can safely copy the
+     file to the temp location of the destination working copy */
+  {
+    svn_stream_t *src_stream;
+    svn_stream_t *dst_stream;
+    const char *tmp_abspath;
+    const char *src_abspath;
+
+    SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath,
+                                   pristine_get_tempdir(tb->dst_wcroot,
+                                                        scratch_pool,
+                                                        scratch_pool),
+                                   svn_io_file_del_on_pool_cleanup,
+                                   scratch_pool, scratch_pool));
+
+    SVN_ERR(get_pristine_fname(&src_abspath, tb->src_wcroot->abspath,
+                               tb->ib.sha1_checksum,
+                               scratch_pool, scratch_pool));
+
+    SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
+                                     scratch_pool, scratch_pool));
+
+    /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */
+    SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
+                             tb->cancel_func, tb->cancel_baton,
+                             scratch_pool));
+
+    /* And now set the right information to install once we leave the
+       src transaction */
+
+    SVN_ERR(get_pristine_fname(&(tb->ib.pristine_abspath),
+                               tb->dst_wcroot->abspath,
+                               tb->ib.sha1_checksum,
+                               scratch_pool, scratch_pool));
+    tb->ib.tempfile_abspath = tmp_abspath;
+  }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_pristine_transfer(svn_wc__db_t *db,
+                             const char *src_local_abspath,
+                             const svn_checksum_t *checksum,
+                             const char *dst_wri_abspath,
+                             svn_cancel_func_t cancel_func,
+                             void *cancel_baton,
+                             apr_pool_t *scratch_pool)
+{
+  const char *src_relpath;
+  const char *dst_relpath;
+  struct pristine_transfer_baton tb;
+  memset(&tb, 0, sizeof(tb));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&tb.src_wcroot, &src_relpath,
+                                                db, src_local_abspath,
+                                                scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(tb.src_wcroot);
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&tb.dst_wcroot, &dst_relpath,
+                                                db, dst_wri_abspath,
+                                                scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(tb.dst_wcroot);
+
+  if (tb.src_wcroot == tb.dst_wcroot
+      || tb.src_wcroot->sdb == tb.dst_wcroot->sdb)
+    {
+      return SVN_NO_ERROR; /* Nothing to transfer */
+    }
+
+  tb.cancel_func = cancel_func;
+  tb.cancel_baton = cancel_baton;
+
+  return svn_error_trace(svn_wc__db_with_txn(tb.dst_wcroot, src_relpath,
+                                             pristine_transfer, &tb,
+                                             scratch_pool));
+}
+
+
+
 
 /* Remove the file at FILE_ABSPATH in such a way that we could re-create a
  * new file of the same name at any time thereafter.
@@ -708,7 +878,6 @@ pristine_cleanup_wcroot(svn_wc__db_wcroo
   return SVN_NO_ERROR;
 }
 
-
 svn_error_t *
 svn_wc__db_pristine_cleanup(svn_wc__db_t *db,
                             const char *wri_abspath,