Author: philip
Date: Thu Jun  2 16:32:18 2011
New Revision: 1130637

URL: http://svn.apache.org/viewvc?rev=1130637&view=rev
Log:
As a prelude to fixing issue 3908, status doesn't show wc-locks,
optimise is_wclocked to reduce the number of queries when the working
copy is not locked.

* subversion/libsvn_wc/wc_db.c
  (is_wclocked): Change signature, reimplement.
  (svn_wc__db_wclocked): Use svn_wc__db_with_txn.

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

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=1130637&r1=1130636&r2=1130637&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Thu Jun  2 16:32:18 
2011
@@ -726,6 +726,10 @@ VALUES (?1, ?2, ?3)
 SELECT locked_levels FROM wc_lock
 WHERE wc_id = ?1 AND local_dir_relpath = ?2
 
+-- STMT_COUNT_WC_LOCK
+SELECT COUNT(*) FROM wc_lock
+WHERE wc_id = ?1
+
 -- STMT_DELETE_WC_LOCK
 DELETE FROM wc_lock
 WHERE wc_id = ?1 AND local_dir_relpath = ?2

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1130637&r1=1130636&r2=1130637&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Jun  2 16:32:18 2011
@@ -10613,54 +10613,78 @@ svn_wc__db_wclock_obtain(svn_wc__db_t *d
 }
 
 
-/* */
+/* Implements svn_wc__db_txn_callback_t. */
 static svn_error_t *
-is_wclocked(svn_boolean_t *locked,
-            svn_wc__db_t *db,
-            const char *local_abspath,
-            apr_int64_t recurse_depth,
+is_wclocked(void *baton,
+            svn_wc__db_wcroot_t *wcroot,
+            const char *dir_relpath,
             apr_pool_t *scratch_pool)
 {
+  svn_boolean_t *locked = baton;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-  svn_error_t *err;
+  apr_int64_t locked_levels, num_locks;
+  apr_int64_t dir_depth, depth = relpath_depth(dir_relpath);
 
-  err = get_statement_for_path(&stmt, db, local_abspath,
-                               STMT_SELECT_WC_LOCK, scratch_pool);
-  if (err && SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
+  /* The most common scenarios are no locks in the wc, or a single
+     fully recursive lock at the root, only legacy API users will
+     create any other locks.  First check for no locks at all. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_COUNT_WC_LOCK));
+  SVN_ERR(svn_sqlite__bindf(stmt, "i", wcroot->wc_id));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_CORRUPT, svn_sqlite__reset(stmt),
+                             _("Count of WC_LOCK for id '%ld' failed"),
+                             wcroot->wc_id);
+  num_locks = svn_sqlite__column_int64(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
+  if (!num_locks)
     {
-      svn_error_clear(err);
       *locked = FALSE;
       return SVN_NO_ERROR;
     }
-  else
-    SVN_ERR(err);
 
+  /* Next check for a lock at root. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_WC_LOCK));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, ""));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
+  if (have_row)
+    locked_levels = svn_sqlite__column_int64(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
   if (have_row)
     {
-      apr_int64_t locked_levels = svn_sqlite__column_int64(stmt, 0);
-
-      /* The directory in question is considered locked if we find a lock
-         with depth -1 or the depth of the lock is greater than or equal to
-         the depth we've recursed. */
-      *locked = (locked_levels == -1 || locked_levels >= recurse_depth);
-      return svn_error_return(svn_sqlite__reset(stmt));
+      *locked = (locked_levels == -1 || locked_levels >= depth);
+      if (*locked || num_locks == 1)
+        return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  if (svn_dirent_is_root(local_abspath, strlen(local_abspath)))
+  /* Finally check for locks on dirs above root, only legacy API users
+     create these.  I'm not sure what order is best here but from the
+     target to the root is easy to code.  */
+  dir_depth = depth;
+  while (*dir_relpath)
     {
-      *locked = FALSE;
-      return SVN_NO_ERROR;
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_SELECT_WC_LOCK));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, dir_relpath));
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+      if (have_row)
+        locked_levels = svn_sqlite__column_int64(stmt, 0);
+      SVN_ERR(svn_sqlite__reset(stmt));
+      if (have_row)
+        {
+          /* Any row here means there can be no locks closer to root
+             that extend past here. */
+          *locked = (locked_levels == -1 || locked_levels + dir_depth >= 
depth);
+          return SVN_NO_ERROR;
+        }
+      dir_relpath = svn_relpath_dirname(dir_relpath, scratch_pool);
+      --dir_depth;
     }
 
-  return svn_error_return(is_wclocked(locked, db,
-                                      svn_dirent_dirname(local_abspath,
-                                                         scratch_pool),
-                                      recurse_depth + 1, scratch_pool));
+  *locked = FALSE;
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -10670,8 +10694,17 @@ svn_wc__db_wclocked(svn_boolean_t *locke
                     const char *local_abspath,
                     apr_pool_t *scratch_pool)
 {
-  return svn_error_return(is_wclocked(locked, db, local_abspath, 0,
-                                      scratch_pool));
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                              local_abspath, scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, is_wclocked, locked,
+                              scratch_pool));
+
+  return SVN_NO_ERROR;
 }
 
 


Reply via email to