You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/01/19 13:25:27 UTC

svn commit: r1435527 - in /subversion/trunk/subversion: include/svn_io.h libsvn_subr/deprecated.c libsvn_subr/io.c libsvn_subr/sysinfo.c libsvn_wc/status.c

Author: rhuijben
Date: Sat Jan 19 12:25:27 2013
New Revision: 1435527

URL: http://svn.apache.org/viewvc?rev=1435527&view=rev
Log:
Optimize a few truename checks on Windows to use a far more efficient code
path.

* subversion/include/svn_io.h
  (svn_io_stat_dirent2): New function, allowing optional truename check.
  (svn_io_stat_dirent): Deprecate function.

* subversion/libsvn_subr/deprecated.c
  (svn_io_stat_dirent): New function.

* subversion/libsvn_subr/io.c
  (svn_io_stat_dirent): Rename to ...
  (svn_io_stat_dirent2): ... this and use the existing stat call to perform
    a truename check.

* subversion/libsvn_subr/sysinfo.c
  (includes): Add path handling.
  (win32_shared_libs): Just use our own apis instead of the apr ones, that
    perform a lot of unnecessary IO for the TRUENAME question that we don't
    even need.

* subversion/libsvn_wc/status.c
  (stat_wc_dirent_case_sensitive): Use svn_io_stat_dirent2 for a cheaper
    truename check.

Modified:
    subversion/trunk/subversion/include/svn_io.h
    subversion/trunk/subversion/libsvn_subr/deprecated.c
    subversion/trunk/subversion/libsvn_subr/io.c
    subversion/trunk/subversion/libsvn_subr/sysinfo.c
    subversion/trunk/subversion/libsvn_wc/status.c

Modified: subversion/trunk/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_io.h?rev=1435527&r1=1435526&r2=1435527&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_io.h (original)
+++ subversion/trunk/subversion/include/svn_io.h Sat Jan 19 12:25:27 2013
@@ -1553,10 +1553,31 @@ svn_io_get_dirents(apr_hash_t **dirents,
 /** Create a svn_io_dirent2_t instance for path. Specialized variant of
  * svn_io_stat() that directly translates node_kind and special.
  *
+ * If @a verify_truename is @c TRUE, an additional check is performed to
+ * verify the truename of the last path component on case insensitive
+ * filesystems. This check is expensive compared to a just a stat,
+ * but certainly cheaper than a full truename calculation using
+ * apr_filepath_merge() which verifies all path components.
+ *
  * If @a ignore_enoent is set to @c TRUE, set *dirent_p->kind to
  * svn_node_none instead of returning an error.
  *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_io_stat_dirent2(const svn_io_dirent2_t **dirent_p,
+                    const char *path,
+                    svn_boolean_t verify_truename,
+                    svn_boolean_t ignore_enoent,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool);
+
+
+/** Similar to svn_io_stat_dirent2, but always passes FALSE for
+ * verify_truename.
+ *
  * @since New in 1.7.
+ * @deprecated Provided for backwards compatibility with the 1.7 API.
  */
 svn_error_t *
 svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p,

Modified: subversion/trunk/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/deprecated.c?rev=1435527&r1=1435526&r2=1435527&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_subr/deprecated.c Sat Jan 19 12:25:27 2013
@@ -878,6 +878,22 @@ svn_io_dir_walk(const char *dirname,
                                           &baton, pool));
 }
 
+svn_error_t *
+svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p,
+                   const char *path,
+                   svn_boolean_t ignore_enoent,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(
+            svn_io_stat_dirent2(dirent_p,
+                                path,
+                                FALSE,
+                                ignore_enoent,
+                                result_pool,
+                                scratch_pool));
+}
+
 /*** From constructors.c ***/
 svn_log_changed_path_t *
 svn_log_changed_path_dup(const svn_log_changed_path_t *changed_path,

Modified: subversion/trunk/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/io.c?rev=1435527&r1=1435526&r2=1435527&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/io.c (original)
+++ subversion/trunk/subversion/libsvn_subr/io.c Sat Jan 19 12:25:27 2013
@@ -2493,20 +2493,25 @@ svn_io_get_dirents3(apr_hash_t **dirents
 }
 
 svn_error_t *
-svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p,
-                   const char *path,
-                   svn_boolean_t ignore_enoent,
-                   apr_pool_t *result_pool,
-                   apr_pool_t *scratch_pool)
+svn_io_stat_dirent2(const svn_io_dirent2_t **dirent_p,
+                    const char *path,
+                    svn_boolean_t verify_truename,
+                    svn_boolean_t ignore_enoent,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
 {
   apr_finfo_t finfo;
   svn_io_dirent2_t *dirent;
   svn_error_t *err;
+  apr_int32_t wanted = APR_FINFO_TYPE | APR_FINFO_LINK
+                       | APR_FINFO_SIZE | APR_FINFO_MTIME;
 
-  err = svn_io_stat(&finfo, path,
-                    APR_FINFO_TYPE | APR_FINFO_LINK
-                    | APR_FINFO_SIZE | APR_FINFO_MTIME,
-                    scratch_pool);
+#if defined(WIN32) || defined(__OS2__) || defined(DARWIN)
+  if (verify_truename)
+    wanted |= APR_FINFO_NAME;
+#endif
+
+  err = svn_io_stat(&finfo, path, wanted, scratch_pool);
 
   if (err && ignore_enoent &&
       (APR_STATUS_IS_ENOENT(err->apr_err)
@@ -2521,6 +2526,76 @@ svn_io_stat_dirent(const svn_io_dirent2_
     }
   SVN_ERR(err);
 
+#if defined(WIN32) || defined(__OS2__) || defined(DARWIN)
+  if (verify_truename)
+    {
+      const char *requested_name = svn_dirent_basename(path, NULL);
+
+      if (requested_name[0] == '\0')
+        {
+          /* No parent directory. No need to stat/verify */
+        }
+      else if (finfo.name)
+        {
+          const char *name_on_disk;
+          SVN_ERR(entry_name_to_utf8(&name_on_disk, finfo.name, path,
+                                     scratch_pool));
+
+          if (strcmp(name_on_disk, requested_name) /* != 0 */)
+            {
+              if (ignore_enoent)
+                {
+                  *dirent_p = svn_io_dirent2_create(result_pool);
+                  return SVN_NO_ERROR;
+                }
+              else
+                return svn_error_createf(APR_ENOENT, NULL,
+                          _("Path '%s' not found, case obstructed by '%s'"),
+                          svn_dirent_local_style(path, scratch_pool),
+                          name_on_disk);
+            }
+        }
+#if defined(DARWIN)
+      /* Currently apr doesn't set finfo.name on DARWIN.
+         ### Can we optimize this in another way? */
+      else
+        {
+          apr_hash_t *dirents;
+
+          err = svn_io_get_dirents3(&dirents,
+                                    svn_dirent_dirname(path, scratch_pool),
+                                    TRUE /* only_check_type */,
+                                    scratch_pool, scratch_pool);
+
+          if (err && ignore_enoent
+              && (APR_STATUS_IS_ENOENT(err->apr_err)
+                  || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
+            {
+              svn_error_clear(err);
+
+              *dirent_p = svn_io_dirent2_create(result_pool);
+              return SVN_NO_ERROR;
+            }
+          else
+            SVN_ERR(err);
+
+          if (! apr_hash_get(dirents, requested_name, APR_HASH_KEY_STRING))
+            {
+              if (ignore_enoent)
+                {
+                  *dirent_p = svn_io_dirent2_create(result_pool);
+                  return SVN_NO_ERROR;
+                }
+              else
+                return svn_error_createf(APR_ENOENT, NULL,
+                          _("Path '%s' not found"),
+                          svn_dirent_local_style(path, scratch_pool));
+            }
+        }
+#endif
+    }
+#endif
+
   dirent = svn_io_dirent2_create(result_pool);
   map_apr_finfo_to_node_kind(&(dirent->kind), &(dirent->special), &finfo);
 

Modified: subversion/trunk/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/sysinfo.c?rev=1435527&r1=1435526&r2=1435527&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/trunk/subversion/libsvn_subr/sysinfo.c Sat Jan 19 12:25:27 2013
@@ -42,7 +42,9 @@
 #include <apr_version.h>
 #include <apu_version.h>
 
+#include "svn_pools.h"
 #include "svn_ctype.h"
+#include "svn_dirent_uri.h"
 #include "svn_error.h"
 #include "svn_io.h"
 #include "svn_string.h"
@@ -831,25 +833,19 @@ win32_shared_libs(apr_pool_t *pool)
       if (GetModuleFileNameW(*module, buffer, MAX_PATH))
         {
           buffer[MAX_PATH] = 0;
+
           version = file_version_number(buffer, pool);
           filename = wcs_to_utf8(buffer, pool);
           if (filename)
             {
               svn_version_ext_loaded_lib_t *lib;
-              char *truename;
-
-              if (0 == apr_filepath_merge(&truename, "", filename,
-                                          APR_FILEPATH_NATIVE
-                                          | APR_FILEPATH_TRUENAME,
-                                          pool))
-                filename = truename;
 
               if (!array)
                 {
                   array = apr_array_make(pool, 32, sizeof(*lib));
                 }
               lib = &APR_ARRAY_PUSH(array, svn_version_ext_loaded_lib_t);
-              lib->name = filename;
+              lib->name = svn_dirent_local_style(filename, pool);
               lib->version = version;
             }
         }

Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=1435527&r1=1435526&r2=1435527&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Sat Jan 19 12:25:27 2013
@@ -2702,6 +2702,7 @@ stat_wc_dirent_case_sensitive(const svn_
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool)
 {
+  svn_boolean_t verify_truename = FALSE;
 #if defined(WIN32) || defined(DARWIN)
   svn_boolean_t is_wcroot;
   /* We only need this code on systems with case insensitive filesystem
@@ -2712,43 +2713,13 @@ stat_wc_dirent_case_sensitive(const svn_
   SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, 
                                scratch_pool));
 
-  if (! is_wcroot)
-    {
-      apr_hash_t *dirents;
-      svn_error_t *err;
-      const char *parent_abspath;
-      const char *name;
-
-      svn_dirent_split(&parent_abspath, &name, local_abspath, scratch_pool);
-
-      /* Obtain the name of the node, as stored in the directory.
-         Do this to avoid case insensitivity differences */
-
-      err = svn_io_get_dirents3(&dirents, parent_abspath, FALSE,
-                                scratch_pool, scratch_pool);
-
-      if (err
-          && (APR_STATUS_IS_ENOENT(err->apr_err)
-              || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
-        {
-          svn_error_clear(err);
-          dirents = NULL;
-        }
-      else
-        SVN_ERR(err);
-
-      *dirent = dirents ? apr_hash_get(dirents, name, APR_HASH_KEY_STRING)
-                       : NULL;
-
-      if (!*dirent)
-        *dirent = svn_io_dirent2_create(scratch_pool);
-
-      return SVN_NO_ERROR;
-    }
+  verify_truename = ! is_wcroot;
 #endif
 
-  return svn_error_trace(svn_io_stat_dirent(dirent, local_abspath, TRUE,
-                                            result_pool, scratch_pool));
+  return svn_error_trace(svn_io_stat_dirent2(dirent, local_abspath,
+                                             verify_truename,
+                                             TRUE /* ignore_enoent */,
+                                             result_pool, scratch_pool));
 }
 
 svn_error_t *
@@ -2800,8 +2771,8 @@ svn_wc__internal_walk_status(svn_wc__db_
 
       wb.externals = apr_hash_make(scratch_pool);
 
-      SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, TRUE, scratch_pool,
-                               scratch_pool));
+      SVN_ERR(svn_io_stat_dirent2(&dirent, local_abspath, FALSE, TRUE,
+                                  scratch_pool, scratch_pool));
     }
   else
     {