Author: stefan2
Date: Mon May 16 00:02:05 2011
New Revision: 1103578

URL: http://svn.apache.org/viewvc?rev=1103578&view=rev
Log:
Eliminate unnecessary stat calls during checkout, part 1 of 2.
Most c/o will be to an otherwise empty directory. In that case,
we don't need to check for obstructions.

* subversion/include/svn_wc.h
  (svn_wc_get_update_editor4): add clean_checkout parameter
* subversion/libsvn_wc/deprecated.c
  (svn_wc_get_update_editor3): disable optimization for legacy API

* subversion/libsvn_wc/update_editor.c
  (edit_baton): add clean_checkout flag
  (add_file): skip obstruction checks if that flag has been set
  (make_editor): add clean_checkout parameter and pass it on to baton
  (svn_wc_get_update_editor4): pass clean_checkout through to make_editor
  (svn_wc_get_switch_editor4): disable optimization for switch ops

* subversion/libsvn_client/update.c
  (is_empty_wc): new utility function
  (update_internal): detect applicability of "clean c/o" optimization 
   and parametrize update_editor accordingly

Modified:
    subversion/trunk/subversion/include/svn_wc.h
    subversion/trunk/subversion/libsvn_client/update.c
    subversion/trunk/subversion/libsvn_wc/deprecated.c
    subversion/trunk/subversion/libsvn_wc/update_editor.c

Modified: subversion/trunk/subversion/include/svn_wc.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1103578&r1=1103577&r2=1103578&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Mon May 16 00:02:05 2011
@@ -5439,6 +5439,7 @@ svn_wc_get_update_editor4(const svn_delt
                           svn_boolean_t allow_unver_obstructions,
                           svn_boolean_t adds_as_modification,
                           svn_boolean_t server_performs_filtering,
+                          svn_boolean_t clean_checkout,
                           const char *diff3_cmd,
                           const apr_array_header_t *preserved_exts,
                           svn_wc_dirents_func_t fetch_dirents_func,
@@ -5465,8 +5466,8 @@ svn_wc_get_update_editor4(const svn_delt
  * All locks, both those in @a anchor and newly acquired ones, will be
  * released when the editor driver calls @c close_edit.
  *
- * Always sets @a adds_as_modification to TRUE and @a server_performs_filtering
- * to FALSE.
+ * Always sets @a adds_as_modification to TRUE, @a server_performs_filtering
+ * and @a clean_checkout to FALSE.
  *
  * Uses a svn_wc_conflict_resolver_func_t conflict resolver instead of a
  * svn_wc_conflict_resolver_func2_t.

Modified: subversion/trunk/subversion/libsvn_client/update.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=1103578&r1=1103577&r2=1103578&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Mon May 16 00:02:05 2011
@@ -92,6 +92,59 @@ svn_client__dirent_fetcher(void *baton,
 
 /*** Code. ***/
 
+/* Set *CLEAN_CHECKOUT to FALSE only if LOCAL_ABSPATH is a non-empty
+   folder. ANCHOR_ABSPATH is the w/c root and LOCAL_ABSPATH will still
+   be considered empty, if it is equal to ANCHOR_ABSPATH and only
+   contains the admin sub-folder. 
+ */
+static svn_error_t *
+is_empty_wc(const char *local_abspath, 
+            const char *anchor_abspath, 
+            svn_boolean_t *clean_checkout, 
+            apr_pool_t *pool)
+{
+  apr_dir_t *dir;
+  apr_finfo_t finfo;
+  svn_error_t *err;
+
+  /* "clean" until found dirty */
+  *clean_checkout = TRUE;
+  
+  /* open directory. If it does not exist, yet, a clean one will
+     be created by the caller. If it cannot be openend for other
+     reasons, the caller will detect and report those as well. */
+  err = svn_io_dir_open(&dir, local_abspath, pool);
+  if (err)
+    {
+      svn_error_clear(err);
+      return SVN_NO_ERROR;
+    }
+  
+  for (err = svn_io_dir_read(&finfo, APR_FINFO_NAME, dir, pool);
+       err == SVN_NO_ERROR;
+       err = svn_io_dir_read(&finfo, APR_FINFO_NAME, dir, pool))
+    {
+      /* Ignore entries for this dir and its parent, robustly.
+         (APR promises that they'll come first, so technically
+         this guard could be moved outside the loop.  But Ryan Bloom
+         says he doesn't believe it, and I believe him. */
+      if (! (finfo.name[0] == '.'
+             && (finfo.name[1] == '\0'
+                 || (finfo.name[1] == '.' && finfo.name[2] == '\0'))))
+        {
+          if (   ! svn_wc_is_adm_dir(finfo.name, pool)
+              || strcmp(local_abspath, anchor_abspath) != 0)
+            {
+              *clean_checkout = FALSE;
+              break;
+            }
+        }
+    }
+  
+  svn_error_clear(err);
+  return svn_io_dir_close(dir);
+}
+
 /* This is a helper for svn_client__update_internal(), which see for
    an explanation of most of these parameters.  Some stuff that's
    unique is as follows:
@@ -134,6 +187,7 @@ update_internal(svn_revnum_t *result_rev
   svn_boolean_t use_commit_times;
   svn_boolean_t sleep_here = FALSE;
   svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
+  svn_boolean_t clean_checkout = FALSE;
   const char *diff3_cmd;
   svn_ra_session_t *ra_session;
   const char *preserved_exts_str;
@@ -211,6 +265,9 @@ update_internal(svn_revnum_t *result_rev
         }
     }
 
+  /* check whether the "clean c/o" optimization is applicable */
+  SVN_ERR(is_empty_wc(local_abspath, anchor_abspath, &clean_checkout, pool));
+
   /* Get the external diff3, if any. */
   svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
                  SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
@@ -299,6 +356,7 @@ update_internal(svn_revnum_t *result_rev
                                     depth_is_sticky, allow_unver_obstructions,
                                     adds_as_modification,
                                     server_supports_depth,
+                                    clean_checkout,
                                     diff3_cmd, preserved_exts,
                                     svn_client__dirent_fetcher, &dfb,
                                     ctx->conflict_func2, ctx->conflict_baton2,

Modified: subversion/trunk/subversion/libsvn_wc/deprecated.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/deprecated.c?rev=1103578&r1=1103577&r2=1103578&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_wc/deprecated.c Mon May 16 00:02:05 2011
@@ -3097,6 +3097,7 @@ svn_wc_get_update_editor3(svn_revnum_t *
                                     allow_unver_obstructions,
                                     TRUE /* adds_as_modification */,
                                     FALSE /* server_performs_filtering */,
+                                    FALSE /* clean_checkout */,
                                     diff3_cmd,
                                     preserved_exts,
                                     NULL, NULL, /* fetch_dirents_func, baton */

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1103578&r1=1103577&r2=1103578&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Mon May 16 00:02:05 
2011
@@ -190,6 +190,10 @@ struct edit_baton
   /* Handle local additions as modifications of new nodes */
   svn_boolean_t adds_as_modification;
 
+  /* If set, we check out into an empty directory. This allows for a number
+     of conflict checks to be omitted. */
+  svn_boolean_t clean_checkout;
+
   /* If this is a 'switch' operation, the new relpath of target_abspath,
      else NULL. */
   const char *switch_relpath;
@@ -2807,14 +2811,14 @@ add_file(const char *path,
   struct dir_baton *pb = parent_baton;
   struct edit_baton *eb = pb->edit_baton;
   struct file_baton *fb;
-  svn_node_kind_t kind;
-  svn_wc__db_kind_t wc_kind;
-  svn_wc__db_status_t status;
+  svn_node_kind_t kind = svn_node_none;
+  svn_wc__db_kind_t wc_kind = svn_wc__db_kind_unknown;
+  svn_wc__db_status_t status = svn_wc__db_status_normal;
   apr_pool_t *scratch_pool;
-  svn_boolean_t conflicted;
-  svn_boolean_t versioned_locally_and_present;
+  svn_boolean_t conflicted = FALSE;
+  svn_boolean_t versioned_locally_and_present = FALSE;
   svn_wc_conflict_description2_t *tree_conflict = NULL;
-  svn_error_t *err;
+  svn_error_t *err = SVN_NO_ERROR;
 
   SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
 
@@ -2839,14 +2843,17 @@ add_file(const char *path,
          "administrative directory"),
        svn_dirent_local_style(fb->local_abspath, pool));
 
-  SVN_ERR(svn_io_check_path(fb->local_abspath, &kind, scratch_pool));
+  if (!eb->clean_checkout)
+    {
+      SVN_ERR(svn_io_check_path(fb->local_abspath, &kind, scratch_pool));
 
-  err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL,
-                             &conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
-                             eb->db, fb->local_abspath,
-                             scratch_pool, scratch_pool);
+      err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, 
NULL,
+                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                NULL, NULL, NULL, NULL, NULL,
+                                &conflicted, NULL, NULL, NULL, NULL, NULL, 
NULL,
+                                eb->db, fb->local_abspath,
+                                scratch_pool, scratch_pool);
+    }
 
   if (err)
     {
@@ -2855,7 +2862,6 @@ add_file(const char *path,
 
       svn_error_clear(err);
       wc_kind = svn_wc__db_kind_unknown;
-      status = svn_wc__db_status_normal;
       conflicted = FALSE;
 
       versioned_locally_and_present = FALSE;
@@ -4344,6 +4350,7 @@ make_editor(svn_revnum_t *target_revisio
             svn_boolean_t allow_unver_obstructions,
             svn_boolean_t adds_as_modification,
             svn_boolean_t server_performs_filtering,
+            svn_boolean_t clean_checkout,
             svn_wc_notify_func2_t notify_func,
             void *notify_baton,
             svn_cancel_func_t cancel_func,
@@ -4428,6 +4435,7 @@ make_editor(svn_revnum_t *target_revisio
   eb->conflict_baton           = conflict_baton;
   eb->allow_unver_obstructions = allow_unver_obstructions;
   eb->adds_as_modification     = adds_as_modification;
+  eb->clean_checkout           = clean_checkout;
   eb->skipped_trees            = apr_hash_make(edit_pool);
   eb->dir_dirents              = apr_hash_make(edit_pool);
   eb->ext_patterns             = preserved_exts;
@@ -4609,6 +4617,7 @@ svn_wc_get_update_editor4(const svn_delt
                           svn_boolean_t allow_unver_obstructions,
                           svn_boolean_t adds_as_modification,
                           svn_boolean_t server_performs_filtering,
+                          svn_boolean_t clean_checkout,
                           const char *diff3_cmd,
                           const apr_array_header_t *preserved_exts,
                           svn_wc_dirents_func_t fetch_dirents_func,
@@ -4628,6 +4637,7 @@ svn_wc_get_update_editor4(const svn_delt
                      target_basename, use_commit_times,
                      NULL, depth, depth_is_sticky, allow_unver_obstructions,
                      adds_as_modification, server_performs_filtering,
+                     clean_checkout,
                      notify_func, notify_baton,
                      cancel_func, cancel_baton,
                      fetch_dirents_func, fetch_dirents_baton,
@@ -4673,6 +4683,7 @@ svn_wc_get_switch_editor4(const svn_delt
                      depth, depth_is_sticky, allow_unver_obstructions,
                      FALSE /* adds_as_modification */,
                      server_performs_filtering,
+                     FALSE /* clean_checkout */,
                      notify_func, notify_baton,
                      cancel_func, cancel_baton,
                      fetch_dirents_func, fetch_dirents_baton,


Reply via email to