You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/12/19 01:59:02 UTC

svn commit: r1423728 - in /subversion/trunk/subversion: include/private/svn_sqlite.h libsvn_fs_fs/fs_fs.c libsvn_subr/sqlite.c libsvn_wc/wc_db_pristine.c

Author: julianfoad
Date: Wed Dec 19 00:59:01 2012
New Revision: 1423728

URL: http://svn.apache.org/viewvc?rev=1423728&view=rev
Log:
Introduce SVN_SQLITE__WITH_TXN and SVN_SQLITE__WITH_IMMEDIATE_TXN macros.

These provide a more convenient interface for wrapping a transaction than
the existing functions svn_sqlite__with_transaction() and
svn_sqlite__with_immediate_transaction(), because there is no need to
marshall the called function's parameters via a 'baton' structure.

### Also macro-ize __with_lock?

* subversion/include/private/svn_sqlite.h
  (svn_sqlite__begin_transaction,
   svn_sqlite__begin_immediate_transaction,
   svn_sqlite__finish_transaction): New functions.
  (SVN_SQLITE__WITH_TXN,
   SVN_SQLITE__WITH_IMMEDIATE_TXN): New macros.

* subversion/libsvn_subr/sqlite.c
  (svn_sqlite__begin_transaction,
   svn_sqlite__begin_immediate_transaction): New functions, factored out
    from svn_sqlite__with_transaction().
  (with_transaction): Rename to svn_sqlite__finish_transaction() and don't
    take or call a callback function.
  (svn_sqlite__with_transaction,
   svn_sqlite__with_immediate_transaction):
    Rewrite as simple wrappers around the new macros.

* subversion/libsvn_fs_fs/fs_fs.c
  (commit_sqlite_txn_callback): Delete this struct.
  (svn_fs_fs__commit): Pass the parameters to write_reps_to_cache() directly,
    using SVN_SQLITE__WITH_TXN().

* subversion/libsvn_wc/wc_db_pristine.c
  (pristine_install_baton_t): Delete.
  (pristine_install_txn): Take the parameters directly.
  (svn_wc__db_pristine_install): Pass the parameters directly, using
    SVN_SQLITE__WITH_IMMEDIATE_TXN.
  (pristine_transfer_baton): Include the 'install' fields in the 'transfer
    baton' directly rather than inside an 'install baton'.
  (pristine_transfer): Refer to the 'install' fields in the 'transfer
    baton' directly.
  (pristine_remove_baton_t): Delete.
  (pristine_remove_if_unreferenced_txn): Take the parameters directly.
  (pristine_remove_if_unreferenced): Pass the parameters directly, using
    SVN_SQLITE__WITH_IMMEDIATE_TXN.

Modified:
    subversion/trunk/subversion/include/private/svn_sqlite.h
    subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c
    subversion/trunk/subversion/libsvn_subr/sqlite.c
    subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c

Modified: subversion/trunk/subversion/include/private/svn_sqlite.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_sqlite.h?rev=1423728&r1=1423727&r2=1423728&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_sqlite.h (original)
+++ subversion/trunk/subversion/include/private/svn_sqlite.h Wed Dec 19 00:59:01 2012
@@ -380,6 +380,39 @@ svn_error_t *
 svn_sqlite__reset(svn_sqlite__stmt_t *stmt);
 
 
+/* Begin a transaction in DB. */
+svn_error_t *
+svn_sqlite__begin_transaction(svn_sqlite__db_t *db);
+
+/* Like svn_sqlite__begin_transaction(), but takes out a 'RESERVED' lock
+   immediately, instead of using the default deferred locking scheme. */
+svn_error_t *
+svn_sqlite__begin_immediate_transaction(svn_sqlite__db_t *db);
+
+/* Commit the current transaction in DB if ERR is SVN_NO_ERROR, otherwise
+ * roll back the transaction.  Return a composition of ERR and any error
+ * that may occur during the commit or roll-back. */
+svn_error_t *
+svn_sqlite__finish_transaction(svn_sqlite__db_t *db,
+                               svn_error_t *err);
+
+/* Evaluate the expression EXPR within a transaction.
+ *
+ * Begin a transaction in DB; evaluate the expression EXPR, which would
+ * typically be a function call that does some work in DB; finally commit
+ * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
+ * the transaction.
+ */
+#define SVN_SQLITE__WITH_TXN(expr, db)                                        \
+  do {                                                                        \
+    svn_sqlite__db_t *svn_sqlite__db = (db);                                  \
+    svn_error_t *svn_sqlite__err;                                             \
+                                                                              \
+    SVN_ERR(svn_sqlite__begin_transaction(svn_sqlite__db));                   \
+    svn_sqlite__err = (expr);                                                 \
+    SVN_ERR(svn_sqlite__finish_transaction(svn_sqlite__db, svn_sqlite__err)); \
+  } while (0)
+
 /* Callback function to for use with svn_sqlite__with_transaction(). */
 typedef svn_error_t *(*svn_sqlite__transaction_callback_t)(
   void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool);
@@ -394,6 +427,18 @@ svn_sqlite__with_transaction(svn_sqlite_
                              svn_sqlite__transaction_callback_t cb_func,
                              void *cb_baton, apr_pool_t *scratch_pool);
 
+/* Like SVN_SQLITE__WITH_TXN(), but takes out a 'RESERVED' lock
+   immediately, instead of using the default deferred locking scheme. */
+#define SVN_SQLITE__WITH_IMMEDIATE_TXN(expr, db)                              \
+  do {                                                                        \
+    svn_sqlite__db_t *svn_sqlite__db = (db);                                  \
+    svn_error_t *svn_sqlite__err;                                             \
+                                                                              \
+    SVN_ERR(svn_sqlite__begin_immediate_transaction(svn_sqlite__db));         \
+    svn_sqlite__err = (expr);                                                 \
+    SVN_ERR(svn_sqlite__finish_transaction(svn_sqlite__db, svn_sqlite__err)); \
+  } while (0)
+
 /* Like svn_sqlite__with_transaction(), but takes out a 'RESERVED' lock
    immediately, instead of using the default deferred locking scheme. */
 svn_error_t *

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=1423728&r1=1423727&r2=1423728&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.c Wed Dec 19 00:59:01 2012
@@ -8560,23 +8560,6 @@ write_reps_to_cache(svn_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
-/* Implements svn_sqlite__transaction_callback_t. */
-static svn_error_t *
-commit_sqlite_txn_callback(void *baton, svn_sqlite__db_t *db,
-                           apr_pool_t *scratch_pool)
-{
-  struct commit_baton *cb = baton;
-
-  /* Write new entries to the rep-sharing database.
-   *
-   * We use an sqlite transcation to speed things up;
-   * see <http://www.sqlite.org/faq.html#q19>.
-   */
-  SVN_ERR(write_reps_to_cache(cb->fs, cb->reps_to_cache, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
 svn_error_t *
 svn_fs_fs__commit(svn_revnum_t *new_rev_p,
                   svn_fs_t *fs,
@@ -8611,9 +8594,15 @@ svn_fs_fs__commit(svn_revnum_t *new_rev_
   if (ffd->rep_sharing_allowed)
     {
       SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool));
-      SVN_ERR(svn_sqlite__with_transaction(ffd->rep_cache_db,
-                                           commit_sqlite_txn_callback,
-                                           &cb, pool));
+
+      /* Write new entries to the rep-sharing database.
+       *
+       * We use an sqlite transaction to speed things up;
+       * see <http://www.sqlite.org/faq.html#q19>.
+       */
+      SVN_SQLITE__WITH_TXN(
+        write_reps_to_cache(fs, cb.reps_to_cache, pool),
+        ffd->rep_cache_db);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/sqlite.c?rev=1423728&r1=1423727&r2=1423728&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/trunk/subversion/libsvn_subr/sqlite.c Wed Dec 19 00:59:01 2012
@@ -992,18 +992,33 @@ reset_all_statements(svn_sqlite__db_t *d
   return err;
 }
 
-/* The body of svn_sqlite__with_transaction() and
-   svn_sqlite__with_immediate_transaction(), which see. */
-static svn_error_t *
-with_transaction(svn_sqlite__db_t *db,
-                 svn_sqlite__transaction_callback_t cb_func,
-                 void *cb_baton,
-                 apr_pool_t *scratch_pool /* NULL allowed */)
+svn_error_t *
+svn_sqlite__begin_transaction(svn_sqlite__db_t *db)
 {
   svn_sqlite__stmt_t *stmt;
-  svn_error_t *err;
 
-  err = cb_func(cb_baton, db, scratch_pool);
+  SVN_ERR(get_internal_statement(&stmt, db,
+                                 STMT_INTERNAL_BEGIN_TRANSACTION));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_sqlite__begin_immediate_transaction(svn_sqlite__db_t *db)
+{
+  svn_sqlite__stmt_t *stmt;
+
+  SVN_ERR(get_internal_statement(&stmt, db,
+                                 STMT_INTERNAL_BEGIN_IMMEDIATE_TRANSACTION));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_sqlite__finish_transaction(svn_sqlite__db_t *db,
+                               svn_error_t *err)
+{
+  svn_sqlite__stmt_t *stmt;
 
   /* Commit or rollback the sqlite transaction. */
   if (err)
@@ -1056,12 +1071,8 @@ svn_sqlite__with_transaction(svn_sqlite_
                              void *cb_baton,
                              apr_pool_t *scratch_pool /* NULL allowed */)
 {
-  svn_sqlite__stmt_t *stmt;
-  SVN_ERR(get_internal_statement(&stmt, db,
-                                 STMT_INTERNAL_BEGIN_TRANSACTION));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-  return svn_error_trace(with_transaction(db, cb_func, cb_baton,
-                                          scratch_pool));
+  SVN_SQLITE__WITH_TXN(cb_func(cb_baton, db, scratch_pool), db);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -1071,12 +1082,8 @@ svn_sqlite__with_immediate_transaction(
   void *cb_baton,
   apr_pool_t *scratch_pool /* NULL allowed */)
 {
-  svn_sqlite__stmt_t *stmt;
-  SVN_ERR(get_internal_statement(&stmt, db,
-                                 STMT_INTERNAL_BEGIN_IMMEDIATE_TRANSACTION));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-  return svn_error_trace(with_transaction(db, cb_func, cb_baton,
-                                          scratch_pool));
+  SVN_SQLITE__WITH_IMMEDIATE_TXN(cb_func(cb_baton, db, scratch_pool), db);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *

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=1423728&r1=1423727&r2=1423728&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_pristine.c Wed Dec 19 00:59:01 2012
@@ -288,20 +288,6 @@ svn_wc__db_pristine_get_tempdir(const ch
 }
 
 
-/* Data for pristine_install_txn(). */
-typedef struct pristine_install_baton_t
-{
-  /* The path to the source file that is to be moved into place. */
-  const char *tempfile_abspath;
-  /* The target path for the file (within the pristine store). */
-  const char *pristine_abspath;
-  /* The pristine text's SHA-1 checksum. */
-  const svn_checksum_t *sha1_checksum;
-  /* The pristine text's MD-5 checksum. */
-  const svn_checksum_t *md5_checksum;
-} pristine_install_baton_t;
-
-
 /* Install the pristine text described by BATON into the pristine store of
  * SDB.  If it is already stored then just delete the new file
  * BATON->tempfile_abspath.
@@ -312,11 +298,17 @@ typedef struct pristine_install_baton_t
  * Implements 'notes/wc-ng/pristine-store' section A-3(a).
  * Implements svn_sqlite__transaction_callback_t. */
 static svn_error_t *
-pristine_install_txn(void *baton,
-                     svn_sqlite__db_t *sdb,
+pristine_install_txn(svn_sqlite__db_t *sdb,
+                     /* The path to the source file that is to be moved into place. */
+                     const char *tempfile_abspath,
+                     /* The target path for the file (within the pristine store). */
+                     const char *pristine_abspath,
+                     /* The pristine text's SHA-1 checksum. */
+                     const svn_checksum_t *sha1_checksum,
+                     /* The pristine text's MD-5 checksum. */
+                     const svn_checksum_t *md5_checksum,
                      apr_pool_t *scratch_pool)
 {
-  pristine_install_baton_t *b = baton;
   apr_finfo_t finfo;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
@@ -325,7 +317,7 @@ pristine_install_txn(void *baton,
   /* If this pristine text is already present in the store, just keep it:
    * delete the new one and return. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+  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));
   if (have_row)
@@ -335,30 +327,30 @@ pristine_install_txn(void *baton,
        * ### We could check much more. */
       {
         apr_finfo_t finfo1, finfo2;
-        SVN_ERR(svn_io_stat(&finfo1, b->tempfile_abspath, APR_FINFO_SIZE,
+        SVN_ERR(svn_io_stat(&finfo1, tempfile_abspath, APR_FINFO_SIZE,
                             scratch_pool));
-        SVN_ERR(svn_io_stat(&finfo2, b->pristine_abspath, APR_FINFO_SIZE,
+        SVN_ERR(svn_io_stat(&finfo2, pristine_abspath, APR_FINFO_SIZE,
                             scratch_pool));
         if (finfo1.size != finfo2.size)
           {
             return svn_error_createf(
               SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
               _("New pristine text '%s' has different size: %ld versus %ld"),
-              svn_checksum_to_cstring_display(b->sha1_checksum, scratch_pool),
+              svn_checksum_to_cstring_display(sha1_checksum, scratch_pool),
               (long int)finfo1.size, (long int)finfo2.size);
           }
       }
 #endif
 
       /* Remove the temp file: it's already there */
-      SVN_ERR(svn_io_remove_file2(b->tempfile_abspath,
+      SVN_ERR(svn_io_remove_file2(tempfile_abspath,
                                   FALSE /* ignore_enoent */, scratch_pool));
       return SVN_NO_ERROR;
     }
 
   /* 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(b->tempfile_abspath, b->pristine_abspath,
+  err = svn_io_file_rename(tempfile_abspath, pristine_abspath,
                            scratch_pool);
 
   /* Maybe the directory doesn't exist yet? */
@@ -366,7 +358,7 @@ pristine_install_txn(void *baton,
     {
       svn_error_t *err2;
 
-      err2 = svn_io_dir_make(svn_dirent_dirname(b->pristine_abspath,
+      err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath,
                                                 scratch_pool),
                              APR_OS_DEFAULT, scratch_pool);
 
@@ -377,19 +369,19 @@ pristine_install_txn(void *baton,
         /* We could create a directory: retry install */
         svn_error_clear(err);
 
-      SVN_ERR(svn_io_file_rename(b->tempfile_abspath, b->pristine_abspath,
+      SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
                            scratch_pool));
     }
   else
     SVN_ERR(err);
 
-  SVN_ERR(svn_io_stat(&finfo, b->pristine_abspath, APR_FINFO_SIZE,
+  SVN_ERR(svn_io_stat(&finfo, pristine_abspath, APR_FINFO_SIZE,
                       scratch_pool));
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                     STMT_INSERT_PRISTINE));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, b->md5_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
   SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
   SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
@@ -407,7 +399,7 @@ svn_wc__db_pristine_install(svn_wc__db_t
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
   const char *wri_abspath;
-  struct pristine_install_baton_t b;
+  const char *pristine_abspath;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
   SVN_ERR_ASSERT(sha1_checksum != NULL);
@@ -429,19 +421,18 @@ svn_wc__db_pristine_install(svn_wc__db_t
                               wri_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  b.tempfile_abspath = tempfile_abspath;
-  b.sha1_checksum = sha1_checksum;
-  b.md5_checksum = md5_checksum;
-
-  SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+  SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
                              sha1_checksum,
                              scratch_pool, scratch_pool));
 
   /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
    * at the disk, to ensure no concurrent pristine install/delete txn. */
-  SVN_ERR(svn_sqlite__with_immediate_transaction(wcroot->sdb,
-                                                 pristine_install_txn, &b,
-                                                 scratch_pool));
+  SVN_SQLITE__WITH_IMMEDIATE_TXN(
+    pristine_install_txn(wcroot->sdb,
+                         tempfile_abspath, pristine_abspath,
+                         sha1_checksum, md5_checksum,
+                         scratch_pool),
+    wcroot->sdb);
 
   return SVN_NO_ERROR;
 }
@@ -531,8 +522,15 @@ struct pristine_transfer_baton
   svn_cancel_func_t cancel_func;
   void * cancel_baton;
 
-  /* pristine install baton, filled from pristine_transfer() */
-  struct pristine_install_baton_t ib;
+  /* The following fields are filled in by pristine_transfer(). */
+  /* The path to the source file that is to be moved into place. */
+  const char *tempfile_abspath;
+  /* The target path for the file (within the pristine store). */
+  const char *pristine_abspath;
+  /* The pristine text's SHA-1 checksum. */
+  const svn_checksum_t *sha1_checksum;
+  /* The pristine text's MD-5 checksum. */
+  const svn_checksum_t *md5_checksum;
 };
 
 /* Transaction implementation of svn_wc__db_pristine_transfer().
@@ -555,8 +553,12 @@ pristine_transfer(void *baton, svn_wc__d
                                   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,
+      if (tb->tempfile_abspath)
+        SVN_ERR(pristine_install_txn(tb->dst_wcroot->sdb,
+                                     tb->tempfile_abspath,
+                                     tb->pristine_abspath,
+                                     tb->sha1_checksum,
+                                     tb->md5_checksum,
                                      scratch_pool));
       return SVN_NO_ERROR;
     }
@@ -564,7 +566,7 @@ pristine_transfer(void *baton, svn_wc__d
   /* 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)
+  if (!tb->sha1_checksum)
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, tb->src_wcroot->sdb,
                                         STMT_SELECT_NODE_INFO));
@@ -575,19 +577,19 @@ pristine_transfer(void *baton, svn_wc__d
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
       if (have_row)
-        SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.sha1_checksum), stmt, 6,
+        SVN_ERR(svn_sqlite__column_checksum(&(tb->sha1_checksum), stmt, 6,
                                             scratch_pool));
 
       SVN_ERR(svn_sqlite__reset(stmt));
 
-      if (!tb->ib.sha1_checksum)
+      if (!tb->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,
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->sha1_checksum,
                                     scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   SVN_ERR(svn_sqlite__reset(stmt));
@@ -599,7 +601,7 @@ pristine_transfer(void *baton, svn_wc__d
   /* 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,
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, tb->sha1_checksum,
                                     scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
@@ -609,9 +611,9 @@ pristine_transfer(void *baton, svn_wc__d
                                _("The pristine text with checksum '%s' was "
                                  "not found"),
                                svn_checksum_to_cstring_display(
-                                        tb->ib.sha1_checksum, scratch_pool));
+                                        tb->sha1_checksum, scratch_pool));
     }
-  SVN_ERR(svn_sqlite__column_checksum(&(tb->ib.md5_checksum), stmt, 0,
+  SVN_ERR(svn_sqlite__column_checksum(&(tb->md5_checksum), stmt, 0,
                                       scratch_pool));
   SVN_ERR(svn_sqlite__reset(stmt));
 
@@ -631,7 +633,7 @@ pristine_transfer(void *baton, svn_wc__d
                                    scratch_pool, scratch_pool));
 
     SVN_ERR(get_pristine_fname(&src_abspath, tb->src_wcroot->abspath,
-                               tb->ib.sha1_checksum,
+                               tb->sha1_checksum,
                                scratch_pool, scratch_pool));
 
     SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath,
@@ -645,11 +647,11 @@ pristine_transfer(void *baton, svn_wc__d
     /* And now set the right information to install once we leave the
        src transaction */
 
-    SVN_ERR(get_pristine_fname(&(tb->ib.pristine_abspath),
+    SVN_ERR(get_pristine_fname(&(tb->pristine_abspath),
                                tb->dst_wcroot->abspath,
-                               tb->ib.sha1_checksum,
+                               tb->sha1_checksum,
                                scratch_pool, scratch_pool));
-    tb->ib.tempfile_abspath = tmp_abspath;
+    tb->tempfile_abspath = tmp_abspath;
   }
   return SVN_NO_ERROR;
 }
@@ -730,17 +732,8 @@ remove_file(const char *file_abspath,
   return SVN_NO_ERROR;
 }
 
-/* Data for pristine_remove_if_unreferenced_txn(). */
-typedef struct pristine_remove_baton_t
-{
-  svn_wc__db_wcroot_t *wcroot;
-  /* The pristine text's SHA-1 checksum. */
-  const svn_checksum_t *sha1_checksum;
-  /* The path to the pristine file (within the pristine store). */
-  const char *pristine_abspath;
-} pristine_remove_baton_t;
-
-/* If the pristine text referenced by BATON in SDB has a reference count of
+/* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path
+ * within the pristine store is PRISTINE_ABSPATH, has a reference count of
  * zero, delete it (both the database row and the disk file).
  *
  * This function expects to be executed inside a SQLite txn that has already
@@ -748,18 +741,19 @@ typedef struct pristine_remove_baton_t
  *
  * Implements svn_sqlite__transaction_callback_t. */
 static svn_error_t *
-pristine_remove_if_unreferenced_txn(void *baton,
-                                    svn_sqlite__db_t *sdb,
+pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb,
+                                    svn_wc__db_wcroot_t *wcroot,
+                                    const svn_checksum_t *sha1_checksum,
+                                    const char *pristine_abspath,
                                     apr_pool_t *scratch_pool)
 {
-  pristine_remove_baton_t *b = baton;
   svn_sqlite__stmt_t *stmt;
   int affected_rows;
 
   /* Remove the DB row, if refcount is 0. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                     STMT_DELETE_PRISTINE_IF_UNREFERENCED));
-  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, b->sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
   SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
 
   /* If we removed the DB row, then remove the file. */
@@ -774,7 +768,7 @@ pristine_remove_if_unreferenced_txn(void
       svn_boolean_t ignore_enoent = TRUE;
 #endif
 
-      SVN_ERR(remove_file(b->pristine_abspath, b->wcroot, ignore_enoent,
+      SVN_ERR(remove_file(pristine_abspath, wcroot, ignore_enoent,
                           scratch_pool));
     }
 
@@ -791,17 +785,17 @@ pristine_remove_if_unreferenced(svn_wc__
                                 const svn_checksum_t *sha1_checksum,
                                 apr_pool_t *scratch_pool)
 {
-  pristine_remove_baton_t b;
+  const char *pristine_abspath;
 
-  b.wcroot = wcroot;
-  b.sha1_checksum = sha1_checksum;
-  SVN_ERR(get_pristine_fname(&b.pristine_abspath, wcroot->abspath,
+  SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath,
                              sha1_checksum, scratch_pool, scratch_pool));
 
   /* Ensure the SQL txn has at least a 'RESERVED' lock before we start looking
    * at the disk, to ensure no concurrent pristine install/delete txn. */
-  SVN_ERR(svn_sqlite__with_immediate_transaction(
-    wcroot->sdb, pristine_remove_if_unreferenced_txn, &b, scratch_pool));
+  SVN_SQLITE__WITH_IMMEDIATE_TXN(
+    pristine_remove_if_unreferenced_txn(
+      wcroot->sdb, wcroot, sha1_checksum, pristine_abspath, scratch_pool),
+    wcroot->sdb);
 
   return SVN_NO_ERROR;
 }