Annotation of embedaddon/nginx/src/os/unix/ngx_writev_chain.c, revision 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>