[PATCH 03 of 15] Cache: Shared memory for tempfile nodes

Jiří Setnička jiri.setnicka at cdn77.com
Fri Jan 28 16:31:55 UTC 2022


# HG changeset patch
# User Jiří Setnička  <jiri.setnicka at cdn77.com>
# Date 1643385660 -3600
#      Fri Jan 28 17:01:00 2022 +0100
# Node ID 535e503156cf141bf9471895468423e82f68c8bb
# Parent  64ff9068a0bd89712a0ae6fc589a881869663642
Cache: Shared memory for tempfile nodes
New option for `proxy_cache_path`: `tf_zone=name:size` (defaults to key zone
name with `_tf` suffix and 10M size). It creates a shared memory zone used to
store tempfiles nodes.

Will be used to track updated state of multiple tempfiles of the same cache file.

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
@@ -156,10 +156,20 @@ typedef struct {
 } ngx_http_file_cache_sh_t;
 
 
+typedef struct {
+    ngx_rbtree_t                     rbtree;
+    ngx_rbtree_node_t                sentinel;
+    ngx_uint_t                       count;
+} ngx_http_file_cache_tf_sh_t;
+
+
 struct ngx_http_file_cache_s {
     ngx_http_file_cache_sh_t        *sh;
     ngx_slab_pool_t                 *shpool;
 
+    ngx_http_file_cache_tf_sh_t     *tf_sh;
+    ngx_slab_pool_t                 *tf_shpool;
+
     ngx_path_t                      *path;
 
     off_t                            min_free;
@@ -181,6 +191,7 @@ struct ngx_http_file_cache_s {
     ngx_msec_t                       manager_threshold;
 
     ngx_shm_zone_t                  *shm_zone;
+    ngx_shm_zone_t                  *tf_shm_zone;
 
     ngx_uint_t                       use_temp_path;
                                      /* unsigned use_temp_path:1 */
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
@@ -172,6 +172,61 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
 }
 
 
+static ngx_int_t
+ngx_http_file_cache_init_tf(ngx_shm_zone_t *shm_zone, void *data)
+{
+    ngx_http_file_cache_t  *ocache = data;
+
+    size_t                  len;
+    ngx_http_file_cache_t  *cache;
+
+    cache = shm_zone->data;
+
+    if (ocache) {
+        /* cache path and level already checked by ngx_http_file_cache_init */
+
+        cache->tf_sh = ocache->tf_sh;
+        cache->tf_shpool = ocache->tf_shpool;
+
+        return NGX_OK;
+    }
+
+    cache->tf_shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
+
+    if (shm_zone->shm.exists) {
+        cache->tf_sh = cache->tf_shpool->data;
+
+        return NGX_OK;
+    }
+
+    cache->tf_sh = ngx_slab_alloc(cache->tf_shpool, sizeof(ngx_http_file_cache_tf_sh_t));
+    if (cache->tf_sh == NULL) {
+        return NGX_ERROR;
+    }
+
+    cache->tf_shpool->data = cache->tf_sh;
+
+    ngx_rbtree_init(&cache->tf_sh->rbtree, &cache->tf_sh->sentinel,
+                    ngx_http_file_cache_rbtree_insert_value);
+
+    cache->tf_sh->count = 0;
+
+    len = sizeof(" in cache tf zone \"\"") + shm_zone->shm.name.len;
+
+    cache->tf_shpool->log_ctx = ngx_slab_alloc(cache->tf_shpool, len);
+    if (cache->tf_shpool->log_ctx == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_sprintf(cache->tf_shpool->log_ctx, " in cache tf zone \"%V\"%Z",
+                &shm_zone->shm.name);
+
+    cache->tf_shpool->log_nomem = 0;
+
+    return NGX_OK;
+}
+
+
 ngx_int_t
 ngx_http_file_cache_new(ngx_http_request_t *r)
 {
@@ -2322,8 +2377,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t 
     off_t                   max_size, min_free;
     u_char                 *last, *p;
     time_t                  inactive;
-    ssize_t                 size;
-    ngx_str_t               s, name, *value;
+    ssize_t                 size, tf_size;
+    ngx_str_t               s, name, tf_name, *value;
     ngx_int_t               loader_files, manager_files;
     ngx_msec_t              loader_sleep, manager_sleep, loader_threshold,
                             manager_threshold;
@@ -2354,7 +2409,9 @@ ngx_http_file_cache_set_slot(ngx_conf_t 
     manager_threshold = 200;
 
     name.len = 0;
+    tf_name.len = 0;
     size = 0;
+    tf_size = 10000000;
     max_size = NGX_MAX_OFF_T_VALUE;
     min_free = 0;
 
@@ -2462,6 +2519,40 @@ ngx_http_file_cache_set_slot(ngx_conf_t 
             continue;
         }
 
+        if (ngx_strncmp(value[i].data, "tf_zone=", 8) == 0) {
+
+            tf_name.data = value[i].data + 8;
+
+            p = (u_char *) ngx_strchr(tf_name.data, ':');
+
+            if (p == NULL) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "invalid tf_zone size \"%V\"", &value[i]);
+                return NGX_CONF_ERROR;
+            }
+
+            tf_name.len = p - tf_name.data;
+
+            s.data = p + 1;
+            s.len = value[i].data + value[i].len - s.data;
+
+            tf_size = ngx_parse_size(&s);
+
+            if (tf_size == NGX_ERROR) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "invalid tf_zone size \"%V\"", &value[i]);
+                return NGX_CONF_ERROR;
+            }
+
+            if (tf_size < (ssize_t) (2 * ngx_pagesize)) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "tf_zone \"%V\" is too small", &value[i]);
+                return NGX_CONF_ERROR;
+            }
+
+            continue;
+        }
+
         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
 
             s.len = value[i].len - 9;
@@ -2611,6 +2702,17 @@ ngx_http_file_cache_set_slot(ngx_conf_t 
         return NGX_CONF_ERROR;
     }
 
+    if (tf_name.len == 0) {
+        tf_name.len = name.len + 3;
+        tf_name.data = ngx_alloc(tf_name.len, cf->log);
+        if (tf_name.data == NULL) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "Cannot allocate tf_zone name");
+            return NGX_CONF_ERROR;
+        }
+        ngx_sprintf(tf_name.data, "%V_tf", &name);
+    }
+
     cache->path->manager = ngx_http_file_cache_manager;
     cache->path->loader = ngx_http_file_cache_loader;
     cache->path->data = cache;
@@ -2642,6 +2744,21 @@ ngx_http_file_cache_set_slot(ngx_conf_t 
     cache->shm_zone->init = ngx_http_file_cache_init;
     cache->shm_zone->data = cache;
 
+    cache->tf_shm_zone = ngx_shared_memory_add(cf, &tf_name, tf_size, cmd->post);
+    if (cache->tf_shm_zone == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (cache->tf_shm_zone->data) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "duplicate zone \"%V\"", &tf_name);
+        return NGX_CONF_ERROR;
+    }
+
+
+    cache->tf_shm_zone->init = ngx_http_file_cache_init_tf;
+    cache->tf_shm_zone->data = cache;
+
     cache->use_temp_path = use_temp_path;
 
     cache->inactive = inactive;


More information about the nginx-devel mailing list