cache: move open to thread pool

Roman Arutyunyan arut at nginx.com
Thu Oct 4 09:32:26 UTC 2018


Hi,

On Thu, Sep 13, 2018 at 09:10:23PM +0300, Maxim Dounin wrote:
> Hello!
> 
> On Tue, Sep 04, 2018 at 04:58:05PM -0700, Ka-Hing Cheung via nginx-devel wrote:
> 
> > On Mon, Sep 3, 2018 at 9:09 AM, Maxim Dounin <mdounin at mdounin.ru> wrote:

[..]

Here's another approach to thread open.  This time it's 4 patches:

- #1 a small open file cache refactoring
- #2 thread open in open file cache
- #3 thread open in http static module
- #4 thread open in http file cache

-- 
Roman Arutyunyan
-------------- next part --------------
# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1538143636 -10800
#      Fri Sep 28 17:07:16 2018 +0300
# Node ID 1ebbfd3e3cd814e4428561b814a5684c69668ba4
# Parent  cd4fa2fab8d8f1a2d03841249230bed76d318502
Prepared open file cache for async open.

Specifically, several open file cache internal functions now receive pool
instead of log and return file descriptor in the ngx_open_file_info_t structure
instead of returning it directtly.

diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -30,13 +30,13 @@ static ngx_int_t ngx_file_o_path_info(ng
     ngx_log_t *log);
 #endif
 #endif
-static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
+static ngx_int_t ngx_open_file_wrapper(ngx_str_t *name,
     ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
-    ngx_int_t access, ngx_log_t *log);
+    ngx_int_t access, ngx_pool_t *pool);
 static ngx_int_t ngx_file_info_wrapper(ngx_str_t *name,
-    ngx_open_file_info_t *of, ngx_file_info_t *fi, ngx_log_t *log);
+    ngx_open_file_info_t *of, ngx_file_info_t *fi, ngx_pool_t *pool);
 static ngx_int_t ngx_open_and_stat_file(ngx_str_t *name,
-    ngx_open_file_info_t *of, ngx_log_t *log);
+    ngx_open_file_info_t *of, ngx_pool_t *pool);
 static void ngx_open_file_add_event(ngx_open_file_cache_t *cache,
     ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log);
 static void ngx_open_file_cleanup(void *data);
@@ -160,10 +160,9 @@ ngx_open_cached_file(ngx_open_file_cache
 
         if (of->test_only) {
 
-            if (ngx_file_info_wrapper(name, of, &fi, pool->log)
-                == NGX_FILE_ERROR)
-            {
-                return NGX_ERROR;
+            rc = ngx_file_info_wrapper(name, of, &fi, pool);
+            if (rc != NGX_OK) {
+                return rc;
             }
 
             of->uniq = ngx_file_uniq(&fi);
@@ -183,7 +182,7 @@ ngx_open_cached_file(ngx_open_file_cache
             return NGX_ERROR;
         }
 
-        rc = ngx_open_and_stat_file(name, of, pool->log);
+        rc = ngx_open_and_stat_file(name, of, pool);
 
         if (rc == NGX_OK && !of->is_dir) {
             cln->handler = ngx_pool_cleanup_file;
@@ -218,7 +217,7 @@ ngx_open_cached_file(ngx_open_file_cache
 
             /* file was not used often enough to keep open */
 
-            rc = ngx_open_and_stat_file(name, of, pool->log);
+            rc = ngx_open_and_stat_file(name, of, pool);
 
             if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
                 goto failed;
@@ -286,7 +285,7 @@ ngx_open_cached_file(ngx_open_file_cache
         of->fd = file->fd;
         of->uniq = file->uniq;
 
-        rc = ngx_open_and_stat_file(name, of, pool->log);
+        rc = ngx_open_and_stat_file(name, of, pool);
 
         if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
             goto failed;
@@ -351,7 +350,7 @@ ngx_open_cached_file(ngx_open_file_cache
 
     /* not found */
 
-    rc = ngx_open_and_stat_file(name, of, pool->log);
+    rc = ngx_open_and_stat_file(name, of, pool);
 
     if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
         goto failed;
@@ -610,40 +609,38 @@ ngx_file_o_path_info(ngx_fd_t fd, ngx_fi
 #endif /* NGX_HAVE_OPENAT */
 
 
-static ngx_fd_t
+static ngx_int_t
 ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
-    ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
+    ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_pool_t *pool)
 {
-    ngx_fd_t  fd;
-
 #if !(NGX_HAVE_OPENAT)
 
-    fd = ngx_open_file(name->data, mode, create, access);
+    of->fd = ngx_open_file(name->data, mode, create, access);
 
-    if (fd == NGX_INVALID_FILE) {
+    if (of->fd == NGX_INVALID_FILE) {
         of->err = ngx_errno;
         of->failed = ngx_open_file_n;
-        return NGX_INVALID_FILE;
+        return NGX_ERROR;
     }
 
-    return fd;
+    return NGX_OK;
 
 #else
 
-    u_char           *p, *cp, *end;
-    ngx_fd_t          at_fd;
-    ngx_str_t         at_name;
+    u_char     *p, *cp, *end;
+    ngx_fd_t    fd, at_fd;
+    ngx_str_t   at_name;
 
     if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
-        fd = ngx_open_file(name->data, mode, create, access);
+        of->fd = ngx_open_file(name->data, mode, create, access);
 
-        if (fd == NGX_INVALID_FILE) {
+        if (of->fd == NGX_INVALID_FILE) {
             of->err = ngx_errno;
             of->failed = ngx_open_file_n;
-            return NGX_INVALID_FILE;
+            return NGX_ERROR;
         }
 
-        return fd;
+        return NGX_OK;
     }
 
     p = name->data;
@@ -665,7 +662,7 @@ ngx_open_file_wrapper(ngx_str_t *name, n
         if (at_fd == NGX_INVALID_FILE) {
             of->err = ngx_errno;
             of->failed = ngx_open_file_n;
-            return NGX_INVALID_FILE;
+            return NGX_ERROR;
         }
 
         at_name.len = of->disable_symlinks_from;
@@ -680,7 +677,7 @@ ngx_open_file_wrapper(ngx_str_t *name, n
         if (at_fd == NGX_INVALID_FILE) {
             of->err = ngx_errno;
             of->failed = ngx_openat_file_n;
-            return NGX_INVALID_FILE;
+            return NGX_ERROR;
         }
 
         at_name.len = 1;
@@ -706,7 +703,7 @@ ngx_open_file_wrapper(ngx_str_t *name, n
         if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
             fd = ngx_openat_file_owner(at_fd, p,
                                        NGX_FILE_SEARCH|NGX_FILE_NONBLOCK,
-                                       NGX_FILE_OPEN, 0, log);
+                                       NGX_FILE_OPEN, 0, pool->log);
 
         } else {
             fd = ngx_openat_file(at_fd, p,
@@ -723,7 +720,7 @@ ngx_open_file_wrapper(ngx_str_t *name, n
         }
 
         if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+            ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                           ngx_close_file_n " \"%V\" failed", &at_name);
         }
 
@@ -752,7 +749,7 @@ ngx_open_file_wrapper(ngx_str_t *name, n
     if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER
         && !(create & (NGX_FILE_CREATE_OR_OPEN|NGX_FILE_TRUNCATE)))
     {
-        fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
+        fd = ngx_openat_file_owner(at_fd, p, mode, create, access, pool->log);
 
     } else {
         fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
@@ -768,18 +765,20 @@ done:
 failed:
 
     if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+        ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                       ngx_close_file_n " \"%V\" failed", &at_name);
     }
 
-    return fd;
+    of->fd = fd;
+
+    return fd == NGX_INVALID_FILE ? NGX_ERROR : NGX_OK;
 #endif
 }
 
 
 static ngx_int_t
 ngx_file_info_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
-    ngx_file_info_t *fi, ngx_log_t *log)
+    ngx_file_info_t *fi, ngx_pool_t *pool)
 {
     ngx_int_t  rc;
 
@@ -790,15 +789,13 @@ ngx_file_info_wrapper(ngx_str_t *name, n
     if (rc == NGX_FILE_ERROR) {
         of->err = ngx_errno;
         of->failed = ngx_file_info_n;
-        return NGX_FILE_ERROR;
+        return NGX_ERROR;
     }
 
-    return rc;
+    return NGX_OK;
 
 #else
 
-    ngx_fd_t  fd;
-
     if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
 
         rc = ngx_file_info(name->data, fi);
@@ -806,48 +803,55 @@ ngx_file_info_wrapper(ngx_str_t *name, n
         if (rc == NGX_FILE_ERROR) {
             of->err = ngx_errno;
             of->failed = ngx_file_info_n;
-            return NGX_FILE_ERROR;
+            return NGX_ERROR;
         }
 
+        return NGX_OK;
+    }
+
+    rc = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+                               NGX_FILE_OPEN, 0, pool);
+    if (rc != NGX_OK) {
         return rc;
     }
 
-    fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
-                               NGX_FILE_OPEN, 0, log);
-
-    if (fd == NGX_INVALID_FILE) {
-        return NGX_FILE_ERROR;
-    }
-
-    rc = ngx_fd_info(fd, fi);
+    rc = ngx_fd_info(of->fd, fi);
 
     if (rc == NGX_FILE_ERROR) {
         of->err = ngx_errno;
         of->failed = ngx_fd_info_n;
     }
 
-    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+    if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
+        ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                       ngx_close_file_n " \"%V\" failed", name);
     }
 
-    return rc;
+    of->fd = NGX_INVALID_FILE;
+
+    return rc == NGX_FILE_ERROR ? NGX_ERROR : NGX_OK;
 #endif
 }
 
 
 static ngx_int_t
 ngx_open_and_stat_file(ngx_str_t *name, ngx_open_file_info_t *of,
-    ngx_log_t *log)
+    ngx_pool_t *pool)
 {
-    ngx_fd_t         fd;
+    ngx_int_t        rc;
     ngx_file_info_t  fi;
 
     if (of->fd != NGX_INVALID_FILE) {
 
-        if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
+        rc = ngx_file_info_wrapper(name, of, &fi, pool);
+
+        if (rc == NGX_AGAIN) {
+            return NGX_AGAIN;
+        }
+
+        if (rc != NGX_OK) {
             of->fd = NGX_INVALID_FILE;
-            return NGX_ERROR;
+            return rc;
         }
 
         if (of->uniq == ngx_file_uniq(&fi)) {
@@ -856,9 +860,15 @@ ngx_open_and_stat_file(ngx_str_t *name, 
 
     } else if (of->test_dir) {
 
-        if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
+        rc = ngx_file_info_wrapper(name, of, &fi, pool);
+
+        if (rc == NGX_AGAIN) {
+            return NGX_AGAIN;
+        }
+
+        if (rc != NGX_OK) {
             of->fd = NGX_INVALID_FILE;
-            return NGX_ERROR;
+            return rc;
         }
 
         if (ngx_is_dir(&fi)) {
@@ -873,26 +883,25 @@ ngx_open_and_stat_file(ngx_str_t *name, 
          * This flag has no effect on a regular files.
          */
 
-        fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
-                                   NGX_FILE_OPEN, 0, log);
+        rc = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+                                   NGX_FILE_OPEN, 0, pool);
 
     } else {
-        fd = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND,
+        rc = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND,
                                    NGX_FILE_CREATE_OR_OPEN,
-                                   NGX_FILE_DEFAULT_ACCESS, log);
+                                   NGX_FILE_DEFAULT_ACCESS, pool);
     }
 
-    if (fd == NGX_INVALID_FILE) {
-        of->fd = NGX_INVALID_FILE;
-        return NGX_ERROR;
+    if (rc != NGX_OK) {
+        return rc;
     }
 
-    if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
-        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+    if (ngx_fd_info(of->fd, &fi) == NGX_FILE_ERROR) {
+        ngx_log_error(NGX_LOG_CRIT, pool->log, ngx_errno,
                       ngx_fd_info_n " \"%V\" failed", name);
 
-        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+        if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                           ngx_close_file_n " \"%V\" failed", name);
         }
 
@@ -902,26 +911,24 @@ ngx_open_and_stat_file(ngx_str_t *name, 
     }
 
     if (ngx_is_dir(&fi)) {
-        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+        if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                           ngx_close_file_n " \"%V\" failed", name);
         }
 
         of->fd = NGX_INVALID_FILE;
 
     } else {
-        of->fd = fd;
-
         if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) {
-            if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) {
-                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+            if (ngx_read_ahead(of->fd, of->read_ahead) == NGX_ERROR) {
+                ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                               ngx_read_ahead_n " \"%V\" failed", name);
             }
         }
 
         if (of->directio <= ngx_file_size(&fi)) {
-            if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
-                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+            if (ngx_directio_on(of->fd) == NGX_FILE_ERROR) {
+                ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
                               ngx_directio_on_n " \"%V\" failed", name);
 
             } else {
-------------- next part --------------
# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1538644508 -10800
#      Thu Oct 04 12:15:08 2018 +0300
# Node ID 82f2dea6f3c6e3edf78968ab9f623d7b92e074fd
# Parent  1ebbfd3e3cd814e4428561b814a5684c69668ba4
Threaded open support in open file cache.

diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -17,6 +17,7 @@ struct ngx_file_s {
     ngx_fd_t                   fd;
     ngx_str_t                  name;
     ngx_file_info_t            info;
+    ngx_err_t                  err;
 
     off_t                      offset;
     off_t                      sys_offset;
diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -177,14 +177,21 @@ ngx_open_cached_file(ngx_open_file_cache
             return NGX_OK;
         }
 
-        cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));
-        if (cln == NULL) {
-            return NGX_ERROR;
-        }
-
         rc = ngx_open_and_stat_file(name, of, pool);
 
         if (rc == NGX_OK && !of->is_dir) {
+            cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));
+
+            if (cln == NULL) {
+                if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
+                    ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
+                                  ngx_close_file_n " \"%s\" failed",
+                                  name->data);
+                }
+
+                return NGX_ERROR;
+            }
+
             cln->handler = ngx_pool_cleanup_file;
             clnf = cln->data;
 
@@ -196,6 +203,11 @@ ngx_open_cached_file(ngx_open_file_cache
         return rc;
     }
 
+#if (NGX_THREADS)
+    /* disable thread open if cache is enabled */
+    of->thread_handler = NULL;
+#endif
+
     cln = ngx_pool_cleanup_add(pool, sizeof(ngx_open_file_cache_cleanup_t));
     if (cln == NULL) {
         return NGX_ERROR;
@@ -613,6 +625,40 @@ static ngx_int_t
 ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
     ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_pool_t *pool)
 {
+#if (NGX_THREADS)
+
+    if (of->thread_handler) {
+        ngx_int_t   rc;
+        ngx_file_t  file;
+
+        ngx_memzero(&file, sizeof(ngx_file_t));
+
+        file.log = pool->log;
+        file.fd = NGX_INVALID_FILE;
+        file.thread_handler = of->thread_handler;
+        file.thread_ctx = of->thread_ctx;
+        file.thread_task = of->thread_task;
+
+        rc = ngx_thread_open(&file, name->data, mode, create, access, pool);
+
+        if (rc == NGX_AGAIN) {
+            of->thread_task = file.thread_task;
+            return NGX_AGAIN;
+        }
+
+        if (rc != NGX_OK) {
+            of->err = file.err;
+            of->failed = ngx_open_file_n;
+            return NGX_ERROR;
+        }
+
+        of->fd = file.fd;
+
+        return NGX_OK;
+    }
+
+#endif
+
 #if !(NGX_HAVE_OPENAT)
 
     of->fd = ngx_open_file(name->data, mode, create, access);
diff --git a/src/core/ngx_open_file_cache.h b/src/core/ngx_open_file_cache.h
--- a/src/core/ngx_open_file_cache.h
+++ b/src/core/ngx_open_file_cache.h
@@ -32,6 +32,13 @@ typedef struct {
 
     ngx_uint_t               min_uses;
 
+#if (NGX_THREADS || NGX_COMPAT)
+    ngx_int_t              (*thread_handler)(ngx_thread_task_t *task,
+                                             ngx_file_t *file);
+    void                    *thread_ctx;
+    ngx_thread_task_t       *thread_task;
+#endif
+
 #if (NGX_HAVE_OPENAT)
     size_t                   disable_symlinks_from;
     unsigned                 disable_symlinks:2;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -420,6 +420,13 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_loc_conf_t, aio_write),
       NULL },
 
+    { ngx_string("aio_open"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, aio_open),
+      NULL },
+
     { ngx_string("read_ahead"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_size_slot,
@@ -3380,6 +3387,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     clcf->subrequest_output_buffer_size = NGX_CONF_UNSET_SIZE;
     clcf->aio = NGX_CONF_UNSET;
     clcf->aio_write = NGX_CONF_UNSET;
+    clcf->aio_open = NGX_CONF_UNSET;
 #if (NGX_THREADS)
     clcf->thread_pool = NGX_CONF_UNSET_PTR;
     clcf->thread_pool_value = NGX_CONF_UNSET_PTR;
@@ -3605,6 +3613,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
                               (size_t) ngx_pagesize);
     ngx_conf_merge_value(conf->aio, prev->aio, NGX_HTTP_AIO_OFF);
     ngx_conf_merge_value(conf->aio_write, prev->aio_write, 0);
+    ngx_conf_merge_value(conf->aio_open, prev->aio_open, 0);
 #if (NGX_THREADS)
     ngx_conf_merge_ptr_value(conf->thread_pool, prev->thread_pool, NULL);
     ngx_conf_merge_ptr_value(conf->thread_pool_value, prev->thread_pool_value,
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -382,6 +382,7 @@ struct ngx_http_core_loc_conf_s {
     ngx_flag_t    sendfile;                /* sendfile */
     ngx_flag_t    aio;                     /* aio */
     ngx_flag_t    aio_write;               /* aio_write */
+    ngx_flag_t    aio_open;                /* aio_open */
     ngx_flag_t    tcp_nopush;              /* tcp_nopush */
     ngx_flag_t    tcp_nodelay;             /* tcp_nodelay */
     ngx_flag_t    reset_timedout_connection; /* reset_timedout_connection */
diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -11,6 +11,7 @@
 
 #if (NGX_THREADS)
 #include <ngx_thread_pool.h>
+static void ngx_thread_open_handler(void *data, ngx_log_t *log);
 static void ngx_thread_read_handler(void *data, ngx_log_t *log);
 static void ngx_thread_write_chain_to_file_handler(void *data, ngx_log_t *log);
 #endif
@@ -77,20 +78,112 @@ ngx_read_file(ngx_file_t *file, u_char *
 
 #if (NGX_THREADS)
 
+typedef enum {
+    NGX_THREAD_FILE_OPEN = 1,
+    NGX_THREAD_FILE_READ,
+    NGX_THREAD_FILE_WRITE
+} ngx_thread_file_op_e;
+
+
 typedef struct {
     ngx_fd_t       fd;
-    ngx_uint_t     write;   /* unsigned  write:1; */
+    u_char        *name;
+    ngx_uint_t     op;  /* ngx_thread_file_op_e */
 
     u_char        *buf;
     size_t         size;
     ngx_chain_t   *chain;
     off_t          offset;
 
+    ngx_int_t      mode;
+    ngx_int_t      create;
+    ngx_int_t      access;
+
     size_t         nbytes;
     ngx_err_t      err;
 } ngx_thread_file_ctx_t;
 
 
+ngx_int_t
+ngx_thread_open(ngx_file_t *file, u_char *name, ngx_int_t mode,
+    ngx_int_t create, ngx_int_t access, ngx_pool_t *pool)
+{
+    ngx_thread_task_t      *task;
+    ngx_thread_file_ctx_t  *ctx;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
+                   "thread open: \"%s\"", name);
+
+    task = file->thread_task;
+
+    if (task == NULL) {
+        task = ngx_thread_task_alloc(pool, sizeof(ngx_thread_file_ctx_t));
+        if (task == NULL) {
+            return NGX_ERROR;
+        }
+
+        file->thread_task = task;
+    }
+
+    ctx = task->ctx;
+
+    if (task->event.complete) {
+        task->event.complete = 0;
+
+        if (ctx->op != NGX_THREAD_FILE_OPEN) {
+            ngx_log_error(NGX_LOG_ALERT, file->log, 0,
+                          "invalid thread operation, open expected");
+            return NGX_ERROR;
+        }
+
+        if (ctx->err) {
+            file->err = ctx->err;
+            return NGX_ERROR;
+        }
+
+        file->fd = ctx->fd;
+
+        return NGX_OK;
+    }
+
+    task->handler = ngx_thread_open_handler;
+
+    ctx->op = NGX_THREAD_FILE_OPEN;
+
+    ctx->name = name;
+    ctx->mode = mode;
+    ctx->create = create;
+    ctx->access = access;
+
+    if (file->thread_handler(task, file) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    return NGX_AGAIN;
+}
+
+
+static void
+ngx_thread_open_handler(void *data, ngx_log_t *log)
+{
+    ngx_thread_file_ctx_t *ctx = data;
+
+    ngx_fd_t  fd;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "thread open handler");
+
+    fd = ngx_open_file(ctx->name, ctx->mode, ctx->create, ctx->access);
+
+    if (fd == NGX_INVALID_FILE) {
+        ctx->err = ngx_errno;
+
+    } else {
+        ctx->fd = fd;
+        ctx->err = 0;
+    }
+}
+
+
 ssize_t
 ngx_thread_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
     ngx_pool_t *pool)
@@ -118,9 +211,9 @@ ngx_thread_read(ngx_file_t *file, u_char
     if (task->event.complete) {
         task->event.complete = 0;
 
-        if (ctx->write) {
+        if (ctx->op != NGX_THREAD_FILE_READ) {
             ngx_log_error(NGX_LOG_ALERT, file->log, 0,
-                          "invalid thread call, read instead of write");
+                          "invalid thread operation, read expected");
             return NGX_ERROR;
         }
 
@@ -135,7 +228,7 @@ ngx_thread_read(ngx_file_t *file, u_char
 
     task->handler = ngx_thread_read_handler;
 
-    ctx->write = 0;
+    ctx->op = NGX_THREAD_FILE_READ;
 
     ctx->fd = file->fd;
     ctx->buf = buf;
@@ -501,9 +594,9 @@ ngx_thread_write_chain_to_file(ngx_file_
     if (task->event.complete) {
         task->event.complete = 0;
 
-        if (!ctx->write) {
+        if (ctx->op != NGX_THREAD_FILE_WRITE) {
             ngx_log_error(NGX_LOG_ALERT, file->log, 0,
-                          "invalid thread call, write instead of read");
+                          "invalid thread operation, write expected");
             return NGX_ERROR;
         }
 
@@ -519,7 +612,7 @@ ngx_thread_write_chain_to_file(ngx_file_
 
     task->handler = ngx_thread_write_chain_to_file_handler;
 
-    ctx->write = 1;
+    ctx->op = NGX_THREAD_FILE_WRITE;
 
     ctx->fd = file->fd;
     ctx->chain = cl;
diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -385,6 +385,8 @@ extern ngx_uint_t  ngx_file_aio;
 #endif
 
 #if (NGX_THREADS)
+ngx_int_t ngx_thread_open(ngx_file_t *file, u_char *name,
+    ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_pool_t *pool);
 ssize_t ngx_thread_read(ngx_file_t *file, u_char *buf, size_t size,
     off_t offset, ngx_pool_t *pool);
 ssize_t ngx_thread_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl,
-------------- next part --------------
# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1538403503 -10800
#      Mon Oct 01 17:18:23 2018 +0300
# Node ID 68e2acd8c4cf81cdbe57c0a83bbafe43072cb9b5
# Parent  82f2dea6f3c6e3edf78968ab9f623d7b92e074fd
Static: support for threaded open.

diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -11,7 +11,21 @@
 
 
 static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_static_send(ngx_http_request_t *r);
 static ngx_int_t ngx_http_static_init(ngx_conf_t *cf);
+#if (NGX_THREADS)
+static void ngx_http_static_write_event_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_static_thread_handler(ngx_thread_task_t *task,
+    ngx_file_t *file);
+static void ngx_http_static_thread_event_handler(ngx_event_t *ev);
+#endif
+
+
+typedef struct {
+    u_char                  *last;
+    ngx_str_t                path;
+    ngx_open_file_info_t     of;
+} ngx_http_static_ctx_t;
 
 
 static ngx_http_module_t  ngx_http_static_module_ctx = {
@@ -48,15 +62,9 @@ ngx_module_t  ngx_http_static_module = {
 static ngx_int_t
 ngx_http_static_handler(ngx_http_request_t *r)
 {
-    u_char                    *last, *location;
-    size_t                     root, len;
-    ngx_str_t                  path;
+    size_t                     root;
     ngx_int_t                  rc;
-    ngx_uint_t                 level;
-    ngx_log_t                 *log;
-    ngx_buf_t                 *b;
-    ngx_chain_t                out;
-    ngx_open_file_info_t       of;
+    ngx_http_static_ctx_t     *ctx;
     ngx_http_core_loc_conf_t  *clcf;
 
     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
@@ -67,42 +75,94 @@ ngx_http_static_handler(ngx_http_request
         return NGX_DECLINED;
     }
 
-    log = r->connection->log;
+    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_static_ctx_t));
+    if (ctx == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_http_set_ctx(r, ctx, ngx_http_static_module);
 
     /*
      * ngx_http_map_uri_to_path() allocates memory for terminating '\0'
      * so we do not need to reserve memory for '/' for possible redirect
      */
 
-    last = ngx_http_map_uri_to_path(r, &path, &root, 0);
-    if (last == NULL) {
+    ctx->last = ngx_http_map_uri_to_path(r, &ctx->path, &root, 0);
+    if (ctx->last == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    path.len = last - path.data;
+    ctx->path.len = ctx->last - ctx->path.data;
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                   "http filename: \"%s\"", path.data);
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http filename: \"%s\"", ctx->path.data);
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+    ctx->of.read_ahead = clcf->read_ahead;
+    ctx->of.directio = clcf->directio;
+    ctx->of.valid = clcf->open_file_cache_valid;
+    ctx->of.min_uses = clcf->open_file_cache_min_uses;
+    ctx->of.errors = clcf->open_file_cache_errors;
+    ctx->of.events = clcf->open_file_cache_events;
 
-    of.read_ahead = clcf->read_ahead;
-    of.directio = clcf->directio;
-    of.valid = clcf->open_file_cache_valid;
-    of.min_uses = clcf->open_file_cache_min_uses;
-    of.errors = clcf->open_file_cache_errors;
-    of.events = clcf->open_file_cache_events;
+#if (NGX_THREADS)
+    if (clcf->aio == NGX_HTTP_AIO_THREADS && clcf->aio_open) {
+        ctx->of.thread_handler = ngx_http_static_thread_handler;
+        ctx->of.thread_ctx = r;
+    }
+#endif
 
-    if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
+    if (ngx_http_set_disable_symlinks(r, clcf, &ctx->path, &ctx->of) != NGX_OK) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
-        != NGX_OK)
-    {
-        switch (of.err) {
+    rc = ngx_http_static_send(r);
+
+#if (NGX_THREADS)
+    if (rc == NGX_DONE) {
+        r->main->count++;
+        r->write_event_handler = ngx_http_static_write_event_handler;
+    }
+#endif
+
+    return rc;
+}
+
+
+static ngx_int_t
+ngx_http_static_send(ngx_http_request_t *r)
+{
+    u_char                    *location;
+    size_t                     len;
+    ngx_log_t                 *log;
+    ngx_int_t                  rc;
+    ngx_uint_t                 level;
+    ngx_buf_t                 *b;
+    ngx_chain_t                out;
+    ngx_http_static_ctx_t     *ctx;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_static_module);
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http static send: \"%s\"", ctx->path.data);
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    log = r->connection->log;
+
+    rc = ngx_open_cached_file(clcf->open_file_cache, &ctx->path, &ctx->of,
+                              r->pool);
+
+#if (NGX_THREADS)
+    if (rc == NGX_AGAIN) {
+        return NGX_DONE;
+    }
+#endif
+
+    if (rc != NGX_OK) {
+        switch (ctx->of.err) {
 
         case 0:
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -133,8 +193,8 @@ ngx_http_static_handler(ngx_http_request
         }
 
         if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
-            ngx_log_error(level, log, of.err,
-                          "%s \"%s\" failed", of.failed, path.data);
+            ngx_log_error(level, log, ctx->of.err,
+                          "%s \"%s\" failed", ctx->of.failed, ctx->path.data);
         }
 
         return rc;
@@ -142,9 +202,10 @@ ngx_http_static_handler(ngx_http_request
 
     r->root_tested = !r->error_page;
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d",
+                   ctx->of.fd);
 
-    if (of.is_dir) {
+    if (ctx->of.is_dir) {
 
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
 
@@ -158,9 +219,9 @@ ngx_http_static_handler(ngx_http_request
         len = r->uri.len + 1;
 
         if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
-            location = path.data + clcf->root.len;
+            location = ctx->path.data + clcf->root.len;
 
-            *last = '/';
+            *ctx->last = '/';
 
         } else {
             if (r->args.len) {
@@ -173,13 +234,13 @@ ngx_http_static_handler(ngx_http_request
                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
             }
 
-            last = ngx_copy(location, r->uri.data, r->uri.len);
+            ctx->last = ngx_copy(location, r->uri.data, r->uri.len);
 
-            *last = '/';
+            *ctx->last = '/';
 
             if (r->args.len) {
-                *++last = '?';
-                ngx_memcpy(++last, r->args.data, r->args.len);
+                *++ctx->last = '?';
+                ngx_memcpy(++ctx->last, r->args.data, r->args.len);
             }
         }
 
@@ -193,9 +254,9 @@ ngx_http_static_handler(ngx_http_request
 
 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
 
-    if (!of.is_file) {
+    if (!ctx->of.is_file) {
         ngx_log_error(NGX_LOG_CRIT, log, 0,
-                      "\"%s\" is not a regular file", path.data);
+                      "\"%s\" is not a regular file", ctx->path.data);
 
         return NGX_HTTP_NOT_FOUND;
     }
@@ -215,8 +276,8 @@ ngx_http_static_handler(ngx_http_request
     log->action = "sending response to client";
 
     r->headers_out.status = NGX_HTTP_OK;
-    r->headers_out.content_length_n = of.size;
-    r->headers_out.last_modified_time = of.mtime;
+    r->headers_out.content_length_n = ctx->of.size;
+    r->headers_out.last_modified_time = ctx->of.mtime;
 
     if (ngx_http_set_etag(r) != NGX_OK) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -226,7 +287,7 @@ ngx_http_static_handler(ngx_http_request
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (r != r->main && of.size == 0) {
+    if (r != r->main && ctx->of.size == 0) {
         return ngx_http_send_header(r);
     }
 
@@ -251,16 +312,16 @@ ngx_http_static_handler(ngx_http_request
     }
 
     b->file_pos = 0;
-    b->file_last = of.size;
+    b->file_last = ctx->of.size;
 
     b->in_file = b->file_last ? 1: 0;
     b->last_buf = (r == r->main) ? 1: 0;
     b->last_in_chain = 1;
 
-    b->file->fd = of.fd;
-    b->file->name = path;
+    b->file->fd = ctx->of.fd;
+    b->file->name = ctx->path;
     b->file->log = log;
-    b->file->directio = of.is_directio;
+    b->file->directio = ctx->of.is_directio;
 
     out.buf = b;
     out.next = NULL;
@@ -269,6 +330,90 @@ ngx_http_static_handler(ngx_http_request
 }
 
 
+#if (NGX_THREADS)
+
+static void
+ngx_http_static_write_event_handler(ngx_http_request_t *r)
+{
+    ngx_int_t  rc;
+
+    rc = ngx_http_static_send(r);
+
+    if (rc != NGX_DONE) {
+        ngx_http_finalize_request(r, rc);
+    }
+}
+
+
+static ngx_int_t
+ngx_http_static_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
+{
+    ngx_str_t                  name;
+    ngx_thread_pool_t         *tp;
+    ngx_http_request_t        *r;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    r = file->thread_ctx;
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    tp = clcf->thread_pool;
+
+    if (tp == NULL) {
+        if (ngx_http_complex_value(r, clcf->thread_pool_value, &name)
+            != NGX_OK)
+        {
+            return NGX_ERROR;
+        }
+
+        tp = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name);
+
+        if (tp == NULL) {
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                          "thread pool \"%V\" not found", &name);
+            return NGX_ERROR;
+        }
+    }
+
+    task->event.data = r;
+    task->event.handler = ngx_http_static_thread_event_handler;
+
+    if (ngx_thread_task_post(tp, task) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    r->main->blocked++;
+    r->aio = 1;
+
+    return NGX_OK;
+}
+
+
+static void
+ngx_http_static_thread_event_handler(ngx_event_t *ev)
+{
+    ngx_connection_t    *c;
+    ngx_http_request_t  *r;
+
+    r = ev->data;
+    c = r->connection;
+
+    ngx_http_set_log_request(c->log, r);
+
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http static thread: \"%V?%V\"", &r->uri, &r->args);
+
+    r->main->blocked--;
+    r->aio = 0;
+
+    r->write_event_handler(r);
+
+    ngx_http_run_posted_requests(c);
+}
+
+#endif
+
+
 static ngx_int_t
 ngx_http_static_init(ngx_conf_t *cf)
 {
-------------- next part --------------
# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1538403511 -10800
#      Mon Oct 01 17:18:31 2018 +0300
# Node ID 8f502ffdfbc032b30f45e6d4271b0822b01c2558
# Parent  68e2acd8c4cf81cdbe57c0a83bbafe43072cb9b5
Threaded open support in http file cache.

diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -69,6 +69,7 @@ struct ngx_http_cache_s {
     u_char                           key[NGX_HTTP_CACHE_KEY_LEN];
     u_char                           main[NGX_HTTP_CACHE_KEY_LEN];
 
+    ngx_open_file_info_t             of;
     ngx_file_uniq_t                  uniq;
     time_t                           valid_sec;
     time_t                           updating_sec;
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -18,6 +18,8 @@ static void ngx_http_file_cache_lock_wai
     ngx_http_cache_t *c);
 static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r,
     ngx_http_cache_t *c);
+static ngx_int_t ngx_http_file_cache_aio_open(ngx_http_request_t *r,
+    ngx_http_cache_t *c);
 static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r,
     ngx_http_cache_t *c);
 #if (NGX_HAVE_FILE_AIO)
@@ -264,13 +266,11 @@ ngx_http_file_cache_create_key(ngx_http_
 ngx_int_t
 ngx_http_file_cache_open(ngx_http_request_t *r)
 {
-    ngx_int_t                  rc, rv;
-    ngx_uint_t                 test;
-    ngx_http_cache_t          *c;
-    ngx_pool_cleanup_t        *cln;
-    ngx_open_file_info_t       of;
-    ngx_http_file_cache_t     *cache;
-    ngx_http_core_loc_conf_t  *clcf;
+    ngx_int_t               rc;
+    ngx_uint_t              test;
+    ngx_http_cache_t       *c;
+    ngx_pool_cleanup_t     *cln;
+    ngx_http_file_cache_t  *cache;
 
     c = r->cache;
 
@@ -315,7 +315,6 @@ ngx_http_file_cache_open(ngx_http_reques
 
         c->temp_file = 1;
         test = c->exists ? 1 : 0;
-        rv = NGX_DECLINED;
 
     } else { /* rc == NGX_DECLINED */
 
@@ -327,11 +326,10 @@ ngx_http_file_cache_open(ngx_http_reques
                 return NGX_HTTP_CACHE_SCARCE;
             }
 
-            rv = NGX_HTTP_CACHE_SCARCE;
+            c->temp_file = 0;
 
         } else {
             c->temp_file = 1;
-            rv = NGX_DECLINED;
         }
     }
 
@@ -340,62 +338,10 @@ ngx_http_file_cache_open(ngx_http_reques
     }
 
     if (!test) {
-        goto done;
-    }
-
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
-    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
-    of.uniq = c->uniq;
-    of.valid = clcf->open_file_cache_valid;
-    of.min_uses = clcf->open_file_cache_min_uses;
-    of.events = clcf->open_file_cache_events;
-    of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
-    of.read_ahead = clcf->read_ahead;
-
-    if (ngx_open_cached_file(clcf->open_file_cache, &c->file.name, &of, r->pool)
-        != NGX_OK)
-    {
-        switch (of.err) {
-
-        case 0:
-            return NGX_ERROR;
-
-        case NGX_ENOENT:
-        case NGX_ENOTDIR:
-            goto done;
-
-        default:
-            ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
-                          ngx_open_file_n " \"%s\" failed", c->file.name.data);
-            return NGX_ERROR;
-        }
-    }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http file cache fd: %d", of.fd);
-
-    c->file.fd = of.fd;
-    c->file.log = r->connection->log;
-    c->uniq = of.uniq;
-    c->length = of.size;
-    c->fs_size = (of.fs_size + cache->bsize - 1) / cache->bsize;
-
-    c->buf = ngx_create_temp_buf(r->pool, c->body_start);
-    if (c->buf == NULL) {
-        return NGX_ERROR;
-    }
-
-    return ngx_http_file_cache_read(r, c);
-
-done:
-
-    if (rv == NGX_DECLINED) {
         return ngx_http_file_cache_lock(r, c);
     }
 
-    return rv;
+    return ngx_http_file_cache_read(r, c);
 }
 
 
@@ -405,6 +351,10 @@ ngx_http_file_cache_lock(ngx_http_reques
     ngx_msec_t                 now, timer;
     ngx_http_file_cache_t     *cache;
 
+    if (!c->temp_file) {
+        return NGX_HTTP_CACHE_SCARCE;
+    }
+
     if (!c->lock) {
         return NGX_DECLINED;
     }
@@ -534,6 +484,12 @@ ngx_http_file_cache_read(ngx_http_reques
     ngx_http_file_cache_t         *cache;
     ngx_http_file_cache_header_t  *h;
 
+    rc = ngx_http_file_cache_aio_open(r, c);
+
+    if (rc != NGX_OK) {
+        return rc;
+    }
+
     n = ngx_http_file_cache_aio_read(r, c);
 
     if (n < 0) {
@@ -663,6 +619,88 @@ ngx_http_file_cache_read(ngx_http_reques
 }
 
 
+static ngx_int_t
+ngx_http_file_cache_aio_open(ngx_http_request_t *r, ngx_http_cache_t *c)
+{
+    ngx_int_t                  rc;
+    ngx_http_file_cache_t     *cache;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    if (c->file.fd != NGX_INVALID_FILE) {
+        return NGX_OK;
+    }
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (!c->reading) {
+        ngx_memzero(&c->of, sizeof(ngx_open_file_info_t));
+
+        c->of.uniq = c->uniq;
+        c->of.valid = clcf->open_file_cache_valid;
+        c->of.min_uses = clcf->open_file_cache_min_uses;
+        c->of.events = clcf->open_file_cache_events;
+        c->of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
+        c->of.read_ahead = clcf->read_ahead;
+
+#if (NGX_THREADS)
+        if (clcf->aio == NGX_HTTP_AIO_THREADS && clcf->aio_open) {
+            c->of.thread_task = c->thread_task;
+            c->of.thread_handler = ngx_http_cache_thread_handler;
+            c->of.thread_ctx = r;
+        }
+#endif
+    }
+
+    rc = ngx_open_cached_file(clcf->open_file_cache, &c->file.name, &c->of,
+                              r->pool);
+
+#if (NGX_THREADS)
+
+    if (rc == NGX_AGAIN) {
+        c->reading = 1;
+        return NGX_AGAIN;
+    }
+
+    c->reading = 0;
+
+#endif
+
+    if (rc != NGX_OK) {
+        switch (c->of.err) {
+
+        case NGX_OK:
+            return NGX_ERROR;
+
+        case NGX_ENOENT:
+        case NGX_ENOTDIR:
+            return ngx_http_file_cache_lock(r, c);
+
+        default:
+            ngx_log_error(NGX_LOG_CRIT, r->connection->log, c->of.err,
+                          ngx_open_file_n " \"%s\" failed", c->file.name.data);
+            return NGX_ERROR;
+        }
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http file cache fd: %d", c->of.fd);
+
+    cache = c->file_cache;
+    c->file.fd = c->of.fd;
+    c->file.log = r->connection->log;
+    c->uniq = c->of.uniq;
+    c->length = c->of.size;
+    c->fs_size = (c->of.fs_size + cache->bsize - 1) / cache->bsize;
+
+    c->buf = ngx_create_temp_buf(r->pool, c->body_start);
+    if (c->buf == NULL) {
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
 static ssize_t
 ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c)
 {
@@ -1229,6 +1267,7 @@ ngx_http_file_cache_reopen(ngx_http_requ
     ngx_shmtx_unlock(&cache->shpool->mutex);
 
     c->secondary = 1;
+    c->file.fd = NGX_INVALID_FILE;
     c->file.name.len = 0;
     c->body_start = c->buf->end - c->buf->start;
 


More information about the nginx-devel mailing list