changeset 142:cb77c084acdb

nginx-0.0.1-2003-10-09-11:00:45 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 09 Oct 2003 07:00:45 +0000
parents 656d468f4ead
children 5526213be452
files src/core/ngx_hunk.h src/http/modules/ngx_http_not_modified_filter.c src/http/modules/ngx_http_static_handler.c src/http/ngx_http.h src/http/ngx_http_event.c src/http/ngx_http_output_filter.c src/http/ngx_http_request.c src/http/ngx_http_special_response.c src/http/ngx_http_write_filter.c src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_freebsd_sendfile_chain.c
diffstat 10 files changed, 174 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_hunk.h
+++ b/src/core/ngx_hunk.h
@@ -75,6 +75,14 @@ typedef struct {
 
 #define ngx_hunk_in_memory_only(h)                                           \
          ((h->type & (NGX_HUNK_IN_MEMORY|NGX_HUNK_FILE)) == NGX_HUNK_IN_MEMORY)
+/*
+    ((h->type & (NGX_HUNK_TEMP|NGX_HUNK_MEMORY|NGX_HUNK_MMAP|NGX_HUNK_FILE)) \
+                  == (h->type & (NGX_HUNK_TEMP|NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))
+
+*/
+
+#define ngx_hunk_special(h)                                                  \
+        (h->type == (h->type & (NGX_HUNK_FLUSH|NGX_HUNK_LAST)))
 
 
 ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
--- a/src/http/modules/ngx_http_not_modified_filter.c
+++ b/src/http/modules/ngx_http_not_modified_filter.c
@@ -39,7 +39,7 @@ static int ngx_http_not_modified_header_
 
     if (r->headers_out.status != NGX_HTTP_OK
         || r->headers_in.if_modified_since == NULL
-        || r->headers_out.last_modified_time == NULL)
+        || r->headers_out.last_modified_time == -1)
     {
         return next_header_filter(r);
     }
@@ -50,7 +50,7 @@ static int ngx_http_not_modified_header_
     ngx_log_debug(r->connection->log, "%d %d" _
                   ims _ r->headers_out.last_modified_time);
 
-    /* I think that the date equality is correcter */
+    /* I think that the equality of the dates is correcter */
 
     if (ims != NGX_ERROR && ims == r->headers_out.last_modified_time) {
         r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -118,6 +118,7 @@ int ngx_http_static_handler(ngx_http_req
     }
 
     /* we need to allocate all before the header would be sent */
+
     ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
 
@@ -132,18 +133,28 @@ int ngx_http_static_handler(ngx_http_req
     }
 
     if (r->header_only) {
+        ngx_http_finalize_request(r, rc);
+
+#if 0
         if (rc == NGX_AGAIN) {
             ngx_http_set_write_handler(r);
 
         } else {
             ngx_http_finalize_request(r, 0);
         }
+#endif
 
         return NGX_OK;
     }
 
 
-    h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
+#if 0
+    h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
+#else
+    h->type = NGX_HUNK_FILE;
+#endif
+
+
     h->file_pos = 0;
     h->file_last = ngx_file_size(r->file.info);
 
@@ -152,6 +163,9 @@ int ngx_http_static_handler(ngx_http_req
 
     rc = ngx_http_output_filter(r, h);
 
+    ngx_http_finalize_request(r, rc);
+
+#if 0
     if (r->main == NULL) {
         if (rc == NGX_AGAIN) {
             ngx_http_set_write_handler(r);
@@ -160,6 +174,7 @@ int ngx_http_static_handler(ngx_http_req
             ngx_http_finalize_request(r, 0);
         }
     }
+#endif
 
     return NGX_OK;
 }
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -54,6 +54,7 @@ void ngx_http_finalize_request(ngx_http_
 void ngx_http_set_write_handler(ngx_http_request_t *r);
 
 
+int ngx_http_send_last(ngx_http_request_t *r);
 void ngx_http_close_request(ngx_http_request_t *r, int error);
 void ngx_http_close_connection(ngx_connection_t *c);
 
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -72,10 +72,11 @@ ngx_module_t  ngx_http_output_filter_mod
 #define ngx_next_filter  (*ngx_http_top_body_filter)
 
 #define need_to_copy(r, hunk)                                             \
-            (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)                \
-               && (hunk->type & NGX_HUNK_IN_MEMORY) == 0)                 \
-             || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)                  \
-                  && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))))
+            (!ngx_hunk_special(hunk)                                      \
+             && (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)            \
+                   && (hunk->type & NGX_HUNK_IN_MEMORY) == 0)             \
+                 || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP)              \
+                  && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))))
 
 
 
@@ -201,6 +202,8 @@ int ngx_http_output_filter(ngx_http_requ
             *ctx->last_out = ce;
             ctx->last_out = &ce->next;
             ctx->hunk = NULL;
+
+            break;
         }
 
         if (ctx->out == NULL && last != NGX_NONE) {
rename from src/http/ngx_http_event.c
rename to src/http/ngx_http_request.c
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_request.c
@@ -785,6 +785,10 @@ void ngx_http_finalize_request(ngx_http_
     int           rc;
     ngx_event_t  *rev, *wev;
 
+    if (r->main) {
+        return;
+    }
+
     rc = error;
 
     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -813,9 +817,25 @@ void ngx_http_finalize_request(ngx_http_
             return;
         }
 
+#if 1
+        return;
+#endif
+
     } else if (rc == NGX_ERROR) {
         r->keepalive = 0;
         r->lingering_close = 0;
+
+    } else {
+        if (ngx_http_send_last(r) == NGX_ERROR) {
+            ngx_http_close_request(r, 0);
+            ngx_http_close_connection(r->connection);
+            return;
+        }
+
+        if (rc == NGX_AGAIN) {
+            ngx_http_set_write_handler(r);
+            return;
+        }
     }
 
     rev = r->connection->read;
@@ -840,6 +860,8 @@ void ngx_http_finalize_request(ngx_http_
         ngx_http_close_request(r, 0);
         ngx_http_close_connection(r->connection);
     }
+
+    return;
 }
 
 
@@ -887,6 +909,8 @@ void ngx_http_set_write_handler(ngx_http
         ngx_http_close_request(r, 0);
         ngx_http_close_connection(r->connection);
     }
+
+    return;
 }
 
 
@@ -951,6 +975,8 @@ static void ngx_http_writer(ngx_event_t 
         ngx_http_close_request(r, 0);
         ngx_http_close_connection(r->connection);
     }
+
+    return;
 }
 
 
@@ -1046,6 +1072,8 @@ static void ngx_http_read_discarded_body
         ngx_http_close_request(r, rc);
         ngx_http_close_connection(c);
     }
+
+    return;
 }
 
 
@@ -1385,6 +1413,17 @@ static void ngx_http_empty_handler(ngx_e
 }
 
 
+int ngx_http_send_last(ngx_http_request_t *r)
+{
+    ngx_hunk_t  *h;
+
+    ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
+    h->type = NGX_HUNK_LAST;
+
+    return ngx_http_output_filter(r, h);
+}
+
+
 void ngx_http_close_request(ngx_http_request_t *r, int error)
 {
     ngx_http_log_ctx_t  *ctx;
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -199,15 +199,19 @@ int ngx_http_special_response_handler(ng
     }
 
     rc = ngx_http_send_header(r);
+
     if (rc == NGX_ERROR) {
         return NGX_ERROR;
     }
 
     if (r->header_only) {
+        ngx_http_finalize_request(r, rc);
+#if 0
         if (rc == NGX_AGAIN) {
             ngx_http_set_write_handler(r);
             return NGX_AGAIN;
         }
+#endif
 
         return NGX_OK;
     }
@@ -248,12 +252,16 @@ int ngx_http_special_response_handler(ng
 
     rc = ngx_http_output_filter(r, h);
 
+    ngx_http_finalize_request(r, rc);
+
+#if 0
     if (r->main == NULL) {
         if (rc == NGX_AGAIN) {
             ngx_http_set_write_handler(r);
             return NGX_AGAIN;
         }
     }
+#endif
 
     return NGX_OK;
 
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -130,14 +130,16 @@ int ngx_http_write_filter(ngx_http_reque
                   last _ flush _ size);
 #endif
 
-    /* avoid the output if there is no last hunk, no flush point and
-       size of the hunks is smaller then "buffer_output" */
+    /*
+     * avoid the output if there is no last hunk, no flush point and
+     * size of the hunks is smaller then "buffer_output"
+     */
 
     if (!last && flush == 0 && size < conf->buffer_output) {
         return NGX_OK;
     }
 
-    if (r->connection->write->delayed) {
+    if (!r->connection->write->ready || r->connection->write->delayed) {
         return NGX_AGAIN;
     }
 
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -93,26 +93,30 @@ int ngx_os_init(ngx_log_t *log)
 
 #if (HAVE_FREEBSD_SENDFILE)
 
-    /* The determination of the sendfile() nbytes bug is complex enough.
-       There're 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 bug.
-       Here is the algorithm that works at least for RELEASEs
-       and for syscalls only (not libc_r wrapper). */
-
-    /* detect the new sendfile() version available at the compile time
-       to allow an old binary to run correctly on an updated FreeBSD system. */
+    /*
+     * The determination of the sendfile() nbytes bug is complex enough.
+     * There're 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.
+     * Here is the algorithm that works at least for RELEASEs
+     * and for syscalls only (not libc_r wrapper).
+     *
+     * We detect the new sendfile() version available at the compile time
+     * to allow an old binary to run correctly on an updated FreeBSD system.
+     */
 
 #if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \
     || __FreeBSD_version == 460002 || __FreeBSD_version >= 500039
 
     /* a new syscall without the bug */
+
     ngx_freebsd_sendfile_nbytes_bug = 0;
 
 #else
 
     /* an old syscall that can have the bug */
+
     ngx_freebsd_sendfile_nbytes_bug = 1;
 
 #endif
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -1,23 +1,24 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
+#include <ngx_event.h>
 #include <ngx_freebsd_init.h>
 
 
 /*
-   sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460 and 1176
-   or in 6 packets: 5x1460 and 892.  Besides although sendfile() allows
-   to pass the header and the trailer it never sends the header or the trailer
-   with the part of the file in one packet.  So we use TCP_NOPUSH (similar
-   to Linux's TCP_CORK) to postpone the sending - it not only sends the header
-   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 not flush
-   the pending data that less than MSS and the data sent with 5 second delay.
-   So we use TCP_NOPUSH on FreeBSD prior to 4.5 only if the connection
-   is not needed not keepalive.
-*/
+ * sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460 and 1176
+ * or in 6 packets: 5x1460 and 892.  Besides although sendfile() allows
+ * to pass the header and the trailer it never sends the header or the trailer
+ * with the part of the file in one packet.  So we use TCP_NOPUSH (similar
+ * to Linux's TCP_CORK) to postpone the sending - it not only sends the header
+ * 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 not flush
+ * the pending data that less than MSS and the data sent with 5 second delay.
+ * So we use TCP_NOPUSH on FreeBSD prior to 4.5 only if the connection
+ * is not needed to be keepalive.
+ */
 
 
 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
@@ -47,12 +48,23 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
                        NGX_CHAIN_ERROR);
 
         /* create the header iovec */
-        if (ngx_hunk_in_memory_only(ce->hunk)) {
+
+#if 0
+        if (ngx_hunk_in_memory_only(ce->hunk) || ngx_hunk_special(ce->hunk)) {
+#endif
             prev = NULL;
             iov = NULL;
 
             /* create the iovec and coalesce the neighbouring chain entries */
-            while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
+
+            for ( /* void */; ce; ce = ce->next) {
+                if (ngx_hunk_special(ce->hunk)) {
+                    continue;
+                }
+
+                if (!ngx_hunk_in_memory_only(ce->hunk)) {
+                    break;
+                }
 
                 if (prev == ce->hunk->pos) {
                     iov->iov_len += ce->hunk->last - ce->hunk->pos;
@@ -67,24 +79,39 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
                 }
 
                 hsize += ce->hunk->last - ce->hunk->pos;
-
-                ce = ce->next;
             }
+#if 0
         }
+#endif
 
         /* TODO: coalesce the neighbouring file hunks */
+
         if (ce && (ce->hunk->type & NGX_HUNK_FILE)) {
             file = ce->hunk;
             ce = ce->next;
         }
 
         /* create the trailer iovec */
-        if (ce && ngx_hunk_in_memory_only(ce->hunk)) {
+
+#if 0
+        if (ce
+            && (ngx_hunk_in_memory_only(ce->hunk)
+                || ngx_hunk_special(ce->hunk)))
+        {
+#endif
             prev = NULL;
             iov = NULL;
 
             /* create the iovec and coalesce the neighbouring chain entries */
-            while (ce && ngx_hunk_in_memory_only(ce->hunk)) {
+
+            for ( /* void */; ce; ce = ce->next) {
+                if (ngx_hunk_special(ce->hunk)) {
+                    continue;
+                }
+
+                if (!ngx_hunk_in_memory_only(ce->hunk)) {
+                    break;
+                }
 
                 if (prev == ce->hunk->pos) {
                     iov->iov_len += ce->hunk->last - ce->hunk->pos;
@@ -97,10 +124,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
                     iov->iov_len = ce->hunk->last - ce->hunk->pos;
                     prev = ce->hunk->last;
                 }
-
-                ce = ce->next;
             }
+#if 0
         }
+#endif
 
         tail = ce;
 
@@ -155,28 +182,36 @@ ngx_log_debug(c->log, "NOPUSH");
 #endif
 
         } else {
-            rc = writev(c->fd, (struct iovec *) header.elts, header.nelts);
+            if (hsize) {
+                rc = writev(c->fd, (struct iovec *) header.elts, header.nelts);
 
-            if (rc == -1) {
-                err = ngx_errno;
-                if (err == NGX_EAGAIN) {
-                    ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
+                if (rc == -1) {
+                    err = ngx_errno;
+                    if (err == NGX_EAGAIN) {
+                        ngx_log_error(NGX_LOG_INFO, c->log, err,
+                                      "writev() EAGAIN");
 
-                } else if (err == NGX_EINTR) {
-                    eintr = 1;
-                    ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
+                    } else if (err == NGX_EINTR) {
+                        eintr = 1;
+                        ngx_log_error(NGX_LOG_INFO, c->log, err,
+                                      "writev() EINTR");
 
-                } else {
-                    ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
-                    return NGX_CHAIN_ERROR;
+                    } else {
+                        ngx_log_error(NGX_LOG_CRIT, c->log, err,
+                                      "writev() failed");
+                        return NGX_CHAIN_ERROR;
+                    }
                 }
-            }
 
-            sent = rc > 0 ? rc : 0;
+                sent = rc > 0 ? rc : 0;
 
 #if (NGX_DEBUG_WRITE_CHAIN)
-            ngx_log_debug(c->log, "writev: %qd" _ sent);
+                ngx_log_debug(c->log, "writev: %qd" _ sent);
 #endif
+
+            } else {
+                sent = 0;
+            }
         }
 
         c->sent += sent;
@@ -221,5 +256,9 @@ ngx_log_debug(c->log, "NOPUSH");
 
     } while ((tail && tail == ce) || eintr);
 
+    if (ce) {
+        c->write->ready = 0;
+    }
+
     return ce;
 }