[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