subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1780845 - /subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c
Date Sun, 29 Jan 2017 19:15:35 GMT
Author: stefan2
Date: Sun Jan 29 19:15:35 2017
New Revision: 1780845

URL: http://svn.apache.org/viewvc?rev=1780845&view=rev
Log:
Make the svn_ra_get_mergeinfo streamy for ra_serf.

All the groundwork has been done in the repos and FS layers and we
only need to use the new callback-based API.  The current pool usage
in brigades is opaque to this code.  So, the memory usage might still
be unbound but it will still be noticibly less than before.

* subversion/svnserve/serve.c
  (mergeinfo_receiver_baton_t,
   send_mergeinfo_starting_sequence,
   mergeinfo_receiver):  The new callback code.
  (get_mergeinfo): Bump to using the new API.

Modified:
    subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c

Modified: subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c?rev=1780845&r1=1780844&r2=1780845&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c Sun Jan 29 19:15:35 2017
@@ -42,6 +42,85 @@
 
 #include "../dav_svn.h"
 
+/* Baton type to be used with mergeinfo_receiver. */
+typedef struct mergeinfo_receiver_baton_t
+{
+  /* Start path of the query; report paths relative to this one. */
+  const char *fs_path;
+
+  /* Allocate the BRIGADE contents here. */
+  apr_pool_t *resource_pool;
+
+  /* Attach the response to this brigade. */
+  apr_bucket_brigade *brigade;
+
+  /* Send the response out here. */
+  dav_svn__output *output;
+
+  /* Did we already send the opening sequence? */
+  svn_boolean_t starting_tuple_sent;
+} mergeinfo_receiver_baton_t;
+
+/* Utility method sending the start of the "get m/i" response once
+   over BATON. */
+static svn_error_t *
+send_mergeinfo_starting_sequence(mergeinfo_receiver_baton_t *baton,
+                                apr_pool_t *scratch_pool)
+{
+  if (baton->starting_tuple_sent)
+    return SVN_NO_ERROR;
+
+  /* Ideally, dav_svn__brigade_printf() would set a flag in bb (or rather,
+     in r->sent_bodyct, see dav_method_report()), and ap_fflush()
+     would not set that flag unless it actually sent something.  But
+     we are condemned to live in another universe, so we must keep
+     track ourselves of whether we've sent anything or not.  See the
+     long comment after the 'cleanup' label for more details. */
+  SVN_ERR(dav_svn__brigade_puts(baton->brigade, baton->output,
+                                DAV_XML_HEADER DEBUG_CR
+                                "<S:" SVN_DAV__MERGEINFO_REPORT " "
+                                "xmlns:S=\"" SVN_XML_NAMESPACE "\" "
+                                "xmlns:D=\"DAV:\">" DEBUG_CR));
+  baton->starting_tuple_sent = TRUE;
+
+  return SVN_NO_ERROR;
+}
+
+/* Implements svn_repos_mergeinfo_receiver_t, sending the MERGEINFO
+ * out over the connection in the mergeinfo_receiver_baton_t * BATON. */
+static svn_error_t *
+mergeinfo_receiver(const char *path,
+                   svn_mergeinfo_t mergeinfo,
+                   void *baton,
+                   apr_pool_t *scratch_pool)
+{
+  mergeinfo_receiver_baton_t *b = baton;
+  svn_string_t *mergeinfo_string;
+
+  /* Delay starting the response until we checked that the initial
+     request went through.  We are at that point now b/c we've got
+     the first results in. */
+  SVN_ERR(send_mergeinfo_starting_sequence(b, scratch_pool));
+
+  /* Adjust the path info and send the m/i. */
+  path = svn_fspath__skip_ancestor(b->fs_path, path);
+  SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string, mergeinfo,
+                                  scratch_pool));
+
+  SVN_ERR(dav_svn__brigade_printf
+        (b->brigade, b->output,
+         "<S:" SVN_DAV__MERGEINFO_ITEM ">"
+         DEBUG_CR
+         "<S:" SVN_DAV__MERGEINFO_PATH ">%s</S:" SVN_DAV__MERGEINFO_PATH ">"
+         DEBUG_CR
+         "<S:" SVN_DAV__MERGEINFO_INFO ">%s</S:" SVN_DAV__MERGEINFO_INFO ">"
+         DEBUG_CR
+         "</S:" SVN_DAV__MERGEINFO_ITEM ">",
+         apr_xml_quote_string(b->resource_pool, path, 0),
+         apr_xml_quote_string(b->resource_pool, mergeinfo_string->data, 0)));
+
+  return SVN_NO_ERROR;
+}
 
 dav_error *
 dav_svn__get_mergeinfo_report(const dav_resource *resource,
@@ -51,13 +130,12 @@ dav_svn__get_mergeinfo_report(const dav_
   svn_error_t *serr;
   dav_error *derr = NULL;
   apr_xml_elem *child;
-  svn_mergeinfo_catalog_t catalog;
   svn_boolean_t include_descendants = FALSE;
   dav_svn__authz_read_baton arb;
   const dav_svn_repos *repos = resource->info->repos;
   int ns;
   apr_bucket_brigade *bb;
-  apr_hash_index_t *hi;
+  mergeinfo_receiver_baton_t receiver_baton;
 
   /* These get determined from the request document. */
   svn_revnum_t rev = SVN_INVALID_REVNUM;
@@ -127,20 +205,17 @@ dav_svn__get_mergeinfo_report(const dav_
   bb = apr_brigade_create(resource->pool,
                           dav_svn__output_get_bucket_alloc(output));
 
-  serr = svn_repos_fs_get_mergeinfo(&catalog, repos->repos, paths, rev,
-                                    inherit, include_descendants,
-                                    dav_svn__authz_read_func(&arb),
-                                    &arb, resource->pool);
-  if (serr)
-    {
-      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
-                                  resource->pool);
-      goto cleanup;
-    }
-
-  serr = svn_mergeinfo__remove_prefix_from_catalog(&catalog, catalog,
-                                                   resource->info->repos_path,
-                                                   resource->pool);
+  receiver_baton.brigade = bb;
+  receiver_baton.output = output;
+  receiver_baton.fs_path = resource->info->repos_path;
+  receiver_baton.resource_pool = resource->pool;
+  receiver_baton.starting_tuple_sent = FALSE;
+
+  serr = svn_repos_fs_get_mergeinfo2(repos->repos, paths, rev,
+                                     inherit, include_descendants,
+                                     dav_svn__authz_read_func(&arb), &arb,
+                                     mergeinfo_receiver, &receiver_baton,
+                                     resource->pool);
   if (serr)
     {
       derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
@@ -148,17 +223,9 @@ dav_svn__get_mergeinfo_report(const dav_
       goto cleanup;
     }
 
-  /* Ideally, dav_svn__brigade_printf() would set a flag in bb (or rather,
-     in r->sent_bodyct, see dav_method_report()), and ap_fflush()
-     would not set that flag unless it actually sent something.  But
-     we are condemned to live in another universe, so we must keep
-     track ourselves of whether we've sent anything or not.  See the
-     long comment after the 'cleanup' label for more details. */
-  serr = dav_svn__brigade_puts(bb, output,
-                               DAV_XML_HEADER DEBUG_CR
-                               "<S:" SVN_DAV__MERGEINFO_REPORT " "
-                               "xmlns:S=\"" SVN_XML_NAMESPACE "\" "
-                               "xmlns:D=\"DAV:\">" DEBUG_CR);
+  /* We might not have sent anything
+     => ensure to begin the response in any case. */
+  serr = send_mergeinfo_starting_sequence(&receiver_baton, resource->pool);
   if (serr)
     {
       derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
@@ -166,46 +233,6 @@ dav_svn__get_mergeinfo_report(const dav_
       goto cleanup;
     }
 
-  for (hi = apr_hash_first(resource->pool, catalog); hi;
-       hi = apr_hash_next(hi))
-    {
-      const void *key;
-      void *value;
-      const char *path;
-      svn_mergeinfo_t mergeinfo;
-      svn_string_t *mergeinfo_string;
-
-      apr_hash_this(hi, &key, NULL, &value);
-      path = key;
-      mergeinfo = value;
-      serr = svn_mergeinfo_to_string(&mergeinfo_string, mergeinfo,
-                                     resource->pool);
-      if (serr)
-        {
-          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
-                                      "Error ending REPORT response.",
-                                      resource->pool);
-          goto cleanup;
-        }
-      serr = dav_svn__brigade_printf
-        (bb, output,
-         "<S:" SVN_DAV__MERGEINFO_ITEM ">"
-         DEBUG_CR
-         "<S:" SVN_DAV__MERGEINFO_PATH ">%s</S:" SVN_DAV__MERGEINFO_PATH ">"
-         DEBUG_CR
-         "<S:" SVN_DAV__MERGEINFO_INFO ">%s</S:" SVN_DAV__MERGEINFO_INFO ">"
-         DEBUG_CR
-         "</S:" SVN_DAV__MERGEINFO_ITEM ">",
-         apr_xml_quote_string(resource->pool, path, 0),
-         apr_xml_quote_string(resource->pool, mergeinfo_string->data, 0));
-      if (serr)
-        {
-          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
-                                      "Error ending REPORT response.",
-                                      resource->pool);
-          goto cleanup;
-        }
-    }
 
   if ((serr = dav_svn__brigade_puts(bb, output,
                                     "</S:" SVN_DAV__MERGEINFO_REPORT ">"



Mime
View raw message