httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Paul J. Reder" <rede...@raleigh.ibm.com>
Subject [Patch]: Make mod_include pass large files in chunks
Date Wed, 21 Feb 2001 15:48:41 GMT
This patch makes mod_include pass AP_MIN_BYTES_TO_WRITE (9000) byte chunks
for SSI files with lots of intervening non-SSI bytes. This should prevent
a large file from being buffered in memory, and should allow the nice user
to start seeing something sooner.

-- 
Paul J. Reder
-----------------------------------------------------------
"The strength of the Constitution lies entirely in the determination of each
citizen to defend it.  Only if every single citizen feels duty bound to do
his share in this defense are the constitutional rights secure."
-- Albert Einstein



Index: mod_include.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/modules/filters/mod_include.c,v
retrieving revision 1.99
diff -u -r1.99 mod_include.c
--- mod_include.c	2001/02/16 13:38:21	1.99
+++ mod_include.c	2001/02/21 03:30:49
@@ -81,6 +81,7 @@
 #include "util_filter.h"
 #include "httpd.h"
 #include "http_config.h"
+#include "http_core.h"
 #include "http_request.h"
 #include "http_core.h"
 #include "http_protocol.h"
@@ -95,6 +96,7 @@
 static apr_hash_t *include_hash;
 static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
 
+#define BYTE_COUNT_THRESHOLD AP_MIN_BYTES_TO_WRITE
 
 /* ------------------------ Environment function -------------------------- */
 
@@ -148,6 +150,8 @@
     const char *c;
     const char *buf;
     const char *str = STARTING_SEQUENCE;
+    apr_bucket *tmp_bkt;
+    apr_size_t  start_index;
 
     *do_cleanup = 0;
 
@@ -162,6 +166,27 @@
         }
         c = buf;
         while (c - buf != len) {
+            if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+                apr_bucket *start_bucket;
+
+                if (ctx->head_start_index > 0) {
+                    start_index  = ctx->head_start_index;
+                    start_bucket = ctx->head_start_bucket;
+                }
+                else {
+                    start_index  = (c - buf);
+                    start_bucket = dptr;
+                }
+                apr_bucket_split(start_bucket, start_index);
+                tmp_bkt = APR_BUCKET_NEXT(start_bucket);
+                if (ctx->head_start_index > 0) {
+                    ctx->head_start_index  = 0;
+                    ctx->head_start_bucket = tmp_bkt;
+                }
+
+                return tmp_bkt;
+            }
+
             if (*c == str[ctx->parse_pos]) {
                 if (ctx->state == PRE_HEAD) {
                     ctx->state             = PARSE_HEAD;
@@ -172,10 +197,8 @@
             }
             else {
                 if (str[ctx->parse_pos] == '\0') {
-                    apr_bucket   *tmp_bkt;
-                    apr_size_t  start_index;
-
                     /* We want to split the bucket at the '<'. */
+                    ctx->bytes_parsed++;
                     ctx->state            = PARSE_DIRECTIVE;
                     ctx->tag_length       = 0;
                     ctx->parse_pos        = 0;
@@ -216,6 +239,7 @@
                 }
             }
             c++;
+            ctx->bytes_parsed++;
         }
         dptr = APR_BUCKET_NEXT(dptr);
     } while (dptr != APR_BRIGADE_SENTINEL(bb));
@@ -245,6 +269,10 @@
             c = buf;
         }
         while (c - buf != len) {
+            if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+                return dptr;
+            }
+
             if (*c == str[ctx->parse_pos]) {
                 if (ctx->state != PARSE_TAIL) {
                     ctx->state             = PARSE_TAIL;
@@ -284,6 +312,7 @@
                          * end of the END_SEQUENCE is in the current bucket.
                          * The beginning might be in a previous bucket.
                          */
+                        ctx->bytes_parsed++;
                         ctx->state = PARSED;
                         if ((c - buf) > 0) {
                             apr_bucket_split(dptr, c - buf);
@@ -323,6 +352,7 @@
                 }
             }
             c++;
+            ctx->bytes_parsed++;
         }
         dptr = APR_BUCKET_NEXT(dptr);
     } while (dptr != APR_BRIGADE_SENTINEL(bb));
@@ -2384,6 +2414,14 @@
                     dptr = APR_BRIGADE_SENTINEL(*bb);
                 }
             }
+            else if ((tmp_dptr != NULL) && (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD))
{
+                               /* Send the large chunk of pre-tag bytes...  */
+                tag_and_after = apr_brigade_split(*bb, tmp_dptr);
+                ap_pass_brigade(f->next, *bb);
+                *bb  = tag_and_after;
+                dptr = tmp_dptr;
+                ctx->bytes_parsed = 0;
+            }
             else if (tmp_dptr == NULL) { /* There was no possible SSI tag in the */
                 dptr = APR_BRIGADE_SENTINEL(*bb);  /* remainder of this brigade...    */
             }
@@ -2410,6 +2448,9 @@
                     APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
                     *bb = tag_and_after;
                 }
+                else if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
+                    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
+                }
             }
             else {
                 dptr = APR_BRIGADE_SENTINEL(*bb);  /* remainder of this brigade...    */
@@ -2587,6 +2628,7 @@
         }
         else { /* Otherwise pass it along... */
             ap_pass_brigade(f->next, *bb);  /* No SSI tags in this brigade... */
+            ctx->bytes_parsed = 0;
         }
     }
     else if (ctx->state == PARSED) {     /* Invalid internal condition... */
@@ -2609,6 +2651,7 @@
             tag_and_after = apr_brigade_split(*bb, ctx->head_start_bucket);
             ap_save_brigade(f, &ctx->ssi_tag_brigade, &tag_and_after);
             ap_pass_brigade(f->next, *bb);
+            ctx->bytes_parsed = 0;
         }
     }
 }
@@ -2691,6 +2734,9 @@
             ap_pass_brigade(f->next, b);
             return APR_ENOMEM;
         }
+    }
+    else {
+        ctx->bytes_parsed = 0;
     }
 
     /* Assure the platform supports Group protections */
Index: mod_include.h
===================================================================
RCS file: /home/cvspublic/httpd-2.0/modules/filters/mod_include.h,v
retrieving revision 1.13
diff -u -r1.13 mod_include.h
--- mod_include.h	2001/02/16 13:38:22	1.13
+++ mod_include.h	2001/02/21 03:30:49
@@ -137,6 +137,7 @@
     long         flags;    /* See the FLAG_XXXXX definitions. */
     int          if_nesting_level;
     apr_size_t   parse_pos;
+    int          bytes_parsed;
     
     apr_bucket   *head_start_bucket;
     apr_size_t   head_start_index;
@@ -189,6 +190,7 @@
                                                                   \
     tag_plus = apr_brigade_split(brgd, cntxt->head_start_bucket); \
     ap_pass_brigade(next, brgd);                                  \
+    cntxt->bytes_parsed = 0;                                      \
     brgd = tag_plus;                                              \
 }

Mime
View raw message