diff src/os/unix/ngx_solaris_sendfilev_chain.c @ 362:7650aea1816f

nginx-0.0.7-2004-06-21-19:59:32 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 21 Jun 2004 15:59:32 +0000
parents e366ba5db8f8
children 5e73d0ea4dab
line wrap: on
line diff
--- a/src/os/unix/ngx_solaris_sendfilev_chain.c
+++ b/src/os/unix/ngx_solaris_sendfilev_chain.c
@@ -9,14 +9,15 @@
 #include <ngx_event.h>
 
 
-ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in)
+ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in,
+                                         off_t limit)
 {
     int             fd;
     u_char         *prev;
-    off_t           fprev;
-    size_t          sent, size;
+    off_t           fprev, sprev, send, aligned;
+    size_t          size, sent;
     ssize_t         n;
-    ngx_int_t       eintr;
+    ngx_int_t       eintr, complete;
     ngx_err_t       err;
     sendfilevec_t  *sfv;
     ngx_array_t     vec;
@@ -29,20 +30,25 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
         return in;
     }
 
-    do {
+    send = 0;
+    complete = 0;
+
+    for ( ;; ) {
         fd = SFV_FD_SELF;
         prev = NULL;
         fprev = 0;
         sfv = NULL;
         eintr = 0;
         sent = 0;
+        sprev = send;
 
         ngx_init_array(vec, c->pool, 10, sizeof(sendfilevec_t),
                        NGX_CHAIN_ERROR);
 
         /* create the sendfilevec and coalesce the neighbouring bufs */
 
-        for (cl = in; cl && vec.nelts < IOV_MAX; cl = cl->next) {
+        for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next)
+        {
             if (ngx_buf_special(cl->buf)) {
                 continue;
             }
@@ -50,24 +56,44 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
             if (ngx_buf_in_memory_only(cl->buf)) {
                 fd = SFV_FD_SELF;
 
+                size = cl->buf->last - cl->buf->pos;
+
+                if (send + size > limit) {
+                    size = limit - send;
+                }
+
                 if (prev == cl->buf->pos) {
-                    sfv->sfv_len += cl->buf->last - cl->buf->pos;
+                    sfv->sfv_len += size;
 
                 } else {
                     ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
                     sfv->sfv_fd = SFV_FD_SELF;
                     sfv->sfv_flag = 0;
                     sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos;
-                    sfv->sfv_len = cl->buf->last - cl->buf->pos;
+                    sfv->sfv_len = size;
                 }
 
-                prev = cl->buf->last;
+                prev = cl->buf->pos + size;
+                send += size;
 
             } else {
                 prev = NULL;
 
+                size = (size_t) (cl->buf->file_last - cl->buf->file_pos);
+
+                if (send + size > limit) {
+                    size = limit - send;
+
+                    aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
+                                                      & ~(ngx_pagesize - 1);
+
+                    if (aligned <= cl->buf->file_last) {
+                        size = aligned - cl->buf->file_pos;
+                    }
+                }
+
                 if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
-                    sfv->sfv_len += cl->buf->file_last - cl->buf->file_pos;
+                    sfv->sfv_len += size;
 
                 } else {
                     ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR);
@@ -75,20 +101,14 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
                     sfv->sfv_fd = fd;
                     sfv->sfv_flag = 0;
                     sfv->sfv_off = cl->buf->file_pos;
-                    sfv->sfv_len = cl->buf->file_last - cl->buf->file_pos;
+                    sfv->sfv_len = size;
                 }
 
-                fprev = cl->buf->file_last;
+                fprev = cl->buf->file_pos + size;
+                send += size;
             }
         }
 
-        /*
-         * the tail is the rest of the chain that exceedes a single
-         * sendfilev() capability, IOV_MAX in Solaris is limited by 16
-         */
-
-        tail = cl;
-
         n = sendfilev(c->fd, vec.elts, vec.nelts, &sent);
 
         if (n == -1) {
@@ -113,6 +133,10 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "sendfilev: %d " SIZE_T_FMT, n, sent);
 
+        if (send - sprev == sent) {
+            complete = 1;
+        }
+
         c->sent += sent;
 
         for (cl = in; cl; cl = cl->next) {
@@ -152,15 +176,19 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
             break;
         }
 
-        in = cl;
-
-        /* "tail == in" means that a single sendfilev() is complete */
-
-    } while ((tail && tail == in) || eintr);
+        if (eintr) {
+            continue;
+        }
 
-    if (in) {
-        wev->ready = 0;
+        if (!complete) {
+            wev->ready = 0;
+            return cl;
+        }
+
+        if (send >= limit || cl == NULL) {
+            return cl;
+        }
+
+        in = cl;
     }
-
-    return in;
 }