diff options
Diffstat (limited to 'src/os/unix')
-rw-r--r-- | src/os/unix/ngx_freebsd_sendfile_chain.c | 3 | ||||
-rw-r--r-- | src/os/unix/ngx_solaris.h | 8 | ||||
-rw-r--r-- | src/os/unix/ngx_solaris_config.h | 1 | ||||
-rw-r--r-- | src/os/unix/ngx_solaris_sendfilev_chain.c | 147 |
4 files changed, 158 insertions, 1 deletions
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index 6b0e62efc..bb89336fe 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -192,7 +192,8 @@ ngx_log_debug(c->log, "NOPUSH"); if (err == NGX_EAGAIN || err == NGX_EINTR) { ngx_log_error(NGX_LOG_INFO, c->log, err, - "sendfile() sent only %qd bytes", sent); + "sendfile() sent only " OFF_T_FMT " bytes", + sent); } else { wev->error = 1; diff --git a/src/os/unix/ngx_solaris.h b/src/os/unix/ngx_solaris.h new file mode 100644 index 000000000..c0829b782 --- /dev/null +++ b/src/os/unix/ngx_solaris.h @@ -0,0 +1,8 @@ +#ifndef _NGX_SOLARIS_H_INCLUDED_ +#define _NGX_SOLARIS_H_INCLUDED_ + + +ngx_chain_t *ngx_solaris_sendfilev_chain(ngx_connection_t *c, ngx_chain_t *in); + + +#endif /* _NGX_SOLARIS_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h index 078d8d07c..233b46bf2 100644 --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -23,6 +23,7 @@ #include <sys/filio.h> /* FIONBIO */ #include <sys/stropts.h> /* INFTIM */ #include <sys/socket.h> +#include <sys/sendfile.h> #include <sys/systeminfo.h> #include <netinet/in.h> #include <arpa/inet.h> diff --git a/src/os/unix/ngx_solaris_sendfilev_chain.c b/src/os/unix/ngx_solaris_sendfilev_chain.c new file mode 100644 index 000000000..8fe5cef1e --- /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; +} |