subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From i...@apache.org
Subject svn commit: r1686174 [10/18] - in /subversion/branches/reuse-ra-session: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ subversion/bindings/javahl/ subversion/bindings/javahl/native/ subversion/bindings/javahl/native/jniwrapper/...
Date Thu, 18 Jun 2015 10:35:33 GMT
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/cache-membuffer.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/cache-membuffer.c Thu Jun 18 10:35:30 2015
@@ -28,13 +28,16 @@
 #include "svn_pools.h"
 #include "svn_checksum.h"
 #include "svn_private_config.h"
-#include "cache.h"
 #include "svn_string.h"
 #include "svn_sorts.h"  /* get the MIN macro */
+
 #include "private/svn_atomic.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_mutex.h"
-#include "private/svn_pseudo_md5.h"
+#include "private/svn_string_private.h"
+
+#include "cache.h"
+#include "fnv1a.h"
 
 /*
  * This svn_cache__t implementation actually consists of two parts:
@@ -45,8 +48,9 @@
  * A membuffer cache consists of two parts:
  *
  * 1. A linear data buffer containing cached items in a serialized
- *    representation. There may be arbitrary gaps between entries.
- *    This buffer is sub-devided into (currently two) cache levels.
+ *    representation, prefixed by their full cache keys. There may be
+ *    arbitrary gaps between entries.  This buffer is sub-devided into
+ *    (currently two) cache levels.
  *
  * 2. A directory of cache entries. This is organized similar to CPU
  *    data caches: for every possible key, there is exactly one group
@@ -78,9 +82,10 @@
  * Insertion can occur at only one, sliding position per cache level.  It is
  * marked by its offset in the data buffer and the index of the first used
  * entry at or behind that position.  If this gap is too small to accommodate
- * the new item, the insertion window is extended as described below. The new
- * entry will always be inserted at the bottom end of the window and since
- * the next used entry is known, properly sorted insertion is possible.
+ * the new item (plus its full key), the insertion window is extended as
+ * described below.  The new entry will always be inserted at the bottom end
+ * of the window and since the next used entry is known, properly sorted
+ * insertion is possible.
  *
  * To make the cache perform robustly in a wide range of usage scenarios,
  * L2 uses a randomized variant of LFU (see ensure_data_insertable_l2 for
@@ -104,11 +109,13 @@
  * an already used group to extend it.
  *
  * To limit the entry size and management overhead, not the actual item keys
- * but only their MD5-based hashes will be stored. This is reasonably safe
- * to do since users have only limited control over the full keys, even if
- * these contain folder paths. So, it is very hard to deliberately construct
- * colliding keys. Random checksum collisions can be shown to be extremely
- * unlikely.
+ * but only their hashed "fingerprint" will be stored.  These are reasonably
+ * unique to prevent collisions, so we only need to support up to one entry
+ * per entry key.  To guarantee that there are no conflicts, however, we
+ * store the actual full key immediately in front of the serialized item
+ * data.  That is, the entry offset actually points to the full key and the
+ * key length stored in the entry acts as an additional offset to find the
+ * actual item.
  *
  * All access to the cached data needs to be serialized. Because we want
  * to scale well despite that bottleneck, we simply segment the cache into
@@ -178,17 +185,34 @@
  */
 #define MAX_ITEM_SIZE ((apr_uint32_t)(0 - ITEM_ALIGNMENT))
 
-/* A 16 byte key type. We use that to identify cache entries.
- * The notation as just two integer values will cause many compilers
- * to create better code.
+/* We use this structure to identify cache entries. There cannot be two
+ * entries with the same entry key. However unlikely, though, two different
+ * full keys (see full_key_t) may have the same entry key.  That is a
+ * collision and at most one of them can be stored in the cache at any time.
  */
-typedef apr_uint64_t entry_key_t[2];
+typedef struct entry_key_t
+{
+  /* 16 byte finger print of the full key. */
+  apr_uint64_t fingerprint[2];
 
-/* The prefix passed to svn_cache__create_membuffer_cache() effectively
- * defines the type of all items stored by that cache instance. We'll take
- * the last 15 bytes + \0 as plaintext for easy identification by the dev.
+  /* Length of the full key.  This value is aligned to ITEM_ALIGNMENT to
+   * make sure the subsequent item content is properly aligned. */
+  apr_size_t key_len;
+} entry_key_t;
+
+/* A full key, i.e. the combination of the cache's key prefix with some
+ * dynamic part appended to it.  It also contains its ENTRY_KEY.
  */
-#define PREFIX_TAIL_LEN 16
+typedef struct full_key_t
+{
+  /* Reduced form identifying the cache entry (if such an entry exists). */
+  entry_key_t entry_key;
+
+  /* This contains the full combination.  Note that the SIZE element may
+   * be larger than ENTRY_KEY.KEY_LEN, but only the latter determines the
+   * valid key size. */
+  svn_membuf_t full_key;
+} full_key_t;
 
 /* Debugging / corruption detection support.
  * If you define this macro, the getter functions will performed expensive
@@ -198,6 +222,12 @@ typedef apr_uint64_t entry_key_t[2];
  */
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
 
+/* The prefix passed to svn_cache__create_membuffer_cache() effectively
+ * defines the type of all items stored by that cache instance. We'll take
+ * the last 15 bytes + \0 as plaintext for easy identification by the dev.
+ */
+#define PREFIX_TAIL_LEN 16
+
 /* This record will be attached to any cache entry. It tracks item data
  * (content), key and type as hash values and is the baseline against which
  * the getters will compare their results to detect inconsistencies.
@@ -233,22 +263,33 @@ typedef struct entry_tag_t
 /* Initialize all members of TAG except for the content hash.
  */
 static svn_error_t *store_key_part(entry_tag_t *tag,
-                                   entry_key_t prefix_hash,
-                                   char *prefix_tail,
+                                   const full_key_t *prefix_key,
                                    const void *key,
                                    apr_size_t key_len,
                                    apr_pool_t *pool)
 {
   svn_checksum_t *checksum;
+  const char *prefix = prefix_key->full_key.data;
+  apr_size_t prefix_len = strlen(prefix);
+
+  if (prefix_len > sizeof(tag->prefix_tail))
+    {
+      prefix += prefix_len - (sizeof(tag->prefix_tail) - 1);
+      prefix_len = sizeof(tag->prefix_tail) - 1;
+    }
+
   SVN_ERR(svn_checksum(&checksum,
                        svn_checksum_md5,
                        key,
                        key_len,
                        pool));
 
-  memcpy(tag->prefix_hash, prefix_hash, sizeof(tag->prefix_hash));
+  memcpy(tag->prefix_hash, prefix_key->entry_key.fingerprint,
+         sizeof(tag->prefix_hash));
   memcpy(tag->key_hash, checksum->digest, sizeof(tag->key_hash));
-  memcpy(tag->prefix_tail, prefix_tail, sizeof(tag->prefix_tail));
+
+  memset(tag->prefix_tail, 0, sizeof(tag->key_hash));
+  memcpy(tag->prefix_tail, prefix, prefix_len + 1);
 
   tag->key_len = key_len;
 
@@ -258,7 +299,7 @@ static svn_error_t *store_key_part(entry
 /* Initialize the content hash member of TAG.
  */
 static svn_error_t* store_content_part(entry_tag_t *tag,
-                                       const char *data,
+                                       const void *data,
                                        apr_size_t size,
                                        apr_pool_t *pool)
 {
@@ -305,8 +346,7 @@ static svn_error_t* assert_equal_tags(co
   entry_tag_t *tag = &_tag;                                      \
   if (key)                                                       \
     SVN_ERR(store_key_part(tag,                                  \
-                           cache->prefix,                        \
-                           cache->info_prefix,                   \
+                           &cache->prefix,                       \
                            key,                                  \
                            cache->key_len == APR_HASH_KEY_STRING \
                                ? strlen((const char *) key)      \
@@ -323,23 +363,6 @@ static svn_error_t* assert_equal_tags(co
 
 #endif /* SVN_DEBUG_CACHE_MEMBUFFER */
 
-/* Per svn_cache_t instance initialization helper.
- * Copy the last to up PREFIX_TAIL_LEN-1 chars from PREFIX to PREFIX_TAIL.
- * If the prefix has been structured by ':', only store the last element
- * (which will tell us the type).
- */
-static void get_prefix_tail(const char *prefix, char *prefix_tail)
-{
-  apr_size_t len = strlen(prefix);
-  apr_size_t to_copy = MIN(len, PREFIX_TAIL_LEN - 1);
-  const char *last_colon = strrchr(prefix, ':');
-  apr_size_t last_element_pos = last_colon ? 0 : last_colon - prefix + 1;
-
-  to_copy = MIN(to_copy, len - last_element_pos);
-  memset(prefix_tail, 0, PREFIX_TAIL_LEN);
-  memcpy(prefix_tail, prefix + len - to_copy, to_copy);
-}
-
 /* A single dictionary entry. Since all entries will be allocated once
  * during cache creation, those entries might be either used or unused.
  * An entry is used if and only if it is contained in the doubly-linked
@@ -360,7 +383,7 @@ typedef struct entry_t
    * above ensures that there will be no overflows.
    * Only valid for used entries.
    */
-  apr_uint32_t size;
+  apr_size_t size;
 
   /* Number of (read) hits for this entry. Will be reset upon write.
    * Only valid for used entries.
@@ -1122,17 +1145,19 @@ insert_entry(svn_membuffer_t *cache, ent
  */
 static apr_uint32_t
 get_group_index(svn_membuffer_t **cache,
-                entry_key_t key)
+                const entry_key_t *key)
 {
   svn_membuffer_t *segment0 = *cache;
+  apr_uint64_t key0 = key->fingerprint[0];
+  apr_uint64_t key1 = key->fingerprint[1];
 
   /* select the cache segment to use. they have all the same group_count.
    * Since key may not be well-distributed, pre-fold it to a smaller but
    * "denser" ranger.  The modulus is a prime larger than the largest
    * counts. */
-  *cache = &segment0[(key[1] % APR_UINT64_C(2809637) + (key[0] / 37))
+  *cache = &segment0[(key1 % APR_UINT64_C(2809637) + (key0 / 37))
                      & (segment0->segment_count - 1)];
-  return (key[0] % APR_UINT64_C(5030895599)) % segment0->group_count;
+  return (key0 % APR_UINT64_C(5030895599)) % segment0->group_count;
 }
 
 /* Reduce the hit count of ENTRY and update the accumulated hit info
@@ -1153,6 +1178,17 @@ let_entry_age(svn_membuffer_t *cache, en
     }
 }
 
+/* Return whether the keys in LHS and RHS match.
+ */
+static svn_boolean_t
+entry_keys_match(const entry_key_t *lhs,
+                 const entry_key_t *rhs)
+{
+  return (lhs->fingerprint[0] == rhs->fingerprint[0])
+      && (lhs->fingerprint[1] == rhs->fingerprint[1])
+      && (lhs->key_len == rhs->key_len);
+}
+
 /* Given the GROUP_INDEX that shall contain an entry with the hash key
  * TO_FIND, find that entry in the specified group.
  *
@@ -1164,11 +1200,15 @@ let_entry_age(svn_membuffer_t *cache, en
  * new content), an unused entry or a forcibly removed entry (if all
  * group entries are currently in use). The entries' hash value will be
  * initialized with TO_FIND.
+ *
+ * Note: This function requires the caller to appropriately lock the CACHE.
+ * For FIND_EMPTY==FALSE, a read lock is required, for FIND_EMPTY==TRUE,
+ * the write lock must have been acquired.
  */
 static entry_t *
 find_entry(svn_membuffer_t *cache,
            apr_uint32_t group_index,
-           const apr_uint64_t to_find[2],
+           const full_key_t *to_find,
            svn_boolean_t find_empty)
 {
   entry_group_t *group;
@@ -1189,8 +1229,7 @@ find_entry(svn_membuffer_t *cache,
           entry = &group->entries[0];
 
           /* initialize entry for the new key */
-          entry->key[0] = to_find[0];
-          entry->key[1] = to_find[1];
+          entry->key = to_find->entry_key;
         }
 
       return entry;
@@ -1201,14 +1240,28 @@ find_entry(svn_membuffer_t *cache,
   while (1)
     {
       for (i = 0; i < group->header.used; ++i)
-        if (   to_find[0] == group->entries[i].key[0]
-            && to_find[1] == group->entries[i].key[1])
+        if (entry_keys_match(&group->entries[i].key, &to_find->entry_key))
           {
-            /* found it
-             */
+            /* This is the only entry that _may_ contain the correct data. */
             entry = &group->entries[i];
+
+            /* If we want to preserve it, check that it is actual a match. */
             if (!find_empty)
-              return entry;
+              {
+                /* If there is no full key to compare, we are done. */
+                if (!entry->key.key_len)
+                  return entry;
+
+                /* Compare the full key. */
+                if (memcmp(to_find->full_key.data,
+                           cache->data + entry->offset,
+                           entry->key.key_len) == 0)
+                  return entry;
+
+                /* Key conflict. The entry to find cannot be anywhere else.
+                 * Therefore, it is not cached. */
+                return NULL;
+              }
 
             /* need to empty that entry */
             drop_entry(cache, entry);
@@ -1218,6 +1271,8 @@ find_entry(svn_membuffer_t *cache,
               group = last_group_in_chain(cache,
                                           &cache->directory[group_index]);
 
+            /* No entry found (actually, none left to find). */
+            entry = NULL;
             break;
           }
 
@@ -1300,8 +1355,7 @@ find_entry(svn_membuffer_t *cache,
       /* initialize entry for the new key
        */
       entry = &group->entries[group->header.used];
-      entry->key[0] = to_find[0];
-      entry->key[1] = to_find[1];
+      entry->key = to_find->entry_key;
     }
 
   return entry;
@@ -1883,7 +1937,7 @@ svn_cache__membuffer_clear(svn_membuffer
 static svn_error_t *
 entry_exists_internal(svn_membuffer_t *cache,
                       apr_uint32_t group_index,
-                      entry_key_t to_find,
+                      const full_key_t *to_find,
                       svn_boolean_t *found)
 {
   *found = find_entry(cache, group_index, to_find, FALSE) != NULL;
@@ -1896,7 +1950,7 @@ entry_exists_internal(svn_membuffer_t *c
 static svn_error_t *
 entry_exists(svn_membuffer_t *cache,
              apr_uint32_t group_index,
-             entry_key_t to_find,
+             const full_key_t *to_find,
              svn_boolean_t *found)
 {
   WITH_READ_LOCK(cache,
@@ -1929,9 +1983,9 @@ select_level(svn_membuffer_t *cache,
            && priority > SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY)
     {
       /* Large but important items go into L2. */
-      entry_t dummy_entry = { { 0 } };
+      entry_t dummy_entry = { { { 0 } } };
       dummy_entry.priority = priority;
-      dummy_entry.size = (apr_uint32_t) size;
+      dummy_entry.size = size;
 
       return ensure_data_insertable_l2(cache, &dummy_entry)
            ? &cache->l2
@@ -1942,9 +1996,9 @@ select_level(svn_membuffer_t *cache,
   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
- * value TO_FIND.
+/* Try to insert the serialized item given in BUFFER with ITEM_SIZE
+ * into the group GROUP_INDEX of CACHE and uniquely identify it by
+ * hash value TO_FIND.
  *
  * However, there is no guarantee that it will actually be put into
  * the cache. If there is already some data associated with TO_FIND,
@@ -1952,19 +2006,20 @@ select_level(svn_membuffer_t *cache,
  * be inserted.
  *
  * Note: This function requires the caller to serialization access.
- * Don't call it directly, call membuffer_cache_get_partial instead.
+ * Don't call it directly, call membuffer_cache_set instead.
  */
 static svn_error_t *
 membuffer_cache_set_internal(svn_membuffer_t *cache,
-                             entry_key_t to_find,
+                             const full_key_t *to_find,
                              apr_uint32_t group_index,
                              char *buffer,
-                             apr_size_t size,
+                             apr_size_t item_size,
                              apr_uint32_t priority,
                              DEBUG_CACHE_MEMBUFFER_TAG_ARG
                              apr_pool_t *scratch_pool)
 {
   cache_level_t *level;
+  apr_size_t size = item_size + to_find->entry_key.key_len;
 
   /* first, look for a previous entry for the given key */
   entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
@@ -1978,20 +2033,24 @@ membuffer_cache_set_internal(svn_membuff
        * negative value.
        */
       cache->data_used += (apr_uint64_t)size - entry->size;
-      entry->size = (apr_uint32_t) size;
+      entry->size = size;
       entry->priority = priority;
 
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
 
       /* Remember original content, type and key (hashes)
        */
-      SVN_ERR(store_content_part(tag, buffer, size, scratch_pool));
+      SVN_ERR(store_content_part(tag, buffer, item_size, scratch_pool));
       memcpy(&entry->tag, tag, sizeof(*tag));
 
 #endif
 
-      if (size)
-        memcpy(cache->data + entry->offset, buffer, size);
+      if (entry->key.key_len)
+        memcpy(cache->data + entry->offset, to_find->full_key.data,
+               entry->key.key_len);
+      if (item_size)
+        memcpy(cache->data + entry->offset + entry->key.key_len, buffer,
+               item_size);
 
       cache->total_writes++;
       return SVN_NO_ERROR;
@@ -2007,7 +2066,7 @@ membuffer_cache_set_internal(svn_membuff
        * the serialized item's (future) position within data buffer.
        */
       entry = find_entry(cache, group_index, to_find, TRUE);
-      entry->size = (apr_uint32_t) size;
+      entry->size = size;
       entry->offset = level->current_data;
       entry->priority = priority;
 
@@ -2015,7 +2074,7 @@ membuffer_cache_set_internal(svn_membuff
 
       /* Remember original content, type and key (hashes)
        */
-      SVN_ERR(store_content_part(tag, buffer, size, scratch_pool));
+      SVN_ERR(store_content_part(tag, buffer, item_size, scratch_pool));
       memcpy(&entry->tag, tag, sizeof(*tag));
 
 #endif
@@ -2026,8 +2085,12 @@ membuffer_cache_set_internal(svn_membuff
 
       /* Copy the serialized item data into the cache.
        */
-      if (size)
-        memcpy(cache->data + entry->offset, buffer, size);
+      if (entry->key.key_len)
+        memcpy(cache->data + entry->offset, to_find->full_key.data,
+               entry->key.key_len);
+      if (item_size)
+        memcpy(cache->data + entry->offset + entry->key.key_len, buffer,
+               item_size);
 
       cache->total_writes++;
     }
@@ -2056,7 +2119,7 @@ membuffer_cache_set_internal(svn_membuff
  */
 static svn_error_t *
 membuffer_cache_set(svn_membuffer_t *cache,
-                    entry_key_t key,
+                    const full_key_t *key,
                     void *item,
                     svn_cache__serialize_func_t serializer,
                     apr_uint32_t priority,
@@ -2069,7 +2132,7 @@ membuffer_cache_set(svn_membuffer_t *cac
 
   /* find the entry group that will hold the key.
    */
-  group_index = get_group_index(&cache, key);
+  group_index = get_group_index(&cache, &key->entry_key);
 
   /* Serialize data data.
    */
@@ -2112,12 +2175,12 @@ increment_hit_counters(svn_membuffer_t *
  * be done in POOL.
  *
  * Note: This function requires the caller to serialization access.
- * Don't call it directly, call membuffer_cache_get_partial instead.
+ * Don't call it directly, call membuffer_cache_get instead.
  */
 static svn_error_t *
 membuffer_cache_get_internal(svn_membuffer_t *cache,
                              apr_uint32_t group_index,
-                             entry_key_t to_find,
+                             const full_key_t *to_find,
                              char **buffer,
                              apr_size_t *item_size,
                              DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -2140,9 +2203,9 @@ membuffer_cache_get_internal(svn_membuff
       return SVN_NO_ERROR;
     }
 
-  size = ALIGN_VALUE(entry->size);
+  size = ALIGN_VALUE(entry->size) - entry->key.key_len;
   *buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
-  memcpy(*buffer, (const char*)cache->data + entry->offset, size);
+  memcpy(*buffer, cache->data + entry->offset + entry->key.key_len, size);
 
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
 
@@ -2154,7 +2217,8 @@ membuffer_cache_get_internal(svn_membuff
 
   /* Compare original content, type and key (hashes)
    */
-  SVN_ERR(store_content_part(tag, *buffer, entry->size, result_pool));
+  SVN_ERR(store_content_part(tag, *buffer, entry->size - entry->key.key_len,
+                             result_pool));
   SVN_ERR(assert_equal_tags(&entry->tag, tag));
 
 #endif
@@ -2162,7 +2226,7 @@ membuffer_cache_get_internal(svn_membuff
   /* update hit statistics
    */
   increment_hit_counters(cache, entry);
-  *item_size = entry->size;
+  *item_size = entry->size - entry->key.key_len;
 
   return SVN_NO_ERROR;
 }
@@ -2174,7 +2238,7 @@ membuffer_cache_get_internal(svn_membuff
  */
 static svn_error_t *
 membuffer_cache_get(svn_membuffer_t *cache,
-                    entry_key_t key,
+                    const full_key_t *key,
                     void **item,
                     svn_cache__deserialize_func_t deserializer,
                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -2186,7 +2250,7 @@ membuffer_cache_get(svn_membuffer_t *cac
 
   /* find the entry group that will hold the key.
    */
-  group_index = get_group_index(&cache, key);
+  group_index = get_group_index(&cache, &key->entry_key);
   WITH_READ_LOCK(cache,
                  membuffer_cache_get_internal(cache,
                                               group_index,
@@ -2214,7 +2278,7 @@ membuffer_cache_get(svn_membuffer_t *cac
 static svn_error_t *
 membuffer_cache_has_key_internal(svn_membuffer_t *cache,
                                  apr_uint32_t group_index,
-                                 entry_key_t to_find,
+                                 const full_key_t *to_find,
                                  svn_boolean_t *found)
 {
   entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
@@ -2243,12 +2307,12 @@ membuffer_cache_has_key_internal(svn_mem
  */
 static svn_error_t *
 membuffer_cache_has_key(svn_membuffer_t *cache,
-                        entry_key_t key,
+                        const full_key_t *key,
                         svn_boolean_t *found)
 {
   /* find the entry group that will hold the key.
    */
-  apr_uint32_t group_index = get_group_index(&cache, key);
+  apr_uint32_t group_index = get_group_index(&cache, &key->entry_key);
   cache->total_reads++;
 
   WITH_READ_LOCK(cache,
@@ -2274,7 +2338,7 @@ membuffer_cache_has_key(svn_membuffer_t
 static svn_error_t *
 membuffer_cache_get_partial_internal(svn_membuffer_t *cache,
                                      apr_uint32_t group_index,
-                                     entry_key_t to_find,
+                                     const full_key_t *to_find,
                                      void **item,
                                      svn_boolean_t *found,
                                      svn_cache__partial_getter_func_t deserializer,
@@ -2293,6 +2357,8 @@ membuffer_cache_get_partial_internal(svn
     }
   else
     {
+      const void *item_data = cache->data + entry->offset + entry->key.key_len;
+      apr_size_t item_size = entry->size - entry->key.key_len;
       *found = TRUE;
       increment_hit_counters(cache, entry);
 
@@ -2306,19 +2372,12 @@ membuffer_cache_get_partial_internal(svn
 
       /* Compare original content, type and key (hashes)
        */
-      SVN_ERR(store_content_part(tag,
-                                 (const char*)cache->data + entry->offset,
-                                 entry->size,
-                                 result_pool));
+      SVN_ERR(store_content_part(tag, item_data, item_size, result_pool));
       SVN_ERR(assert_equal_tags(&entry->tag, tag));
 
 #endif
 
-      return deserializer(item,
-                          (const char*)cache->data + entry->offset,
-                          entry->size,
-                          baton,
-                          result_pool);
+      return deserializer(item, item_data, item_size, baton, result_pool);
     }
 }
 
@@ -2330,7 +2389,7 @@ membuffer_cache_get_partial_internal(svn
  */
 static svn_error_t *
 membuffer_cache_get_partial(svn_membuffer_t *cache,
-                            entry_key_t key,
+                            const full_key_t *key,
                             void **item,
                             svn_boolean_t *found,
                             svn_cache__partial_getter_func_t deserializer,
@@ -2338,7 +2397,7 @@ membuffer_cache_get_partial(svn_membuffe
                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
                             apr_pool_t *result_pool)
 {
-  apr_uint32_t group_index = get_group_index(&cache, key);
+  apr_uint32_t group_index = get_group_index(&cache, &key->entry_key);
 
   WITH_READ_LOCK(cache,
                  membuffer_cache_get_partial_internal
@@ -2362,7 +2421,7 @@ membuffer_cache_get_partial(svn_membuffe
 static svn_error_t *
 membuffer_cache_set_partial_internal(svn_membuffer_t *cache,
                                      apr_uint32_t group_index,
-                                     entry_key_t to_find,
+                                     const full_key_t *to_find,
                                      svn_cache__partial_setter_func_t func,
                                      void *baton,
                                      DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -2380,9 +2439,10 @@ membuffer_cache_set_partial_internal(svn
       svn_error_t *err;
 
       /* access the serialized cache item */
-      char *data = (char*)cache->data + entry->offset;
-      char *orig_data = data;
-      apr_size_t size = entry->size;
+      apr_size_t key_len = entry->key.key_len;
+      void *item_data = cache->data + entry->offset + key_len;
+      void *orig_data = item_data;
+      apr_size_t item_size = entry->size - key_len;
 
       increment_hit_counters(cache, entry);
       cache->total_writes++;
@@ -2392,19 +2452,19 @@ membuffer_cache_set_partial_internal(svn
       /* Check for overlapping entries.
        */
       SVN_ERR_ASSERT(entry->next == NO_INDEX ||
-                     entry->offset + size
+                     entry->offset + entry->size
                         <= get_entry(cache, entry->next)->offset);
 
       /* Compare original content, type and key (hashes)
        */
-      SVN_ERR(store_content_part(tag, data, size, scratch_pool));
+      SVN_ERR(store_content_part(tag, item_data, item_size, scratch_pool));
       SVN_ERR(assert_equal_tags(&entry->tag, tag));
 
 #endif
 
       /* modify it, preferably in-situ.
        */
-      err = func((void **)&data, &size, baton, scratch_pool);
+      err = func(&item_data, &item_size, baton, scratch_pool);
 
       if (err)
         {
@@ -2421,21 +2481,26 @@ membuffer_cache_set_partial_internal(svn
           /* if the modification caused a re-allocation, we need to remove
            * the old entry and to copy the new data back into cache.
            */
-          if (data != orig_data)
+          if (item_data != orig_data)
             {
               /* Remove the old entry and try to make space for the new one.
                */
               drop_entry(cache, entry);
-              if (   (cache->max_entry_size >= size)
-                  && ensure_data_insertable_l1(cache, size))
+              if (   (cache->max_entry_size >= item_size + key_len)
+                  && ensure_data_insertable_l1(cache, item_size + key_len))
                 {
                   /* Write the new entry.
                    */
                   entry = find_entry(cache, group_index, to_find, TRUE);
-                  entry->size = (apr_uint32_t) size;
+                  entry->size = item_size + key_len;
                   entry->offset = cache->l1.current_data;
-                  if (size)
-                    memcpy(cache->data + entry->offset, data, size);
+
+                  if (key_len)
+                    memcpy(cache->data + entry->offset,
+                           to_find->full_key.data, key_len);
+                  if (item_size)
+                    memcpy(cache->data + entry->offset + key_len, item_data,
+                           item_size);
 
                   /* Link the entry properly.
                    */
@@ -2447,7 +2512,7 @@ membuffer_cache_set_partial_internal(svn
 
           /* Remember original content, type and key (hashes)
            */
-          SVN_ERR(store_content_part(tag, data, size, scratch_pool));
+          SVN_ERR(store_content_part(tag, item_data, item_size, scratch_pool));
           memcpy(&entry->tag, tag, sizeof(*tag));
 
 #endif
@@ -2464,7 +2529,7 @@ membuffer_cache_set_partial_internal(svn
  */
 static svn_error_t *
 membuffer_cache_set_partial(svn_membuffer_t *cache,
-                            entry_key_t key,
+                            const full_key_t *key,
                             svn_cache__partial_setter_func_t func,
                             void *baton,
                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
@@ -2472,7 +2537,7 @@ membuffer_cache_set_partial(svn_membuffe
 {
   /* cache item lookup
    */
-  apr_uint32_t group_index = get_group_index(&cache, key);
+  apr_uint32_t group_index = get_group_index(&cache, &key->entry_key);
   WITH_WRITE_LOCK(cache,
                   membuffer_cache_set_partial_internal
                      (cache, group_index, key, func, baton,
@@ -2498,22 +2563,6 @@ membuffer_cache_set_partial(svn_membuffe
  * svn_cache__t instance.
  */
 
-/* Stores the combined key value for the given key.  It will be used by
- * combine_key() to short-circuit expensive hash calculations.
- */
-typedef struct last_access_key_t
-{
-  /* result of key combining */
-  entry_key_t combined_key;
-
-  /* length of the key (or APR_HASH_KEY_STRING if not used) */
-  apr_ssize_t key_len;
-
-  /* the original key.  Only KEY_LEN bytes are valid.  We use uint32 for
-   * better compatibility with pseudo-md5 functions. */
-  apr_uint32_t key[64];
-} last_access_key_t;
-
 /* Internal cache structure (used in svn_cache__t.cache_internal) basically
  * holding the additional parameters needed to call the respective membuffer
  * functions.
@@ -2533,15 +2582,10 @@ typedef struct svn_membuffer_cache_t
   svn_cache__deserialize_func_t deserializer;
 
   /* Prepend this byte sequence to any key passed to us.
-   * This makes (very likely) our keys different from all keys used
-   * by other svn_membuffer_cache_t instances.
+   * This makes our keys different from all keys used by svn_membuffer_cache_t
+   * instances that we don't want to share cached data with.
    */
-  entry_key_t prefix;
-
-  /* The tail of the prefix string. It is being used as a developer-visible
-   * ID for this cache instance.
-   */
-  char info_prefix[PREFIX_TAIL_LEN];
+  full_key_t prefix;
 
   /* length of the keys that will be passed to us through the
    * svn_cache_t interface. May be APR_HASH_KEY_STRING.
@@ -2553,23 +2597,13 @@ typedef struct svn_membuffer_cache_t
 
   /* Temporary buffer containing the hash key for the current access
    */
-  entry_key_t combined_key;
-
-  /* cache for the last key used.
-   * Will be NULL for caches with short fix-sized keys.
-   */
-  last_access_key_t *last_access;
+  full_key_t combined_key;
 
   /* if enabled, this will serialize the access to this instance.
    */
   svn_mutex__t *mutex;
 } svn_membuffer_cache_t;
 
-/* After an estimated ALLOCATIONS_PER_POOL_CLEAR allocations, we should
- * clear the svn_membuffer_cache_t.pool to keep memory consumption in check.
- */
-#define ALLOCATIONS_PER_POOL_CLEAR 10
-
 /* Basically calculate a hash value for KEY of length KEY_LEN, combine it
  * with the CACHE->PREFIX and write the result in CACHE->COMBINED_KEY.
  * This could replace combine_key() entirely but we actually use it only
@@ -2580,70 +2614,35 @@ combine_long_key(svn_membuffer_cache_t *
                  const void *key,
                  apr_ssize_t key_len)
 {
-  assert(cache->last_access);
+  apr_uint32_t *digest_buffer;
+  char *key_copy;
+  apr_size_t prefix_len = cache->prefix.entry_key.key_len;
+  apr_size_t aligned_key_len;
 
   /* handle variable-length keys */
   if (key_len == APR_HASH_KEY_STRING)
     key_len = strlen((const char *) key);
 
-  /* same key as the last time? -> short-circuit */
-  if (   key_len == cache->last_access->key_len
-      && memcmp(key, cache->last_access->key, key_len) == 0)
-    {
-      memcpy(cache->combined_key, cache->last_access->combined_key,
-             sizeof(cache->combined_key));
-    }
-  else if (key_len >= 64)
-    {
-      /* relatively long key.  Use the generic, slow hash code for it */
-      apr_md5((unsigned char*)cache->combined_key, key, key_len);
-      cache->combined_key[0] ^= cache->prefix[0];
-      cache->combined_key[1] ^= cache->prefix[1];
-
-      /* is the key short enough to cache the result? */
-      if (key_len <= sizeof(cache->last_access->key))
-        {
-          memcpy(cache->last_access->combined_key, cache->combined_key,
-                 sizeof(cache->combined_key));
-          cache->last_access->key_len = key_len;
-          memcpy(cache->last_access->key, key, key_len);
-        }
-    }
-  else
-    {
-      /* shorter keys use efficient hash code and *do* cache the results */
-      cache->last_access->key_len = key_len;
-      if (key_len < 16)
-        {
-          memset(cache->last_access->key, 0, 16);
-          memcpy(cache->last_access->key, key, key_len);
-
-          svn__pseudo_md5_15((apr_uint32_t *)cache->combined_key,
-                             cache->last_access->key);
-        }
-      else if (key_len < 32)
-        {
-          memset(cache->last_access->key, 0, 32);
-          memcpy(cache->last_access->key, key, key_len);
-
-          svn__pseudo_md5_31((apr_uint32_t *)cache->combined_key,
-                             cache->last_access->key);
-        }
-      else
-        {
-          memset(cache->last_access->key, 0, 64);
-          memcpy(cache->last_access->key, key, key_len);
-
-          svn__pseudo_md5_63((apr_uint32_t *)cache->combined_key,
-                             cache->last_access->key);
-        }
+  aligned_key_len = ALIGN_VALUE(key_len);
 
-      cache->combined_key[0] ^= cache->prefix[0];
-      cache->combined_key[1] ^= cache->prefix[1];
-
-      memcpy(cache->last_access->combined_key, cache->combined_key,
-             sizeof(cache->combined_key));
-    }
+  /* Combine keys. */
+  svn_membuf__ensure(&cache->combined_key.full_key,
+                     aligned_key_len + prefix_len);
+
+  key_copy = (char *)cache->combined_key.full_key.data + prefix_len;
+  cache->combined_key.entry_key.key_len = aligned_key_len + prefix_len;
+  memcpy(key_copy, key, key_len);
+  memset(key_copy + key_len, 0, aligned_key_len - key_len);
+
+  /* Hash key into 16 bytes. */
+  digest_buffer = (apr_uint32_t *)cache->combined_key.entry_key.fingerprint;
+  svn__fnv1a_32x4_raw(digest_buffer, key, key_len);
+
+  /* Combine with prefix. */
+  cache->combined_key.entry_key.fingerprint[0]
+    ^= cache->prefix.entry_key.fingerprint[0];
+  cache->combined_key.entry_key.fingerprint[1]
+    ^= cache->prefix.entry_key.fingerprint[1];
 }
 
 /* Basically calculate a hash value for KEY of length KEY_LEN, combine it
@@ -2654,42 +2653,47 @@ combine_key(svn_membuffer_cache_t *cache
             const void *key,
             apr_ssize_t key_len)
 {
-  /* copy of *key, padded with 0 */
-  apr_uint64_t data[2];
-
   /* short, fixed-size keys are the most common case */
-  if (key_len == 16)
-    {
-      data[0] = ((const apr_uint64_t *)key)[0];
-      data[1] = ((const apr_uint64_t *)key)[1];
-    }
-  else if (key_len == 8)
-    {
-      data[0] = ((const apr_uint64_t *)key)[0];
-      data[1] = 0;
-    }
-  else if (key_len != APR_HASH_KEY_STRING && key_len < 16)
+  if (key_len != APR_HASH_KEY_STRING && key_len <= 16)
     {
+      const apr_size_t prefix_len = cache->prefix.entry_key.key_len;
+
+      /* Copy of *key, padded with 0.
+       * We put it just behind the prefix already copied into the COMBINED_KEY.
+       * The buffer space has been allocated when the cache was created. */
+      apr_uint64_t *data = (void *)((char *)cache->combined_key.full_key.data + 
+                                    prefix_len);
+      assert(prefix_len <= cache->combined_key.full_key.size - 16);
+      cache->combined_key.entry_key.key_len = prefix_len + 16;
+
       data[0] = 0;
       data[1] = 0;
       memcpy(data, key, key_len);
+
+      /* Scramble key DATA to spread the key space more evenly across the
+       * cache segments and entry buckets.  All of this shall be reversible
+       * to prevent key collisions.  So, we limit ourselves to xor and
+       * permutations.
+       *
+       * As long as we compare the full combined key, the additional
+       * fingerprint collisions introduced by a non-reversible scramble
+       * would simply reduce the cache effectiveness.
+       */
+      data[1] = (data[1] << 27) | (data[1] >> 37);
+      data[1] ^= data[0] & 0xffff;
+      data[0] ^= data[1] & APR_UINT64_C(0xffffffffffff0000);
+
+      /* combine with this cache's namespace */
+      cache->combined_key.entry_key.fingerprint[0]
+        = data[0] ^ cache->prefix.entry_key.fingerprint[0];
+      cache->combined_key.entry_key.fingerprint[1]
+        = data[1] ^ cache->prefix.entry_key.fingerprint[1];
     }
   else
     {
       /* longer or variably sized keys */
       combine_long_key(cache, key, key_len);
-      return;
     }
-
-  /* scramble key DATA.  All of this must be reversible to prevent key
-   * collisions.  So, we limit ourselves to xor and permutations. */
-  data[1] = (data[1] << 27) | (data[1] >> 37);
-  data[1] ^= data[0] & 0xffff;
-  data[0] ^= data[1] & APR_UINT64_C(0xffffffffffff0000);
-
-  /* combine with this cache's namespace */
-  cache->combined_key[0] = data[0] ^ cache->prefix[0];
-  cache->combined_key[1] = data[1] ^ cache->prefix[1];
 }
 
 /* Implement svn_cache__vtable_t.get (not thread-safe)
@@ -2721,7 +2725,7 @@ svn_membuffer_cache_get(void **value_p,
 
   /* Look the item up. */
   SVN_ERR(membuffer_cache_get(cache->membuffer,
-                              cache->combined_key,
+                              &cache->combined_key,
                               value_p,
                               cache->deserializer,
                               DEBUG_CACHE_MEMBUFFER_TAG
@@ -2758,7 +2762,7 @@ svn_membuffer_cache_has_key(svn_boolean_
 
   /* Look the item up. */
   SVN_ERR(membuffer_cache_has_key(cache->membuffer,
-                                  cache->combined_key,
+                                  &cache->combined_key,
                                   found));
 
   /* return result */
@@ -2790,7 +2794,7 @@ svn_membuffer_cache_set(void *cache_void
    * that the item will actually be cached afterwards.
    */
   return membuffer_cache_set(cache->membuffer,
-                             cache->combined_key,
+                             &cache->combined_key,
                              value,
                              cache->serializer,
                              cache->priority,
@@ -2836,7 +2840,7 @@ svn_membuffer_cache_get_partial(void **v
 
   combine_key(cache, key, cache->key_len);
   SVN_ERR(membuffer_cache_get_partial(cache->membuffer,
-                                      cache->combined_key,
+                                      &cache->combined_key,
                                       value_p,
                                       found,
                                       func,
@@ -2864,7 +2868,7 @@ svn_membuffer_cache_set_partial(void *ca
     {
       combine_key(cache, key, cache->key_len);
       SVN_ERR(membuffer_cache_set_partial(cache->membuffer,
-                                          cache->combined_key,
+                                          &cache->combined_key,
                                           func,
                                           baton,
                                           DEBUG_CACHE_MEMBUFFER_TAG
@@ -2936,7 +2940,7 @@ svn_membuffer_cache_get_info(void *cache
 
   /* cache front-end specific data */
 
-  info->id = apr_pstrdup(result_pool, cache->info_prefix);
+  info->id = apr_pstrdup(result_pool, cache->prefix.full_key.data);
 
   /* collect info from shared cache back-end */
 
@@ -3129,11 +3133,12 @@ svn_cache__create_membuffer_cache(svn_ca
                                   apr_pool_t *scratch_pool)
 {
   svn_checksum_t *checksum;
+  apr_size_t prefix_len, prefix_orig_len;
 
   /* allocate the cache header structures
    */
   svn_cache__t *wrapper = apr_pcalloc(result_pool, sizeof(*wrapper));
-  svn_membuffer_cache_t *cache = apr_palloc(result_pool, sizeof(*cache));
+  svn_membuffer_cache_t *cache = apr_pcalloc(result_pool, sizeof(*cache));
 
   /* initialize our internal cache header
    */
@@ -3144,33 +3149,38 @@ svn_cache__create_membuffer_cache(svn_ca
   cache->deserializer = deserializer
                       ? deserializer
                       : deserialize_svn_stringbuf;
-  get_prefix_tail(prefix, cache->info_prefix);
   cache->priority = priority;
   cache->key_len = klen;
 
   SVN_ERR(svn_mutex__init(&cache->mutex, thread_safe, result_pool));
 
-  /* for performance reasons, we don't actually store the full prefix but a
-   * hash value of it
-   */
+  /* Copy the prefix into the prefix full key. Align it to ITEM_ALIGMENT.
+   * Don't forget to include the terminating NUL. */
+  prefix_orig_len = strlen(prefix) + 1;
+  prefix_len = ALIGN_VALUE(prefix_orig_len);
+
+  svn_membuf__create(&cache->prefix.full_key, prefix_len, result_pool);
+  memcpy((char *)cache->prefix.full_key.data, prefix, prefix_orig_len);
+  memset((char *)cache->prefix.full_key.data + prefix_orig_len, 0,
+         prefix_len - prefix_orig_len);
+
+  /* Construct the folded prefix key. */
   SVN_ERR(svn_checksum(&checksum,
                        svn_checksum_md5,
                        prefix,
                        strlen(prefix),
                        scratch_pool));
-  memcpy(cache->prefix, checksum->digest, sizeof(cache->prefix));
-
-  /* fix-length keys of 16 bytes or under don't need a buffer because we
-   * can use a very fast key combining algorithm. */
-  if ((klen == APR_HASH_KEY_STRING) ||  klen > sizeof(entry_key_t))
-    {
-      cache->last_access = apr_pcalloc(result_pool, sizeof(*cache->last_access));
-      cache->last_access->key_len = APR_HASH_KEY_STRING;
-    }
-  else
-    {
-      cache->last_access = NULL;
-    }
+  memcpy(cache->prefix.entry_key.fingerprint, checksum->digest,
+         sizeof(cache->prefix.entry_key.fingerprint));
+  cache->prefix.entry_key.key_len = prefix_len;
+
+  /* Initialize the combined key. Pre-allocate some extra room in the full
+   * key such that we probably don't need to re-alloc. */
+  cache->combined_key.entry_key = cache->prefix.entry_key;
+  svn_membuf__create(&cache->combined_key.full_key, prefix_len + 200,
+                     result_pool);
+  memcpy(cache->combined_key.full_key.data, cache->prefix.full_key.data,
+         prefix_len);
 
   /* initialize the generic cache wrapper
    */

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/checksum.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/checksum.c Thu Jun 18 10:35:30 2015
@@ -80,6 +80,14 @@ static const apr_size_t digest_sizes[] =
   sizeof(apr_uint32_t)
 };
 
+/* Checksum type prefixes used in serialized checksums. */
+static const char *ckind_str[] = {
+  "$md5 $",
+  "$sha1$",
+  "$fnv1$",
+  "$fnvm$",
+};
+
 /* Returns the digest size of it's argument. */
 #define DIGESTSIZE(k) \
   (((k) < svn_checksum_md5 || (k) > svn_checksum_fnv1a_32x4) ? 0 : digest_sizes[k])
@@ -317,13 +325,10 @@ svn_checksum_serialize(const svn_checksu
                        apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool)
 {
-  const char *ckind_str;
-
   SVN_ERR_ASSERT_NO_RETURN(checksum->kind >= svn_checksum_md5
                            || checksum->kind <= svn_checksum_fnv1a_32x4);
-  ckind_str = (checksum->kind == svn_checksum_md5 ? "$md5 $" : "$sha1$");
   return apr_pstrcat(result_pool,
-                     ckind_str,
+                     ckind_str[checksum->kind],
                      svn_checksum_to_cstring(checksum, scratch_pool),
                      SVN_VA_NULL);
 }
@@ -335,18 +340,29 @@ svn_checksum_deserialize(const svn_check
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
-  svn_checksum_kind_t ckind;
+  svn_checksum_kind_t kind;
   svn_checksum_t *parsed_checksum;
 
-  /* "$md5 $..." or "$sha1$..." */
-  SVN_ERR_ASSERT(strlen(data) > 6);
+  /* All prefixes have the same length. */
+  apr_size_t prefix_len = strlen(ckind_str[0]);
 
-  ckind = (data[1] == 'm' ? svn_checksum_md5 : svn_checksum_sha1);
-  SVN_ERR(svn_checksum_parse_hex(&parsed_checksum, ckind,
-                                 data + 6, result_pool));
-  *checksum = parsed_checksum;
+  /* "$md5 $...", "$sha1$..." or ... */
+  if (strlen(data) <= prefix_len)
+    return svn_error_createf(SVN_ERR_BAD_CHECKSUM_PARSE, NULL,
+                             _("Invalid prefix in checksum '%s'"),
+                             data);
+
+  for (kind = svn_checksum_md5; kind <= svn_checksum_fnv1a_32x4; ++kind)
+    if (strncmp(ckind_str[kind], data, prefix_len) == 0)
+      {
+        SVN_ERR(svn_checksum_parse_hex(&parsed_checksum, kind,
+                                       data + prefix_len, result_pool));
+        *checksum = parsed_checksum;
+        return SVN_NO_ERROR;
+      }
 
-  return SVN_NO_ERROR;
+  return svn_error_createf(SVN_ERR_BAD_CHECKSUM_KIND, NULL,
+                           "Unknown checksum kind in '%s'", data);
 }
 
 

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/cmdline.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/cmdline.c Thu Jun 18 10:35:30 2015
@@ -538,19 +538,20 @@ trust_server_cert_non_interactive(svn_au
                                   apr_pool_t *pool)
 {
   struct trust_server_cert_non_interactive_baton *b = baton;
+  apr_uint32_t non_ignored_failures;
   *cred_p = NULL;
 
-  if (failures == 0 ||
-      (b->trust_server_cert_unknown_ca &&
-       (failures & SVN_AUTH_SSL_UNKNOWNCA)) ||
-      (b->trust_server_cert_cn_mismatch &&
-       (failures & SVN_AUTH_SSL_CNMISMATCH)) ||
-      (b->trust_server_cert_expired &&
-       (failures & SVN_AUTH_SSL_EXPIRED)) ||
-      (b->trust_server_cert_not_yet_valid &&
-        (failures & SVN_AUTH_SSL_NOTYETVALID)) ||
-      (b->trust_server_cert_other_failure &&
-        (failures & SVN_AUTH_SSL_OTHER)))
+  /* Mask away bits we are instructed to ignore. */
+  non_ignored_failures = failures & ~(
+        (b->trust_server_cert_unknown_ca ? SVN_AUTH_SSL_UNKNOWNCA : 0)
+      | (b->trust_server_cert_cn_mismatch ? SVN_AUTH_SSL_CNMISMATCH : 0)
+      | (b->trust_server_cert_expired ? SVN_AUTH_SSL_EXPIRED : 0)
+      | (b->trust_server_cert_not_yet_valid ? SVN_AUTH_SSL_NOTYETVALID : 0)
+      | (b->trust_server_cert_other_failure ? SVN_AUTH_SSL_OTHER : 0)
+  );
+
+  /* If no failures remain, accept the certificate. */
+  if (non_ignored_failures == 0)
     {
       *cred_p = apr_pcalloc(pool, sizeof(**cred_p));
       (*cred_p)->may_save = FALSE;
@@ -810,9 +811,124 @@ svn_cmdline__print_xml_prop(svn_stringbu
   return;
 }
 
+/* Return the most similar string to NEEDLE in HAYSTACK, which contains
+ * HAYSTACK_LEN elements.  Return NULL if no string is sufficiently similar.
+ */
+/* See svn_cl__similarity_check() for a more general solution. */
+static const char *
+most_similar(const char *needle_cstr,
+             const char **haystack,
+             apr_size_t haystack_len,
+             apr_pool_t *scratch_pool)
+{
+  const char *max_similar;
+  apr_size_t max_score = 0;
+  apr_size_t i;
+  svn_membuf_t membuf;
+  svn_string_t *needle_str = svn_string_create(needle_cstr, scratch_pool);
+
+  svn_membuf__create(&membuf, 64, scratch_pool);
+
+  for (i = 0; i < haystack_len; i++)
+    {
+      apr_size_t score;
+      svn_string_t *hay = svn_string_create(haystack[i], scratch_pool);
+
+      score = svn_string__similarity(needle_str, hay, &membuf, NULL);
+
+      /* If you update this factor, consider updating
+       * svn_cl__similarity_check(). */
+      if (score >= (2 * SVN_STRING__SIM_RANGE_MAX + 1) / 3
+          && score > max_score)
+        {
+          max_score = score;
+          max_similar = haystack[i];
+        }
+    }
+
+  if (max_score)
+    return max_similar;
+  else
+    return NULL;
+}
+
+/* Verify that NEEDLE is in HAYSTACK, which contains HAYSTACK_LEN elements. */
+static svn_error_t *
+string_in_array(const char *needle,
+                const char **haystack,
+                apr_size_t haystack_len,
+                apr_pool_t *scratch_pool)
+{
+  const char *next_of_kin;
+  apr_size_t i;
+  for (i = 0; i < haystack_len; i++)
+    {
+      if (!strcmp(needle, haystack[i]))
+        return SVN_NO_ERROR;
+    }
+
+  /* Error. */
+  next_of_kin = most_similar(needle, haystack, haystack_len, scratch_pool);
+  if (next_of_kin)
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("Ignoring unknown value '%s'; "
+                               "did you mean '%s'?"),
+                             needle, next_of_kin);
+  else
+    return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                             _("Ignoring unknown value '%s'"),
+                             needle);
+}
+
+#include "config_keys.inc"
+
+/* Validate the FILE, SECTION, and OPTION components of CONFIG_OPTION are
+ * known.  Return an error if not.  (An unknown value may be either a typo
+ * or added in a newer minor version of Subversion.) */
+static svn_error_t *
+validate_config_option(svn_cmdline__config_argument_t *config_option,
+                       apr_pool_t *scratch_pool)
+{
+  svn_boolean_t arbitrary_keys = FALSE;
+
+  /* TODO: some day, we could also verify that OPTION is valid for SECTION;
+     i.e., forbid invalid combinations such as config:auth:diff-extensions. */
+
+#define ARRAYLEN(x) ( sizeof((x)) / sizeof((x)[0]) )
+
+  SVN_ERR(string_in_array(config_option->file, svn__valid_config_files,
+                          ARRAYLEN(svn__valid_config_files),
+                          scratch_pool));
+  SVN_ERR(string_in_array(config_option->section, svn__valid_config_sections,
+                          ARRAYLEN(svn__valid_config_sections),
+                          scratch_pool));
+
+  /* Don't validate option names for sections such as servers[group],
+   * config[tunnels], and config[auto-props] that permit arbitrary options. */
+    {
+      int i;
+
+      for (i = 0; i < ARRAYLEN(svn__empty_config_sections); i++)
+        {
+        if (!strcmp(config_option->section, svn__empty_config_sections[i]))
+          arbitrary_keys = TRUE;
+        }
+    }
+
+  if (! arbitrary_keys)
+    SVN_ERR(string_in_array(config_option->option, svn__valid_config_options,
+                            ARRAYLEN(svn__valid_config_options),
+                            scratch_pool));
+
+#undef ARRAYLEN
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_cmdline__parse_config_option(apr_array_header_t *config_options,
                                  const char *opt_arg,
+                                 const char *prefix,
                                  apr_pool_t *pool)
 {
   svn_cmdline__config_argument_t *config_option;
@@ -826,6 +942,8 @@ svn_cmdline__parse_config_option(apr_arr
           if ((equals_sign = strchr(second_colon + 1, '=')) &&
               (equals_sign != second_colon + 1))
             {
+              svn_error_t *warning;
+
               config_option = apr_pcalloc(pool, sizeof(*config_option));
               config_option->file = apr_pstrndup(pool, opt_arg,
                                                  first_colon - opt_arg);
@@ -834,6 +952,13 @@ svn_cmdline__parse_config_option(apr_arr
               config_option->option = apr_pstrndup(pool, second_colon + 1,
                                                    equals_sign - second_colon - 1);
 
+              warning = validate_config_option(config_option, pool);
+              if (warning)
+                {
+                  svn_handle_warning2(stderr, warning, prefix);
+                  svn_error_clear(warning);
+                }
+
               if (! (strchr(config_option->option, ':')))
                 {
                   config_option->value = apr_pstrndup(pool, equals_sign + 1,
@@ -1404,3 +1529,50 @@ svn_cmdline__edit_string_externally(svn_
 
   return svn_error_trace(err);
 }
+
+svn_error_t *
+svn_cmdline__parse_trust_options(
+                        svn_boolean_t *trust_server_cert_unknown_ca,
+                        svn_boolean_t *trust_server_cert_cn_mismatch,
+                        svn_boolean_t *trust_server_cert_expired,
+                        svn_boolean_t *trust_server_cert_not_yet_valid,
+                        svn_boolean_t *trust_server_cert_other_failure,
+                        const char *opt_arg,
+                        apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *failures;
+  int i;
+
+  *trust_server_cert_unknown_ca = FALSE;
+  *trust_server_cert_cn_mismatch = FALSE;
+  *trust_server_cert_expired = FALSE;
+  *trust_server_cert_not_yet_valid = FALSE;
+  *trust_server_cert_other_failure = FALSE;
+
+  failures = svn_cstring_split(opt_arg, ", \n\r\t\v", TRUE, scratch_pool);
+
+  for (i = 0; i < failures->nelts; i++)
+    {
+      const char *value = APR_ARRAY_IDX(failures, i, const char *);
+      if (!strcmp(value, "unknown-ca"))
+        *trust_server_cert_unknown_ca = TRUE;
+      else if (!strcmp(value, "cn-mismatch"))
+        *trust_server_cert_cn_mismatch = TRUE;
+      else if (!strcmp(value, "expired"))
+        *trust_server_cert_expired = TRUE;
+      else if (!strcmp(value, "not-yet-valid"))
+        *trust_server_cert_not_yet_valid = TRUE;
+      else if (!strcmp(value, "other"))
+        *trust_server_cert_other_failure = TRUE;
+      else
+        return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                  _("Unknown value '%s' for %s.\n"
+                                    "Supported values: %s"),
+                                  value,
+                                  "--trust-server-cert-failures",
+                                  "unknown-ca, cn-mismatch, expired, "
+                                  "not-yet-valid, other");
+    }
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/compress.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/compress.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/compress.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/compress.c Thu Jun 18 10:35:30 2015
@@ -220,7 +220,7 @@ zlib_decode(const unsigned char *in, apr
 }
 
 svn_error_t *
-svn__compress(svn_stringbuf_t *in,
+svn__compress(const void *data, apr_size_t len,
               svn_stringbuf_t *out,
               int compression_method)
 {
@@ -230,13 +230,13 @@ svn__compress(svn_stringbuf_t *in,
                              _("Unsupported compression method %d"),
                              compression_method);
 
-  return zlib_encode(in->data, in->len, out, compression_method);
+  return zlib_encode(data, len, out, compression_method);
 }
 
 svn_error_t *
-svn__decompress(svn_stringbuf_t *in,
+svn__decompress(const void *data, apr_size_t len,
                 svn_stringbuf_t *out,
                 apr_size_t limit)
 {
-  return zlib_decode((const unsigned char*)in->data, in->len, out, limit);
+  return zlib_decode(data, len, out, limit);
 }

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_file.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_file.c Thu Jun 18 10:35:30 2015
@@ -940,7 +940,6 @@ svn_config_ensure(const char *config_dir
         "###                              HTTP operation."                   NL
         "###   http-chunked-requests      Whether to use chunked transfer"   NL
         "###                              encoding for HTTP requests body."  NL
-        "###   neon-debug-mask            Debug mask for Neon HTTP library"  NL
         "###   ssl-authority-files        List of files, each of a trusted CA"
                                                                              NL
         "###   ssl-trust-default-ca       Trust the system 'default' CAs"    NL
@@ -1033,7 +1032,6 @@ svn_config_ensure(const char *config_dir
         "### Most users will not need to explicitly set the http-library"    NL
         "### option, but valid values for the option include:"               NL
         "###    'serf': Serf-based module (Subversion 1.5 - present)"        NL
-        "###    'neon': Neon-based module (Subversion 1.0 - 1.7)"            NL
         "### Availability of these modules may depend on your specific"      NL
         "### Subversion distribution."                                       NL
         "###"                                                                NL
@@ -1058,7 +1056,6 @@ svn_config_ensure(const char *config_dir
         "# http-proxy-username = blah"                                       NL
         "# http-proxy-password = doubleblah"                                 NL
         "# http-timeout = 60"                                                NL
-        "# neon-debug-mask = 130"                                            NL
 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
         "# store-plaintext-passwords = no"                                   NL
 #endif
@@ -1099,7 +1096,6 @@ svn_config_ensure(const char *config_dir
         "# http-proxy-password = defaultpassword"                            NL
         "# http-compression = no"                                            NL
         "# No http-timeout, so just use the builtin default."                NL
-        "# No neon-debug-mask, so neon debugging is disabled."               NL
         "# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem"   NL
         "#"                                                                  NL
         "# Password / passphrase caching parameters:"                        NL

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_win.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/config_win.c Thu Jun 18 10:35:30 2015
@@ -197,14 +197,19 @@ svn_config__parse_registry(svn_config_t
                      &hkey);
   if (err != ERROR_SUCCESS)
     {
-      const int is_enoent = APR_STATUS_IS_ENOENT(APR_FROM_OS_ERROR(err));
+      apr_status_t apr_err = APR_FROM_OS_ERROR(err);
+      svn_boolean_t is_enoent = APR_STATUS_IS_ENOENT(apr_err)
+                                || (err == ERROR_INVALID_HANDLE);
+
       if (!is_enoent)
-        return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
+        return svn_error_createf(SVN_ERR_BAD_FILENAME,
+                                 svn_error_wrap_apr(apr_err, NULL),
                                  _("Can't open registry key '%s'"),
                                  svn_dirent_local_style(file, pool));
-      else if (must_exist && is_enoent)
-        return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
-                                 _("Can't find registry key '%s'"),
+      else if (must_exist)
+        return svn_error_createf(SVN_ERR_BAD_FILENAME,
+                                 NULL,
+                                 _("Can't open registry key '%s'"),
                                  svn_dirent_local_style(file, pool));
       else
         return SVN_NO_ERROR;

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/dirent_uri.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/dirent_uri.c Thu Jun 18 10:35:30 2015
@@ -1295,9 +1295,9 @@ svn_relpath_split(const char **dirpath,
 }
 
 const char *
-svn_relpath_limit(const char *relpath,
-                  int max_components,
-                  apr_pool_t *result_pool)
+svn_relpath_prefix(const char *relpath,
+                   int max_components,
+                   apr_pool_t *result_pool)
 {
   const char *end;
   assert(relpath_is_canonical(relpath));

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/dso.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/dso.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/dso.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/dso.c Thu Jun 18 10:35:30 2015
@@ -19,7 +19,6 @@
  * ====================================================================
  */
 
-#include <apr_thread_mutex.h>
 #include <apr_hash.h>
 
 #include "svn_hash.h"
@@ -29,6 +28,7 @@
 
 #include "private/svn_mutex.h"
 #include "private/svn_atomic.h"
+#include "private/svn_subr_private.h"
 
 /* A mutex to protect our global pool and cache. */
 static svn_mutex__t *dso_mutex = NULL;
@@ -123,4 +123,11 @@ svn_dso_load(apr_dso_handle_t **dso, con
 
   return SVN_NO_ERROR;
 }
+
+apr_pool_t *
+svn_dso__pool(void)
+{
+  return dso_pool;
+}
+
 #endif /* APR_HAS_DSO */

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/error.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/error.c Thu Jun 18 10:35:30 2015
@@ -59,11 +59,12 @@ static apr_threadkey_t *error_line_key =
 /* No-op destructor for apr_threadkey_private_create(). */
 static void null_threadkey_dtor(void *stuff) {}
 
-/* Handler for svn_atomic__init_once used by svn_error__locate to
-   initialize the thread-local error location storage.
-   This function will never return an error. */
-static svn_error_t *
-locate_init_once(void *ignored_baton, apr_pool_t *ignored_pool)
+/* Implements svn_atomic__str_init_func_t.
+   Callback used by svn_error__locate to initialize the thread-local
+   error location storage.  This function will never return an
+   error string. */
+static const char *
+locate_init_once(void *ignored_baton)
 {
   /* Strictly speaking, this is a memory leak, since we're creating an
      unmanaged, top-level pool and never destroying it.  We do this
@@ -86,7 +87,7 @@ locate_init_once(void *ignored_baton, ap
   if (status != APR_SUCCESS)
     error_file_key = error_line_key = NULL;
 
-  return SVN_NO_ERROR;
+  return NULL;
 }
 #  endif  /* APR_HAS_THREADS */
 
@@ -124,9 +125,7 @@ svn_error__locate(const char *file, long
 #ifdef SVN_DEBUG
 #  if APR_HAS_THREADS
   static volatile svn_atomic_t init_status = 0;
-  svn_error_clear(svn_atomic__init_once(&init_status,
-                                        locate_init_once,
-                                        NULL, NULL));
+  svn_atomic__init_once_no_error(&init_status, locate_init_once, NULL);
 
   if (error_file_key && error_line_key)
     {
@@ -164,7 +163,9 @@ make_error_internal(apr_status_t apr_err
 {
   apr_pool_t *pool;
   svn_error_t *new_error;
-  apr_status_t status = APR_SUCCESS;
+#ifdef SVN_DEBUG
+  apr_status_t status = APR_ENOTIMPL;
+#endif
 
   /* Reuse the child's pool, or create our own. */
   if (child)

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.c Thu Jun 18 10:35:30 2015
@@ -132,6 +132,25 @@ svn__fnv1a_32x4(const void *input, apr_s
                              len - processed);
 }
 
+void
+svn__fnv1a_32x4_raw(apr_uint32_t hashes[4],
+                    const void *input,
+                    apr_size_t len)
+{
+  apr_size_t processed;
+
+  apr_size_t i;
+  for (i = 0; i < SCALING; ++i)
+    hashes[i] = FNV1_BASE_32;
+
+  /* Process full 16 byte chunks. */
+  processed = fnv1a_32x4(hashes, input, len);
+
+  /* Fold the remainder (if any) into the first hash. */
+  hashes[0] = fnv1a_32(hashes[0], (const char *)input + processed,
+                       len - processed);
+}
+
 struct svn_fnv1a_32__context_t
 {
   apr_uint32_t hash;

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.h?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/fnv1a.h Thu Jun 18 10:35:30 2015
@@ -76,6 +76,14 @@ svn_fnv1a_32x4__update(svn_fnv1a_32x4__c
 apr_uint32_t
 svn_fnv1a_32x4__finalize(svn_fnv1a_32x4__context_t *context);
 
+/* Set HASHES to the 4 partial hash sums produced by the modified FVN-1a
+ * over INPUT of LEN bytes.
+ */
+void
+svn__fnv1a_32x4_raw(apr_uint32_t hashes[4],
+                    const void *input,
+                    apr_size_t len);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/hash.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/hash.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/hash.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/hash.c Thu Jun 18 10:35:30 2015
@@ -135,7 +135,7 @@ svn_hash__read_entry(svn_hash__entry_t *
                                   0, APR_SIZE_MAX, 10);
       if (err)
         return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key length"));
       entry->keylen = (apr_size_t)ui64;
 
       /* Now read that much into a buffer. */
@@ -148,19 +148,19 @@ svn_hash__read_entry(svn_hash__entry_t *
       SVN_ERR(svn_stream_read_full(stream, &c, &len));
       if (c != '\n')
         return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key data"));
 
       /* Read a val length line */
       SVN_ERR(svn_stream_readline(stream, &buf, "\n", &eof, pool));
 
       if ((buf->data[0] == 'V') && (buf->data[1] == ' '))
         {
-          /* Get the length of the key */
+          /* Get the length of the val */
           err = svn_cstring_strtoui64(&ui64, buf->data + 2,
                                       0, APR_SIZE_MAX, 10);
           if (err)
             return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
-                                    _("Serialized hash malformed"));
+                                    _("Serialized hash malformed value length"));
           entry->vallen = (apr_size_t)ui64;
 
           entry->val = apr_palloc(pool, entry->vallen + 1);
@@ -172,7 +172,7 @@ svn_hash__read_entry(svn_hash__entry_t *
           SVN_ERR(svn_stream_read_full(stream, &c, &len));
           if (c != '\n')
             return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
-                                    _("Serialized hash malformed"));
+                                    _("Serialized hash malformed value data"));
         }
       else
         return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
@@ -186,7 +186,7 @@ svn_hash__read_entry(svn_hash__entry_t *
                                   0, APR_SIZE_MAX, 10);
       if (err)
         return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key length"));
       entry->keylen = (apr_size_t)ui64;
 
       /* Now read that much into a buffer. */
@@ -199,7 +199,7 @@ svn_hash__read_entry(svn_hash__entry_t *
       SVN_ERR(svn_stream_read_full(stream, &c, &len));
       if (c != '\n')
         return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key data"));
 
       /* Remove this hash entry. */
       entry->vallen = 0;

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/io.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/io.c Thu Jun 18 10:35:30 2015
@@ -1191,7 +1191,7 @@ svn_error_t *
 svn_io_file_create_bytes(const char *file,
                          const void *contents,
                          apr_size_t length,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
   apr_file_t *f;
   apr_size_t written;
@@ -1200,13 +1200,14 @@ svn_io_file_create_bytes(const char *fil
   SVN_ERR(svn_io_file_open(&f, file,
                            (APR_WRITE | APR_CREATE | APR_EXCL),
                            APR_OS_DEFAULT,
-                           pool));
+                           scratch_pool));
   if (length)
-    err = svn_io_file_write_full(f, contents, length, &written, pool);
+    err = svn_io_file_write_full(f, contents, length, &written,
+                                 scratch_pool);
 
   err = svn_error_compose_create(
                     err,
-                    svn_io_file_close(f, pool));
+                    svn_io_file_close(f, scratch_pool));
 
   if (err)
     {
@@ -1216,7 +1217,7 @@ svn_io_file_create_bytes(const char *fil
       return svn_error_trace(
                 svn_error_compose_create(
                     err,
-                    svn_io_remove_file2(file, TRUE, pool)));
+                    svn_io_remove_file2(file, TRUE, scratch_pool)));
     }
 
   return SVN_NO_ERROR;
@@ -1235,9 +1236,10 @@ svn_io_file_create(const char *file,
 
 svn_error_t *
 svn_io_file_create_empty(const char *file,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
-  return svn_error_trace(svn_io_file_create_bytes(file, NULL, 0, pool));
+  return svn_error_trace(svn_io_file_create_bytes(file, NULL, 0,
+                                                  scratch_pool));
 }
 
 svn_error_t *
@@ -1854,7 +1856,7 @@ io_win_file_attrs_set(const char *fname,
                                   _("Can't set attributes of file '%s'"),
                                   svn_dirent_local_style(fname, pool));
 
-    return SVN_NO_ERROR;;
+    return SVN_NO_ERROR;
 }
 
 static svn_error_t *win_init_dynamic_imports(void *baton, apr_pool_t *pool)
@@ -2565,7 +2567,7 @@ svn_io_remove_dir2(const char *path, svn
      If we need to bail out, do so early. */
 
   if (cancel_func)
-    SVN_ERR((*cancel_func)(cancel_baton));
+    SVN_ERR(cancel_func(cancel_baton));
 
   subpool = svn_pool_create(pool);
 
@@ -2598,7 +2600,7 @@ svn_io_remove_dir2(const char *path, svn
       else
         {
           if (cancel_func)
-            SVN_ERR((*cancel_func)(cancel_baton));
+            SVN_ERR(cancel_func(cancel_baton));
 
           err = svn_io_remove_file2(fullpath, FALSE, subpool);
           if (err)
@@ -3580,6 +3582,16 @@ svn_io_file_info_get(apr_finfo_t *finfo,
              pool);
 }
 
+svn_error_t *
+svn_io_file_size_get(svn_filesize_t *filesize_p, apr_file_t *file,
+                     apr_pool_t *pool)
+{
+  apr_finfo_t finfo;
+  SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, file, pool));
+
+  *filesize_p = finfo.size;
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_io_file_read(apr_file_t *file, void *buf,
@@ -3633,7 +3645,7 @@ svn_io_file_aligned_seek(apr_file_t *fil
                          apr_off_t block_size,
                          apr_off_t *buffer_start,
                          apr_off_t offset,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
   const apr_size_t apr_default_buffer_size = 4096;
   apr_size_t file_buffer_size = apr_default_buffer_size;
@@ -3683,7 +3695,7 @@ svn_io_file_aligned_seek(apr_file_t *fil
          buffer and no I/O will actually happen in the FILL_BUFFER
          section below.
        */
-      SVN_ERR(svn_io_file_seek(file, APR_CUR, &current, pool));
+      SVN_ERR(svn_io_file_seek(file, APR_CUR, &current, scratch_pool));
       fill_buffer = aligned_offset + file_buffer_size <= current
                  || current <= aligned_offset;
     }
@@ -3694,7 +3706,8 @@ svn_io_file_aligned_seek(apr_file_t *fil
       apr_status_t status;
 
       /* seek to the start of the block and cause APR to read 1 block */
-      SVN_ERR(svn_io_file_seek(file, APR_SET, &aligned_offset, pool));
+      SVN_ERR(svn_io_file_seek(file, APR_SET, &aligned_offset,
+                               scratch_pool));
       status = apr_file_getc(&dummy, file);
 
       /* read may fail if we seek to or behind EOF.  That's ok then. */
@@ -3702,17 +3715,17 @@ svn_io_file_aligned_seek(apr_file_t *fil
         return do_io_file_wrapper_cleanup(file, status,
                                           N_("Can't read file '%s'"),
                                           N_("Can't read stream"),
-                                          pool);
+                                          scratch_pool);
     }
 
   /* finally, seek to the OFFSET the caller wants */
   desired_offset = offset;
-  SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, pool));
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, scratch_pool));
   if (desired_offset != offset)
     return do_io_file_wrapper_cleanup(file, APR_EOF,
                                       N_("Can't seek in file '%s'"),
                                       N_("Can't seek in stream"),
-                                      pool);
+                                      scratch_pool);
 
   /* return the buffer start that we (probably) enforced */
   if (buffer_start)
@@ -3865,11 +3878,10 @@ svn_io_write_atomic(const char *final_pa
                                                       scratch_pool));
     }
 
-#ifdef __linux__
+#if SVN_ON_POSIX
   {
-    /* Linux has the unusual feature that fsync() on a file is not
-       enough to ensure that a file's directory entries have been
-       flushed to disk; you have to fsync the directory as well.
+    /* On POSIX, the file name is stored in the file's directory entry.
+       Hence, we need to fsync() that directory as well.
        On other operating systems, we'd only be asking for trouble
        by trying to open and fsync a directory. */
     apr_file_t *file;
@@ -4043,37 +4055,16 @@ svn_error_t *
 svn_io_file_move(const char *from_path, const char *to_path,
                  apr_pool_t *pool)
 {
-  svn_error_t *err = svn_io_file_rename(from_path, to_path, pool);
+  svn_error_t *err = svn_error_trace(svn_io_file_rename(from_path, to_path,
+                                                        pool));
 
   if (err && APR_STATUS_IS_EXDEV(err->apr_err))
     {
-      const char *tmp_to_path;
-
       svn_error_clear(err);
 
-      SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_to_path,
-                                       svn_dirent_dirname(to_path, pool),
-                                       svn_io_file_del_none,
-                                       pool, pool));
-
-      err = svn_io_copy_file(from_path, tmp_to_path, TRUE, pool);
-      if (err)
-        goto failed_tmp;
-
-      err = svn_io_file_rename(tmp_to_path, to_path, pool);
-      if (err)
-        goto failed_tmp;
-
-      err = svn_io_remove_file2(from_path, FALSE, pool);
-      if (! err)
-        return SVN_NO_ERROR;
-
-      svn_error_clear(svn_io_remove_file2(to_path, FALSE, pool));
-
-      return err;
-
-    failed_tmp:
-      svn_error_clear(svn_io_remove_file2(tmp_to_path, FALSE, pool));
+      /* svn_io_copy_file() performs atomic copy via temporary file. */
+      err = svn_error_trace(svn_io_copy_file(from_path, to_path, TRUE,
+                                             pool));
     }
 
   return err;

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/mergeinfo.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/mergeinfo.c Thu Jun 18 10:35:30 2015
@@ -2306,8 +2306,7 @@ svn_rangelist_dup(const svn_rangelist_t
 svn_merge_range_t *
 svn_merge_range_dup(const svn_merge_range_t *range, apr_pool_t *pool)
 {
-  svn_merge_range_t *new_range = apr_palloc(pool, sizeof(*new_range));
-  memcpy(new_range, range, sizeof(*new_range));
+  svn_merge_range_t *new_range = apr_pmemdup(pool, range, sizeof(*new_range));
   return new_range;
 }
 

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/packed_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/packed_data.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/packed_data.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/packed_data.c Thu Jun 18 10:35:30 2015
@@ -561,7 +561,7 @@ write_stream_data(svn_stream_t *stream,
                   svn_stringbuf_t *uncompressed,
                   svn_stringbuf_t *compressed)
 {
-  SVN_ERR(svn__compress(uncompressed,
+  SVN_ERR(svn__compress(uncompressed->data, uncompressed->len,
                         compressed,
                         SVN_DELTA_COMPRESSION_LEVEL_DEFAULT));
 
@@ -972,7 +972,8 @@ read_stream_data(svn_stream_t *stream,
   SVN_ERR(svn_stream_read_full(stream, compressed->data, &compressed->len));
   compressed->data[compressed_len] = '\0';
 
-  SVN_ERR(svn__decompress(compressed, uncompressed, uncompressed_len));
+  SVN_ERR(svn__decompress(compressed->data, compressed->len,
+                          uncompressed, uncompressed_len));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/pool.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/pool.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/pool.c Thu Jun 18 10:35:30 2015
@@ -30,7 +30,6 @@
 #include <apr_version.h>
 #include <apr_general.h>
 #include <apr_pools.h>
-#include <apr_thread_mutex.h>
 
 #include "svn_pools.h"
 

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/properties.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/properties.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/properties.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/properties.c Thu Jun 18 10:35:30 2015
@@ -131,7 +131,6 @@ svn_boolean_t
 svn_prop_has_svn_prop(const apr_hash_t *props, apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
-  const void *prop_name;
 
   if (! props)
     return FALSE;
@@ -139,8 +138,9 @@ svn_prop_has_svn_prop(const apr_hash_t *
   for (hi = apr_hash_first(pool, (apr_hash_t *)props); hi;
        hi = apr_hash_next(hi))
     {
-      apr_hash_this(hi, &prop_name, NULL, NULL);
-      if (svn_prop_is_svn_prop((const char *) prop_name))
+      const char *prop_name = apr_hash_this_key(hi);
+
+      if (svn_prop_is_svn_prop(prop_name))
         return TRUE;
     }
 

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/stream.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/stream.c Thu Jun 18 10:35:30 2015
@@ -1443,13 +1443,14 @@ svn_error_t *
 svn_stringbuf_from_stream(svn_stringbuf_t **str,
                           svn_stream_t *stream,
                           apr_size_t len_hint,
-                          apr_pool_t *pool)
+                          apr_pool_t *result_pool)
 {
 #define MIN_READ_SIZE 64
 
   apr_size_t to_read = 0;
   svn_stringbuf_t *text
-    = svn_stringbuf_create_ensure(len_hint ? len_hint : MIN_READ_SIZE, pool);
+    = svn_stringbuf_create_ensure(len_hint ? len_hint : MIN_READ_SIZE,
+                                  result_pool);
 
   do
     {
@@ -2199,11 +2200,11 @@ svn_stream__install_stream(svn_stream_t
 
       apr_os_file_get(&hFile, ib->baton_apr.file);
 
-      SVN_ERR(svn_utf__win32_utf8_to_utf16(&w_final_abspath,
-                                           svn_dirent_local_style(
+      SVN_ERR(svn_io__utf8_to_unicode_longpath(&w_final_abspath,
+                                               svn_dirent_local_style(
                                                           final_abspath,
                                                           scratch_pool),
-                                           NULL, scratch_pool));
+                                               scratch_pool));
       path_len = wcslen(w_final_abspath);
       rename_size = sizeof(*rename_info) + sizeof(WCHAR) * path_len;
 

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/utf8proc/utf8proc.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/utf8proc/utf8proc.h?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/utf8proc/utf8proc.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/utf8proc/utf8proc.h Thu Jun 18 10:35:30 2015
@@ -74,17 +74,17 @@
 # if _MSC_VER >= 1600
 #   include <stdint.h>
 # else
-    typedef signed char int8_t;
-    typedef unsigned char uint8_t;
-    typedef short int16_t;
-    typedef unsigned short uint16_t;
-    typedef int int32_t;
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
 # endif
 # if _MSC_VER >= 1800
 #   include <stdbool.h>
 # else
-    typedef unsigned char bool;
-    enum {false, true};
+typedef unsigned char bool;
+enum {false, true};
 # endif
 # ifdef _WIN64
 #   define ssize_t __int64

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/version.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/version.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/version.c Thu Jun 18 10:35:30 2015
@@ -40,11 +40,13 @@ svn_subr_version(void)
 svn_boolean_t svn_ver_compatible(const svn_version_t *my_version,
                                  const svn_version_t *lib_version)
 {
-  /* With normal development builds the matching rules are strict, to
-     avoid inadvertantly using the wrong libraries.  For backward
-     compatibility testing use --disable-full-version-match to
-     configure 1.7 and then the libraries that get built can be used
-     to replace those in 1.6 or earlier builds.  */
+  /* With normal development builds the matching rules are stricter
+     that for release builds, to avoid inadvertantly using the wrong
+     libraries.  For backward compatibility testing of development
+     builds one can use --disable-full-version-match to cause a
+     development build to use the release build rules.  This allows
+     the libraries from the newer development build to be used by an
+     older development build. */
 
 #ifndef SVN_DISABLE_FULL_VERSION_MATCH
   if (lib_version->tag[0] != '\0')
@@ -83,6 +85,11 @@ svn_ver_check_list2(const svn_version_t
   svn_error_t *err = SVN_NO_ERROR;
   int i;
 
+#ifdef SVN_DISABLE_FULL_VERSION_MATCH
+  /* Force more relaxed check for --disable-full-version-match. */
+  comparator = svn_ver_compatible;
+#endif
+
   for (i = 0; checklist[i].label != NULL; ++i)
     {
       const svn_version_t *lib_version = checklist[i].version_query();
@@ -136,7 +143,7 @@ svn_version_extended(svn_boolean_t verbo
   info->build_time = __TIME__;
   info->build_host = SVN_BUILD_HOST;
   info->copyright = apr_pstrdup
-    (pool, _("Copyright (C) 2014 The Apache Software Foundation.\n"
+    (pool, _("Copyright (C) 2015 The Apache Software Foundation.\n"
              "This software consists of contributions made by many people;\n"
              "see the NOTICE file for more information.\n"
              "Subversion is open source software, see "

Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c?rev=1686174&r1=1686173&r2=1686174&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c Thu Jun 18 10:35:30 2015
@@ -41,8 +41,7 @@ svn_x509_name_attr_dup(const svn_x509_na
 {
   svn_x509_name_attr_t *result = apr_palloc(result_pool, sizeof(*result));
   result->oid_len = attr->oid_len;
-  result->oid = apr_palloc(result_pool, result->oid_len);
-  memcpy(result->oid, attr->oid, result->oid_len);
+  result->oid = apr_pmemdup(result_pool, attr->oid, attr->oid_len);
   result->utf8_value = apr_pstrdup(result_pool, attr->utf8_value);
 
   return result;



Mime
View raw message