# HG changeset patch # User Jiří Setnička <jiri.setni...@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; _______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org