# HG changeset patch # User Igor Sysoev # Date 1249910834 0 # Node ID 8fc7b94f647b6286103dcc7d6a4c949cb438d28c # Parent c466605d942687b45ab2feff47045e3b0cfe53df cache loader process diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -264,7 +264,8 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, n } path->len = 0; - path->manager = (ngx_path_manager_pt) cmd->post; + path->manager = NULL; + path->loader = NULL; path->conf_file = cf->conf_file->file.name.data; path->line = cf->conf_file->line; @@ -325,6 +326,7 @@ ngx_conf_merge_path_value(ngx_conf_t *cf + init->level[2] + (init->level[2] ? 1 : 0); (*path)->manager = NULL; + (*path)->loader = NULL; (*path)->conf_file = NULL; if (ngx_add_path(cf, path) != NGX_OK) { diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -30,6 +30,7 @@ struct ngx_file_s { typedef time_t (*ngx_path_manager_pt) (void *data); +typedef void (*ngx_path_loader_pt) (void *data); typedef struct { @@ -38,6 +39,7 @@ typedef struct { size_t level[3]; ngx_path_manager_pt manager; + ngx_path_loader_pt loader; void *data; u_char *conf_file; diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -97,6 +97,7 @@ typedef struct { ngx_rbtree_node_t sentinel; ngx_queue_t queue; ngx_atomic_t cold; + ngx_atomic_t loading; off_t size; } ngx_http_file_cache_sh_t; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -85,6 +85,10 @@ ngx_http_file_cache_init(ngx_shm_zone_t cache->max_size /= cache->bsize; + if (!cache->sh->cold || cache->sh->loading) { + cache->path->loader = NULL; + } + return NGX_OK; } @@ -110,6 +114,7 @@ ngx_http_file_cache_init(ngx_shm_zone_t ngx_queue_init(&cache->sh->queue); cache->sh->cold = 1; + cache->sh->loading = 0; cache->sh->size = 0; cache->bsize = ngx_fs_bsize(cache->path->name.data); @@ -1036,39 +1041,8 @@ ngx_http_file_cache_manager(void *data) { ngx_http_file_cache_t *cache = data; - off_t size; - time_t next; - ngx_tree_ctx_t tree; - - if (cache->sh->cold) { - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, - "http file cache manager update"); - - tree.init_handler = NULL; - tree.file_handler = ngx_http_file_cache_manage_file; - tree.pre_tree_handler = ngx_http_file_cache_noop; - tree.post_tree_handler = ngx_http_file_cache_noop; - tree.spec_handler = ngx_http_file_cache_delete_file; - tree.data = cache; - tree.alloc = 0; - tree.log = ngx_cycle->log; - - cache->last = ngx_current_msec; - cache->files = 0; - - if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) { - return 10; - } - - cache->sh->cold = 0; - - ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, - "http file cache: %V %.3fM, bsize: %uz", - &cache->path->name, - ((double) cache->sh->size * cache->bsize) / (1024 * 1024), - cache->bsize); - } + off_t size; + time_t next; next = ngx_http_file_cache_expire(cache); @@ -1098,6 +1072,51 @@ ngx_http_file_cache_manager(void *data) } +static void +ngx_http_file_cache_loader(void *data) +{ + ngx_http_file_cache_t *cache = data; + + ngx_tree_ctx_t tree; + + if (!cache->sh->cold || cache->sh->loading) { + return; + } + + if (!ngx_atomic_cmp_set(&cache->sh->loading, 0, ngx_pid)) { + return; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http file cache loader"); + + tree.init_handler = NULL; + tree.file_handler = ngx_http_file_cache_manage_file; + tree.pre_tree_handler = ngx_http_file_cache_noop; + tree.post_tree_handler = ngx_http_file_cache_noop; + tree.spec_handler = ngx_http_file_cache_delete_file; + tree.data = cache; + tree.alloc = 0; + tree.log = ngx_cycle->log; + + cache->last = ngx_current_msec; + cache->files = 0; + + if (ngx_walk_tree(&tree, &cache->path->name) == NGX_ABORT) { + return; + } + + cache->sh->cold = 0; + cache->sh->loading = 0; + + ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, + "http file cache: %V %.3fM, bsize: %uz", + &cache->path->name, + ((double) cache->sh->size * cache->bsize) / (1024 * 1024), + cache->bsize); +} + + static ngx_int_t ngx_http_file_cache_manager_sleep(ngx_http_file_cache_t *cache) { @@ -1478,6 +1497,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t } cache->path->manager = ngx_http_file_cache_manager; + cache->path->loader = ngx_http_file_cache_loader; cache->path->data = cache; if (ngx_add_path(cf, &cache->path) != NGX_OK) { diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -12,7 +12,9 @@ static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type); -static void ngx_start_cache_manager_process(ngx_cycle_t *cycle, ngx_int_t type); +static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, + ngx_uint_t respawn); +static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch); static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle); static void ngx_master_process_exit(ngx_cycle_t *cycle); @@ -26,6 +28,7 @@ static ngx_thread_value_t ngx_worker_thr #endif static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data); static void ngx_cache_manager_process_handler(ngx_event_t *ev); +static void ngx_cache_loader_process_handler(ngx_event_t *ev); ngx_uint_t ngx_process; @@ -61,6 +64,15 @@ u_long cpu_affinity; static u_char master_process[] = "master process"; +static ngx_cache_manager_ctx_t ngx_cache_manager_ctx = { + ngx_cache_manager_process_handler, "cache manager process", 0 +}; + +static ngx_cache_manager_ctx_t ngx_cache_loader_ctx = { + ngx_cache_loader_process_handler, "cache loader process", 60000 +}; + + static ngx_cycle_t ngx_exit_cycle; static ngx_log_t ngx_exit_log; static ngx_open_file_t ngx_exit_log_file; @@ -122,7 +134,7 @@ ngx_master_process_cycle(ngx_cycle_t *cy ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); - ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN); + ngx_start_cache_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; @@ -203,7 +215,7 @@ ngx_master_process_cycle(ngx_cycle_t *cy if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); - ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN); + ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; @@ -222,7 +234,7 @@ ngx_master_process_cycle(ngx_cycle_t *cy ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); - ngx_start_cache_manager_process(cycle, NGX_PROCESS_JUST_RESPAWN); + ngx_start_cache_manager_processes(cycle, 1); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); @@ -232,7 +244,7 @@ ngx_master_process_cycle(ngx_cycle_t *cy ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); - ngx_start_cache_manager_process(cycle, NGX_PROCESS_RESPAWN); + ngx_start_cache_manager_processes(cycle, 0); live = 1; } @@ -317,7 +329,7 @@ ngx_single_process_cycle(ngx_cycle_t *cy static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) { - ngx_int_t i, s; + ngx_int_t i; ngx_channel_t ch; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes"); @@ -335,58 +347,70 @@ ngx_start_worker_processes(ngx_cycle_t * ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; - for (s = 0; s < ngx_last_process; s++) { - - if (s == ngx_process_slot - || ngx_processes[s].pid == -1 - || ngx_processes[s].channel[0] == -1) - { - continue; - } - - ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, - "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", - ch.slot, ch.pid, ch.fd, - s, ngx_processes[s].pid, - ngx_processes[s].channel[0]); - - /* TODO: NGX_AGAIN */ - - ngx_write_channel(ngx_processes[s].channel[0], - &ch, sizeof(ngx_channel_t), cycle->log); - } + ngx_pass_open_channel(cycle, &ch); } } static void -ngx_start_cache_manager_process(ngx_cycle_t *cycle, ngx_int_t type) +ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) { - ngx_int_t i; - ngx_uint_t n; + ngx_uint_t i, manager, loader; ngx_path_t **path; ngx_channel_t ch; + manager = 0; + loader = 0; + path = ngx_cycle->pathes.elts; - for (n = 0; n < ngx_cycle->pathes.nelts; n++) { - if (path[n]->manager) { - goto start; + for (i = 0; i < ngx_cycle->pathes.nelts; i++) { + + if (path[i]->manager) { + manager = 1; + } + + if (path[i]->loader) { + loader = 1; } } - return; + if (manager == 0) { + return; + } -start: + ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, + &ngx_cache_manager_ctx, "cache manager process", + respawn ? NGX_PROCESS_JUST_RESPAWN : NGX_PROCESS_RESPAWN); ch.command = NGX_CMD_OPEN_CHANNEL; - - ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, NULL, - "cache manager process", type); - ch.pid = ngx_processes[ngx_process_slot].pid; ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; + ngx_pass_open_channel(cycle, &ch); + + if (loader == 0) { + return; + } + + ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, + &ngx_cache_loader_ctx, "cache loader process", + respawn ? NGX_PROCESS_JUST_SPAWN : NGX_PROCESS_NORESPAWN); + + ch.command = NGX_CMD_OPEN_CHANNEL; + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + ngx_pass_open_channel(cycle, &ch); +} + + +static void +ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) +{ + ngx_int_t i; + for (i = 0; i < ngx_last_process; i++) { if (i == ngx_process_slot @@ -398,14 +422,14 @@ start: ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", - ch.slot, ch.pid, ch.fd, + ch->slot, ch->pid, ch->fd, i, ngx_processes[i].pid, ngx_processes[i].channel[0]); /* TODO: NGX_AGAIN */ ngx_write_channel(ngx_processes[i].channel[0], - &ch, sizeof(ngx_channel_t), cycle->log); + ch, sizeof(ngx_channel_t), cycle->log); } } @@ -590,26 +614,7 @@ ngx_reap_children(ngx_cycle_t *cycle) ch.slot = ngx_process_slot; ch.fd = ngx_processes[ngx_process_slot].channel[0]; - for (n = 0; n < ngx_last_process; n++) { - - if (n == ngx_process_slot - || ngx_processes[n].pid == -1 - || ngx_processes[n].channel[0] == -1) - { - continue; - } - - ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, - "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", - ch.slot, ch.pid, ch.fd, - n, ngx_processes[n].pid, - ngx_processes[n].channel[0]); - - /* TODO: NGX_AGAIN */ - - ngx_write_channel(ngx_processes[n].channel[0], - &ch, sizeof(ngx_channel_t), cycle->log); - } + ngx_pass_open_channel(cycle, &ch); live = 1; @@ -1265,6 +1270,8 @@ ngx_worker_thread_cycle(void *data) static void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data) { + ngx_cache_manager_ctx_t *ctx = data; + void *ident[4]; ngx_event_t ev; @@ -1275,16 +1282,16 @@ ngx_cache_manager_process_cycle(ngx_cycl ngx_close_listening_sockets(cycle); ngx_memzero(&ev, sizeof(ngx_event_t)); - ev.handler = ngx_cache_manager_process_handler; + ev.handler = ctx->handler; ev.data = ident; ev.log = cycle->log; ident[3] = (void *) -1; ngx_use_accept_mutex = 0; - ngx_setproctitle("cache manager process"); + ngx_setproctitle(ctx->name); - ngx_add_timer(&ev, 0); + ngx_add_timer(&ev, ctx->delay); for ( ;; ) { @@ -1331,3 +1338,31 @@ ngx_cache_manager_process_handler(ngx_ev ngx_add_timer(ev, next * 1000); } + + +static void +ngx_cache_loader_process_handler(ngx_event_t *ev) +{ + ngx_uint_t i; + ngx_path_t **path; + ngx_cycle_t *cycle; + + cycle = (ngx_cycle_t *) ngx_cycle; + + path = cycle->pathes.elts; + for (i = 0; i < cycle->pathes.nelts; i++) { + + if (ngx_terminate || ngx_quit) { + break; + } + + if (path[i]->loader) { + path[i]->loader(path[i]->data); + ngx_time_update(0, 0); + } + } + +sleep(50); + + exit(0); +} diff --git a/src/os/unix/ngx_process_cycle.h b/src/os/unix/ngx_process_cycle.h --- a/src/os/unix/ngx_process_cycle.h +++ b/src/os/unix/ngx_process_cycle.h @@ -25,6 +25,13 @@ #define NGX_PROCESS_SIGNALLER 3 +typedef struct { + ngx_event_handler_pt handler; + char *name; + ngx_msec_t delay; +} ngx_cache_manager_ctx_t; + + void ngx_master_process_cycle(ngx_cycle_t *cycle); void ngx_single_process_cycle(ngx_cycle_t *cycle);