10
10
#include <ngx_md5.h>
13
static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r,
15
static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r,
17
#if (NGX_HAVE_FILE_AIO)
18
static void ngx_http_cache_aio_event_handler(ngx_event_t *ev);
13
20
static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache,
14
21
ngx_http_cache_t *c);
22
static ngx_int_t ngx_http_file_cache_name(ngx_http_request_t *r,
15
24
static ngx_http_file_cache_node_t *
16
25
ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key);
17
26
static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,
149
ngx_http_file_cache_new(ngx_http_request_t *r)
153
c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
158
if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
163
c->file.log = r->connection->log;
164
c->file.fd = NGX_INVALID_FILE;
171
ngx_http_file_cache_create(ngx_http_request_t *r)
174
ngx_pool_cleanup_t *cln;
175
ngx_http_file_cache_t *cache;
177
ngx_http_file_cache_create_key(r);
180
cache = c->file_cache;
182
cln = ngx_pool_cleanup_add(r->pool, 0);
187
if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) {
191
cln->handler = ngx_http_file_cache_cleanup;
194
if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
139
203
ngx_http_file_cache_create_key(ngx_http_request_t *r)
174
238
ngx_http_file_cache_open(ngx_http_request_t *r)
180
ngx_uint_t cold, test;
183
ngx_pool_cleanup_t *cln;
184
ngx_open_file_info_t of;
185
ngx_http_file_cache_t *cache;
186
ngx_http_core_loc_conf_t *clcf;
187
ngx_http_file_cache_header_t *h;
241
ngx_uint_t cold, test;
243
ngx_pool_cleanup_t *cln;
244
ngx_open_file_info_t of;
245
ngx_http_file_cache_t *cache;
246
ngx_http_core_loc_conf_t *clcf;
251
return ngx_http_file_cache_read(r, c);
190
254
cache = c->file_cache;
192
256
cln = ngx_pool_cleanup_add(r->pool, 0);
245
c->file.name.len = path->name.len + 1 + path->len
246
+ 2 * NGX_HTTP_CACHE_KEY_LEN;
248
c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
249
if (c->file.name.data == NULL) {
307
if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
250
308
return NGX_ERROR;
253
ngx_memcpy(c->file.name.data, path->name.data, path->name.len);
255
p = c->file.name.data + path->name.len + 1 + path->len;
256
p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
259
ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);
261
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
262
"cache file: \"%s\"", c->file.name.data);
265
312
return NGX_DECLINED;
300
348
c->file.fd = of.fd;
301
349
c->file.log = r->connection->log;
303
353
c->buf = ngx_create_temp_buf(r->pool, c->body_start);
304
354
if (c->buf == NULL) {
305
355
return NGX_ERROR;
308
n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0);
310
if (n == NGX_ERROR) {
358
return ngx_http_file_cache_read(r, c);
363
ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c)
368
ngx_http_file_cache_t *cache;
369
ngx_http_file_cache_header_t *h;
371
n = ngx_http_file_cache_aio_read(r, c);
320
383
h = (ngx_http_file_cache_header_t *) c->buf->pos;
322
if (h->crc32 != c->crc32 || (size_t) h->header_start != c->header_start) {
385
if (h->crc32 != c->crc32) {
323
386
ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
324
387
"cache file \"%s\" has md5 collision", c->file.name.data);
325
388
return NGX_DECLINED;
449
ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c)
451
#if (NGX_HAVE_FILE_AIO)
453
ngx_http_core_loc_conf_t *clcf;
459
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
465
n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool);
467
if (n != NGX_AGAIN) {
471
c->file.aio->data = r;
472
c->file.aio->handler = ngx_http_cache_aio_event_handler;
483
return ngx_read_file(&c->file, c->buf->pos, c->body_start, 0);
487
#if (NGX_HAVE_FILE_AIO)
490
ngx_http_cache_aio_event_handler(ngx_event_t *ev)
492
ngx_event_aio_t *aio;
493
ngx_http_request_t *r;
501
r->connection->write->handler(r->connection->write);
383
508
ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
618
ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
625
c->file.name.len = path->name.len + 1 + path->len
626
+ 2 * NGX_HTTP_CACHE_KEY_LEN;
628
c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
629
if (c->file.name.data == NULL) {
633
ngx_memcpy(c->file.name.data, path->name.data, path->name.len);
635
p = c->file.name.data + path->name.len + 1 + path->len;
636
p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
639
ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);
641
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
642
"cache file: \"%s\"", c->file.name.data);
489
648
static ngx_http_file_cache_node_t *
490
649
ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key)
748
ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf)
908
ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf)
751
ngx_http_file_cache_t *cache;
910
ngx_http_file_cache_t *cache;
911
ngx_http_file_cache_node_t *fcn;
755
913
if (c->updated) {
761
917
cache = c->file_cache;
763
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
764
"http file cache free");
919
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
920
"http file cache free, fd: %d", c->file.fd);
766
922
ngx_shmtx_lock(&cache->shpool->mutex);
771
c->node->valid_sec = c->valid_sec;
772
c->node->valid_msec = c->valid_msec;
773
c->node->error = c->error;
932
fcn->error = c->error;
935
fcn->valid_sec = c->valid_sec;
936
fcn->valid_msec = c->valid_msec;
939
} else if (!fcn->exists && fcn->count == 0 && c->min_uses == 1) {
940
ngx_queue_remove(&fcn->queue);
941
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
942
ngx_slab_free_locked(cache->shpool, fcn);
776
c->node->updating = 0;
778
946
ngx_shmtx_unlock(&cache->shpool->mutex);
780
951
if (c->temp_file) {
781
952
if (tf && tf->file.fd != NGX_INVALID_FILE) {
782
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
953
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
783
954
"http file cache incomplete: \"%s\"",
784
955
tf->file.name.data);
786
957
if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) {
787
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
958
ngx_log_error(NGX_LOG_CRIT, c->file.log, ngx_errno,
788
959
ngx_delete_file_n " \"%s\" failed",
789
960
tf->file.name.data);
799
970
ngx_http_cache_t *c = data;
801
ngx_http_file_cache_t *cache;
803
972
if (c->updated) {
809
976
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
810
977
"http file cache cleanup");
980
ngx_log_error(NGX_LOG_ALERT, c->file.log, 0,
981
"stalled cache updating, error:%ui", c->error);
816
cache = c->file_cache;
818
ngx_shmtx_lock(&cache->shpool->mutex);
822
ngx_shmtx_unlock(&cache->shpool->mutex);
984
ngx_http_file_cache_free(c, NULL);
863
1025
fcn->count, fcn->exists,
864
1026
fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);
1028
if (fcn->count == 0) {
1029
ngx_http_file_cache_delete(cache, q, name);
880
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
881
ngx_slab_free_locked(cache->shpool, fcn);
886
ngx_http_file_cache_delete(cache, q, name);
947
1098
fcn->count, fcn->exists,
948
1099
fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);
952
p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
953
sizeof(ngx_rbtree_key_t));
955
len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
956
(void) ngx_hex_dump(p, fcn->key, len);
959
* abnormally exited workers may leave locked cache entries,
960
* and although it may be safe to remove them completely,
961
* we prefer to remove them from inactive queue and rbtree
962
* only, and to allow other leaks
966
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
968
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
969
"ignore long locked inactive cache entry %*s, count:%d",
970
2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
978
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
979
ngx_slab_free_locked(cache->shpool, fcn);
984
ngx_http_file_cache_delete(cache, q, name);
1101
if (fcn->count == 0) {
1102
ngx_http_file_cache_delete(cache, q, name);
1106
if (fcn->deleting) {
1110
p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
1111
sizeof(ngx_rbtree_key_t));
1112
len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
1113
(void) ngx_hex_dump(p, fcn->key, len);
1116
* abnormally exited workers may leave locked cache entries,
1117
* and although it may be safe to remove them completely,
1118
* we prefer to remove them from inactive queue and rbtree
1119
* only, and to allow other leaks
1122
ngx_queue_remove(q);
1123
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
1125
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
1126
"ignore long locked inactive cache entry %*s, count:%d",
1127
2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
987
1130
ngx_shmtx_unlock(&cache->shpool->mutex);
1004
1147
fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
1006
cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
1010
p = name + path->name.len + 1 + path->len;
1012
p = ngx_hex_dump(p, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t));
1014
len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
1015
p = ngx_hex_dump(p, fcn->key, len);
1018
ngx_queue_remove(q);
1020
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
1022
ngx_slab_free_locked(cache->shpool, fcn);
1024
ngx_shmtx_unlock(&cache->shpool->mutex);
1026
len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;
1028
ngx_create_hashed_filename(path, name, len);
1030
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1031
"http file cache expire: \"%s\"", name);
1033
if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1034
ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
1035
ngx_delete_file_n " \"%s\" failed", name);
1038
ngx_shmtx_lock(&cache->shpool->mutex);
1150
cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
1153
p = name + path->name.len + 1 + path->len;
1154
p = ngx_hex_dump(p, (u_char *) &fcn->node.key,
1155
sizeof(ngx_rbtree_key_t));
1156
len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
1157
p = ngx_hex_dump(p, fcn->key, len);
1162
ngx_shmtx_unlock(&cache->shpool->mutex);
1164
len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;
1165
ngx_create_hashed_filename(path, name, len);
1167
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1168
"http file cache expire: \"%s\"", name);
1170
if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1171
ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
1172
ngx_delete_file_n " \"%s\" failed", name);
1175
ngx_shmtx_lock(&cache->shpool->mutex);
1180
if (fcn->count == 0) {
1181
ngx_queue_remove(q);
1182
ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
1183
ngx_slab_free_locked(cache->shpool, fcn);