[PATCH 08 of 15] Tempfiles: Mechanism of opening tempfiles used for serving paralell requests

Jiří Setnička jiri.setnicka at cdn77.com
Fri Jan 28 16:32:00 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 101a15e01c313f1327937c84fbf143f875d868de
# Parent  10e917f6ddb56c338f9597b76a68cdbf21d8f8e8
Tempfiles: Mechanism of opening tempfiles used for serving paralell requests
This commit adds mechanism of choosing and opening tempfile. For the
first request it acts like before, fcn->updating is set and request is
downloaded to tempfile and served at the same moment.

Other paralell requests will have c->waiting flag set and they try to
use tempfile number to locate and open the tempfile used by the primary
request.

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
@@ -11,6 +11,10 @@
 #include <ngx_md5.h>
 
 
+static ngx_int_t ngx_http_file_cache_open_file(ngx_http_request_t *r,
+    ngx_str_t *filename);
+static ngx_int_t ngx_http_file_cache_open_temp_file(ngx_http_request_t *r,
+    ngx_http_cache_t *c);
 static ngx_int_t ngx_http_file_cache_lock(ngx_http_request_t *r,
     ngx_http_cache_t *c);
 static void ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev);
@@ -369,13 +373,14 @@ ngx_http_file_cache_open(ngx_http_reques
     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;
 
     c = r->cache;
 
     if (c->waiting) {
+        if (c->serve_tempfile) {
+            return ngx_http_file_cache_open_temp_file(r, c);
+        }
         return NGX_AGAIN;
     }
 
@@ -446,6 +451,32 @@ ngx_http_file_cache_open(ngx_http_reques
         goto done;
     }
 
+    rc = ngx_http_file_cache_open_file(r, &c->file.name);
+    if (rc != NGX_DECLINED) {
+        return rc;
+    }
+
+done:
+
+    if (rv == NGX_DECLINED) {
+        return ngx_http_file_cache_lock(r, c);
+    }
+
+    return rv;
+}
+
+
+static ngx_int_t
+ngx_http_file_cache_open_file(ngx_http_request_t *r, ngx_str_t *filename)
+{
+    ngx_http_cache_t          *c;
+    ngx_open_file_info_t       of;
+    ngx_http_file_cache_t     *cache;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    c = r->cache;
+    cache = c->file_cache;
+
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
@@ -457,7 +488,7 @@ ngx_http_file_cache_open(ngx_http_reques
     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)
+    if (ngx_open_cached_file(clcf->open_file_cache, filename, &of, r->pool)
         != NGX_OK)
     {
         switch (of.err) {
@@ -467,7 +498,7 @@ ngx_http_file_cache_open(ngx_http_reques
 
         case NGX_ENOENT:
         case NGX_ENOTDIR:
-            goto done;
+            return NGX_DECLINED;
 
         default:
             ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
@@ -491,24 +522,90 @@ ngx_http_file_cache_open(ngx_http_reques
     }
 
     return ngx_http_file_cache_read(r, c);
+}
+
+
+static ngx_int_t
+ngx_http_file_cache_open_temp_file(ngx_http_request_t *r, ngx_http_cache_t *c)
+{
+    u_char                 *p;
+    ngx_int_t               rc;
+    ngx_file_t              temp_file;
+    ngx_uint_t              tf_number;
+    ngx_http_file_cache_t  *cache;
+
+    cache = c->file_cache;
+
+    if (c->tf_node) {
+        return NGX_OK;
+    }
+
+    ngx_shmtx_lock(&cache->shpool->mutex);
+
+    tf_number = c->node->tf_number;
+
+    if (tf_number > 0) {
+        c->tf_node = ngx_http_file_cache_tf_lookup(cache, tf_number);
+        if (c->tf_node == NULL) {
+            ngx_shmtx_unlock(&cache->shpool->mutex);
+            ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+                "Missing tf_node for %d, probably full tf_zone", tf_number);
+            return NGX_DECLINED;
+        }
+
+        c->tf_node->count++;
+    }
+
+    ngx_shmtx_unlock(&cache->shpool->mutex);
+
+    if (c->tf_node == NULL) {
+        rc = ngx_http_file_cache_wait_for_temp_file(r, c);
+
+        if (rc == NGX_DONE || rc == NGX_DECLINED) {
+            goto done;
+        }
+
+        return rc;
+    }
+
+    temp_file.name.len = c->file.name.len + 10 + 1;
+    temp_file.name.data = ngx_pnalloc(r->pool, temp_file.name.len + 1);
+    if (temp_file.name.data == NULL) {
+        return NGX_ERROR;
+    }
+
+    p = ngx_cpymem(temp_file.name.data, c->file.name.data, c->file.name.len);
+    ngx_sprintf(p, ".%010uD%Z", tf_number);
+
+    rc = ngx_http_file_cache_open_file(r, &temp_file.name);
+
+    if (rc == NGX_DECLINED) {
+        /* tempfile was moved meantime */
+        ngx_shmtx_lock(&cache->shpool->mutex);
+
+        if (c->tf_node != NULL) {
+            ngx_http_file_cache_tf_delete(c, cache);
+        }
+
+        ngx_shmtx_unlock(&cache->shpool->mutex);
+        goto done;
+    }
+
+    return rc;
 
 done:
-
-    if (rv == NGX_DECLINED) {
-        return ngx_http_file_cache_lock(r, c);
-    }
-
-    return rv;
+    c->waiting = 0;
+    return ngx_http_file_cache_open_file(r, &c->file.name);
 }
 
 
 static ngx_int_t
 ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
 {
-    ngx_msec_t                 now, timer;
-    ngx_http_file_cache_t     *cache;
-
-    if (!c->lock) {
+    ngx_msec_t              now, timer;
+    ngx_http_file_cache_t  *cache;
+
+    if (!c->lock && !c->serve_tempfile) {
         return NGX_DECLINED;
     }
 
@@ -522,7 +619,7 @@ ngx_http_file_cache_lock(ngx_http_reques
 
     if (!c->node->updating || (ngx_msec_int_t) timer <= 0) {
         c->node->updating = 1;
-        c->node->lock_time = now + c->lock_age;
+        c->node->lock_time = now + (c->lock ? c->lock_age : c->tempfile_timeout);
         c->updating = 1;
         c->lock_time = c->node->lock_time;
     }
@@ -537,27 +634,40 @@ ngx_http_file_cache_lock(ngx_http_reques
         return NGX_DECLINED;
     }
 
-    if (c->lock_timeout == 0) {
+    if (c->lock && c->lock_timeout == 0) {
+        return NGX_HTTP_CACHE_SCARCE;
+    }
+
+    if (c->serve_tempfile && c->tempfile_timeout == 0) {
         return NGX_HTTP_CACHE_SCARCE;
     }
 
     c->waiting = 1;
 
     if (c->wait_time == 0) {
-        c->wait_time = now + c->lock_timeout;
-
-        c->wait_event.handler = ngx_http_file_cache_lock_wait_handler;
+        if (c->lock) {
+            c->wait_time = now + c->lock_timeout;
+            c->wait_event.handler = ngx_http_file_cache_lock_wait_handler;
+        } else {
+            c->wait_time = now + c->tempfile_timeout;
+            c->wait_event.handler = ngx_http_file_cache_tempfile_wait_handler;
+        }
         c->wait_event.data = r;
         c->wait_event.log = r->connection->log;
     }
 
-    timer = c->wait_time - now;
-
-    ngx_add_timer(&c->wait_event, (timer > 500) ? 500 : timer);
-
-    r->main->blocked++;
-
-    return NGX_AGAIN;
+    if (c->lock) {
+        timer = c->wait_time - now;
+
+        ngx_add_timer(&c->wait_event, timer > 500 ? 500 : timer);
+
+        r->main->blocked++;
+
+        return NGX_AGAIN;
+    }
+
+    /* Tempfile may be already there, try it immediately */
+    return ngx_http_file_cache_open_temp_file(r, c);
 }
 
 
@@ -829,10 +939,15 @@ ngx_http_file_cache_read(ngx_http_reques
         } else {
             c->node->updating = 1;
             c->updating = 1;
+            c->node->lock_time = ngx_current_msec + (c->lock ? c->lock_age : c->tempfile_timeout);
             c->lock_time = c->node->lock_time;
             rc = NGX_HTTP_CACHE_STALE;
         }
 
+        if (c->tf_node != NULL) {
+            ngx_http_file_cache_tf_delete(c, cache);
+        }
+
         ngx_shmtx_unlock(&cache->shpool->mutex);
 
         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1464,6 +1579,7 @@ ngx_http_file_cache_reopen(ngx_http_requ
     ngx_shmtx_unlock(&cache->shpool->mutex);
 
     c->secondary = 1;
+    c->waiting = 0;
     c->file.name.len = 0;
     c->body_start = c->buffer_size;
 


More information about the nginx-devel mailing list