changeset 3018:8fc7b94f647b

cache loader process
author Igor Sysoev <igor@sysoev.ru>
date Mon, 10 Aug 2009 13:27:14 +0000
parents c466605d9426
children 56d1e38a0dda
files src/core/ngx_file.c src/core/ngx_file.h src/http/ngx_http_cache.h src/http/ngx_http_file_cache.c src/os/unix/ngx_process_cycle.c src/os/unix/ngx_process_cycle.h
diffstat 6 files changed, 164 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- 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) {
--- 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;
--- 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;
 
--- 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) {
--- 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);
+}
--- 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);