diff options
author | Bill Stoddard <stoddard@apache.org> | 2000-09-21 18:22:13 +0200 |
---|---|---|
committer | Bill Stoddard <stoddard@apache.org> | 2000-09-21 18:22:13 +0200 |
commit | 9115d6301c2c34fae742e6457fa1f089c268b7cc (patch) | |
tree | 4e60653920bb926b8f0903df717edc6f8c783f81 | |
parent | Fix the prior fix to the usage of ap_brigade_split()... The caller of (diff) | |
download | apache2-9115d6301c2c34fae742e6457fa1f089c268b7cc.tar.xz apache2-9115d6301c2c34fae742e6457fa1f089c268b7cc.zip |
First cut at a file bucket. Modify the core_filter to handle use
of apr_sendfile(). Modify ap_send_fd() to use the new file bucket.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86278 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | ApacheCore.dsp | 4 | ||||
-rw-r--r-- | httpd.dsp | 4 | ||||
-rw-r--r-- | modules/http/http_core.c | 113 | ||||
-rw-r--r-- | modules/http/http_protocol.c | 74 |
4 files changed, 125 insertions, 70 deletions
diff --git a/ApacheCore.dsp b/ApacheCore.dsp index c26b7c42e7..7528d2544d 100644 --- a/ApacheCore.dsp +++ b/ApacheCore.dsp @@ -98,6 +98,10 @@ SOURCE=.\ap\ap_buckets_eos.c # End Source File # Begin Source File +SOURCE=.\ap\ap_buckets_file.c +# End Source File +# Begin Source File + SOURCE=.\ap\ap_buckets_heap.c # End Source File # Begin Source File @@ -98,6 +98,10 @@ SOURCE=.\ap\ap_buckets_eos.c # End Source File # Begin Source File +SOURCE=.\ap\ap_buckets_file.c +# End Source File +# Begin Source File + SOURCE=.\ap\ap_buckets_heap.c # End Source File # Begin Source File diff --git a/modules/http/http_core.c b/modules/http/http_core.c index d676b02924..f855e0a6c5 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -2525,6 +2525,61 @@ static const char *set_limit_nproc(cmd_parms *cmd, void *conf_, } #endif +#if APR_HAS_SENDFILE +static apr_status_t send_the_file(apr_file_t *fd, apr_off_t offset, apr_size_t length, + request_rec *r, apr_size_t *nbytes) +{ + apr_int32_t flags = 0; + apr_status_t rv; + struct iovec iov; + apr_hdtr_t hdtr; + +#if 0 + ap_bsetopt(r->connection->client, BO_TIMEOUT, + r->connection->keptalive + ? &r->server->keep_alive_timeout + : &r->server->timeout); +#endif + /* + * We want to send any data held in the client buffer on the + * call to apr_sendfile. So hijack it then set outcnt to 0 + * to prevent the data from being sent to the client again + * when the buffer is flushed to the client at the end of the + * request. + */ + iov.iov_base = r->connection->client->outbase; + iov.iov_len = r->connection->client->outcnt; + r->connection->client->outcnt = 0; + + /* initialize the apr_hdtr_t struct */ + hdtr.headers = &iov; + hdtr.numheaders = 1; + hdtr.trailers = NULL; + hdtr.numtrailers = 0; + + if (!r->connection->keepalive) { + /* Prepare the socket to be reused */ + /* XXX fix me - byteranges? */ + flags |= APR_SENDFILE_DISCONNECT_SOCKET; + } + + rv = apr_sendfile(r->connection->client->bsock, + fd, /* The file to send */ + &hdtr, /* Header and trailer iovecs */ + &offset, /* Offset in file to begin sending from */ + &length, + flags); +#if 0 + if (r->connection->keptalive) { + ap_bsetopt(r->connection->client, BO_TIMEOUT, + &r->server->timeout); + } +#endif + *nbytes = length; + + return rv; +} +#endif /* Note --- ErrorDocument will now work from .htaccess files. * The AllowOverride of Fileinfo allows webmasters to turn it off */ @@ -3058,9 +3113,7 @@ static apr_status_t chunk_filter(ap_filter_t *f, ap_bucket_brigade *b) */ static int core_filter(ap_filter_t *f, ap_bucket_brigade *b) { -#if 0 request_rec *r = f->r; -#endif apr_status_t rv; apr_ssize_t bytes_sent = 0, len = 0, written; ap_bucket *e; @@ -3087,25 +3140,51 @@ static int core_filter(ap_filter_t *f, ap_bucket_brigade *b) } else { #endif - AP_BRIGADE_FOREACH(e, b) { - rv = e->read(e, &str, &len, 0); - if (rv != APR_SUCCESS) { - return rv; - } - if (len == AP_END_OF_BRIGADE) { - break; - } - rv = ap_bwrite(f->r->connection->client, str, len, &written); - if (rv != APR_SUCCESS) { - return rv; - } - bytes_sent += written; - } + + AP_BRIGADE_FOREACH(e, b) { + if (e->type == AP_BUCKET_EOS) { + /* there shouldn't be anything after the eos */ + break; + } + else if (e->type == AP_BUCKET_FILE) { +#if APR_HAS_SENDFILE + /* If a file bucket gets all the way down to the core filter, + * the bucket by definition represents the unfiltered contents + * of a file. Thus it is acceptable to use apr_sendfile(). + */ + rv = send_the_file(e->data, e->offset, e->length, r, &bytes_sent); + + if (rv == APR_SUCCESS) { + ap_brigade_destroy(b); + return APR_SUCCESS; + } + + /* If apr_sendfile is not implemented (e.g. Win95/98), then + * continue to the read/write loop. + */ + if (rv != APR_ENOTIMPL) { + /* check_first_conn_error(r, "send_fd", rv); */ + return rv; + } +#endif + } + rv = e->read(e, &str, &len, 0); + if (rv != APR_SUCCESS) { + return rv; + } + rv = ap_bwrite(r->connection->client, str, len, &written); + if (rv != APR_SUCCESS) { + return rv; + } + bytes_sent += written; + } + ap_brigade_destroy(b); /* This line will go away as soon as the BUFFs are removed */ if (len == AP_END_OF_BRIGADE) { - ap_bflush(f->r->connection->client); + ap_bflush(r->connection->client); } + return APR_SUCCESS; #if 0 } diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 5d81855733..e44fd5faf7 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -2514,63 +2514,30 @@ API_EXPORT(int) ap_discard_request_body(request_rec *r) return OK; } -#if APR_HAS_SENDFILE -static apr_status_t static_send_file(apr_file_t *fd, request_rec *r, apr_off_t offset, - apr_size_t length, apr_size_t *nbytes) +/* + * Send the body of a response to the client. + */ +API_EXPORT(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset, + apr_size_t len, apr_size_t *nbytes) { - apr_int32_t flags = 0; - apr_status_t rv; - struct iovec iov; - apr_hdtr_t hdtr; - - ap_bsetopt(r->connection->client, BO_TIMEOUT, - r->connection->keptalive - ? &r->server->keep_alive_timeout - : &r->server->timeout); - - /* - * We want to send any data held in the client buffer on the - * call to apr_sendfile. So hijack it then set outcnt to 0 - * to prevent the data from being sent to the client again - * when the buffer is flushed to the client at the end of the - * request. - */ - iov.iov_base = r->connection->client->outbase; - iov.iov_len = r->connection->client->outcnt; - r->connection->client->outcnt = 0; - - /* initialize the apr_hdtr_t struct */ - hdtr.headers = &iov; - hdtr.numheaders = 1; - hdtr.trailers = NULL; - hdtr.numtrailers = 0; - - if (!r->connection->keepalive) { - /* Prepare the socket to be reused */ - /* XXX fix me - byteranges? */ - flags |= APR_SENDFILE_DISCONNECT_SOCKET; - } - - rv = apr_sendfile(r->connection->client->bsock, - fd, /* The file to send */ - &hdtr, /* Header and trailer iovecs */ - &offset, /* Offset in file to begin sending from */ - &length, - flags); + ap_bucket_brigade *bb = NULL; + ap_bucket *b; - if (r->connection->keptalive) { - ap_bsetopt(r->connection->client, BO_TIMEOUT, - &r->server->timeout); - } + bb = ap_brigade_create(r->pool); + b = ap_bucket_create_file(fd, offset, len); + AP_BRIGADE_INSERT_TAIL(bb, b); - *nbytes = length; + /* Hummm, is this the right place to insert eos? */ +#if 0 + b = ap_bucket_create_eos(); + AP_BRIGADE_INSERT_TAIL(bb, b); +#endif + ap_pass_brigade(r->output_filters, bb); - return rv; + return len; } -#endif -/* - * Send the body of a response to the client. - */ +#if 0 +/* Leave the old implementation around temporarily for reference purposes */ API_EXPORT(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset, apr_size_t length, apr_size_t *nbytes) { @@ -2642,7 +2609,8 @@ API_EXPORT(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t of SET_BYTES_SENT(r); *nbytes = total_bytes_sent; return rv; -} +} +#endif /* * Send the body of a response to the client. |