Mercurial > hg > nginx-ranges
comparison src/http/ngx_http_file_cache.c @ 539:5f4de8cf0d9d
Merge with current.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 15 Sep 2009 03:43:40 +0400 |
parents | 86dad910eeb6 |
children | 005a70f9573b |
comparison
equal
deleted
inserted
replaced
522:40fd8d7b82f9 | 539:5f4de8cf0d9d |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 #include <ngx_md5.h> | 10 #include <ngx_md5.h> |
11 | 11 |
12 | 12 |
13 static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r, | |
14 ngx_http_cache_t *c); | |
15 #if (NGX_HAVE_FILE_AIO) | |
16 static void ngx_http_cache_aio_event_handler(ngx_event_t *ev); | |
17 #endif | |
13 static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, | 18 static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, |
14 ngx_http_cache_t *c); | 19 ngx_http_cache_t *c); |
15 static ngx_http_file_cache_node_t * | 20 static ngx_http_file_cache_node_t * |
16 ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key); | 21 ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key); |
17 static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, | 22 static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, |
51 ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data) | 56 ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data) |
52 { | 57 { |
53 ngx_http_file_cache_t *ocache = data; | 58 ngx_http_file_cache_t *ocache = data; |
54 | 59 |
55 size_t len; | 60 size_t len; |
61 ngx_uint_t n; | |
56 ngx_http_file_cache_t *cache; | 62 ngx_http_file_cache_t *cache; |
57 | 63 |
58 cache = shm_zone->data; | 64 cache = shm_zone->data; |
59 | 65 |
60 if (ocache) { | 66 if (ocache) { |
66 &ocache->path->name); | 72 &ocache->path->name); |
67 | 73 |
68 return NGX_ERROR; | 74 return NGX_ERROR; |
69 } | 75 } |
70 | 76 |
77 for (n = 0; n < 3; n++) { | |
78 if (cache->path->level[n] != ocache->path->level[n]) { | |
79 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, | |
80 "cache \"%V\" had previously different levels", | |
81 &shm_zone->shm.name); | |
82 return NGX_ERROR; | |
83 } | |
84 } | |
85 | |
71 cache->sh = ocache->sh; | 86 cache->sh = ocache->sh; |
72 | 87 |
73 cache->shpool = ocache->shpool; | 88 cache->shpool = ocache->shpool; |
74 cache->bsize = ocache->bsize; | 89 cache->bsize = ocache->bsize; |
75 | 90 |
76 cache->max_size /= cache->bsize; | 91 cache->max_size /= cache->bsize; |
92 | |
93 if (!cache->sh->cold || cache->sh->loading) { | |
94 cache->path->loader = NULL; | |
95 } | |
77 | 96 |
78 return NGX_OK; | 97 return NGX_OK; |
79 } | 98 } |
80 | 99 |
81 cache->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; | 100 cache->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; |
98 ngx_http_file_cache_rbtree_insert_value); | 117 ngx_http_file_cache_rbtree_insert_value); |
99 | 118 |
100 ngx_queue_init(&cache->sh->queue); | 119 ngx_queue_init(&cache->sh->queue); |
101 | 120 |
102 cache->sh->cold = 1; | 121 cache->sh->cold = 1; |
122 cache->sh->loading = 0; | |
103 cache->sh->size = 0; | 123 cache->sh->size = 0; |
104 | 124 |
105 cache->bsize = ngx_fs_bsize(cache->path->name.data); | 125 cache->bsize = ngx_fs_bsize(cache->path->name.data); |
106 | 126 |
107 cache->max_size /= cache->bsize; | 127 cache->max_size /= cache->bsize; |
156 | 176 |
157 | 177 |
158 ngx_int_t | 178 ngx_int_t |
159 ngx_http_file_cache_open(ngx_http_request_t *r) | 179 ngx_http_file_cache_open(ngx_http_request_t *r) |
160 { | 180 { |
161 u_char *p; | 181 u_char *p; |
162 time_t now; | 182 ngx_int_t rc, rv; |
163 ssize_t n; | 183 ngx_uint_t cold, test; |
164 ngx_int_t rc, rv; | 184 ngx_path_t *path; |
165 ngx_uint_t cold, test; | 185 ngx_http_cache_t *c; |
166 ngx_path_t *path; | 186 ngx_pool_cleanup_t *cln; |
167 ngx_http_cache_t *c; | 187 ngx_open_file_info_t of; |
168 ngx_pool_cleanup_t *cln; | 188 ngx_http_file_cache_t *cache; |
169 ngx_open_file_info_t of; | 189 ngx_http_core_loc_conf_t *clcf; |
170 ngx_http_file_cache_t *cache; | |
171 ngx_http_core_loc_conf_t *clcf; | |
172 ngx_http_file_cache_header_t *h; | |
173 | 190 |
174 c = r->cache; | 191 c = r->cache; |
192 | |
193 if (c->buf) { | |
194 return ngx_http_file_cache_read(r, c); | |
195 } | |
196 | |
175 cache = c->file_cache; | 197 cache = c->file_cache; |
176 | 198 |
177 cln = ngx_pool_cleanup_add(r->pool, 0); | 199 cln = ngx_pool_cleanup_add(r->pool, 0); |
178 if (cln == NULL) { | 200 if (cln == NULL) { |
179 return NGX_ERROR; | 201 return NGX_ERROR; |
190 | 212 |
191 cln->handler = ngx_http_file_cache_cleanup; | 213 cln->handler = ngx_http_file_cache_cleanup; |
192 cln->data = c; | 214 cln->data = c; |
193 | 215 |
194 if (rc == NGX_AGAIN) { | 216 if (rc == NGX_AGAIN) { |
195 return rc; | 217 return NGX_HTTP_CACHE_SCARCE; |
196 } | 218 } |
197 | 219 |
198 cold = cache->sh->cold; | 220 cold = cache->sh->cold; |
199 | 221 |
200 if (rc == NGX_OK) { | 222 if (rc == NGX_OK) { |
210 } else { /* rc == NGX_DECLINED */ | 232 } else { /* rc == NGX_DECLINED */ |
211 | 233 |
212 if (c->min_uses > 1) { | 234 if (c->min_uses > 1) { |
213 | 235 |
214 if (!cold) { | 236 if (!cold) { |
215 return NGX_AGAIN; | 237 return NGX_HTTP_CACHE_SCARCE; |
216 } | 238 } |
217 | 239 |
218 test = 1; | 240 test = 1; |
219 rv = NGX_AGAIN; | 241 rv = NGX_HTTP_CACHE_SCARCE; |
220 | 242 |
221 } else { | 243 } else { |
222 c->temp_file = 1; | 244 c->temp_file = 1; |
223 test = cold ? 1 : 0; | 245 test = cold ? 1 : 0; |
224 rv = NGX_DECLINED; | 246 rv = NGX_DECLINED; |
282 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 304 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
283 "http file cache fd: %d", of.fd); | 305 "http file cache fd: %d", of.fd); |
284 | 306 |
285 c->file.fd = of.fd; | 307 c->file.fd = of.fd; |
286 c->file.log = r->connection->log; | 308 c->file.log = r->connection->log; |
309 c->uniq = of.uniq; | |
310 c->length = of.size; | |
287 | 311 |
288 c->buf = ngx_create_temp_buf(r->pool, c->body_start); | 312 c->buf = ngx_create_temp_buf(r->pool, c->body_start); |
289 if (c->buf == NULL) { | 313 if (c->buf == NULL) { |
290 return NGX_ERROR; | 314 return NGX_ERROR; |
291 } | 315 } |
292 | 316 |
317 return ngx_http_file_cache_read(r, c); | |
318 } | |
319 | |
320 | |
321 static ngx_int_t | |
322 ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) | |
323 { | |
324 time_t now; | |
325 ssize_t n; | |
326 ngx_int_t rc; | |
327 ngx_http_file_cache_t *cache; | |
328 ngx_http_file_cache_header_t *h; | |
329 | |
330 c = r->cache; | |
331 | |
332 #if (NGX_HAVE_FILE_AIO) | |
333 { | |
334 ngx_http_core_loc_conf_t *clcf; | |
335 | |
336 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
337 | |
338 if (clcf->aio) { | |
339 n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool); | |
340 | |
341 if (n == NGX_AGAIN) { | |
342 c->file.aio->data = r; | |
343 c->file.aio->handler = ngx_http_cache_aio_event_handler; | |
344 | |
345 r->main->blocked++; | |
346 r->aio = 1; | |
347 | |
348 return NGX_AGAIN; | |
349 } | |
350 | |
351 } else { | |
352 n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); | |
353 } | |
354 } | |
355 #else | |
356 | |
293 n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); | 357 n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); |
358 | |
359 #endif | |
294 | 360 |
295 if (n == NGX_ERROR) { | 361 if (n == NGX_ERROR) { |
296 return n; | 362 return n; |
297 } | 363 } |
298 | 364 |
314 | 380 |
315 c->valid_sec = h->valid_sec; | 381 c->valid_sec = h->valid_sec; |
316 c->last_modified = h->last_modified; | 382 c->last_modified = h->last_modified; |
317 c->date = h->date; | 383 c->date = h->date; |
318 c->valid_msec = h->valid_msec; | 384 c->valid_msec = h->valid_msec; |
319 c->length = of.size; | |
320 c->body_start = h->body_start; | 385 c->body_start = h->body_start; |
321 | 386 |
322 r->cached = 1; | 387 r->cached = 1; |
323 | 388 |
324 if (cold) { | 389 cache = c->file_cache; |
390 | |
391 if (cache->sh->cold) { | |
325 | 392 |
326 ngx_shmtx_lock(&cache->shpool->mutex); | 393 ngx_shmtx_lock(&cache->shpool->mutex); |
327 | 394 |
328 if (!c->node->exists) { | 395 if (!c->node->exists) { |
329 c->node->uses = 1; | 396 c->node->uses = 1; |
330 c->node->body_start = c->body_start; | 397 c->node->body_start = c->body_start; |
331 c->node->exists = 1; | 398 c->node->exists = 1; |
332 c->node->uniq = of.uniq; | 399 c->node->uniq = c->uniq; |
333 | 400 |
334 cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize; | 401 cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize; |
335 } | 402 } |
336 | 403 |
337 ngx_shmtx_unlock(&cache->shpool->mutex); | 404 ngx_shmtx_unlock(&cache->shpool->mutex); |
360 return rc; | 427 return rc; |
361 } | 428 } |
362 | 429 |
363 return NGX_OK; | 430 return NGX_OK; |
364 } | 431 } |
432 | |
433 | |
434 #if (NGX_HAVE_FILE_AIO) | |
435 | |
436 | |
437 static void | |
438 ngx_http_cache_aio_event_handler(ngx_event_t *ev) | |
439 { | |
440 ngx_event_aio_t *aio; | |
441 ngx_http_request_t *r; | |
442 | |
443 aio = ev->data; | |
444 r = aio->data; | |
445 | |
446 r->main->blocked--; | |
447 r->aio = 0; | |
448 | |
449 r->connection->write->handler(r->connection->write); | |
450 } | |
451 | |
452 #endif | |
365 | 453 |
366 | 454 |
367 static ngx_int_t | 455 static ngx_int_t |
368 ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) | 456 ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) |
369 { | 457 { |
633 ext.access = NGX_FILE_OWNER_ACCESS; | 721 ext.access = NGX_FILE_OWNER_ACCESS; |
634 ext.path_access = NGX_FILE_OWNER_ACCESS; | 722 ext.path_access = NGX_FILE_OWNER_ACCESS; |
635 ext.time = -1; | 723 ext.time = -1; |
636 ext.create_path = 1; | 724 ext.create_path = 1; |
637 ext.delete_file = 1; | 725 ext.delete_file = 1; |
638 ext.log_rename_error = 1; | |
639 ext.log = r->connection->log; | 726 ext.log = r->connection->log; |
640 | 727 |
641 rc = ngx_ext_rename_file(&tf->file.name, &c->file.name, &ext); | 728 rc = ngx_ext_rename_file(&tf->file.name, &c->file.name, &ext); |
642 | 729 |
643 if (rc == NGX_OK) { | 730 if (rc == NGX_OK) { |
1024 static time_t | 1111 static time_t |
1025 ngx_http_file_cache_manager(void *data) | 1112 ngx_http_file_cache_manager(void *data) |
1026 { | 1113 { |
1027 ngx_http_file_cache_t *cache = data; | 1114 ngx_http_file_cache_t *cache = data; |
1028 | 1115 |
1029 off_t size; | 1116 off_t size; |
1030 time_t next; | 1117 time_t next; |
1031 ngx_tree_ctx_t tree; | |
1032 | |
1033 if (cache->sh->cold) { | |
1034 | |
1035 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, | |
1036 "http file cache manager update"); | |
1037 | |
1038 tree.init_handler = NULL; | |
1039 tree.file_handler = ngx_http_file_cache_manage_file; | |
1040 tree.pre_tree_handler = ngx_http_file_cache_noop; | |
1041 tree.post_tree_handler = ngx_http_file_cache_noop; | |
1042 tree.spec_handler = ngx_http_file_cache_delete_file; | |
1043 tree.data = cache; | |
1044 tree.alloc = 0; | |
1045 tree.log = ngx_cycle->log; | |
1046 | |
1047 cache->last = ngx_current_msec; | |
1048 cache->files = 0; | |
1049 | |
1050 if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) { | |
1051 return 10; | |
1052 } | |
1053 | |
1054 cache->sh->cold = 0; | |
1055 | |
1056 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, | |
1057 "http file cache: %V %.3fM, bsize: %uz", | |
1058 &cache->path->name, | |
1059 ((double) cache->sh->size * cache->bsize) / (1024 * 1024), | |
1060 cache->bsize); | |
1061 } | |
1062 | 1118 |
1063 next = ngx_http_file_cache_expire(cache); | 1119 next = ngx_http_file_cache_expire(cache); |
1064 | 1120 |
1065 cache->last = ngx_current_msec; | 1121 cache->last = ngx_current_msec; |
1066 cache->files = 0; | 1122 cache->files = 0; |
1083 | 1139 |
1084 if (ngx_http_file_cache_manager_sleep(cache) != NGX_OK) { | 1140 if (ngx_http_file_cache_manager_sleep(cache) != NGX_OK) { |
1085 return next; | 1141 return next; |
1086 } | 1142 } |
1087 } | 1143 } |
1144 } | |
1145 | |
1146 | |
1147 static void | |
1148 ngx_http_file_cache_loader(void *data) | |
1149 { | |
1150 ngx_http_file_cache_t *cache = data; | |
1151 | |
1152 ngx_tree_ctx_t tree; | |
1153 | |
1154 if (!cache->sh->cold || cache->sh->loading) { | |
1155 return; | |
1156 } | |
1157 | |
1158 if (!ngx_atomic_cmp_set(&cache->sh->loading, 0, ngx_pid)) { | |
1159 return; | |
1160 } | |
1161 | |
1162 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, | |
1163 "http file cache loader"); | |
1164 | |
1165 tree.init_handler = NULL; | |
1166 tree.file_handler = ngx_http_file_cache_manage_file; | |
1167 tree.pre_tree_handler = ngx_http_file_cache_noop; | |
1168 tree.post_tree_handler = ngx_http_file_cache_noop; | |
1169 tree.spec_handler = ngx_http_file_cache_delete_file; | |
1170 tree.data = cache; | |
1171 tree.alloc = 0; | |
1172 tree.log = ngx_cycle->log; | |
1173 | |
1174 cache->last = ngx_current_msec; | |
1175 cache->files = 0; | |
1176 | |
1177 if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) { | |
1178 cache->sh->loading = 0; | |
1179 return; | |
1180 } | |
1181 | |
1182 cache->sh->cold = 0; | |
1183 cache->sh->loading = 0; | |
1184 | |
1185 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, | |
1186 "http file cache: %V %.3fM, bsize: %uz", | |
1187 &cache->path->name, | |
1188 ((double) cache->sh->size * cache->bsize) / (1024 * 1024), | |
1189 cache->bsize); | |
1088 } | 1190 } |
1089 | 1191 |
1090 | 1192 |
1091 static ngx_int_t | 1193 static ngx_int_t |
1092 ngx_http_file_cache_manager_sleep(ngx_http_file_cache_t *cache) | 1194 ngx_http_file_cache_manager_sleep(ngx_http_file_cache_t *cache) |
1466 &cmd->name); | 1568 &cmd->name); |
1467 return NGX_CONF_ERROR; | 1569 return NGX_CONF_ERROR; |
1468 } | 1570 } |
1469 | 1571 |
1470 cache->path->manager = ngx_http_file_cache_manager; | 1572 cache->path->manager = ngx_http_file_cache_manager; |
1573 cache->path->loader = ngx_http_file_cache_loader; | |
1471 cache->path->data = cache; | 1574 cache->path->data = cache; |
1472 | 1575 |
1473 if (ngx_add_path(cf, &cache->path) != NGX_OK) { | 1576 if (ngx_add_path(cf, &cache->path) != NGX_OK) { |
1474 return NGX_CONF_ERROR; | 1577 return NGX_CONF_ERROR; |
1475 } | 1578 } |