Annotation of embedaddon/nginx/src/os/unix/ngx_readv_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: #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>