subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1416996 [5/13] - in /subversion/branches/wc-collate-path: ./ build/ build/ac-macros/ build/generator/ contrib/client-side/svnmerge/ contrib/server-side/svncutter/ notes/ subversion/bindings/cxxhl/ subversion/bindings/javahl/native/ subvers...
Date Tue, 04 Dec 2012 15:35:57 GMT
Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/fs_fs.c Tue Dec  4 15:35:13 2012
@@ -360,6 +360,18 @@ path_txn_dir(svn_fs_t *fs, const char *t
                               NULL);
 }
 
+/* Return the name of the sha1->rep mapping file in transaction TXN_ID
+ * within FS for the given SHA1 checksum.  Use POOL for allocations.
+ */
+static APR_INLINE const char *
+path_txn_sha1(svn_fs_t *fs, const char *txn_id, svn_checksum_t *sha1,
+              apr_pool_t *pool)
+{
+  return svn_dirent_join(path_txn_dir(fs, txn_id, pool),
+                         svn_checksum_to_cstring(sha1, pool),
+                         pool);
+}
+
 static APR_INLINE const char *
 path_txn_changes(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool)
 {
@@ -1273,9 +1285,9 @@ write_config(svn_fs_t *fs,
 "###"                                                                        NL
 "### The following parameter enables deltification for properties on files"  NL
 "### and directories.  Overall, this is a minor tuning option but can save"  NL
-"### some disk space if frequently merge or if you frequently change node"   NL
+"### some disk space if you merge frequently or frequently change node"      NL
 "### properties.  You should not activate this if rep-sharing has been"      NL
-"### disabled."                                                              NL
+"### disabled because this may result in a net increase in repository size." NL
 "### property deltification is disabled by default."                         NL
 "# " CONFIG_OPTION_ENABLE_PROPS_DELTIFICATION " = false"                     NL
 "###"                                                                        NL
@@ -2226,8 +2238,10 @@ get_cached_node_revision_body(node_revis
     }
   else
     {
-      pair_cache_key_t key = { svn_fs_fs__id_rev(id),
-                               svn_fs_fs__id_offset(id) };
+      pair_cache_key_t key;
+
+      key.revision = svn_fs_fs__id_rev(id);
+      key.second = svn_fs_fs__id_offset(id);
       SVN_ERR(svn_cache__get((void **) noderev_p,
                             is_cached,
                             ffd->node_revision_cache,
@@ -2253,8 +2267,10 @@ set_cached_node_revision_body(node_revis
 
   if (ffd->node_revision_cache && !svn_fs_fs__id_txn_id(id))
     {
-      pair_cache_key_t key = { svn_fs_fs__id_rev(id),
-                               svn_fs_fs__id_offset(id) };
+      pair_cache_key_t key;
+
+      key.revision = svn_fs_fs__id_rev(id);
+      key.second = svn_fs_fs__id_offset(id);
       return svn_cache__set(ffd->node_revision_cache,
                             &key,
                             noderev_p,
@@ -2613,10 +2629,6 @@ svn_fs_fs__put_node_revision(svn_fs_t *f
   fs_fs_data_t *ffd = fs->fsap_data;
   apr_file_t *noderev_file;
   const char *txn_id = svn_fs_fs__id_txn_id(id);
-  const char *sha1 = ffd->rep_sharing_allowed && noderev->data_rep
-                   ? svn_checksum_to_cstring(noderev->data_rep->sha1_checksum,
-                                             pool)
-                   : NULL;
 
   noderev->is_fresh_txn_root = fresh_txn_root;
 
@@ -2637,13 +2649,31 @@ svn_fs_fs__put_node_revision(svn_fs_t *f
 
   SVN_ERR(svn_io_file_close(noderev_file, pool));
 
+  return SVN_NO_ERROR;
+}
+
+/* For the in-transaction NODEREV within FS, write the sha1->rep mapping
+ * file in the respective transaction, if rep sharing has been enabled etc.
+ * Use POOL for temporary allocations.
+ */
+static svn_error_t *
+store_sha1_rep_mapping(svn_fs_t *fs,
+                       node_revision_t *noderev,
+                       apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
   /* if rep sharing has been enabled and the noderev has a data rep and
    * its SHA-1 is known, store the rep struct under its SHA1. */
-  if (sha1)
+  if (   ffd->rep_sharing_allowed
+      && noderev->data_rep
+      && noderev->data_rep->sha1_checksum)
     {
       apr_file_t *rep_file;
-      const char *file_name = svn_dirent_join(path_txn_dir(fs, txn_id, pool),
-                                              sha1, pool);
+      const char *file_name = path_txn_sha1(fs,
+                                            svn_fs_fs__id_txn_id(noderev->id),
+                                            noderev->data_rep->sha1_checksum,
+                                            pool);
       const char *rep_string = representation_string(noderev->data_rep,
                                                      ffd->format,
                                                      (noderev->kind
@@ -3503,9 +3533,11 @@ parse_revprop(apr_hash_t **properties,
   SVN_ERR(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, pool));
   if (has_revprop_cache(fs, pool))
     {
-      pair_cache_key_t key = {revision, generation};
       fs_fs_data_t *ffd = fs->fsap_data;
+      pair_cache_key_t key;
 
+      key.revision = revision;
+      key.second = generation;
       SVN_ERR(svn_cache__set(ffd->revprop_cache, &key, *properties,
                              scratch_pool));
     }
@@ -3805,10 +3837,11 @@ get_revision_proplist(apr_hash_t **propl
   if (has_revprop_cache(fs, pool))
     {
       svn_boolean_t is_cached;
-      pair_cache_key_t key = { rev, 0};
+      pair_cache_key_t key;
 
       SVN_ERR(read_revprop_generation(&generation, fs, pool));
 
+      key.revision = rev;
       key.second = generation;
       SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
                              ffd->revprop_cache, &key, pool));
@@ -4822,8 +4855,8 @@ rep_read_get_baton(struct rep_read_baton
 /* Skip forwards to THIS_CHUNK in REP_STATE and then read the next delta
    window into *NWIN. */
 static svn_error_t *
-read_window(svn_txdelta_window_t **nwin, int this_chunk, struct rep_state *rs,
-            apr_pool_t *pool)
+read_delta_window(svn_txdelta_window_t **nwin, int this_chunk,
+                  struct rep_state *rs, apr_pool_t *pool)
 {
   svn_stream_t *stream;
   svn_boolean_t is_cached;
@@ -4870,6 +4903,27 @@ read_window(svn_txdelta_window_t **nwin,
   return set_cached_window(*nwin, rs, old_offset, pool);
 }
 
+/* Read SIZE bytes from the representation RS and return it in *NWIN. */
+static svn_error_t *
+read_plain_window(svn_stringbuf_t **nwin, struct rep_state *rs,
+                  apr_size_t size, apr_pool_t *pool)
+{
+  /* RS->FILE may be shared between RS instances -> make sure we point
+   * to the right data. */
+  SVN_ERR(svn_io_file_seek(rs->file, APR_SET, &rs->off, pool));
+
+  /* Read the plain data. */
+  *nwin = svn_stringbuf_create_ensure(size, pool);
+  SVN_ERR(svn_io_file_read_full2(rs->file, (*nwin)->data, size, NULL, NULL,
+                                 pool));
+  (*nwin)->data[size] = 0;
+
+  /* Update RS. */
+  rs->off += (apr_off_t)size;
+
+  return SVN_NO_ERROR;
+}
+
 /* Get the undeltified window that is a result of combining all deltas
    from the current desired representation identified in *RB with its
    base representation.  Store the window in *RESULT. */
@@ -4893,7 +4947,7 @@ get_combined_window(svn_stringbuf_t **re
   for (i = 0; i < rb->rs_list->nelts; ++i)
     {
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
-      SVN_ERR(read_window(&window, rb->chunk_index, rs, window_pool));
+      SVN_ERR(read_delta_window(&window, rb->chunk_index, rs, window_pool));
 
       APR_ARRAY_PUSH(windows, svn_txdelta_window_t *) = window;
       if (window->src_ops == 0)
@@ -4907,11 +4961,20 @@ get_combined_window(svn_stringbuf_t **re
   pool = svn_pool_create(rb->pool);
   for (--i; i >= 0; --i)
     {
+
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
       window = APR_ARRAY_IDX(windows, i, svn_txdelta_window_t *);
 
-      /* Combine this window with the current one. */
+      /* Maybe, we've got a PLAIN start representation.  If we do, read
+         as much data from it as the needed for the txdelta window's source
+         view.
+         Note that BUF / SOURCE may only be NULL in the first iteration. */
       source = buf;
+      if (source == NULL && rb->src_state != NULL)
+        SVN_ERR(read_plain_window(&source, rb->src_state, window->sview_len,
+                                  pool));
+
+      /* Combine this window with the current one. */
       new_pool = svn_pool_create(rb->pool);
       buf = svn_stringbuf_create_ensure(window->tview_len, new_pool);
       buf->len = window->tview_len;
@@ -5127,10 +5190,12 @@ read_representation(svn_stream_t **conte
   else
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key = {rep->revision, rep->offset};
+      pair_cache_key_t fulltext_cache_key;
       svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
       struct rep_read_baton *rb;
 
+      fulltext_cache_key.revision = rep->revision;
+      fulltext_cache_key.second = rep->offset;
       if (ffd->fulltext_cache && SVN_IS_VALID_REVNUM(rep->revision)
           && fulltext_size_is_cachable(ffd, len))
         {
@@ -5187,7 +5252,7 @@ delta_read_next_window(svn_txdelta_windo
       return SVN_NO_ERROR;
     }
 
-  return read_window(window, drb->rs->chunk_index, drb->rs, pool);
+  return read_delta_window(window, drb->rs->chunk_index, drb->rs, pool);
 }
 
 /* This implements the svn_txdelta_md5_digest_fn_t interface. */
@@ -5299,14 +5364,18 @@ svn_fs_fs__try_process_file_contents(svn
   if (rep)
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key = {rep->revision, rep->offset};
+      pair_cache_key_t fulltext_cache_key;
 
+      fulltext_cache_key.revision = rep->revision;
+      fulltext_cache_key.second = rep->offset;
       if (ffd->fulltext_cache && SVN_IS_VALID_REVNUM(rep->revision)
           && fulltext_size_is_cachable(ffd, rep->expanded_size))
         {
-          cache_access_wrapper_baton_t wrapper_baton = {processor, baton};
+          cache_access_wrapper_baton_t wrapper_baton;
           void *dummy = NULL;
 
+          wrapper_baton.func = processor;
+          wrapper_baton.baton = baton;
           return svn_cache__get_partial(&dummy, success,
                                         ffd->fulltext_cache,
                                         &fulltext_cache_key,
@@ -5602,8 +5671,10 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
     {
       fs_fs_data_t *ffd = fs->fsap_data;
       representation_t *rep = noderev->prop_rep;
-      
-      pair_cache_key_t key = { rep->revision, rep->offset };
+      pair_cache_key_t key;
+
+      key.revision = rep->revision;
+      key.second = rep->offset;
       if (ffd->properties_cache && SVN_IS_VALID_REVNUM(rep->revision))
         {
           svn_boolean_t is_cached;
@@ -7100,22 +7171,14 @@ rep_write_cleanup(void *data)
   
   /* Truncate and close the protorevfile. */
   err = svn_io_file_trunc(b->file, b->rep_offset, b->pool);
-  if (err)
-    {
-      apr_status_t rc = err->apr_err;
-      svn_error_clear(err);
-      return rc;
-    }
-  err = svn_io_file_close(b->file, b->pool);
-  if (err)
-    {
-      apr_status_t rc = err->apr_err;
-      svn_error_clear(err);
-      return rc;
-    }
+  err = svn_error_compose_create(err, svn_io_file_close(b->file, b->pool));
 
-  /* Remove our lock */
-  err = unlock_proto_rev(b->fs, txn_id, b->lockcookie, b->pool);
+  /* Remove our lock regardless of any preceeding errors so that the 
+     being_written flag is always removed and stays consistent with the
+     file lock which will be removed no matter what since the pool is
+     going away. */
+  err = svn_error_compose_create(err, unlock_proto_rev(b->fs, txn_id,
+                                                       b->lockcookie, b->pool));
   if (err)
     {
       apr_status_t rc = err->apr_err;
@@ -7279,9 +7342,7 @@ get_shared_rep(representation_t **old_re
     {
       svn_node_kind_t kind;
       const char *file_name
-        = svn_dirent_join(path_txn_dir(fs, rep->txn_id, pool),
-                          svn_checksum_to_cstring(rep->sha1_checksum, pool),
-                          pool);
+        = path_txn_sha1(fs, rep->txn_id, rep->sha1_checksum, pool);
 
       /* in our txn, is there a rep file named with the wanted SHA1?
          If so, read it and use that rep.
@@ -7371,6 +7432,8 @@ rep_write_contents_close(void *baton)
   /* Write out the new node-rev information. */
   SVN_ERR(svn_fs_fs__put_node_revision(b->fs, b->noderev->id, b->noderev, FALSE,
                                        b->pool));
+  if (!old_rep)
+    SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->pool));
 
   SVN_ERR(svn_io_file_close(b->file, b->pool));
   SVN_ERR(unlock_proto_rev(b->fs, rep->txn_id, b->lockcookie, b->pool));

Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/structure?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/structure Tue Dec  4 15:35:13 2012
@@ -526,6 +526,7 @@ A transaction directory has the followin
   node.<nid>.<cid>           New node-rev data for node
   node.<nid>.<cid>.props     Props for new node-rev, if changed
   node.<nid>.<cid>.children  Directory contents for node-rev
+  <sha1>                     Text representation of that sha1
 
 In FS formats 1 and 2, it also contains:
 
@@ -543,6 +544,11 @@ The two kinds of props files are all in 
 file will always be present.  The "node.<nid>.<cid>.props" file will
 only be present if the node-rev properties have been changed.
 
+The <sha1> files have been introduced in FS format 6. Their content
+is that of text rep references: "<rev> <offset> <length> <size> <digest>"
+They will be written for text reps in the current transaction and be
+used to eliminate duplicate reps within that transaction.
+
 The "next-ids" file contains a single line "<next-temp-node-id>
 <next-temp-copy-id>\n" giving the next temporary node-ID and copy-ID
 assignments (without the leading underscores).  The next node-ID is

Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.c Tue Dec  4 15:35:13 2012
@@ -88,27 +88,6 @@ svn_fs_fs__combine_number_and_string(apr
   return key;
 }
 
-const char*
-svn_fs_fs__combine_two_numbers(apr_int64_t a,
-                               apr_int64_t b,
-                               apr_pool_t *pool)
-{
-  /* encode numbers as 2x 10x7 bits + 1 space + 1 terminating \0*/
-  char *key_buffer = apr_palloc(pool, 22);
-  const char *key = key_buffer;
-
-  /* combine the numbers. Since the separator is disjoint from any part
-   * of the encoded numbers, there is no other combination that can yield
-   * the same result */
-  key_buffer = encode_number(a, key_buffer);
-  *++key_buffer = ' ';
-  key_buffer = encode_number(b, ++key_buffer);
-  *++key_buffer = '\0';
-
-  /* return the start of the key */
-  return key;
-}
-
 /* Utility function to serialize string S in the given serialization CONTEXT.
  */
 static void

Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.h?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/temp_serializer.h Tue Dec  4 15:35:13 2012
@@ -36,16 +36,6 @@ svn_fs_fs__combine_number_and_string(apr
                                      apr_pool_t *pool);
 
 /**
- * Combine the numbers @a a and @a b in a space efficient way such that no
- * other combination of numbers can produce the same result.
- * Allocate temporaries as well as the result from @a pool.
- */
-const char*
-svn_fs_fs__combine_two_numbers(apr_int64_t a,
-                               apr_int64_t b,
-                               apr_pool_t *pool);
-
-/**
  * Serialize a @a noderev_p within the serialization @a context.
  */
 void

Modified: subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/tree.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_fs_fs/tree.c Tue Dec  4 15:35:13 2012
@@ -3243,7 +3243,7 @@ prev_location(const char **prev_path,
   */
   SVN_ERR(fs_copied_from(&copy_src_rev, &copy_src_path,
                          copy_root, copy_path, pool));
-  remainder_path = svn_relpath_skip_ancestor(copy_path, path);
+  remainder_path = svn_fspath__skip_ancestor(copy_path, path);
   *prev_path = svn_fspath__join(copy_src_path, remainder_path, pool);
   *prev_rev = copy_src_rev;
   return SVN_NO_ERROR;

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_local/ra_plugin.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_local/ra_plugin.c Tue Dec  4 15:35:13 2012
@@ -1064,7 +1064,7 @@ get_node_props(apr_hash_t **props,
       int i;
 
       SVN_ERR(svn_repos_fs_get_inherited_props(inherited_props, root, path,
-                                               NULL, NULL,
+                                               NULL, NULL, NULL,
                                                result_pool, scratch_pool));
 
       for (i = 0; i < (*inherited_props)->nelts; i++)

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_local/split_url.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_local/split_url.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_local/split_url.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_local/split_url.c Tue Dec  4 15:35:13 2012
@@ -23,14 +23,13 @@
 
 #include "ra_local.h"
 #include <string.h>
-#include "svn_path.h"
 #include "svn_dirent_uri.h"
 #include "svn_private_config.h"
 
 
 svn_error_t *
 svn_ra_local__split_URL(svn_repos_t **repos,
-                        const char **repos_url,
+                        const char **repos_root_url,
                         const char **fs_path,
                         const char *URL,
                         apr_pool_t *pool)
@@ -38,7 +37,6 @@ svn_ra_local__split_URL(svn_repos_t **re
   svn_error_t *err = SVN_NO_ERROR;
   const char *repos_dirent;
   const char *repos_root_dirent;
-  svn_stringbuf_t *urlbuf;
 
   SVN_ERR(svn_uri_get_dirent_from_file_url(&repos_dirent, URL, pool));
 
@@ -61,18 +59,18 @@ svn_ra_local__split_URL(svn_repos_t **re
     SVN_ERR(svn_repos_remember_client_capabilities(*repos, caps));
   }
 
+  /* = apr_pstrcat(pool,
+                   "/",
+                   svn_dirent_skip_ancestor(repos_root_dirent, repos_dirent),
+                   (const char *)NULL */
   *fs_path = &repos_dirent[strlen(repos_root_dirent)];
 
   if (**fs_path == '\0')
     *fs_path = "/";
 
-  /* Remove the path components in *fs_path from the original URL, to get
-     the URL to the repository root. */
-  urlbuf = svn_stringbuf_create(URL, pool);
-  svn_path_remove_components(urlbuf,
-                             svn_path_component_count(repos_dirent)
-                             - svn_path_component_count(repos_root_dirent));
-  *repos_url = urlbuf->data;
+  /* Create a url to the repository root. */
+  SVN_ERR(svn_uri_get_file_url_from_dirent(repos_root_url, repos_root_dirent,
+                                           pool));
 
   /* Configure hook script environment variables. */
   SVN_ERR(svn_repos_hooks_setenv(*repos, NULL, pool, pool));

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/inherited_props.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/inherited_props.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/inherited_props.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/inherited_props.c Tue Dec  4 15:35:13 2012
@@ -277,8 +277,7 @@ svn_ra_serf__get_inherited_props(svn_ra_
                                  apr_pool_t *result_pool,
                                  apr_pool_t *scratch_pool)
 {
-  svn_error_t *err, *err2;
-
+  svn_error_t *err;
   iprops_context_t *iprops_ctx;
   svn_ra_serf__session_t *session = ra_session->priv;
   svn_ra_serf__handler_t *handler;
@@ -293,6 +292,8 @@ svn_ra_serf__get_inherited_props(svn_ra_
                                       revision,
                                       result_pool, scratch_pool));
 
+  SVN_ERR_ASSERT(session->repos_root_str);
+
   iprops_ctx = apr_pcalloc(scratch_pool, sizeof(*iprops_ctx));
   iprops_ctx->done = FALSE;
   iprops_ctx->repos_root_url = session->repos_root_str;
@@ -329,20 +330,12 @@ svn_ra_serf__get_inherited_props(svn_ra_
   handler->response_handler = svn_ra_serf__handle_xml_parser;
   handler->response_baton = parser_ctx;
 
-  svn_ra_serf__request_create(handler);
-
-  err = svn_ra_serf__context_run_wait(&iprops_ctx->done, session,
-                                      scratch_pool);
-
-  err2 = svn_ra_serf__error_on_status(handler->sline.code, handler->path,
-                                      handler->location);
-  if (err2)
-    {
-      svn_error_clear(err);
-      return err2;
-    }
-
-  SVN_ERR(err);
+  err = svn_ra_serf__context_run_one(handler, scratch_pool);
+  SVN_ERR(svn_error_compose_create(
+                    svn_ra_serf__error_on_status(handler->sline.code,
+                                                 handler->path,
+                                                 handler->location),
+                    err));
 
   if (iprops_ctx->done)
     *iprops = iprops_ctx->iprops;

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/property.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/property.c Tue Dec  4 15:35:13 2012
@@ -468,10 +468,6 @@ setup_propfind_headers(serf_bucket_t *he
 {
   propfind_context_t *ctx = setup_baton;
 
-  if (ctx->sess->using_compression)
-    {
-      serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
-    }
   serf_bucket_headers_setn(headers, "Depth", ctx->depth);
   if (ctx->label)
     {

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/ra_serf.h?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/ra_serf.h Tue Dec  4 15:35:13 2012
@@ -189,7 +189,7 @@ struct svn_ra_serf__session_t {
   const char *uuid;
 
   /* Connection timeout value */
-  apr_short_interval_time_t timeout;
+  apr_interval_time_t timeout;
 
   /* HTTPv1 flags */
   svn_tristate_t supports_deadprop_count;
@@ -393,6 +393,11 @@ typedef struct svn_ra_serf__handler_t {
   /* The content-type of the request body. */
   const char *body_type;
 
+  /* If TRUE then default Accept-Encoding request header is not configured for
+     request. If FALSE then 'gzip' accept encoding will be used if compression
+     enabled. */
+  svn_boolean_t custom_accept_encoding;
+
   /* Has the request/response been completed?  */
   svn_boolean_t done;
 
@@ -954,6 +959,7 @@ svn_ra_serf__xml_pop_state(svn_ra_serf__
 
 svn_error_t *
 svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
+                             svn_boolean_t *network_eof,
                              apr_pool_t *scratch_pool);
 
 

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/replay.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/replay.c Tue Dec  4 15:35:13 2012
@@ -732,7 +732,7 @@ svn_ra_serf__replay_range(svn_ra_session
   svn_revnum_t rev = start_revision;
   const char *report_target;
   int active_reports = 0;
-  apr_short_interval_time_t waittime_left = session->timeout;
+  apr_interval_time_t waittime_left = session->timeout;
 
   SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
 
@@ -873,14 +873,17 @@ svn_ra_serf__replay_range(svn_ra_session
           err = SVN_NO_ERROR;
           status = 0;
 
-          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+          if (session->timeout)
             {
-              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
-            }
-          else
-            {
-              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
-                                      _("Connection timed out"));
+              if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+                {
+                  waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+                }
+              else
+                {
+                  return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                          _("Connection timed out"));
+                }
             }
         }
       else

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/serf.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/serf.c Tue Dec  4 15:35:13 2012
@@ -131,7 +131,11 @@ load_http_auth_types(apr_pool_t *pool, s
 
   return SVN_NO_ERROR;
 }
-#define DEFAULT_HTTP_TIMEOUT 3600
+
+/* Default HTTP timeout (in seconds); overridden by the 'http-timeout'
+   runtime configuration variable. */
+#define DEFAULT_HTTP_TIMEOUT 600
+
 static svn_error_t *
 load_config(svn_ra_serf__session_t *session,
             apr_hash_t *config_hash,
@@ -253,6 +257,7 @@ load_config(svn_ra_serf__session_t *sess
     }
 
   /* Parse the connection timeout value, if any. */
+  session->timeout = apr_time_from_sec(DEFAULT_HTTP_TIMEOUT);
   if (timeout_str)
     {
       char *endstr;
@@ -267,13 +272,7 @@ load_config(svn_ra_serf__session_t *sess
                                 _("Invalid config: negative timeout value"));
       session->timeout = apr_time_from_sec(timeout);
     }
-  else
-    session->timeout = apr_time_from_sec(DEFAULT_HTTP_TIMEOUT);
-
-  if (session->timeout < 0) /* Always true for DEFAULT_HTTP_TIMEOUT */
-    session->timeout = apr_time_from_sec(600); /* 10 min */
-
-  SVN_ERR_ASSERT(session->timeout > 0);
+  SVN_ERR_ASSERT(session->timeout >= 0);
 
   /* Convert the proxy port value, if any. */
   if (port_str)

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/update.c Tue Dec  4 15:35:13 2012
@@ -63,13 +63,19 @@
  */
 typedef enum report_state_e {
     NONE = 0,
+    INITIAL = 0,
+    UPDATE_REPORT,
+    TARGET_REVISION,
     OPEN_DIR,
     ADD_DIR,
+    ABSENT_DIR,
     OPEN_FILE,
     ADD_FILE,
+    ABSENT_FILE,
     PROP,
     IGNORE_PROP_NAME,
-    NEED_PROP_NAME
+    NEED_PROP_NAME,
+    TXDELTA
 } report_state_e;
 
 
@@ -85,8 +91,8 @@ typedef enum report_state_e {
    since network and parsing behavior (ie. it doesn't pause immediately)
    can make the measurements quite imprecise.
 
-   We measure outstanding requests as the sum of ACTIVE_FETCHES and
-   ACTIVE_PROPFINDS in the report_context_t structure.  */
+   We measure outstanding requests as the sum of NUM_ACTIVE_FETCHES and
+   NUM_ACTIVE_PROPFINDS in the report_context_t structure.  */
 #define REQUEST_COUNT_TO_PAUSE 1000
 #define REQUEST_COUNT_TO_RESUME 100
 
@@ -126,7 +132,7 @@ typedef struct report_dir_t
   /* Our base revision - SVN_INVALID_REVNUM if we're adding this dir. */
   svn_revnum_t base_rev;
 
-  /* controlling dir baton - this is only created in open_dir() */
+  /* controlling dir baton - this is only created in ensure_dir_opened() */
   void *dir_baton;
   apr_pool_t *dir_baton_pool;
 
@@ -223,6 +229,8 @@ typedef struct report_info_t
   const char *final_sha1_checksum;
   svn_txdelta_window_handler_t textdelta;
   void *textdelta_baton;
+  svn_stream_t *svndiff_decoder;
+  svn_stream_t *base64_decoder;
 
   /* Checksum for close_file */
   const char *final_checksum;
@@ -313,6 +321,9 @@ struct report_context_t {
   /* Do we want the server to send copyfrom args or not? */
   svn_boolean_t send_copyfrom_args;
 
+  /* Is the server sending everything in one response? */
+  svn_boolean_t send_all_mode;
+
   /* Is the server including properties inline for newly added
      files/dirs? */
   svn_boolean_t add_props_included;
@@ -342,16 +353,20 @@ struct report_context_t {
   report_dir_t *root_dir;
 
   /* number of pending GET requests */
-  unsigned int active_fetches;
+  unsigned int num_active_fetches;
 
   /* completed fetches (contains report_fetch_t) */
   svn_ra_serf__list_t *done_fetches;
 
   /* number of pending PROPFIND requests */
-  unsigned int active_propfinds;
+  unsigned int num_active_propfinds;
 
   /* completed PROPFIND requests (contains svn_ra_serf__handler_t) */
   svn_ra_serf__list_t *done_propfinds;
+  svn_ra_serf__list_t *done_dir_propfinds;
+
+  /* list of outstanding prop changes (contains report_dir_t) */
+  svn_ra_serf__list_t *active_dir_propfinds;
 
   /* list of files that only have prop changes (contains report_info_t) */
   svn_ra_serf__list_t *file_propchanges_only;
@@ -362,13 +377,155 @@ struct report_context_t {
   /* Are we done parsing the REPORT response? */
   svn_boolean_t done;
 
+  /* Did we receive all data from the network? */
+  svn_boolean_t report_received;
+
   /* Did we get a complete (non-truncated) report? */
   svn_boolean_t report_completed;
 
   /* The XML parser context for the REPORT response.  */
   svn_ra_serf__xml_parser_t *parser_ctx;
+
+  /* Did we close the root directory? */
+  svn_boolean_t closed_root;
+};
+
+
+#ifdef NOT_USED_YET
+
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t update_ttable[] = {
+  { INITIAL, S_, "update-report", UPDATE_REPORT,
+    FALSE, { NULL }, FALSE },
+
+  { UPDATE_REPORT, S_, "target-revision", TARGET_REVISION,
+    FALSE, { "rev", NULL }, TRUE },
+
+  { UPDATE_REPORT, S_, "open-directory", OPEN_DIR,
+    FALSE, { "rev", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "open-directory", OPEN_DIR,
+    FALSE, { "rev", "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "add-directory", ADD_DIR,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { ADD_DIR, S_, "add-directory", ADD_DIR,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "open-file", OPEN_FILE,
+    FALSE, { "rev", "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "add-file", ADD_FILE,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { ADD_DIR, S_, "add-file", ADD_FILE,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "delete-entry", OPEN_FILE,
+    FALSE, { "?rev", "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "absent-directory", ABSENT_DIR,
+    FALSE, { "name", NULL }, TRUE },
+
+  { ADD_DIR, S_, "absent-directory", ABSENT_DIR,
+    FALSE, { "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "absent-file", ABSENT_FILE,
+    FALSE, { "name", NULL }, TRUE },
+
+  { ADD_DIR, S_, "absent-file", ABSENT_FILE,
+    FALSE, { "name", NULL }, TRUE },
+
+  { 0 }
 };
 
+
+
+/* Conforms to svn_ra_serf__xml_opened_t  */
+static svn_error_t *
+update_opened(svn_ra_serf__xml_estate_t *xes,
+              void *baton,
+              int entered_state,
+              const svn_ra_serf__dav_props_t *tag,
+              apr_pool_t *scratch_pool)
+{
+  report_context_t *ctx = baton;
+
+  return SVN_NO_ERROR;
+}
+
+
+
+/* Conforms to svn_ra_serf__xml_closed_t  */
+static svn_error_t *
+update_closed(svn_ra_serf__xml_estate_t *xes,
+              void *baton,
+              int leaving_state,
+              const svn_string_t *cdata,
+              apr_hash_t *attrs,
+              apr_pool_t *scratch_pool)
+{
+  report_context_t *ctx = baton;
+
+  if (leaving_state == TARGET_REVISION)
+    {
+      const char *rev = apr_hash_get(attrs, "rev", APR_HASH_KEY_STRING);
+
+      SVN_ERR(ctx->update_editor->set_target_revision(ctx->update_baton,
+                                                      SVN_STR_TO_REV(rev),
+                                                      ctx->sess->pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Conforms to svn_ra_serf__xml_cdata_t  */
+static svn_error_t *
+update_cdata(svn_ra_serf__xml_estate_t *xes,
+             void *baton,
+             int current_state,
+             const char *data,
+             apr_size_t len,
+             apr_pool_t *scratch_pool)
+{
+  report_context_t *ctx = baton;
+
+  return SVN_NO_ERROR;
+}
+
+#endif /* NOT_USED_YET */
+
+
+/* Returns best connection for fetching files/properties. */
+static svn_ra_serf__connection_t *
+get_best_connection(report_context_t *ctx)
+{
+  svn_ra_serf__connection_t * conn;
+  int first_conn;
+
+  /* Skip the first connection if the REPORT response hasn't been completely
+     received yet. */
+  first_conn = ctx->report_received ? 0: 1;
+
+  if (ctx->sess->num_conns - first_conn == 1)
+    return ctx->sess->conns[first_conn];
+
+  /* Currently just cycle connections. In future we could store number of
+   * pending requests on each connection for better connection usage. */
+  conn = ctx->sess->conns[ctx->sess->cur_conn];
+
+  /* Switch our connection. */
+  ctx->sess->cur_conn++;
+
+  if (ctx->sess->cur_conn >= ctx->sess->num_conns)
+      ctx->sess->cur_conn = first_conn;
+
+  return conn;
+}
+
 
 /** Report state management helper **/
 
@@ -547,7 +704,7 @@ remove_dir_props(void *baton,
 /** Helpers to open and close directories */
 
 static svn_error_t*
-open_dir(report_dir_t *dir)
+ensure_dir_opened(report_dir_t *dir)
 {
   report_context_t *ctx = dir->report_context;
 
@@ -576,7 +733,7 @@ open_dir(report_dir_t *dir)
     }
   else
     {
-      SVN_ERR(open_dir(dir->parent_dir));
+      SVN_ERR(ensure_dir_opened(dir->parent_dir));
 
       dir->dir_baton_pool = svn_pool_create(dir->parent_dir->dir_baton_pool);
 
@@ -672,7 +829,7 @@ static svn_error_t *close_all_dirs(repor
 
   SVN_ERR_ASSERT(! dir->ref_count);
 
-  SVN_ERR(open_dir(dir));
+  SVN_ERR(ensure_dir_opened(dir));
 
   return close_dir(dir);
 }
@@ -817,7 +974,7 @@ open_updated_file(report_info_t *info,
   const svn_delta_editor_t *update_editor = ctx->update_editor;
 
   /* Ensure our parent is open. */
-  SVN_ERR(open_dir(info->dir));
+  SVN_ERR(ensure_dir_opened(info->dir));
   info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
 
   /* Expand our full name now if we haven't done so yet. */
@@ -1176,6 +1333,67 @@ handle_stream(serf_request_t *request,
   /* not reached */
 }
 
+/* Close the directory represented by DIR -- and any suitable parents
+   thereof -- if we are able to do so.  This is the case whenever:
+
+     - there are no remaining open items within the directory, and
+     - the directory's XML close tag has been processed (so we know
+       there are no more children to worry about in the future), and
+     - either:
+         - we aren't fetching properties for this directory, or
+         - we've already finished fetching those properties.
+*/
+static svn_error_t *
+maybe_close_dir_chain(report_dir_t *dir)
+{
+  report_dir_t *cur_dir = dir;
+
+  SVN_ERR(ensure_dir_opened(cur_dir));
+                  
+  while (cur_dir
+         && !cur_dir->ref_count
+         && cur_dir->tag_closed
+         && (!cur_dir->fetch_props || cur_dir->propfind_handler->done))
+    {
+      report_dir_t *parent = cur_dir->parent_dir;
+      report_context_t *report_context = cur_dir->report_context;
+      svn_boolean_t propfind_in_done_list = FALSE;
+      svn_ra_serf__list_t *done_list;
+
+      /* Make sure there are no references to this dir in the
+         active_dir_propfinds list.  If there are, don't close the
+         directory -- which would delete the pool from which the
+         relevant active_dir_propfinds list item is allocated -- and
+         of course don't crawl upward to check the parents for
+         a closure opportunity, either.  */
+      done_list = report_context->active_dir_propfinds;
+      while (done_list)
+        {
+          if (done_list->data == cur_dir)
+            {
+              propfind_in_done_list = TRUE;
+              break;
+            }
+          done_list = done_list->next;
+        }
+      if (propfind_in_done_list)
+        break;
+
+      SVN_ERR(close_dir(cur_dir));
+      if (parent)
+        {
+          parent->ref_count--;
+        }
+      else
+        {
+          report_context->closed_root = TRUE;
+        }
+      cur_dir = parent;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Open the file associated with INFO for editing, pass along any
    propchanges we've recorded for it, and then close the file. */
 static svn_error_t *
@@ -1190,6 +1408,10 @@ handle_propchange_only(report_info_t *in
 
   info->dir->ref_count--;
 
+  /* See if the parent directory of this file (and perhaps even
+     parents of that) can be closed now.  */
+  SVN_ERR(maybe_close_dir_chain(info->dir));
+
   return SVN_NO_ERROR;
 }
 
@@ -1214,6 +1436,10 @@ handle_local_content(report_info_t *info
 
   info->dir->ref_count--;
 
+  /* See if the parent directory of this fetched item (and
+     perhaps even parents of that) can be closed now. */
+  SVN_ERR(maybe_close_dir_chain(info->dir));
+
   return SVN_NO_ERROR;
 }
 
@@ -1226,18 +1452,7 @@ fetch_file(report_context_t *ctx, report
   svn_ra_serf__handler_t *handler;
 
   /* What connection should we go on? */
-  conn = ctx->sess->conns[ctx->sess->cur_conn];
-
-  /* go fetch info->name from DAV:checked-in */
-  info->url = svn_ra_serf__get_ver_prop(info->props, info->base_name,
-                                        info->base_rev, "DAV:", "checked-in");
-
-  if (!info->url)
-    {
-      return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
-                              _("The REPORT or PROPFIND response did not "
-                                "include the requested checked-in value"));
-    }
+  conn = get_best_connection(ctx);
 
   /* If needed, create the PROPFIND to retrieve the file's properties. */
   info->propfind_handler = NULL;
@@ -1253,7 +1468,7 @@ fetch_file(report_context_t *ctx, report
       /* Create a serf request for the PROPFIND.  */
       svn_ra_serf__request_create(info->propfind_handler);
 
-      ctx->active_propfinds++;
+      ctx->num_active_propfinds++;
     }
 
   /* If we've been asked to fetch the file or it's an add, do so.
@@ -1350,6 +1565,7 @@ fetch_file(report_context_t *ctx, report
           handler->conn = conn;
           handler->session = ctx->sess;
 
+          handler->custom_accept_encoding = TRUE;
           handler->header_delegate = headers_fetch;
           handler->header_delegate_baton = fetch_ctx;
 
@@ -1363,7 +1579,7 @@ fetch_file(report_context_t *ctx, report
 
           svn_ra_serf__request_create(handler);
 
-          ctx->active_fetches++;
+          ctx->num_active_fetches++;
         }
     }
   else if (info->propfind_handler)
@@ -1377,16 +1593,12 @@ fetch_file(report_context_t *ctx, report
     }
   else
     {
-      /* No propfind or GET request.  Just handle the prop changes now.
-
-         Note: we'll use INFO->POOL for the scratch_pool here since it will
-         be destroyed at the end of handle_propchange_only(). That pool
-         would be quite fine, but it is unclear how long INFO->POOL will
-         stick around since its lifetime and usage are unclear.  */
+      /* No propfind or GET request.  Just handle the prop changes now. */
       SVN_ERR(handle_propchange_only(info, info->pool));
     }
 
-  if (ctx->active_fetches + ctx->active_propfinds > REQUEST_COUNT_TO_PAUSE)
+  if (ctx->num_active_fetches + ctx->num_active_propfinds
+      > REQUEST_COUNT_TO_PAUSE)
     ctx->parser_ctx->paused = TRUE;
 
   return SVN_NO_ERROR;
@@ -1408,9 +1620,15 @@ start_report(svn_ra_serf__xml_parser_t *
 
   if (state == NONE && strcmp(name.name, "update-report") == 0)
     {
-      const char *val = svn_xml_get_attr_value("inline-props", attrs);
+      const char *val;
+
+      val = svn_xml_get_attr_value("inline-props", attrs);
       if (val && (strcmp(val, "true") == 0))
         ctx->add_props_included = TRUE;
+
+      val = svn_xml_get_attr_value("send-all", attrs);
+      if (val && (strcmp(val, "true") == 0))
+        ctx->send_all_mode = TRUE;
     }
   else if (state == NONE && strcmp(name.name, "target-revision") == 0)
     {
@@ -1613,7 +1831,11 @@ start_report(svn_ra_serf__xml_parser_t *
       info = push_state(parser, ctx, ADD_FILE);
 
       info->base_rev = SVN_INVALID_REVNUM;
-      info->fetch_file = TRUE;
+
+      /* If the server isn't in "send-all" mode, we should expect to
+         fetch contents for added files. */
+      if (! ctx->send_all_mode)
+        info->fetch_file = TRUE;
 
       /* If the server isn't included properties for added items,
          we'll need to fetch them ourselves. */
@@ -1657,7 +1879,7 @@ start_report(svn_ra_serf__xml_parser_t *
 
       info = parser->state->private;
 
-      SVN_ERR(open_dir(info->dir));
+      SVN_ERR(ensure_dir_opened(info->dir));
 
       tmppool = svn_pool_create(info->dir->dir_baton_pool);
 
@@ -1687,7 +1909,7 @@ start_report(svn_ra_serf__xml_parser_t *
 
       info = parser->state->private;
 
-      SVN_ERR(open_dir(info->dir));
+      SVN_ERR(ensure_dir_opened(info->dir));
 
       SVN_ERR(ctx->update_editor->absent_directory(
                                         svn_relpath_join(info->name, file_name,
@@ -1712,7 +1934,7 @@ start_report(svn_ra_serf__xml_parser_t *
 
       info = parser->state->private;
 
-      SVN_ERR(open_dir(info->dir));
+      SVN_ERR(ensure_dir_opened(info->dir));
 
       SVN_ERR(ctx->update_editor->absent_file(
                                         svn_relpath_join(info->name, file_name,
@@ -1853,7 +2075,31 @@ start_report(svn_ra_serf__xml_parser_t *
              addition to <fetch-file>s and such) when *not* in
              "send-all" mode.  As a client, we're smart enough to know
              that's wrong, so we'll just ignore these tags. */
-          ;
+          if (ctx->send_all_mode)
+            {
+              const svn_delta_editor_t *update_editor = ctx->update_editor;
+
+              info = push_state(parser, ctx, TXDELTA);
+
+              if (! info->file_baton)
+                {
+                  SVN_ERR(open_updated_file(info, FALSE, info->pool));
+                }
+
+              info->base_checksum = svn_xml_get_attr_value("base-checksum",
+                                                           attrs);
+              SVN_ERR(update_editor->apply_textdelta(info->file_baton,
+                                                     info->base_checksum,
+                                                     info->editor_pool,
+                                                     &info->textdelta,
+                                                     &info->textdelta_baton));
+              info->svndiff_decoder = svn_txdelta_parse_svndiff(
+                                          info->textdelta,
+                                          info->textdelta_baton,
+                                          TRUE, info->pool);
+              info->base64_decoder = svn_base64_decode(info->svndiff_decoder,
+                                                       info->pool);
+            }
         }
       else
         {
@@ -1937,25 +2183,29 @@ end_report(svn_ra_serf__xml_parser_t *pa
        */
       if (info->dir->fetch_props)
         {
-          /* Unconditionally set fetch_props now. */
-          info->dir->fetch_props = TRUE;
-
+          svn_ra_serf__list_t *list_item;
+ 
           SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind_handler,
                                              info->dir->props, ctx->sess,
-                                             ctx->sess->conns[ctx->sess->cur_conn],
+                                             get_best_connection(ctx),
                                              info->dir->url,
                                              ctx->target_rev, "0",
                                              all_props,
-                                             &ctx->done_propfinds,
+                                             &ctx->done_dir_propfinds,
                                              info->dir->pool));
           SVN_ERR_ASSERT(info->dir->propfind_handler);
 
           /* Create a serf request for the PROPFIND.  */
           svn_ra_serf__request_create(info->dir->propfind_handler);
 
-          ctx->active_propfinds++;
+          ctx->num_active_propfinds++;
 
-          if (ctx->active_fetches + ctx->active_propfinds
+          list_item = apr_pcalloc(info->dir->pool, sizeof(*list_item));
+          list_item->data = info->dir;
+          list_item->next = ctx->active_dir_propfinds;
+          ctx->active_dir_propfinds = list_item;
+
+          if (ctx->num_active_fetches + ctx->num_active_propfinds
               > REQUEST_COUNT_TO_PAUSE)
             ctx->parser_ctx->paused = TRUE;
         }
@@ -1964,6 +2214,12 @@ end_report(svn_ra_serf__xml_parser_t *pa
           info->dir->propfind_handler = NULL;
         }
 
+      /* See if this directory (and perhaps even parents of that) can
+         be closed now.  This is likely to be the case only if we
+         didn't need to contact the server for supplemental
+         information required to handle any of this directory's
+         children.  */
+      SVN_ERR(maybe_close_dir_chain(info->dir));
       svn_ra_serf__xml_pop_state(parser);
     }
   else if (state == OPEN_FILE && strcmp(name.name, "open-file") == 0)
@@ -2037,13 +2293,89 @@ end_report(svn_ra_serf__xml_parser_t *pa
           info->delta_base = value ? value->data : NULL;
         }
 
-      SVN_ERR(fetch_file(ctx, info));
+      /* go fetch info->name from DAV:checked-in */
+      info->url = svn_ra_serf__get_ver_prop(info->props, info->base_name,
+                                            info->base_rev, "DAV:", "checked-in");
+      if (!info->url)
+        {
+          return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                                  _("The REPORT or PROPFIND response did not "
+                                    "include the requested checked-in value"));
+        }
+
+      /* If the server is in "send-all" mode, we might have opened the
+         file when we started seeing content for it.  If we didn't get
+         any content for it, we still need to open the file.  But in
+         any case, we can then immediately close it.  */
+      if (ctx->send_all_mode)
+        {
+          if (! info->file_baton)
+            {
+              SVN_ERR(open_updated_file(info, FALSE, info->pool));
+            }
+          SVN_ERR(close_updated_file(info, info->pool));
+          info->dir->ref_count--;
+        }
+      /* Otherwise, if the server is *not* in "send-all" mode, we
+         should be at a point where we can queue up any auxiliary
+         content-fetching requests.  */
+      else
+        {
+          SVN_ERR(fetch_file(ctx, info));
+        }
+
       svn_ra_serf__xml_pop_state(parser);
     }
   else if (state == ADD_FILE && strcmp(name.name, "add-file") == 0)
     {
-      /* We should have everything we need to fetch the file. */
-      SVN_ERR(fetch_file(ctx, parser->state->private));
+      report_info_t *info = parser->state->private;
+
+      /* go fetch info->name from DAV:checked-in */
+      info->url = svn_ra_serf__get_ver_prop(info->props, info->base_name,
+                                            info->base_rev, "DAV:", "checked-in");
+      if (!info->url)
+        {
+          return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                                  _("The REPORT or PROPFIND response did not "
+                                    "include the requested checked-in value"));
+        }
+
+      /* If the server is in "send-all" mode, we might have opened the
+         file when we started seeing content for it.  If we didn't get
+         any content for it, we still need to open the file.  But in
+         any case, we can then immediately close it.  */
+      if (ctx->send_all_mode)
+        {
+          if (! info->file_baton)
+            {
+              SVN_ERR(open_updated_file(info, FALSE, info->pool));
+            }
+          SVN_ERR(close_updated_file(info, info->pool));
+          info->dir->ref_count--;
+        }
+      /* Otherwise, if the server is *not* in "send-all" mode, we
+         should be at a point where we can queue up any auxiliary
+         content-fetching requests.  */
+      else
+        {
+          SVN_ERR(fetch_file(ctx, info));
+        }
+
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == TXDELTA && strcmp(name.name, "txdelta") == 0)
+    {
+      report_info_t *info = parser->state->private;
+
+      /* Pre 1.2, mod_dav_svn was using <txdelta> tags (in addition to
+         <fetch-file>s and such) when *not* in "send-all" mode.  As a
+         client, we're smart enough to know that's wrong, so when not
+         in "receiving-all" mode, we'll ignore these tags. */
+      if (ctx->send_all_mode)
+        {
+          SVN_ERR(svn_stream_close(info->base64_decoder));
+        }
+
       svn_ra_serf__xml_pop_state(parser);
     }
   else if (state == PROP)
@@ -2170,6 +2502,27 @@ cdata_report(svn_ra_serf__xml_parser_t *
 
       svn_stringbuf_appendbytes(info->prop_value, data, len);
     }
+  else if (parser->state->current_state == TXDELTA)
+    {
+      /* Pre 1.2, mod_dav_svn was using <txdelta> tags (in addition to
+         <fetch-file>s and such) when *not* in "send-all" mode.  As a
+         client, we're smart enough to know that's wrong, so when not
+         in "receiving-all" mode, we'll ignore these tags. */
+      if (ctx->send_all_mode)
+        {
+          apr_size_t nlen = len;
+          report_info_t *info = parser->state->private;
+
+          SVN_ERR(svn_stream_write(info->base64_decoder, data, &nlen));
+          if (nlen != len)
+            {
+              /* Short write without associated error?  "Can't happen." */
+              return svn_error_createf(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL,
+                                       _("Error writing to '%s': unexpected EOF"),
+                                       info->name);
+            }
+        }
+    }
 
   return SVN_NO_ERROR;
 }
@@ -2310,16 +2663,16 @@ link_path(void *report_baton,
 #define REQS_PER_CONN 8
 
 /** This function creates a new connection for this serf session, but only
- * if the number of ACTIVE_REQS > REQS_PER_CONN or if there currently is
+ * if the number of NUM_ACTIVE_REQS > REQS_PER_CONN or if there currently is
  * only one main connection open.
  */
 static svn_error_t *
-open_connection_if_needed(svn_ra_serf__session_t *sess, int active_reqs)
+open_connection_if_needed(svn_ra_serf__session_t *sess, int num_active_reqs)
 {
   /* For each REQS_PER_CONN outstanding requests open a new connection, with
    * a minimum of 1 extra connection. */
   if (sess->num_conns == 1 ||
-      ((active_reqs / REQS_PER_CONN) > sess->num_conns))
+      ((num_active_reqs / REQS_PER_CONN) > sess->num_conns))
     {
       int cur = sess->num_conns;
       apr_status_t status;
@@ -2365,21 +2718,6 @@ create_update_report_body(serf_bucket_t 
 }
 
 static svn_error_t *
-headers_report(serf_bucket_t *headers,
-               void *baton,
-               apr_pool_t *pool)
-{
-  report_context_t *report = baton;
-
-  if (report->sess->using_compression)
-    {
-      serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
-    }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
 finish_report(void *report_baton,
               apr_pool_t *pool)
 {
@@ -2388,11 +2726,10 @@ finish_report(void *report_baton,
   svn_ra_serf__handler_t *handler;
   svn_ra_serf__xml_parser_t *parser_ctx;
   const char *report_target;
-  svn_boolean_t closed_root;
   svn_stringbuf_t *buf = NULL;
   apr_pool_t *iterpool = svn_pool_create(pool);
   svn_error_t *err;
-  apr_short_interval_time_t waittime_left = sess->timeout;
+  apr_interval_time_t waittime_left = sess->timeout;
 
   svn_xml_make_close_tag(&buf, iterpool, "S:update-report");
   SVN_ERR(svn_io_file_write_full(report->body_file, buf->data, buf->len,
@@ -2427,8 +2764,6 @@ finish_report(void *report_baton,
   handler->body_type = "text/xml";
   handler->conn = sess->conns[0];
   handler->session = sess;
-  handler->header_delegate = headers_report;
-  handler->header_delegate_baton = report;
 
   parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
 
@@ -2451,14 +2786,15 @@ finish_report(void *report_baton,
   SVN_ERR(open_connection_if_needed(sess, 0));
 
   sess->cur_conn = 1;
-  closed_root = FALSE;
 
   /* Note that we may have no active GET or PROPFIND requests, yet the
      processing has not been completed. This could be from a delay on the
      network or because we've spooled the entire response into our "pending"
      content of the XML parser. The DONE flag will get set when all the
      XML content has been received *and* parsed.  */
-  while (!report->done || report->active_fetches || report->active_propfinds)
+  while (!report->done
+         || report->num_active_fetches
+         || report->num_active_propfinds)
     {
       apr_pool_t *iterpool_inner;
       svn_ra_serf__list_t *done_list;
@@ -2497,14 +2833,17 @@ finish_report(void *report_baton,
           err = SVN_NO_ERROR;
           status = 0;
 
-          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
-            {
-              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
-            }
-          else
+          if (sess->timeout)
             {
-              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
-                                      _("Connection timed out"));
+              if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+                {
+                  waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+                }
+              else
+                {
+                  return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                          _("Connection timed out"));
+                }
             }
         }
       else
@@ -2520,21 +2859,18 @@ finish_report(void *report_baton,
 
       /* Open extra connections if we have enough requests to send. */
       if (sess->num_conns < MAX_NR_OF_CONNS)
-        SVN_ERR(open_connection_if_needed(sess, report->active_fetches +
-                                          report->active_propfinds));
-
-      /* Switch our connection. */
-      if (!report->done)
-         if (++sess->cur_conn == sess->num_conns)
-             sess->cur_conn = 1;
+        SVN_ERR(open_connection_if_needed(sess, report->num_active_fetches +
+                                          report->num_active_propfinds));
 
-      /* prune our propfind list if they are done. */
+      /* Prune completed file PROPFINDs. */
       done_list = report->done_propfinds;
       while (done_list)
         {
+          svn_ra_serf__list_t *next_done = done_list->next;
+
           svn_pool_clear(iterpool_inner);
 
-          report->active_propfinds--;
+          report->num_active_propfinds--;
 
           /* If we have some files that we won't be fetching the content
            * for, ensure that we update the file with any altered props.
@@ -2566,82 +2902,131 @@ finish_report(void *report_baton,
                 {
                   report_info_t *info = cur->data;
 
-                  /* If we've got cached file content for this file,
-                     take care of the locally collected properties and
-                     file content at once.  Otherwise, just deal with
-                     the collected properties. */
-                  if (info->cached_contents)
+                  if (!prev)
                     {
-                      SVN_ERR(handle_local_content(info, iterpool_inner));
+                      report->file_propchanges_only = cur->next;
                     }
                   else
                     {
-                      SVN_ERR(handle_propchange_only(info, iterpool_inner));
+                      prev->next = cur->next;
                     }
 
-                  if (!prev)
+                  /* If we've got cached file content for this file,
+                     take care of the locally collected properties and
+                     file content at once.  Otherwise, just deal with
+                     the collected properties.
+
+                     NOTE:  These functions below could delete
+                     info->dir->pool (via maybe_close_dir_chain()),
+                     from which is allocated the list item in
+                     report->file_propchanges_only.
+                  */
+                  if (info->cached_contents)
                     {
-                      report->file_propchanges_only = cur->next;
+                      SVN_ERR(handle_local_content(info, iterpool_inner));
                     }
                   else
                     {
-                      prev->next = cur->next;
+                      SVN_ERR(handle_propchange_only(info, iterpool_inner));
                     }
                 }
             }
 
-          done_list = done_list->next;
+          done_list = next_done;
         }
       report->done_propfinds = NULL;
 
-      /* prune our fetches list if they are done. */
+      /* Prune completed fetches from our list. */
       done_list = report->done_fetches;
       while (done_list)
         {
           report_fetch_t *done_fetch = done_list->data;
+          svn_ra_serf__list_t *next_done = done_list->next;
           report_dir_t *cur_dir;
 
-          /* decrease our parent's directory refcount. */
+          /* Decrease the refcount in the parent directory of the file
+             whose fetch has completed. */
           cur_dir = done_fetch->info->dir;
           cur_dir->ref_count--;
 
           /* Decrement our active fetch count. */
-          report->active_fetches--;
+          report->num_active_fetches--;
 
-          done_list = done_list->next;
+          /* See if the parent directory of this fetched item (and
+             perhaps even parents of that) can be closed now. 
 
-          /* If we have a valid directory and
-           * we have no open items in this dir and
-           * we've closed the directory tag (no more children can be added)
-           * and either:
-           *   we know we won't be fetching props or
-           *   we've already completed the propfind
-           * then, we know it's time for us to close this directory.
-           */
-          while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed
-                 && (!cur_dir->fetch_props
-                     || cur_dir->propfind_handler->done))
+             NOTE:  This could delete cur_dir->pool, from which is
+             allocated the list item in report->done_fetches.
+          */
+          SVN_ERR(maybe_close_dir_chain(cur_dir));
+
+          done_list = next_done;
+        }
+      report->done_fetches = NULL;
+
+      /* Prune completed directory PROPFINDs. */
+      done_list = report->done_dir_propfinds;
+      while (done_list)
+        {
+          svn_ra_serf__list_t *next_done = done_list->next;
+
+          report->num_active_propfinds--;
+
+          if (report->active_dir_propfinds)
             {
-              report_dir_t *parent = cur_dir->parent_dir;
+              svn_ra_serf__list_t *cur, *prev;
+
+              prev = NULL;
+              cur = report->active_dir_propfinds;
 
-              SVN_ERR(close_dir(cur_dir));
-              if (parent)
+              while (cur)
                 {
-                  parent->ref_count--;
+                  report_dir_t *item = cur->data;
+
+                  if (item->propfind_handler == done_list->data)
+                    {
+                      break;
+                    }
+
+                  prev = cur;
+                  cur = cur->next;
                 }
-              else
+              SVN_ERR_ASSERT(cur); /* we expect to find a matching propfind! */
+
+              /* If we found a match, set the new props and remove this
+               * propchange from our list.
+               */
+              if (cur)
                 {
-                  closed_root = TRUE;
+                  report_dir_t *cur_dir = cur->data;
+
+                  if (!prev)
+                    {
+                      report->active_dir_propfinds = cur->next;
+                    }
+                  else
+                    {
+                      prev->next = cur->next;
+                    }
+
+                  /* See if this directory (and perhaps even parents of that)
+                     can be closed now.
+
+                     NOTE:  This could delete cur_dir->pool, from which is
+                     allocated the list item in report->active_dir_propfinds.
+                  */
+                  SVN_ERR(maybe_close_dir_chain(cur_dir));
                 }
-              cur_dir = parent;
             }
+
+          done_list = next_done;
         }
-      report->done_fetches = NULL;
+      report->done_dir_propfinds = NULL;
 
       /* If the parser is paused, and the number of active requests has
          dropped far enough, then resume parsing.  */
       if (parser_ctx->paused
-          && (report->active_fetches + report->active_propfinds
+          && (report->num_active_fetches + report->num_active_propfinds
               < REQUEST_COUNT_TO_RESUME))
         parser_ctx->paused = FALSE;
 
@@ -2649,25 +3034,29 @@ finish_report(void *report_baton,
          present (we can't know for sure because of the private structure),
          then go process the pending content.  */
       if (!parser_ctx->paused && parser_ctx->pending != NULL)
-        SVN_ERR(svn_ra_serf__process_pending(parser_ctx, iterpool_inner));
+        SVN_ERR(svn_ra_serf__process_pending(parser_ctx,
+                                             &report->report_received,
+                                             iterpool_inner));
 
       /* Debugging purposes only! */
       for (i = 0; i < sess->num_conns; i++)
         {
-         serf_debug__closed_conn(sess->conns[i]->bkt_alloc);
+          serf_debug__closed_conn(sess->conns[i]->bkt_alloc);
         }
     }
 
-  /* Ensure that we opened and closed our root dir and that we closed
-   * all of our children. */
-  if (closed_root == FALSE && report->root_dir != NULL)
-    {
-      SVN_ERR(close_all_dirs(report->root_dir));
-    }
-
   /* If we got a complete report, close the edit.  Otherwise, abort it. */
   if (report->report_completed)
-    err = report->update_editor->close_edit(report->update_baton, iterpool);
+    {
+      /* Ensure that we opened and closed our root dir and that we closed
+       * all of our children. */
+      if (report->closed_root == FALSE && report->root_dir != NULL)
+        {
+          SVN_ERR(close_all_dirs(report->root_dir));
+        }
+
+      err = report->update_editor->close_edit(report->update_baton, iterpool);
+    }
   else
     err = svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
                            _("Missing update-report close tag"));
@@ -2772,9 +3161,19 @@ make_update_reporter(svn_ra_session_t *r
                                    svn_io_file_del_on_pool_cleanup,
                                    report->pool, scratch_pool));
 
+#ifdef SVN_RA_SERF__UPDATES_SEND_ALL
+  svn_xml_make_open_tag(&buf, scratch_pool, svn_xml_normal, "S:update-report",
+                        "xmlns:S", SVN_XML_NAMESPACE, "send-all", "true",
+                        NULL);
+#else
   svn_xml_make_open_tag(&buf, scratch_pool, svn_xml_normal, "S:update-report",
                         "xmlns:S", SVN_XML_NAMESPACE,
                         NULL);
+  /* Subversion 1.8+ servers can be told to send properties for newly
+     added items inline even when doing a skelta response. */
+  make_simple_xml_tag(&buf, "S:include-props", "yes", scratch_pool);
+#endif
+
 
   make_simple_xml_tag(&buf, "S:src-path", report->source, scratch_pool);
 
@@ -2813,9 +3212,18 @@ make_update_reporter(svn_ra_session_t *r
       make_simple_xml_tag(&buf, "S:recursive", "no", scratch_pool);
     }
 
-  /* Subversion 1.8+ servers can be told to send properties for newly
-     added items inline even when doing a skelta response. */
-  make_simple_xml_tag(&buf, "S:include-props", "yes", scratch_pool);
+  /* When in 'send-all' mode, mod_dav_svn will assume that it should
+     calculate and transmit real text-deltas (instead of empty windows
+     that merely indicate "text is changed") unless it finds this
+     element.  When not in 'send-all' mode, mod_dav_svn will never
+     send text-deltas at all.
+
+     NOTE: Do NOT count on servers actually obeying this, as some exist
+     which obey send-all, but do not check for this directive at all! */
+  if (! text_deltas)
+    {
+      make_simple_xml_tag(&buf, "S:text-deltas", "no", scratch_pool);
+    }
 
   make_simple_xml_tag(&buf, "S:depth", svn_depth_to_word(depth), scratch_pool);
 
@@ -3081,6 +3489,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
           handler->conn = conn;
           handler->session = session;
 
+          handler->custom_accept_encoding = TRUE;
           handler->header_delegate = headers_fetch;
           handler->header_delegate_baton = stream_ctx;
 

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/util.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_serf/util.c Tue Dec  4 15:35:13 2012
@@ -636,6 +636,7 @@ setup_serf_req(serf_request_t *request,
                svn_ra_serf__session_t *session,
                const char *method, const char *url,
                serf_bucket_t *body_bkt, const char *content_type,
+               const char *accept_encoding,
                apr_pool_t *request_pool,
                apr_pool_t *scratch_pool)
 {
@@ -656,6 +657,10 @@ setup_serf_req(serf_request_t *request,
       SVN_ERR(svn_ra_serf__copy_into_spillbuf(&buf, body_bkt,
                                               request_pool,
                                               scratch_pool));
+      /* Destroy original bucket since it content is already copied 
+         to spillbuf. */
+      serf_bucket_destroy(body_bkt);
+
       body_bkt = svn_ra_serf__create_sb_bucket(buf, allocator,
                                                request_pool,
                                                scratch_pool);
@@ -696,6 +701,11 @@ setup_serf_req(serf_request_t *request,
       serf_bucket_headers_setn(*hdrs_bkt, "Connection", "keep-alive");
 #endif
 
+  if (accept_encoding)
+    {
+      serf_bucket_headers_setn(*hdrs_bkt, "Accept-Encoding", accept_encoding);
+    }
+
   /* These headers need to be sent with every request; see issue #3255
      ("mod_dav_svn does not pass client capabilities to start-commit
      hooks") for why. */
@@ -712,7 +722,7 @@ svn_ra_serf__context_run_wait(svn_boolea
                               apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool;
-  apr_short_interval_time_t waittime_left = sess->timeout;
+  apr_interval_time_t waittime_left = sess->timeout;
   
   assert(sess->pending_error == SVN_NO_ERROR);
 
@@ -745,14 +755,17 @@ svn_ra_serf__context_run_wait(svn_boolea
           err = SVN_NO_ERROR;
           status = 0;
 
-          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+          if (sess->timeout)
             {
-              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
-            }
-          else
-            {
-              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
-                                      _("Connection timed out"));
+              if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+                {
+                  waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+                }
+              else 
+                {
+                  return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                          _("Connection timed out"));
+                }
             }
         }
       else
@@ -1389,45 +1402,65 @@ xml_parser_cleanup(void *baton)
   return APR_SUCCESS;
 }
 
+/* Limit the amount of pending content to parse at once to < 100KB per
+   iteration. This number is chosen somewhat arbitrarely. Making it lower
+   will have a drastical negative impact on performance, whereas increasing it
+   increases the risk for connection timeouts.
+ */
+#define PENDING_TO_PARSE PARSE_CHUNK_SIZE * 5
+
 svn_error_t *
 svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
+                             svn_boolean_t *network_eof,
                              apr_pool_t *scratch_pool)
 {
+  svn_boolean_t pending_empty = FALSE;
+  apr_size_t cur_read = 0;
+
   /* Fast path exit: already paused, nothing to do, or already done.  */
   if (parser->paused || parser->pending == NULL || *parser->done)
-    return SVN_NO_ERROR;
-
-  /* ### it is possible that the XML parsing of the pending content is
-     ### so slow, and that we don't return to reading the connection
-     ### fast enough... that the server will disconnect us. right now,
-     ### that is highly improbable, but is noted for future's sake.
-     ### should that ever happen, the loops in this function can simply
-     ### terminate after N seconds.  */
+    {
+      *network_eof = parser->pending ? parser->pending->network_eof : FALSE;
+      return SVN_NO_ERROR;
+    }
 
-  /* Try to read everything from the spillbuf.  */
-  while (TRUE)
+  /* Parsing the pending conten in the spillbuf will result in many disc i/o
+     operations. This can be so slow that we don't run the network event
+     processing loop often enough, resulting in timed out connections.
+   
+     So we limit the amounts of bytes parsed per iteration.
+   */
+  while (cur_read < PENDING_TO_PARSE)
     {
       const char *data;
       apr_size_t len;
 
       /* Get a block of content, stopping the loop when we run out.  */
       SVN_ERR(svn_spillbuf__read(&data, &len, parser->pending->buf,
-                                 scratch_pool));
-      if (data == NULL)
-        break;
-
-      /* Inject the content into the XML parser.  */
-      SVN_ERR(inject_to_parser(parser, data, len, NULL));
-
-      /* If the XML parsing callbacks paused us, then we're done for now.  */
-      if (parser->paused)
-        return SVN_NO_ERROR;
+                             scratch_pool));
+      if (data)
+        {
+          /* Inject the content into the XML parser.  */
+          SVN_ERR(inject_to_parser(parser, data, len, NULL));
+
+          /* If the XML parsing callbacks paused us, then we're done for now.  */
+          if (parser->paused)
+            break;
+
+          cur_read += len;
+        }
+      else
+        {
+          /* The buffer is empty. */
+          pending_empty = TRUE;
+          break;
+        }
     }
-  /* All stored content (memory and file) has now been exhausted.  */
 
   /* If the PENDING structures are empty *and* we consumed all content from
      the network, then we're completely done with the parsing.  */
-  if (parser->pending->network_eof)
+  if (pending_empty &&
+      parser->pending->network_eof)
     {
       SVN_ERR_ASSERT(parser->xmlp != NULL);
 
@@ -1440,8 +1473,11 @@ svn_ra_serf__process_pending(svn_ra_serf
       add_done_item(parser);
     }
 
+  *network_eof = parser->pending ? parser->pending->network_eof : FALSE;
+
   return SVN_NO_ERROR;
 }
+#undef PENDING_TO_PARSE
 
 
 /* ### this is still broken conceptually. just shifting incrementally... */
@@ -1874,10 +1910,12 @@ handle_response(serf_request_t *request,
   handler->conn->last_status_code = handler->sline.code;
 
   if (handler->sline.code == 405
+      || handler->sline.code == 408
       || handler->sline.code == 409
       || handler->sline.code >= 500)
     {
       /* 405 Method Not allowed.
+         408 Request Timeout
          409 Conflict: can indicate a hook error.
          5xx (Internal) Server error. */
       serf_bucket_t *hdrs;
@@ -2051,6 +2089,7 @@ setup_request(serf_request_t *request,
 {
   serf_bucket_t *body_bkt;
   serf_bucket_t *headers_bkt;
+  const char *accept_encoding;
 
   if (handler->body_delegate)
     {
@@ -2065,9 +2104,23 @@ setup_request(serf_request_t *request,
       body_bkt = NULL;
     }
 
+  if (handler->custom_accept_encoding)
+    {
+      accept_encoding = NULL;
+    }
+  else if (handler->session->using_compression)
+    {
+      /* Accept gzip compression if enabled. */
+      accept_encoding = "gzip";
+    }
+  else
+    {
+      accept_encoding = NULL;
+    }
+
   SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
                          handler->session, handler->method, handler->path,
-                         body_bkt, handler->body_type,
+                         body_bkt, handler->body_type, accept_encoding,
                          request_pool, scratch_pool));
 
   if (handler->header_delegate)

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/client.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/client.c Tue Dec  4 15:35:13 2012
@@ -325,6 +325,11 @@ static svn_ra_reporter3_t ra_svn_reporte
   ra_svn_abort_report
 };
 
+/* Set *REPORTER and *REPORT_BATON to a new reporter which will drive
+ * EDITOR/EDIT_BATON when it gets the finish_report() call.
+ *
+ * Allocate the new reporter in POOL.
+ */
 static svn_error_t *
 ra_svn_get_reporter(svn_ra_svn__session_baton_t *sess_baton,
                     apr_pool_t *pool,

Modified: subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_ra_svn/cyrus_auth.c Tue Dec  4 15:35:13 2012
@@ -871,12 +871,12 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__se
 
   /* The username callback. */
   callbacks[0].id = SASL_CB_AUTHNAME;
-  callbacks[0].proc = (void*)get_username_cb;
+  callbacks[0].proc = (int (*)(void))get_username_cb;
   callbacks[0].context = &cred_baton;
 
   /* The password callback. */
   callbacks[1].id = SASL_CB_PASS;
-  callbacks[1].proc = (void*)get_password_cb;
+  callbacks[1].proc = (int (*)(void))get_password_cb;
   callbacks[1].context = &cred_baton;
 
   /* Mark the end of the array. */

Modified: subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_repos/fs-wrap.c Tue Dec  4 15:35:13 2012
@@ -743,6 +743,7 @@ svn_error_t *
 svn_repos_fs_get_inherited_props(apr_array_header_t **inherited_props_p,
                                  svn_fs_root_t *root,
                                  const char *path,
+                                 const char *propname,
                                  svn_repos_authz_func_t authz_read_func,
                                  void *authz_read_baton,
                                  apr_pool_t *result_pool,
@@ -757,7 +758,7 @@ svn_repos_fs_get_inherited_props(apr_arr
   while (!(parent_path[0] == '/' && parent_path[1] == '\0'))
     {
       svn_boolean_t allowed = TRUE;
-      apr_hash_t *parent_properties;
+      apr_hash_t *parent_properties = NULL;
 
       svn_pool_clear(iterpool);
       parent_path = svn_fspath__dirname(parent_path, scratch_pool);
@@ -767,8 +768,25 @@ svn_repos_fs_get_inherited_props(apr_arr
                                 authz_read_baton, iterpool));
       if (allowed)
         {
-          SVN_ERR(svn_fs_node_proplist(&parent_properties, root,
-                                       parent_path, result_pool));
+          if (propname)
+            {
+              svn_string_t *propval;
+
+              SVN_ERR(svn_fs_node_prop(&propval, root, parent_path, propname,
+                                       result_pool));
+              if (propval)
+                {
+                  parent_properties = apr_hash_make(result_pool);
+                  apr_hash_set(parent_properties, propname,
+                               APR_HASH_KEY_STRING, propval);
+                }
+            }
+          else
+            {
+              SVN_ERR(svn_fs_node_proplist(&parent_properties, root,
+                                           parent_path, result_pool));
+            }
+
           if (parent_properties && apr_hash_count(parent_properties))
             {
               svn_prop_inherited_item_t *i_props =

Modified: subversion/branches/wc-collate-path/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_repos/reporter.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_repos/reporter.c Tue Dec  4 15:35:13 2012
@@ -717,11 +717,13 @@ delta_files(report_baton_t *b, void *fil
              zero-copy code. */
           if (b->zero_copy_limit > 0 && s_path == NULL)
             {
-              zero_copy_baton_t baton = { b->zero_copy_limit
-                                        , dhandler
-                                        , dbaton
-                                        , FALSE};
+              zero_copy_baton_t baton;
               svn_boolean_t called = FALSE;
+
+              baton.zero_copy_limit = b->zero_copy_limit;
+              baton.dhandler = dhandler;
+              baton.dbaton = dbaton;
+              baton.zero_copy_succeeded = FALSE;
               SVN_ERR(svn_fs_try_process_file_contents(&called,
                                                        b->t_root, t_path,
                                                        send_zero_copy_delta,

Modified: subversion/branches/wc-collate-path/subversion/libsvn_subr/cache_config.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_subr/cache_config.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_subr/cache_config.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_subr/cache_config.c Tue Dec  4 15:35:13 2012
@@ -124,7 +124,7 @@ svn_cache__get_global_membuffer_cache(vo
           FALSE,
           pool);
 
-      /* Some error occured. Most likely it's an OOM error but we don't
+      /* Some error occurred. Most likely it's an OOM error but we don't
        * really care. Simply release all cache memory and disable caching
        */
       if (err)

Modified: subversion/branches/wc-collate-path/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/wc-collate-path/subversion/libsvn_subr/cmdline.c?rev=1416996&r1=1416995&r2=1416996&view=diff
==============================================================================
--- subversion/branches/wc-collate-path/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/wc-collate-path/subversion/libsvn_subr/cmdline.c Tue Dec  4 15:35:13 2012
@@ -52,6 +52,9 @@
 #include "svn_xml.h"
 #include "svn_base64.h"
 #include "svn_config.h"
+#include "svn_sorts.h"
+#include "svn_props.h"
+#include "svn_subst.h"
 
 #include "private/svn_cmdline_private.h"
 #include "private/svn_utf_private.h"
@@ -758,3 +761,165 @@ svn_cmdline__apply_config_options(apr_ha
 
   return SVN_NO_ERROR;
 }
+
+/* Return a copy, allocated in POOL, of the next line of text from *STR
+ * up to and including a CR and/or an LF. Change *STR to point to the
+ * remainder of the string after the returned part. If there are no
+ * characters to be returned, return NULL; never return an empty string.
+ */
+static const char *
+next_line(const char **str, apr_pool_t *pool)
+{
+  const char *start = *str;
+  const char *p = *str;
+
+  /* n.b. Throughout this fn, we never read any character after a '\0'. */
+  /* Skip over all non-EOL characters, if any. */
+  while (*p != '\r' && *p != '\n' && *p != '\0')
+    p++;
+  /* Skip over \r\n or \n\r or \r or \n, if any. */
+  if (*p == '\r' || *p == '\n')
+    {
+      char c = *p++;
+
+      if ((c == '\r' && *p == '\n') || (c == '\n' && *p == '\r'))
+        p++;
+    }
+
+  /* Now p points after at most one '\n' and/or '\r'. */
+  *str = p;
+
+  if (p == start)
+    return NULL;
+
+  return svn_string_ncreate(start, p - start, pool)->data;
+}
+
+const char *
+svn_cmdline__indent_string(const char *str,
+                           const char *indent,
+                           apr_pool_t *pool)
+{
+  svn_stringbuf_t *out = svn_stringbuf_create_empty(pool);
+  const char *line;
+
+  while ((line = next_line(&str, pool)))
+    {
+      svn_stringbuf_appendcstr(out, indent);
+      svn_stringbuf_appendcstr(out, line);
+    }
+  return out->data;
+}
+
+svn_error_t *
+svn_cmdline__print_prop_hash(svn_stream_t *out,
+                             apr_hash_t *prop_hash,
+                             svn_boolean_t names_only,
+                             apr_pool_t *pool)
+{
+  apr_array_header_t *sorted_props;
+  int i;
+
+  sorted_props = svn_sort__hash(prop_hash, svn_sort_compare_items_lexically,
+                                pool);
+  for (i = 0; i < sorted_props->nelts; i++)
+    {
+      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
+      const char *pname = item.key;
+      svn_string_t *propval = item.value;
+      const char *pname_stdout;
+
+      if (svn_prop_needs_translation(pname))
+        SVN_ERR(svn_subst_detranslate_string(&propval, propval,
+                                             TRUE, pool));
+
+      SVN_ERR(svn_cmdline_cstring_from_utf8(&pname_stdout, pname, pool));
+
+      if (out)
+        {
+          pname_stdout = apr_psprintf(pool, "  %s\n", pname_stdout);
+          SVN_ERR(svn_subst_translate_cstring2(pname_stdout, &pname_stdout,
+                                              APR_EOL_STR,  /* 'native' eol */
+                                              FALSE, /* no repair */
+                                              NULL,  /* no keywords */
+                                              FALSE, /* no expansion */
+                                              pool));
+
+          SVN_ERR(svn_stream_puts(out, pname_stdout));
+        }
+      else
+        {
+          /* ### We leave these printfs for now, since if propval wasn't
+             translated above, we don't know anything about its encoding.
+             In fact, it might be binary data... */
+          printf("  %s\n", pname_stdout);
+        }
+
+      if (!names_only)
+        {
+          /* Add an extra newline to the value before indenting, so that
+           * every line of output has the indentation whether the value
+           * already ended in a newline or not. */
+          const char *newval = apr_psprintf(pool, "%s\n", propval->data);
+          const char *indented_newval = svn_cmdline__indent_string(newval,
+                                                                   "    ",
+                                                                   pool);
+          if (out)
+            {
+              SVN_ERR(svn_stream_puts(out, indented_newval));
+            }
+          else
+            {
+              printf("%s", indented_newval);
+            }
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_cmdline__print_xml_prop_hash(svn_stringbuf_t **outstr,
+                                 apr_hash_t *prop_hash,
+                                 svn_boolean_t names_only,
+                                 svn_boolean_t inherited_props,
+                                 apr_pool_t *pool)
+{
+  apr_array_header_t *sorted_props;
+  int i;
+
+  if (*outstr == NULL)
+    *outstr = svn_stringbuf_create_empty(pool);
+
+  sorted_props = svn_sort__hash(prop_hash, svn_sort_compare_items_lexically,
+                                pool);
+  for (i = 0; i < sorted_props->nelts; i++)
+    {
+      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
+      const char *pname = item.key;
+      svn_string_t *propval = item.value;
+
+      if (names_only)
+        {
+          svn_xml_make_open_tag(
+            outstr, pool, svn_xml_self_closing,
+            inherited_props ? "inherited_property" : "property",
+            "name", pname, NULL);
+        }
+      else
+        {
+          const char *pname_out;
+
+          if (svn_prop_needs_translation(pname))
+            SVN_ERR(svn_subst_detranslate_string(&propval, propval,
+                                                 TRUE, pool));
+
+          SVN_ERR(svn_cmdline_cstring_from_utf8(&pname_out, pname, pool));
+
+          svn_cmdline__print_xml_prop(outstr, pname_out, propval,
+                                      inherited_props, pool);
+        }
+    }
+
+    return SVN_NO_ERROR;
+}



Mime
View raw message