Annotation of embedaddon/nginx/src/os/unix/ngx_readv_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: #define NGX_IOVS  16
                     14: 
                     15: 
                     16: #if (NGX_HAVE_KQUEUE)
                     17: 
                     18: ssize_t
                     19: ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
                     20: {
                     21:     u_char        *prev;
                     22:     ssize_t        n, size;
                     23:     ngx_err_t      err;
                     24:     ngx_array_t    vec;
                     25:     ngx_event_t   *rev;
                     26:     struct iovec  *iov, iovs[NGX_IOVS];
                     27: 
                     28:     rev = c->read;
                     29: 
                     30:     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
                     31:         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
                     32:                        "readv: eof:%d, avail:%d, err:%d",
                     33:                        rev->pending_eof, rev->available, rev->kq_errno);
                     34: 
                     35:         if (rev->available == 0) {
                     36:             if (rev->pending_eof) {
                     37:                 rev->ready = 0;
                     38:                 rev->eof = 1;
                     39: 
                     40:                 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
                     41:                               "kevent() reported about an closed connection");
                     42: 
                     43:                 if (rev->kq_errno) {
                     44:                     rev->error = 1;
                     45:                     ngx_set_socket_errno(rev->kq_errno);
                     46:                     return NGX_ERROR;
                     47:                 }
                     48: 
                     49:                 return 0;
                     50: 
                     51:             } else {
                     52:                 return NGX_AGAIN;
                     53:             }
                     54:         }
                     55:     }
                     56: 
                     57:     prev = NULL;
                     58:     iov = NULL;
                     59:     size = 0;
                     60: 
                     61:     vec.elts = iovs;
                     62:     vec.nelts = 0;
                     63:     vec.size = sizeof(struct iovec);
                     64:     vec.nalloc = NGX_IOVS;
                     65:     vec.pool = c->pool;
                     66: 
                     67:     /* coalesce the neighbouring bufs */
                     68: 
                     69:     while (chain) {
                     70:         if (prev == chain->buf->last) {
                     71:             iov->iov_len += chain->buf->end - chain->buf->last;
                     72: 
                     73:         } else {
                     74:             if (vec.nelts >= IOV_MAX) {
                     75:                 break;
                     76:             }
                     77: 
                     78:             iov = ngx_array_push(&vec);
                     79:             if (iov == NULL) {
                     80:                 return NGX_ERROR;
                     81:             }
                     82: 
                     83:             iov->iov_base = (void *) chain->buf->last;
                     84:             iov->iov_len = chain->buf->end - chain->buf->last;
                     85:         }
                     86: 
                     87:         size += chain->buf->end - chain->buf->last;
                     88:         prev = chain->buf->end;
                     89:         chain = chain->next;
                     90:     }
                     91: 
                     92:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                     93:                    "readv: %d, last:%d", vec.nelts, iov->iov_len);
                     94: 
                     95:     rev = c->read;
                     96: 
                     97:     do {
                     98:         n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
                     99: 
                    100:         if (n >= 0) {
                    101:             if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
                    102:                 rev->available -= n;
                    103: 
                    104:                 /*
                    105:                  * rev->available may be negative here because some additional
                    106:                  * bytes may be received between kevent() and recv()
                    107:                  */
                    108: 
                    109:                 if (rev->available <= 0) {
                    110:                     if (!rev->pending_eof) {
                    111:                         rev->ready = 0;
                    112:                     }
                    113: 
                    114:                     if (rev->available < 0) {
                    115:                         rev->available = 0;
                    116:                     }
                    117:                 }
                    118: 
                    119:                 if (n == 0) {
                    120: 
                    121:                     /*
                    122:                      * on FreeBSD recv() may return 0 on closed socket
                    123:                      * even if kqueue reported about available data
                    124:                      */
                    125: 
                    126: #if 0
                    127:                     ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                    128:                                   "readv() returned 0 while kevent() reported "
                    129:                                   "%d available bytes", rev->available);
                    130: #endif
                    131: 
                    132:                     rev->eof = 1;
                    133:                     rev->available = 0;
                    134:                 }
                    135: 
                    136:                 return n;
                    137:             }
                    138: 
                    139:             if (n < size) {
                    140:                 rev->ready = 0;
                    141:             }
                    142: 
                    143:             if (n == 0) {
                    144:                 rev->eof = 1;
                    145:             }
                    146: 
                    147:             return n;
                    148:         }
                    149: 
                    150:         err = ngx_socket_errno;
                    151: 
                    152:         if (err == NGX_EAGAIN || err == NGX_EINTR) {
                    153:             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                    154:                            "readv() not ready");
                    155:             n = NGX_AGAIN;
                    156: 
                    157:         } else {
                    158:             n = ngx_connection_error(c, err, "readv() failed");
                    159:             break;
                    160:         }
                    161: 
                    162:     } while (err == NGX_EINTR);
                    163: 
                    164:     rev->ready = 0;
                    165: 
                    166:     if (n == NGX_ERROR) {
                    167:         c->read->error = 1;
                    168:     }
                    169: 
                    170:     return n;
                    171: }
                    172: 
                    173: #else /* ! NGX_HAVE_KQUEUE */
                    174: 
                    175: ssize_t
                    176: ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
                    177: {
                    178:     u_char        *prev;
                    179:     ssize_t        n, size;
                    180:     ngx_err_t      err;
                    181:     ngx_array_t    vec;
                    182:     ngx_event_t   *rev;
                    183:     struct iovec  *iov, iovs[NGX_IOVS];
                    184: 
                    185:     prev = NULL;
                    186:     iov = NULL;
                    187:     size = 0;
                    188: 
                    189:     vec.elts = iovs;
                    190:     vec.nelts = 0;
                    191:     vec.size = sizeof(struct iovec);
                    192:     vec.nalloc = NGX_IOVS;
                    193:     vec.pool = c->pool;
                    194: 
                    195:     /* coalesce the neighbouring bufs */
                    196: 
                    197:     while (chain) {
                    198:         if (prev == chain->buf->last) {
                    199:             iov->iov_len += chain->buf->end - chain->buf->last;
                    200: 
                    201:         } else {
                    202:             if (vec.nelts >= IOV_MAX) {
                    203:                 break;
                    204:             }
                    205: 
                    206:             iov = ngx_array_push(&vec);
                    207:             if (iov == NULL) {
                    208:                 return NGX_ERROR;
                    209:             }
                    210: 
                    211:             iov->iov_base = (void *) chain->buf->last;
                    212:             iov->iov_len = chain->buf->end - chain->buf->last;
                    213:         }
                    214: 
                    215:         size += chain->buf->end - chain->buf->last;
                    216:         prev = chain->buf->end;
                    217:         chain = chain->next;
                    218:     }
                    219: 
                    220:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    221:                    "readv: %d:%d", vec.nelts, iov->iov_len);
                    222: 
                    223:     rev = c->read;
                    224: 
                    225:     do {
                    226:         n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
                    227: 
                    228:         if (n == 0) {
                    229:             rev->ready = 0;
                    230:             rev->eof = 1;
                    231: 
                    232:             return n;
                    233: 
                    234:         } else if (n > 0) {
                    235: 
                    236:             if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) {
                    237:                 rev->ready = 0;
                    238:             }
                    239: 
                    240:             return n;
                    241:         }
                    242: 
                    243:         err = ngx_socket_errno;
                    244: 
                    245:         if (err == NGX_EAGAIN || err == NGX_EINTR) {
                    246:             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                    247:                            "readv() not ready");
                    248:             n = NGX_AGAIN;
                    249: 
                    250:         } else {
                    251:             n = ngx_connection_error(c, err, "readv() failed");
                    252:             break;
                    253:         }
                    254: 
                    255:     } while (err == NGX_EINTR);
                    256: 
                    257:     rev->ready = 0;
                    258: 
                    259:     if (n == NGX_ERROR) {
                    260:         c->read->error = 1;
                    261:     }
                    262: 
                    263:     return n;
                    264: }
                    265: 
                    266: #endif /* NGX_HAVE_KQUEUE */

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