subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1545955 [6/15] - in /subversion/branches/fsfs-improvements: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/server-side/ contrib/server-side/svncutter/ notes/ subversion/bindings/javahl/native/ s...
Date Wed, 27 Nov 2013 07:53:35 GMT
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/config_pool.c Wed Nov 27 07:53:29 2013
@@ -24,45 +24,42 @@
 
 
 
-#include <assert.h>
-
 #include "svn_checksum.h"
 #include "svn_config.h"
 #include "svn_error.h"
+#include "svn_hash.h"
 #include "svn_path.h"
 #include "svn_pools.h"
 #include "svn_repos.h"
 
-#include "private/svn_atomic.h"
+#include "private/svn_dep_compat.h"
 #include "private/svn_mutex.h"
 #include "private/svn_subr_private.h"
 #include "private/svn_repos_private.h"
+#include "private/svn_object_pool.h"
 
 #include "svn_private_config.h"
 
 
-/* A reference counting wrapper around a parsed svn_config_t* instance.  All
- * data in CFG is expanded (to make it thread-safe) and considered read-only.
+/* Our wrapper structure for parsed svn_config_t* instances.  All data in
+ * CS_CFG and CI_CFG is expanded (to make it thread-safe) and considered
+ * read-only.
  */
-typedef struct config_ref_t
+typedef struct config_object_t
 {
-  /* reference to the parent container */
-  svn_repos__config_pool_t *config_pool;
-
   /* UUID of the configuration contents.
    * This is a SHA1 checksum of the parsed textual representation of CFG. */
   svn_checksum_t *key;
 
-  /* Parsed and expanded configuration */
-  svn_config_t *cfg;
+  /* Parsed and expanded configuration.  At least one of the following
+   * must not be NULL. */
+
+  /* Case-sensitive config. May be NULL */
+  svn_config_t *cs_cfg;
 
-  /* private pool. This instance and its other members got allocated in it.
-   * Will be destroyed when this instance is cleaned up. */
-  apr_pool_t *pool;
-
-  /* Number of references to this data struct */
-  volatile svn_atomic_t ref_count;
-} config_ref_t;
+  /* Case-insensitive config. May be NULL */
+  svn_config_t *ci_cfg;
+} config_object_t;
 
 
 /* Data structure used to short-circuit the repository access for configs
@@ -71,8 +68,8 @@ typedef struct config_ref_t
  * the repository.
  *
  * As this is only an optimization and may create many entries in
- * svn_config_pool__t's IN_REPO_HASH_POOL index, we clean them up once in
- * a while.
+ * svn_repos__config_pool_t's IN_REPO_HASH_POOL index, we clean them up
+ * once in a while.
  */
 typedef struct in_repo_config_t
 {
@@ -90,10 +87,8 @@ typedef struct in_repo_config_t
 } in_repo_config_t;
 
 
-/* Core data structure.  All access to it must be serialized using MUTEX.
- *
- * CONFIGS maps a SHA1 checksum of the config text to the config_ref_t with
- * the parsed configuration in it.
+/* Core data structure extending the encapsulated OBJECT_POOL.  All access
+ * to it must be serialized using the OBJECT_POOL->MUTEX.
  *
  * To speed up URL@HEAD lookups, we maintain IN_REPO_CONFIGS as a secondary
  * hash index.  It maps URLs as provided by the caller onto in_repo_config_t
@@ -102,240 +97,105 @@ typedef struct in_repo_config_t
  * the respective repository.
  *
  * Unused configurations that are kept in the IN_REPO_CONFIGS hash and may
- * be cleaned up when the hash is about to grow.  We use various pools to
- * ensure that we can release unused memory for each data structure:
- *
- * - every config_ref_t uses its own pool
- *   (gets destroyed when config is removed from cache)
- * - CONFIGS_HASH_POOL is used for configs only
- * - IN_REPO_HASH_POOL is used for IN_REPO_CONFIGS and the in_repo_config_t
- *   structure in it
- *
- * References handed out to callers must remain valid until released.  In
- * that case, cleaning up the config pool will only set READY_FOR_CLEANUP
- * and the last reference being returned will actually trigger the
- * destruction.
+ * be cleaned up when the hash is about to grow.
  */
 struct svn_repos__config_pool_t
 {
-  /* serialization object for all non-atomic data in this struct */
-  svn_mutex__t *mutex;
-
-  /* set to TRUE when pool passed to svn_config_pool__create() gets cleaned
-   * up.  When set, the last config reference released must also destroy
-   * this config pool object. */
-  volatile svn_atomic_t ready_for_cleanup;
-
-  /* SHA1 -> config_ref_t* mapping */
-  apr_hash_t *configs;
-
-  /* number of entries in CONFIGS with a reference count > 0 */
-  volatile svn_atomic_t used_config_count;
+  svn_object_pool__t *object_pool;
 
   /* URL -> in_repo_config_t* mapping.
    * This is only a partial index and will get cleared regularly. */
   apr_hash_t *in_repo_configs;
 
-  /* the root pool owning this structure */
-  apr_pool_t *root_pool;
-
-  /* allocate the CONFIGS index here */
-  apr_pool_t *configs_hash_pool;
-
   /* allocate the IN_REPO_CONFIGS index and in_repo_config_t here */
   apr_pool_t *in_repo_hash_pool;
 };
 
 
-/* Destructor function for the whole config pool.
+/* Return an automatic reference to the CFG member in CONFIG that will be
+ * released when POOL gets cleaned up.  The case sensitivity flag in *BATON
+ * selects the desired option and section name matching mode.
  */
-static apr_status_t
-destroy_config_pool(svn_repos__config_pool_t *config_pool)
+static void *
+getter(void *object,
+       void *baton,
+       apr_pool_t *pool)
 {
-  svn_mutex__lock(config_pool->mutex);
-
-  /* there should be no outstanding references to any config in this pool */
-  assert(svn_atomic_read(&config_pool->used_config_count) == 0);
-
-  /* make future attempts to access this pool cause definitive segfaults */
-  config_pool->configs = NULL;
-  config_pool->in_repo_configs = NULL;
+  config_object_t *wrapper = object;
+  svn_boolean_t *case_sensitive = baton;
+  svn_config_t *config = *case_sensitive ? wrapper->cs_cfg : wrapper->ci_cfg;
 
-  /* This is the actual point of destruction. */
-  /* Destroying the pool will also release the lock. */
-  svn_pool_destroy(config_pool->root_pool);
-
-  return APR_SUCCESS;
+  /* we need to duplicate the root structure as it contains temp. buffers */
+  return config ? svn_config__shallow_copy(config, pool) : NULL;
 }
 
-/* Pool cleanup function for the whole config pool.  Actual destruction will
- * be deferred until no configurations are left in use.
+/* Return a memory buffer structure allocated in POOL and containing the
+ * data from CHECKSUM.
  */
-static apr_status_t
-config_pool_cleanup(void *baton)
+static svn_membuf_t *
+checksum_as_key(svn_checksum_t *checksum,
+                apr_pool_t *pool)
 {
-  svn_repos__config_pool_t *config_pool = baton;
+  svn_membuf_t *result = apr_pcalloc(pool, sizeof(*result));
+  apr_size_t size = svn_checksum_size(checksum);
 
-  svn_atomic_set(&config_pool->ready_for_cleanup, TRUE);
-  if (svn_atomic_read(&config_pool->used_config_count) == 0)
-    {
-      /* Attempts to get a configuration from a pool that whose cleanup has
-       * already started is illegal.
-       * So, used_config_count must not increase again.
-       */
-      destroy_config_pool(config_pool);
-    }
+  svn_membuf__create(result, size, pool);
+  result->size = size; /* exact length is required! */
+  memcpy(result->data, checksum->digest, size);
 
-  return APR_SUCCESS;
+  return result;
 }
 
-/* Cleanup function called when a config_ref_t gets released.
- */
-static apr_status_t
-config_ref_cleanup(void *baton)
-{
-  config_ref_t *config = baton;
-  svn_repos__config_pool_t *config_pool = config->config_pool;
-
-  /* Maintain reference counters and handle object cleanup */
-  if (   svn_atomic_dec(&config->ref_count) == 1
-      && svn_atomic_dec(&config_pool->used_config_count) == 1
-      && svn_atomic_read(&config_pool->ready_for_cleanup) == TRUE)
-    {
-      /* There cannot be any future references to a config in this pool.
-       * So, we are the last one and need to finally clean it up.
-       */
-      destroy_config_pool(config_pool);
-    }
-
-  return APR_SUCCESS;
-}
-
-/* Return an automatic reference to the CFG member in CONFIG that will be
- * released when POOL gets cleaned up.
- */
-static svn_config_t *
-return_config_ref(config_ref_t *config,
-                  apr_pool_t *pool)
-{
-  if (svn_atomic_inc(&config->ref_count) == 0)
-    svn_atomic_inc(&config->config_pool->used_config_count);
-  apr_pool_cleanup_register(pool, config, config_ref_cleanup,
-                            apr_pool_cleanup_null);
-  return config->cfg;
-}
-
-/* Set *CFG to the configuration with a parsed textual matching CHECKSUM.
- * Set *CFG to NULL if no such config can be found in CONFIG_POOL.
- * 
- * RESULT_POOL determines the lifetime of the returned reference.
- *
- * Requires external serialization on CONFIG_POOL.
+/* Copy the configuration from the wrapper in SOURCE to the wrapper in
+ * *TARGET with the case sensitivity flag in *BATON selecting the config
+ * to copy.  This is usually done to add the missing case-(in)-sensitive
+ * variant.  Since we must hold all data in *TARGET from the same POOL,
+ * a deep copy is required.
  */
 static svn_error_t *
-config_by_checksum(svn_config_t **cfg,
-                   svn_repos__config_pool_t *config_pool,
-                   svn_checksum_t *checksum,
-                   apr_pool_t *result_pool)
-{
-  config_ref_t *config_ref = apr_hash_get(config_pool->configs,
-                                          checksum->digest,
-                                          svn_checksum_size(checksum));
-  *cfg = config_ref ? return_config_ref(config_ref, result_pool) : NULL;
-
-  return SVN_NO_ERROR;
-}
+setter(void **target,
+       void *source,
+       void *baton,
+       apr_pool_t *pool)
+{
+  svn_boolean_t *case_sensitive = baton;
+  config_object_t *target_cfg = *(config_object_t **)target;
+  config_object_t *source_cfg = source;
 
-/* Re-allocate CONFIGS in CONFIG_POOL and remove all unused configurations
- * to minimize memory consumption.
- *
- * Requires external serialization on CONFIG_POOL.
- */
-static void
-remove_unused_configs(svn_repos__config_pool_t *config_pool)
-{
-  apr_pool_t *new_pool = svn_pool_create(config_pool->root_pool);
-  apr_hash_t *new_hash = svn_hash__make(new_pool);
-
-  apr_hash_index_t *hi;
-  for (hi = apr_hash_first(config_pool->configs_hash_pool,
-                           config_pool->configs);
-       hi != NULL;
-       hi = apr_hash_next(hi))
+  /* Maybe, we created a variant with different case sensitivity? */
+  if (*case_sensitive && target_cfg->cs_cfg == NULL)
     {
-      config_ref_t *config_ref = svn__apr_hash_index_val(hi);
-      if (config_ref->ref_count == 0)
-        svn_pool_destroy(config_ref->pool);
-      else
-        apr_hash_set(new_hash, config_ref->key->digest,
-                     svn_checksum_size(config_ref->key), config_ref);
+      SVN_ERR(svn_config_dup(&target_cfg->cs_cfg, source_cfg->cs_cfg, pool));
+      svn_config__set_read_only(target_cfg->cs_cfg, pool);
     }
-
-  svn_pool_destroy(config_pool->configs_hash_pool);
-  config_pool->configs = new_hash;
-  config_pool->configs_hash_pool = new_pool;
-}
-
-/* Cache config_ref* in CONFIG_POOL and return a reference to it in *CFG.
- * RESULT_POOL determines the lifetime of that reference.
- *
- * Requires external serialization on CONFIG_POOL.
- */
-static svn_error_t *
-config_add(svn_config_t **cfg,
-           svn_repos__config_pool_t *config_pool,
-           config_ref_t *config_ref,
-           apr_pool_t *result_pool)
-{
-  config_ref_t *config = apr_hash_get(config_ref->config_pool->configs,
-                                      config_ref->key->digest,
-                                      svn_checksum_size(config_ref->key));
-  if (config)
-    {
-      /* entry already exists (e.g. race condition)
-       * Destroy the new one and return a reference to the existing one
-       * because the existing one may already have references on it.
-       */
-      svn_pool_destroy(config_ref->pool);
-      config_ref = config;
-    }
-  else
+  else if (!*case_sensitive && target_cfg->ci_cfg == NULL)
     {
-      /* Release unused configurations if there are relatively frequent. */
-      if (  config_pool->used_config_count * 2 + 4
-          < apr_hash_count(config_pool->configs))
-        {
-          remove_unused_configs(config_pool);
-        }
-
-      /* add new index entry */
-      apr_hash_set(config_ref->config_pool->configs,
-                   config_ref->key->digest,
-                   svn_checksum_size(config_ref->key),
-                   config_ref);
+      SVN_ERR(svn_config_dup(&target_cfg->ci_cfg, source_cfg->ci_cfg, pool));
+      svn_config__set_read_only(target_cfg->ci_cfg, pool);
     }
 
-  *cfg = return_config_ref(config_ref, result_pool);
-
   return SVN_NO_ERROR;
 }
 
-/* Set *CFG to the configuration passed in as text in CONTENTS.  If no such
- * configuration exists in CONFIG_POOL, yet, parse CONTENTS and cache the
- * result.
- * 
+/* Set *CFG to the configuration passed in as text in CONTENTS and *KEY to
+ * the corresponding object pool key.  If no such configuration exists in
+ * CONFIG_POOL, yet, parse CONTENTS and cache the result.  CASE_SENSITIVE
+ * controls option and section name matching.
+ *
  * RESULT_POOL determines the lifetime of the returned reference and 
  * SCRATCH_POOL is being used for temporary allocations.
  */
 static svn_error_t *
 auto_parse(svn_config_t **cfg,
+           svn_membuf_t **key,
            svn_repos__config_pool_t *config_pool,
            svn_stringbuf_t *contents,
+           svn_boolean_t case_sensitive,
            apr_pool_t *result_pool,
            apr_pool_t *scratch_pool)
 {
   svn_checksum_t *checksum;
-  config_ref_t *config_ref;
+  config_object_t *config_object;
   apr_pool_t *cfg_pool;
 
   /* calculate SHA1 over the whole file contents */
@@ -345,46 +205,36 @@ auto_parse(svn_config_t **cfg,
                    &checksum, NULL, svn_checksum_sha1, TRUE, scratch_pool)));
 
   /* return reference to suitable config object if that already exists */
-  *cfg = NULL;
-  SVN_MUTEX__WITH_LOCK(config_pool->mutex,
-                       config_by_checksum(cfg, config_pool, checksum,
-                                          result_pool));
-
+  *key = checksum_as_key(checksum, scratch_pool);
+  SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool,
+                                  *key, &case_sensitive, result_pool));
   if (*cfg)
     return SVN_NO_ERROR;
 
   /* create a pool for the new config object and parse the data into it  */
+  cfg_pool = svn_pool_create(svn_object_pool__pool(config_pool->object_pool));
 
-  /* the following is thread-safe because the allocator is thread-safe */
-  cfg_pool = svn_pool_create(config_pool->root_pool);
-
-  config_ref = apr_pcalloc(cfg_pool, sizeof(*config_ref));
-  config_ref->config_pool = config_pool;
-  config_ref->key = svn_checksum_dup(checksum, cfg_pool);
-  config_ref->pool = cfg_pool;
-  config_ref->ref_count = 0;
+  config_object = apr_pcalloc(cfg_pool, sizeof(*config_object));
 
-  SVN_ERR(svn_config_parse(&config_ref->cfg,
+  SVN_ERR(svn_config_parse(case_sensitive ? &config_object->cs_cfg
+                                          : &config_object->ci_cfg,
                            svn_stream_from_stringbuf(contents, scratch_pool),
-                           TRUE, TRUE, cfg_pool));
+                           case_sensitive, case_sensitive, cfg_pool));
 
   /* switch config data to r/o mode to guarantee thread-safe access */
-  svn_config__set_read_only(config_ref->cfg, cfg_pool);
+  svn_config__set_read_only(case_sensitive ? config_object->cs_cfg
+                                           : config_object->ci_cfg,
+                            cfg_pool);
 
   /* add config in pool, handle loads races and return the right config */
-  SVN_MUTEX__WITH_LOCK(config_pool->mutex,
-                       config_add(cfg, config_pool, config_ref, result_pool));
+  SVN_ERR(svn_object_pool__insert((void **)cfg, config_pool->object_pool,
+                                  *key, config_object, &case_sensitive,
+                                  cfg_pool, result_pool));
 
   return SVN_NO_ERROR;
 }
 
-/* Set *CFG to the configuration stored in URL@HEAD and cache it in 
- * CONFIG_POOL.
- * 
- * RESULT_POOL determines the lifetime of the returned reference and 
- * SCRATCH_POOL is being used for temporary allocations.
- *
- * Requires external serialization on CONFIG_POOL.
+/* Store a URL@REVISION to CHECKSUM, REPOS_ROOT in CONFIG_POOL.
  */
 static svn_error_t *
 add_checksum(svn_repos__config_pool_t *config_pool,
@@ -396,7 +246,7 @@ add_checksum(svn_repos__config_pool_t *c
   apr_size_t path_len = strlen(url);
   apr_pool_t *pool = config_pool->in_repo_hash_pool;
   in_repo_config_t *config = apr_hash_get(config_pool->in_repo_configs,
-                                            url, path_len);
+                                          url, path_len);
   if (config)
     {
       /* update the existing entry */
@@ -412,7 +262,7 @@ add_checksum(svn_repos__config_pool_t *c
     {
       /* insert a new entry.
        * Limit memory consumption by cyclically clearing pool and hash. */
-      if (2 * apr_hash_count(config_pool->configs)
+      if (2 * svn_object_pool__count(config_pool->object_pool)
           < apr_hash_count(config_pool->in_repo_configs))
         {
           svn_pool_clear(pool);
@@ -434,19 +284,24 @@ add_checksum(svn_repos__config_pool_t *c
 }
 
 /* Set *CFG to the configuration stored in URL@HEAD and cache it in 
- * CONFIG_POOL. ### Always returns a NULL CFG.
+ * CONFIG_POOL.  CASE_SENSITIVE controls
+ * option and section name matching.  If PREFERRED_REPOS is given,
+ * use that if it also matches URL.
  * 
  * RESULT_POOL determines the lifetime of the returned reference and 
  * SCRATCH_POOL is being used for temporary allocations.
  */
 static svn_error_t *
 find_repos_config(svn_config_t **cfg,
+                  svn_membuf_t **key,
                   svn_repos__config_pool_t *config_pool,
                   const char *url,
+                  svn_boolean_t case_sensitive,
+                  svn_repos_t *preferred_repos,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
-  svn_repos_t *repos;
+  svn_repos_t *repos = NULL;
   svn_fs_t *fs;
   svn_fs_root_t *root;
   svn_revnum_t youngest_rev;
@@ -461,11 +316,29 @@ find_repos_config(svn_config_t **cfg,
   *cfg = NULL;
   SVN_ERR(svn_uri_get_dirent_from_file_url(&dirent, url, scratch_pool));
 
-  /* Search for a repository in the full path. */
-  repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
+  /* maybe we can use the preferred repos instance instead of creating a
+   * new one */
+  if (preferred_repos)
+    {
+      repos_root_dirent = svn_repos_path(preferred_repos, scratch_pool);
+      if (!svn_dirent_is_absolute(repos_root_dirent))
+        SVN_ERR(svn_dirent_get_absolute(&repos_root_dirent,
+                                        repos_root_dirent,
+                                        scratch_pool));
+
+      if (svn_dirent_is_ancestor(repos_root_dirent, dirent))
+        repos = preferred_repos;
+    }
 
-  /* Attempt to open a repository at repos_root_dirent. */
-  SVN_ERR(svn_repos_open2(&repos, repos_root_dirent, NULL, scratch_pool));
+  /* open repos if no suitable preferred repos was provided. */
+  if (!repos)
+    {
+      /* Search for a repository in the full path. */
+      repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
+
+      /* Attempt to open a repository at repos_root_dirent. */
+      SVN_ERR(svn_repos_open2(&repos, repos_root_dirent, NULL, scratch_pool));
+    }
 
   fs_path = &dirent[strlen(repos_root_dirent)];
 
@@ -480,9 +353,11 @@ find_repos_config(svn_config_t **cfg,
   SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, root, fs_path,
                                FALSE, scratch_pool));
   if (checksum)
-    SVN_MUTEX__WITH_LOCK(config_pool->mutex,
-                         config_by_checksum(cfg, config_pool, checksum,
-                                            result_pool));
+    {
+      *key = checksum_as_key(checksum, scratch_pool);
+      SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool,
+                                      *key, &case_sensitive, result_pool));
+    }
 
   /* not parsed, yet? */
   if (!*cfg)
@@ -500,64 +375,57 @@ find_repos_config(svn_config_t **cfg,
                                         (apr_size_t)length, scratch_pool));
 
       /* handle it like ordinary file contents and cache it */
-      SVN_ERR(auto_parse(cfg, config_pool, contents, result_pool,
-                         scratch_pool));
+      SVN_ERR(auto_parse(cfg, key, config_pool, contents, case_sensitive,
+                         result_pool, scratch_pool));
     }
 
   /* store the (path,rev) -> checksum mapping as well */
   if (*cfg)
-    SVN_MUTEX__WITH_LOCK(config_pool->mutex,
+    SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool),
                          add_checksum(config_pool, url, repos_root_dirent,
                                       youngest_rev, checksum));
 
   return SVN_NO_ERROR;
 }
 
-/* Set *CFG to the configuration cached in CONFIG_POOL for URL.  If no
- * suitable config has been cached or if it is potentially outdated, set
- * *CFG to NULL.
- *
- * RESULT_POOL determines the lifetime of the returned reference and 
- * SCRATCH_POOL is being used for temporary allocations.
+/* Given the URL, search the CONFIG_POOL for an entry that maps it URL to
+ * a content checksum and is still up-to-date.  If this could be found,
+ * return the object's *KEY.  Use POOL for allocations.
  *
  * Requires external serialization on CONFIG_POOL.
+ *
+ * Note that this is only the URL(+rev) -> Checksum lookup and does not
+ * guarantee that there is actually a config object available for *KEY.
  */
 static svn_error_t *
-config_by_url(svn_config_t **cfg,
-              svn_repos__config_pool_t *config_pool,
-              const char *url,
-              apr_pool_t *result_pool,
-              apr_pool_t *scratch_pool)
+key_by_url(svn_membuf_t **key,
+           svn_repos__config_pool_t *config_pool,
+           const char *url,
+           apr_pool_t *pool)
 {
   svn_error_t *err;
-  config_ref_t *config_ref = NULL;
   svn_stringbuf_t *contents;
   apr_int64_t current;
 
   /* hash lookup url -> sha1 -> config */
-  in_repo_config_t *config = apr_hash_get(config_pool->in_repo_configs,
-                                          url, APR_HASH_KEY_STRING);
-  *cfg = 0;
-  if (config)
-    config_ref = apr_hash_get(config_pool->configs,
-                              config->key->digest,
-                              svn_checksum_size(config->key));
-  if (!config_ref)
+  in_repo_config_t *config = svn_hash_gets(config_pool->in_repo_configs, url);
+  *key = NULL;
+  if (!config)
     return SVN_NO_ERROR;
 
-  /* found *some* configuration. 
+  /* found *some* reference to a configuration.
    * Verify that it is still current.  Will fail for BDB repos. */
   err = svn_stringbuf_from_file2(&contents, 
                                  svn_dirent_join(config->repo_root,
-                                                 "db/current", scratch_pool),
-                                 scratch_pool);
+                                                 "db/current", pool),
+                                 pool);
   if (!err)
     err = svn_cstring_atoi64(&current, contents->data);
 
   if (err)
     svn_error_clear(err);
   else if (current == config->revision)
-    *cfg = return_config_ref(config_ref, result_pool);
+    *key = checksum_as_key(config->key, pool);
 
   return SVN_NO_ERROR;
 }
@@ -566,27 +434,25 @@ config_by_url(svn_config_t **cfg,
 
 svn_error_t *
 svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool,
+                              svn_boolean_t thread_safe,
                               apr_pool_t *pool)
 {
-  /* our allocator must be thread-safe */
-  apr_pool_t *root_pool
-    = apr_allocator_owner_get(svn_pool_create_allocator(TRUE));
+  svn_repos__config_pool_t *result;
+  svn_object_pool__t *object_pool;
+  apr_pool_t *root_pool;
+
+  SVN_ERR(svn_object_pool__create(&object_pool, getter, setter,
+                                  4, APR_UINT32_MAX, TRUE, thread_safe,
+                                  pool));
+  root_pool = svn_object_pool__pool(object_pool);
 
   /* construct the config pool in our private ROOT_POOL to survive POOL
    * cleanup and to prevent threading issues with the allocator */
-  svn_repos__config_pool_t *result = apr_pcalloc(pool, sizeof(*result));
-  SVN_ERR(svn_mutex__init(&result->mutex, TRUE, root_pool));
+  result = apr_pcalloc(root_pool, sizeof(*result));
 
-  result->root_pool = root_pool;
-  result->configs_hash_pool = svn_pool_create(root_pool);
+  result->object_pool = object_pool;
   result->in_repo_hash_pool = svn_pool_create(root_pool);
-  result->configs = svn_hash__make(result->configs_hash_pool);
   result->in_repo_configs = svn_hash__make(result->in_repo_hash_pool);
-  result->ready_for_cleanup = FALSE;
-
-  /* make sure we clean up nicely */
-  apr_pool_cleanup_register(pool, result, config_pool_cleanup,
-                            apr_pool_cleanup_null);
 
   *config_pool = result;
   return SVN_NO_ERROR;
@@ -594,30 +460,51 @@ svn_repos__config_pool_create(svn_repos_
 
 svn_error_t *
 svn_repos__config_pool_get(svn_config_t **cfg,
+                           svn_membuf_t **key,
                            svn_repos__config_pool_t *config_pool,
                            const char *path,
+                           svn_boolean_t must_exist,
+                           svn_boolean_t case_sensitive,
+                           svn_repos_t *preferred_repos,
                            apr_pool_t *pool)
 {
   svn_error_t *err = SVN_NO_ERROR;
   apr_pool_t *scratch_pool = svn_pool_create(pool);
 
+  /* make sure we always have a *KEY object */
+  svn_membuf_t *local_key = NULL;
+  if (key == NULL)
+    key = &local_key;
+  else
+    *key = NULL;
+
   if (svn_path_is_url(path))
     {
       /* Read config file from repository.
        * Attempt a quick lookup first. */
-      SVN_MUTEX__WITH_LOCK(config_pool->mutex,
-                           config_by_url(cfg, config_pool, path, pool,
-                                         scratch_pool));
-      if (cfg)
-        return SVN_NO_ERROR;
+      SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool),
+                           key_by_url(key, config_pool, path, pool));
+      if (*key)
+        {
+          SVN_ERR(svn_object_pool__lookup((void **)cfg,
+                                          config_pool->object_pool,
+                                          *key, &case_sensitive, pool));
+          if (*cfg)
+            {
+              svn_pool_destroy(scratch_pool);
+              return SVN_NO_ERROR;
+            }
+        }
 
       /* Read and cache the configuration.  This may fail. */
-      err = find_repos_config(cfg, config_pool, path, pool, scratch_pool);
+      err = find_repos_config(cfg, key, config_pool, path, case_sensitive,
+                              preferred_repos, pool, scratch_pool);
       if (err || !*cfg)
         {
           /* let the standard implementation handle all the difficult cases */
           svn_error_clear(err);
-          err = svn_repos__retrieve_config(cfg, path, TRUE, pool);
+          err = svn_repos__retrieve_config(cfg, path, must_exist,
+                                           case_sensitive, pool);
         }
     }
   else
@@ -629,12 +516,14 @@ svn_repos__config_pool_get(svn_config_t 
         {
           /* let the standard implementation handle all the difficult cases */
           svn_error_clear(err);
-          err = svn_config_read3(cfg, path, TRUE, TRUE, TRUE, pool);
+          err = svn_config_read3(cfg, path, must_exist, case_sensitive,
+                                 case_sensitive, pool);
         }
       else
         {
           /* parsing and caching will always succeed */
-          err = auto_parse(cfg, config_pool, contents, pool, scratch_pool);
+          err = auto_parse(cfg, key, config_pool, contents, case_sensitive,
+                           pool, scratch_pool);
         }
     }
 

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/deprecated.c Wed Nov 27 07:53:29 2013
@@ -763,6 +763,7 @@ svn_repos_verify_fs2(svn_repos_t *repos,
                                               start_rev,
                                               end_rev,
                                               FALSE,
+                                              FALSE,
                                               notify_func,
                                               notify_baton,
                                               cancel_func,

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c Wed Nov 27 07:53:29 2013
@@ -38,6 +38,7 @@
 
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_fs_private.h"
+#include "private/svn_utf_private.h"
 #include "private/svn_cache.h"
 
 #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
@@ -134,9 +135,9 @@ tracker_create(svn_revnum_t revision,
  * we encounter a new tree change.
  */
 static void
-tracker__trim(path_tracker_t *tracker,
-              const char *path,
-              svn_boolean_t allow_exact_match)
+tracker_trim(path_tracker_t *tracker,
+             const char *path,
+             svn_boolean_t allow_exact_match)
 {
   /* remove everything that is unrelated to PATH.
      Note that TRACKER->STACK is depth-ordered,
@@ -176,7 +177,7 @@ tracker_lookup(const char **orig_path,
                const char *path,
                apr_pool_t *pool)
 {
-  tracker__trim(tracker, path, TRUE);
+  tracker_trim(tracker, path, TRUE);
   if (tracker->depth == 0)
     {
       /* no tree changes -> paths are the same as in the previous rev. */
@@ -230,11 +231,11 @@ tracker_lookup(const char **orig_path,
    will have undefined values.
  */
 static path_tracker_entry_t *
-tracker__add_entry(path_tracker_t *tracker,
-                   const char *path)
+tracker_add_entry(path_tracker_t *tracker,
+                  const char *path)
 {
   path_tracker_entry_t *entry;
-  tracker__trim(tracker, path, FALSE);
+  tracker_trim(tracker, path, FALSE);
 
   if (tracker->depth == tracker->stack->nelts)
     {
@@ -263,7 +264,7 @@ tracker_path_copy(path_tracker_t *tracke
                   const char *copyfrom_path,
                   svn_revnum_t copyfrom_rev)
 {
-  path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+  path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
 
   svn_stringbuf_set(entry->copyfrom_path, copyfrom_path);
   entry->copyfrom_rev = copyfrom_rev;
@@ -276,7 +277,7 @@ static void
 tracker_path_add(path_tracker_t *tracker,
                  const char *path)
 {
-  path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+  path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
 
   svn_stringbuf_setempty(entry->copyfrom_path);
   entry->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -301,7 +302,7 @@ static void
 tracker_path_delete(path_tracker_t *tracker,
                     const char *path)
 {
-  path_tracker_entry_t *entry = tracker__add_entry(tracker, path);
+  path_tracker_entry_t *entry = tracker_add_entry(tracker, path);
 
   svn_stringbuf_setempty(entry->copyfrom_path);
   entry->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -380,6 +381,9 @@ struct edit_baton
   /* True if this "dump" is in fact a verify. */
   svn_boolean_t verify;
 
+  /* True if checking UCS normalization during a verify. */
+  svn_boolean_t check_ucs_norm;
+
   /* The first revision dumped in this dumpstream. */
   svn_revnum_t oldest_dumped_rev;
 
@@ -434,6 +438,12 @@ struct dir_baton
      really, they're all within this directory.) */
   apr_hash_t *deleted_entries;
 
+  /* A flag indicating that new entries have been added to this
+     directory in this revision. Used to optimize detection of UCS
+     representation collisions; we will only check for that in
+     revisions where new names appear in the directory. */
+  svn_boolean_t check_name_collision;
+
   /* pool to be used for deleting the hash items */
   apr_pool_t *pool;
 };
@@ -486,6 +496,7 @@ make_dir_baton(const char *path,
   new_db->added = added;
   new_db->written_out = FALSE;
   new_db->deleted_entries = apr_hash_make(pool);
+  new_db->check_name_collision = FALSE;
   new_db->pool = pool;
 
   return new_db;
@@ -581,6 +592,104 @@ node_must_not_exist(struct edit_baton *e
   return SVN_NO_ERROR;
 }
 
+
+static svn_error_t *
+check_ucs_normalization(const char *path,
+                        svn_node_kind_t kind,
+                        svn_repos_notify_func_t notify_func,
+                        void *notify_baton,
+                        apr_pool_t *scratch_pool)
+{
+  const char *const name = svn_relpath_basename(path, scratch_pool);
+  if (!svn_utf__is_normalized(name, scratch_pool))
+    {
+      svn_repos_notify_t *const notify =
+        svn_repos_notify_create(svn_repos_notify_warning, scratch_pool);
+      notify->warning = svn_repos_notify_warning_denormalized_name;
+      switch (kind)
+        {
+        case svn_node_dir:
+          notify->warning_str = apr_psprintf(
+              scratch_pool, _("Denormalized directory name '%s'"), path);
+          break;
+        case svn_node_file:
+          notify->warning_str = apr_psprintf(
+              scratch_pool, _("Denormalized file name '%s'"), path);
+          break;
+        default:
+          notify->warning_str = apr_psprintf(
+              scratch_pool, _("Denormalized entry name '%s'"), path);
+        }
+      notify_func(notify_baton, notify, scratch_pool);
+    }
+  return SVN_NO_ERROR;
+}
+
+
+/* Baton used by the check_mergeinfo_normalization hash iterator. */
+struct check_mergeinfo_normalization_baton
+{
+  const char* path;
+  apr_hash_t *normalized;
+  svn_membuf_t buffer;
+  svn_repos_notify_func_t notify_func;
+  void *notify_baton;
+};
+
+/* Hash iterator that verifies normalization and collision of paths in
+   an svn:mergeinfo property. */
+static svn_error_t *
+check_mergeinfo_normalization(void *baton, const void *key, apr_ssize_t klen,
+                              void *val, apr_pool_t *pool)
+{
+  static const char unique[] = "unique";
+  static const char collision[] = "collision";
+
+  struct check_mergeinfo_normalization_baton *const check_baton = baton;
+
+  const char *const path = key;
+  const char *normpath;
+  const char *found;
+
+  SVN_ERR(svn_utf__normalize(&normpath, path, klen, &check_baton->buffer));
+
+  found = svn_hash_gets(check_baton->normalized, normpath);
+  if (!found)
+    {
+      if (0 != strcmp(path, normpath))
+        {
+          /* Report denormlized mergeinfo path */
+          svn_repos_notify_t *const notify =
+            svn_repos_notify_create(svn_repos_notify_warning, pool);
+          notify->warning = svn_repos_notify_warning_denormalized_mergeinfo;
+          notify->warning_str = apr_psprintf(
+              pool, _("Denormalized path '%s' in %s property of '%s'"),
+              path, SVN_PROP_MERGEINFO, check_baton->path);
+          check_baton->notify_func(check_baton->notify_baton, notify, pool);
+        }
+      svn_hash_sets(check_baton->normalized,
+                    apr_pstrdup(pool, normpath), unique);
+    }
+  else if (found == collision)
+    /* Skip already reported collision */;
+  else
+    {
+      /* Report path collision in mergeinfo */
+      svn_repos_notify_t *const notify =
+        svn_repos_notify_create(svn_repos_notify_warning, pool);
+      notify->warning = svn_repos_notify_warning_mergeinfo_collision;
+      notify->warning_str = apr_psprintf(
+          pool, _("Duplicate representation of path '%s'"
+                  " in %s property of '%s'"),
+          normpath, SVN_PROP_MERGEINFO, check_baton->path);
+      check_baton->notify_func(check_baton->notify_baton, notify, pool);
+      svn_hash_sets(check_baton->normalized,
+                    apr_pstrdup(pool, normpath), collision);
+    }
+  return SVN_NO_ERROR;
+}
+
+
 /* This helper is the main "meat" of the editor -- it does all the
    work of writing a node record.
 
@@ -926,6 +1035,33 @@ dump_node(struct edit_baton *eb,
             }
         }
 
+      /* If we're checking UCS normalization, also parse any changed
+         mergeinfo and warn about denormalized paths and name
+         collisions there. */
+      if (eb->verify && eb->check_ucs_norm && eb->notify_func)
+        {
+          /* N.B.: This hash lookup happens only once; the conditions
+             for verifying historic mergeinfo references and checking
+             UCS normalization are mutually exclusive. */
+          svn_string_t *mergeinfo_str = svn_hash_gets(prophash,
+                                                      SVN_PROP_MERGEINFO);
+          if (mergeinfo_str)
+            {
+              svn_mergeinfo_t mergeinfo;
+              struct check_mergeinfo_normalization_baton check_baton;
+              check_baton.path = path;
+              check_baton.normalized = apr_hash_make(pool);
+              svn_membuf__create(&check_baton.buffer, 0, pool);
+              check_baton.notify_func = eb->notify_func;
+              check_baton.notify_baton = eb->notify_baton;
+              SVN_ERR(svn_mergeinfo_parse(&mergeinfo,
+                                          mergeinfo_str->data, pool));
+              SVN_ERR(svn_iter_apr_hash(NULL, mergeinfo,
+                                        check_mergeinfo_normalization,
+                                        &check_baton, pool));
+            }
+        }
+
       if (eb->use_deltas && compare_root)
         {
           /* Fetch the old property hash to diff against and output a header
@@ -1116,6 +1252,16 @@ add_directory(const char *path,
     /* Delete the path, it's now been dumped. */
     svn_hash_sets(pb->deleted_entries, path, NULL);
 
+  /* Check for UCS normalization and name clashes, but only if this is
+     actually a new name in the parent, not a replacement. */
+  if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
+    {
+      pb->check_name_collision = TRUE;
+      SVN_ERR(check_ucs_normalization(
+                  path, svn_node_dir,
+                  eb->notify_func, eb->notify_baton, pool));
+    }
+
   new_db->written_out = TRUE;
 
   *child_baton = new_db;
@@ -1215,6 +1361,16 @@ add_file(const char *path,
                     is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
                     pool));
 
+  /* Check for UCS normalization and name clashes, but only if this is
+     actually a new name in the parent, not a replacement. */
+  if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
+    {
+      pb->check_name_collision = TRUE;
+      SVN_ERR(check_ucs_normalization(
+                  path, svn_node_file,
+                  eb->notify_func, eb->notify_baton, pool));
+    }
+
   if (val)
     /* delete the path, it's now been dumped. */
     svn_hash_sets(pb->deleted_entries, path, NULL);
@@ -1382,6 +1538,7 @@ get_dump_editor(const svn_delta_editor_t
                 svn_revnum_t oldest_dumped_rev,
                 svn_boolean_t use_deltas,
                 svn_boolean_t verify,
+                svn_boolean_t check_ucs_norm,
                 svn_cache__t *verified_dirents_cache,
                 apr_pool_t *pool)
 {
@@ -1405,6 +1562,7 @@ get_dump_editor(const svn_delta_editor_t
   eb->current_rev = to_rev;
   eb->use_deltas = use_deltas;
   eb->verify = verify;
+  eb->check_ucs_norm = check_ucs_norm;
   eb->found_old_reference = found_old_reference;
   eb->found_old_mergeinfo = found_old_mergeinfo;
   eb->verified_dirents_cache = verified_dirents_cache;
@@ -1612,7 +1770,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
                               "", stream, &found_old_reference,
                               &found_old_mergeinfo, NULL,
                               notify_func, notify_baton,
-                              start_rev, use_deltas_for_rev, FALSE,
+                              start_rev, use_deltas_for_rev, FALSE, FALSE,
                               NULL, subpool));
 
       /* Drive the editor in one way or another. */
@@ -1790,9 +1948,59 @@ verify_directory_entry(void *baton, cons
   return SVN_NO_ERROR;
 }
 
+/* Baton used by the check_name_collision hash iterator. */
+struct check_name_collision_baton
+{
+  struct dir_baton *dir_baton;
+  apr_hash_t *normalized;
+  svn_membuf_t buffer;
+};
+
+/* Scan the directory and report all entry names that differ only in
+   Unicode character representaiton. */
+static svn_error_t *
+check_name_collision(void *baton, const void *key, apr_ssize_t klen,
+                     void *val, apr_pool_t *pool)
+{
+  static const char unique[] = "unique";
+  static const char collision[] = "collision";
+
+  struct check_name_collision_baton *const check_baton = baton;
+  const char *name;
+  const char *found;
+
+  SVN_ERR(svn_utf__normalize(&name, key, klen, &check_baton->buffer));
+
+  found = svn_hash_gets(check_baton->normalized, name);
+  if (!found)
+    svn_hash_sets(check_baton->normalized,
+                  apr_pstrdup(pool, name), unique);
+  else if (found == collision)
+    /* Skip already reported collision */;
+  else
+    {
+      struct dir_baton *const db = check_baton->dir_baton;
+      struct edit_baton *const eb = db->edit_baton;
+      svn_repos_notify_t *notify;
+      const char* normpath;
+
+      svn_hash_sets(check_baton->normalized,
+                    apr_pstrdup(pool, name), collision);
+      SVN_ERR(svn_utf__normalize(
+                  &normpath, svn_relpath_join(db->path, name, pool),
+                  SVN_UTF__UNKNOWN_LENGTH, &check_baton->buffer));
+      notify = svn_repos_notify_create(svn_repos_notify_warning, pool);
+      notify->warning = svn_repos_notify_warning_name_collision;
+      notify->warning_str = apr_psprintf(
+          pool, _("Duplicate representation of path '%s'"), normpath);
+      eb->notify_func(eb->notify_baton, notify, pool);
+    }
+  return SVN_NO_ERROR;
+}
+
+
 static svn_error_t *
-verify_close_directory(void *dir_baton,
-                apr_pool_t *pool)
+verify_close_directory(void *dir_baton, apr_pool_t *pool)
 {
   struct dir_baton *db = dir_baton;
   apr_hash_t *dirents;
@@ -1800,6 +2008,17 @@ verify_close_directory(void *dir_baton,
                              db->path, pool));
   SVN_ERR(svn_iter_apr_hash(NULL, dirents, verify_directory_entry,
                             dir_baton, pool));
+
+  if (db->check_name_collision)
+    {
+      struct check_name_collision_baton check_baton;
+      check_baton.dir_baton = db;
+      check_baton.normalized = apr_hash_make(pool);
+      svn_membuf__create(&check_baton.buffer, 0, pool);
+      SVN_ERR(svn_iter_apr_hash(NULL, dirents, check_name_collision,
+                                &check_baton, pool));
+    }
+
   return close_directory(dir_baton, pool);
 }
 
@@ -1828,6 +2047,7 @@ verify_one_revision(svn_fs_t *fs,
                     svn_repos_notify_func_t notify_func,
                     void *notify_baton,
                     svn_revnum_t start_rev,
+                    svn_boolean_t check_ucs_norm,
                     svn_cancel_func_t cancel_func,
                     void *cancel_baton,
                     svn_cache__t *verified_dirents_cache,
@@ -1849,6 +2069,7 @@ verify_one_revision(svn_fs_t *fs,
                           notify_func, notify_baton,
                           start_rev,
                           FALSE, TRUE, /* use_deltas, verify */
+                          check_ucs_norm,
                           verified_dirents_cache,
                           scratch_pool));
   SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
@@ -1926,6 +2147,7 @@ svn_repos_verify_fs3(svn_repos_t *repos,
                      svn_revnum_t start_rev,
                      svn_revnum_t end_rev,
                      svn_boolean_t keep_going,
+                     svn_boolean_t check_ucs_norm,
                      svn_repos_notify_func_t notify_func,
                      void *notify_baton,
                      svn_cancel_func_t cancel_func,
@@ -2021,7 +2243,8 @@ svn_repos_verify_fs3(svn_repos_t *repos,
 
       /* Wrapper function to catch the possible errors. */
       err = verify_one_revision(fs, rev, notify_func, notify_baton,
-                                start_rev, cancel_func, cancel_baton,
+                                start_rev, check_ucs_norm,
+                                cancel_func, cancel_baton,
                                 verified_dirents_cache, iterpool);
 
       if (err)

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/hooks.c Wed Nov 27 07:53:29 2013
@@ -417,17 +417,25 @@ svn_repos__parse_hooks_env(apr_hash_t **
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool)
 {
-  svn_config_t *cfg;
   struct parse_hooks_env_section_baton b;
-
   if (local_abspath)
     {
-      SVN_ERR(svn_config_read3(&cfg, local_abspath, FALSE,
-                               TRUE, TRUE, scratch_pool));
-      b.cfg = cfg;
+      svn_node_kind_t kind;
+      SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+
       b.hooks_env = apr_hash_make(result_pool);
-      (void)svn_config_enumerate_sections2(cfg, parse_hooks_env_section, &b,
-                                           scratch_pool);
+
+      if (kind != svn_node_none)
+        {
+          svn_config_t *cfg;
+          SVN_ERR(svn_config_read3(&cfg, local_abspath, FALSE,
+                                  TRUE, TRUE, scratch_pool));
+          b.cfg = cfg;
+
+          (void)svn_config_enumerate_sections2(cfg, parse_hooks_env_section,
+                                               &b, scratch_pool);
+        }
+
       *hooks_env_p = b.hooks_env;
     }
   else

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.c Wed Nov 27 07:53:29 2013
@@ -1796,6 +1796,11 @@ svn_repos_fs(svn_repos_t *repos)
   return repos->fs;
 }
 
+const char *
+svn_repos_fs_type(svn_repos_t *repos, apr_pool_t *pool)
+{
+  return apr_pstrdup(pool, repos->fs_type);
+}
 
 /* For historical reasons, for the Berkeley DB backend, this code uses
  * repository locking, which is motivated by the need to support the

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/repos.h Wed Nov 27 07:53:29 2013
@@ -382,6 +382,11 @@ svn_repos__authz_read(svn_authz_t **auth
                       svn_boolean_t accept_urls,
                       apr_pool_t *pool);
 
+/* Walk the configuration in AUTHZ looking for any errors. */
+svn_error_t *
+svn_repos__authz_validate(svn_authz_t *authz,
+                          apr_pool_t *pool);
+
 
 /*** Utility Functions ***/
 

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.c Wed Nov 27 07:53:29 2013
@@ -177,14 +177,18 @@ svn_auth_set_parameter(svn_auth_baton_t 
                        const char *name,
                        const void *value)
 {
-  svn_hash_sets(auth_baton->parameters, name, value);
+  if (auth_baton)
+    svn_hash_sets(auth_baton->parameters, name, value);
 }
 
 const void *
 svn_auth_get_parameter(svn_auth_baton_t *auth_baton,
                        const char *name)
 {
-  return svn_hash_gets(auth_baton->parameters, name);
+  if (auth_baton)
+    return svn_hash_gets(auth_baton->parameters, name);
+  else
+    return NULL;
 }
 
 
@@ -215,6 +219,10 @@ svn_auth_first_credentials(void **creden
   svn_auth_iterstate_t *iterstate;
   const char *cache_key;
 
+  if (! auth_baton)
+    return svn_error_create(SVN_ERR_AUTHN_NO_PROVIDER, NULL,
+                            _("No authentication providers registered"));
+
   /* Get the appropriate table of providers for CRED_KIND. */
   table = svn_hash_gets(auth_baton->tables, cred_kind);
   if (! table)
@@ -511,19 +519,19 @@ svn_auth_get_platform_specific_provider(
       if (strcmp(provider_name, "gpg_agent") == 0 &&
           strcmp(provider_type, "simple") == 0)
         {
-          svn_auth_get_gpg_agent_simple_provider(provider, pool);
+          svn_auth__get_gpg_agent_simple_provider(provider, pool);
         }
 #endif
 #ifdef SVN_HAVE_KEYCHAIN_SERVICES
       if (strcmp(provider_name, "keychain") == 0 &&
           strcmp(provider_type, "simple") == 0)
         {
-          svn_auth_get_keychain_simple_provider(provider, pool);
+          svn_auth__get_keychain_simple_provider(provider, pool);
         }
       else if (strcmp(provider_name, "keychain") == 0 &&
                strcmp(provider_type, "ssl_client_cert_pw") == 0)
         {
-          svn_auth_get_keychain_ssl_client_cert_pw_provider(provider, pool);
+          svn_auth__get_keychain_ssl_client_cert_pw_provider(provider, pool);
         }
 #endif
 
@@ -531,17 +539,17 @@ svn_auth_get_platform_specific_provider(
       if (strcmp(provider_name, "windows") == 0 &&
           strcmp(provider_type, "simple") == 0)
         {
-          svn_auth_get_windows_simple_provider(provider, pool);
+          svn_auth__get_windows_simple_provider(provider, pool);
         }
       else if (strcmp(provider_name, "windows") == 0 &&
                strcmp(provider_type, "ssl_client_cert_pw") == 0)
         {
-          svn_auth_get_windows_ssl_client_cert_pw_provider(provider, pool);
+          svn_auth__get_windows_ssl_client_cert_pw_provider(provider, pool);
         }
       else if (strcmp(provider_name, "windows") == 0 &&
                strcmp(provider_type, "ssl_server_trust") == 0)
         {
-          svn_auth_get_windows_ssl_server_trust_provider(provider, pool);
+          svn_auth__get_windows_ssl_server_trust_provider(provider, pool);
         }
       else if (strcmp(provider_name, "windows") == 0 &&
                strcmp(provider_type, "ssl_server_authority") == 0)

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/auth.h Wed Nov 27 07:53:29 2013
@@ -41,6 +41,121 @@ svn_auth__file_path(const char **path,
                     const char *config_dir,
                     apr_pool_t *pool);
 
+#if (defined(WIN32) && !defined(__MINGW32__)) || defined(DOXYGEN)
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory.  Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_simple_provider(), except that, when
+ * running on Window 2000 or newer (or any other Windows version that
+ * includes the CryptoAPI), the provider encrypts the password before
+ * storing it to disk. On earlier versions of Windows, the provider
+ * does nothing.
+ *
+ * @note This function is only available on Windows.
+ *
+ * @note An administrative password reset may invalidate the account's
+ * secret key. This function will detect that situation and behave as
+ * if the password were not cached at all.
+ */
+void
+svn_auth__get_windows_simple_provider(svn_auth_provider_object_t **provider,
+                                      apr_pool_t *pool);
+
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_ssl_client_cert_pw_t that gets/sets information from the
+ * user's ~/.subversion configuration directory.  Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_ssl_client_cert_pw_file_provider(), except that
+ * when running on Window 2000 or newer, the provider encrypts the password
+ * before storing it to disk. On earlier versions of Windows, the provider
+ * does nothing.
+ *
+ * @note This function is only available on Windows.
+ *
+ * @note An administrative password reset may invalidate the account's
+ * secret key. This function will detect that situation and behave as
+ * if the password were not cached at all.
+ */
+void
+svn_auth__get_windows_ssl_client_cert_pw_provider(
+  svn_auth_provider_object_t **provider,
+  apr_pool_t *pool);
+
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_ssl_server_trust_t, allocated in @a pool.
+ *
+ * This provider automatically validates ssl server certificates with
+ * the CryptoApi, like Internet Explorer and the Windows network API do.
+ * This allows the rollout of root certificates via Windows Domain
+ * policies, instead of Subversion specific configuration.
+ *
+ * @note This function is only available on Windows.
+ */
+void
+svn_auth__get_windows_ssl_server_trust_provider(
+  svn_auth_provider_object_t **provider,
+  apr_pool_t *pool);
+#endif /* WIN32 && !__MINGW32__ || DOXYGEN */
+
+#if defined(DARWIN) || defined(DOXYGEN)
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory.  Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_simple_provider(), except that the
+ * password is stored in the Mac OS KeyChain.
+ *
+ * @note This function is only available on Mac OS 10.2 and higher.
+ */
+void
+svn_auth__get_keychain_simple_provider(svn_auth_provider_object_t **provider,
+                                      apr_pool_t *pool);
+
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_ssl_client_cert_pw_t that gets/sets information from the
+ * user's ~/.subversion configuration directory.  Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_auth_get_ssl_client_cert_pw_file_provider(), except
+ * that the password is stored in the Mac OS KeyChain.
+ *
+ * @note This function is only available on Mac OS 10.2 and higher.
+ */
+void
+svn_auth__get_keychain_ssl_client_cert_pw_provider(
+  svn_auth_provider_object_t **provider,
+  apr_pool_t *pool);
+#endif /* DARWIN || DOXYGEN */
+
+#if !defined(WIN32) || defined(DOXYGEN)
+/**
+ * Set @a *provider to an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory.
+ *
+ * This is like svn_client_get_simple_provider(), except that the
+ * password is obtained from gpg_agent, which will keep it in
+ * a memory cache.
+ *
+ * Allocate @a *provider in @a pool.
+ *
+ * @note This function actually works only on systems with
+ * GNU Privacy Guard installed.
+ */
+void
+svn_auth__get_gpg_agent_simple_provider
+    (svn_auth_provider_object_t **provider,
+     apr_pool_t *pool);
+#endif /* !defined(WIN32) || defined(DOXYGEN) */
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c Wed Nov 27 07:53:29 2013
@@ -791,7 +791,7 @@ free_spare_group(svn_membuffer_t *cache,
 {
   assert(group->header.used == 0);
   assert(group->header.previous != NO_INDEX);
-  assert(group - cache->directory >= cache->group_count);
+  assert(group - cache->directory >= (apr_ssize_t)cache->group_count);
 
   /* unchain */
   cache->directory[group->header.previous].header.next = NO_INDEX;
@@ -1817,6 +1817,39 @@ entry_exists(svn_membuffer_t *cache,
   return SVN_NO_ERROR;
 }
 
+/* Given the SIZE and PRIORITY of a new item, return the cache level
+   (L1 or L2) in fragment CACHE that this item shall be inserted into.
+   If we can't find nor make enough room for the item, return NULL.
+ */
+static cache_level_t *
+select_level(svn_membuffer_t *cache,
+             apr_size_t size,
+             apr_uint32_t priority)
+{
+  if (cache->max_entry_size >= size)
+    {
+      /* Small items go into L1. */
+      return ensure_data_insertable_l1(cache, size)
+           ? &cache->l1
+           : NULL;
+    }
+  else if (   cache->l2.size >= size
+           && MAX_ITEM_SIZE >= size
+           && priority >= SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY)
+    {
+      /* Large and somewhat important items go into L2. */
+      entry_t dummy_entry = { { 0 } };
+      dummy_entry.priority = priority;
+      dummy_entry.size = size;
+
+      return ensure_data_insertable_l2(cache, &dummy_entry)
+           ? &cache->l2
+           : NULL;
+    }
+
+  /* Don't cache large, unimportant items. */
+  return NULL;
+}
 
 /* Try to insert the serialized item given in BUFFER with SIZE into
  * the group GROUP_INDEX of CACHE and uniquely identify it by hash
@@ -1840,6 +1873,8 @@ membuffer_cache_set_internal(svn_membuff
                              DEBUG_CACHE_MEMBUFFER_TAG_ARG
                              apr_pool_t *scratch_pool)
 {
+  cache_level_t *level;
+
   /* first, look for a previous entry for the given key */
   entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
 
@@ -1869,9 +1904,8 @@ membuffer_cache_set_internal(svn_membuff
 
   /* if necessary, enlarge the insertion window.
    */
-  if (   buffer != NULL
-      && cache->max_entry_size >= size
-      && ensure_data_insertable_l1(cache, size))
+  level = buffer ? select_level(cache, size, priority) : NULL;
+  if (level)
     {
       /* Remove old data for this key, if that exists.
        * Get an unused entry for the key and and initialize it with
@@ -1879,7 +1913,7 @@ membuffer_cache_set_internal(svn_membuff
        */
       entry = find_entry(cache, group_index, to_find, TRUE);
       entry->size = size;
-      entry->offset = cache->l1.current_data;
+      entry->offset = level->current_data;
       entry->priority = priority;
 
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -2371,7 +2405,7 @@ typedef struct last_access_key_t
   entry_key_t combined_key;
 
   /* length of the key (or APR_HASH_KEY_STRING if not used) */
-  apr_size_t key_len;
+  apr_ssize_t key_len;
 
   /* the original key.  Only KEY_LEN bytes are valid.  We use uint32 for
    * better compatibility with pseudo-md5 functions. */
@@ -2774,7 +2808,9 @@ svn_membuffer_cache_is_cachable(void *ca
    * must be small enough to be stored in a 32 bit value.
    */
   svn_membuffer_cache_t *cache = cache_void;
-  return size <= cache->membuffer->max_entry_size;
+  return cache->priority >= SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY
+       ? cache->membuffer->l2.size >= size && MAX_ITEM_SIZE >= size
+       : size <= cache->membuffer->max_entry_size;
 }
 
 /* Add statistics of SEGMENT to INFO.  If INCLUDE_HISTOGRAM is TRUE,

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cmdline.c Wed Nov 27 07:53:29 2013
@@ -757,12 +757,12 @@ svn_cmdline__print_xml_prop(svn_stringbu
       outstr, pool, svn_xml_protect_pcdata,
       inherited_prop ? "inherited_property" : "property",
       "name", propname,
-      "encoding", encoding, NULL);
+      "encoding", encoding, SVN_VA_NULL);
   else
     svn_xml_make_open_tag(
       outstr, pool, svn_xml_protect_pcdata,
       inherited_prop ? "inherited_property" : "property",
-      "name", propname, NULL);
+      "name", propname, SVN_VA_NULL);
 
   svn_stringbuf_appendcstr(*outstr, xml_safe);
 
@@ -988,7 +988,7 @@ svn_cmdline__print_xml_prop_hash(svn_str
           svn_xml_make_open_tag(
             outstr, pool, svn_xml_self_closing,
             inherited_props ? "inherited_property" : "property",
-            "name", pname, NULL);
+            "name", pname, SVN_VA_NULL);
         }
       else
         {

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config.c Wed Nov 27 07:53:29 2013
@@ -421,6 +421,26 @@ make_hash_key(char *key)
   return key;
 }
 
+/* Return the value for KEY in HASH.  If CASE_SENSITIVE is FALSE,
+   BUFFER will be used to construct the normalized hash key. */
+static void *
+get_hash_value(apr_hash_t *hash,
+               svn_stringbuf_t *buffer,
+               const char *key,
+               svn_boolean_t case_sensitive)
+{
+  apr_size_t i;
+  apr_size_t len = strlen(key);
+
+  if (case_sensitive)
+    return apr_hash_get(hash, key, len);
+
+  svn_stringbuf_ensure(buffer, len);
+  for (i = 0; i < len; ++i)
+    buffer->data[i] = (char)apr_tolower(key[i]);
+
+  return apr_hash_get(hash, buffer->data, len);
+}
 
 /* Return a pointer to an option in CFG, or NULL if it doesn't exist.
    if SECTIONP is non-null, return a pointer to the option's section.
@@ -429,30 +449,16 @@ static cfg_option_t *
 find_option(svn_config_t *cfg, const char *section, const char *option,
             cfg_section_t **sectionp)
 {
-  void *sec_ptr;
-
-  /* Canonicalize the hash key */
-  svn_stringbuf_set(cfg->tmp_key, section);
-  if (! cfg->section_names_case_sensitive)
-    make_hash_key(cfg->tmp_key->data);
-
-  sec_ptr = apr_hash_get(cfg->sections, cfg->tmp_key->data,
-                         cfg->tmp_key->len);
+  void *sec_ptr = get_hash_value(cfg->sections, cfg->tmp_key, section,
+                                 cfg->section_names_case_sensitive);
   if (sectionp != NULL)
     *sectionp = sec_ptr;
 
   if (sec_ptr != NULL && option != NULL)
     {
       cfg_section_t *sec = sec_ptr;
-      cfg_option_t *opt;
-
-      /* Canonicalize the option key */
-      svn_stringbuf_set(cfg->tmp_key, option);
-      if (! cfg->option_names_case_sensitive)
-        make_hash_key(cfg->tmp_key->data);
-
-      opt = apr_hash_get(sec->options, cfg->tmp_key->data,
-                         cfg->tmp_key->len);
+      cfg_option_t *opt = get_hash_value(sec->options, cfg->tmp_key, option,
+                                         cfg->option_names_case_sensitive);
       /* NOTE: ConfigParser's sections are case sensitive. */
       if (opt == NULL
           && apr_strnatcasecmp(section, SVN_CONFIG__DEFAULT_SECTION) != 0)
@@ -697,11 +703,11 @@ svn_config_get(svn_config_t *cfg, const 
         }
       else
         /* before attempting to expand an option, check for the placeholder.
-         * If none is there, there is no point in calling expand_option_value.
+         * If there is none, there is no point in calling expand_option_value.
          */
         if (default_value && strchr(default_value, '%'))
           {
-            apr_pool_t *tmp_pool = svn_pool_create(cfg->x_pool);
+            apr_pool_t *tmp_pool = svn_pool_create(cfg->pool);
             const char *x_default;
             expand_option_value(cfg, sec, default_value, &x_default, tmp_pool);
             if (x_default)
@@ -979,7 +985,7 @@ svn_config_enumerate(svn_config_t *cfg, 
   if (sec == NULL)
     return 0;
 
-  subpool = svn_pool_create(cfg->x_pool);
+  subpool = svn_pool_create(cfg->pool);
   count = 0;
   for (opt_ndx = apr_hash_first(subpool, sec->options);
        opt_ndx != NULL;
@@ -1246,13 +1252,6 @@ svn_config_get_server_setting_bool(svn_c
 svn_boolean_t
 svn_config_has_section(svn_config_t *cfg, const char *section)
 {
-  cfg_section_t *sec;
-
-  /* Canonicalize the hash key */
-  svn_stringbuf_set(cfg->tmp_key, section);
-  if (! cfg->section_names_case_sensitive)
-    make_hash_key(cfg->tmp_key->data);
-
-  sec = svn_hash_gets(cfg->sections, cfg->tmp_key->data);
-  return sec != NULL;
+  return NULL != get_hash_value(cfg->sections, cfg->tmp_key, section,
+                                cfg->section_names_case_sensitive);
 }

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c Wed Nov 27 07:53:29 2013
@@ -30,6 +30,7 @@
 #include "svn_types.h"
 #include "svn_dirent_uri.h"
 #include "svn_auth.h"
+#include "svn_hash.h"
 #include "svn_subst.h"
 #include "svn_utf.h"
 #include "svn_pools.h"
@@ -184,7 +185,25 @@ skip_to_eoln(parse_context_t *ctx, int *
 
   SVN_ERR(parser_getc(ctx, &ch));
   while (ch != '\n' && ch != EOF)
-    SVN_ERR(parser_getc_plain(ctx, &ch));
+    {
+      /* This is much faster than checking individual bytes.
+       * We use this function a lot when skipping comment lines.
+       *
+       * This assumes that the ungetc buffer is empty, but that is a
+       * safe assumption right after reading a character (which would
+       * clear the buffer. */
+      const char *newline = memchr(ctx->parser_buffer + ctx->buffer_pos, '\n',
+                                   ctx->buffer_size - ctx->buffer_pos);
+      if (newline)
+        {
+          ch = '\n';
+          ctx->buffer_pos = newline - ctx->parser_buffer + 1;
+          break;
+        }
+
+      /* refill buffer, check for EOF */
+      SVN_ERR(parser_getc_plain(ctx, &ch));
+    }
 
   *c = ch;
   return SVN_NO_ERROR;
@@ -469,6 +488,38 @@ svn_config__is_read_only(svn_config_t *c
   return cfg->read_only;
 }
 
+svn_config_t *
+svn_config__shallow_copy(svn_config_t *src,
+                         apr_pool_t *pool)
+{
+  svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));
+
+  cfg->sections = src->sections;
+  cfg->pool = pool;
+
+  /* r/o configs are fully expanded and don't need the x_pool anymore */
+  cfg->x_pool = src->read_only ? NULL : svn_pool_create(pool);
+  cfg->x_values = src->x_values;
+  cfg->tmp_key = svn_stringbuf_create_empty(pool);
+  cfg->tmp_value = svn_stringbuf_create_empty(pool);
+  cfg->section_names_case_sensitive = src->section_names_case_sensitive;
+  cfg->option_names_case_sensitive = src->option_names_case_sensitive;
+  cfg->read_only = src->read_only;
+
+  return cfg;
+}
+
+void
+svn_config__shallow_replace_section(svn_config_t *target,
+                                    svn_config_t *source,
+                                    const char *section)
+{
+  if (target->read_only)
+    target->sections = apr_hash_copy(target->pool, target->sections);
+
+  svn_hash_sets(target->sections, section,
+                svn_hash_gets(source->sections, section));
+}
 
 
 svn_error_t *

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h Wed Nov 27 07:53:29 2013
@@ -47,7 +47,8 @@ struct svn_config_t
   /* Table of cfg_section_t's. */
   apr_hash_t *sections;
 
-  /* Pool for hash tables, table entries and unexpanded values */
+  /* Pool for hash tables, table entries and unexpanded values.
+     Also, parent pool for temporary pools. */
   apr_pool_t *pool;
 
   /* Pool for expanded values -- this is separate, so that we can

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/deprecated.c Wed Nov 27 07:53:29 2013
@@ -44,8 +44,10 @@
 #include "svn_mergeinfo.h"
 #include "svn_utf.h"
 #include "svn_xml.h"
+#include "svn_auth.h"
 
 #include "opt.h"
+#include "auth.h"
 #include "private/svn_opt_private.h"
 #include "private/svn_mergeinfo_private.h"
 
@@ -1321,3 +1323,54 @@ svn_ver_check_list(const svn_version_t *
   return svn_ver_check_list2(my_version, checklist, svn_ver_compatible);
 }
 
+/*** From win32_crypto.c ***/
+#if defined(WIN32) && !defined(__MINGW32__)
+void
+svn_auth_get_windows_simple_provider(svn_auth_provider_object_t **provider,
+                                     apr_pool_t *pool)
+{
+  svn_auth__get_windows_simple_provider(provider, pool);
+}
+
+void
+svn_auth_get_windows_ssl_client_cert_pw_provider
+   (svn_auth_provider_object_t **provider,
+    apr_pool_t *pool)
+{
+  svn_auth__get_windows_ssl_client_cert_pw_provider(provider, pool);
+}
+
+void
+svn_auth_get_windows_ssl_server_trust_provider
+  (svn_auth_provider_object_t **provider, apr_pool_t *pool)
+{
+  svn_auth__get_windows_ssl_server_trust_provider(provider, pool);
+}
+#endif /* WIN32 && !__MINGW32__ */
+
+/*** From macos_keychain.c ***/
+#if defined(DARWIN)
+void
+svn_auth_get_keychain_simple_provider(svn_auth_provider_object_t **provider,
+                                      apr_pool_t *pool)
+{
+  svn_auth__get_keychain_simple_provider(provider, pool);
+}
+
+void
+svn_auth_get_keychain_ssl_client_cert_pw_provider
+  (svn_auth_provider_object_t **provider,
+   apr_pool_t *pool)
+{
+  svn_auth__get_keychain_ssl_client_cert_pw_provider(provider, pool);
+}
+#endif /* DARWIN */
+
+#if !defined(WIN32)
+void
+svn_auth_get_gpg_agent_simple_provider(svn_auth_provider_object_t **provider,
+                                       apr_pool_t *pool)
+{
+  svn_auth__get_gpg_agent_simple_provider(provider, pool);
+}
+#endif /* !WIN32 */

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/dirent_uri.c Wed Nov 27 07:53:29 2013
@@ -1293,6 +1293,29 @@ svn_relpath_split(const char **dirpath,
     *base_name = svn_relpath_basename(relpath, pool);
 }
 
+const char *
+svn_relpath_limit(const char *relpath,
+                  int max_components,
+                  apr_pool_t *result_pool)
+{
+  const char *end;
+  assert(relpath_is_canonical(relpath));
+
+  if (max_components <= 0)
+    return "";
+
+  for (end = relpath; *end; end++)
+    {
+      if (*end == '/')
+        {
+          if (!--max_components)
+            break;
+        }
+    }
+
+  return apr_pstrmemdup(result_pool, relpath, end-relpath);
+}
+
 char *
 svn_uri_dirname(const char *uri, apr_pool_t *pool)
 {

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/error.c Wed Nov 27 07:53:29 2013
@@ -699,7 +699,7 @@ svn_error_symbolic_name(apr_status_t sta
       return defn->errname;
 
   /* "No error" is not in error_table. */
-  if (statcode == SVN_NO_ERROR)
+  if (statcode == APR_SUCCESS)
     return "SVN_NO_ERROR";
 
 #ifdef SVN_DEBUG

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/gpg_agent.c Wed Nov 27 07:53:29 2013
@@ -73,6 +73,7 @@
 #include "svn_checksum.h"
 #include "svn_string.h"
 
+#include "auth.h"
 #include "private/svn_auth_private.h"
 
 #include "svn_private_config.h"
@@ -475,7 +476,7 @@ static const svn_auth_provider_t gpg_age
 
 /* Public API */
 void
-svn_auth_get_gpg_agent_simple_provider(svn_auth_provider_object_t **provider,
+svn_auth__get_gpg_agent_simple_provider(svn_auth_provider_object_t **provider,
                                        apr_pool_t *pool)
 {
   svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c Wed Nov 27 07:53:29 2013
@@ -1591,14 +1591,9 @@ io_set_file_perms(const char *path,
     {
       if (enable_write) /* Make read-write. */
         {
-          apr_file_t *fd;
-
-          /* Get the perms for the original file so we'll have any other bits
-           * that were already set (like the execute bits, for example). */
-          SVN_ERR(svn_io_file_open(&fd, path, APR_READ,
-                                   APR_OS_DEFAULT, pool));
-          SVN_ERR(merge_default_file_perms(fd, &perms_to_set, pool));
-          SVN_ERR(svn_io_file_close(fd, pool));
+          /* Tweak the owner bits only. The group/other bits aren't safe to
+           * touch because we may end up setting them in undesired ways. */
+          perms_to_set |= (APR_UREAD|APR_UWRITE);
         }
       else
         {
@@ -2312,12 +2307,11 @@ stringbuf_from_aprfile(svn_stringbuf_t *
      efficient memory handling, we'll try to do so. */
   if (check_size)
     {
-      apr_finfo_t finfo;
+      apr_finfo_t finfo = { 0 };
 
       /* In some cases we get size 0 and no error for non files,
           so we also check for the name. (= cached in apr_file_t) */
-      if (! apr_file_info_get(&finfo, APR_FINFO_SIZE | APR_FINFO_NAME, file)
-          && finfo.name != NULL)
+      if (! apr_file_info_get(&finfo, APR_FINFO_SIZE, file) && finfo.fname)
         {
           /* we've got the file length. Now, read it in one go. */
           svn_boolean_t eof;
@@ -3787,15 +3781,21 @@ svn_io_write_atomic(const char *final_pa
   if (!err && copy_perms_path)
     err = svn_io_copy_perms(copy_perms_path, tmp_path, scratch_pool);
 
+  if (!err)
+    err = svn_io_file_rename(tmp_path, final_path, scratch_pool);
+
   if (err)
     {
-      return svn_error_compose_create(err,
-                                      svn_io_remove_file2(tmp_path, FALSE,
-                                                          scratch_pool));
+      err = svn_error_compose_create(err,
+                                     svn_io_remove_file2(tmp_path, TRUE,
+                                                         scratch_pool));
+
+      return svn_error_createf(err->apr_err, err,
+                               _("Can't write '%s' atomicly"),
+                               svn_dirent_local_style(final_path,
+                                                      scratch_pool));
     }
 
-  SVN_ERR(svn_io_file_rename(tmp_path, final_path, scratch_pool));
-
 #ifdef __linux__
   {
     /* Linux has the unusual feature that fsync() on a file is not

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/iter.c Wed Nov 27 07:53:29 2013
@@ -193,24 +193,36 @@ svn_iter__break(void)
 
 const void *svn__apr_hash_index_key(const apr_hash_index_t *hi)
 {
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+  return apr_hash_this_key((apr_hash_index_t *)hi);
+#else
   const void *key;
 
   apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL);
   return key;
+#endif
 }
 
 apr_ssize_t svn__apr_hash_index_klen(const apr_hash_index_t *hi)
 {
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+  return apr_hash_this_key_len((apr_hash_index_t *)hi);
+#else
   apr_ssize_t klen;
 
   apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL);
   return klen;
+#endif
 }
 
 void *svn__apr_hash_index_val(const apr_hash_index_t *hi)
 {
+#if APR_VERSION_AT_LEAST(1, 5, 0)
+  return apr_hash_this_val((apr_hash_index_t *)hi);
+#else
   void *val;
 
   apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val);
   return val;
+#endif
 }

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/macos_keychain.c Wed Nov 27 07:53:29 2013
@@ -32,6 +32,7 @@
 #include "svn_config.h"
 #include "svn_user.h"
 
+#include "auth.h"
 #include "private/svn_auth_private.h"
 
 #include "svn_private_config.h"
@@ -241,7 +242,7 @@ static const svn_auth_provider_t keychai
 
 /* Public API */
 void
-svn_auth_get_keychain_simple_provider(svn_auth_provider_object_t **provider,
+svn_auth__get_keychain_simple_provider(svn_auth_provider_object_t **provider,
                                       apr_pool_t *pool)
 {
   svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
@@ -251,7 +252,7 @@ svn_auth_get_keychain_simple_provider(sv
 }
 
 void
-svn_auth_get_keychain_ssl_client_cert_pw_provider
+svn_auth__get_keychain_ssl_client_cert_pw_provider
   (svn_auth_provider_object_t **provider,
    apr_pool_t *pool)
 {

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/packed_data.c Wed Nov 27 07:53:29 2013
@@ -849,7 +849,7 @@ svn_packed__get_bytes(svn_packed__byte_s
                       apr_size_t *len)
 {
   const char *result = stream->packed->data;
-  apr_size_t count = svn_packed__get_uint(stream->lengths_stream);
+  apr_size_t count = (apr_size_t)svn_packed__get_uint(stream->lengths_stream);
 
   if (count > stream->packed->len)
     count = stream->packed->len;
@@ -1011,8 +1011,8 @@ svn_packed__data_read(svn_packed__data_r
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
 {
-  apr_size_t i;
-  apr_size_t count;
+  apr_uint64_t i;
+  apr_uint64_t count;
   
   svn_packed__int_stream_t *int_stream;
   svn_packed__byte_stream_t *byte_stream;

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/prefix_string.c Wed Nov 27 07:53:29 2013
@@ -184,7 +184,7 @@ svn_prefix_string__create(svn_prefix_tre
           : 0;
 
       /* any (partially) matching sub-nodes? */
-      if (idx == node->sub_node_count
+      if (idx == (int)node->sub_node_count
           || node->sub_nodes[idx]->key.data[0] != s[node->length])
         break;
 

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/sorts.c Wed Nov 27 07:53:29 2013
@@ -333,8 +333,9 @@ heap_is_less(svn_priority_queue__t *queu
   char *lhs_value = queue->elements->elts + lhs * queue->elements->elt_size;
   char *rhs_value = queue->elements->elts + rhs * queue->elements->elt_size;
 
-  assert(lhs < queue->elements->nelts);
-  assert(rhs < queue->elements->nelts);
+  /* nelts is never negative */
+  assert(lhs < (apr_size_t)queue->elements->nelts);
+  assert(rhs < (apr_size_t)queue->elements->nelts);
   return queue->compare_func((void *)lhs_value, (void *)rhs_value) < 0;
 }
 

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/sysinfo.c Wed Nov 27 07:53:29 2013
@@ -270,7 +270,7 @@ release_name_from_uname(apr_pool_t *pool
 
 #if __linux__
 /* Split a stringbuf into a key/value pair.
-   Return the key, leaving the striped value in the stringbuf. */
+   Return the key, leaving the stripped value in the stringbuf. */
 static const char *
 stringbuf_split_key(svn_stringbuf_t *buffer, char delim)
 {
@@ -282,11 +282,21 @@ stringbuf_split_key(svn_stringbuf_t *buf
     return NULL;
 
   svn_stringbuf_strip_whitespace(buffer);
+
+  /* Now we split the currently allocated buffer in two parts:
+      - a const char * HEAD
+      - the remaining stringbuf_t. */
+
+  /* Create HEAD as '\0' terminated const char * */
   key = buffer->data;
   end = strchr(key, delim);
   *end = '\0';
-  buffer->len = 1 + end - key;
+
+  /* And update the TAIL to be a smaller, but still valid stringbuf */
   buffer->data = end + 1;
+  buffer->len -= 1 + end - key;
+  buffer->blocksize -= 1 + end - key;
+
   svn_stringbuf_strip_whitespace(buffer);
 
   return key;

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc.c Wed Nov 27 07:53:29 2013
@@ -155,7 +155,6 @@ ucs4cmp(const apr_int32_t *bufa, apr_siz
   return (lena == lenb ? 0 : (lena < lenb ? -1 : 1));
 }
 
-
 svn_error_t *
 svn_utf__normcmp(int *result,
                  const char *str1, apr_size_t len1,
@@ -182,6 +181,16 @@ svn_utf__normcmp(int *result,
   return SVN_NO_ERROR;
 }
 
+svn_error_t*
+svn_utf__normalize(const char **result,
+                   const char *str, apr_size_t len,
+                   svn_membuf_t *buf)
+{
+  apr_size_t result_length;
+  SVN_ERR(normalize_cstring(&result_length, str, len, buf));
+  *result = (const char*)(buf->data);
+  return SVN_NO_ERROR;
+}
 
 /* Decode a single UCS-4 code point to UTF-8, appending the result to BUFFER.
  * Assume BUFFER is already filled to *LENGTH and return the new size there.
@@ -424,7 +433,7 @@ svn_utf__fuzzy_escape(const char *src, a
               len = utf8proc_utf8class[(uint8_t)*p];
 
               /* Check if the multi-byte sequence is valid UTF-8. */
-              if (len > 1 && len <= length - done)
+              if (len > 1 && len <= (apr_ssize_t)(length - done))
                 last = svn_utf__last_valid(p, len);
               else
                 last = NULL;

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf8proc/utf8proc.c Wed Nov 27 07:53:29 2013
@@ -182,10 +182,10 @@ ssize_t utf8proc_encode_char(int32_t uc,
   if (uc < 0x00) {
     return 0;
   } else if (uc < 0x80) {
-    dst[0] = uc;
+    dst[0] = (uint8_t)uc;
     return 1;
   } else if (uc < 0x800) {
-    dst[0] = 0xC0 + (uc >> 6);
+    dst[0] = 0xC0 + (uint8_t)(uc >> 6);
     dst[1] = 0x80 + (uc & 0x3F);
     return 2;
   } else if (uc == 0xFFFF) {
@@ -195,12 +195,12 @@ ssize_t utf8proc_encode_char(int32_t uc,
     dst[0] = 0xFE;
     return 1;
   } else if (uc < 0x10000) {
-    dst[0] = 0xE0 + (uc >> 12);
+    dst[0] = 0xE0 + (uint8_t)(uc >> 12);
     dst[1] = 0x80 + ((uc >> 6) & 0x3F);
     dst[2] = 0x80 + (uc & 0x3F);
     return 3;
   } else if (uc < 0x110000) {
-    dst[0] = 0xF0 + (uc >> 18);
+    dst[0] = 0xF0 + (uint8_t)(uc >> 18);
     dst[1] = 0x80 + ((uc >> 12) & 0x3F);
     dst[2] = 0x80 + ((uc >> 6) & 0x3F);
     dst[3] = 0x80 + (uc & 0x3F);



Mime
View raw message