changeset 152:fb48bf4fea1c

nginx-0.0.1-2003-10-21-11:47:21 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 21 Oct 2003 07:47:21 +0000
parents 2d9e4a8b6d11
children c71aeb75c071
files src/event/ngx_event_proxy.c src/event/ngx_event_proxy.h src/http/modules/proxy/ngx_http_proxy_handler.c src/http/ngx_http_core_module.c src/http/ngx_http_request.c src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_freebsd_sendfile_chain.c
diffstat 7 files changed, 193 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_proxy.c
+++ b/src/event/ngx_event_proxy.c
@@ -10,6 +10,7 @@ ngx_inline static void ngx_remove_shadow
                                                        ngx_hunk_t *h);
 ngx_inline static void ngx_add_after_partially_filled_hunk(ngx_chain_t **chain,
                                                            ngx_chain_t *ce);
+static int ngx_drain_chains(ngx_event_proxy_t *p);
 
 
 int ngx_event_proxy(ngx_event_proxy_t *p, int do_write)
@@ -53,11 +54,22 @@ int ngx_event_proxy_read_upstream(ngx_ev
     ngx_hunk_t   *h;
     ngx_chain_t  *chain, *ce, *te;
 
+    if (p->upstream_eof || p->upstream_error || p->upstream_done) {
+        return NGX_OK;
+    }
+
     ngx_log_debug(p->log, "read upstream: %d" _ p->upstream->read->ready);
 
-    while (p->preread_hunks
-           || (p->upstream->read->ready && !p->upstream_done))
-    {
+    for ( ;; ) {
+
+        if (p->upstream_eof || p->upstream_error || p->upstream_done) {
+            break;
+        }
+
+        if (p->preread_hunks == NULL && !p->upstream->read->ready) {
+            break;
+        }
+
         if (p->preread_hunks) {
 
             /* use the pre-read hunks if they exist */
@@ -184,14 +196,12 @@ ngx_log_debug(p->log, "FREE: %08X:%d" _ 
                 break;
             }
 
-            /* TODO THINK about eof */
             p->read = 1;
 
             if (n == 0) {
                 p->upstream_eof = 1;
                 break;
             }
-
         }
 
         ce = chain;
@@ -244,13 +254,16 @@ ngx_log_debug(p->log, "PART: %08X:%d" _ 
 
 int ngx_event_proxy_write_to_downstream(ngx_event_proxy_t *p)
 {
-    int           rc;
+    size_t        busy_len;
     ngx_hunk_t   *h;
     ngx_chain_t  *out, *ce, *te;
 
     ngx_log_debug(p->log, "write downstream: %d" _ p->downstream->write->ready);
 
     for ( ;; ) {
+        if (p->downstream_error) {
+            return ngx_drain_chains(p);
+        }
 
         if ((p->upstream_eof || p->upstream_error || p->upstream_done)
             && p->out == NULL && p->in == NULL)
@@ -263,10 +276,22 @@ int ngx_event_proxy_write_to_downstream(
             break;
         }
 
+        busy_len = 0;
+
+        if (!(p->upstream_eof || p->upstream_error || p->upstream_done)) {
+            /* calculate p->busy_len */
+            for (ce = p->busy; ce; ce = ce->next) {
+                busy_len += ngx_hunk_size(ce->hunk);
+            }
+        }
+
+
         if (p->out) {
             out = p->out;
 
-            if (p->busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len) {
+            if (!(p->upstream_eof || p->upstream_error || p->upstream_done)
+                && (busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len))
+            {
                 break;
             }
 
@@ -277,7 +302,7 @@ int ngx_event_proxy_write_to_downstream(
             out = p->in;
 
             if (!(p->upstream_eof || p->upstream_error || p->upstream_done)
-                && (p->busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len))
+                && (busy_len + ngx_hunk_size(out->hunk) > p->max_busy_len))
             {
                 break;
             }
@@ -290,22 +315,14 @@ int ngx_event_proxy_write_to_downstream(
 
         out->next = NULL;
 
-        rc = p->output_filter(p->output_ctx, out->hunk);
 
-        if (rc == NGX_ERROR) {
+        if (p->output_filter(p->output_ctx, out->hunk) == NGX_ERROR) {
             p->downstream_error = 1;
-            return NGX_ERROR;
+            continue;
         }
 
         ngx_chain_update_chains(&p->free, &p->busy, &out);
 
-        /* calculate p->busy_len */
-
-        p->busy_len = 0;
-        for (ce = p->busy; ce; ce = ce->next) {
-            p->busy_len += ngx_hunk_size(ce->hunk);
-        }
-
         /* add the free shadow raw hunks to p->free_raw_hunks */
 
         for (ce = p->free; ce; ce = ce->next) {
@@ -323,13 +340,6 @@ ngx_log_debug(p->log, "RAW %08X" _ h->po
             }
             ce->hunk->shadow = NULL;
         }
-
-#if 0 /* TODO THINK p->read_priority ??? */
-        if (p->upstream->read->ready) {
-            return;
-        }
-#endif
-
     }
 
     ngx_log_debug(p->log, "STATE %d:%d:%d:%X:%X" _
@@ -340,21 +350,15 @@ ngx_log_debug(p->log, "RAW %08X" _ h->po
                   p->out
                  );
 
-    if ((p->upstream_eof || p->upstream_error || p->upstream_done)
-        && p->in == NULL && p->out == NULL)
-    {
-        p->downstream_done = 1;
-    }
-
     return NGX_OK;
 }
 
 
 static int ngx_event_proxy_write_chain_to_temp_file(ngx_event_proxy_t *p)
 {
-    int           rc, size;
+    int           rc, size, hunk_size;
     ngx_hunk_t   *h;
-    ngx_chain_t  *ce, *te, *next, *in, **last, **last_free;
+    ngx_chain_t  *ce, *te, *next, *in, **le, **last_free;
 
     ngx_log_debug(p->log, "write to file");
 
@@ -379,31 +383,41 @@ static int ngx_event_proxy_write_chain_t
 
         size = 0;
         ce = p->in;
+        le = NULL;
+
+ngx_log_debug(p->log, "offset: %d" _ p->temp_offset);
 
         do {
-            if (size + ce->hunk->last - ce->hunk->pos
-                                                    >= p->temp_file_write_size)
+            hunk_size = ce->hunk->last - ce->hunk->pos;
+
+ngx_log_debug(p->log, "hunk size: %d" _ hunk_size);
+
+            if ((size + hunk_size > p->temp_file_write_size)
+                || (p->temp_offset + hunk_size > p->max_temp_file_size))
             {
                 break;
             }
-            size += ce->hunk->last - ce->hunk->pos;
+
+            size += hunk_size;
+            le = &ce->next;
             ce = ce->next;
 
         } while (ce);
 
+ngx_log_debug(p->log, "size: %d" _ size);
+
         if (ce) {
-           in = ce->next;
-           last = &ce->next;
-           ce->next = NULL;
+           in = ce;
+           *le = NULL;
 
         } else {
            in = NULL;
-           last = &p->in;
+           p->last_in = &p->in;
         }
 
     } else {
         in = NULL;
-        last = &p->in;
+        p->last_in = &p->in;
     }
 
     if (ngx_write_chain_to_file(p->temp_file, p->in, p->temp_offset,
@@ -413,7 +427,7 @@ static int ngx_event_proxy_write_chain_t
 
     for (last_free = &p->free_raw_hunks;
          *last_free != NULL;
-         last_free = &(*last)->next)
+         last_free = &(*last_free)->next)
     {
         /* void */
     }
@@ -440,7 +454,6 @@ static int ngx_event_proxy_write_chain_t
     }
 
     p->in = in;
-    p->last_in = last;
 
     return NGX_OK;
 }
@@ -552,3 +565,43 @@ ngx_inline static void ngx_add_after_par
         (*chain) = ce;
     }
 }
+
+
+static int ngx_drain_chains(ngx_event_proxy_t *p)
+{
+    ngx_hunk_t   *h;
+    ngx_chain_t  *ce, *te;
+
+    for ( ;; ) {
+        if (p->busy) {
+            ce = p->busy;
+
+        } else if (p->out) {
+            ce = p->out;
+
+        } else if (p->in) {
+            ce = p->in;
+
+        } else {
+            return NGX_OK;
+        }
+
+        while (ce) {
+            if (ce->hunk->type & NGX_HUNK_LAST_SHADOW) {
+                h = ce->hunk->shadow;
+                /* THINK NEEDED ??? */ h->pos = h->last = h->start;
+                h->shadow = NULL;
+                ngx_alloc_ce_and_set_hunk(te, h, p->pool, NGX_ABORT);
+                ngx_add_after_partially_filled_hunk(&p->free_raw_hunks, te);
+
+                ce->hunk->type &= ~NGX_HUNK_LAST_SHADOW;
+            }
+
+            ce->hunk->shadow = NULL;
+            te = ce->next;
+            ce->next = p->free;
+            p->free = ce;
+            ce = te;
+        }
+    }
+}
--- a/src/event/ngx_event_proxy.h
+++ b/src/event/ngx_event_proxy.h
@@ -47,7 +47,6 @@ struct ngx_event_proxy_s {
     int                hunks;
     ngx_bufs_t         bufs;
 
-    size_t             busy_len;
     size_t             max_busy_len;
 
     off_t              temp_offset;
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -742,6 +742,12 @@ static void ngx_http_proxy_send_response
 
     ep->preread_size = p->header_in->last - p->header_in->pos;
 
+    /*
+     * event_proxy would do p->header_in->last += ep->preread_size
+     * as these bytes were read.
+     */
+    p->header_in->last = p->header_in->pos;
+
     /* STUB */ ep->cachable = 0;
 
     p->event_proxy = ep;
@@ -806,7 +812,7 @@ static void ngx_http_proxy_process_body(
         }
 
         if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) {
-            ngx_http_proxy_close_connection(c);
+            ngx_http_proxy_close_connection(p->upstream.connection);
             p->upstream.connection = NULL;
         }
     }
@@ -819,7 +825,7 @@ static void ngx_http_proxy_process_body(
 
     if (ep->downstream_error) {
         if (!p->cachable && p->upstream.connection) {
-            ngx_http_proxy_close_connection(c);
+            ngx_http_proxy_close_connection(p->upstream.connection);
             p->upstream.connection = NULL;
         }
  
@@ -1052,7 +1058,9 @@ static void ngx_http_proxy_finalize_requ
         p->upstream.connection = NULL;
     }
 
-    if (p->header_sent) {
+    if (p->header_sent
+        && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
+    {
         rc = 0;
     }
 
@@ -1152,7 +1160,12 @@ static void *ngx_http_proxy_create_loc_c
     conf->bufs.num = 10;
     conf->bufs.size = 4096;
     conf->max_busy_len = 8192 + 4096;
+
+
+    /* CHECK in _init conf->max_temp_size >= conf->bufs.size !!! */
     conf->max_temp_file_size = 4096 * 6;
+
+
     conf->temp_file_write_size = 4096 * 2;
 
     ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)),
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -207,13 +207,31 @@ void ngx_http_handler(ngx_http_request_t
     lcx = r->connection->log->data;
     lcx->action = NULL;
 
+    /* STUB */
     r->keepalive = 1;
+    if (r->headers_in.connection) {
+        if (r->headers_in.connection->value.len == 5
+            && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
+                                                                          == 0)
+        {
+            r->keepalive = 0;
+        }
+    }
+
+#if 0
+    /* TEST STUB */ r->keepalive = 0;
+#endif
 
     if (r->headers_in.content_length_n > 0) {
         r->lingering_close = 1;
+
+    } else {
+        r->lingering_close = 0;
     }
 
+#if 0
     /* TEST STUB */ r->lingering_close = 1;
+#endif
 
     r->connection->write->event_handler = ngx_http_phase_event_handler;
 
@@ -258,6 +276,11 @@ static void ngx_http_run_phases(ngx_http
         {
             rc = h[r->phase_handler](r);
 
+            if (rc == NGX_DONE) {
+                return;
+            }
+
+            /* TODO THINK: is it dupliate NGX_DONE ??? */
             if (r->closed) {
                 return;
             }
@@ -435,7 +458,7 @@ int ngx_http_internal_redirect(ngx_http_
 
     ngx_http_handler(r);
 
-    return NGX_OK;
+    return NGX_DONE;
 }
 
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -583,6 +583,7 @@ static void ngx_http_process_request_hea
                 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) {
                     *((ngx_table_elt_t **)
                         ((char *) &r->headers_in + headers_in[i].offset)) = h;
+                    break;
                 }
             }
 
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -100,7 +100,7 @@ int ngx_os_init(ngx_log_t *log)
 
     /*
      * The determination of the sendfile() nbytes bug is complex enough.
-     * There're two sendfile() syscalls: a new 393 has no bug while
+     * There are two sendfile() syscalls: a new 393 has no bug while
      * an old 336 has the bug in some versions and has not in others.
      * Besides libc_r wrapper also emulates the bug in some versions.
      * There's no way to say exactly if a given FreeBSD version has the bug.
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -14,8 +14,8 @@
  * and the first part of the file in one packet but also sends 4K pages
  * in the full packets.
  *
- * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush
- * the pending data that less than MSS so the data is sent with 5 second delay.
+ * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush the pending
+ * data that less than MSS so the data can be sent with 5 second delay.
  * We do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used
  * for non-keepalive HTTP connections.
  */
@@ -23,10 +23,10 @@
 
 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
 {
-    int              rc, eintr;
+    int              rc, eintr, eagain;
     char            *prev;
-    ssize_t          hsize, size;
-    off_t            sent;
+    ssize_t          hsize, fsize, size;
+    off_t            sent, fprev;
     struct iovec    *iov;
     struct sf_hdtr   hdtr;
     ngx_err_t        err;
@@ -41,8 +41,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
     do {
         ce = in;
         file = NULL;
+        fsize = 0;
         hsize = 0;
         eintr = 0;
+        eagain = 0;
 
         ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
                        NGX_CHAIN_ERROR);
@@ -77,11 +79,27 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
             hsize += ce->hunk->last - ce->hunk->pos;
         }
 
-        /* TODO: coalesce the neighbouring file hunks */
+        /* get the file hunk */
 
         if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
             file = ce->hunk;
             ce = ce->next;
+            fsize = (size_t) (file->file_last - file->file_pos);
+            fprev = file->file_last;
+
+            /* coalesce the neighbouring file hunks */
+
+            while (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
+                if (file->file->fd != ce->hunk->file->fd
+                    || fprev != ce->hunk->file_pos)
+                {
+                    break;
+                }
+
+                fsize += (size_t) (ce->hunk->file_last - ce->hunk->file_pos);
+                fprev = ce->hunk->file_last;
+                ce = ce->next;
+            }
         }
 
         /* create the iovec and coalesce the neighbouring chain entries */
@@ -110,6 +128,11 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
             }
         }
 
+        /*
+         * the tail is the rest of the chain that exceeded
+         * a single sendfile() capability
+         */
+
         tail = ce;
 
         if (file) {
@@ -136,8 +159,7 @@ ngx_log_debug(c->log, "NOPUSH");
             }
 
             rc = sendfile(file->file->fd, c->fd, file->file_pos,
-                          (size_t) (file->file_last - file->file_pos) + hsize,
-                          &hdtr, &sent, 0);
+                          fsize + hsize, &hdtr, &sent, 0);
 
             if (rc == -1) {
                 err = ngx_errno;
@@ -146,6 +168,10 @@ ngx_log_debug(c->log, "NOPUSH");
                     eintr = 1;
                 }
 
+                if (err == NGX_EAGAIN) {
+                    eagain = 1;
+                }
+
                 if (err == NGX_EAGAIN || err == NGX_EINTR) {
                     ngx_log_error(NGX_LOG_INFO, c->log, err,
                                   "sendfile() sent only %qd bytes", sent);
@@ -159,8 +185,7 @@ ngx_log_debug(c->log, "NOPUSH");
 
 #if (NGX_DEBUG_WRITE_CHAIN)
             ngx_log_debug(c->log, "sendfile: %d, @%qd %qd:%d" _
-                          rc _ file->file_pos _ sent _
-                          (size_t) (file->file_last - file->file_pos) + hsize);
+                          rc _ file->file_pos _ sent _ fsize + hsize);
 #endif
 
         } else {
@@ -169,6 +194,7 @@ ngx_log_debug(c->log, "NOPUSH");
             if (rc == -1) {
                 err = ngx_errno;
                 if (err == NGX_EAGAIN) {
+                    eagain = 1;
                     ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
 
                 } else if (err == NGX_EINTR) {
@@ -190,14 +216,18 @@ ngx_log_debug(c->log, "NOPUSH");
 
         c->sent += sent;
 
-        for (ce = in; ce && sent > 0; ce = ce->next) {
+        for (ce = in; ce; ce = ce->next) {
+
+            if (ngx_hunk_special(ce->hunk)) {
+                continue;
+            }
 
-            if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
-                size = ce->hunk->last - ce->hunk->pos;
-            } else {
-                size = ce->hunk->file_last - ce->hunk->file_pos;
+            if (sent == 0) {
+                break;
             }
 
+            size = ngx_hunk_size(ce->hunk);
+
             if (sent >= size) {
                 sent -= size;
 
@@ -223,16 +253,20 @@ ngx_log_debug(c->log, "NOPUSH");
             break;
         }
 
-        ngx_destroy_array(&trailer);
-        ngx_destroy_array(&header);
-
         in = ce;
 
-    } while ((tail && tail == ce) || eintr);
+        if (eagain) {
+            c->write->ready = 0;
+            break;
+        }
 
-    if (ce) {
+        /* "tail == in" means that a single sendfile() is complete */
+
+    } while ((tail && tail == in) || eintr);
+
+    if (in) {
         c->write->ready = 0;
     }
 
-    return ce;
+    return in;
 }