[nginx] Introduced the ngx_chain_to_iovec() function.

Valentin Bartenev vbart at nginx.com
Thu Mar 3 15:41:50 UTC 2016


details:   http://hg.nginx.org/nginx/rev/3832b608dc8d
branches:  
changeset: 6421:3832b608dc8d
user:      Valentin Bartenev <vbart at nginx.com>
date:      Thu Mar 03 18:41:05 2016 +0300
description:
Introduced the ngx_chain_to_iovec() function.

It's similar to ngx_output_chain_to_iovec() and uses only preallocated memory.

diffstat:

 src/os/unix/ngx_files.c |  110 ++++++++++++++++++++++++++---------------------
 1 files changed, 60 insertions(+), 50 deletions(-)

diffs (195 lines):

diff -r 3b9fe734a76c -r 3832b608dc8d src/os/unix/ngx_files.c
--- a/src/os/unix/ngx_files.c	Tue Mar 01 15:18:07 2016 +0300
+++ b/src/os/unix/ngx_files.c	Thu Mar 03 18:41:05 2016 +0300
@@ -14,7 +14,8 @@
 static void ngx_thread_read_handler(void *data, ngx_log_t *log);
 #endif
 
-static ssize_t ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size,
+static ngx_chain_t *ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl);
+static ssize_t ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec,
     off_t offset);
 
 
@@ -276,17 +277,13 @@ ngx_open_tempfile(u_char *name, ngx_uint
 }
 
 
-#define NGX_IOVS  8
-
 ssize_t
 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
     ngx_pool_t *pool)
 {
-    u_char        *prev;
-    size_t         size;
     ssize_t        total, n;
-    ngx_array_t    vec;
-    struct iovec  *iov, iovs[NGX_IOVS];
+    ngx_iovec_t    vec;
+    struct iovec   iovs[NGX_IOVS_PREALLOCATE];
 
     /* use pwrite() if there is the only buf in a chain */
 
@@ -298,46 +295,18 @@ ngx_write_chain_to_file(ngx_file_t *file
 
     total = 0;
 
-    vec.elts = iovs;
-    vec.size = sizeof(struct iovec);
-    vec.nalloc = NGX_IOVS;
-    vec.pool = pool;
+    vec.iovs = iovs;
+    vec.nalloc = NGX_IOVS_PREALLOCATE;
 
     do {
-        prev = NULL;
-        iov = NULL;
-        size = 0;
-
-        vec.nelts = 0;
-
         /* create the iovec and coalesce the neighbouring bufs */
-
-        while (cl && vec.nelts < IOV_MAX) {
-            if (prev == cl->buf->pos) {
-                iov->iov_len += cl->buf->last - cl->buf->pos;
-
-            } else {
-                iov = ngx_array_push(&vec);
-                if (iov == NULL) {
-                    return NGX_ERROR;
-                }
-
-                iov->iov_base = (void *) cl->buf->pos;
-                iov->iov_len = cl->buf->last - cl->buf->pos;
-            }
-
-            size += cl->buf->last - cl->buf->pos;
-            prev = cl->buf->last;
-            cl = cl->next;
-        }
+        cl = ngx_chain_to_iovec(&vec, cl);
 
         /* use pwrite() if there is the only iovec buffer */
 
-        if (vec.nelts == 1) {
-            iov = vec.elts;
-
-            n = ngx_write_file(file, (u_char *) iov[0].iov_base,
-                               iov[0].iov_len, offset);
+        if (vec.count == 1) {
+            n = ngx_write_file(file, (u_char *) iovs[0].iov_base,
+                               iovs[0].iov_len, offset);
 
             if (n == NGX_ERROR) {
                 return n;
@@ -346,7 +315,7 @@ ngx_write_chain_to_file(ngx_file_t *file
             return total + n;
         }
 
-        n = ngx_writev_file(file, &vec, size, offset);
+        n = ngx_writev_file(file, &vec, offset);
 
         if (n == NGX_ERROR) {
             return n;
@@ -361,20 +330,61 @@ ngx_write_chain_to_file(ngx_file_t *file
 }
 
 
+static ngx_chain_t *
+ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl)
+{
+    size_t         total, size;
+    u_char        *prev;
+    ngx_uint_t     n;
+    struct iovec  *iov;
+
+    iov = NULL;
+    prev = NULL;
+    total = 0;
+    n = 0;
+
+    for ( /* void */ ; cl; cl = cl->next) {
+        size = cl->buf->last - cl->buf->pos;
+
+        if (prev == cl->buf->pos) {
+            iov->iov_len += size;
+
+        } else {
+            if (n == vec->nalloc) {
+                break;
+            }
+
+            iov = &vec->iovs[n++];
+
+            iov->iov_base = (void *) cl->buf->pos;
+            iov->iov_len = size;
+        }
+
+        prev = cl->buf->pos + size;
+        total += size;
+    }
+
+    vec->count = n;
+    vec->size = total;
+
+    return cl;
+}
+
+
 static ssize_t
-ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size, off_t offset)
+ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, off_t offset)
 {
     ssize_t    n;
     ngx_err_t  err;
 
     ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0,
-                   "writev: %d, %uz, %O", file->fd, size, offset);
+                   "writev: %d, %uz, %O", file->fd, vec->size, offset);
 
 #if (NGX_HAVE_PWRITEV)
 
 eintr:
 
-    n = pwritev(file->fd, vec->elts, vec->nelts, offset);
+    n = pwritev(file->fd, vec->iovs, vec->count, offset);
 
     if (n == -1) {
         err = ngx_errno;
@@ -390,10 +400,10 @@ eintr:
         return NGX_ERROR;
     }
 
-    if ((size_t) n != size) {
+    if ((size_t) n != vec->size) {
         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
                       "pwritev() \"%s\" has written only %z of %uz",
-                      file->name.data, n, size);
+                      file->name.data, n, vec->size);
         return NGX_ERROR;
     }
 
@@ -411,7 +421,7 @@ eintr:
 
 eintr:
 
-    n = writev(file->fd, vec->elts, vec->nelts);
+    n = writev(file->fd, vec->iovs, vec->count);
 
     if (n == -1) {
         err = ngx_errno;
@@ -427,10 +437,10 @@ eintr:
         return NGX_ERROR;
     }
 
-    if ((size_t) n != size) {
+    if ((size_t) n != vec->size) {
         ngx_log_error(NGX_LOG_CRIT, file->log, 0,
                       "writev() \"%s\" has written only %z of %uz",
-                      file->name.data, n, size);
+                      file->name.data, n, vec->size);
         return NGX_ERROR;
     }
 



More information about the nginx-devel mailing list