diff src/os/unix/ngx_writev_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 6bdf858bff8c
children 744ccb59062d
line wrap: on
line diff
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -4,15 +4,15 @@
 #include <ngx_event.h>
 
 
-ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in)
+ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
 {
     u_char          *prev;
     ssize_t          n, size;
-    off_t            sent;
+    off_t            send, sprev, sent;
     struct iovec    *iov;
-    ngx_int_t        eintr;
+    ngx_uint_t       eintr, complete;
     ngx_err_t        err;
-    ngx_array_t      io;
+    ngx_array_t      vec;
     ngx_chain_t     *cl;
     ngx_event_t     *wev;
 
@@ -34,30 +34,45 @@ ngx_chain_t *ngx_writev_chain(ngx_connec
 
 #endif
 
-    ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
+    ngx_init_array(vec, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR);
 
-    do {
+    send = 0;
+    complete = 0;
+
+    for ( ;; ) {
         prev = NULL;
         iov = NULL;
         eintr = 0;
+        sprev = send;
 
         /* create the iovec and coalesce the neighbouring bufs */
 
-        for (cl = in; cl; cl = cl->next) {
+        for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next)
+        {
+            if (ngx_buf_special(cl->buf)) {
+                continue;
+            }
+
+            size = cl->buf->last - cl->buf->pos;
+
+            if (send + size > limit) {
+                size = limit - send;
+            }
 
             if (prev == cl->buf->pos) {
-                iov->iov_len += cl->buf->last - cl->buf->pos;
-                prev = cl->buf->last;
+                iov->iov_len += size;
 
             } else {
-                ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR);
+                ngx_test_null(iov, ngx_push_array(&vec), NGX_CHAIN_ERROR);
                 iov->iov_base = (void *) cl->buf->pos;
-                iov->iov_len = cl->buf->last - cl->buf->pos;
-                prev = cl->buf->last;
+                iov->iov_len = size;
             }
+
+            prev = cl->buf->pos + size;
+            send += size;
         }
 
-        n = writev(c->fd, io.elts, io.nelts);
+        n = writev(c->fd, vec.elts, vec.nelts);
 
         if (n == -1) {
             err = ngx_errno;
@@ -82,34 +97,48 @@ ngx_chain_t *ngx_writev_chain(ngx_connec
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                        "writev: " OFF_T_FMT, sent);
 
+        if (send - sprev == sent) {
+            complete = 1;
+        }
+
         c->sent += sent;
 
         for (cl = in; cl && sent > 0; cl = cl->next) {
+            if (ngx_buf_special(cl->buf)) {
+                continue;
+            }
+
+            if (sent == 0) {
+                break;
+            }
 
             size = cl->buf->last - cl->buf->pos;
 
             if (sent >= size) {
                 sent -= size;
-
-                if (ngx_buf_in_memory(cl->buf)) {
-                    cl->buf->pos = cl->buf->last;
-                }
+                cl->buf->pos = cl->buf->last;
 
                 continue;
             }
 
-            if (ngx_buf_in_memory(cl->buf)) {
-                cl->buf->pos += sent;
-            }
+            cl->buf->pos += sent;
 
             break;
         }
 
-    } while (eintr);
+        if (eintr) {
+            continue;
+        }
 
-    if (cl) {
-        wev->ready = 0;
+        if (!complete) {
+            wev->ready = 0;
+            return cl;
+        }
+
+        if (send >= limit || cl == NULL) {
+            return cl;
+        }
+
+        in = cl;
     }
-
-    return cl;
 }