Mercurial > hg > nginx
diff src/os/unix/ngx_solaris_sendfilev_chain.c @ 197:0b81c7a0b133
nginx-0.0.1-2003-11-27-10:45:22 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 27 Nov 2003 07:45:22 +0000 |
parents | |
children | 34995c5ec6c4 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_solaris_sendfilev_chain.c @@ -0,0 +1,147 @@ + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> + + +ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in) +{ + int fd; + char *prev; + off_t fprev; + size_t sent; + ssize_t n; + ngx_int_t eintr; + sendfilevec_t *sfv; + ngx_array_t vec; + ngx_event_t *wev; + ngx_chain_t *cl; + + wev = c->write; + + if (!wev->ready) { + return in; + } + + do { + fd = SFV_FD_SELF; + prev = NULL; + sfv = NULL; + eintr = 0; + sent = 0; + + /* create the sendfilevec and coalesce the neighbouring hunks */ + + for (cl = in; cl; cl = cl->next) { + if (ngx_hunk_special(cl->hunk)) { + continue; + } + + if (ngx_hunk_in_memory_only(cl->hunk)) { + fd = SFV_FD_SELF; + + if (prev == cl->hunk->pos) { + sfv->sfv_len += cl->hunk->last - cl->hunk->pos; + + } else { + ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR); + sfv->sfv_fd = SFV_FD_SELF; + sfv->sfv_flag = 0; + sfv->sfv_off = cl->hunk->pos; + sfv->sfv_len = cl->hunk->last - cl->hunk->pos; + } + + prev = cl->hunk->last; + + } else { + prev = NULL; + + if (fd == cl->hunk->file->fd && fprev == cl->hunk->file_pos) { + sfv->sfv_len += cl->hunk->file_last - cl->hunk->file_pos; + + } else { + ngx_test_null(sfv, ngx_push_array(&vec), NGX_CHAIN_ERROR); + fd = cl->hunk->file->fd; + sfv->sfv_fd = fd; + sfv->sfv_flag = 0; + sfv->sfv_off = cl->hunk->file_pos; + sfv->sfv_len = cl->hunk->file_last - cl->hunk->file_pos; + } + + fprev = cl->hunk->file_last; + } + } + + n = sendfile(c->fd, vec->elts, vec->nelts, &sent); + + if (n == -1) { + err = ngx_errno; + + if (err == NGX_EINTR) { + eintr = 1; + } + + if (err == NGX_EAGAIN || err == NGX_EINTR) { + ngx_log_error(NGX_LOG_INFO, c->log, err, + "sendfilev() sent only " SIZE_T_FMT " bytes", + sent); + } else { + wev->error = 1; + ngx_log_error(NGX_LOG_CRIT, c->log, err, "sendfilev() failed"); + return NGX_CHAIN_ERROR; + } + } + +#if (NGX_DEBUG_WRITE_CHAIN) + ngx_log_debug(c->log, "sendfilev: %d " SIZE_T_FMT ", n _ sent); +#endif + + c->sent += sent; + + for (cl = in; cl; cl = cl->next) { + + if (ngx_hunk_special(cl->hunk)) { + continue; + } + + if (sent == 0) { + break; + } + + size = ngx_hunk_size(cl->hunk); + + if (sent >= size) { + sent -= size; + + if (cl->hunk->type & NGX_HUNK_IN_MEMORY) { + cl->hunk->pos = cl->hunk->last; + } + + if (cl->hunk->type & NGX_HUNK_FILE) { + cl->hunk->file_pos = cl->hunk->file_last; + } + + continue; + } + + if (cl->hunk->type & NGX_HUNK_IN_MEMORY) { + cl->hunk->pos += sent; + } + + if (cl->hunk->type & NGX_HUNK_FILE) { + cl->hunk->file_pos += sent; + } + + break; + } + + in = cl; + + } while (eintr); + + if (in) { + wev->ready = 0; + } + + return in; +}