Klaus Demo nginx / 7571f6c
merge r3017, r3018, r3019, r3020, r3021, r3022, r3023, r3196: cache management fixes: *) separate cache loader process *) use real file cache length, this fixes cache size counting for responses without "Content-Length" header and 304 responses. Igor Sysoev 12 years ago
12 changed file(s) with 253 addition(s) and 134 deletion(s). Raw diff Collapse all Expand all
263263 }
264264
265265 path->len = 0;
266 path->manager = (ngx_path_manager_pt) cmd->post;
266 path->manager = NULL;
267 path->loader = NULL;
267268 path->conf_file = cf->conf_file->file.name.data;
268269 path->line = cf->conf_file->line;
269270
324325 + init->level[2] + (init->level[2] ? 1 : 0);
325326
326327 (*path)->manager = NULL;
328 (*path)->loader = NULL;
327329 (*path)->conf_file = NULL;
328330
329331 if (ngx_add_path(cf, path) != NGX_OK) {
2929
3030
3131 typedef time_t (*ngx_path_manager_pt) (void *data);
32 typedef void (*ngx_path_loader_pt) (void *data);
3233
3334
3435 typedef struct {
3738 size_t level[3];
3839
3940 ngx_path_manager_pt manager;
41 ngx_path_loader_pt loader;
4042 void *data;
4143
4244 u_char *conf_file;
9696 ngx_rbtree_node_t sentinel;
9797 ngx_queue_t queue;
9898 ngx_atomic_t cold;
99 ngx_atomic_t loading;
99100 off_t size;
100101 } ngx_http_file_cache_sh_t;
101102
5252 ngx_http_file_cache_t *ocache = data;
5353
5454 size_t len;
55 ngx_uint_t n;
5556 ngx_http_file_cache_t *cache;
5657
5758 cache = shm_zone->data;
6768 return NGX_ERROR;
6869 }
6970
71 for (n = 0; n < 3; n++) {
72 if (cache->path->level[n] != ocache->path->level[n]) {
73 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
74 "cache \"%V\" had previously different levels",
75 &shm_zone->shm.name);
76 return NGX_ERROR;
77 }
78 }
79
7080 cache->sh = ocache->sh;
7181
7282 cache->shpool = ocache->shpool;
7383 cache->bsize = ocache->bsize;
7484
7585 cache->max_size /= cache->bsize;
86
87 if (!cache->sh->cold || cache->sh->loading) {
88 cache->path->loader = NULL;
89 }
7690
7791 return NGX_OK;
7892 }
99113 ngx_queue_init(&cache->sh->queue);
100114
101115 cache->sh->cold = 1;
116 cache->sh->loading = 0;
102117 cache->sh->size = 0;
103118
104119 cache->bsize = ngx_fs_bsize(cache->path->name.data);
602617 void
603618 ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf)
604619 {
605 off_t size;
620 off_t size, length;
606621 ngx_int_t rc;
607622 ngx_file_uniq_t uniq;
608623 ngx_file_info_t fi;
624639 cache = c->file_cache;
625640
626641 uniq = 0;
642 length = 0;
627643
628644 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
629645 "http file cache rename: \"%s\" to \"%s\"",
649665
650666 } else {
651667 uniq = ngx_file_uniq(&fi);
652 }
653 }
654
655 size = (c->length + cache->bsize - 1) / cache->bsize;
668 length = ngx_file_size(&fi);
669 }
670 }
671
672 size = (length + cache->bsize - 1) / cache->bsize;
656673
657674 ngx_shmtx_lock(&cache->shpool->mutex);
658675
662679
663680 size = size - (c->node->length + cache->bsize - 1) / cache->bsize;
664681
665 c->node->length = c->length;
682 c->node->length = length;
666683
667684 cache->sh->size += size;
668685
10251042 {
10261043 ngx_http_file_cache_t *cache = data;
10271044
1028 off_t size;
1029 time_t next;
1030 ngx_tree_ctx_t tree;
1031
1032 if (cache->sh->cold) {
1033
1034 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1035 "http file cache manager update");
1036
1037 tree.init_handler = NULL;
1038 tree.file_handler = ngx_http_file_cache_manage_file;
1039 tree.pre_tree_handler = ngx_http_file_cache_noop;
1040 tree.post_tree_handler = ngx_http_file_cache_noop;
1041 tree.spec_handler = ngx_http_file_cache_delete_file;
1042 tree.data = cache;
1043 tree.alloc = 0;
1044 tree.log = ngx_cycle->log;
1045
1046 cache->last = ngx_current_msec;
1047 cache->files = 0;
1048
1049 if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) {
1050 return 10;
1051 }
1052
1053 cache->sh->cold = 0;
1054
1055 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
1056 "http file cache: %V %.3fM, bsize: %uz",
1057 &cache->path->name,
1058 ((double) cache->sh->size * cache->bsize) / (1024 * 1024),
1059 cache->bsize);
1060 }
1045 off_t size;
1046 time_t next;
10611047
10621048 next = ngx_http_file_cache_expire(cache);
10631049
10841070 return next;
10851071 }
10861072 }
1073 }
1074
1075
1076 static void
1077 ngx_http_file_cache_loader(void *data)
1078 {
1079 ngx_http_file_cache_t *cache = data;
1080
1081 ngx_tree_ctx_t tree;
1082
1083 if (!cache->sh->cold || cache->sh->loading) {
1084 return;
1085 }
1086
1087 if (!ngx_atomic_cmp_set(&cache->sh->loading, 0, ngx_pid)) {
1088 return;
1089 }
1090
1091 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
1092 "http file cache loader");
1093
1094 tree.init_handler = NULL;
1095 tree.file_handler = ngx_http_file_cache_manage_file;
1096 tree.pre_tree_handler = ngx_http_file_cache_noop;
1097 tree.post_tree_handler = ngx_http_file_cache_noop;
1098 tree.spec_handler = ngx_http_file_cache_delete_file;
1099 tree.data = cache;
1100 tree.alloc = 0;
1101 tree.log = ngx_cycle->log;
1102
1103 cache->last = ngx_current_msec;
1104 cache->files = 0;
1105
1106 if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) {
1107 cache->sh->loading = 0;
1108 return;
1109 }
1110
1111 cache->sh->cold = 0;
1112 cache->sh->loading = 0;
1113
1114 ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
1115 "http file cache: %V %.3fM, bsize: %uz",
1116 &cache->path->name,
1117 ((double) cache->sh->size * cache->bsize) / (1024 * 1024),
1118 cache->bsize);
10871119 }
10881120
10891121
14671499 }
14681500
14691501 cache->path->manager = ngx_http_file_cache_manager;
1502 cache->path->loader = ngx_http_file_cache_loader;
14701503 cache->path->data = cache;
14711504
14721505 if (ngx_add_path(cf, &cache->path) != NGX_OK) {
20622062 r->cache->date = now;
20632063 r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
20642064
2065 if (r->headers_out.content_length_n != -1) {
2066 r->cache->length = r->cache->body_start
2067 + r->headers_out.content_length_n;
2068 }
2069
20702065 ngx_http_file_cache_set_header(r, u->buffer.start);
20712066
20722067 } else {
213213
214214 switch (respawn) {
215215
216 case NGX_PROCESS_NORESPAWN:
217 ngx_processes[s].respawn = 0;
218 ngx_processes[s].just_spawn = 0;
219 ngx_processes[s].detached = 0;
220 break;
221
222 case NGX_PROCESS_JUST_SPAWN:
223 ngx_processes[s].respawn = 0;
224 ngx_processes[s].just_spawn = 1;
225 ngx_processes[s].detached = 0;
226 break;
227
216228 case NGX_PROCESS_RESPAWN:
217229 ngx_processes[s].respawn = 1;
218 ngx_processes[s].just_respawn = 0;
230 ngx_processes[s].just_spawn = 0;
219231 ngx_processes[s].detached = 0;
220232 break;
221233
222234 case NGX_PROCESS_JUST_RESPAWN:
223235 ngx_processes[s].respawn = 1;
224 ngx_processes[s].just_respawn = 1;
236 ngx_processes[s].just_spawn = 1;
225237 ngx_processes[s].detached = 0;
226238 break;
227239
228240 case NGX_PROCESS_DETACHED:
229241 ngx_processes[s].respawn = 0;
230 ngx_processes[s].just_respawn = 0;
242 ngx_processes[s].just_spawn = 0;
231243 ngx_processes[s].detached = 1;
232244 break;
233245 }
2626 char *name;
2727
2828 unsigned respawn:1;
29 unsigned just_respawn:1;
29 unsigned just_spawn:1;
3030 unsigned detached:1;
3131 unsigned exiting:1;
3232 unsigned exited:1;
4444 #define NGX_MAX_PROCESSES 1024
4545
4646 #define NGX_PROCESS_NORESPAWN -1
47 #define NGX_PROCESS_RESPAWN -2
48 #define NGX_PROCESS_JUST_RESPAWN -3
49 #define NGX_PROCESS_DETACHED -4
47 #define NGX_PROCESS_JUST_SPAWN -2
48 #define NGX_PROCESS_RESPAWN -3
49 #define NGX_PROCESS_JUST_RESPAWN -4
50 #define NGX_PROCESS_DETACHED -5
5051
5152
5253 #define ngx_getpid getpid
1111
1212 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
1313 ngx_int_t type);
14 static void ngx_start_cache_manager_process(ngx_cycle_t *cycle, ngx_int_t type);
14 static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle,
15 ngx_uint_t respawn);
16 static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch);
1517 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
1618 static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
1719 static void ngx_master_process_exit(ngx_cycle_t *cycle);
2527 #endif
2628 static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data);
2729 static void ngx_cache_manager_process_handler(ngx_event_t *ev);
30 static void ngx_cache_loader_process_handler(ngx_event_t *ev);
2831
2932
3033 ngx_uint_t ngx_process;
5962
6063 u_long cpu_affinity;
6164 static u_char master_process[] = "master process";
65
66
67 static ngx_cache_manager_ctx_t ngx_cache_manager_ctx = {
68 ngx_cache_manager_process_handler, "cache manager process", 0
69 };
70
71 static ngx_cache_manager_ctx_t ngx_cache_loader_ctx = {
72 ngx_cache_loader_process_handler, "cache loader process", 60000
73 };
6274
6375
6476 static ngx_cycle_t ngx_exit_cycle;
122134
123135 ngx_start_worker_processes(cycle, ccf->worker_processes,
124136 NGX_PROCESS_RESPAWN);
125 ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN);
137 ngx_start_cache_manager_processes(cycle, 0);
126138
127139 ngx_new_binary = 0;
128140 delay = 0;
206218 if (ngx_new_binary) {
207219 ngx_start_worker_processes(cycle, ccf->worker_processes,
208220 NGX_PROCESS_RESPAWN);
209 ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN);
221 ngx_start_cache_manager_processes(cycle, 0);
210222 ngx_noaccepting = 0;
211223
212224 continue;
225237 ngx_core_module);
226238 ngx_start_worker_processes(cycle, ccf->worker_processes,
227239 NGX_PROCESS_JUST_RESPAWN);
228 ngx_start_cache_manager_process(cycle, NGX_PROCESS_JUST_RESPAWN);
240 ngx_start_cache_manager_processes(cycle, 1);
229241 live = 1;
230242 ngx_signal_worker_processes(cycle,
231243 ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
235247 ngx_restart = 0;
236248 ngx_start_worker_processes(cycle, ccf->worker_processes,
237249 NGX_PROCESS_RESPAWN);
238 ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN);
250 ngx_start_cache_manager_processes(cycle, 0);
239251 live = 1;
240252 }
241253
320332 static void
321333 ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
322334 {
323 ngx_int_t i, s;
335 ngx_int_t i;
324336 ngx_channel_t ch;
325337
326338 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
338350 ch.slot = ngx_process_slot;
339351 ch.fd = ngx_processes[ngx_process_slot].channel[0];
340352
341 for (s = 0; s < ngx_last_process; s++) {
342
343 if (s == ngx_process_slot
344 || ngx_processes[s].pid == -1
345 || ngx_processes[s].channel[0] == -1)
346 {
347 continue;
348 }
349
350 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
351 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
352 ch.slot, ch.pid, ch.fd,
353 s, ngx_processes[s].pid,
354 ngx_processes[s].channel[0]);
355
356 /* TODO: NGX_AGAIN */
357
358 ngx_write_channel(ngx_processes[s].channel[0],
359 &ch, sizeof(ngx_channel_t), cycle->log);
360 }
353 ngx_pass_open_channel(cycle, &ch);
361354 }
362355 }
363356
364357
365358 static void
366 ngx_start_cache_manager_process(ngx_cycle_t *cycle, ngx_int_t type)
367 {
368 ngx_int_t i;
369 ngx_uint_t n;
359 ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn)
360 {
361 ngx_uint_t i, manager, loader;
370362 ngx_path_t **path;
371363 ngx_channel_t ch;
372364
365 manager = 0;
366 loader = 0;
367
373368 path = ngx_cycle->pathes.elts;
374 for (n = 0; n < ngx_cycle->pathes.nelts; n++) {
375 if (path[n]->manager) {
376 goto start;
377 }
378 }
379
380 return;
381
382 start:
369 for (i = 0; i < ngx_cycle->pathes.nelts; i++) {
370
371 if (path[i]->manager) {
372 manager = 1;
373 }
374
375 if (path[i]->loader) {
376 loader = 1;
377 }
378 }
379
380 if (manager == 0) {
381 return;
382 }
383
384 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
385 &ngx_cache_manager_ctx, "cache manager process",
386 respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN);
383387
384388 ch.command = NGX_CMD_OPEN_CHANNEL;
385
386 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, NULL,
387 "cache manager process", type);
388
389389 ch.pid = ngx_processes[ngx_process_slot].pid;
390390 ch.slot = ngx_process_slot;
391391 ch.fd = ngx_processes[ngx_process_slot].channel[0];
392
393 ngx_pass_open_channel(cycle, &ch);
394
395 if (loader == 0) {
396 return;
397 }
398
399 ngx_spawn_process(cycle, ngx_cache_manager_process_cycle,
400 &ngx_cache_loader_ctx, "cache loader process",
401 respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN);
402
403 ch.command = NGX_CMD_OPEN_CHANNEL;
404 ch.pid = ngx_processes[ngx_process_slot].pid;
405 ch.slot = ngx_process_slot;
406 ch.fd = ngx_processes[ngx_process_slot].channel[0];
407
408 ngx_pass_open_channel(cycle, &ch);
409 }
410
411
412 static void
413 ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
414 {
415 ngx_int_t i;
392416
393417 for (i = 0; i < ngx_last_process; i++) {
394418
401425
402426 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
403427 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
404 ch.slot, ch.pid, ch.fd,
428 ch->slot, ch->pid, ch->fd,
405429 i, ngx_processes[i].pid,
406430 ngx_processes[i].channel[0]);
407431
408432 /* TODO: NGX_AGAIN */
409433
410434 ngx_write_channel(ngx_processes[i].channel[0],
411 &ch, sizeof(ngx_channel_t), cycle->log);
435 ch, sizeof(ngx_channel_t), cycle->log);
412436 }
413437 }
414438
459483 ngx_processes[i].exited,
460484 ngx_processes[i].detached,
461485 ngx_processes[i].respawn,
462 ngx_processes[i].just_respawn);
486 ngx_processes[i].just_spawn);
463487
464488 if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
465489 continue;
466490 }
467491
468 if (ngx_processes[i].just_respawn) {
469 ngx_processes[i].just_respawn = 0;
492 if (ngx_processes[i].just_spawn) {
493 ngx_processes[i].just_spawn = 0;
470494 continue;
471495 }
472496
535559 ngx_processes[i].exited,
536560 ngx_processes[i].detached,
537561 ngx_processes[i].respawn,
538 ngx_processes[i].just_respawn);
562 ngx_processes[i].just_spawn);
539563
540564 if (ngx_processes[i].pid == -1) {
541565 continue;
592616 ch.slot = ngx_process_slot;
593617 ch.fd = ngx_processes[ngx_process_slot].channel[0];
594618
595 for (n = 0; n < ngx_last_process; n++) {
596
597 if (n == ngx_process_slot
598 || ngx_processes[n].pid == -1
599 || ngx_processes[n].channel[0] == -1)
600 {
601 continue;
602 }
603
604 ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
605 "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
606 ch.slot, ch.pid, ch.fd,
607 n, ngx_processes[n].pid,
608 ngx_processes[n].channel[0]);
609
610 /* TODO: NGX_AGAIN */
611
612 ngx_write_channel(ngx_processes[n].channel[0],
613 &ch, sizeof(ngx_channel_t), cycle->log);
614 }
619 ngx_pass_open_channel(cycle, &ch);
615620
616621 live = 1;
617622
12671272 static void
12681273 ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
12691274 {
1275 ngx_cache_manager_ctx_t *ctx = data;
1276
12701277 void *ident[4];
12711278 ngx_event_t ev;
12721279
12771284 ngx_close_listening_sockets(cycle);
12781285
12791286 ngx_memzero(&ev, sizeof(ngx_event_t));
1280 ev.handler = ngx_cache_manager_process_handler;
1287 ev.handler = ctx->handler;
12811288 ev.data = ident;
12821289 ev.log = cycle->log;
12831290 ident[3] = (void *) -1;
12841291
12851292 ngx_use_accept_mutex = 0;
12861293
1287 ngx_setproctitle("cache manager process");
1288
1289 ngx_add_timer(&ev, 0);
1294 ngx_setproctitle(ctx->name);
1295
1296 ngx_add_timer(&ev, ctx->delay);
12901297
12911298 for ( ;; ) {
12921299
13331340
13341341 ngx_add_timer(ev, next * 1000);
13351342 }
1343
1344
1345 static void
1346 ngx_cache_loader_process_handler(ngx_event_t *ev)
1347 {
1348 ngx_uint_t i;
1349 ngx_path_t **path;
1350 ngx_cycle_t *cycle;
1351
1352 cycle = (ngx_cycle_t *) ngx_cycle;
1353
1354 path = cycle->pathes.elts;
1355 for (i = 0; i < cycle->pathes.nelts; i++) {
1356
1357 if (ngx_terminate || ngx_quit) {
1358 break;
1359 }
1360
1361 if (path[i]->loader) {
1362 path[i]->loader(path[i]->data);
1363 ngx_time_update(0, 0);
1364 }
1365 }
1366
1367 exit(0);
1368 }
2424 #define NGX_PROCESS_SIGNALLER 3
2525
2626
27 typedef struct {
28 ngx_event_handler_pt handler;
29 char *name;
30 ngx_msec_t delay;
31 } ngx_cache_manager_ctx_t;
32
33
2734 void ngx_master_process_cycle(ngx_cycle_t *cycle);
2835 void ngx_single_process_cycle(ngx_cycle_t *cycle);
2936
162162 switch (respawn) {
163163
164164 case NGX_PROCESS_RESPAWN:
165 ngx_processes[s].just_respawn = 0;
165 ngx_processes[s].just_spawn = 0;
166166 break;
167167
168168 case NGX_PROCESS_JUST_RESPAWN:
169 ngx_processes[s].just_respawn = 1;
169 ngx_processes[s].just_spawn = 1;
170170 break;
171171 }
172172
3232 u_char quit_event[NGX_PROCESS_SYNC_NAME];
3333 u_char reopen_event[NGX_PROCESS_SYNC_NAME];
3434
35 unsigned just_respawn:1;
35 unsigned just_spawn:1;
3636 unsigned exiting:1;
3737 } ngx_process_t;
3838
2424 static ngx_thread_value_t __stdcall ngx_worker_thread(void *data);
2525 static ngx_thread_value_t __stdcall ngx_cache_manager_thread(void *data);
2626 static void ngx_cache_manager_process_handler(void);
27 static ngx_thread_value_t __stdcall ngx_cache_loader_thread(void *data);
2728
2829
2930 ngx_uint_t ngx_process;
439440 ngx_processes[n].pid,
440441 ngx_processes[n].handle,
441442 ngx_processes[n].exiting,
442 ngx_processes[n].just_respawn);
443
444 if (old && ngx_processes[n].just_respawn) {
445 ngx_processes[n].just_respawn = 0;
443 ngx_processes[n].just_spawn);
444
445 if (old && ngx_processes[n].just_spawn) {
446 ngx_processes[n].just_spawn = 0;
446447 continue;
447448 }
448449
549550 ngx_processes[n].pid,
550551 ngx_processes[n].handle,
551552 ngx_processes[n].exiting,
552 ngx_processes[n].just_respawn);
553 ngx_processes[n].just_spawn);
553554
554555 if (ngx_processes[n].handle) {
555556 return 1;
666667 }
667668
668669 if (ngx_create_thread(&cmtid, ngx_cache_manager_thread, NULL, log) != 0) {
670 goto failed;
671 }
672
673 if (ngx_create_thread(&cmtid, ngx_cache_loader_thread, NULL, log) != 0) {
669674 goto failed;
670675 }
671676
924929 return 0;
925930 }
926931
927 break;
932 break;
928933 }
929934
930935 for ( ;; ) {
981986 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
982987 "cache manager WaitForSingleObject: %ul", ev);
983988 }
989 }
990
991
992 static ngx_thread_value_t __stdcall
993 ngx_cache_loader_thread(void *data)
994 {
995 ngx_uint_t i;
996 ngx_path_t **path;
997 ngx_cycle_t *cycle;
998
999 ngx_msleep(60000);
1000
1001 cycle = (ngx_cycle_t *) ngx_cycle;
1002
1003 path = cycle->pathes.elts;
1004 for (i = 0; i < cycle->pathes.nelts; i++) {
1005
1006 if (ngx_terminate || ngx_quit) {
1007 break;
1008 }
1009
1010 if (path[i]->loader) {
1011 path[i]->loader(path[i]->data);
1012 ngx_time_update(0, 0);
1013 }
1014 }
1015
1016 return 0;
9841017 }
9851018
9861019