diff src/event/ngx_event_write.c @ 0:4eff17414a43

nginx-0.0.1-2002-08-06-20:39:45 import The first code that uses "ngx_" prefix, the previous one used "gx_" prefix. At that point the code is not yet usable. The first draft ideas are dated back to 23.10.2001.
author Igor Sysoev <igor@sysoev.ru>
date Tue, 06 Aug 2002 16:39:45 +0000
parents
children d220029ac7f3
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/event/ngx_event_write.c
@@ -0,0 +1,136 @@
+
+#include <ngx_config.h>
+#include <ngx_types.h>
+#include <ngx_alloc.h>
+#include <ngx_array.h>
+#include <ngx_hunk.h>
+#include <ngx_connection.h>
+#include <ngx_sendv.h>
+#include <ngx_sendfile.h>
+#include <ngx_event_write.h>
+
+
+ngx_chain_t *ngx_event_writer(ngx_connection_t *cn, ngx_chain_t *in,
+                              off_t flush)
+{
+    int           rc;
+    char         *last;
+    off_t         sent;
+    ngx_iovec_t  *iov;
+    ngx_array_t  *header, *trailer;
+    ngx_hunk_t   *file;
+    ngx_chain_t  *ch;
+
+    ch = in;
+    file = NULL;
+
+    ngx_test_null(header, ngx_create_array(cn->pool, 10, sizeof(ngx_iovec_t)),
+                  (ngx_chain_t *) -1);
+
+    ngx_test_null(trailer, ngx_create_array(cn->pool, 10, sizeof(ngx_iovec_t)),
+                  (ngx_chain_t *) -1);
+
+    do {
+        header->nelts = 0;
+        trailer->nelts = 0;
+
+        if (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)) {
+            last = NULL;
+            iov = NULL;
+
+            while (ch
+                   && (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)))
+            {
+                if (ch->hunk->type & NGX_HUNK_FLUSH)
+                    continue;
+
+                if (last == ch->hunk->pos.p) {
+                    iov->ngx_iov_len += ch->hunk->last.p - ch->hunk->pos.p;
+
+                } else {
+                    ngx_test_null(iov, ngx_push_array(header),
+                                  (ngx_chain_t *) -1);
+                    iov->ngx_iov_base = ch->hunk->pos.p;
+                    iov->ngx_iov_len = ch->hunk->last.p - ch->hunk->pos.p;
+                    last = ch->hunk->last.p;
+                }
+
+                ch = ch->next;
+            }
+        }
+
+        if (ch && (ch->hunk->type & NGX_HUNK_FILE)) {
+            file = ch->hunk;
+            ch = ch->next;
+        }
+
+#if (HAVE_MAX_SENDFILE_IOVEC)
+        if (file && header->nelts > HAVE_MAX_SENDFILE_IOVEC) {
+            rc = ngx_sendv(cn->fd, (ngx_iovec_t *) header->elts, header->nelts,
+                           &sent);
+        } else {
+#endif
+            if (ch && ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)) {
+                last = NULL;
+                iov = NULL;
+
+                while (ch
+                   && (ch->hunk->type & (NGX_HUNK_IN_MEMORY | NGX_HUNK_FLUSH)))
+                {
+                    if (ch->hunk->type & NGX_HUNK_FLUSH)
+                        continue;
+
+                    if (last == ch->hunk->pos.p) {
+                        iov->ngx_iov_len += ch->hunk->last.p - ch->hunk->pos.p;
+
+                    } else {
+                        ngx_test_null(iov, ngx_push_array(trailer),
+                                      (ngx_chain_t *) -1);
+                        iov->ngx_iov_base = ch->hunk->pos.p;
+                        iov->ngx_iov_len = ch->hunk->last.p - ch->hunk->pos.p;
+                        last = ch->hunk->last.p;
+                    }
+
+                    ch = ch->next;
+                }
+            }
+
+            if (file) {
+                rc = ngx_sendfile(cn->fd,
+                                  (ngx_iovec_t *) header->elts, header->nelts,
+                                  file->fd, file->pos.f,
+                                          (size_t) (file->last.f - file->pos.f),
+                                  (ngx_iovec_t *) trailer->elts, trailer->nelts,
+                                  &sent, cn->log);
+            } else {
+                rc = ngx_sendv(cn->fd, (ngx_iovec_t *) header->elts,
+                               header->nelts, (size_t *) &sent);
+            }
+#if (HAVE_MAX_SENDFILE_IOVEC)
+        }
+#endif
+        /* save sent for logging */
+
+        if (rc == -1)
+            return (ngx_chain_t *) -1;
+
+        flush -= sent;
+
+        for (ch = in; ch && !(ch->hunk->type & NGX_HUNK_LAST); ch = ch->next) {
+            if (sent >= ch->hunk->last.f - ch->hunk->pos.f) {
+                sent -= ch->hunk->last.f - ch->hunk->pos.f;
+                ch->hunk->last.f = ch->hunk->pos.f;
+                    continue;
+            }
+
+            ch->hunk->pos.f += sent;
+            break;
+        }
+
+    } while (flush > 0);
+
+    ngx_destroy_array(trailer);
+    ngx_destroy_array(header);
+
+    return ch;
+}