Annotation of embedaddon/nginx/src/os/unix/ngx_writev_chain.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_event.h>
                     11: 
                     12: 
                     13: #if (IOV_MAX > 64)
                     14: #define NGX_IOVS  64
                     15: #else
                     16: #define NGX_IOVS  IOV_MAX
                     17: #endif
                     18: 
                     19: 
                     20: ngx_chain_t *
                     21: ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
                     22: {
                     23:     u_char        *prev;
                     24:     ssize_t        n, size, sent;
                     25:     off_t          send, prev_send;
                     26:     ngx_uint_t     eintr, complete;
                     27:     ngx_err_t      err;
                     28:     ngx_array_t    vec;
                     29:     ngx_chain_t   *cl;
                     30:     ngx_event_t   *wev;
                     31:     struct iovec  *iov, iovs[NGX_IOVS];
                     32: 
                     33:     wev = c->write;
                     34: 
                     35:     if (!wev->ready) {
                     36:         return in;
                     37:     }
                     38: 
                     39: #if (NGX_HAVE_KQUEUE)
                     40: 
                     41:     if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) {
                     42:         (void) ngx_connection_error(c, wev->kq_errno,
                     43:                                "kevent() reported about an closed connection");
                     44:         wev->error = 1;
                     45:         return NGX_CHAIN_ERROR;
                     46:     }
                     47: 
                     48: #endif
                     49: 
                     50:     /* the maximum limit size is the maximum size_t value - the page size */
                     51: 
                     52:     if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
                     53:         limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
                     54:     }
                     55: 
                     56:     send = 0;
                     57: 
                     58:     vec.elts = iovs;
                     59:     vec.size = sizeof(struct iovec);
                     60:     vec.nalloc = NGX_IOVS;
                     61:     vec.pool = c->pool;
                     62: 
                     63:     for ( ;; ) {
                     64:         prev = NULL;
                     65:         iov = NULL;
                     66:         eintr = 0;
                     67:         complete = 0;
                     68:         prev_send = send;
                     69: 
                     70:         vec.nelts = 0;
                     71: 
                     72:         /* create the iovec and coalesce the neighbouring bufs */
                     73: 
                     74:         for (cl = in; cl && send < limit; cl = cl->next) {
                     75: 
                     76:             if (ngx_buf_special(cl->buf)) {
                     77:                 continue;
                     78:             }
                     79: 
                     80: #if 1
                     81:             if (!ngx_buf_in_memory(cl->buf)) {
                     82:                 ngx_debug_point();
                     83:             }
                     84: #endif
                     85: 
                     86:             size = cl->buf->last - cl->buf->pos;
                     87: 
                     88:             if (send + size > limit) {
                     89:                 size = (ssize_t) (limit - send);
                     90:             }
                     91: 
                     92:             if (prev == cl->buf->pos) {
                     93:                 iov->iov_len += size;
                     94: 
                     95:             } else {
                     96:                 if (vec.nelts >= IOV_MAX) {
                     97:                     break;
                     98:                 }
                     99: 
                    100:                 iov = ngx_array_push(&vec);
                    101:                 if (iov == NULL) {
                    102:                     return NGX_CHAIN_ERROR;
                    103:                 }
                    104: 
                    105:                 iov->iov_base = (void *) cl->buf->pos;
                    106:                 iov->iov_len = size;
                    107:             }
                    108: 
                    109:             prev = cl->buf->pos + size;
                    110:             send += size;
                    111:         }
                    112: 
                    113:         n = writev(c->fd, vec.elts, vec.nelts);
                    114: 
                    115:         if (n == -1) {
                    116:             err = ngx_errno;
                    117: 
                    118:             switch (err) {
                    119:             case NGX_EAGAIN:
                    120:                 break;
                    121: 
                    122:             case NGX_EINTR:
                    123:                 eintr = 1;
                    124:                 break;
                    125: 
                    126:             default:
                    127:                 wev->error = 1;
                    128:                 (void) ngx_connection_error(c, err, "writev() failed");
                    129:                 return NGX_CHAIN_ERROR;
                    130:             }
                    131: 
                    132:             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                    133:                            "writev() not ready");
                    134:         }
                    135: 
                    136:         sent = n > 0 ? n : 0;
                    137: 
                    138:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent);
                    139: 
                    140:         if (send - prev_send == sent) {
                    141:             complete = 1;
                    142:         }
                    143: 
                    144:         c->sent += sent;
                    145: 
                    146:         for (cl = in; cl; cl = cl->next) {
                    147: 
                    148:             if (ngx_buf_special(cl->buf)) {
                    149:                 continue;
                    150:             }
                    151: 
                    152:             if (sent == 0) {
                    153:                 break;
                    154:             }
                    155: 
                    156:             size = cl->buf->last - cl->buf->pos;
                    157: 
                    158:             if (sent >= size) {
                    159:                 sent -= size;
                    160:                 cl->buf->pos = cl->buf->last;
                    161: 
                    162:                 continue;
                    163:             }
                    164: 
                    165:             cl->buf->pos += sent;
                    166: 
                    167:             break;
                    168:         }
                    169: 
                    170:         if (eintr) {
                    171:             continue;
                    172:         }
                    173: 
                    174:         if (!complete) {
                    175:             wev->ready = 0;
                    176:             return cl;
                    177:         }
                    178: 
                    179:         if (send >= limit || cl == NULL) {
                    180:             return cl;
                    181:         }
                    182: 
                    183:         in = cl;
                    184:     }
                    185: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>