Author: julianfoad
Date: Tue Nov 30 18:07:51 2010
New Revision: 1040663

URL: http://svn.apache.org/viewvc?rev=1040663&view=rev
Log:
Speed up the pristine store garbage collection done by "svn cleanup".  In a
trunk svn WC on my system, this reduces the overall "svn cleanup" time from
about 1 second to about 0.2 seconds for a no-op cleanup with a hot cache.

* subversion/libsvn_wc/wc_db.c
  (svn_wc__db_pristine_cleanup): Instead of using a separate query to check
    whether each pristine text is still referenced, get a list of all the
    pristine texts and a list of those that are referenced, and find the
    difference by using an APR hash.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_SELECT_ALL_PRISTINE_REFERENCES): New query.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1040663&r1=1040662&r2=1040663&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Tue Nov 30 18:07:51 
2010
@@ -440,6 +440,19 @@ SELECT 1 FROM actual_node
     OR  right_checksum = ?1 OR right_checksum = ?2
 LIMIT 1
 
+-- STMT_SELECT_ALL_PRISTINE_REFERENCES
+SELECT checksum FROM nodes
+  WHERE checksum IS NOT NULL
+UNION ALL
+SELECT older_checksum FROM actual_node
+  WHERE older_checksum IS NOT NULL
+UNION ALL
+SELECT left_checksum FROM actual_node
+  WHERE left_checksum  IS NOT NULL
+UNION ALL
+SELECT right_checksum FROM actual_node
+  WHERE right_checksum IS NOT NULL
+
 -- STMT_DELETE_PRISTINE
 DELETE FROM pristine
 WHERE checksum = ?1

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1040663&r1=1040662&r2=1040663&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Tue Nov 30 18:07:51 2010
@@ -2659,6 +2659,8 @@ svn_wc__db_pristine_cleanup(svn_wc__db_t
   svn_wc__db_pdh_t *pdh;
   const char *local_relpath;
   svn_sqlite__stmt_t *stmt;
+  apr_hash_t *sha1s = apr_hash_make(scratch_pool);
+  apr_hash_index_t *hi;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
 
@@ -2667,25 +2669,63 @@ svn_wc__db_pristine_cleanup(svn_wc__db_t
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
-  /* Find the pristines in the DB */
+  /* Find all the pristines in the DB; store their SHA-1s in SHA1S. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_SELECT_PRISTINE_ROWS));
   while (1)
     {
       svn_boolean_t have_row;
-      const svn_checksum_t *checksum;
+      const svn_checksum_t *sha1_checksum;
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
       if (! have_row)
         break;
 
-      SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0,
+      SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
                                           scratch_pool));
-      SVN_ERR(svn_wc__db_pristine_remove(db, wri_abspath, checksum,
-                                         scratch_pool));
+      apr_hash_set(sha1s, sha1_checksum->digest,
+                   svn_checksum_size(sha1_checksum), (void *)1);
     }
   SVN_ERR(svn_sqlite__reset(stmt));
 
+  /* Find all the referenced pristines; remove their SHA-1s from SHA1S. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                    STMT_SELECT_ALL_PRISTINE_REFERENCES));
+  while (1)
+    {
+      svn_boolean_t have_row;
+      const svn_checksum_t *sha1_checksum;
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+      if (! have_row)
+        break;
+
+      SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
+                                          scratch_pool));
+      if (sha1_checksum->kind != svn_checksum_sha1)
+        {
+          /* ### Transitional. Should no longer be possible. */
+          SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
+                                               sha1_checksum,
+                                               scratch_pool, scratch_pool));
+        }
+      apr_hash_set(sha1s, sha1_checksum->digest,
+                   svn_checksum_size(sha1_checksum), NULL);
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  /* Remove each remaining pristine that is listed in SHA1S. */
+  for (hi = apr_hash_first(scratch_pool, sha1s);
+       hi; hi = apr_hash_next(hi))
+    {
+      const unsigned char *sha1_digest = svn__apr_hash_index_key(hi);
+      const svn_checksum_t *sha1_checksum
+        = svn_checksum__from_digest(sha1_digest, svn_checksum_sha1,
+                                    scratch_pool);
+
+      SVN_ERR(pristine_remove(pdh, sha1_checksum, scratch_pool));
+    }
+
   return SVN_NO_ERROR;
 }
 


Reply via email to