]> granicus.if.org Git - apache/commitdiff
A single outermost loop is all that is needed. Simplify and add comments
authorGreg Stein <gstein@apache.org>
Wed, 24 Jan 2001 06:17:26 +0000 (06:17 +0000)
committerGreg Stein <gstein@apache.org>
Wed, 24 Jan 2001 06:17:26 +0000 (06:17 +0000)
about what is going on in there. Shift some declarations to scope their
usage and (re)initialize them on each pass over the brigade.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87811 13f79535-47bb-0310-9956-ffa450edef68

modules/http/http_core.c

index 4545cb4761ab1831d5c2d7f1af5a5564ec83ea02..5863f80dd7301036572ca7c87831758f9d2152b0 100644 (file)
@@ -3314,28 +3314,19 @@ static int core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mod
 typedef struct CORE_OUTPUT_FILTER_CTX {
     apr_bucket_brigade *b;
 } core_output_filter_ctx_t;
+
 #define MAX_IOVEC_TO_WRITE 16
+
 static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
 {
     apr_status_t rv;
-    apr_bucket_brigade *more = NULL;
-    apr_size_t bytes_sent = 0, nbytes;
-    apr_bucket *e;
     conn_rec *c = f->c;
     core_output_filter_ctx_t *ctx = f->ctx;
 
-    apr_size_t nvec = 0;
-    apr_size_t nvec_trailers= 0;
-    struct iovec vec[MAX_IOVEC_TO_WRITE];
-    struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
-
-    apr_file_t *fd = NULL;
-    apr_size_t flen = 0;
-    apr_off_t foffset = 0;
-
     if (ctx == NULL) {
         f->ctx = ctx = apr_pcalloc(c->pool, sizeof(core_output_filter_ctx_t));
     }
+
     /* If we have a saved brigade, concatenate the new brigade to it */
     if (ctx->b) {
         APR_BRIGADE_CONCAT(ctx->b, b);
@@ -3343,152 +3334,183 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
         ctx->b = NULL;
     }
 
-    /* Iterate over the brigade collecting iovecs */
-    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)) {
+    /* Perform multiple passes over the brigade, sending batches of output
+       to the connection. */
+    while (b) {
+        apr_size_t nbytes = 0;
+        apr_bucket *e;
+
+        /* tail of brigade if we need another pass */
+        apr_bucket_brigade *more = NULL;
+
+        /* one group of iovecs per pass over the brigade */
+        apr_size_t nvec = 0;
+        apr_size_t nvec_trailers = 0;
+        struct iovec vec[MAX_IOVEC_TO_WRITE];
+        struct iovec vec_trailers[MAX_IOVEC_TO_WRITE];
+
+        /* one file per pass over the brigade */
+        apr_file_t *fd = NULL;
+        apr_size_t flen = 0;
+        apr_off_t foffset = 0;
+
+        /* Iterate over the brigade: collect iovecs and/or a file */
+        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, 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, 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++;
                     }
-    
-                    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++;
-                        }
+                    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));
-                    }
-                    break;
+            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;
             }
+        }
     
-            /* 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)) {
+        /* Completed iterating over the brigades, now determine if we want 
+         * to buffer the brigade or send the brigade out on the network.
+         *
+         * Save if:
+         *
+         *   1) we didn't see a file, we don't have more passes over the
+         *      brigade to perform, we haven't accumulated enough bytes to
+         *      send, AND we didn't stop at a FLUSH bucket.
+         *      (IOW, we will save away plain old bytes)
+         * or
+         *   2) we hit the EOS and have a keep-alive connection
+         *      (IOW, this response is a bit more complex, but we save it
+         *       with the hope of concatenating with another response)
+         */
+        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;
+            /* 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);
             }
-            if (fd) {
-                apr_hdtr_t hdtr;
+            ap_save_brigade(f, &ctx->b, &b);
+            return APR_SUCCESS;
+        }
+
+        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 (!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 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);
+                apr_size_t unused_bytes_sent;
+
+                rv = send_the_file(c, fd, &hdtr, foffset, flen,
+                                   &unused_bytes_sent);
     
 #if APR_HAS_SENDFILE
-                }
-#endif
-                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 () */
+#endif
+            fd = NULL;
+        }
+        else {
+            apr_size_t unused_bytes_sent;
+
+            rv = writev_it_all(c->client_socket, 
+                               vec, nvec, 
+                               nbytes, &unused_bytes_sent);
+        }
 
+        apr_brigade_destroy(b);
+        if (rv != APR_SUCCESS) {
+            /* XXX: log the error */
+            if (more)
+                apr_brigade_destroy(more);
+            return rv;
+        }
+    
         b = more;
-    } while (more);
+        more = NULL;
+    }  /* end while () */
 
     return APR_SUCCESS;
 }