comparison src/http/ngx_http_file_cache.c @ 480:549994537f15 NGINX_0_7_52

nginx 0.7.52 *) Feature: the first native Windows binary release. *) Bugfix: in processing HEAD method while caching. *) Bugfix: in processing the "If-Modified-Since", "If-Range", etc. client request header lines while caching. *) Bugfix: now the "Set-Cookie" and "P3P" header lines are hidden in cacheable responses. *) Bugfix: if nginx was built with the ngx_http_perl_module and with a perl which supports threads, then during a master process exit the message "panic: MUTEX_LOCK" might be issued. *) Bugfix: nginx could not be built --without-http-cache; the bug had appeared in 0.7.48. *) Bugfix: nginx could not be built on platforms different from i386, amd64, sparc, and ppc; the bug had appeared in 0.7.42.
author Igor Sysoev <http://sysoev.ru>
date Mon, 20 Apr 2009 00:00:00 +0400
parents f2c6a7373274
children 207ae3ff0444
comparison
equal deleted inserted replaced
479:eb4fdebda673 480:549994537f15
42 ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data) 42 ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data)
43 { 43 {
44 ngx_http_file_cache_t *ocache = data; 44 ngx_http_file_cache_t *ocache = data;
45 45
46 size_t len; 46 size_t len;
47 ngx_rbtree_node_t *sentinel;
48 ngx_http_file_cache_t *cache; 47 ngx_http_file_cache_t *cache;
49 48
50 cache = shm_zone->data; 49 cache = shm_zone->data;
51 50
52 if (ocache) { 51 if (ocache) {
53 if (ngx_strcmp(cache->path->name.data, ocache->path->name.data) != 0) { 52 if (ngx_strcmp(cache->path->name.data, ocache->path->name.data) != 0) {
54 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, 53 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
55 "cache \"%V\" uses the \"%V\" cache path " 54 "cache \"%V\" uses the \"%V\" cache path "
56 "while previously it used the \"%V\" cache path", 55 "while previously it used the \"%V\" cache path",
57 &shm_zone->name, &cache->path->name, 56 &shm_zone->shm.name, &cache->path->name,
58 &ocache->path->name); 57 &ocache->path->name);
59 58
60 return NGX_ERROR; 59 return NGX_ERROR;
61 } 60 }
62 61
63 cache->rbtree = ocache->rbtree; 62 cache->sh = ocache->sh;
64 cache->queue = ocache->queue; 63
65 cache->shpool = ocache->shpool; 64 cache->shpool = ocache->shpool;
66 cache->cold = ocache->cold;
67 cache->size = ocache->size;
68 cache->bsize = ocache->bsize; 65 cache->bsize = ocache->bsize;
69 66
70 cache->max_size /= cache->bsize; 67 cache->max_size /= cache->bsize;
71 68
72 return NGX_OK; 69 return NGX_OK;
73 } 70 }
74 71
75 cache->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 72 cache->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
76 73
77 cache->rbtree = ngx_slab_alloc(cache->shpool, sizeof(ngx_rbtree_t)); 74 if (shm_zone->shm.exists) {
78 if (cache->rbtree == NULL) { 75 cache->sh = cache->shpool->data;
76 cache->bsize = ngx_fs_bsize(cache->path->name.data);
77
78 return NGX_OK;
79 }
80
81 cache->sh = ngx_slab_alloc(cache->shpool, sizeof(ngx_http_file_cache_sh_t));
82 if (cache->sh == NULL) {
79 return NGX_ERROR; 83 return NGX_ERROR;
80 } 84 }
81 85
82 sentinel = ngx_slab_alloc(cache->shpool, sizeof(ngx_rbtree_node_t)); 86 cache->shpool->data = cache->sh;
83 if (sentinel == NULL) { 87
84 return NGX_ERROR; 88 ngx_rbtree_init(&cache->sh->rbtree, &cache->sh->sentinel,
85 }
86
87 ngx_rbtree_init(cache->rbtree, sentinel,
88 ngx_http_file_cache_rbtree_insert_value); 89 ngx_http_file_cache_rbtree_insert_value);
89 90
90 cache->queue = ngx_slab_alloc(cache->shpool, sizeof(ngx_queue_t)); 91 ngx_queue_init(&cache->sh->queue);
91 if (cache->queue == NULL) { 92
92 return NGX_ERROR; 93 cache->sh->cold = 1;
93 } 94 cache->sh->size = 0;
94
95 ngx_queue_init(cache->queue);
96
97 cache->cold = ngx_slab_alloc(cache->shpool, sizeof(ngx_atomic_t));
98 if (cache->cold == NULL) {
99 return NGX_ERROR;
100 }
101
102 *cache->cold = 1;
103
104 cache->size = ngx_slab_alloc(cache->shpool, sizeof(off_t));
105 if (cache->size == NULL) {
106 return NGX_ERROR;
107 }
108
109 *cache->size = 0;
110 95
111 cache->bsize = ngx_fs_bsize(cache->path->name.data); 96 cache->bsize = ngx_fs_bsize(cache->path->name.data);
112 97
113 cache->max_size /= cache->bsize; 98 cache->max_size /= cache->bsize;
114 99
115 len = sizeof(" in cache keys zone \"\"") + shm_zone->name.len; 100 len = sizeof(" in cache keys zone \"\"") + shm_zone->shm.name.len;
116 101
117 cache->shpool->log_ctx = ngx_slab_alloc(cache->shpool, len); 102 cache->shpool->log_ctx = ngx_slab_alloc(cache->shpool, len);
118 if (cache->shpool->log_ctx == NULL) { 103 if (cache->shpool->log_ctx == NULL) {
119 return NGX_ERROR; 104 return NGX_ERROR;
120 } 105 }
121 106
122 ngx_sprintf(cache->shpool->log_ctx, " in cache keys zone \"%V\"%Z", 107 ngx_sprintf(cache->shpool->log_ctx, " in cache keys zone \"%V\"%Z",
123 &shm_zone->name); 108 &shm_zone->shm.name);
124 109
125 return NGX_OK; 110 return NGX_OK;
126 } 111 }
127 112
128 113
200 185
201 if (rc == NGX_AGAIN) { 186 if (rc == NGX_AGAIN) {
202 return rc; 187 return rc;
203 } 188 }
204 189
205 cold = *cache->cold; 190 cold = cache->sh->cold;
206 191
207 if (rc == NGX_OK) { 192 if (rc == NGX_OK) {
208 193
209 if (c->error) { 194 if (c->error) {
210 return c->error; 195 return c->error;
335 if (!c->node->exists) { 320 if (!c->node->exists) {
336 c->node->uses = 1; 321 c->node->uses = 1;
337 c->node->body_start = c->body_start; 322 c->node->body_start = c->body_start;
338 c->node->exists = 1; 323 c->node->exists = 1;
339 324
340 *cache->size += (c->length + cache->bsize - 1) / cache->bsize; 325 cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize;
341 } 326 }
342 327
343 ngx_shmtx_unlock(&cache->shpool->mutex); 328 ngx_shmtx_unlock(&cache->shpool->mutex);
344 } 329 }
345 330
432 ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t)); 417 ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t));
433 418
434 ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)], 419 ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],
435 NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t)); 420 NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
436 421
437 ngx_rbtree_insert(cache->rbtree, &fcn->node); 422 ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
438 423
439 renew: 424 renew:
440 425
441 rc = NGX_DECLINED; 426 rc = NGX_DECLINED;
442 427
452 437
453 done: 438 done:
454 439
455 fcn->expire = ngx_time() + cache->inactive; 440 fcn->expire = ngx_time() + cache->inactive;
456 441
457 ngx_queue_insert_head(cache->queue, &fcn->queue); 442 ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);
458 443
459 c->uniq = fcn->uniq; 444 c->uniq = fcn->uniq;
460 c->uses = fcn->uses; 445 c->uses = fcn->uses;
461 c->error = fcn->error; 446 c->error = fcn->error;
462 c->node = fcn; 447 c->node = fcn;
477 ngx_rbtree_node_t *node, *sentinel; 462 ngx_rbtree_node_t *node, *sentinel;
478 ngx_http_file_cache_node_t *fcn; 463 ngx_http_file_cache_node_t *fcn;
479 464
480 ngx_memcpy((u_char *) &node_key, key, sizeof(ngx_rbtree_key_t)); 465 ngx_memcpy((u_char *) &node_key, key, sizeof(ngx_rbtree_key_t));
481 466
482 node = cache->rbtree->root; 467 node = cache->sh->rbtree.root;
483 sentinel = cache->rbtree->sentinel; 468 sentinel = cache->sh->rbtree.sentinel;
484 469
485 while (node != sentinel) { 470 while (node != sentinel) {
486 471
487 if (node_key < node->key) { 472 if (node_key < node->key) {
488 node = node->left; 473 node = node->left;
661 646
662 size = size - (c->node->length + cache->bsize - 1) / cache->bsize; 647 size = size - (c->node->length + cache->bsize - 1) / cache->bsize;
663 648
664 c->node->length = c->length; 649 c->node->length = c->length;
665 650
666 *cache->size += size; 651 cache->sh->size += size;
667 652
668 if (rc == NGX_OK) { 653 if (rc == NGX_OK) {
669 c->node->exists = 1; 654 c->node->exists = 1;
670 } 655 }
671 656
826 wait = 10; 811 wait = 10;
827 tries = 0; 812 tries = 0;
828 813
829 ngx_shmtx_lock(&cache->shpool->mutex); 814 ngx_shmtx_lock(&cache->shpool->mutex);
830 815
831 for (q = ngx_queue_last(cache->queue); 816 for (q = ngx_queue_last(&cache->sh->queue);
832 q != ngx_queue_sentinel(cache->queue); 817 q != ngx_queue_sentinel(&cache->sh->queue);
833 q = ngx_queue_prev(q)) 818 q = ngx_queue_prev(q))
834 { 819 {
835 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); 820 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
836 821
837 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 822 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
851 } 836 }
852 837
853 if (!fcn->exists) { 838 if (!fcn->exists) {
854 839
855 ngx_queue_remove(q); 840 ngx_queue_remove(q);
856 ngx_rbtree_delete(cache->rbtree, &fcn->node); 841 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
857 ngx_slab_free_locked(cache->shpool, fcn); 842 ngx_slab_free_locked(cache->shpool, fcn);
858 843
859 break; 844 break;
860 } 845 }
861 846
900 885
901 ngx_shmtx_lock(&cache->shpool->mutex); 886 ngx_shmtx_lock(&cache->shpool->mutex);
902 887
903 for ( ;; ) { 888 for ( ;; ) {
904 889
905 if (ngx_queue_empty(cache->queue)) { 890 if (ngx_queue_empty(&cache->sh->queue)) {
906 wait = 10; 891 wait = 10;
907 break; 892 break;
908 } 893 }
909 894
910 q = ngx_queue_last(cache->queue); 895 q = ngx_queue_last(&cache->sh->queue);
911 896
912 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); 897 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
913 898
914 wait = fcn->expire - now; 899 wait = fcn->expire - now;
915 900
937 * we prefer to remove them from inactive queue and rbtree 922 * we prefer to remove them from inactive queue and rbtree
938 * only, and to allow other leaks 923 * only, and to allow other leaks
939 */ 924 */
940 925
941 ngx_queue_remove(q); 926 ngx_queue_remove(q);
942 ngx_rbtree_delete(cache->rbtree, &fcn->node); 927 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
943 928
944 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, 929 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
945 "ignore long locked inactive cache entry %*s, count:%d", 930 "ignore long locked inactive cache entry %*s, count:%d",
946 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); 931 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count);
947 932
949 } 934 }
950 935
951 if (!fcn->exists) { 936 if (!fcn->exists) {
952 937
953 ngx_queue_remove(q); 938 ngx_queue_remove(q);
954 ngx_rbtree_delete(cache->rbtree, &fcn->node); 939 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
955 ngx_slab_free_locked(cache->shpool, fcn); 940 ngx_slab_free_locked(cache->shpool, fcn);
956 941
957 continue; 942 continue;
958 } 943 }
959 944
977 ngx_path_t *path; 962 ngx_path_t *path;
978 ngx_http_file_cache_node_t *fcn; 963 ngx_http_file_cache_node_t *fcn;
979 964
980 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); 965 fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
981 966
982 *cache->size -= (fcn->length + cache->bsize - 1) / cache->bsize; 967 cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
983 968
984 path = cache->path; 969 path = cache->path;
985 970
986 p = name + path->name.len + 1 + path->len; 971 p = name + path->name.len + 1 + path->len;
987 972
991 p = ngx_hex_dump(p, fcn->key, len); 976 p = ngx_hex_dump(p, fcn->key, len);
992 *p = '\0'; 977 *p = '\0';
993 978
994 ngx_queue_remove(q); 979 ngx_queue_remove(q);
995 980
996 ngx_rbtree_delete(cache->rbtree, &fcn->node); 981 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
997 982
998 ngx_slab_free_locked(cache->shpool, fcn); 983 ngx_slab_free_locked(cache->shpool, fcn);
999 984
1000 ngx_shmtx_unlock(&cache->shpool->mutex); 985 ngx_shmtx_unlock(&cache->shpool->mutex);
1001 986
1022 1007
1023 off_t size; 1008 off_t size;
1024 time_t next; 1009 time_t next;
1025 ngx_tree_ctx_t tree; 1010 ngx_tree_ctx_t tree;
1026 1011
1027 if (*cache->cold) { 1012 if (cache->sh->cold) {
1028 1013
1029 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 1014 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1030 "http file cache manager update"); 1015 "http file cache manager update");
1031 1016
1032 tree.init_handler = NULL; 1017 tree.init_handler = NULL;
1043 1028
1044 if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) { 1029 if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) {
1045 return 10; 1030 return 10;
1046 } 1031 }
1047 1032
1048 *cache->cold = 0; 1033 cache->sh->cold = 0;
1049 1034
1050 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, 1035 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
1051 "http file cache: %V %.3fM, bsize: %uz", 1036 "http file cache: %V %.3fM, bsize: %uz",
1052 &cache->path->name, 1037 &cache->path->name,
1053 ((double) *cache->size * cache->bsize) / (1024 * 1024), 1038 ((double) cache->sh->size * cache->bsize) / (1024 * 1024),
1054 cache->bsize); 1039 cache->bsize);
1055 } 1040 }
1056 1041
1057 next = ngx_http_file_cache_expire(cache); 1042 next = ngx_http_file_cache_expire(cache);
1058 1043
1060 cache->files = 0; 1045 cache->files = 0;
1061 1046
1062 for ( ;; ) { 1047 for ( ;; ) {
1063 ngx_shmtx_lock(&cache->shpool->mutex); 1048 ngx_shmtx_lock(&cache->shpool->mutex);
1064 1049
1065 size = *cache->size; 1050 size = cache->sh->size;
1066 1051
1067 ngx_shmtx_unlock(&cache->shpool->mutex); 1052 ngx_shmtx_unlock(&cache->shpool->mutex);
1068 1053
1069 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, 1054 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1070 "http file cache size: %O", size); 1055 "http file cache size: %O", size);
1243 ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t)); 1228 ngx_memcpy((u_char *) &fcn->node.key, c->key, sizeof(ngx_rbtree_key_t));
1244 1229
1245 ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)], 1230 ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],
1246 NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t)); 1231 NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
1247 1232
1248 ngx_rbtree_insert(cache->rbtree, &fcn->node); 1233 ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
1249 1234
1250 fcn->uses = 1; 1235 fcn->uses = 1;
1251 fcn->count = 0; 1236 fcn->count = 0;
1252 fcn->valid_msec = c->valid_msec; 1237 fcn->valid_msec = c->valid_msec;
1253 fcn->error = 0; 1238 fcn->error = 0;
1255 fcn->uniq = c->uniq; 1240 fcn->uniq = c->uniq;
1256 fcn->valid_sec = c->valid_sec; 1241 fcn->valid_sec = c->valid_sec;
1257 fcn->body_start = c->body_start; 1242 fcn->body_start = c->body_start;
1258 fcn->length = c->length; 1243 fcn->length = c->length;
1259 1244
1260 *cache->size += (c->length + cache->bsize - 1) / cache->bsize; 1245 cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize;
1261 1246
1262 } else { 1247 } else {
1263 ngx_queue_remove(&fcn->queue); 1248 ngx_queue_remove(&fcn->queue);
1264 } 1249 }
1265 1250
1266 fcn->expire = ngx_time() + cache->inactive; 1251 fcn->expire = ngx_time() + cache->inactive;
1267 1252
1268 ngx_queue_insert_head(cache->queue, &fcn->queue); 1253 ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);
1269 1254
1270 ngx_shmtx_unlock(&cache->shpool->mutex); 1255 ngx_shmtx_unlock(&cache->shpool->mutex);
1271 1256
1272 return NGX_OK; 1257 return NGX_OK;
1273 } 1258 }
1397 name.data = value[i].data + 10; 1382 name.data = value[i].data + 10;
1398 1383
1399 p = (u_char *) ngx_strchr(name.data, ':'); 1384 p = (u_char *) ngx_strchr(name.data, ':');
1400 1385
1401 if (p) { 1386 if (p) {
1387 *p = '\0';
1388
1402 name.len = p - name.data; 1389 name.len = p - name.data;
1403 1390
1404 p++; 1391 p++;
1405 1392
1406 s.len = value[i].data + value[i].len - p; 1393 s.len = value[i].data + value[i].len - p;