#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
static ssize_t ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file,
size_t size);
#if (NGX_THREADS)
#include <ngx_thread_pool.h>
#if !(NGX_HAVE_SENDFILE64)
#error sendfile64() is required!
#endif
static ssize_t ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file,
size_t size);
static void ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log);
#endif
#define NGX_SENDFILE_MAXSIZE …
ngx_chain_t *
ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{ … }
static ssize_t
ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size)
{ … }
#if (NGX_THREADS)
typedef struct {
ngx_buf_t *file;
ngx_socket_t socket;
size_t size;
size_t sent;
ngx_err_t err;
} ngx_linux_sendfile_ctx_t;
static ssize_t
ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size)
{
ngx_event_t *wev;
ngx_thread_task_t *task;
ngx_linux_sendfile_ctx_t *ctx;
ngx_log_debug3(NGX_LOG_DEBUG_CORE, c->log, 0,
"linux sendfile thread: %d, %uz, %O",
file->file->fd, size, file->file_pos);
task = c->sendfile_task;
if (task == NULL) {
task = ngx_thread_task_alloc(c->pool, sizeof(ngx_linux_sendfile_ctx_t));
if (task == NULL) {
return NGX_ERROR;
}
task->event.log = c->log;
task->handler = ngx_linux_sendfile_thread_handler;
c->sendfile_task = task;
}
ctx = task->ctx;
wev = c->write;
if (task->event.complete) {
task->event.complete = 0;
if (ctx->err == NGX_EAGAIN) {
if (wev->complete) {
return 0;
}
return NGX_AGAIN;
}
if (ctx->err) {
wev->error = 1;
ngx_connection_error(c, ctx->err, "sendfile() failed");
return NGX_ERROR;
}
if (ctx->sent == 0) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
"sendfile() reported that \"%s\" was truncated at %O",
file->file->name.data, file->file_pos);
return NGX_ERROR;
}
return ctx->sent;
}
ctx->file = file;
ctx->socket = c->fd;
ctx->size = size;
wev->complete = 0;
if (file->file->thread_handler(task, file->file) != NGX_OK) {
return NGX_ERROR;
}
return NGX_DONE;
}
static void
ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log)
{
ngx_linux_sendfile_ctx_t *ctx = data;
off_t offset;
ssize_t n;
ngx_buf_t *file;
ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "linux sendfile thread handler");
file = ctx->file;
offset = file->file_pos;
again:
n = sendfile(ctx->socket, file->file->fd, &offset, ctx->size);
if (n == -1) {
ctx->err = ngx_errno;
} else {
ctx->sent = n;
ctx->err = 0;
}
#if 0
ngx_time_update();
#endif
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0,
"sendfile: %z (err: %d) of %uz @%O",
n, ctx->err, ctx->size, file->file_pos);
if (ctx->err == NGX_EINTR) {
goto again;
}
}
#endif