diff src/os/unix/ngx_files.c @ 6022:1fdba317ee6d

Added support for offloading read() in thread pools.
author Valentin Bartenev <vbart@nginx.com>
date Sat, 14 Mar 2015 17:37:25 +0300
parents 1e2d5d3f9f6b
children 6fce16b1fc10
line wrap: on
line diff
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -9,6 +9,12 @@
 #include <ngx_core.h>
 
 
+#if (NGX_THREADS)
+#include <ngx_thread_pool.h>
+static void ngx_thread_read_handler(void *data, ngx_log_t *log);
+#endif
+
+
 #if (NGX_HAVE_FILE_AIO)
 
 ngx_uint_t  ngx_file_aio = 1;
@@ -64,6 +70,109 @@ ngx_read_file(ngx_file_t *file, u_char *
 }
 
 
+#if (NGX_THREADS)
+
+typedef struct {
+    ngx_fd_t     fd;
+    u_char      *buf;
+    size_t       size;
+    off_t        offset;
+
+    size_t       read;
+    ngx_err_t    err;
+} ngx_thread_read_ctx_t;
+
+
+ssize_t
+ngx_thread_read(ngx_thread_task_t **taskp, ngx_file_t *file, u_char *buf,
+    size_t size, off_t offset, ngx_pool_t *pool)
+{
+    ngx_thread_task_t      *task;
+    ngx_thread_read_ctx_t  *ctx;
+
+    ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
+                   "thread read: %d, %p, %uz, %O",
+                   file->fd, buf, size, offset);
+
+    task = *taskp;
+
+    if (task == NULL) {
+        task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_read_ctx_t));
+        if (task == NULL) {
+            return NGX_ERROR;
+        }
+
+        task->handler = ngx_thread_read_handler;
+
+        *taskp = task;
+    }
+
+    ctx = task->ctx;
+
+    if (task->event.complete) {
+        task->event.complete = 0;
+
+        if (ctx->err) {
+            ngx_log_error(NGX_LOG_CRIT, file->log, ctx->err,
+                          "pread() \"%s\" failed", file->name.data);
+            return NGX_ERROR;
+        }
+
+        return ctx->read;
+    }
+
+    ctx->fd = file->fd;
+    ctx->buf = buf;
+    ctx->size = size;
+    ctx->offset = offset;
+
+    if (file->thread_handler(task, file) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    return NGX_AGAIN;
+}
+
+
+#if (NGX_HAVE_PREAD)
+
+static void
+ngx_thread_read_handler(void *data, ngx_log_t *log)
+{
+    ngx_thread_read_ctx_t *ctx = data;
+
+    ssize_t  n;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread read handler");
+
+    n = pread(ctx->fd, ctx->buf, ctx->size, ctx->offset);
+
+    if (n == -1) {
+        ctx->err = ngx_errno;
+
+    } else {
+        ctx->read = n;
+        ctx->err = 0;
+    }
+
+#if 0
+    ngx_time_update();
+#endif
+
+    ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0,
+                   "pread: %z (err: %i) of %uz @%O",
+                   n, ctx->err, ctx->size, ctx->offset);
+}
+
+#else
+
+#error pread() is required!
+
+#endif
+
+#endif /* NGX_THREADS */
+
+
 ssize_t
 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
 {