Mercurial > hg > nginx
diff src/os/unix/ngx_writev_chain.c @ 362:7650aea1816f
nginx-0.0.7-2004-06-21-19:59:32 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 21 Jun 2004 15:59:32 +0000 |
parents | 6bdf858bff8c |
children | 744ccb59062d |
line wrap: on
line diff
--- a/src/os/unix/ngx_writev_chain.c +++ b/src/os/unix/ngx_writev_chain.c @@ -4,15 +4,15 @@ #include <ngx_event.h> -ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in) +ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { u_char *prev; ssize_t n, size; - off_t sent; + off_t send, sprev, sent; struct iovec *iov; - ngx_int_t eintr; + ngx_uint_t eintr, complete; ngx_err_t err; - ngx_array_t io; + ngx_array_t vec; ngx_chain_t *cl; ngx_event_t *wev; @@ -34,30 +34,45 @@ ngx_chain_t *ngx_writev_chain(ngx_connec #endif - ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); + ngx_init_array(vec, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); - do { + send = 0; + complete = 0; + + for ( ;; ) { prev = NULL; iov = NULL; eintr = 0; + sprev = send; /* create the iovec and coalesce the neighbouring bufs */ - for (cl = in; cl; cl = cl->next) { + for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next) + { + if (ngx_buf_special(cl->buf)) { + continue; + } + + size = cl->buf->last - cl->buf->pos; + + if (send + size > limit) { + size = limit - send; + } if (prev == cl->buf->pos) { - iov->iov_len += cl->buf->last - cl->buf->pos; - prev = cl->buf->last; + iov->iov_len += size; } else { - ngx_test_null(iov, ngx_push_array(&io), NGX_CHAIN_ERROR); + ngx_test_null(iov, ngx_push_array(&vec), NGX_CHAIN_ERROR); iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = cl->buf->last - cl->buf->pos; - prev = cl->buf->last; + iov->iov_len = size; } + + prev = cl->buf->pos + size; + send += size; } - n = writev(c->fd, io.elts, io.nelts); + n = writev(c->fd, vec.elts, vec.nelts); if (n == -1) { err = ngx_errno; @@ -82,34 +97,48 @@ ngx_chain_t *ngx_writev_chain(ngx_connec ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: " OFF_T_FMT, sent); + if (send - sprev == sent) { + complete = 1; + } + c->sent += sent; for (cl = in; cl && sent > 0; cl = cl->next) { + if (ngx_buf_special(cl->buf)) { + continue; + } + + if (sent == 0) { + break; + } size = cl->buf->last - cl->buf->pos; if (sent >= size) { sent -= size; - - if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos = cl->buf->last; - } + cl->buf->pos = cl->buf->last; continue; } - if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos += sent; - } + cl->buf->pos += sent; break; } - } while (eintr); + if (eintr) { + continue; + } - if (cl) { - wev->ready = 0; + if (!complete) { + wev->ready = 0; + return cl; + } + + if (send >= limit || cl == NULL) { + return cl; + } + + in = cl; } - - return cl; }