Author: rhuijben
Date: Wed Mar 16 22:13:21 2011
New Revision: 1082320

URL: http://svn.apache.org/viewvc?rev=1082320&view=rev
Log:
Remove at least one more read transaction and in most cases a filestat for
every BASE node in a working copy when updating, by querying the data the
adm crawler needs per directory, like how philipm implemented that for
status a few months ago.

* subversion/libsvn_wc/adm_crawler.c
  (report_revisions_and_depths): Use svn_wc__db_base_get_children_info instead
    of svn_wc__db_base_get_children to avoid a svn_wc__db_base_get_info()
    call for all nodes found.

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

* subversion/libsvn_wc/wc_db.c
  (svn_wc__db_base_get_children_info): New function.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_base_info_t): New struct.
  (svn_wc__db_base_get_children_info): New function.

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

Modified: subversion/trunk/subversion/libsvn_wc/adm_crawler.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_crawler.c?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/trunk/subversion/libsvn_wc/adm_crawler.c Wed Mar 16 22:13:21 2011
@@ -285,10 +285,10 @@ report_revisions_and_depths(svn_wc__db_t
                             apr_pool_t *scratch_pool)
 {
   const char *dir_abspath;
-  const apr_array_header_t *base_children;
+  apr_hash_t *base_children;
   apr_hash_t *dirents;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  int i;
+  apr_hash_index_t *hi;
   const char *dir_repos_root, *dir_repos_relpath;
   svn_depth_t dir_depth;
   svn_error_t *err;
@@ -298,8 +298,8 @@ report_revisions_and_depths(svn_wc__db_t
      notice that we're picking up hidden entries too (read_children never
      hides children). */
   dir_abspath = svn_dirent_join(anchor_abspath, dir_path, scratch_pool);
-  SVN_ERR(svn_wc__db_base_get_children(&base_children, db, dir_abspath,
-                                       scratch_pool, iterpool));
+  SVN_ERR(svn_wc__db_base_get_children_info(&base_children, db, dir_abspath,
+                                            scratch_pool, iterpool));
 
   err = svn_io_get_dirents3(&dirents, dir_abspath, TRUE,
                             scratch_pool, scratch_pool);
@@ -336,18 +336,21 @@ report_revisions_and_depths(svn_wc__db_t
                                 external_baton, dir_depth, iterpool));
 
   /* Looping over current directory's BASE children: */
-  for (i = 0; i < base_children->nelts; ++i)
+  for (hi = apr_hash_first(scratch_pool, base_children); 
+       hi != NULL;
+       hi = apr_hash_next(hi))
     {
-      const char *child = APR_ARRAY_IDX(base_children, i, const char *);
+      const char *child = svn__apr_hash_index_key(hi);
       const char *this_path, *this_abspath;
-      const char *this_repos_root_url, *this_repos_relpath;
-      svn_wc__db_status_t this_status;
-      svn_wc__db_kind_t this_kind;
-      svn_revnum_t this_rev;
-      svn_depth_t this_depth;
-      svn_wc__db_lock_t *this_lock;
+
+      //svn_wc__db_status_t this_status;
+      //svn_wc__db_kind_t this_kind;
+      //svn_revnum_t this_rev;
+      //svn_depth_t this_depth;
+      //svn_wc__db_lock_t *this_lock;
       svn_boolean_t this_switched = FALSE;
-      svn_boolean_t this_file_external = FALSE;
+      //svn_boolean_t this_file_external = FALSE;
+      struct svn_wc__db_base_info_t *ths = svn__apr_hash_index_val(hi);
 
       /* Clear the iteration subpool here because the loop has a bunch
          of 'continue' jump statements. */
@@ -357,16 +360,16 @@ report_revisions_and_depths(svn_wc__db_t
       this_path = svn_dirent_join(dir_path, child, iterpool);
       this_abspath = svn_dirent_join(dir_abspath, child, iterpool);
 
-      SVN_ERR(svn_wc__db_base_get_info(&this_status, &this_kind, &this_rev,
-                                       &this_repos_relpath,
-                                       &this_repos_root_url,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       &this_depth,
-                                       NULL, NULL, NULL, &this_lock, NULL,
-                                       db, this_abspath, iterpool, iterpool));
+      //SVN_ERR(svn_wc__db_base_get_info(&this_status, &this_kind, &this_rev,
+      //                                 &this_repos_relpath,
+      //                                 &this_repos_root_url,
+      //                                 NULL, NULL, NULL, NULL, NULL,
+      //                                 &this_depth,
+      //                                 NULL, NULL, NULL, &this_lock, NULL,
+      //                                 db, this_abspath, iterpool, 
iterpool));
 
       /* First check for exclusion */
-      if (this_status == svn_wc__db_status_excluded)
+      if (ths->status == svn_wc__db_status_excluded)
         {
           if (honor_depth_exclude)
             {
@@ -399,8 +402,8 @@ report_revisions_and_depths(svn_wc__db_t
         }
 
       /*** The Big Tests: ***/
-      if (this_status == svn_wc__db_status_absent
-          || this_status == svn_wc__db_status_not_present)
+      if (ths->status == svn_wc__db_status_absent
+          || ths->status == svn_wc__db_status_not_present)
         {
           /* If the entry is 'absent' or 'not-present', make sure the server
              knows it's gone...
@@ -459,55 +462,44 @@ report_revisions_and_depths(svn_wc__db_t
         }
 
       /* And finally prepare for reporting */
-      if (!this_repos_relpath)
+      if (!ths->repos_relpath)
         {
-          this_repos_relpath = svn_relpath_join(dir_repos_relpath, child,
+          ths->repos_relpath = svn_relpath_join(dir_repos_relpath, child,
                                                 iterpool);
         }
       else
         {
           const char *childname = svn_relpath_is_child(dir_repos_relpath,
-                                                       this_repos_relpath,
+                                                       ths->repos_relpath,
                                                        NULL);
 
           if (childname == NULL || strcmp(childname, child) != 0)
             {
-              const char *file_ext_str;
-
               this_switched = TRUE;
-
-              /* This could be a file external!  We need to know
-                 that. */
-              SVN_ERR(svn_wc__db_temp_get_file_external(&file_ext_str, db,
-                                                        this_abspath,
-                                                        scratch_pool,
-                                                        scratch_pool));
-              if (file_ext_str)
-                this_file_external = TRUE;
             }
         }
 
       /* Tweak THIS_DEPTH to a useful value.  */
-      if (this_depth == svn_depth_unknown)
-        this_depth = svn_depth_infinity;
+      if (ths->depth == svn_depth_unknown)
+        ths->depth = svn_depth_infinity;
 
       /* Obstructed nodes might report SVN_INVALID_REVNUM. Tweak it.
 
          ### it seems that obstructed nodes should be handled quite a
          ### bit differently. maybe reported as missing, like not-present
          ### or absent nodes?  */
-      if (!SVN_IS_VALID_REVNUM(this_rev))
-        this_rev = dir_rev;
+      if (!SVN_IS_VALID_REVNUM(ths->revnum))
+        ths->revnum = dir_rev;
 
       /*** File Externals **/
-      if (this_file_external)
+      if (ths->update_root)
         {
           /* File externals are ... special.  We ignore them. */;
         }
 
       /*** Files ***/
-      else if (this_kind == svn_wc__db_kind_file ||
-               this_kind == svn_wc__db_kind_symlink)
+      else if (ths->kind == svn_wc__db_kind_file ||
+               ths->kind == svn_wc__db_kind_symlink)
         {
           if (report_everything)
             {
@@ -517,19 +509,19 @@ report_revisions_and_depths(svn_wc__db_t
                                             this_path,
                                             svn_path_url_add_component2(
                                                 dir_repos_root,
-                                                this_repos_relpath, iterpool),
-                                            this_rev,
-                                            this_depth,
+                                                ths->repos_relpath, iterpool),
+                                            ths->revnum,
+                                            ths->depth,
                                             FALSE,
-                                            this_lock ? this_lock->token : 
NULL,
+                                            ths->lock ? ths->lock->token : 
NULL,
                                             iterpool));
               else
                 SVN_ERR(reporter->set_path(report_baton,
                                            this_path,
-                                           this_rev,
-                                           this_depth,
+                                           ths->revnum,
+                                           ths->depth,
                                            FALSE,
-                                           this_lock ? this_lock->token : NULL,
+                                           ths->lock ? ths->lock->token : NULL,
                                            iterpool));
             }
 
@@ -539,40 +531,40 @@ report_revisions_and_depths(svn_wc__db_t
                                         this_path,
                                         svn_path_url_add_component2(
                                                 dir_repos_root,
-                                                this_repos_relpath, iterpool),
-                                        this_rev,
-                                        this_depth,
+                                                ths->repos_relpath, iterpool),
+                                        ths->revnum,
+                                        ths->depth,
                                         FALSE,
-                                        this_lock ? this_lock->token : NULL,
+                                        ths->lock ? ths->lock->token : NULL,
                                         iterpool));
           /* ... or perhaps just a differing revision or lock token,
              or the mere presence of the file in a depth-empty dir. */
-          else if (this_rev != dir_rev
-                   || this_lock
+          else if (ths->revnum != dir_rev
+                   || ths->lock
                    || dir_depth == svn_depth_empty)
             SVN_ERR(reporter->set_path(report_baton,
                                        this_path,
-                                       this_rev,
-                                       this_depth,
+                                       ths->revnum,
+                                       ths->depth,
                                        FALSE,
-                                       this_lock ? this_lock->token : NULL,
+                                       ths->lock ? ths->lock->token : NULL,
                                        iterpool));
         } /* end file case */
 
       /*** Directories (in recursive mode) ***/
-      else if (this_kind == svn_wc__db_kind_dir
+      else if (ths->kind == svn_wc__db_kind_dir
                && (depth > svn_depth_files
                    || depth == svn_depth_unknown))
         {
           svn_boolean_t is_incomplete;
           svn_boolean_t start_empty;
 
-          is_incomplete = (this_status == svn_wc__db_status_incomplete);
+          is_incomplete = (ths->status == svn_wc__db_status_incomplete);
           start_empty = is_incomplete;
 
           if (depth_compatibility_trick
-              && this_depth <= svn_depth_files
-              && depth > this_depth)
+              && ths->depth <= svn_depth_files
+              && depth > ths->depth)
             {
               start_empty = TRUE;
             }
@@ -585,20 +577,20 @@ report_revisions_and_depths(svn_wc__db_t
                                             this_path,
                                             svn_path_url_add_component2(
                                                 dir_repos_root,
-                                                this_repos_relpath, iterpool),
-                                            this_rev,
-                                            this_depth,
+                                                ths->repos_relpath, iterpool),
+                                            ths->revnum,
+                                            ths->depth,
                                             start_empty,
-                                            this_lock ? this_lock->token
+                                            ths->lock ? ths->lock->token
                                                       : NULL,
                                             iterpool));
               else
                 SVN_ERR(reporter->set_path(report_baton,
                                            this_path,
-                                           this_rev,
-                                           this_depth,
+                                           ths->revnum,
+                                           ths->depth,
                                            start_empty,
-                                           this_lock ? this_lock->token : NULL,
+                                           ths->lock ? ths->lock->token : NULL,
                                            iterpool));
             }
           else if (this_switched)
@@ -608,21 +600,21 @@ report_revisions_and_depths(svn_wc__db_t
                                           this_path,
                                           svn_path_url_add_component2(
                                               dir_repos_root,
-                                              this_repos_relpath, iterpool),
-                                          this_rev,
-                                          this_depth,
+                                              ths->repos_relpath, iterpool),
+                                          ths->revnum,
+                                          ths->depth,
                                           start_empty,
-                                          this_lock ? this_lock->token : NULL,
+                                          ths->lock ? ths->lock->token : NULL,
                                           iterpool));
             }
-          else if (this_rev != dir_rev
-                   || this_lock
+          else if (ths->revnum != dir_rev
+                   || ths->lock
                    || is_incomplete
                    || dir_depth == svn_depth_empty
                    || dir_depth == svn_depth_files
                    || (dir_depth == svn_depth_immediates
-                       && this_depth != svn_depth_empty)
-                   || (this_depth < svn_depth_infinity
+                       && ths->depth != svn_depth_empty)
+                   || (ths->depth < svn_depth_infinity
                        && depth == svn_depth_infinity))
             {
               /* ... or perhaps just a differing revision, lock token,
@@ -633,10 +625,10 @@ report_revisions_and_depths(svn_wc__db_t
                  trying to set depth to infinity. */
               SVN_ERR(reporter->set_path(report_baton,
                                          this_path,
-                                         this_rev,
-                                         this_depth,
+                                         ths->revnum,
+                                         ths->depth,
                                          start_empty,
-                                         this_lock ? this_lock->token : NULL,
+                                         ths->lock ? ths->lock->token : NULL,
                                          iterpool));
             }
 
@@ -645,7 +637,7 @@ report_revisions_and_depths(svn_wc__db_t
             SVN_ERR(report_revisions_and_depths(db,
                                                 anchor_abspath,
                                                 this_path,
-                                                this_rev,
+                                                ths->revnum,
                                                 reporter, report_baton,
                                                 external_func, external_baton,
                                                 notify_func, notify_baton,

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Wed Mar 16 22:13:21 
2011
@@ -62,6 +62,15 @@ LEFT OUTER JOIN lock ON nodes.repos_id =
   AND nodes.repos_path = lock.repos_relpath
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
 
+-- STMT_SELECT_BASE_CHILDREN_INFO
+SELECT local_relpath, nodes.repos_id, nodes.repos_path, presence, kind,
+  revision, depth, file_external IS NOT NULL,
+  lock_token, lock_owner, lock_comment, lock_date
+FROM nodes
+LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
+  AND nodes.repos_path = lock.repos_relpath
+WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0;
+
 -- STMT_SELECT_WORKING_NODE
 SELECT op_depth, presence, kind, checksum, translated_size,
   changed_revision, changed_date, changed_author, depth, symlink_target,

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Wed Mar 16 22:13:21 2011
@@ -1935,6 +1935,76 @@ svn_wc__db_base_get_info(svn_wc__db_stat
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__db_base_get_children_info(apr_hash_t **nodes,
+                                  svn_wc__db_t *db,
+                                  const char *dir_abspath,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                              dir_abspath, svn_sqlite__mode_readonly,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  *nodes = apr_hash_make(result_pool);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, 
+                                    STMT_SELECT_BASE_CHILDREN_INFO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  while (have_row)
+    {
+      struct svn_wc__db_base_info_t *info;
+      svn_error_t *err;
+      apr_int64_t repos_id;
+      const char *depth_str;
+      const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *name = svn_relpath_basename(child_relpath, result_pool);
+
+      info = apr_pcalloc(result_pool, sizeof(*info));
+
+      repos_id = svn_sqlite__column_int64(stmt, 1);
+      info->repos_relpath = svn_sqlite__column_text(stmt, 2, result_pool);
+      info->status = svn_sqlite__column_token(stmt, 3, presence_map);
+      info->kind = svn_sqlite__column_token(stmt, 4, kind_map);
+      info->revnum = svn_sqlite__column_revnum(stmt, 5);
+
+      depth_str = svn_sqlite__column_text(stmt, 6, NULL);
+
+      info->depth = (depth_str != NULL) ? svn_depth_from_word(depth_str)
+                                        : svn_depth_unknown;
+      info->update_root = svn_sqlite__column_boolean(stmt, 7);
+
+      info->lock = lock_from_columns(stmt, 8, 9, 10, 11, result_pool);
+
+      err = fetch_repos_info(&info->repos_root_url, NULL, wcroot->sdb,
+                             repos_id, result_pool);
+
+      if (err)
+        return svn_error_return(
+                 svn_error_compose_create(err,
+                                          svn_sqlite__reset(stmt)));
+                           
+
+      apr_hash_set(*nodes, name, APR_HASH_KEY_STRING, info);
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_wc__db_base_get_prop(const svn_string_t **propval,

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Wed Mar 16 22:13:21 2011
@@ -747,6 +747,29 @@ svn_wc__db_base_get_info(svn_wc__db_stat
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/* Structure returned by svn_wc__db_base_get_children_info.  Only has the
+   fields needed by the adm crawler. */
+struct svn_wc__db_base_info_t {
+  svn_wc__db_status_t status;
+  svn_wc__db_kind_t kind;
+  svn_revnum_t revnum;
+  const char *repos_relpath;
+  const char *repos_root_url;
+  svn_depth_t depth;
+  svn_boolean_t update_root;
+  svn_wc__db_lock_t *lock;
+};
+
+/* Return in *NODES a hash mapping name->struct svn_wc__db_base_info_t for
+   the children of DIR_ABSPATH at op_depth 0.
+ */
+svn_error_t *
+svn_wc__db_base_get_children_info(apr_hash_t **nodes,
+                                  svn_wc__db_t *db,
+                                  const char *dir_abspath,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool);
+
 
 /* Set *PROPVAL to the value of the property named PROPNAME of the node
    LOCAL_ABSPATH in the BASE tree.


Reply via email to