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 2013/01/10 14:40:41 UTC

svn commit: r1431352 - in /subversion/trunk/subversion/libsvn_wc: copy.c wc-queries.sql wc_db.h wc_db_pristine.c

Author: rhuijben
Date: Thu Jan 10 13:40:40 2013
New Revision: 1431352

URL: http://svn.apache.org/viewvc?rev=1431352&view=rev
Log:
Use Sqlite to determine which pristines must be transferred on copy/move
operations to avoid having to do this for every node separately.

Extracting this from the copy/move code allows moving more copy handling in
the db state.

Avoid copying pristines that already exist in the destination working copy.

* subversion/libsvn_wc/copy.c
  (copy_versioned_file): Instead of moving every separate pristine here...
  (copy_or_move): Do this in a single step here.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_SELECT_COPY_PRISTINES): New query, selecting pristines of all relevant
    layers.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_pristine_transfer): Document as recursive.

* subversion/libsvn_wc/wc_db_pristine.c
  (includes): Add svn_pools.h.
  (pristine_transfer_txn2): Remove function.
  (maybe_transfer_one_pristine): New function.

  (pristine_transfer_txn1): Rename to ...
  (pristine_transfer_txn): ... this. Use STMT_SELECT_COPY_PRISTINES to iterate
    through all nodes and to keep a read lock on src_wcroot.

  (svn_wc__db_pristine_transfer): Update caller.

Modified:
    subversion/trunk/subversion/libsvn_wc/copy.c
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    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=1431352&r1=1431351&r2=1431352&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/copy.c (original)
+++ subversion/trunk/subversion/libsvn_wc/copy.c Thu Jan 10 13:40:40 2013
@@ -196,12 +196,6 @@ copy_versioned_file(svn_wc__db_t *db,
   /* In case we are copying from one WC to another (e.g. an external dir),
      ensure the destination WC has a copy of the pristine text. */
 
-  if (copy_pristine_file)
-    SVN_ERR(svn_wc__db_pristine_transfer(db, src_abspath,
-                                         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. */
   if (!metadata_only)
@@ -772,6 +766,11 @@ copy_or_move(svn_boolean_t *move_degrade
         is_move = FALSE;
     }
 
+  if (!within_one_wc)
+    SVN_ERR(svn_wc__db_pristine_transfer(db, src_abspath, dst_wcroot_abspath,
+                                         cancel_func, cancel_baton,
+                                         scratch_pool));
+
   if (src_db_kind == svn_kind_file
       || src_db_kind == svn_kind_symlink)
     {

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1431352&r1=1431351&r2=1431352&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Thu Jan 10 13:40:40 2013
@@ -751,6 +751,25 @@ WHERE refcount = 0
 DELETE FROM pristine
 WHERE checksum = ?1 AND refcount = 0
 
+-- STMT_SELECT_COPY_PRISTINES
+/* For the root itself */
+SELECT n.checksum, md5_checksum, size
+FROM nodes_current n
+LEFT JOIN pristine p ON n.checksum = p.checksum
+WHERE wc_id = ?1
+  AND n.local_relpath = ?2
+  AND n.checksum IS NOT NULL
+UNION ALL
+/* And all descendants */
+SELECT n.checksum, md5_checksum, size
+FROM nodes n
+LEFT JOIN pristine p ON n.checksum = p.checksum
+WHERE wc_id = ?1
+  AND IS_STRICT_DESCENDANT_OF(n.local_relpath, ?2)
+  AND op_depth >=
+      (SELECT MAX(op_depth) FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2)
+  AND n.checksum IS NOT NULL
+
 -- STMT_VACUUM
 VACUUM
 

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1431352&r1=1431351&r2=1431352&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Thu Jan 10 13:40:40 2013
@@ -994,8 +994,8 @@ 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 necessary transfers the PRISTINE files of the tree rooted at
+   SRC_LOCAL_ABSPATH to the working copy identified by DST_WRI_ABSPATH. */
 svn_error_t *
 svn_wc__db_pristine_transfer(svn_wc__db_t *db,
                              const char *src_local_abspath,

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=1431352&r1=1431351&r2=1431352&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c Thu Jan 10 13:40:40 2013
@@ -25,6 +25,7 @@
 
 #define SVN_WC__I_AM_WC_DB
 
+#include "svn_pools.h"
 #include "svn_dirent_uri.h"
 
 #include "wc.h"
@@ -500,118 +501,84 @@ svn_wc__db_pristine_get_sha1(const svn_c
   return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
-/* Transaction implementation of svn_wc__db_pristine_transfer().
-   We have a lock on DST_WCROOT and a lock on SRC_WCROOT.
-
-   Outputs:
-   *TEMPFILE_ABSPATH is the path to the source file that is to be moved
-   into place.
-   *PRISTINE_ABSPATH is the target path for the file (within the pristine
-   store).
-   *SHA1_CHECKSUM is the pristine text's SHA-1 checksum.
-   *MD5_CHECKSUM is the pristine text's MD-5 checksum.
-
-   If there is nothing to transfer (it is not found in the source, or is
-   already in the destination), then set *TEMPFILE_ABSPATH_P to NULL.
- */
+/* Handle the moving of a pristine from SRC_WCROOT to DST_WCROOT. The existing
+   pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM and SIZE */
 static svn_error_t *
-pristine_transfer_txn2(const char **tempfile_abspath,
-                       const char **pristine_abspath,
-                       const svn_checksum_t **sha1_checksum,
-                       const svn_checksum_t **md5_checksum,
-                       svn_wc__db_wcroot_t *src_wcroot,
-                       svn_wc__db_wcroot_t *dst_wcroot,
-                       const char *src_relpath,
-                       svn_cancel_func_t cancel_func,
-                       void *cancel_baton,
-                       apr_pool_t *scratch_pool)
+maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot,
+                            svn_wc__db_wcroot_t *dst_wcroot,
+                            const svn_checksum_t *checksum,
+                            const svn_checksum_t *md5_checksum,
+                            apr_int64_t size,
+                            svn_cancel_func_t cancel_func,
+                            void *cancel_baton,
+                            apr_pool_t *scratch_pool)
 {
+  const char *pristine_abspath;
   svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
+  svn_stream_t *src_stream;
+  svn_stream_t *dst_stream;
+  const char *tmp_abspath;
+  const char *src_abspath;
+  int affected_rows;
+  svn_error_t *err;
 
-  *tempfile_abspath = NULL;
+  SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb,
+                                    STMT_INSERT_OR_IGNORE_PRISTINE));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size));
 
-  /* Get the SHA1 checksum */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb,
-                                    STMT_SELECT_NODE_INFO));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is",
-                            src_wcroot->wc_id, src_relpath));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  if (have_row)
-    SVN_ERR(svn_sqlite__column_checksum(sha1_checksum, stmt, 6,
-                                        scratch_pool));
-  SVN_ERR(svn_sqlite__reset(stmt));
+  SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
 
-  if (! *sha1_checksum)
-    return SVN_NO_ERROR; /* Nothing to transfer */
+  if (affected_rows == 0)
+    return SVN_NO_ERROR;
 
-  /* Check if we have the pristine in the destination wcroot */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb,
-                                    STMT_SELECT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, *sha1_checksum,
-                                    scratch_pool));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  SVN_ERR(svn_sqlite__reset(stmt));
+  SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath,
+                                 pristine_get_tempdir(dst_wcroot,
+                                                      scratch_pool,
+                                                      scratch_pool),
+                                 svn_io_file_del_on_pool_cleanup,
+                                 scratch_pool, scratch_pool));
 
-  /* Destination repository already has this pristine. We're done */
-  if (have_row)
-    return SVN_NO_ERROR;
+  SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum,
+                             scratch_pool, scratch_pool));
 
-  /* Verify if the pristine actually exists and get the MD5 in one query */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb,
-                                    STMT_SELECT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, *sha1_checksum,
-                                    scratch_pool));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
+                                   scratch_pool, scratch_pool));
 
-  if (!have_row)
+  /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */
+  SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
+                           cancel_func, cancel_baton,
+                           scratch_pool));
+
+  SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum,
+                             scratch_pool, scratch_pool));
+
+  /* Move the file to its target location.  (If it is already there, it is
+   * an orphan file and it doesn't matter if we overwrite it.) */
+  err = svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool);
+
+  /* Maybe the directory doesn't exist yet? */
+  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
     {
-      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(
-                                        *sha1_checksum, scratch_pool));
-    }
-  SVN_ERR(svn_sqlite__column_checksum(md5_checksum, stmt, 0,
-                                      scratch_pool));
-  SVN_ERR(svn_sqlite__reset(stmt));
+      svn_error_t *err2;
 
-  /* We 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(dst_wcroot,
-                                                        scratch_pool,
-                                                        scratch_pool),
-                                   svn_io_file_del_on_pool_cleanup,
-                                   scratch_pool, scratch_pool));
+      err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
+                                                scratch_pool),
+                             APR_OS_DEFAULT, scratch_pool);
+
+      if (err2)
+        /* Creating directory didn't work: Return all errors */
+        return svn_error_trace(svn_error_compose_create(err, err2));
+      else
+        /* We could create a directory: retry install */
+        svn_error_clear(err);
+
+      SVN_ERR(svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool));
+    }
+  else
+    SVN_ERR(err);
 
-    SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath,
-                               *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,
-                             cancel_func, cancel_baton,
-                             scratch_pool));
-
-    /* And now set the right information to install once we leave the
-       src transaction */
-
-    SVN_ERR(get_pristine_fname(pristine_abspath,
-                               dst_wcroot->abspath,
-                               *sha1_checksum,
-                               scratch_pool, scratch_pool));
-    *tempfile_abspath = tmp_abspath;
-  }
   return SVN_NO_ERROR;
 }
 
@@ -619,32 +586,51 @@ pristine_transfer_txn2(const char **temp
    We have a lock on DST_WCROOT.
  */
 static svn_error_t *
-pristine_transfer_txn1(svn_wc__db_wcroot_t *src_wcroot,
+pristine_transfer_txn(svn_wc__db_wcroot_t *src_wcroot,
                        svn_wc__db_wcroot_t *dst_wcroot,
                        const char *src_relpath,
                        svn_cancel_func_t cancel_func,
                        void *cancel_baton,
                        apr_pool_t *scratch_pool)
 {
-  const char *tempfile_abspath;
-  const char *pristine_abspath;
-  const svn_checksum_t *sha1_checksum;
-  const svn_checksum_t *md5_checksum;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t got_row;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, src_wcroot->sdb,
+                                    STMT_SELECT_COPY_PRISTINES));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", src_wcroot->wc_id, src_relpath));
+
+  /* This obtains an sqlite read lock on src_wcroot */
+  SVN_ERR(svn_sqlite__step(&got_row, stmt));
+
+  while (got_row)
+    {
+      svn_checksum_t *checksum;
+      svn_checksum_t *md5_checksum;
+      apr_int64_t size;
+      svn_error_t *err;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0, iterpool));
+      SVN_ERR(svn_sqlite__column_checksum(&md5_checksum, stmt, 1, iterpool));
+      size = svn_sqlite__column_int64(stmt, 2);
+
+      err = maybe_transfer_one_pristine(src_wcroot, dst_wcroot,
+                                        checksum, md5_checksum, size,
+                                        cancel_func, cancel_baton,
+                                        iterpool);
+
+      if (err)
+        return svn_error_trace(svn_error_compose_create(
+                                    err,
+                                    svn_sqlite__reset(stmt)));
+
+      SVN_ERR(svn_sqlite__step(&got_row, stmt));
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
 
-  /* Get all the info within a src wcroot lock */
-  SVN_WC__DB_WITH_TXN(
-    pristine_transfer_txn2(&tempfile_abspath, &pristine_abspath,
-                           &sha1_checksum, &md5_checksum,
-                           src_wcroot, dst_wcroot, src_relpath,
-                           cancel_func, cancel_baton, scratch_pool),
-    src_wcroot);
-
-  /* And do the final install, while we still have the dst lock */
-  if (tempfile_abspath)
-    SVN_ERR(pristine_install_txn(dst_wcroot->sdb,
-                                 tempfile_abspath, pristine_abspath,
-                                 sha1_checksum, md5_checksum,
-                                 scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -675,8 +661,8 @@ svn_wc__db_pristine_transfer(svn_wc__db_
     }
 
   SVN_WC__DB_WITH_TXN(
-    pristine_transfer_txn1(src_wcroot, dst_wcroot, src_relpath,
-                           cancel_func, cancel_baton, scratch_pool),
+    pristine_transfer_txn(src_wcroot, dst_wcroot, src_relpath,
+                          cancel_func, cancel_baton, scratch_pool),
     dst_wcroot);
 
   return SVN_NO_ERROR;