subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kot...@apache.org
Subject svn commit: r1758224 - in /subversion/trunk/subversion/mod_dav_svn: ./ posts/ reports/
Date Mon, 29 Aug 2016 13:41:11 GMT
Author: kotkov
Date: Mon Aug 29 13:41:11 2016
New Revision: 1758224

URL: http://svn.apache.org/viewvc?rev=1758224&view=rev
Log:
Fix the unbounded memory usage when mod_dav_svn is paired up with
mod_headers or mod_deflate.

The problem is caused by how mod_dav passes the output filter list to its
providers.  A hook receives the current head of the output filter list for
a particular request.  Certain filters, such as the one in mod_headers, are
designed to perform the work only once.  When the work is done, a filter
removes itself from the list.  If a filter is the first in the list, this
updates the head of the linked list in request_rec (r->output_filters), but
not the ap_filter_t * pointer that was passed as an argument to mod_dav_svn.
So, mod_dav_svn continues to operate with an outdated list of filters, and
every write causes a re-execution of the already removed filter.

In case with mod_headers, this triggers an unbounded memory usage, e.g.,
responding to a GET request for a 500 MB file results in the server
consuming a large amount (~3.2 GB) of memory.  Full discussion of the
mod_dav's part of the issue can be found in [1].

The idea behind the fix is that we add a new opaque type, dav_svn__output,
a small corresponding set of private API functions, and adjust the existing
output helpers so that every write would target a dav_svn__output object.
A dav_svn__output is constructed for a particular request, and internally
it ensures that the writes *always* target the actual output filter list
in r->output_filters.

[1] https://mail-archives.apache.org/mod_mbox/httpd-dev/201608.mbox/%3C20160822151917.GA22369%40redhat.com%3E

* subversion/mod_dav_svn/dav_svn.h
  (dav_svn__output): New.
  (dav_svn__output_create, dav_svn__output_get_bucket_alloc,
   dav_svn__output_pass_brigade): New.
  (dav_svn__merge_response, dav_svn__update_report,
   dav_svn__log_report, dav_svn__dated_rev_report,
   dav_svn__get_locations_report, dav_svn__get_location_segments_report,
   dav_svn__file_revs_report, dav_svn__replay_report,
   dav_svn__get_mergeinfo_report, dav_svn__get_locks_report,
   dav_svn__get_deleted_rev_report, dav_svn__get_inherited_props_report,
   dav_svn__post_create_txn, dav_svn__post_create_txn_with_props,
   dav_svn__brigade_write, dav_svn__brigade_puts,
   dav_svn__brigade_printf, dav_svn__brigade_putstrs,
   dav_svn__make_base64_output_stream, dav_svn__final_flush_or_error):
   Now work with a dav_svn__output, instead of an ap_filter_t.

* subversion/mod_dav_svn/util.c
  (dav_svn__output): New.
  (dav_svn__output_create, dav_svn__output_get_bucket_alloc,
   dav_svn__output_pass_brigade): Implement new functions.
  (dav_svn__brigade_write, dav_svn__brigade_puts,
   dav_svn__brigade_printf, dav_svn__brigade_putstrs,
   dav_svn__final_flush_or_error): Target the actual output filter list
   for a particular request.
  (brigade_write_baton): Store a dav_svn__output object.
  (brigade_write_fn): Target the actual output filter list for a
   particular request.
  (dav_svn__make_base64_output_stream): Now works with a dav_svn__output,
   instead of an ap_filter_t.

* subversion/mod_dav_svn/repos.c
  (diff_ctx_t): Store a dav_svn__output object.
  (write_to_filter): Call dav_svn__brigade_write() function.
  (close_filter): Use the dav_svn__output's API.  The apr_brigade_cleanup()
   call is no longer required, since dav_svn__output_pass_brigade() also
   cleans the bucket brigade.
  (emit_collection_head, emit_collection_entry, emit_collection_tail):
   Now work with a dav_svn__output, instead of an ap_filter_t.
  (deliver): Create a dav_svn__output at the beginning of this function.
   Use the dav_svn__output's API for brigade creation and passing to the
   output filter stack.
  (handle_post_request): Now works with a dav_svn__output, instead of
   an ap_filter_t.
  (dav_svn__method_post): Create a dav_svn__output and forward it to
   handle_post_request().

* subversion/mod_dav_svn/version.c
  (deliver_report): Create a dav_svn__output and forward it to the
   report handlers.
  (merge): Create a dav_svn__output and forward it to
   dav_svn__merge_response().

* subversion/mod_dav_svn/merge.c
  (send_response, do_resources, dav_svn__merge_response): Now work with
   a dav_svn__output and use the new private API.

* subversion/mod_dav_svn/posts/create_txn.c
  (dav_svn__post_create_txn, dav_svn__post_create_txn_with_props): Now
   work with a dav_svn__output.

* subversion/mod_dav_svn/reports/dated-rev.c
  (dav_svn__dated_rev_report): Work with a dav_svn__output.  Use the new
   private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/deleted-rev.c
  (dav_svn__get_deleted_rev_report): Work with a dav_svn__output.  Use
   the new private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/file-revs.c
  (file_rev_baton): Store a dav_svn__output object.
  (dav_svn__file_revs_report): Work with a dav_svn__output.  Use the new
   private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/get-location-segments.c
  (location_segment_baton): Store a dav_svn__output object.
  (dav_svn__get_location_segments_report): Work with a dav_svn__output.
   Use the new private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/get-locations.c
  (send_get_locations_report, dav_svn__get_locations_report): Work with a
   dav_svn__output.  Use the new private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/get-locks.c
  (send_get_lock_response, dav_svn__get_locks_report): Work with a
   dav_svn__output. Use the new private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/inherited-props.c
  (dav_svn__get_inherited_props_report): Work with a dav_svn__output.
   Use the new private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/log.c
  (log_receiver_baton): Store a dav_svn__output object.
  (log_revision_receiver): Rewrite the forced flush by creating and sending
   a flush bucket to the output filters (that's what ap_fflush() does
   internally).  Drop the aborted connection check, since it's now a
   part of dav_svn__output_pass_brigade().
  (dav_svn__log_report): Work with a dav_svn__output.  Use the new private
   API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/mergeinfo.c
  (dav_svn__get_mergeinfo_report): Work with a dav_svn__output.  Use the
   new private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/replay.c
  (edit_baton_t): Store a dav_svn__output object.
  (make_editor, dav_svn__replay_report): Work with a dav_svn__output.
   Use the new private API when creating a bucket brigade.

* subversion/mod_dav_svn/reports/update.c
  (update_ctx_t): Store a dav_svn__output object.
  (dav_svn__update_report): Work with a dav_svn__output.  Use the new
   private API when creating a bucket brigade.

Modified:
    subversion/trunk/subversion/mod_dav_svn/dav_svn.h
    subversion/trunk/subversion/mod_dav_svn/merge.c
    subversion/trunk/subversion/mod_dav_svn/posts/create_txn.c
    subversion/trunk/subversion/mod_dav_svn/reports/dated-rev.c
    subversion/trunk/subversion/mod_dav_svn/reports/deleted-rev.c
    subversion/trunk/subversion/mod_dav_svn/reports/file-revs.c
    subversion/trunk/subversion/mod_dav_svn/reports/get-location-segments.c
    subversion/trunk/subversion/mod_dav_svn/reports/get-locations.c
    subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c
    subversion/trunk/subversion/mod_dav_svn/reports/inherited-props.c
    subversion/trunk/subversion/mod_dav_svn/reports/log.c
    subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c
    subversion/trunk/subversion/mod_dav_svn/reports/replay.c
    subversion/trunk/subversion/mod_dav_svn/reports/update.c
    subversion/trunk/subversion/mod_dav_svn/repos.c
    subversion/trunk/subversion/mod_dav_svn/util.c
    subversion/trunk/subversion/mod_dav_svn/version.c

Modified: subversion/trunk/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/dav_svn.h?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/trunk/subversion/mod_dav_svn/dav_svn.h Mon Aug 29 13:41:11 2016
@@ -457,6 +457,40 @@ const char *dav_svn__get_vtxn_stub(reque
 /* For accessing transaction properties (typically "!svn/vtxr") */
 const char *dav_svn__get_vtxn_root_stub(request_rec *r);
 
+
+/*** Output helpers ***/
+
+/* An opaque type which represents an output for a particular request.
+
+   All writes should target a dav_svn__output object by either using
+   the dav_svn__brigade functions or by preparing a bucket brigade and
+   passing it to the output with dav_svn__output_pass_brigade().
+
+   IMPORTANT:  Don't write to an ap_filter_t coming from mod_dav, and
+   use this wrapper and the corresponding private API instead.  Using
+   the ap_filter_t can cause unbounded memory usage with self-removing
+   output filters (e.g., with the filters installed by mod_headers or
+   mod_deflate).
+
+   See https://mail-archives.apache.org/mod_mbox/httpd-dev/201608.mbox/%3C20160822151917.GA22369%40redhat.com%3E
+*/
+typedef struct dav_svn__output dav_svn__output;
+
+/* Create the output wrapper for request R, allocated in POOL. */
+dav_svn__output *
+dav_svn__output_create(request_rec *r,
+                       apr_pool_t *pool);
+
+/* Get a bucket allocator to use for all bucket/brigade creations
+   when writing to OUTPUT. */
+apr_bucket_alloc_t *
+dav_svn__output_get_bucket_alloc(dav_svn__output *output);
+
+/* Pass the bucket brigade BB down to the OUTPUT's filter stack. */
+svn_error_t *
+dav_svn__output_pass_brigade(dav_svn__output *output,
+                             apr_bucket_brigade *bb);
+
 
 /*** activity.c ***/
 
@@ -645,7 +679,7 @@ dav_svn__insert_all_liveprops(request_re
 /* Generate the HTTP response body for a successful MERGE. */
 /* ### more docco */
 dav_error *
-dav_svn__merge_response(ap_filter_t *output,
+dav_svn__merge_response(dav_svn__output *output,
                         const dav_svn_repos *repos,
                         svn_revnum_t new_rev,
                         const char *post_commit_err,
@@ -679,49 +713,49 @@ static const dav_report_elem dav_svn__re
 dav_error *
 dav_svn__update_report(const dav_resource *resource,
                        const apr_xml_doc *doc,
-                       ap_filter_t *output);
+                       dav_svn__output *output);
 dav_error *
 dav_svn__log_report(const dav_resource *resource,
                     const apr_xml_doc *doc,
-                    ap_filter_t *output);
+                    dav_svn__output *output);
 dav_error *
 dav_svn__dated_rev_report(const dav_resource *resource,
                           const apr_xml_doc *doc,
-                          ap_filter_t *output);
+                          dav_svn__output *output);
 dav_error *
 dav_svn__get_locations_report(const dav_resource *resource,
                               const apr_xml_doc *doc,
-                              ap_filter_t *output);
+                              dav_svn__output *output);
 dav_error *
 dav_svn__get_location_segments_report(const dav_resource *resource,
                                       const apr_xml_doc *doc,
-                                      ap_filter_t *output);
+                                      dav_svn__output *output);
 dav_error *
 dav_svn__file_revs_report(const dav_resource *resource,
                           const apr_xml_doc *doc,
-                          ap_filter_t *output);
+                          dav_svn__output *output);
 dav_error *
 dav_svn__replay_report(const dav_resource *resource,
                        const apr_xml_doc *doc,
-                       ap_filter_t *output);
+                       dav_svn__output *output);
 dav_error *
 dav_svn__get_mergeinfo_report(const dav_resource *resource,
                               const apr_xml_doc *doc,
-                              ap_filter_t *output);
+                              dav_svn__output *output);
 dav_error *
 dav_svn__get_locks_report(const dav_resource *resource,
                           const apr_xml_doc *doc,
-                          ap_filter_t *output);
+                          dav_svn__output *output);
 
 dav_error *
 dav_svn__get_deleted_rev_report(const dav_resource *resource,
                                 const apr_xml_doc *doc,
-                                ap_filter_t *output);
+                                dav_svn__output *output);
 
 dav_error *
 dav_svn__get_inherited_props_report(const dav_resource *resource,
                                     const apr_xml_doc *doc,
-                                    ap_filter_t *output);
+                                    dav_svn__output *output);
 
 /*** posts/ ***/
 
@@ -729,11 +763,11 @@ dav_svn__get_inherited_props_report(cons
 dav_error *
 dav_svn__post_create_txn(const dav_resource *resource,
                          svn_skel_t *request_skel,
-                         ap_filter_t *output);
+                         dav_svn__output *output);
 dav_error *
 dav_svn__post_create_txn_with_props(const dav_resource *resource,
                                     svn_skel_t *request_skel,
-                                    ap_filter_t *output);
+                                    dav_svn__output *output);
 
 /*** authz.c ***/
 
@@ -940,26 +974,26 @@ int dav_svn__find_ns(const apr_array_hea
 
 /* Write LEN bytes from DATA to OUTPUT using BB.  */
 svn_error_t *dav_svn__brigade_write(apr_bucket_brigade *bb,
-                                    ap_filter_t *output,
+                                    dav_svn__output *output,
                                     const char *buf,
                                     apr_size_t len);
 
 /* Write NULL-terminated string STR to OUTPUT using BB.  */
 svn_error_t *dav_svn__brigade_puts(apr_bucket_brigade *bb,
-                                   ap_filter_t *output,
+                                   dav_svn__output *output,
                                    const char *str);
 
 
 /* Write data to OUTPUT using BB, using FMT as the output format string.  */
 svn_error_t *dav_svn__brigade_printf(apr_bucket_brigade *bb,
-                                     ap_filter_t *output,
+                                     dav_svn__output *output,
                                      const char *fmt,
                                      ...)
   __attribute__((format(printf, 3, 4)));
 
 /* Write an unspecified number of strings to OUTPUT using BB.  */
 svn_error_t *dav_svn__brigade_putstrs(apr_bucket_brigade *bb,
-                                      ap_filter_t *output,
+                                      dav_svn__output *output,
                                       ...) SVN_NEEDS_SENTINEL_NULL;
 
 
@@ -995,11 +1029,10 @@ dav_svn__sanitize_error(svn_error_t *ser
 
 
 /* Return a writable generic stream that will encode its output to base64
-   and send it to the Apache filter OUTPUT using BB.  Allocate the stream in
-   POOL. */
+   and send it to OUTPUT using BB.  Allocate the stream in POOL. */
 svn_stream_t *
 dav_svn__make_base64_output_stream(apr_bucket_brigade *bb,
-                                   ap_filter_t *output,
+                                   dav_svn__output *output,
                                    apr_pool_t *pool);
 
 /* In INFO->r->subprocess_env set "SVN-ACTION" to LINE, "SVN-REPOS" to
@@ -1041,7 +1074,8 @@ dav_svn__operational_log(struct dav_reso
  */
 dav_error *
 dav_svn__final_flush_or_error(request_rec *r, apr_bucket_brigade *bb,
-                              ap_filter_t *output, dav_error *preferred_err,
+                              dav_svn__output *output,
+                              dav_error *preferred_err,
                               apr_pool_t *pool);
 
 /* Log a DAV error response.

Modified: subversion/trunk/subversion/mod_dav_svn/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/merge.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/merge.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/merge.c Mon Aug 29 13:41:11 2016
@@ -72,7 +72,7 @@ send_response(const dav_svn_repos *repos
               svn_fs_root_t *root,
               const char *path,
               svn_boolean_t is_dir,
-              ap_filter_t *output,
+              dav_svn__output *output,
               apr_bucket_brigade *bb,
               apr_pool_t *pool)
 {
@@ -112,7 +112,7 @@ static svn_error_t *
 do_resources(const dav_svn_repos *repos,
              svn_fs_root_t *root,
              svn_revnum_t revision,
-             ap_filter_t *output,
+             dav_svn__output *output,
              apr_bucket_brigade *bb,
              apr_pool_t *pool)
 {
@@ -214,7 +214,7 @@ do_resources(const dav_svn_repos *repos,
 */
 
 dav_error *
-dav_svn__merge_response(ap_filter_t *output,
+dav_svn__merge_response(dav_svn__output *output,
                         const dav_svn_repos *repos,
                         svn_revnum_t new_rev,
                         const char *post_commit_err,
@@ -230,7 +230,6 @@ dav_svn__merge_response(ap_filter_t *out
   svn_string_t *creationdate, *creator_displayname;
   const char *post_commit_err_elem = NULL,
              *post_commit_header_info = NULL;
-  apr_status_t status;
   apr_hash_t *revprops;
 
   serr = svn_fs_revision_root(&root, repos->fs, new_rev, pool);
@@ -242,7 +241,8 @@ dav_svn__merge_response(ap_filter_t *out
                                   repos->pool);
     }
 
-  bb = apr_brigade_create(pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(pool,
+                          dav_svn__output_get_bucket_alloc(output));
 
   /* prep some strings */
 
@@ -383,11 +383,11 @@ dav_svn__merge_response(ap_filter_t *out
                                 repos->pool);
 
   /* send whatever is left in the brigade */
-  status = ap_pass_brigade(output, bb);
-  if (status != APR_SUCCESS)
-    return dav_svn__new_error(repos->pool, HTTP_INTERNAL_SERVER_ERROR,
-                              0, status,
-                              "Could not write output");
+  serr = dav_svn__output_pass_brigade(output, bb);
+  if (serr != NULL)
+    return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                "Could not write output",
+                                repos->pool);
 
   return NULL;
 }

Modified: subversion/trunk/subversion/mod_dav_svn/posts/create_txn.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/posts/create_txn.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/posts/create_txn.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/posts/create_txn.c Mon Aug 29 13:41:11 2016
@@ -34,7 +34,7 @@
 dav_error *
 dav_svn__post_create_txn(const dav_resource *resource,
                          svn_skel_t *request_skel,
-                         ap_filter_t *output)
+                         dav_svn__output *output)
 {
   const char *txn_name;
   const char *vtxn_name;
@@ -75,7 +75,7 @@ dav_svn__post_create_txn(const dav_resou
 dav_error *
 dav_svn__post_create_txn_with_props(const dav_resource *resource,
                                     svn_skel_t *request_skel,
-                                    ap_filter_t *output)
+                                    dav_svn__output *output)
 {
   const char *txn_name;
   const char *vtxn_name;

Modified: subversion/trunk/subversion/mod_dav_svn/reports/dated-rev.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/dated-rev.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/dated-rev.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/dated-rev.c Mon Aug 29 13:41:11 2016
@@ -50,7 +50,7 @@
 dav_error *
 dav_svn__dated_rev_report(const dav_resource *resource,
                           const apr_xml_doc *doc,
-                          ap_filter_t *output)
+                          dav_svn__output *output)
 {
   apr_xml_elem *child;
   int ns;
@@ -94,7 +94,8 @@ dav_svn__dated_rev_report(const dav_reso
                                 "Could not access revision times.");
     }
 
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(resource->pool,
+                          dav_svn__output_get_bucket_alloc(output));
   err = dav_svn__brigade_printf(bb, output,
                        DAV_XML_HEADER DEBUG_CR
                        "<S:dated-rev-report xmlns:S=\"" SVN_XML_NAMESPACE "\" "

Modified: subversion/trunk/subversion/mod_dav_svn/reports/deleted-rev.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/deleted-rev.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/deleted-rev.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/deleted-rev.c Mon Aug 29 13:41:11 2016
@@ -41,7 +41,7 @@
 dav_error *
 dav_svn__get_deleted_rev_report(const dav_resource *resource,
                                 const apr_xml_doc *doc,
-                                ap_filter_t *output)
+                                dav_svn__output *output)
 {
   apr_xml_elem *child;
   int ns;
@@ -117,7 +117,8 @@ dav_svn__get_deleted_rev_report(const da
                                 "Could not find revision path was deleted.");
     }
 
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(resource->pool,
+                          dav_svn__output_get_bucket_alloc(output));
   err = dav_svn__brigade_printf(bb, output,
                        DAV_XML_HEADER DEBUG_CR
                        "<S:get-deleted-rev-report xmlns:S=\""

Modified: subversion/trunk/subversion/mod_dav_svn/reports/file-revs.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/file-revs.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/file-revs.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/file-revs.c Mon Aug 29 13:41:11 2016
@@ -43,7 +43,7 @@ struct file_rev_baton {
   apr_bucket_brigade *bb;
 
   /* where to deliver the output */
-  ap_filter_t *output;
+  dav_svn__output *output;
 
   /* Whether we've written the <S:file-revs-report> header.  Allows for lazy
      writes to support mod_dav-based error handling. */
@@ -234,7 +234,7 @@ file_rev_handler(void *baton,
 dav_error *
 dav_svn__file_revs_report(const dav_resource *resource,
                           const apr_xml_doc *doc,
-                          ap_filter_t *output)
+                          dav_svn__output *output)
 {
   svn_error_t *serr;
   dav_error *derr = NULL;
@@ -304,7 +304,7 @@ dav_svn__file_revs_report(const dav_reso
                                   "Not all parameters passed");
 
   frb.bb = apr_brigade_create(resource->pool,
-                              output->c->bucket_alloc);
+                              dav_svn__output_get_bucket_alloc(output));
   frb.output = output;
   frb.needs_header = TRUE;
   frb.svndiff_version = resource->info->svndiff_version;

Modified: subversion/trunk/subversion/mod_dav_svn/reports/get-location-segments.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/get-location-segments.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/get-location-segments.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/get-location-segments.c Mon Aug 29 13:41:11 2016
@@ -48,7 +48,7 @@
 struct location_segment_baton
 {
   svn_boolean_t sent_opener;
-  ap_filter_t *output;
+  dav_svn__output *output;
   apr_bucket_brigade *bb;
   dav_svn__authz_read_baton arb;
 };
@@ -106,7 +106,7 @@ location_segment_receiver(svn_location_s
 dav_error *
 dav_svn__get_location_segments_report(const dav_resource *resource,
                                       const apr_xml_doc *doc,
-                                      ap_filter_t *output)
+                                      dav_svn__output *output)
 {
   svn_error_t *serr;
   dav_error *derr = NULL;
@@ -214,7 +214,8 @@ dav_svn__get_location_segments_report(co
   arb.repos = resource->info->repos;
 
   /* Build the bucket brigade we'll use for output. */
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(resource->pool,
+                          dav_svn__output_get_bucket_alloc(output));
 
   /* Do what we came here for. */
   location_segment_baton.sent_opener = FALSE;

Modified: subversion/trunk/subversion/mod_dav_svn/reports/get-locations.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/get-locations.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/get-locations.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/get-locations.c Mon Aug 29 13:41:11 2016
@@ -45,7 +45,7 @@
 
 
 static svn_error_t *
-send_get_locations_report(ap_filter_t *output,
+send_get_locations_report(dav_svn__output *output,
                           apr_bucket_brigade *bb,
                           const dav_resource *resource,
                           apr_hash_t *fs_locations)
@@ -82,7 +82,7 @@ send_get_locations_report(ap_filter_t *o
 dav_error *
 dav_svn__get_locations_report(const dav_resource *resource,
                               const apr_xml_doc *doc,
-                              ap_filter_t *output)
+                              dav_svn__output *output)
 {
   svn_error_t *serr;
   dav_error *derr = NULL;
@@ -169,7 +169,8 @@ dav_svn__get_locations_report(const dav_
                                   resource->pool);
     }
 
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(resource->pool,
+                          dav_svn__output_get_bucket_alloc(output));
 
   serr = send_get_locations_report(output, bb, resource, fs_locations);
 

Modified: subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/get-locks.c Mon Aug 29 13:41:11 2016
@@ -48,7 +48,7 @@
    path) across OUTPUT using BB.  Use POOL for necessary allocations. */
 static svn_error_t *
 send_get_lock_response(apr_hash_t *locks,
-                       ap_filter_t *output,
+                       dav_svn__output *output,
                        apr_bucket_brigade *bb,
                        apr_pool_t *pool)
 {
@@ -161,7 +161,7 @@ send_get_lock_response(apr_hash_t *locks
 dav_error *
 dav_svn__get_locks_report(const dav_resource *resource,
                           const apr_xml_doc *doc,
-                          ap_filter_t *output)
+                          dav_svn__output *output)
 {
   apr_bucket_brigade *bb;
   svn_error_t *err;
@@ -211,7 +211,8 @@ dav_svn__get_locks_report(const dav_reso
     return dav_svn__convert_err(err, HTTP_INTERNAL_SERVER_ERROR,
                                 err->message, resource->pool);
 
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(resource->pool,
+                          dav_svn__output_get_bucket_alloc(output));
 
   err = send_get_lock_response(locks, output, bb, resource->pool);
   if (err)

Modified: subversion/trunk/subversion/mod_dav_svn/reports/inherited-props.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/inherited-props.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/inherited-props.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/inherited-props.c Mon Aug 29 13:41:11 2016
@@ -47,7 +47,7 @@
 dav_error *
 dav_svn__get_inherited_props_report(const dav_resource *resource,
                                     const apr_xml_doc *doc,
-                                    ap_filter_t *output)
+                                    dav_svn__output *output)
 {
   svn_error_t *serr;
   dav_error *derr = NULL;
@@ -106,7 +106,8 @@ dav_svn__get_inherited_props_report(cons
   arb.repos = resource->info->repos;
 
   /* Build inherited property brigade */
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(resource->pool,
+                          dav_svn__output_get_bucket_alloc(output));
 
   serr = svn_fs_revision_root(&root, resource->info->repos->fs,
                               rev, resource->pool);

Modified: subversion/trunk/subversion/mod_dav_svn/reports/log.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/log.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/log.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/log.c Mon Aug 29 13:41:11 2016
@@ -50,7 +50,7 @@ struct log_receiver_baton
   apr_bucket_brigade *bb;
 
   /* where to deliver the output */
-  ap_filter_t *output;
+  dav_svn__output *output;
 
   /* Whether we've written the <S:log-report> header.  Allows for lazy
      writes to support mod_dav-based error handling. */
@@ -334,25 +334,17 @@ log_revision_receiver(void *baton,
   lrb->result_count++;
   if (lrb->result_count == lrb->next_forced_flush)
     {
-      apr_status_t apr_err;
+      apr_bucket *bkt;
 
-      /* This flush is similar to that in dav_svn__final_flush_or_error().
-
-         Compared to using ap_filter_flush(), which we use in other place
+      /* Compared to using ap_filter_flush(), which we use in other place
          this adds a flush frame before flushing the brigade, to make output
          filters perform a flush as well */
 
       /* No brigade empty check. We want output filters to flush anyway */
-      apr_err = ap_fflush(lrb->output, lrb->bb);
-      if (apr_err)
-        return svn_error_create(apr_err, NULL, NULL);
-
-      /* Check for an aborted connection, just like our brigade write
-         helper functions, since the brigade functions don't appear to
-         be return useful errors when the connection is dropped. */
-      if (lrb->output->c->aborted)
-        return svn_error_create(SVN_ERR_APMOD_CONNECTION_ABORTED,
-                                NULL, NULL);
+      bkt = apr_bucket_flush_create(
+                dav_svn__output_get_bucket_alloc(lrb->output));
+      APR_BRIGADE_INSERT_TAIL(lrb->bb, bkt);
+      SVN_ERR(dav_svn__output_pass_brigade(lrb->output, lrb->bb));
 
       if (lrb->result_count < 256)
         lrb->next_forced_flush = lrb->next_forced_flush * 4;
@@ -365,7 +357,7 @@ log_revision_receiver(void *baton,
 dav_error *
 dav_svn__log_report(const dav_resource *resource,
                     const apr_xml_doc *doc,
-                    ap_filter_t *output)
+                    dav_svn__output *output)
 {
   svn_error_t *serr;
   dav_error *derr = NULL;
@@ -497,7 +489,7 @@ dav_svn__log_report(const dav_resource *
 
   /* Build log receiver baton */
   lrb.bb = apr_brigade_create(resource->pool,  /* not the subpool! */
-                              output->c->bucket_alloc);
+                              dav_svn__output_get_bucket_alloc(output));
   lrb.output = output;
   lrb.needs_header = TRUE;
   lrb.needs_log_item = TRUE;

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=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/mergeinfo.c Mon Aug 29 13:41:11 2016
@@ -46,7 +46,7 @@
 dav_error *
 dav_svn__get_mergeinfo_report(const dav_resource *resource,
                               const apr_xml_doc *doc,
-                              ap_filter_t *output)
+                              dav_svn__output *output)
 {
   svn_error_t *serr;
   dav_error *derr = NULL;
@@ -124,7 +124,8 @@ dav_svn__get_mergeinfo_report(const dav_
   arb.repos = resource->info->repos;
 
   /* Build mergeinfo brigade */
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  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,

Modified: subversion/trunk/subversion/mod_dav_svn/reports/replay.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/replay.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/replay.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/replay.c Mon Aug 29 13:41:11 2016
@@ -44,7 +44,7 @@
 
 typedef struct edit_baton_t {
   apr_bucket_brigade *bb;
-  ap_filter_t *output;
+  dav_svn__output *output;
   svn_boolean_t started;
   svn_boolean_t sending_textdelta;
   int compression_level;
@@ -367,7 +367,7 @@ static void
 make_editor(const svn_delta_editor_t **editor,
             void **edit_baton,
             apr_bucket_brigade *bb,
-            ap_filter_t *output,
+            dav_svn__output *output,
             int compression_level,
             apr_pool_t *pool)
 {
@@ -413,7 +413,7 @@ malformed_element_error(const char *tagn
 dav_error *
 dav_svn__replay_report(const dav_resource *resource,
                        const apr_xml_doc *doc,
-                       ap_filter_t *output)
+                       dav_svn__output *output)
 {
   dav_error *derr = NULL;
   svn_revnum_t low_water_mark = SVN_INVALID_REVNUM;
@@ -530,7 +530,8 @@ dav_svn__replay_report(const dav_resourc
   if (! base_dir)
     base_dir = "";
 
-  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  bb = apr_brigade_create(resource->pool,
+                          dav_svn__output_get_bucket_alloc(output));
 
   if ((err = svn_fs_revision_root(&root, resource->info->repos->fs, rev,
                                   resource->pool)))

Modified: subversion/trunk/subversion/mod_dav_svn/reports/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/reports/update.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/reports/update.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/reports/update.c Mon Aug 29 13:41:11 2016
@@ -68,7 +68,7 @@ typedef struct update_ctx_t {
   apr_bucket_brigade *bb;
 
   /* where to deliver the output */
-  ap_filter_t *output;
+  dav_svn__output *output;
 
   /* where do these editor paths *really* point to? */
   apr_hash_t *pathmap;
@@ -954,7 +954,7 @@ validate_input_revision(svn_revnum_t rev
 dav_error *
 dav_svn__update_report(const dav_resource *resource,
                        const apr_xml_doc *doc,
-                       ap_filter_t *output)
+                       dav_svn__output *output)
 {
   svn_delta_editor_t *editor;
   apr_xml_elem *child;
@@ -1202,7 +1202,8 @@ dav_svn__update_report(const dav_resourc
   uc.output = output;
   uc.anchor = src_path;
   uc.target = target;
-  uc.bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  uc.bb = apr_brigade_create(resource->pool,
+                             dav_svn__output_get_bucket_alloc(output));
   uc.pathmap = NULL;
   uc.enable_v2_response = ((resource->info->restype == DAV_SVN_RESTYPE_ME)
                            && (resource->info->repos->v2_protocol));

Modified: subversion/trunk/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/repos.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/repos.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/repos.c Mon Aug 29 13:41:11 2016
@@ -3236,7 +3236,7 @@ set_headers(request_rec *r, const dav_re
 
 
 typedef struct diff_ctx_t {
-  ap_filter_t *output;
+  dav_svn__output *output;
   apr_bucket_brigade *bb;
 } diff_ctx_t;
 
@@ -3245,14 +3245,9 @@ static svn_error_t *  __attribute__((war
 write_to_filter(void *baton, const char *buffer, apr_size_t *len)
 {
   diff_ctx_t *dc = baton;
-  apr_status_t status;
 
   /* take the current data and shove it into the filter */
-  status = apr_brigade_write(dc->bb, ap_filter_flush, dc->output,
-                             buffer, *len);
-  if (status != APR_SUCCESS)
-    return svn_error_create(status, NULL,
-                            "Could not write data to filter");
+  SVN_ERR(dav_svn__brigade_write(dc->bb, dc->output, buffer, *len));
 
   return SVN_NO_ERROR;
 }
@@ -3263,16 +3258,11 @@ close_filter(void *baton)
 {
   diff_ctx_t *dc = baton;
   apr_bucket *bkt;
-  apr_status_t status;
 
   /* done with the file. write an EOS bucket now. */
-  bkt = apr_bucket_eos_create(dc->output->c->bucket_alloc);
+  bkt = apr_bucket_eos_create(dav_svn__output_get_bucket_alloc(dc->output));
   APR_BRIGADE_INSERT_TAIL(dc->bb, bkt);
-  status = ap_pass_brigade(dc->output, dc->bb);
-  apr_brigade_cleanup(dc->bb);
-
-  if (status != APR_SUCCESS)
-    return svn_error_create(status, NULL, "Could not write EOS to filter");
+  SVN_ERR(dav_svn__output_pass_brigade(dc->output, dc->bb));
 
   return SVN_NO_ERROR;
 }
@@ -3281,7 +3271,7 @@ close_filter(void *baton)
 static svn_error_t *
 emit_collection_head(const dav_resource *resource,
                      apr_bucket_brigade *bb,
-                     ap_filter_t *output,
+                     dav_svn__output *output,
                      svn_boolean_t gen_html,
                      apr_pool_t *pool)
 {
@@ -3409,7 +3399,7 @@ emit_collection_head(const dav_resource
 static svn_error_t *
 emit_collection_entry(const dav_resource *resource,
                       apr_bucket_brigade *bb,
-                      ap_filter_t *output,
+                      dav_svn__output *output,
                       const svn_fs_dirent_t *entry,
                       svn_boolean_t gen_html,
                       apr_pool_t *pool)
@@ -3490,7 +3480,7 @@ emit_collection_entry(const dav_resource
 static svn_error_t *
 emit_collection_tail(const dav_resource *resource,
                      apr_bucket_brigade *bb,
-                     ap_filter_t *output,
+                     dav_svn__output *output,
                      svn_boolean_t gen_html,
                      apr_pool_t *pool)
 {
@@ -3525,12 +3515,12 @@ emit_collection_tail(const dav_resource
 
 
 static dav_error *
-deliver(const dav_resource *resource, ap_filter_t *output)
+deliver(const dav_resource *resource, ap_filter_t *unused)
 {
   svn_error_t *serr;
   apr_bucket_brigade *bb;
   apr_bucket *bkt;
-  apr_status_t status;
+  dav_svn__output *output;
 
   /* Check resource type */
   if (resource->baselined
@@ -3543,6 +3533,8 @@ deliver(const dav_resource *resource, ap
                                 "Cannot GET this type of resource.");
     }
 
+  output = dav_svn__output_create(resource->info->r, resource->pool);
+
   if (resource->collection)
     {
       const int gen_html = !resource->info->repos->xslt_uri;
@@ -3632,7 +3624,8 @@ deliver(const dav_resource *resource, ap
                                         resource->pool);
         }
 
-      bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+      bb = apr_brigade_create(resource->pool,
+                              dav_svn__output_get_bucket_alloc(output));
 
       serr = emit_collection_head(resource, bb, output, gen_html,
                                   resource->pool);
@@ -3695,12 +3688,13 @@ deliver(const dav_resource *resource, ap
                                     "could not output collection",
                                     resource->pool);
 
-      bkt = apr_bucket_eos_create(output->c->bucket_alloc);
+      bkt = apr_bucket_eos_create(dav_svn__output_get_bucket_alloc(output));
       APR_BRIGADE_INSERT_TAIL(bb, bkt);
-      if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS)
-        return dav_svn__new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR,
-                                  0, status,
-                                  "Could not write EOS to filter.");
+      serr = dav_svn__output_pass_brigade(output, bb);
+      if (serr != NULL)
+        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                    "Could not write EOS to filter.",
+                                    resource->pool);
 
       return NULL;
     }
@@ -3763,7 +3757,8 @@ deliver(const dav_resource *resource, ap
                                         "could not prepare to read a delta",
                                         resource->pool);
 
-          bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+          bb = apr_brigade_create(resource->pool,
+                                  dav_svn__output_get_bucket_alloc(output));
 
           /* create a stream that svndiff data will be written to,
              which will copy it to the network */
@@ -3891,7 +3886,8 @@ deliver(const dav_resource *resource, ap
          ### which will read from the FS stream on demand */
 
       block = apr_palloc(resource->pool, SVN__STREAM_CHUNK_SIZE);
-      bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+      bb = apr_brigade_create(resource->pool,
+                              dav_svn__output_get_bucket_alloc(output));
 
       while (1) {
         apr_size_t bufsize = SVN__STREAM_CHUNK_SIZE;
@@ -3909,29 +3905,32 @@ deliver(const dav_resource *resource, ap
           break;
 
         /* write to the filter ... */
-        bkt = apr_bucket_transient_create(block, bufsize,
-                                          output->c->bucket_alloc);
+        bkt = apr_bucket_transient_create(
+          block, bufsize, dav_svn__output_get_bucket_alloc(output));
         APR_BRIGADE_INSERT_TAIL(bb, bkt);
-        if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS) {
-          apr_brigade_destroy(bb);
-          /* ### that HTTP code... */
-          return dav_svn__new_error(resource->pool,
-                                    HTTP_INTERNAL_SERVER_ERROR, 0, status,
-                                    "Could not write data to filter.");
-        }
-        apr_brigade_cleanup(bb);
+        serr = dav_svn__output_pass_brigade(output, bb);
+        if (serr != NULL)
+          {
+            apr_brigade_destroy(bb);
+            /* ### that HTTP code... */
+            return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                        "Could not write data to filter.",
+                                        resource->pool);
+          }
       }
 
       /* done with the file. write an EOS bucket now. */
-      bkt = apr_bucket_eos_create(output->c->bucket_alloc);
+      bkt = apr_bucket_eos_create(dav_svn__output_get_bucket_alloc(output));
       APR_BRIGADE_INSERT_TAIL(bb, bkt);
-      if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS) {
-        apr_brigade_destroy(bb);
-        /* ### that HTTP code... */
-        return dav_svn__new_error(resource->pool,
-                                  HTTP_INTERNAL_SERVER_ERROR, 0, status,
-                                  "Could not write EOS to filter.");
-      }
+      serr = dav_svn__output_pass_brigade(output, bb);
+      if (serr != NULL)
+        {
+          apr_brigade_destroy(bb);
+          /* ### that HTTP code... */
+          return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                      "Could not write EOS to filter.",
+                                      resource->pool);
+        }
 
       apr_brigade_destroy(bb);
       return NULL;
@@ -4712,7 +4711,7 @@ dav_svn__create_version_resource(dav_res
 static dav_error *
 handle_post_request(request_rec *r,
                     dav_resource *resource,
-                    ap_filter_t *output)
+                    dav_svn__output *output)
 {
   svn_skel_t *request_skel, *post_skel;
   int status;
@@ -4795,7 +4794,9 @@ int dav_svn__method_post(request_rec *r)
   content_type = apr_table_get(r->headers_in, "content-type");
   if (content_type && (strcmp(content_type, SVN_SKEL_MIME_TYPE) == 0))
     {
-      derr = handle_post_request(r, resource, r->output_filters);
+      dav_svn__output *output = dav_svn__output_create(resource->info->r,
+                                                       resource->pool);
+      derr = handle_post_request(r, resource, output);
     }
   else
     {

Modified: subversion/trunk/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/util.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/util.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/util.c Mon Aug 29 13:41:11 2016
@@ -465,6 +465,48 @@ dav_svn__find_ns(const apr_array_header_
   return -1;
 }
 
+
+/*** Output helpers ***/
+
+
+struct dav_svn__output
+{
+  request_rec *r;
+};
+
+dav_svn__output *
+dav_svn__output_create(request_rec *r,
+                       apr_pool_t *pool)
+{
+  dav_svn__output *output = apr_pcalloc(pool, sizeof(*output));
+  output->r = r;
+  return output;
+}
+
+apr_bucket_alloc_t *
+dav_svn__output_get_bucket_alloc(dav_svn__output *output)
+{
+  return output->r->connection->bucket_alloc;
+}
+
+svn_error_t *
+dav_svn__output_pass_brigade(dav_svn__output *output,
+                             apr_bucket_brigade *bb)
+{
+  apr_status_t status;
+
+  status = ap_pass_brigade(output->r->output_filters, bb);
+  /* Empty the brigade here, as required by ap_pass_brigade(). */
+  apr_brigade_cleanup(bb);
+  if (status)
+    return svn_error_create(status, NULL, "Could not write data to filter");
+
+  /* Check for an aborted connection, since the brigade functions don't
+     appear to return useful errors when the connection is dropped. */
+  if (output->r->connection->aborted)
+    return svn_error_create(SVN_ERR_APMOD_CONNECTION_ABORTED, NULL, NULL);
+  return SVN_NO_ERROR;
+}
 
 
 /*** Brigade I/O wrappers ***/
@@ -472,17 +514,18 @@ dav_svn__find_ns(const apr_array_header_
 
 svn_error_t *
 dav_svn__brigade_write(apr_bucket_brigade *bb,
-                       ap_filter_t *output,
+                       dav_svn__output *output,
                        const char *data,
                        apr_size_t len)
 {
   apr_status_t apr_err;
-  apr_err = apr_brigade_write(bb, ap_filter_flush, output, data, len);
+  apr_err = apr_brigade_write(bb, ap_filter_flush,
+                              output->r->output_filters, data, len);
   if (apr_err)
     return svn_error_create(apr_err, 0, NULL);
   /* Check for an aborted connection, since the brigade functions don't
      appear to be return useful errors when the connection is dropped. */
-  if (output->c->aborted)
+  if (output->r->connection->aborted)
     return svn_error_create(SVN_ERR_APMOD_CONNECTION_ABORTED, 0, NULL);
   return SVN_NO_ERROR;
 }
@@ -490,16 +533,17 @@ dav_svn__brigade_write(apr_bucket_brigad
 
 svn_error_t *
 dav_svn__brigade_puts(apr_bucket_brigade *bb,
-                      ap_filter_t *output,
+                      dav_svn__output *output,
                       const char *str)
 {
   apr_status_t apr_err;
-  apr_err = apr_brigade_puts(bb, ap_filter_flush, output, str);
+  apr_err = apr_brigade_puts(bb, ap_filter_flush,
+                             output->r->output_filters, str);
   if (apr_err)
     return svn_error_create(apr_err, 0, NULL);
   /* Check for an aborted connection, since the brigade functions don't
      appear to be return useful errors when the connection is dropped. */
-  if (output->c->aborted)
+  if (output->r->connection->aborted)
     return svn_error_create(SVN_ERR_APMOD_CONNECTION_ABORTED, 0, NULL);
   return SVN_NO_ERROR;
 }
@@ -507,7 +551,7 @@ dav_svn__brigade_puts(apr_bucket_brigade
 
 svn_error_t *
 dav_svn__brigade_printf(apr_bucket_brigade *bb,
-                        ap_filter_t *output,
+                        dav_svn__output *output,
                         const char *fmt,
                         ...)
 {
@@ -515,13 +559,14 @@ dav_svn__brigade_printf(apr_bucket_briga
   va_list ap;
 
   va_start(ap, fmt);
-  apr_err = apr_brigade_vprintf(bb, ap_filter_flush, output, fmt, ap);
+  apr_err = apr_brigade_vprintf(bb, ap_filter_flush,
+                                output->r->output_filters, fmt, ap);
   va_end(ap);
   if (apr_err)
     return svn_error_create(apr_err, 0, NULL);
   /* Check for an aborted connection, since the brigade functions don't
      appear to be return useful errors when the connection is dropped. */
-  if (output->c->aborted)
+  if (output->r->connection->aborted)
     return svn_error_create(SVN_ERR_APMOD_CONNECTION_ABORTED, 0, NULL);
   return SVN_NO_ERROR;
 }
@@ -529,20 +574,21 @@ dav_svn__brigade_printf(apr_bucket_briga
 
 svn_error_t *
 dav_svn__brigade_putstrs(apr_bucket_brigade *bb,
-                         ap_filter_t *output,
+                         dav_svn__output *output,
                          ...)
 {
   apr_status_t apr_err;
   va_list ap;
 
   va_start(ap, output);
-  apr_err = apr_brigade_vputstrs(bb, ap_filter_flush, output, ap);
+  apr_err = apr_brigade_vputstrs(bb, ap_filter_flush,
+                                 output->r->output_filters, ap);
   va_end(ap);
   if (apr_err)
     return svn_error_create(apr_err, NULL, NULL);
   /* Check for an aborted connection, since the brigade functions don't
      appear to return useful errors when the connection is dropped. */
-  if (output->c->aborted)
+  if (output->r->connection->aborted)
     return svn_error_create(SVN_ERR_APMOD_CONNECTION_ABORTED, NULL, NULL);
   return SVN_NO_ERROR;
 }
@@ -609,7 +655,7 @@ dav_svn__sanitize_error(svn_error_t *ser
 struct brigade_write_baton
 {
   apr_bucket_brigade *bb;
-  ap_filter_t *output;
+  dav_svn__output *output;
 };
 
 
@@ -620,7 +666,8 @@ brigade_write_fn(void *baton, const char
   struct brigade_write_baton *wb = baton;
   apr_status_t apr_err;
 
-  apr_err = apr_brigade_write(wb->bb, ap_filter_flush, wb->output, data, *len);
+  apr_err = apr_brigade_write(wb->bb, ap_filter_flush,
+                              wb->output->r->output_filters, data, *len);
 
   if (apr_err != APR_SUCCESS)
     return svn_error_wrap_apr(apr_err, "Error writing base64 data");
@@ -631,7 +678,7 @@ brigade_write_fn(void *baton, const char
 
 svn_stream_t *
 dav_svn__make_base64_output_stream(apr_bucket_brigade *bb,
-                                   ap_filter_t *output,
+                                   dav_svn__output *output,
                                    apr_pool_t *pool)
 {
   struct brigade_write_baton *wb = apr_palloc(pool, sizeof(*wb));
@@ -658,7 +705,7 @@ dav_svn__operational_log(struct dav_reso
 dav_error *
 dav_svn__final_flush_or_error(request_rec *r,
                               apr_bucket_brigade *bb,
-                              ap_filter_t *output,
+                              dav_svn__output *output,
                               dav_error *preferred_err,
                               apr_pool_t *pool)
 {
@@ -680,7 +727,7 @@ dav_svn__final_flush_or_error(request_re
      provided a more-important DERR, though. */
   if (do_flush)
     {
-      apr_status_t apr_err = ap_fflush(output, bb);
+      apr_status_t apr_err = ap_fflush(output->r->output_filters, bb);
       if (apr_err && (! derr))
         derr = dav_svn__new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, apr_err,
                                   "Error flushing brigade.");

Modified: subversion/trunk/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/version.c?rev=1758224&r1=1758223&r2=1758224&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/version.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/version.c Mon Aug 29 13:41:11 2016
@@ -1096,12 +1096,16 @@ static dav_error *
 deliver_report(request_rec *r,
                const dav_resource *resource,
                const apr_xml_doc *doc,
-               ap_filter_t *output)
+               ap_filter_t *unused)
 {
   int ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
 
   if (doc->root->ns == ns)
     {
+      dav_svn__output *output;
+
+      output = dav_svn__output_create(resource->info->r, resource->pool);
+
       /* ### note that these report names should have symbols... */
 
       if (strcmp(doc->root->name, "update-report") == 0)
@@ -1408,7 +1412,7 @@ merge(dav_resource *target,
       int no_auto_merge,
       int no_checkout,
       apr_xml_elem *prop_elem,
-      ap_filter_t *output)
+      ap_filter_t *unused)
 {
   apr_pool_t *pool;
   dav_error *err;
@@ -1419,6 +1423,7 @@ merge(dav_resource *target,
   svn_revnum_t new_rev;
   apr_hash_t *locks;
   svn_boolean_t disable_merge_response = FALSE;
+  dav_svn__output *output;
 
   /* We'll use the target's pool for our operation. We happen to know that
      it matches the request pool, which (should) have the proper lifetime. */
@@ -1588,6 +1593,7 @@ merge(dav_resource *target,
     }
 
   /* process the response for the new revision. */
+  output = dav_svn__output_create(source->info->r, pool);
   return dav_svn__merge_response(output, source->info->repos, new_rev,
                                  post_commit_err, prop_elem,
                                  disable_merge_response, pool);



Mime
View raw message