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 }