Mercurial > hg > nginx
diff src/os/unix/ngx_linux_sendfile_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 | e366ba5db8f8 |
children | f209f3391020 |
line wrap: on
line diff
--- a/src/os/unix/ngx_linux_sendfile_chain.c Sun Jun 20 19:54:15 2004 +0000 +++ b/src/os/unix/ngx_linux_sendfile_chain.c Mon Jun 21 15:59:32 2004 +0000 @@ -19,19 +19,21 @@ */ -ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) +ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit) { int rc; u_char *prev; - off_t fprev; - size_t size, fsize, sent; - ngx_int_t eintr; + off_t fprev, send, sprev, aligned; + size_t fsize; + ssize_t size, sent; + ngx_uint_t eintr, complete; struct iovec *iov; ngx_err_t err; ngx_buf_t *file; ngx_array_t header; ngx_event_t *wev; - ngx_chain_t *cl, *tail; + ngx_chain_t *cl; #if (HAVE_SENDFILE64) off_t offset; #else @@ -44,10 +46,14 @@ return in; } - do { + send = 0; + + for ( ;; ) { file = NULL; fsize = 0; eintr = 0; + complete = 0; + sprev = send; ngx_init_array(header, c->pool, 10, sizeof(struct iovec), NGX_CHAIN_ERROR); @@ -57,7 +63,10 @@ /* create the iovec and coalesce the neighbouring bufs */ - for (cl = in; cl && header.nelts < IOV_MAX; cl = cl->next) { + for (cl = in; + cl && header.nelts < IOV_MAX && send < limit; + cl = cl->next) + { if (ngx_buf_special(cl->buf)) { continue; } @@ -66,16 +75,23 @@ break; } + 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; + iov->iov_len += size; } else { ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR); iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = cl->buf->last - cl->buf->pos; + iov->iov_len = size; } - prev = cl->buf->last; + prev = cl->buf->pos + size; + send += size; } /* set TCP_CORK if there is a header before a file */ @@ -107,38 +123,41 @@ } } - if (header.nelts == 0 && cl && cl->buf->in_file) { - - /* get the file buf */ + /* get the file buf */ + if (header.nelts == 0 && cl && cl->buf->in_file && send < limit) { file = cl->buf; - fsize = (size_t) (file->file_last - file->file_pos); - fprev = file->file_last; - cl = cl->next; + fsize = 0; /* coalesce the neighbouring file bufs */ - while (cl && (cl->buf->in_file)) { - if (file->file->fd != cl->buf->file->fd - || fprev != cl->buf->file_pos) - { - break; + do { + size = (size_t) (cl->buf->file_last - cl->buf->file_pos); + + if (send + size > limit) { + size = limit - send; + + aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) + & ~(ngx_pagesize - 1); + + if (aligned <= cl->buf->file_last) { + size = aligned - cl->buf->file_pos; + } } - fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos); - fprev = cl->buf->file_last; + fsize += size; + send += size; + fprev = cl->buf->file_pos + size; cl = cl->next; - } + + } while (cl + && cl->buf->in_file + && send < limit + && file->file->fd == cl->buf->file->fd + && fprev == cl->buf->file_pos); } - /* - * the tail is the rest of the chain that exceedes - * a single sendfile() capability - */ - - tail = cl; - - if (fsize) { + if (file) { #if (HAVE_SENDFILE64) offset = file->file_pos; #else @@ -196,6 +215,10 @@ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d", sent); } + if (send - sprev == sent) { + complete = 1; + } + c->sent += sent; for (cl = in; cl; cl = cl->next) { @@ -235,15 +258,19 @@ break; } - in = cl; - - /* "tail == in" means that a single sendfile() is complete */ - - } while ((tail && tail == in) || eintr); + if (eintr) { + continue; + } - if (in) { - wev->ready = 0; + if (!complete) { + wev->ready = 0; + return cl; + } + + if (send >= limit || cl == NULL) { + return cl; + } + + in = cl; } - - return in; }