comparison src/http/ngx_http_file_cache.c @ 635:e67b227c8dbb default tip

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:07:55 +0400
parents b4dcae568a2a
children
comparison
equal deleted inserted replaced
578:f3a9e57d2e17 635:e67b227c8dbb
17 #if (NGX_HAVE_FILE_AIO) 17 #if (NGX_HAVE_FILE_AIO)
18 static void ngx_http_cache_aio_event_handler(ngx_event_t *ev); 18 static void ngx_http_cache_aio_event_handler(ngx_event_t *ev);
19 #endif 19 #endif
20 static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, 20 static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache,
21 ngx_http_cache_t *c); 21 ngx_http_cache_t *c);
22 static ngx_int_t ngx_http_file_cache_name(ngx_http_request_t *r,
23 ngx_path_t *path);
22 static ngx_http_file_cache_node_t * 24 static ngx_http_file_cache_node_t *
23 ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key); 25 ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key);
24 static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, 26 static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,
25 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 27 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
26 static void ngx_http_file_cache_cleanup(void *data); 28 static void ngx_http_file_cache_cleanup(void *data);
42 ngx_str_t *path); 44 ngx_str_t *path);
43 45
44 46
45 ngx_str_t ngx_http_cache_status[] = { 47 ngx_str_t ngx_http_cache_status[] = {
46 ngx_string("MISS"), 48 ngx_string("MISS"),
49 ngx_string("BYPASS"),
47 ngx_string("EXPIRED"), 50 ngx_string("EXPIRED"),
48 ngx_string("STALE"), 51 ngx_string("STALE"),
49 ngx_string("UPDATING"), 52 ngx_string("UPDATING"),
50 ngx_string("HIT") 53 ngx_string("HIT")
51 }; 54 };
140 143
141 return NGX_OK; 144 return NGX_OK;
142 } 145 }
143 146
144 147
148 ngx_int_t
149 ngx_http_file_cache_new(ngx_http_request_t *r)
150 {
151 ngx_http_cache_t *c;
152
153 c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
154 if (c == NULL) {
155 return NGX_ERROR;
156 }
157
158 if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
159 return NGX_ERROR;
160 }
161
162 r->cache = c;
163 c->file.log = r->connection->log;
164 c->file.fd = NGX_INVALID_FILE;
165
166 return NGX_OK;
167 }
168
169
170 ngx_int_t
171 ngx_http_file_cache_create(ngx_http_request_t *r)
172 {
173 ngx_http_cache_t *c;
174 ngx_pool_cleanup_t *cln;
175 ngx_http_file_cache_t *cache;
176
177 ngx_http_file_cache_create_key(r);
178
179 c = r->cache;
180 cache = c->file_cache;
181
182 cln = ngx_pool_cleanup_add(r->pool, 0);
183 if (cln == NULL) {
184 return NGX_ERROR;
185 }
186
187 if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) {
188 return NGX_ERROR;
189 }
190
191 cln->handler = ngx_http_file_cache_cleanup;
192 cln->data = c;
193
194 if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
195 return NGX_ERROR;
196 }
197
198 return NGX_OK;
199 }
200
201
145 void 202 void
146 ngx_http_file_cache_create_key(ngx_http_request_t *r) 203 ngx_http_file_cache_create_key(ngx_http_request_t *r)
147 { 204 {
148 size_t len; 205 size_t len;
149 ngx_str_t *key; 206 ngx_str_t *key;
178 235
179 236
180 ngx_int_t 237 ngx_int_t
181 ngx_http_file_cache_open(ngx_http_request_t *r) 238 ngx_http_file_cache_open(ngx_http_request_t *r)
182 { 239 {
183 u_char *p;
184 ngx_int_t rc, rv; 240 ngx_int_t rc, rv;
185 ngx_uint_t cold, test; 241 ngx_uint_t cold, test;
186 ngx_path_t *path;
187 ngx_http_cache_t *c; 242 ngx_http_cache_t *c;
188 ngx_pool_cleanup_t *cln; 243 ngx_pool_cleanup_t *cln;
189 ngx_open_file_info_t of; 244 ngx_open_file_info_t of;
190 ngx_http_file_cache_t *cache; 245 ngx_http_file_cache_t *cache;
191 ngx_http_core_loc_conf_t *clcf; 246 ngx_http_core_loc_conf_t *clcf;
247 test = cold ? 1 : 0; 302 test = cold ? 1 : 0;
248 rv = NGX_DECLINED; 303 rv = NGX_DECLINED;
249 } 304 }
250 } 305 }
251 306
252 path = cache->path; 307 if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
253
254 c->file.name.len = path->name.len + 1 + path->len
255 + 2 * NGX_HTTP_CACHE_KEY_LEN;
256
257 c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
258 if (c->file.name.data == NULL) {
259 return NGX_ERROR; 308 return NGX_ERROR;
260 } 309 }
261
262 ngx_memcpy(c->file.name.data, path->name.data, path->name.len);
263
264 p = c->file.name.data + path->name.len + 1 + path->len;
265 p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN);
266 *p = '\0';
267
268 ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);
269
270 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
271 "cache file: \"%s\"", c->file.name.data);
272 310
273 if (!test) { 311 if (!test) {
274 return NGX_DECLINED; 312 return NGX_DECLINED;
275 } 313 }
276 314
328 ssize_t n; 366 ssize_t n;
329 ngx_int_t rc; 367 ngx_int_t rc;
330 ngx_http_file_cache_t *cache; 368 ngx_http_file_cache_t *cache;
331 ngx_http_file_cache_header_t *h; 369 ngx_http_file_cache_header_t *h;
332 370
333 c = r->cache;
334
335 n = ngx_http_file_cache_aio_read(r, c); 371 n = ngx_http_file_cache_aio_read(r, c);
336 372
337 if (n < 0) { 373 if (n < 0) {
338 return n; 374 return n;
339 } 375 }
390 if (c->node->updating) { 426 if (c->node->updating) {
391 rc = NGX_HTTP_CACHE_UPDATING; 427 rc = NGX_HTTP_CACHE_UPDATING;
392 428
393 } else { 429 } else {
394 c->node->updating = 1; 430 c->node->updating = 1;
431 c->updating = 1;
395 rc = NGX_HTTP_CACHE_STALE; 432 rc = NGX_HTTP_CACHE_STALE;
396 } 433 }
397 434
398 ngx_shmtx_unlock(&cache->shpool->mutex); 435 ngx_shmtx_unlock(&cache->shpool->mutex);
399 436
478 fcn = ngx_http_file_cache_lookup(cache, c->key); 515 fcn = ngx_http_file_cache_lookup(cache, c->key);
479 516
480 if (fcn) { 517 if (fcn) {
481 ngx_queue_remove(&fcn->queue); 518 ngx_queue_remove(&fcn->queue);
482 519
520 fcn->uses++;
521 fcn->count++;
522
483 if (fcn->error) { 523 if (fcn->error) {
484 524
485 if (fcn->valid_sec < ngx_time()) { 525 if (fcn->valid_sec < ngx_time()) {
486 goto renew; 526 goto renew;
487 } 527 }
488 528
489 rc = NGX_OK; 529 rc = NGX_OK;
490 530
491 goto done; 531 goto done;
492 } 532 }
493
494 fcn->uses++;
495 fcn->count++;
496 533
497 if (fcn->exists) { 534 if (fcn->exists) {
498 535
499 c->exists = fcn->exists; 536 c->exists = fcn->exists;
500 c->body_start = fcn->body_start; 537 c->body_start = fcn->body_start;
540 ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)], 577 ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],
541 NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t)); 578 NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
542 579
543 ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node); 580 ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
544 581
545 renew:
546
547 rc = NGX_DECLINED;
548
549 fcn->uses = 1; 582 fcn->uses = 1;
550 fcn->count = 1; 583 fcn->count = 1;
584 fcn->updating = 0;
585 fcn->deleting = 0;
586
587 renew:
588
589 rc = NGX_DECLINED;
590
551 fcn->valid_msec = 0; 591 fcn->valid_msec = 0;
552 fcn->error = 0; 592 fcn->error = 0;
553 fcn->exists = 0; 593 fcn->exists = 0;
554 fcn->valid_sec = 0; 594 fcn->valid_sec = 0;
555 fcn->uniq = 0; 595 fcn->uniq = 0;
572 612
573 return rc; 613 return rc;
574 } 614 }
575 615
576 616
617 static ngx_int_t
618 ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
619 {
620 u_char *p;
621 ngx_http_cache_t *c;
622
623 c = r->cache;
624
625 c->file.name.len = path->name.len + 1 + path->len
626 + 2 * NGX_HTTP_CACHE_KEY_LEN;
627
628 c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1);
629 if (c->file.name.data == NULL) {
630 return NGX_ERROR;
631 }
632
633 ngx_memcpy(c->file.name.data, path->name.data, path->name.len);
634
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);
637 *p = '\0';
638
639 ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len);
640
641 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
642 "cache file: \"%s\"", c->file.name.data);
643
644 return NGX_OK;
645 }
646
647
577 static ngx_http_file_cache_node_t * 648 static ngx_http_file_cache_node_t *
578 ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key) 649 ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key)
579 { 650 {
580 ngx_int_t rc; 651 ngx_int_t rc;
581 ngx_rbtree_key_t node_key; 652 ngx_rbtree_key_t node_key;
722 793
723 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 794 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
724 "http file cache update"); 795 "http file cache update");
725 796
726 c->updated = 1; 797 c->updated = 1;
798 c->updating = 0;
727 799
728 cache = c->file_cache; 800 cache = c->file_cache;
729 801
730 uniq = 0; 802 uniq = 0;
731 length = 0; 803 length = 0;
831 return ngx_http_output_filter(r, &out); 903 return ngx_http_output_filter(r, &out);
832 } 904 }
833 905
834 906
835 void 907 void
836 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)
837 { 909 {
838 ngx_http_cache_t *c; 910 ngx_http_file_cache_t *cache;
839 ngx_http_file_cache_t *cache; 911 ngx_http_file_cache_node_t *fcn;
840
841 c = r->cache;
842 912
843 if (c->updated) { 913 if (c->updated) {
844 return; 914 return;
845 } 915 }
846 916
917 cache = c->file_cache;
918
919 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
920 "http file cache free, fd: %d", c->file.fd);
921
922 ngx_shmtx_lock(&cache->shpool->mutex);
923
924 fcn = c->node;
925 fcn->count--;
926
927 if (c->updating) {
928 fcn->updating = 0;
929 }
930
931 if (c->error) {
932 fcn->error = c->error;
933
934 if (c->valid_sec) {
935 fcn->valid_sec = c->valid_sec;
936 fcn->valid_msec = c->valid_msec;
937 }
938
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);
943 c->node = NULL;
944 }
945
946 ngx_shmtx_unlock(&cache->shpool->mutex);
947
847 c->updated = 1; 948 c->updated = 1;
848 949 c->updating = 0;
849 cache = c->file_cache;
850
851 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
852 "http file cache free");
853
854 ngx_shmtx_lock(&cache->shpool->mutex);
855
856 c->node->count--;
857
858 if (c->error) {
859 c->node->valid_sec = c->valid_sec;
860 c->node->valid_msec = c->valid_msec;
861 c->node->error = c->error;
862 }
863
864 c->node->updating = 0;
865
866 ngx_shmtx_unlock(&cache->shpool->mutex);
867 950
868 if (c->temp_file) { 951 if (c->temp_file) {
869 if (tf && tf->file.fd != NGX_INVALID_FILE) { 952 if (tf && tf->file.fd != NGX_INVALID_FILE) {
870 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 953 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
871 "http file cache incomplete: \"%s\"", 954 "http file cache incomplete: \"%s\"",
872 tf->file.name.data); 955 tf->file.name.data);
873 956
874 if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) { 957 if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) {
875 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, 958 ngx_log_error(NGX_LOG_CRIT, c->file.log, ngx_errno,
876 ngx_delete_file_n " \"%s\" failed", 959 ngx_delete_file_n " \"%s\" failed",
877 tf->file.name.data); 960 tf->file.name.data);
878 } 961 }
879 } 962 }
880 } 963 }
884 static void 967 static void
885 ngx_http_file_cache_cleanup(void *data) 968 ngx_http_file_cache_cleanup(void *data)
886 { 969 {
887 ngx_http_cache_t *c = data; 970 ngx_http_cache_t *c = data;
888 971
889 ngx_http_file_cache_t *cache;
890
891 if (c->updated) { 972 if (c->updated) {
892 return; 973 return;
893 } 974 }
894 975
895 c->updated = 1;
896
897 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->file.log, 0, 976 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
898 "http file cache cleanup"); 977 "http file cache cleanup");
899 978
900 if (c->error) { 979 if (c->updating) {
901 return; 980 ngx_log_error(NGX_LOG_ALERT, c->file.log, 0,
902 } 981 "stalled cache updating, error:%ui", c->error);
903 982 }
904 cache = c->file_cache; 983
905 984 ngx_http_file_cache_free(c, NULL);
906 ngx_shmtx_lock(&cache->shpool->mutex);
907
908 c->node->count--;
909
910 ngx_shmtx_unlock(&cache->shpool->mutex);
911 } 985 }
912 986
913 987
914 static time_t 988 static time_t
915 ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) 989 ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache)
934 } 1008 }
935 1009
936 ngx_memcpy(name, path->name.data, path->name.len); 1010 ngx_memcpy(name, path->name.data, path->name.len);
937 1011
938 wait = 10; 1012 wait = 10;
939 tries = 0; 1013 tries = 20;
940 1014
941 ngx_shmtx_lock(&cache->shpool->mutex); 1015 ngx_shmtx_lock(&cache->shpool->mutex);
942 1016
943 for (q = ngx_queue_last(&cache->sh->queue); 1017 for (q = ngx_queue_last(&cache->sh->queue);
944 q != ngx_queue_sentinel(&cache->sh->queue); 1018 q != ngx_queue_sentinel(&cache->sh->queue);
949 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 1023 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
950 "http file cache forced expire: #%d %d %02xd%02xd%02xd%02xd", 1024 "http file cache forced expire: #%d %d %02xd%02xd%02xd%02xd",
951 fcn->count, fcn->exists, 1025 fcn->count, fcn->exists,
952 fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); 1026 fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);
953 1027
954 if (fcn->count) { 1028 if (fcn->count == 0) {
955 1029 ngx_http_file_cache_delete(cache, q, name);
956 if (tries++ < 20) { 1030 wait = 0;
1031
1032 } else {
1033 if (--tries) {
957 continue; 1034 continue;
958 } 1035 }
959 1036
960 wait = 1; 1037 wait = 1;
961 1038 }
962 break;
963 }
964
965 if (!fcn->exists) {
966
967 ngx_queue_remove(q);
968 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
969 ngx_slab_free_locked(cache->shpool, fcn);
970
971 break;
972 }
973
974 ngx_http_file_cache_delete(cache, q, name);
975 1039
976 break; 1040 break;
977 } 1041 }
978 1042
979 ngx_shmtx_unlock(&cache->shpool->mutex); 1043 ngx_shmtx_unlock(&cache->shpool->mutex);
1033 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 1097 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1034 "http file cache expire: #%d %d %02xd%02xd%02xd%02xd", 1098 "http file cache expire: #%d %d %02xd%02xd%02xd%02xd",
1035 fcn->count, fcn->exists, 1099 fcn->count, fcn->exists,
1036 fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); 1100 fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]);
1037 1101
1038 if (fcn->count) { 1102 if (fcn->count == 0) {
1039 1103 ngx_http_file_cache_delete(cache, q, name);
1040 p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
1041 sizeof(ngx_rbtree_key_t));
1042
1043 len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
1044 (void) ngx_hex_dump(p, fcn->key, len);
1045
1046 /*
1047 * abnormally exited workers may leave locked cache entries,
1048 * and although it may be safe to remove them completely,
1049 * we prefer to remove them from inactive queue and rbtree
1050 * only, and to allow other leaks
1051 */
1052
1053 ngx_queue_remove(q);
1054 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
1055
1056 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
1057 "ignore long locked inactive cache entry %*s, count:%d",
1058 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
1059
1060 continue; 1104 continue;
1061 } 1105 }
1062 1106
1063 if (!fcn->exists) { 1107 if (fcn->deleting) {
1064
1065 ngx_queue_remove(q);
1066 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
1067 ngx_slab_free_locked(cache->shpool, fcn);
1068
1069 continue; 1108 continue;
1070 } 1109 }
1071 1110
1072 ngx_http_file_cache_delete(cache, q, name); 1111 p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
1112 sizeof(ngx_rbtree_key_t));
1113 len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
1114 (void) ngx_hex_dump(p, fcn->key, len);
1115
1116 /*
1117 * abnormally exited workers may leave locked cache entries,
1118 * and although it may be safe to remove them completely,
1119 * we prefer to remove them from inactive queue and rbtree
1120 * only, and to allow other leaks
1121 */
1122
1123 ngx_queue_remove(q);
1124 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
1125
1126 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
1127 "ignore long locked inactive cache entry %*s, count:%d",
1128 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
1073 } 1129 }
1074 1130
1075 ngx_shmtx_unlock(&cache->shpool->mutex); 1131 ngx_shmtx_unlock(&cache->shpool->mutex);
1076 1132
1077 ngx_free(name); 1133 ngx_free(name);
1089 ngx_path_t *path; 1145 ngx_path_t *path;
1090 ngx_http_file_cache_node_t *fcn; 1146 ngx_http_file_cache_node_t *fcn;
1091 1147
1092 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); 1148 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
1093 1149
1094 cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize; 1150 if (fcn->exists) {
1095 1151 cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
1096 path = cache->path; 1152
1097 1153 path = cache->path;
1098 p = name + path->name.len + 1 + path->len; 1154 p = name + path->name.len + 1 + path->len;
1099 1155 p = ngx_hex_dump(p, (u_char *) &fcn->node.key,
1100 p = ngx_hex_dump(p, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t)); 1156 sizeof(ngx_rbtree_key_t));
1101 1157 len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
1102 len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); 1158 p = ngx_hex_dump(p, fcn->key, len);
1103 p = ngx_hex_dump(p, fcn->key, len); 1159 *p = '\0';
1104 *p = '\0'; 1160
1105 1161 fcn->count++;
1106 ngx_queue_remove(q); 1162 fcn->deleting = 1;
1107 1163 ngx_shmtx_unlock(&cache->shpool->mutex);
1108 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); 1164
1109 1165 len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;
1110 ngx_slab_free_locked(cache->shpool, fcn); 1166 ngx_create_hashed_filename(path, name, len);
1111 1167
1112 ngx_shmtx_unlock(&cache->shpool->mutex); 1168 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1113 1169 "http file cache expire: \"%s\"", name);
1114 len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; 1170
1115 1171 if (ngx_delete_file(name) == NGX_FILE_ERROR) {
1116 ngx_create_hashed_filename(path, name, len); 1172 ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno,
1117 1173 ngx_delete_file_n " \"%s\" failed", name);
1118 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 1174 }
1119 "http file cache expire: \"%s\"", name); 1175
1120 1176 ngx_shmtx_lock(&cache->shpool->mutex);
1121 if (ngx_delete_file(name) == NGX_FILE_ERROR) { 1177 fcn->count--;
1122 ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, 1178 fcn->deleting = 0;
1123 ngx_delete_file_n " \"%s\" failed", name); 1179 }
1124 } 1180
1125 1181 if (fcn->count == 0) {
1126 ngx_shmtx_lock(&cache->shpool->mutex); 1182 ngx_queue_remove(q);
1183 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
1184 ngx_slab_free_locked(cache->shpool, fcn);
1185 }
1127 } 1186 }
1128 1187
1129 1188
1130 static time_t 1189 static time_t
1131 ngx_http_file_cache_manager(void *data) 1190 ngx_http_file_cache_manager(void *data)
1132 { 1191 {
1133 ngx_http_file_cache_t *cache = data; 1192 ngx_http_file_cache_t *cache = data;
1134 1193
1135 off_t size; 1194 off_t size;
1136 time_t next; 1195 time_t next, wait;
1137 1196
1138 next = ngx_http_file_cache_expire(cache); 1197 next = ngx_http_file_cache_expire(cache);
1139 1198
1140 cache->last = ngx_current_msec; 1199 cache->last = ngx_current_msec;
1141 cache->files = 0; 1200 cache->files = 0;
1152 1211
1153 if (size < cache->max_size) { 1212 if (size < cache->max_size) {
1154 return next; 1213 return next;
1155 } 1214 }
1156 1215
1157 next = ngx_http_file_cache_forced_expire(cache); 1216 wait = ngx_http_file_cache_forced_expire(cache);
1217
1218 if (wait > 0) {
1219 return wait;
1220 }
1158 1221
1159 if (ngx_http_file_cache_manager_sleep(cache) != NGX_OK) { 1222 if (ngx_http_file_cache_manager_sleep(cache) != NGX_OK) {
1160 return next; 1223 return next;
1161 } 1224 }
1162 } 1225 }
1214 { 1277 {
1215 ngx_msec_t elapsed; 1278 ngx_msec_t elapsed;
1216 1279
1217 if (cache->files++ > 100) { 1280 if (cache->files++ > 100) {
1218 1281
1219 ngx_time_update(0, 0); 1282 ngx_time_update();
1220 1283
1221 elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); 1284 elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last));
1222 1285
1223 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 1286 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1224 "http file cache manager time: %M", elapsed); 1287 "http file cache manager time: %M", elapsed);
1231 * therefore sleep 200ms 1294 * therefore sleep 200ms
1232 */ 1295 */
1233 1296
1234 ngx_msleep(200); 1297 ngx_msleep(200);
1235 1298
1236 ngx_time_update(0, 0); 1299 ngx_time_update();
1237 } 1300 }
1238 1301
1239 cache->last = ngx_current_msec; 1302 cache->last = ngx_current_msec;
1240 cache->files = 0; 1303 cache->files = 0;
1241 } 1304 }
1377 fcn->uses = 1; 1440 fcn->uses = 1;
1378 fcn->count = 0; 1441 fcn->count = 0;
1379 fcn->valid_msec = c->valid_msec; 1442 fcn->valid_msec = c->valid_msec;
1380 fcn->error = 0; 1443 fcn->error = 0;
1381 fcn->exists = 1; 1444 fcn->exists = 1;
1445 fcn->updating = 0;
1446 fcn->deleting = 0;
1382 fcn->uniq = c->uniq; 1447 fcn->uniq = c->uniq;
1383 fcn->valid_sec = c->valid_sec; 1448 fcn->valid_sec = c->valid_sec;
1384 fcn->body_start = c->body_start; 1449 fcn->body_start = c->body_start;
1385 fcn->length = c->length; 1450 fcn->length = c->length;
1386 1451
1690 v->valid = valid; 1755 v->valid = valid;
1691 } 1756 }
1692 1757
1693 return NGX_CONF_OK; 1758 return NGX_CONF_OK;
1694 } 1759 }
1760
1761
1762 ngx_int_t
1763 ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache)
1764 {
1765 ngx_str_t val;
1766 ngx_uint_t i;
1767 ngx_http_complex_value_t *cv;
1768
1769 cv = no_cache->elts;
1770
1771 for (i = 0; i < no_cache->nelts; i++) {
1772 if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
1773 return NGX_ERROR;
1774 }
1775
1776 if (val.len && val.data[0] != '0') {
1777 return NGX_DECLINED;
1778 }
1779 }
1780
1781 return NGX_OK;
1782 }
1783
1784
1785 char *
1786 ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1787 {
1788 char *p = conf;
1789
1790 ngx_str_t *value;
1791 ngx_uint_t i;
1792 ngx_array_t **a;
1793 ngx_http_complex_value_t *cv;
1794 ngx_http_compile_complex_value_t ccv;
1795
1796 a = (ngx_array_t **) (p + cmd->offset);
1797
1798 if (*a == NGX_CONF_UNSET_PTR) {
1799 *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
1800 if (*a == NULL) {
1801 return NGX_CONF_ERROR;
1802 }
1803 }
1804
1805 value = cf->args->elts;
1806
1807 for (i = 1; i < cf->args->nelts; i++) {
1808 cv = ngx_array_push(*a);
1809 if (cv == NULL) {
1810 return NGX_CONF_ERROR;
1811 }
1812
1813 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
1814
1815 ccv.cf = cf;
1816 ccv.value = &value[i];
1817 ccv.complex_value = cv;
1818
1819 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
1820 return NGX_CONF_ERROR;
1821 }
1822 }
1823
1824 return NGX_CONF_OK;
1825 }