From 67ce4131226281fa1e69747d3bfb85829d5f0825 Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Wed, 24 Jan 2001 01:38:31 +0000 Subject: [PATCH] Loop over the brigade when multiple buckets file are found, instead of breaking out of the function. Submitted by: Greg Stein git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87805 13f79535-47bb-0310-9956-ffa450edef68 --- modules/http/http_core.c | 249 ++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 121 deletions(-) diff --git a/modules/http/http_core.c b/modules/http/http_core.c index b7e6e20e38..4578b4b9b5 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -3343,144 +3343,151 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) } /* Iterate over the brigade collecting iovecs */ - while (b) { - nbytes = 0; /* in case more points to another brigade */ - more = NULL; - APR_BRIGADE_FOREACH(e, b) { - if (APR_BUCKET_IS_EOS(e) || APR_BUCKET_IS_FLUSH(e)) { - break; - } - /* It doesn't make any sense to use sendfile for a file bucket - * that represents 10 bytes. - */ - else if (APR_BUCKET_IS_FILE(e) && (e->length >= AP_MIN_SENDFILE_BYTES)) { - apr_bucket_shared *s = e->data; - apr_bucket_file *a = s->data; - - /* We can't handle more than one file bucket at a time - * so we split here and send the file we have already found. - */ - if (fd) { - more = apr_brigade_split(b, APR_BUCKET_NEXT(e)); - ap_save_brigade(f, &ctx->b, &more); + do { + while (b) { + nbytes = 0; /* in case more points to another brigade */ + APR_BRIGADE_FOREACH(e, b) { + if (APR_BUCKET_IS_EOS(e) || APR_BUCKET_IS_FLUSH(e)) { break; } - - fd = a->fd; - flen = e->length; - foffset = s->start; - } - else { - const char *str; - apr_size_t n; - rv = apr_bucket_read(e, &str, &n, APR_BLOCK_READ); - if (n) { - nbytes += n; - if (!fd) { - vec[nvec].iov_base = (char*) str; - vec[nvec].iov_len = n; - nvec++; + /* It doesn't make any sense to use sendfile for a file bucket + * that represents 10 bytes. + */ + else if (APR_BUCKET_IS_FILE(e) && (e->length >= AP_MIN_SENDFILE_BYTES)) { + apr_bucket_shared *s = e->data; + apr_bucket_file *a = s->data; + + /* We can't handle more than one file bucket at a time + * so we split here and send the file we have already found. + */ + if (fd) { + more = apr_brigade_split(b, e); + break; } - else { - /* The bucket is a trailer to a file bucket */ - vec_trailers[nvec_trailers].iov_base = (char*) str; - vec_trailers[nvec_trailers].iov_len = n; - nvec_trailers++; + + fd = a->fd; + flen = e->length; + foffset = s->start; + } + else { + const char *str; + apr_size_t n; + rv = apr_bucket_read(e, &str, &n, APR_BLOCK_READ); + if (n) { + nbytes += n; + if (!fd) { + vec[nvec].iov_base = (char*) str; + vec[nvec].iov_len = n; + nvec++; + } + else { + /* The bucket is a trailer to a file bucket */ + vec_trailers[nvec_trailers].iov_base = (char*) str; + vec_trailers[nvec_trailers].iov_len = n; + nvec_trailers++; + } } } - } - - if ((nvec == MAX_IOVEC_TO_WRITE) || (nvec_trailers == MAX_IOVEC_TO_WRITE)) { - /* Split the brigade and break */ - if (APR_BUCKET_NEXT(e) != APR_BRIGADE_SENTINEL(b)) { - more = apr_brigade_split(b, APR_BUCKET_NEXT(e)); + + if ((nvec == MAX_IOVEC_TO_WRITE) || + (nvec_trailers == MAX_IOVEC_TO_WRITE)) { + /* Split the brigade and break */ + if (APR_BUCKET_NEXT(e) != APR_BRIGADE_SENTINEL(b)) { + more = apr_brigade_split(b, APR_BUCKET_NEXT(e)); + } + break; } - break; } - } - - /* Completed iterating over the brigades, now determine if we want to - * buffer the brigade or send the brigade out on the network - */ - if ((!fd && (!more) && (nbytes < AP_MIN_BYTES_TO_WRITE) && !APR_BUCKET_IS_FLUSH(e)) - || (APR_BUCKET_IS_EOS(e) && c->keepalive)) { - - /* NEVER save an EOS in here. If we are saving a brigade with an - * EOS bucket, then we are doing keepalive connections, and we want - * to process to second request fully. + + /* Completed iterating over the brigades, now determine if we want + * to buffer the brigade or send the brigade out on the network */ - if (APR_BUCKET_IS_EOS(e)) { - APR_BUCKET_REMOVE(e); - apr_bucket_destroy(e); + if ((!fd && (!more) && + (nbytes < AP_MIN_BYTES_TO_WRITE) && !APR_BUCKET_IS_FLUSH(e)) + || (APR_BUCKET_IS_EOS(e) && c->keepalive)) { + + /* NEVER save an EOS in here. If we are saving a brigade with + * an EOS bucket, then we are doing keepalive connections, and + * we want to process to second request fully. + */ + if (APR_BUCKET_IS_EOS(e)) { + APR_BUCKET_REMOVE(e); + apr_bucket_destroy(e); + } + ap_save_brigade(f, &ctx->b, &b); + return APR_SUCCESS; } - ap_save_brigade(f, &ctx->b, &b); - return APR_SUCCESS; - } - if (fd) { - apr_hdtr_t hdtr; + if (fd) { + apr_hdtr_t hdtr; #if APR_HAS_SENDFILE - apr_int32_t flags = 0; + apr_int32_t flags = 0; #endif - - memset(&hdtr, '\0', sizeof(hdtr)); - if (nvec) { - hdtr.numheaders = nvec; - hdtr.headers = vec; - } - if (nvec_trailers) { - hdtr.numtrailers = nvec_trailers; - hdtr.trailers = vec_trailers; - } + + memset(&hdtr, '\0', sizeof(hdtr)); + if (nvec) { + hdtr.numheaders = nvec; + hdtr.headers = vec; + } + if (nvec_trailers) { + hdtr.numtrailers = nvec_trailers; + hdtr.trailers = vec_trailers; + } #if APR_HAS_SENDFILE - if (!c->keepalive) { - /* Prepare the socket to be reused */ - flags |= APR_SENDFILE_DISCONNECT_SOCKET; - } - rv = sendfile_it_all(c, /* the connection */ - fd, /* the file to send */ - &hdtr, /* header and trailer iovecs */ - foffset, /* offset in the file to begin - sending from */ - flen, /* length of file */ - nbytes + flen, /* total length including - headers */ - flags); /* apr_sendfile flags */ - - /* If apr_sendfile() returns APR_ENOTIMPL, call send_the_file() to - * loop on apr_read/apr_send to send the file. Our Windows binary - * distributions (which work on Windows 9x/NT) are compiled on - * Windows NT. TransmitFile is not available on Windows 95/98 and - * we discover this at runtime when apr_sendfile() returns - * APR_ENOTIMPL. Having apr_sendfile() return APR_ENOTIMPL seems - * the cleanest way to handle this case. - */ - if (rv == APR_ENOTIMPL) { + if (!c->keepalive) { + /* Prepare the socket to be reused */ + flags |= APR_SENDFILE_DISCONNECT_SOCKET; + } + rv = sendfile_it_all(c, /* the connection */ + fd, /* the file to send */ + &hdtr, /* header and trailer iovecs */ + foffset, /* offset in the file to begin + sending from */ + flen, /* length of file */ + nbytes + flen, /* total length including + headers */ + flags); /* apr_sendfile flags */ + + /* If apr_sendfile() returns APR_ENOTIMPL, call send_the_file() + * to loop on apr_read/apr_send to send the file. Our Windows + * binary distributions (which work on Windows 9x/NT) are + * compiled on Windows NT. TransmitFile is not available on + * Windows 95/98 and we discover this at runtime when + * apr_sendfile() returns APR_ENOTIMPL. Having apr_sendfile() + * return APR_ENOTIMPL seems the cleanest way to handle this + * case. + */ + if (rv == APR_ENOTIMPL) { #endif - - rv = send_the_file(c, fd, &hdtr, foffset, flen, &bytes_sent); - + + rv = send_the_file(c, fd, &hdtr, foffset, flen, &bytes_sent); + #if APR_HAS_SENDFILE - } + } #endif - } - else { - rv = writev_it_all(c->client_socket, - vec, nvec, - nbytes, &bytes_sent); - } - - apr_brigade_destroy(b); - if (rv != APR_SUCCESS) { - /* XXX: log the error */ - if (more) - apr_brigade_destroy(more); - return rv; - } - nvec = 0; - nvec_trailers = 0; + fd = NULL; + } + else { + rv = writev_it_all(c->client_socket, + vec, nvec, + nbytes, &bytes_sent); + } + + apr_brigade_destroy(b); + if (rv != APR_SUCCESS) { + /* XXX: log the error */ + if (more) + apr_brigade_destroy(more); + return rv; + } + nvec = 0; + nvec_trailers = 0; + + b = more; + more = NULL; + } /* end while () */ b = more; - } /* end while () */ + } while (more); return APR_SUCCESS; } -- 2.40.0