subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1632906 [5/10] - in /subversion/branches/revprop-caching-ng: ./ build/ notes/ subversion/bindings/ctypes-python/ subversion/bindings/cxxhl/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_delta/ ...
Date Sun, 19 Oct 2014 13:55:38 GMT
Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_fs/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_fs_fs/verify.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_fs_fs/verify.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_fs_fs/verify.c Sun Oct 19 13:55:35 2014
@@ -159,6 +159,93 @@ verify_rep_cache(svn_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Verify that the MD5 checksum of the data between offsets START and END
+ * in FILE matches the EXPECTED checksum.  If there is a mismatch use the
+ * indedx NAME in the error message.  Supports cancellation with CANCEL_FUNC
+ * and CANCEL_BATON.  SCRATCH_POOL is for temporary allocations. */
+static svn_error_t *
+verify_index_checksum(apr_file_t *file,
+                      const char *name,
+                      apr_off_t start,
+                      apr_off_t end,
+                      svn_checksum_t *expected,
+                      svn_cancel_func_t cancel_func,
+                      void *cancel_baton,
+                      apr_pool_t *scratch_pool)
+{
+  unsigned char buffer[SVN__STREAM_CHUNK_SIZE];
+  apr_off_t size = end - start;
+  svn_checksum_t *actual;
+  svn_checksum_ctx_t *context
+    = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool);
+
+  /* Calculate the index checksum. */
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &start, scratch_pool));
+  while (size > 0)
+    {
+      apr_size_t to_read = size > sizeof(buffer)
+                         ? sizeof(buffer)
+                         : (apr_size_t)size;
+      SVN_ERR(svn_io_file_read_full2(file, buffer, to_read, NULL, NULL,
+                                     scratch_pool));
+      SVN_ERR(svn_checksum_update(context, buffer, to_read));
+      size -= to_read;
+
+      if (cancel_func)
+        SVN_ERR(cancel_func(cancel_baton));
+    }
+
+  SVN_ERR(svn_checksum_final(&actual, context, scratch_pool));
+
+  /* Verify that it matches the expected checksum. */
+  if (!svn_checksum_match(expected, actual))
+    {
+      const char *file_name;
+
+      SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool));
+      SVN_ERR(svn_checksum_mismatch_err(expected, actual, scratch_pool, 
+                                        _("%s checksum mismatch in file %s"),
+                                        name, file_name));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Verify the MD5 checksums of the index data in the rev / pack file
+ * containing revision START in FS.  If given, invoke CANCEL_FUNC with
+ * CANCEL_BATON at regular intervals.  Use SCRATCH_POOL for temporary
+ * allocations.
+ */
+static svn_error_t *
+verify_index_checksums(svn_fs_t *fs,
+                       svn_revnum_t start,
+                       svn_cancel_func_t cancel_func,
+                       void *cancel_baton,
+                       apr_pool_t *scratch_pool)
+{
+  svn_fs_fs__revision_file_t *rev_file;
+
+  /* Open the rev / pack file and read the footer */
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, start,
+                                           scratch_pool, scratch_pool));
+  SVN_ERR(svn_fs_fs__auto_read_footer(rev_file));
+
+  /* Verify the index contents against the checksum from the footer. */
+  SVN_ERR(verify_index_checksum(rev_file->file, "L2P index",
+                                rev_file->l2p_offset, rev_file->p2l_offset,
+                                rev_file->l2p_checksum,
+                                cancel_func, cancel_baton, scratch_pool));
+  SVN_ERR(verify_index_checksum(rev_file->file, "P2L index",
+                                rev_file->p2l_offset, rev_file->footer_offset,
+                                rev_file->p2l_checksum,
+                                cancel_func, cancel_baton, scratch_pool));
+
+  /* Done. */
+  SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
+
+  return SVN_NO_ERROR;
+}
+
 /* Verify that for all log-to-phys index entries for revisions START to
  * START + COUNT-1 in FS there is a consistent entry in the phys-to-log
  * index.  If given, invoke CANCEL_FUNC with CANCEL_BATON at regular
@@ -182,7 +269,8 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
                                            iterpool));
 
   /* determine the range of items to check for each revision */
-  SVN_ERR(svn_fs_fs__l2p_get_max_ids(&max_ids, fs, start, count, pool));
+  SVN_ERR(svn_fs_fs__l2p_get_max_ids(&max_ids, fs, start, count, pool,
+                                     iterpool));
 
   /* check all items in all revisions if the given range */
   for (i = 0; i < max_ids->nelts; ++i)
@@ -205,10 +293,11 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
 
           /* find the corresponding P2L entry */
           SVN_ERR(svn_fs_fs__p2l_entry_lookup(&p2l_entry, fs, rev_file,
-                                              revision, offset, iterpool));
+                                              revision, offset, iterpool,
+                                              iterpool));
 
           if (p2l_entry == NULL)
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+            return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                      NULL,
                                      _("p2l index entry not found for "
                                        "PHYS %s returned by "
@@ -218,7 +307,7 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
 
           if (   p2l_entry->item.number != k
               || p2l_entry->item.revision != revision)
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+            return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                      NULL,
                                      _("p2l index info LOG r%ld:i%ld"
                                        " does not match "
@@ -282,9 +371,9 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
       /* get all entries for the current block */
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, rev_file, start,
                                           offset, ffd->p2l_page_size,
-                                          iterpool));
+                                          iterpool, iterpool));
       if (entries->nelts == 0)
-        return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_CORRUPTION,
+        return svn_error_createf(SVN_ERR_FS_INDEX_CORRUPTION,
                                  NULL,
                                  _("p2l does not cover offset %s"
                                    " for revision %ld"),
@@ -301,7 +390,24 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
             = &APR_ARRAY_IDX(entries, i, svn_fs_fs__p2l_entry_t);
 
           /* check all sub-items for consist entries in the L2P index */
-          if (entry->type != SVN_FS_FS__ITEM_TYPE_UNUSED)
+          if (entry->type == SVN_FS_FS__ITEM_TYPE_UNUSED)
+            {
+              /* There is no L2P entry for unused rev file sections.
+               * And its P2L index data is hardly ever used.  But we
+               * should still check whether someone tempered with it. */
+              if (   entry->item.revision != SVN_INVALID_REVNUM
+                  && (   entry->item.revision < start
+                      || entry->item.revision >= start + count))
+                return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
+                                         NULL,
+                                         _("Empty P2L entry for PHYS %s "
+                                           "refers to revision %ld outside "
+                                           "the rev / pack file (%ld-%ld)"),
+                                         apr_off_t_toa(pool, entry->offset),
+                                         entry->item.number,
+                                         start, start + count - 1);
+            }
+          else
             {
               apr_off_t l2p_offset;
               SVN_ERR(svn_fs_fs__item_offset(&l2p_offset, fs, rev_file,
@@ -309,7 +415,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
                                              entry->item.number, iterpool));
 
               if (l2p_offset != entry->offset)
-                return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+                return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                          NULL,
                                          _("l2p index entry PHYS %s"
                                            "does not match p2l index value "
@@ -416,7 +522,7 @@ expected_checksum(apr_file_t *file,
 
       SVN_ERR(svn_io_file_name_get(&file_name, file, pool));
       return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                               _("Checksum mismatch item at offset %s of "
+                               _("Checksum mismatch in item at offset %s of "
                                  "length %s bytes in file %s"),
                                apr_off_t_toa(pool, entry->offset),
                                apr_off_t_toa(pool, entry->size), file_name);
@@ -511,7 +617,7 @@ compare_p2l_to_rev(svn_fs_t *fs,
                                         pool));
 
   if (rev_file->l2p_offset != max_offset)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT, NULL,
+    return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT, NULL,
                              _("File size of %s for revision r%ld does "
                                "not match p2l index size of %s"),
                              apr_off_t_toa(pool, rev_file->l2p_offset), start,
@@ -532,7 +638,12 @@ compare_p2l_to_rev(svn_fs_t *fs,
       /* get all entries for the current block */
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, rev_file, start,
                                           offset, ffd->p2l_page_size,
-                                          iterpool));
+                                          iterpool, iterpool));
+
+      /* The above might have moved the file pointer.
+       * Ensure we actually start reading at OFFSET.  */
+      SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size,
+                                       NULL, offset, iterpool));
 
       /* process all entries (and later continue with the next block) */
       for (i = 0; i < entries->nelts; ++i)
@@ -550,7 +661,7 @@ compare_p2l_to_rev(svn_fs_t *fs,
 
           /* p2l index must cover all rev / pack file offsets exactly once */
           if (entry->offset != offset)
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+            return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                      NULL,
                                      _("p2l index entry for revision r%ld"
                                        " is non-contiguous between offsets "
@@ -566,7 +677,7 @@ compare_p2l_to_rev(svn_fs_t *fs,
               if (entry->offset != max_offset)
                 SVN_ERR(read_all_nul(rev_file->file, entry->size, pool));
             }
-          else if (entry->fnv1_checksum)
+          else
             {
               if (entry->size < STREAM_THRESHOLD)
                 SVN_ERR(expected_buffered_checksum(rev_file->file, entry,
@@ -592,16 +703,6 @@ compare_p2l_to_rev(svn_fs_t *fs,
 }
 
 static svn_revnum_t
-packed_base_rev(svn_fs_t *fs, svn_revnum_t rev)
-{
-  fs_fs_data_t *ffd = fs->fsap_data;
-
-  return rev < ffd->min_unpacked_rev
-       ? rev - (rev % ffd->max_files_per_dir)
-       : rev;
-}
-
-static svn_revnum_t
 pack_size(svn_fs_t *fs, svn_revnum_t rev)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -635,7 +736,7 @@ verify_index_consistency(svn_fs_t *fs,
       svn_error_t *err = SVN_NO_ERROR;
 
       svn_revnum_t count = pack_size(fs, revision);
-      svn_revnum_t pack_start = packed_base_rev(fs, revision);
+      svn_revnum_t pack_start = svn_fs_fs__packed_base_rev(fs, revision);
       svn_revnum_t pack_end = pack_start + count;
 
       svn_pool_clear(iterpool);
@@ -643,9 +744,14 @@ verify_index_consistency(svn_fs_t *fs,
       if (notify_func && (pack_start % ffd->max_files_per_dir == 0))
         notify_func(pack_start, notify_baton, iterpool);
 
+      /* Check for external corruption to the indexes. */
+      err = verify_index_checksums(fs, pack_start, cancel_func,
+                                   cancel_baton, iterpool);
+ 
       /* two-way index check */
-      err = compare_l2p_to_p2l_index(fs, pack_start, pack_end - pack_start,
-                                     cancel_func, cancel_baton, iterpool);
+      if (!err)
+        err = compare_l2p_to_p2l_index(fs, pack_start, pack_end - pack_start,
+                                       cancel_func, cancel_baton, iterpool);
       if (!err)
         err = compare_p2l_to_l2p_index(fs, pack_start, pack_end - pack_start,
                                        cancel_func, cancel_baton, iterpool);
@@ -668,7 +774,7 @@ verify_index_consistency(svn_fs_t *fs,
 
           /* We could simply assign revision here but the code below is
              more intuitive to maintainers. */
-          next_revision = packed_base_rev(fs, revision);
+          next_revision = svn_fs_fs__packed_base_rev(fs, revision);
         }
       else
         {

Propchange: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged /subversion/trunk/subversion/libsvn_fs_fs:r1631115,1631171,1631180
  Merged /subversion/trunk/subversion/libsvn_fs_x:r1619780-1632905

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/cached_data.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/cached_data.c Sun Oct 19 13:55:35 2014
@@ -772,13 +772,18 @@ svn_fs_x__rep_chain_length(int *chain_le
   svn_revnum_t shard_size = ffd->max_files_per_dir
                           ? ffd->max_files_per_dir
                           : 1;
-  apr_pool_t *sub_pool = svn_pool_create(pool);
   svn_boolean_t is_delta = FALSE;
   int count = 0;
   int shards = 1;
   svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set);
   svn_revnum_t last_shard = revision / shard_size;
-  
+
+  /* Note that this iteration pool will be used in a non-standard way.
+   * To reuse open file handles between iterations (e.g. while within the
+   * same pack file), we only clear this pool once in a while instead of
+   * at the start of each iteration. */
+  apr_pool_t *iterpool = svn_pool_create(pool);
+
   /* Check whether the length of the deltification chain is acceptable.
    * Otherwise, shared reps may form a non-skipping delta chain in
    * extreme cases. */
@@ -806,7 +811,7 @@ svn_fs_x__rep_chain_length(int *chain_le
                                     &file_hint,
                                     &base_rep,
                                     fs,
-                                    sub_pool));
+                                    iterpool));
 
       base_rep.id.change_set
         = svn_fs_x__change_set_by_rev(header->base_revision);
@@ -814,18 +819,28 @@ svn_fs_x__rep_chain_length(int *chain_le
       base_rep.size = header->base_length;
       is_delta = header->type == svn_fs_x__rep_delta;
 
+      /* Clear it the ITERPOOL once in a while.  Doing it too frequently
+       * renders the FILE_HINT ineffective.  Doing too infrequently, may
+       * leave us with too many open file handles.
+       *
+       * Note that this is mostly about efficiency, with larger values
+       * being more efficient, and any non-zero value is legal here.  When
+       * reading deltified contents, we may keep 10s of rev files open at
+       * the same time and the system has to cope with that.  Thus, the
+       * limit of 16 chosen below is in the same ballpark.
+       */
       ++count;
       if (count % 16 == 0)
         {
           file_hint = NULL;
-          svn_pool_clear(sub_pool);
+          svn_pool_clear(iterpool);
         }
     }
   while (is_delta && base_rep.id.change_set);
 
   *chain_length = count;
   *shard_count = shards;
-  svn_pool_destroy(sub_pool);
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -3116,7 +3131,7 @@ block_read(void **result,
               key.revision = svn_fs_x__get_revnum(entry->items[0].change_set);
               key.second = entry->items[0].number;
 
-              SVN_ERR(svn_io_file_seek(revision_file, SEEK_SET,
+              SVN_ERR(svn_io_file_seek(revision_file, APR_SET,
                                        &entry->offset, iterpool));
               switch (entry->type)
                 {

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/index.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/index.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/index.c Sun Oct 19 13:55:35 2014
@@ -200,7 +200,7 @@ stream_error_create(packed_number_stream
   apr_off_t offset = 0;
   SVN_ERR(svn_io_file_name_get(&file_name, stream->file,
                                stream->pool));
-  SVN_ERR(svn_io_file_seek(stream->file, SEEK_CUR, &offset, stream->pool));
+  SVN_ERR(svn_io_file_seek(stream->file, APR_CUR, &offset, stream->pool));
 
   return svn_error_createf(err, NULL, message, file_name,
                            (apr_uint64_t)offset);
@@ -292,7 +292,7 @@ packed_stream_read(packed_number_stream_
           /* let's catch corrupted data early.  It would surely cause
            * havoc further down the line. */
           if SVN__PREDICT_FALSE(shift > 8 * sizeof(value))
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_CORRUPTION, NULL,
+            return svn_error_createf(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                                      _("Corrupt index: number too large"));
        }
     }
@@ -718,7 +718,7 @@ svn_fs_x__l2p_index_create(svn_fs_t *fs,
   /* Paranoia check that makes later casting to int32 safe.
    * The current implementation is limited to 2G entries per page. */
   if (ffd->l2p_page_size > APR_INT32_MAX)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+    return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
                             _("L2P index page size  %s" 
                               " exceeds current limit of 2G entries"),
                             apr_psprintf(local_pool, "%" APR_UINT64_T_FMT,
@@ -781,7 +781,7 @@ svn_fs_x__l2p_index_create(svn_fs_t *fs,
           l2p_page_entry_t page_entry = { 0 };
 
           if (proto_entry.item_index > APR_INT32_MAX)
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+            return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
                                     _("Item index %s too large "
                                       "in l2p proto index for revision %ld"),
                                     apr_psprintf(local_pool,
@@ -808,7 +808,7 @@ svn_fs_x__l2p_index_create(svn_fs_t *fs,
   /* Paranoia check that makes later casting to int32 safe.
    * The current implementation is limited to 2G pages per index. */
   if (page_counts->nelts > APR_INT32_MAX)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+    return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
                             _("L2P index page count  %d"
                               " exceeds current limit of 2G pages"),
                             page_counts->nelts);
@@ -915,7 +915,7 @@ l2p_header_copy(l2p_page_info_baton_t *b
   /* revision offset within the index file */
   apr_size_t rel_revision = baton->revision - header->first_revision;
   if (rel_revision >= header->revision_count)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_REVISION , NULL,
+    return svn_error_createf(SVN_ERR_FS_INDEX_REVISION , NULL,
                              _("Revision %ld not covered by item index"),
                              baton->revision);
 
@@ -941,7 +941,7 @@ l2p_header_copy(l2p_page_info_baton_t *b
       max_item_index =   (apr_uint64_t)header->page_size
                        * (last_entry - first_entry);
       if (baton->item_index >= max_item_index)
-        return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+        return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
                                 _("Item index %s exceeds l2p limit "
                                   "of %s for revision %ld"),
                                 apr_psprintf(scratch_pool,
@@ -1070,7 +1070,7 @@ get_l2p_header_body(l2p_header_t **heade
 
   if (result->first_revision > revision
       || result->first_revision + result->revision_count <= revision)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_CORRUPTION, NULL,
+    return svn_error_createf(SVN_ERR_FS_INDEX_CORRUPTION, NULL,
                       _("Corrupt L2P index for r%ld only covers r%ld:%ld"),
                       revision, result->first_revision,
                       result->first_revision + result->revision_count);
@@ -1292,7 +1292,7 @@ l2p_page_get_offset(l2p_page_baton_t *ba
 {
   /* overflow check */
   if (page->entry_count <= baton->page_offset)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+    return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
                              _("Item index %s too large in"
                                " revision %ld"),
                              apr_psprintf(pool, "%" APR_UINT64_T_FMT,
@@ -1843,7 +1843,7 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
      = svn_spillbuf__create(0x10000, 0x1000000, local_pool);
 
   /* for loop temps ... */
-  apr_pool_t *iter_pool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(pool);
 
   /* start at the beginning of the source file */
   SVN_ERR(svn_io_file_open(&proto_index, proto_file_name,
@@ -1861,20 +1861,20 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
       svn_revnum_t last_revision = revision;
       apr_uint64_t last_number = 0;
 
-      svn_pool_clear(iter_pool);
+      svn_pool_clear(iterpool);
 
       /* (attempt to) read the next entry from the source */
       SVN_ERR(svn_io_file_read_full2(proto_index, &entry, sizeof(entry),
-                                     &read, &eof, iter_pool));
+                                     &read, &eof, iterpool));
       SVN_ERR_ASSERT(eof || read == sizeof(entry));
 
       if (entry.item_count && !eof)
         {
           to_read = entry.item_count * sizeof(*entry.items);
-          entry.items = apr_palloc(iter_pool, to_read);
+          entry.items = apr_palloc(iterpool, to_read);
 
           SVN_ERR(svn_io_file_read_full2(proto_index, entry.items, to_read,
-                                         &read, &eof, iter_pool));
+                                         &read, &eof, iterpool));
           SVN_ERR_ASSERT(eof || read == to_read);
         }
 
@@ -1884,7 +1884,7 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
           apr_size_t entry_size;
           to_read = sizeof(entry_size);
           SVN_ERR(svn_io_file_read_full2(proto_index, &entry_size, to_read,
-                                         &read, &eof, iter_pool));
+                                         &read, &eof, iterpool));
           SVN_ERR_ASSERT(eof || read == to_read);
         }
 
@@ -1925,20 +1925,20 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
         {
           SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded,
                                       encode_uint(encoded, entry.offset),
-                                      iter_pool));
+                                      iterpool));
           last_revision = revision;
         }
 
       /* write simple item / container entry */
       SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded,
                                   encode_uint(encoded, entry.size),
-                                  iter_pool));
+                                  iterpool));
       SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded,
                                   encode_uint(encoded, entry.type + entry.item_count * 16),
-                                  iter_pool));
+                                  iterpool));
       SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded,
                                   encode_uint(encoded, entry.fnv1_checksum),
-                                  iter_pool));
+                                  iterpool));
 
       /* container contents (only one for non-container items) */
       for (sub_item = 0; sub_item < entry.item_count; ++sub_item)
@@ -1948,7 +1948,7 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
           apr_int64_t diff = item_rev - last_revision;
           SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded,
                                       encode_int(encoded, diff),
-                                      iter_pool));
+                                      iterpool));
           last_revision = item_rev;
         }
 
@@ -1957,7 +1957,7 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
           apr_int64_t diff = entry.items[sub_item].number - last_number;
           SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded,
                                       encode_int(encoded, diff),
-                                      iter_pool));
+                                      iterpool));
           last_number = entry.items[sub_item].number;
         }
 
@@ -2007,7 +2007,7 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
   SVN_ERR(svn_io_file_close(index_file, local_pool));
   SVN_ERR(svn_io_set_file_read_only(file_name, FALSE, local_pool));
 
-  svn_pool_destroy(iter_pool);
+  svn_pool_destroy(iterpool);
   svn_pool_destroy(local_pool);
 
   return SVN_NO_ERROR;
@@ -2438,7 +2438,7 @@ get_p2l_keys(p2l_page_info_baton_t *page
   if (page_info.page_count <= page_info.page_no)
     {
       SVN_ERR(packed_stream_close(*stream));
-      return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+      return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
                                _("Offset %s too large in revision %ld"),
                                apr_off_t_toa(pool, offset), revision);
     }

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/noderevs.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/noderevs.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/noderevs.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/noderevs.c Sun Oct 19 13:55:35 2014
@@ -60,8 +60,6 @@ typedef struct binary_id_t
 } binary_id_t;
 
 /* Our internal representation of an representation.
- * We simply omit the uniquifier, which allows us to share instances of
- * binary_representation_t and uniquify them in a shared_representation_t.
  */
 typedef struct binary_representation_t
 {

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/pack.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/pack.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/pack.c Sun Oct 19 13:55:35 2014
@@ -483,7 +483,7 @@ copy_item_to_temp(pack_context_t *contex
   svn_fs_x__p2l_entry_t *new_entry
     = svn_fs_x__p2l_entry_dup(entry, context->info_pool);
   new_entry->offset = 0;
-  SVN_ERR(svn_io_file_seek(temp_file, SEEK_CUR, &new_entry->offset, pool));
+  SVN_ERR(svn_io_file_seek(temp_file, APR_CUR, &new_entry->offset, pool));
   APR_ARRAY_PUSH(entries, svn_fs_x__p2l_entry_t *) = new_entry;
   
   SVN_ERR(copy_file_data(context, temp_file, rev_file, entry->size, pool));
@@ -573,7 +573,7 @@ copy_rep_to_temp(pack_context_t *context
    * store it in CONTEXT */
   entry = svn_fs_x__p2l_entry_dup(entry, context->info_pool);
   entry->offset = 0;
-  SVN_ERR(svn_io_file_seek(context->reps_file, SEEK_CUR, &entry->offset,
+  SVN_ERR(svn_io_file_seek(context->reps_file, APR_CUR, &entry->offset,
                            pool));
   add_item_rep_mapping(context, entry);
 
@@ -596,7 +596,7 @@ copy_rep_to_temp(pack_context_t *context
     }
 
   /* copy the whole rep (including header!) to our temp file */
-  SVN_ERR(svn_io_file_seek(rev_file, SEEK_SET, &source_offset, pool));
+  SVN_ERR(svn_io_file_seek(rev_file, APR_SET, &source_offset, pool));
   SVN_ERR(copy_file_data(context, context->reps_file, rev_file, entry->size,
                          pool));
 
@@ -699,12 +699,12 @@ copy_node_to_temp(pack_context_t *contex
    * store it in CONTEXT */
   entry = svn_fs_x__p2l_entry_dup(entry, context->info_pool);
   entry->offset = 0;
-  SVN_ERR(svn_io_file_seek(context->reps_file, SEEK_CUR,
+  SVN_ERR(svn_io_file_seek(context->reps_file, APR_CUR,
                            &entry->offset, pool));
   add_item_rep_mapping(context, entry);
 
   /* copy the noderev to our temp file */
-  SVN_ERR(svn_io_file_seek(rev_file, SEEK_SET, &source_offset, pool));
+  SVN_ERR(svn_io_file_seek(rev_file, APR_SET, &source_offset, pool));
   SVN_ERR(copy_file_data(context, context->reps_file, rev_file, entry->size,
                          pool));
 
@@ -1245,7 +1245,7 @@ write_reps_container(pack_context_t *con
 
   SVN_ERR(svn_fs_x__write_reps_container(pack_stream, container, pool));
   SVN_ERR(svn_stream_close(pack_stream));
-  SVN_ERR(svn_io_file_seek(context->pack_file, SEEK_CUR, &offset, pool));
+  SVN_ERR(svn_io_file_seek(context->pack_file, APR_CUR, &offset, pool));
 
   container_entry.offset = context->pack_offset;
   container_entry.size = offset - container_entry.offset;
@@ -1327,7 +1327,7 @@ write_reps_containers(pack_context_t *co
 
       /* select the change list in the source file, parse it and add it to
        * the container */
-      SVN_ERR(svn_io_file_seek(temp_file, SEEK_SET, &entry->offset,
+      SVN_ERR(svn_io_file_seek(temp_file, APR_SET, &entry->offset,
                                iterpool));
       SVN_ERR(svn_fs_x__get_representation_length(&representation.size,
                                              &representation.expanded_size,
@@ -1414,7 +1414,7 @@ store_items(pack_context_t *context,
 
       /* select the item in the source file and copy it into the target
        * pack file */
-      SVN_ERR(svn_io_file_seek(temp_file, SEEK_SET, &entry->offset,
+      SVN_ERR(svn_io_file_seek(temp_file, APR_SET, &entry->offset,
                                iterpool));
       SVN_ERR(copy_file_data(context, context->pack_file, temp_file,
                              entry->size, iterpool));
@@ -1558,7 +1558,7 @@ write_changes_container(pack_context_t *
                                              container,
                                              pool));
   SVN_ERR(svn_stream_close(pack_stream));
-  SVN_ERR(svn_io_file_seek(context->pack_file, SEEK_CUR, &offset, pool));
+  SVN_ERR(svn_io_file_seek(context->pack_file, APR_CUR, &offset, pool));
 
   container_entry.offset = context->pack_offset;
   container_entry.size = offset - container_entry.offset;
@@ -1654,7 +1654,7 @@ write_changes_containers(pack_context_t 
 
       /* select the change list in the source file, parse it and add it to
        * the container */
-      SVN_ERR(svn_io_file_seek(temp_file, SEEK_SET, &entry->offset,
+      SVN_ERR(svn_io_file_seek(temp_file, APR_SET, &entry->offset,
                                iterpool));
       SVN_ERR(svn_fs_x__read_changes(&changes, temp_stream, iterpool));
       SVN_ERR(svn_fs_x__changes_append_list(&list_index, container, changes));
@@ -1880,7 +1880,7 @@ pack_range(pack_context_t *context,
               offset = entry->offset;
               if (offset < finfo.size)
                 {
-                  SVN_ERR(svn_io_file_seek(rev_file, SEEK_SET, &offset,
+                  SVN_ERR(svn_io_file_seek(rev_file, APR_SET, &offset,
                                            iterpool));
 
                   if (entry->type == SVN_FS_X__ITEM_TYPE_CHANGES)

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/transaction.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/transaction.c Sun Oct 19 13:55:35 2014
@@ -649,7 +649,7 @@ auto_truncate_proto_rev(svn_fs_t *fs,
   if (indexed_length < actual_length)
     SVN_ERR(svn_io_file_trunc(proto_rev, indexed_length, pool));
   else if (indexed_length > actual_length)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+    return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                              NULL,
                              _("p2l proto index offset %s beyond proto"
                                "rev file size %s for TXN %s"),
@@ -857,47 +857,37 @@ unparse_dir_entries(apr_array_header_t *
   return SVN_NO_ERROR;
 }
 
-/* Copy the contents of NEW_CHANGE into OLD_CHANGE assuming that both
-   belong to the same path.  Allocate copies in POOL.
+/* Return a deep copy of SOURCE and allocate it in RESULT_POOL.
  */
-static void
-replace_change(svn_fs_path_change2_t *old_change,
-               const svn_fs_path_change2_t *new_change,
-               apr_pool_t *pool)
-{
-  /* An add at this point must be following a previous delete,
-      so treat it just like a replace. */
-  old_change->node_kind = new_change->node_kind;
-  old_change->node_rev_id = svn_fs_x__id_copy(new_change->node_rev_id, pool);
-  old_change->text_mod = new_change->text_mod;
-  old_change->prop_mod = new_change->prop_mod;
-  old_change->mergeinfo_mod = new_change->mergeinfo_mod;
-  if (new_change->copyfrom_rev == SVN_INVALID_REVNUM)
-    {
-      old_change->copyfrom_rev = SVN_INVALID_REVNUM;
-      old_change->copyfrom_path = NULL;
-    }
-  else
-    {
-      old_change->copyfrom_rev = new_change->copyfrom_rev;
-      old_change->copyfrom_path = apr_pstrdup(pool,
-                                              new_change->copyfrom_path);
-    }
+static svn_fs_path_change2_t *
+path_change_dup(const svn_fs_path_change2_t *source,
+                apr_pool_t *result_pool)
+{
+  svn_fs_path_change2_t *result = apr_pmemdup(result_pool, source,
+                                              sizeof(*source));
+  result->node_rev_id = svn_fs_x__id_copy(source->node_rev_id, result_pool);
+  if (source->copyfrom_path)
+    result->copyfrom_path = apr_pstrdup(result_pool, source->copyfrom_path);
+
+  return result;
 }
 
 /* Merge the internal-use-only CHANGE into a hash of public-FS
-   svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
-   single summarical (is that real word?) change per path.  */
+   svn_fs_path_change2_t CHANGED_PATHS, collapsing multiple changes into a
+   single summarical (is that real word?) change per path.  DELETIONS is
+   also a path->svn_fs_path_change2_t hash and contains all the deletions
+   that got turned into a replacement. */
 static svn_error_t *
-fold_change(apr_hash_t *changes,
+fold_change(apr_hash_t *changed_paths,
+            apr_hash_t *deletions,
             const change_t *change)
 {
-  apr_pool_t *pool = apr_hash_pool_get(changes);
+  apr_pool_t *pool = apr_hash_pool_get(changed_paths);
   svn_fs_path_change2_t *old_change, *new_change;
   const svn_string_t *path = &change->path;
   const svn_fs_path_change2_t *info = &change->info;
 
-  if ((old_change = apr_hash_get(changes, path->data, path->len)))
+  if ((old_change = apr_hash_get(changed_paths, path->data, path->len)))
     {
       /* This path already exists in the hash, so we have to merge
          this change into the already existing one. */
@@ -921,7 +911,7 @@ fold_change(apr_hash_t *changes,
            _("Invalid change ordering: new node revision ID "
              "without delete"));
 
-      /* Sanity check: an add, replacement, move, or reset must be the first
+      /* Sanity check: an add, replacement, or reset must be the first
          thing to follow a deletion. */
       if ((old_change->change_kind == svn_fs_path_change_delete)
           && (! ((info->change_kind == svn_fs_path_change_replace)
@@ -946,7 +936,7 @@ fold_change(apr_hash_t *changes,
         case svn_fs_path_change_reset:
           /* A reset here will simply remove the path change from the
              hash. */
-          old_change = NULL;
+          apr_hash_set(changed_paths, path->data, path->len, NULL);
           break;
 
         case svn_fs_path_change_delete:
@@ -954,60 +944,65 @@ fold_change(apr_hash_t *changes,
             {
               /* If the path was introduced in this transaction via an
                  add, and we are deleting it, just remove the path
-                 altogether. */
-              old_change = NULL;
+                 altogether.  (The caller will delete any child paths.) */
+              apr_hash_set(changed_paths, path->data, path->len, NULL);
+            }
+          else if (old_change->change_kind == svn_fs_path_change_replace)
+            {
+              /* A deleting a 'replace' restore the original deletion. */
+              new_change = apr_hash_get(deletions, path->data, path->len);
+              SVN_ERR_ASSERT(new_change);
+              apr_hash_set(changed_paths, path->data, path->len, new_change);
             }
           else
             {
-              /* A deletion overrules all previous changes. */
-              old_change->change_kind = svn_fs_path_change_delete;
-              old_change->text_mod = info->text_mod;
-              old_change->prop_mod = info->prop_mod;
-              old_change->mergeinfo_mod = info->mergeinfo_mod;
-              old_change->copyfrom_rev = SVN_INVALID_REVNUM;
-              old_change->copyfrom_path = NULL;
+              /* A deletion overrules a previous change (modify). */
+              new_change = path_change_dup(info, pool);
+              apr_hash_set(changed_paths, path->data, path->len, new_change);
             }
           break;
 
         case svn_fs_path_change_add:
         case svn_fs_path_change_replace:
           /* An add at this point must be following a previous delete,
-             so treat it just like a replace. */
-          replace_change(old_change, info, pool);
-          old_change->change_kind = svn_fs_path_change_replace;
+             so treat it just like a replace.  Remember the original
+             deletion such that we are able to delete this path again
+             (the replacement may have changed node kind and id). */
+          new_change = path_change_dup(info, pool);
+          new_change->change_kind = svn_fs_path_change_replace;
+
+          apr_hash_set(changed_paths, path->data, path->len, new_change);
+
+          /* Remember the original change.
+           * Make sure to allocate the hash key in a durable pool. */
+          apr_hash_set(deletions,
+                       apr_pstrmemdup(apr_hash_pool_get(deletions),
+                                      path->data, path->len),
+                       path->len, old_change);
           break;
 
         case svn_fs_path_change_modify:
         default:
+          /* If the new change modifies some attribute of the node, set
+             the corresponding flag, whether it already was set or not.
+             Note: We do not reset a flag to FALSE if a change is undone. */
           if (info->text_mod)
             old_change->text_mod = TRUE;
           if (info->prop_mod)
             old_change->prop_mod = TRUE;
-          if (info->mergeinfo_mod)
+          if (info->mergeinfo_mod == svn_tristate_true)
             old_change->mergeinfo_mod = svn_tristate_true;
           break;
         }
-
-      /* remove old_change from the cache if it is no longer needed. */
-      if (old_change == NULL)
-        apr_hash_set(changes, path->data, path->len, NULL);
     }
   else
     {
-      /* This change is new to the hash, so make a new public change
-         structure from the internal one (in the hash's pool), and dup
-         the path into the hash's pool, too. */
-      new_change = apr_pmemdup(pool, info, sizeof(*new_change));
-      new_change->node_rev_id = svn_fs_x__id_copy(info->node_rev_id, pool);
-      if (info->copyfrom_path)
-        new_change->copyfrom_path = apr_pstrdup(pool, info->copyfrom_path);
-
       /* Add this path.  The API makes no guarantees that this (new) key
-        will not be retained.  Thus, we copy the key into the target pool
-        to ensure a proper lifetime.  */
-      apr_hash_set(changes,
+         will not be retained.  Thus, we copy the key into the target pool
+         to ensure a proper lifetime.  */
+      apr_hash_set(changed_paths,
                    apr_pstrmemdup(pool, path->data, path->len), path->len,
-                   new_change);
+                   path_change_dup(info, pool));
     }
 
   return SVN_NO_ERROR;
@@ -1016,13 +1011,14 @@ fold_change(apr_hash_t *changes,
 
 /* Examine all the changed path entries in CHANGES and store them in
    *CHANGED_PATHS.  Folding is done to remove redundant or unnecessary
-   data. Do all allocations in POOL. */
+   data. Use SCRATCH_POOL for temporary allocations. */
 static svn_error_t *
 process_changes(apr_hash_t *changed_paths,
                 apr_array_header_t *changes,
-                apr_pool_t *pool)
+                apr_pool_t *scratch_pool)
 {
-  apr_pool_t *iterpool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_t *deletions = svn_hash__make(scratch_pool);
   int i;
 
   /* Read in the changes one by one, folding them into our local hash
@@ -1035,7 +1031,7 @@ process_changes(apr_hash_t *changed_path
        */
       change_t *change = APR_ARRAY_IDX(changes, i, change_t *);
 
-      SVN_ERR(fold_change(changed_paths, change));
+      SVN_ERR(fold_change(changed_paths, deletions, change));
 
       /* Now, if our change was a deletion or replacement, we have to
          blow away any changes thus far on paths that are (or, were)
@@ -1513,7 +1509,7 @@ allocate_item_index(apr_uint64_t *item_i
   to_write = svn__ui64toa(buffer, *item_index + 1);
 
   /* write it back to disk */
-  SVN_ERR(svn_io_file_seek(file, SEEK_SET, &offset, pool));
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, pool));
   SVN_ERR(svn_io_file_write_full(file, buffer, to_write, NULL, pool));
   SVN_ERR(svn_io_file_close(file, pool));
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/verify.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/verify.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x/verify.c Sun Oct 19 13:55:35 2014
@@ -181,7 +181,7 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
                                             offset, sub_item, iterpool));
 
           if (p2l_item == NULL)
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+            return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                      NULL,
                                      _("p2l index entry not found for "
                                        "PHYS o%s:s%ld returned by "
@@ -190,7 +190,7 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
                                      (long)sub_item, revision, (long)k);
 
           if (!svn_fs_x__id_part_eq(&l2p_item, p2l_item))
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+            return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                      NULL,
                                      _("p2l index info LOG r%ld:i%ld"
                                        " does not match "
@@ -247,7 +247,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
       SVN_ERR(svn_fs_x__p2l_index_lookup(&entries, fs, start, offset,
                                          ffd->p2l_page_size, iterpool));
       if (entries->nelts == 0)
-        return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_CORRUPTION,
+        return svn_error_createf(SVN_ERR_FS_INDEX_CORRUPTION,
                                  NULL,
                                  _("p2l does not cover offset %s"
                                    " for revision %ld"),
@@ -277,7 +277,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
                                             p2l_item, iterpool));
 
               if (sub_item != k || l2p_offset != entry->offset)
-                return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+                return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                          NULL,
                                          _("l2p index entry PHYS o%s:s%ld "
                                            "does not match p2l index value "
@@ -478,7 +478,7 @@ compare_p2l_to_rev(svn_fs_t *fs,
   SVN_ERR(svn_fs_x__p2l_get_max_offset(&max_offset, fs, start, pool));
 
   if (offset != max_offset)
-    return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT, NULL,
+    return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT, NULL,
                              _("File size of %s for revision r%ld does "
                                "not match p2l index size of %s"),
                              apr_off_t_toa(pool, offset), start,
@@ -515,7 +515,7 @@ compare_p2l_to_rev(svn_fs_t *fs,
 
           /* p2l index must cover all rev / pack file offsets exactly once */
           if (entry->offset != offset)
-            return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
+            return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT,
                                      NULL,
                                      _("p2l index entry for revision r%ld"
                                        " is non-contiguous between offsets "

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/blame.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/blame.c Sun Oct 19 13:55:35 2014
@@ -302,9 +302,8 @@ create_file_revs_body(serf_bucket_t **bo
 
   if (blame_ctx->include_merged_revisions)
     {
-      svn_ra_serf__add_tag_buckets(buckets,
-                                   "S:include-merged-revisions", NULL,
-                                   alloc);
+      svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                         "S:include-merged-revisions", SVN_VA_NULL);
     }
 
   svn_ra_serf__add_tag_buckets(buckets,

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/commit.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/commit.c Sun Oct 19 13:55:35 2014
@@ -226,7 +226,8 @@ create_checkout_body(serf_bucket_t **bkt
 
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:href");
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:activity-set");
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:apply-to-version", NULL, alloc);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:apply-to-version", SVN_VA_NULL);
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:checkout");
 
   *bkt = body_bkt;

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/get_lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/get_lock.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/get_lock.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/get_lock.c Sun Oct 19 13:55:35 2014
@@ -243,7 +243,8 @@ create_getlock_body(serf_bucket_t **body
                                     "xmlns", "DAV:",
                                     SVN_VA_NULL);
   svn_ra_serf__add_open_tag_buckets(buckets, alloc, "prop", SVN_VA_NULL);
-  svn_ra_serf__add_tag_buckets(buckets, "lockdiscovery", NULL, alloc);
+  svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                     "lockdiscovery", SVN_VA_NULL);
   svn_ra_serf__add_close_tag_buckets(buckets, alloc, "prop");
   svn_ra_serf__add_close_tag_buckets(buckets, alloc, "propfind");
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/lock.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/lock.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/lock.c Sun Oct 19 13:55:35 2014
@@ -315,6 +315,19 @@ run_locks(svn_ra_serf__session_t *sess,
                   && !SVN_ERR_IS_UNLOCK_ERROR(err)
                   && !SVN_ERR_IS_LOCK_ERROR(err))
                 {
+                  /* If the error that we are going to report is just about the
+                     POST unlock hook, we should first report that the operation
+                     succeeded, or the repository and working copy will be
+                     out of sync... */
+
+                  if (lock_func &&
+                      err->apr_err == SVN_ERR_REPOS_POST_UNLOCK_HOOK_FAILED)
+                    {
+                      err = svn_error_compose_create(
+                                  err, lock_func(lock_baton, ctx->path, locking,
+                                                 NULL, NULL, ctx->pool));
+                    }
+
                   return svn_error_trace(err); /* Don't go through callbacks */
                 }
 
@@ -399,11 +412,11 @@ create_lock_body(serf_bucket_t **body_bk
                                     SVN_VA_NULL);
 
   svn_ra_serf__add_open_tag_buckets(buckets, alloc, "lockscope", SVN_VA_NULL);
-  svn_ra_serf__add_tag_buckets(buckets, "exclusive", NULL, alloc);
+  svn_ra_serf__add_empty_tag_buckets(buckets, alloc, "exclusive", SVN_VA_NULL);
   svn_ra_serf__add_close_tag_buckets(buckets, alloc, "lockscope");
 
   svn_ra_serf__add_open_tag_buckets(buckets, alloc, "locktype", SVN_VA_NULL);
-  svn_ra_serf__add_tag_buckets(buckets, "write", NULL, alloc);
+  svn_ra_serf__add_empty_tag_buckets(buckets, alloc, "write", SVN_VA_NULL);
   svn_ra_serf__add_close_tag_buckets(buckets, alloc, "locktype");
 
   if (ctx->lock->comment)

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/log.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/log.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/log.c Sun Oct 19 13:55:35 2014
@@ -442,23 +442,22 @@ create_log_body(serf_bucket_t **body_bkt
 
   if (log_ctx->changed_paths)
     {
-      svn_ra_serf__add_tag_buckets(buckets,
-                                   "S:discover-changed-paths", NULL,
-                                   alloc);
+      svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                         "S:discover-changed-paths",
+                                         SVN_VA_NULL);
     }
 
   if (log_ctx->strict_node_history)
     {
-      svn_ra_serf__add_tag_buckets(buckets,
-                                   "S:strict-node-history", NULL,
-                                   alloc);
+      svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                         "S:strict-node-history", SVN_VA_NULL);
     }
 
   if (log_ctx->include_merged_revisions)
     {
-      svn_ra_serf__add_tag_buckets(buckets,
-                                   "S:include-merged-revisions", NULL,
-                                   alloc);
+      svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                         "S:include-merged-revisions",
+                                         SVN_VA_NULL);
     }
 
   if (log_ctx->revprops)
@@ -473,16 +472,14 @@ create_log_body(serf_bucket_t **body_bkt
         }
       if (log_ctx->revprops->nelts == 0)
         {
-          svn_ra_serf__add_tag_buckets(buckets,
-                                       "S:no-revprops", NULL,
-                                       alloc);
+          svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                             "S:no-revprops", SVN_VA_NULL);
         }
     }
   else
     {
-      svn_ra_serf__add_tag_buckets(buckets,
-                                   "S:all-revprops", NULL,
-                                   alloc);
+      svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                         "S:all-revprops", SVN_VA_NULL);
     }
 
   if (log_ctx->paths)
@@ -497,9 +494,8 @@ create_log_body(serf_bucket_t **body_bkt
         }
     }
 
-  svn_ra_serf__add_tag_buckets(buckets,
-                               "S:encode-binary-props", NULL,
-                               alloc);
+  svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                     "S:encode-binary-props", SVN_VA_NULL);
 
   svn_ra_serf__add_close_tag_buckets(buckets, alloc,
                                      "S:log-report");

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/merge.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/merge.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/merge.c Sun Oct 19 13:55:35 2014
@@ -358,15 +358,22 @@ create_merge_body(serf_bucket_t **bkt,
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:href");
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:source");
 
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:no-auto-merge", NULL, alloc);
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:no-checkout", NULL, alloc);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:no-auto-merge", SVN_VA_NULL);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:no-checkout", SVN_VA_NULL);
 
   svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", SVN_VA_NULL);
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:checked-in", NULL, alloc);
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:" SVN_DAV__VERSION_NAME, NULL, alloc);
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:resourcetype", NULL, alloc);
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:" SVN_DAV__CREATIONDATE, NULL, alloc);
-  svn_ra_serf__add_tag_buckets(body_bkt, "D:creator-displayname", NULL, alloc);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:checked-in", SVN_VA_NULL);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:" SVN_DAV__VERSION_NAME, SVN_VA_NULL);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:resourcetype", SVN_VA_NULL);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:" SVN_DAV__CREATIONDATE, SVN_VA_NULL);
+  svn_ra_serf__add_empty_tag_buckets(body_bkt, alloc,
+                                     "D:creator-displayname", SVN_VA_NULL);
   svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
 
   merge_lock_token_list(ctx->lock_tokens, NULL, body_bkt, alloc, pool);

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/ra_serf.h?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/ra_serf.h Sun Oct 19 13:55:35 2014
@@ -144,13 +144,6 @@ struct svn_ra_serf__session_t {
      i.e. is there a (reverse) proxy that does not support them?  */
   svn_boolean_t detect_chunking;
 
-  /* Can serf use HTTP pipelining, or should it send requests one by one.
-     HTTP pipelining is enabled by default. The only known case where it should
-     be disabled is when the server triggers SSL renegotiations in the middle
-     of HTTP traffic on a connection, which OpenSSL currently doesn't handle
-     well. See serf issue #135. */
-  svn_boolean_t http_pipelining;
-
   /* Our Version-Controlled-Configuration; may be NULL until we know it. */
   const char *vcc_url;
 
@@ -899,6 +892,16 @@ svn_ra_serf__add_close_tag_buckets(serf_
                                    serf_bucket_alloc_t *bkt_alloc,
                                    const char *tag);
 
+/* Add the appropriate serf buckets to AGG_BUCKET representing the XML
+ * open tag with name TAG, and then immediately closes the tag using the />
+ * notation
+ */
+void
+svn_ra_serf__add_empty_tag_buckets(serf_bucket_t *agg_bucket,
+                                   serf_bucket_alloc_t *bkt_alloc,
+                                   const char *tag,
+                                   ...) SVN_NEEDS_SENTINEL_NULL;
+
 /*
  * Add the appropriate serf buckets to AGG_BUCKET with xml-escaped
  * version of DATA.

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/serf.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/serf.c Sun Oct 19 13:55:35 2014
@@ -244,12 +244,6 @@ load_config(svn_ra_serf__session_t *sess
                                   SVN_CONFIG_OPTION_HTTP_CHUNKED_REQUESTS,
                                   "auto", svn_tristate_unknown));
 
-  /* Should we use HTTP pipelining. */
-  SVN_ERR(svn_config_get_bool(config, &session->http_pipelining,
-                              SVN_CONFIG_SECTION_GLOBAL,
-                              SVN_CONFIG_OPTION_HTTP_PIPELINING,
-                              TRUE));
-
 #if SERF_VERSION_AT_LEAST(1, 4, 0) && !defined(SVN_SERF_NO_LOGGING)
   SVN_ERR(svn_config_get_int64(config, &log_components,
                                SVN_CONFIG_SECTION_GLOBAL,
@@ -317,12 +311,6 @@ load_config(svn_ra_serf__session_t *sess
                                       SVN_CONFIG_OPTION_HTTP_CHUNKED_REQUESTS,
                                       "auto", chunked_requests));
 
-      /* Should we use HTTP pipelining. */
-      SVN_ERR(svn_config_get_bool(config, &session->http_pipelining,
-                                  server_group,
-                                  SVN_CONFIG_OPTION_HTTP_PIPELINING,
-                                  session->http_pipelining));
-
 #if SERF_VERSION_AT_LEAST(1, 4, 0) && !defined(SVN_SERF_NO_LOGGING)
       SVN_ERR(svn_config_get_int64(config, &log_components,
                                    server_group,
@@ -582,10 +570,6 @@ svn_ra_serf__open(svn_ra_session_t *sess
   if (status)
     return svn_ra_serf__wrap_err(status, NULL);
 
-  if (!serf_sess->http_pipelining) {
-      serf_connection_set_max_outstanding_requests(serf_sess->conns[0]->conn, 1);
-  }
-
   /* Set the progress callback. */
   serf_context_set_progress_cb(serf_sess->context, svn_ra_serf__progress,
                                serf_sess);
@@ -787,10 +771,6 @@ ra_serf_dup_session(svn_ra_session_t *ne
   if (status)
     return svn_ra_serf__wrap_err(status, NULL);
 
-  if (!new_sess->http_pipelining) {
-      serf_connection_set_max_outstanding_requests(new_sess->conns[0]->conn, 1);
-  }
-
   /* Set the progress callback. */
   serf_context_set_progress_cb(new_sess->context, svn_ra_serf__progress,
                                new_sess);

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/update.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/update.c Sun Oct 19 13:55:35 2014
@@ -723,11 +723,6 @@ open_connection_if_needed(svn_ra_serf__s
       if (status)
         return svn_ra_serf__wrap_err(status, NULL);
 
-      if (!sess->http_pipelining) {
-          serf_connection_set_max_outstanding_requests(sess->conns[cur]->conn,
-                                                       1);
-      }
-
       sess->num_conns++;
     }
 
@@ -757,22 +752,45 @@ get_best_connection(report_context_t *ct
   if (ctx->report_received && (ctx->sess->max_connections > 2))
     first_conn = 0;
 
-  /* Currently, we just cycle connections.  In the future we could
-     store the number of pending requests on each connection, or
-     perform other heuristics, to achieve better connection usage.
-     (As an optimization, if there's only one available auxiliary
-     connection to use, don't bother doing all the cur_conn math --
-     just return that one connection.)  */
+  /* If there's only one available auxiliary connection to use, don't bother
+     doing all the cur_conn math -- just return that one connection.  */
   if (ctx->sess->num_conns - first_conn == 1)
     {
       conn = ctx->sess->conns[first_conn];
     }
   else
     {
+#if SERF_VERSION_AT_LEAST(1, 4, 0)
+      /* Often one connection is slower than others, e.g. because the server
+         process/thread has to do more work for the particular set of requests.
+         In the worst case, when REQUEST_COUNT_TO_RESUME requests are queued
+         on such a slow connection, ra_serf will completely stop sending
+         requests.
+
+         The method used here selects the connection with the least amount of
+         pending requests, thereby giving more work to lightly loaded server
+         processes.
+       */
+      unsigned int i, min = INT_MAX, best_conn = first_conn;
+      for (i = first_conn; i < ctx->sess->num_conns; i++)
+        {
+          serf_connection_t *sc = ctx->sess->conns[i]->conn;
+          unsigned int pending = serf_connection_pending_requests(sc);
+          if (pending < min)
+            {
+              min = pending;
+              best_conn = i;
+            }
+        }
+      conn = ctx->sess->conns[best_conn];
+#else
+    /* We don't know how many requests are pending per connection, so just 
+       cycle them. */
       conn = ctx->sess->conns[ctx->sess->cur_conn];
       ctx->sess->cur_conn++;
       if (ctx->sess->cur_conn >= ctx->sess->num_conns)
         ctx->sess->cur_conn = first_conn;
+#endif
     }
   return conn;
 }

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/xml.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_serf/xml.c Sun Oct 19 13:55:35 2014
@@ -324,6 +324,49 @@ svn_ra_serf__add_open_tag_buckets(serf_b
 }
 
 void
+svn_ra_serf__add_empty_tag_buckets(serf_bucket_t *agg_bucket,
+                                   serf_bucket_alloc_t *bkt_alloc,
+                                   const char *tag, ...)
+{
+  va_list ap;
+  const char *key;
+  serf_bucket_t *tmp;
+
+  tmp = SERF_BUCKET_SIMPLE_STRING_LEN("<", 1, bkt_alloc);
+  serf_bucket_aggregate_append(agg_bucket, tmp);
+
+  tmp = SERF_BUCKET_SIMPLE_STRING(tag, bkt_alloc);
+  serf_bucket_aggregate_append(agg_bucket, tmp);
+
+  va_start(ap, tag);
+  while ((key = va_arg(ap, char *)) != NULL)
+    {
+      const char *val = va_arg(ap, const char *);
+      if (val)
+        {
+          tmp = SERF_BUCKET_SIMPLE_STRING_LEN(" ", 1, bkt_alloc);
+          serf_bucket_aggregate_append(agg_bucket, tmp);
+
+          tmp = SERF_BUCKET_SIMPLE_STRING(key, bkt_alloc);
+          serf_bucket_aggregate_append(agg_bucket, tmp);
+
+          tmp = SERF_BUCKET_SIMPLE_STRING_LEN("=\"", 2, bkt_alloc);
+          serf_bucket_aggregate_append(agg_bucket, tmp);
+
+          tmp = SERF_BUCKET_SIMPLE_STRING(val, bkt_alloc);
+          serf_bucket_aggregate_append(agg_bucket, tmp);
+
+          tmp = SERF_BUCKET_SIMPLE_STRING_LEN("\"", 1, bkt_alloc);
+          serf_bucket_aggregate_append(agg_bucket, tmp);
+        }
+    }
+  va_end(ap);
+
+  tmp = SERF_BUCKET_SIMPLE_STRING_LEN("/>", 2, bkt_alloc);
+  serf_bucket_aggregate_append(agg_bucket, tmp);
+}
+
+void
 svn_ra_serf__add_close_tag_buckets(serf_bucket_t *agg_bucket,
                                    serf_bucket_alloc_t *bkt_alloc,
                                    const char *tag)

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_ra_svn/client.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_ra_svn/client.c Sun Oct 19 13:55:35 2014
@@ -368,15 +368,16 @@ ra_svn_get_reporter(svn_ra_svn__session_
 
 /* --- RA LAYER IMPLEMENTATION --- */
 
-/* (Note: *ARGV is an output parameter.) */
+/* (Note: *ARGV_P is an output parameter.) */
 static svn_error_t *find_tunnel_agent(const char *tunnel,
                                       const char *hostinfo,
-                                      const char ***argv,
+                                      const char ***argv_p,
                                       apr_hash_t *config, apr_pool_t *pool)
 {
   svn_config_t *cfg;
   const char *val, *var, *cmd;
   char **cmd_argv;
+  const char **argv;
   apr_size_t len;
   apr_status_t status;
   int n;
@@ -430,16 +431,22 @@ static svn_error_t *find_tunnel_agent(co
   if (status != APR_SUCCESS)
     return svn_error_wrap_apr(status, _("Can't tokenize command '%s'"), cmd);
 
-  /* Append the fixed arguments to the result. */
+  /* Calc number of the fixed arguments. */
   for (n = 0; cmd_argv[n] != NULL; n++)
     ;
-  *argv = apr_palloc(pool, (n + 4) * sizeof(char *));
-  memcpy(*argv, cmd_argv, n * sizeof(char *));
-  (*argv)[n++] = svn_path_uri_decode(hostinfo, pool);
-  (*argv)[n++] = "svnserve";
-  (*argv)[n++] = "-t";
-  (*argv)[n] = NULL;
 
+  argv = apr_palloc(pool, (n + 4) * sizeof(char *));
+
+  /* Append the fixed arguments to the result. */
+  for (n = 0; cmd_argv[n] != NULL; n++)
+    argv[n] = cmd_argv[n];
+
+  argv[n++] = svn_path_uri_decode(hostinfo, pool);
+  argv[n++] = "svnserve";
+  argv[n++] = "-t";
+  argv[n] = NULL;
+
+  *argv_p = argv;
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_repos/dump.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_repos/dump.c Sun Oct 19 13:55:35 2014
@@ -2245,16 +2245,26 @@ svn_repos_verify_fs3(svn_repos_t *repos,
       found_corruption = TRUE;
       notify_verification_error(SVN_INVALID_REVNUM, err, notify_func,
                                 notify_baton, iterpool);
-      svn_error_clear(err);
 
+      /* If we already reported the error, reset it. */
+      if (notify_func)
+        {
+          svn_error_clear(err);
+          err = NULL;
+        }
+
+      /* If we abort the verification now, combine yet unreported error
+         info with the generic one we return. */
       if (!keep_going)
         /* ### Jump to "We're done" and so send the final notification,
                for consistency? */
-        return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
+        return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, err,
                                 _("Repository '%s' failed to verify"),
                                 svn_dirent_local_style(svn_repos_path(repos,
                                                                       pool),
                                                         pool));
+
+      svn_error_clear(err);
     }
 
   if (!metadata_only)

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_repos/replay.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_repos/replay.c Sun Oct 19 13:55:35 2014
@@ -548,6 +548,17 @@ path_driver_cb_func(void **dir_baton,
       svn_boolean_t src_readable;
       svn_fs_root_t *copyfrom_root;
 
+      /* E.g. when verifying corrupted repositories, their changed path
+         lists may contain an ADD for "/".  The delta path driver will
+         call us with a NULL parent in that case. */
+      if (*edit_path == 0)
+        return svn_error_create(SVN_ERR_FS_ALREADY_EXISTS, NULL,
+                                _("Root directory already exists."));
+
+      /* A NULL parent_baton will cause a segfault.  It should never be
+          NULL for non-root paths. */
+      SVN_ERR_ASSERT(parent_baton);
+
       /* Was this node copied? */
       SVN_ERR(fill_copyfrom(&copyfrom_root, &copyfrom_path, &copyfrom_rev,
                             &src_readable, root, change,

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_repos/repos.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_repos/repos.c Sun Oct 19 13:55:35 2014
@@ -1690,7 +1690,7 @@ svn_repos_delete(const char *path,
   SVN_ERR(svn_fs_delete_fs(db_path, pool));
 
   /* ...then blow away everything else.  */
-  return svn_io_remove_dir2(path, FALSE, NULL, NULL, pool);
+  return svn_error_trace(svn_io_remove_dir2(path, FALSE, NULL, NULL, pool));
 }
 
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_repos/rev_hunt.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_repos/rev_hunt.c Sun Oct 19 13:55:35 2014
@@ -984,7 +984,8 @@ struct path_revision
   svn_revnum_t revnum;
   const char *path;
 
-  /* Does this path_rev have merges to also be included?  */
+  /* Does this path_rev have merges to also be included?  If so, this is
+     the union of both additions and (negated) deletions of mergeinfo. */
   apr_hash_t *merged_mergeinfo;
 
   /* Is this a merged revision? */
@@ -993,6 +994,7 @@ struct path_revision
 
 /* Check for merges in OLD_PATH_REV->PATH at OLD_PATH_REV->REVNUM.  Store
    the mergeinfo difference in *MERGED_MERGEINFO, allocated in POOL.  The
+   difference is the union of both additions and (negated) deletions.  The
    returned *MERGED_MERGEINFO will be NULL if there are no changes. */
 static svn_error_t *
 get_merged_mergeinfo(apr_hash_t **merged_mergeinfo,
@@ -1070,7 +1072,8 @@ get_merged_mergeinfo(apr_hash_t **merged
   else
     SVN_ERR(err);
 
-  /* Then calculate and merge the differences. */
+  /* Then calculate and merge the differences, combining additions and
+     (negated) deletions as all positive changes in CHANGES. */
   SVN_ERR(svn_mergeinfo_diff2(&deleted, &changed, prev_mergeinfo,
                               curr_mergeinfo, FALSE, result_pool,
                               scratch_pool));

Propchange: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/bit_array.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cache-inprocess.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cache-inprocess.c Sun Oct 19 13:55:35 2014
@@ -196,7 +196,8 @@ inprocess_cache_get_internal(char **buff
 
       /* duplicate the buffer entry */
       *buffer = apr_palloc(result_pool, entry->size);
-      memcpy(*buffer, entry->value, entry->size);
+      if (entry->size)
+        memcpy(*buffer, entry->value, entry->size);
 
       *size = entry->size;
     }

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cmdline.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/cmdline.c Sun Oct 19 13:55:35 2014
@@ -507,31 +507,50 @@ svn_cmdline_handle_exit_error(svn_error_
   return EXIT_FAILURE;
 }
 
+struct trust_server_cert_non_interactive_baton {
+  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;
+};
+
 /* This implements 'svn_auth_ssl_server_trust_prompt_func_t'.
 
    Don't actually prompt.  Instead, set *CRED_P to valid credentials
-   iff FAILURES is empty or is exactly SVN_AUTH_SSL_UNKNOWNCA.  If
-   there are any other failure bits, then set *CRED_P to null (that
-   is, reject the cert).
+   iff FAILURES is empty or may be accepted according to the flags
+   in BATON. If there are any other failure bits, then set *CRED_P
+   to null (that is, reject the cert).
 
    Ignore MAY_SAVE; we don't save certs we never prompted for.
 
-   Ignore BATON, REALM, and CERT_INFO,
+   Ignore REALM and CERT_INFO,
 
    Ignore any further films by George Lucas. */
 static svn_error_t *
-ssl_trust_unknown_server_cert
-  (svn_auth_cred_ssl_server_trust_t **cred_p,
-   void *baton,
-   const char *realm,
-   apr_uint32_t failures,
-   const svn_auth_ssl_server_cert_info_t *cert_info,
-   svn_boolean_t may_save,
-   apr_pool_t *pool)
+trust_server_cert_non_interactive(svn_auth_cred_ssl_server_trust_t **cred_p,
+                                  void *baton,
+                                  const char *realm,
+                                  apr_uint32_t failures,
+                                  const svn_auth_ssl_server_cert_info_t
+                                    *cert_info,
+                                  svn_boolean_t may_save,
+                                  apr_pool_t *pool)
 {
+  struct trust_server_cert_non_interactive_baton *b = baton;
   *cred_p = NULL;
 
-  if (failures == 0 || failures == SVN_AUTH_SSL_UNKNOWNCA)
+  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)))
     {
       *cred_p = apr_pcalloc(pool, sizeof(**cred_p));
       (*cred_p)->may_save = FALSE;
@@ -542,17 +561,22 @@ ssl_trust_unknown_server_cert
 }
 
 svn_error_t *
-svn_cmdline_create_auth_baton(svn_auth_baton_t **ab,
-                              svn_boolean_t non_interactive,
-                              const char *auth_username,
-                              const char *auth_password,
-                              const char *config_dir,
-                              svn_boolean_t no_auth_cache,
-                              svn_boolean_t trust_server_cert,
-                              svn_config_t *cfg,
-                              svn_cancel_func_t cancel_func,
-                              void *cancel_baton,
-                              apr_pool_t *pool)
+svn_cmdline_create_auth_baton2(svn_auth_baton_t **ab,
+                               svn_boolean_t non_interactive,
+                               const char *auth_username,
+                               const char *auth_password,
+                               const char *config_dir,
+                               svn_boolean_t no_auth_cache,
+                               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,
+                               svn_config_t *cfg,
+                               svn_cancel_func_t cancel_func,
+                               void *cancel_baton,
+                               apr_pool_t *pool)
+
 {
   svn_boolean_t store_password_val = TRUE;
   svn_boolean_t store_auth_creds_val = TRUE;
@@ -653,11 +677,22 @@ svn_cmdline_create_auth_baton(svn_auth_b
           APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
         }
     }
-  else if (trust_server_cert)
-    {
+  else if (trust_server_cert_unknown_ca || trust_server_cert_cn_mismatch ||
+           trust_server_cert_expired || trust_server_cert_not_yet_valid ||
+           trust_server_cert_other_failure)
+    {
+      struct trust_server_cert_non_interactive_baton *b;
+
+      b = apr_palloc(pool, sizeof(*b));
+      b->trust_server_cert_unknown_ca = trust_server_cert_unknown_ca;
+      b->trust_server_cert_cn_mismatch = trust_server_cert_cn_mismatch;
+      b->trust_server_cert_expired = trust_server_cert_expired;
+      b->trust_server_cert_not_yet_valid = trust_server_cert_not_yet_valid;
+      b->trust_server_cert_other_failure = trust_server_cert_other_failure;
+
       /* Remember, only register this provider if non_interactive. */
       svn_auth_get_ssl_server_trust_prompt_provider
-        (&provider, ssl_trust_unknown_server_cert, NULL, pool);
+        (&provider, trust_server_cert_non_interactive, b, pool);
       APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
     }
 

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/config_file.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/config_file.c Sun Oct 19 13:55:35 2014
@@ -940,15 +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
-        "###   http-pipelining            Whether to use HTTP pipelining "   NL
-        "###                              or send requests one by one."      NL
-        "###                              Pipelining is enabled by default." NL
-        "###                              The only known case where it should"
-                                                                             NL
-        "###                              be disabled is when the server"    NL
-        "###                              triggers SSL renegotiations in the"NL
-        "###                              middle of HTTP traffic, resulting" NL
-        "###                              in SSL communication errors."      NL
         "###   neon-debug-mask            Debug mask for Neon HTTP library"  NL
         "###   ssl-authority-files        List of files, each of a trusted CA"
                                                                              NL

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/deprecated.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/deprecated.c Sun Oct 19 13:55:35 2014
@@ -1504,3 +1504,33 @@ svn_auth_get_gpg_agent_simple_provider(s
   svn_auth__get_gpg_agent_simple_provider(provider, pool);
 }
 #endif /* !WIN32 */
+
+svn_error_t *
+svn_cmdline_create_auth_baton(svn_auth_baton_t **ab,
+                              svn_boolean_t non_interactive,
+                              const char *auth_username,
+                              const char *auth_password,
+                              const char *config_dir,
+                              svn_boolean_t no_auth_cache,
+                              svn_boolean_t trust_server_cert,
+                              svn_config_t *cfg,
+                              svn_cancel_func_t cancel_func,
+                              void *cancel_baton,
+                              apr_pool_t *pool)
+{
+  return svn_error_trace(svn_cmdline_create_auth_baton2(ab,
+                                                        non_interactive,
+                                                        auth_username,
+                                                        auth_password,
+                                                        config_dir,
+                                                        no_auth_cache,
+                                                        trust_server_cert,
+                                                        FALSE,
+                                                        FALSE,
+                                                        FALSE,
+                                                        FALSE,
+                                                        cfg,
+                                                        cancel_func,
+                                                        cancel_baton,
+                                                        pool));
+}

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/gpg_agent.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/gpg_agent.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/gpg_agent.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/gpg_agent.c Sun Oct 19 13:55:35 2014
@@ -108,7 +108,7 @@ escape_blanks(char *str)
  * to other password caching mechanisms. */
 static svn_error_t *
 get_cache_id(const char **cache_id_p, const char *realmstring,
-             apr_pool_t *scratch_pool, apr_pool_t *result_pool)
+             apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
   const char *cache_id = NULL;
   svn_checksum_t *digest = NULL;

Modified: subversion/branches/revprop-caching-ng/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-caching-ng/subversion/libsvn_subr/io.c?rev=1632906&r1=1632905&r2=1632906&view=diff
==============================================================================
--- subversion/branches/revprop-caching-ng/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/revprop-caching-ng/subversion/libsvn_subr/io.c Sun Oct 19 13:55:35 2014
@@ -3662,7 +3662,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, SEEK_CUR, &current, pool));
+      SVN_ERR(svn_io_file_seek(file, APR_CUR, &current, pool));
       fill_buffer = aligned_offset + file_buffer_size <= current
                  || current <= aligned_offset;
     }
@@ -3673,7 +3673,7 @@ 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, SEEK_SET, &aligned_offset, pool));
+      SVN_ERR(svn_io_file_seek(file, APR_SET, &aligned_offset, pool));
       status = apr_file_getc(&dummy, file);
 
       /* read may fail if we seek to or behind EOF.  That's ok then. */
@@ -3686,7 +3686,7 @@ svn_io_file_aligned_seek(apr_file_t *fil
 
   /* finally, seek to the OFFSET the caller wants */
   desired_offset = offset;
-  SVN_ERR(svn_io_file_seek(file, SEEK_SET, &offset, pool));
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, pool));
   if (desired_offset != offset)
     return do_io_file_wrapper_cleanup(file, APR_EOF,
                                       N_("Can't seek in file '%s'"),



Mime
View raw message