]> git.kaiwu.me - nginx.git/commitdiff
Cache: introduced min_free cache clearing.
authorMaxim Dounin <mdounin@mdounin.ru>
Mon, 22 Jun 2020 15:03:00 +0000 (18:03 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Mon, 22 Jun 2020 15:03:00 +0000 (18:03 +0300)
Clearing cache based on free space left on a file system is
expected to allow better disk utilization in some cases, notably
when disk space might be also used for something other than nginx
cache (including nginx own temporary files) and while loading
cache (when cache size might be inaccurate for a while, effectively
disabling max_size cache clearing).

Based on a patch by Adam Bambuch.

src/http/ngx_http_cache.h
src/http/ngx_http_file_cache.c
src/os/unix/ngx_files.c
src/os/unix/ngx_files.h
src/os/win32/ngx_files.c
src/os/win32/ngx_files.h

index f9e96640998c62a6b4a02f1249df8b73f271b234..cd0b4bbf81410ebb06b1ae2e74fd8a4c0813061c 100644 (file)
@@ -160,6 +160,7 @@ struct ngx_http_file_cache_s {
 
     ngx_path_t                      *path;
 
+    off_t                            min_free;
     off_t                            max_size;
     size_t                           bsize;
 
index ecdf11e28797cad8b12e841cae325ac853ef31d8..e985f27b115bc633d96fe518d02c5e6ee1d383cd 100644 (file)
@@ -1959,7 +1959,7 @@ ngx_http_file_cache_manager(void *data)
 {
     ngx_http_file_cache_t  *cache = data;
 
-    off_t       size;
+    off_t       size, free;
     time_t      wait;
     ngx_msec_t  elapsed, next;
     ngx_uint_t  count, watermark;
@@ -1988,7 +1988,19 @@ ngx_http_file_cache_manager(void *data)
                        size, count, (ngx_int_t) watermark);
 
         if (size < cache->max_size && count < watermark) {
-            break;
+
+            if (!cache->min_free) {
+                break;
+            }
+
+            free = ngx_fs_available(cache->path->name.data);
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
+                           "http file cache free: %O", free);
+
+            if (free > cache->min_free) {
+                break;
+            }
         }
 
         wait = ngx_http_file_cache_forced_expire(cache);
@@ -2304,7 +2316,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char  *confp = conf;
 
-    off_t                   max_size;
+    off_t                   max_size, min_free;
     u_char                 *last, *p;
     time_t                  inactive;
     ssize_t                 size;
@@ -2341,6 +2353,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
     name.len = 0;
     size = 0;
     max_size = NGX_MAX_OFF_T_VALUE;
+    min_free = 0;
 
     value = cf->args->elts;
 
@@ -2476,6 +2489,29 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
             continue;
         }
 
+        if (ngx_strncmp(value[i].data, "min_free=", 9) == 0) {
+
+#if (NGX_WIN32 || NGX_HAVE_STATFS || NGX_HAVE_STATVFS)
+
+            s.len = value[i].len - 9;
+            s.data = value[i].data + 9;
+
+            min_free = ngx_parse_offset(&s);
+            if (min_free < 0) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "invalid min_free value \"%V\"", &value[i]);
+                return NGX_CONF_ERROR;
+            }
+
+#else
+            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                               "min_free is not supported "
+                               "on this platform, ignored");
+#endif
+
+            continue;
+        }
+
         if (ngx_strncmp(value[i].data, "loader_files=", 13) == 0) {
 
             loader_files = ngx_atoi(value[i].data + 13, value[i].len - 13);
@@ -2607,6 +2643,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
     cache->inactive = inactive;
     cache->max_size = max_size;
+    cache->min_free = min_free;
 
     caches = (ngx_array_t *) (confp + cmd->offset);
 
index 7e8e58fe71cace3da7f8f6d63b07854b25b08f50..1c82a8ead0c43ce909c0ebc912ddd1d04ffc17d7 100644 (file)
@@ -884,6 +884,19 @@ ngx_fs_bsize(u_char *name)
     return (size_t) fs.f_bsize;
 }
 
+
+off_t
+ngx_fs_available(u_char *name)
+{
+    struct statfs  fs;
+
+    if (statfs((char *) name, &fs) == -1) {
+        return NGX_MAX_OFF_T_VALUE;
+    }
+
+    return (off_t) fs.f_bavail * fs.f_bsize;
+}
+
 #elif (NGX_HAVE_STATVFS)
 
 size_t
@@ -908,6 +921,19 @@ ngx_fs_bsize(u_char *name)
     return (size_t) fs.f_frsize;
 }
 
+
+off_t
+ngx_fs_available(u_char *name)
+{
+    struct statvfs  fs;
+
+    if (statvfs((char *) name, &fs) == -1) {
+        return NGX_MAX_OFF_T_VALUE;
+    }
+
+    return (off_t) fs.f_bavail * fs.f_frsize;
+}
+
 #else
 
 size_t
@@ -916,4 +942,11 @@ ngx_fs_bsize(u_char *name)
     return 512;
 }
 
+
+off_t
+ngx_fs_available(u_char *name)
+{
+    return NGX_MAX_OFF_T_VALUE;
+}
+
 #endif
index 3e36984b998ee858fa373019bf535a192130cbdd..d084713b6e7f95b369caa7248c42459fb8161a1d 100644 (file)
@@ -349,6 +349,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
 #endif
 
 size_t ngx_fs_bsize(u_char *name);
+off_t ngx_fs_available(u_char *name);
 
 
 #if (NGX_HAVE_OPENAT)
index 0b131b58af25763e7ad5b2396a5138351834ca98..3017b45fed10b3db65e40202680497e712b5573b 100644 (file)
@@ -658,6 +658,19 @@ ngx_fs_bsize(u_char *name)
 }
 
 
+off_t
+ngx_fs_available(u_char *name)
+{
+    ULARGE_INTEGER  navail;
+
+    if (GetDiskFreeSpaceEx((const char *) name, &navail, NULL, NULL) == 0) {
+        return NGX_MAX_OFF_T_VALUE;
+    }
+
+    return (off_t) navail.QuadPart;
+}
+
+
 static ngx_int_t
 ngx_win32_check_filename(u_char *name, u_short *u, size_t len)
 {
index 6eb720e78ed9090390712f77571aff6a68a2a96e..a10839ba470b32cacbba0fb17ba0db891fb26208 100644 (file)
@@ -259,6 +259,7 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
 #define ngx_directio_off_n          "ngx_directio_off_n"
 
 size_t ngx_fs_bsize(u_char *name);
+off_t ngx_fs_available(u_char *name);
 
 
 #define ngx_stdout               GetStdHandle(STD_OUTPUT_HANDLE)