httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Greg Stein <>
Subject Re: filtered I/O - flow control
Date Thu, 01 Jun 2000 19:52:37 GMT
On Thu, 1 Jun 2000 wrote:
> A couple of things that MUST be done regardless of which design is
> used.  The headers can't be sent from the output generator.  If they are,
> the filter's must parse and munge HTTP headers, Bad mojo.  The headers
> should be stored in an array in the request_rec,

This is pretty much how Apache works today. All of the headers go into
r->headers_out. Right before a client wants to begin sending the body of
the response, they call ap_send_http_header().

ap_send_http_header() calls ap_send_header_field() which calls
ap_rvputs(). In both designs, this would cause problems since we planning
to hook the ap_rwrite (and friends) functions. ap_send_header_field would
need to be changed to use ap_bwrite() or something.

> and sent out from ap_r*
> after the filters are run (in the hook design) or from ap_lfoo just before
> the data is sent (in the link design).

Given that all "body output" will come through ap_r*(), we can fix Apache
to automatically call ap_send_http_header(). This would allow the content
generator and the filters to monkey with the headers right up to the last
moment. It also means people don't have to worry about calling
ap_send_http_header() any more, which can be a bonus.

> The basic flow control for the hook based design would be that 
> The generator would generate the data and pass it to ap_r* which passes it
> to the first filter.  The first filter passes it back to ap_r* which
> passes it to the next filter and so until all filters are done
> executing.  At that point, it gets passed to ap_bwrite which actually
> writes to the network.  If at any point there is too much data to write to
> the network, it will be up to Apache's internal buffering to catch it and
> hold it until the socket is ready.  I expect that this is the way the link
> based design would work as well.

Yes. The two approaches filter the data a bit differently, but the end
result is arrival at ap_bwrite() after the filtering. Apache then delivers
the data to the socket, which will block the thread if we jam too much in

> In this design, there is no reason for
> the filters to "wake up" once the socket is ready for more data, because
> they weren't executing when the data was being written to the socket.

The thread blocks on the write to the socket. It will then unblock when
the socket clears out some data.

> It will need to be possible for either approach for the filter to save the
> data off to the side (along with the current filter list [either as a
> linked list or as a table (the way hooks are implemented)]), and then come
> back later and get the data back and continue parsing it.  Both
> implementations have mechanisms for doing this in their design.

In the link-based approach, each layer is defined as:

struct ap_layer_t {
    ap_layer_func_t *callback;  /* callback to process a write */
    void *ctx;                  /* context for callback */
    struct ap_layer_t *next;    /* next layer to call */
    request_rec *r;             /* associated request for this layer */

The callback prototype is:

ap_status_t my_callback(ap_layer_t *this_layer, const void *buf, size_t len);

This is a bit different than my initial suggestion a couple months ago.
Specifically, it provides the container for the context (e.g. mod_include
state) and request that the layer is associated with (to deal with
sub-request issues).

I am not sure how the hook-based mechanism would record state. I presume
that it would set "user data" on the request_rec.


Greg Stein,

View raw message