summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2009-08-17 18:00:02 +0000
committerJonathan Kolb <jon@b0g.us>2009-08-17 18:00:02 +0000
commit6538d1e13bd5889e3c64c07a01b4a3cb28c52722 (patch)
tree28e0291c92bf7ec755c984b4d6452a58f7a76e72
parent28ee64eb5666e0dff44f597e3791234cf2275ffd (diff)
downloadnginx-6538d1e13bd5889e3c64c07a01b4a3cb28c52722.tar.gz
Changes with nginx 0.8.9 17 Aug 2009v0.8.9
*) Feature: now the start cache loader runs in a separate process; this should improve large caches handling. *) Feature: now temporarily files and permanent storage area may reside at different file systems.
-rw-r--r--CHANGES9
-rw-r--r--CHANGES.ru9
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_file.c196
-rw-r--r--src/core/ngx_file.h16
-rw-r--r--src/http/modules/ngx_http_dav_module.c115
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c49
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_cache.h1
-rw-r--r--src/http/ngx_http_file_cache.c98
-rw-r--r--src/http/ngx_http_upstream.c1
-rw-r--r--src/os/unix/ngx_errno.h1
-rw-r--r--src/os/unix/ngx_process.c18
-rw-r--r--src/os/unix/ngx_process.h9
-rw-r--r--src/os/unix/ngx_process_cycle.c170
-rw-r--r--src/os/unix/ngx_process_cycle.h7
16 files changed, 445 insertions, 260 deletions
diff --git a/CHANGES b/CHANGES
index 77afb576e..e2355b7a0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,13 @@
+Changes with nginx 0.8.9 17 Aug 2009
+
+ *) Feature: now the start cache loader runs in a separate process; this
+ should improve large caches handling.
+
+ *) Feature: now temporarily files and permanent storage area may reside
+ at different file systems.
+
+
Changes with nginx 0.8.8 10 Aug 2009
*) Bugfix: in handling FastCGI headers split in records.
diff --git a/CHANGES.ru b/CHANGES.ru
index 282e0b05e..86066365b 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,13 @@
+Изменения в nginx 0.8.9 17.08.2009
+
+ *) Добавление: теперь стартовый загрузчик кэша работает в отдельном
+ процесс; это должно улучшить обработку больших кэшей.
+
+ *) Добавление: теперь временные файлы и постоянное место хранения могут
+ располагаться на разных файловых системах.
+
+
Изменения в nginx 0.8.8 10.08.2009
*) Исправление: в обработке заголовков ответа, разделённых в
diff --git a/src/core/nginx.h b/src/core/nginx.h
index dc8d27138..e1ec63b66 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 8008
-#define NGINX_VERSION "0.8.8"
+#define nginx_version 8009
+#define NGINX_VERSION "0.8.9"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 3f47fc98b..dff522674 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -99,13 +99,7 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool,
continue;
}
- if ((path->level[0] == 0)
- || (err != NGX_ENOENT
-#if (NGX_WIN32)
- && err != NGX_ENOTDIR
-#endif
- ))
- {
+ if ((path->level[0] == 0) || (err != NGX_ENOPATH)) {
ngx_log_error(NGX_LOG_CRIT, file->log, err,
ngx_open_tempfile_n " \"%s\" failed",
file->name.data);
@@ -264,7 +258,8 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
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 +320,7 @@ ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev,
+ 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) {
@@ -528,7 +524,9 @@ ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user)
ngx_int_t
ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
{
- ngx_err_t err;
+ u_char *name;
+ ngx_err_t err;
+ ngx_copy_file_t cf;
#if !(NGX_WIN32)
@@ -558,14 +556,8 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
err = ngx_errno;
- if (err
-#if (NGX_WIN32)
- == ERROR_PATH_NOT_FOUND
-#else
- == NGX_ENOENT
-#endif
- )
- {
+ if (err == NGX_ENOPATH) {
+
if (!ext->create_path) {
goto failed;
}
@@ -605,6 +597,44 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
#endif
+ if (err == NGX_EXDEV) {
+
+ cf.size = -1;
+ cf.buf_size = 0;
+ cf.access = ext->access;
+ cf.time = ext->time;
+ cf.log = ext->log;
+
+ name = ngx_alloc(to->len + 1 + 10, ext->log);
+ if (name == NULL) {
+ return NGX_ERROR;
+ }
+
+ (void) ngx_sprintf(name, "%*s.%010uD%Z", to->len - 1, to->data,
+ (uint32_t) ngx_next_temp_number(0));
+
+ if (ngx_copy_file(src->data, name, &cf) == NGX_OK) {
+
+ if (ngx_rename_file(name, to->data) == NGX_FILE_ERROR) {
+ ngx_free(name);
+ goto failed;
+ }
+
+ ngx_free(name);
+
+ if (ngx_delete_file(src->data) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
+ ngx_delete_file_n " \"%s\" failed", src->data);
+
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+ }
+
+ ngx_free(name);
+ }
+
failed:
if (ext->delete_file) {
@@ -614,18 +644,144 @@ failed:
}
}
- if (err && ext->log_rename_error) {
+ if (err) {
ngx_log_error(NGX_LOG_CRIT, ext->log, err,
ngx_rename_file_n " \"%s\" to \"%s\" failed",
src->data, to->data);
}
- ext->rename_error = err;
-
return NGX_ERROR;
}
+ngx_int_t
+ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf)
+{
+ char *buf;
+ off_t size;
+ size_t len;
+ ssize_t n;
+ ngx_fd_t fd, nfd;
+ ngx_int_t rc;
+ ngx_file_info_t fi;
+
+ rc = NGX_ERROR;
+ buf = NULL;
+ nfd = NGX_INVALID_FILE;
+
+ fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+
+ if (fd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno,
+ ngx_open_file_n " \"%s\" failed", from);
+ goto failed;
+ }
+
+ if (cf->size != -1) {
+ size = cf->size;
+
+ } else {
+ if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_fd_info_n " \"%s\" failed", from);
+
+ goto failed;
+ }
+
+ size = ngx_file_size(&fi);
+ }
+
+ len = cf->buf_size ? cf->buf_size : 65536;
+
+ if ((off_t) len > size) {
+ len = (size_t) size;
+ }
+
+ buf = ngx_alloc(len, cf->log);
+ if (buf == NULL) {
+ goto failed;
+ }
+
+ nfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
+ cf->access);
+
+ if (nfd == NGX_INVALID_FILE) {
+ ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno,
+ ngx_open_file_n " \"%s\" failed", to);
+ goto failed;
+ }
+
+ while (size > 0) {
+
+ if ((off_t) len > size) {
+ len = (size_t) size;
+ }
+
+ n = ngx_read_fd(fd, buf, len);
+
+ if (n == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_read_fd_n " \"%s\" failed", from);
+ goto failed;
+ }
+
+ if ((size_t) n != len) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_read_fd_n " has read only %z of %uz from %s",
+ n, size, from);
+ goto failed;
+ }
+
+ n = ngx_write_fd(nfd, buf, len);
+
+ if (n == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_write_fd_n " \"%s\" failed", to);
+ goto failed;
+ }
+
+ if ((size_t) n != len) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_write_fd_n " has written only %z of %uz to %s",
+ n, size, to);
+ goto failed;
+ }
+
+ size -= n;
+ }
+
+ if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_set_file_time_n " \"%s\" failed", to);
+ goto failed;
+ }
+
+ rc = NGX_OK;
+
+failed:
+
+ if (nfd != NGX_INVALID_FILE) {
+ if (ngx_close_file(nfd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", to);
+ }
+ }
+
+ if (fd != NGX_INVALID_FILE) {
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", from);
+ }
+ }
+
+ if (buf) {
+ ngx_free(buf);
+ }
+
+ return rc;
+}
+
+
/*
* ctx->init_handler() - see ctx->alloc
* ctx->file_handler() - file handler
diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h
index 264ba391b..0da8646eb 100644
--- 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;
@@ -71,16 +73,25 @@ typedef struct {
ngx_uint_t path_access;
time_t time;
ngx_fd_t fd;
- ngx_err_t rename_error;
unsigned create_path:1;
unsigned delete_file:1;
- unsigned log_rename_error:1;
ngx_log_t *log;
} ngx_ext_rename_file_t;
+typedef struct {
+ off_t size;
+ size_t buf_size;
+
+ ngx_uint_t access;
+ time_t time;
+
+ ngx_log_t *log;
+} ngx_copy_file_t;
+
+
typedef struct ngx_tree_ctx_s ngx_tree_ctx_t;
typedef ngx_int_t (*ngx_tree_init_handler_pt) (void *ctx, void *prev);
@@ -115,6 +126,7 @@ ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot);
ngx_int_t ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user);
ngx_int_t ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to,
ngx_ext_rename_file_t *ext);
+ngx_int_t ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf);
ngx_int_t ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree);
void ngx_init_temp_number(void);
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index 7f53d5416..753387acc 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -53,8 +53,6 @@ static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx,
ngx_str_t *path);
static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx,
ngx_str_t *path);
-static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from,
- u_char *to);
static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt);
static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err,
@@ -249,7 +247,6 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
ext.time = -1;
ext.create_path = dlcf->create_full_put_path;
ext.delete_file = 1;
- ext.log_rename_error = 1;
ext.log = r->connection->log;
if (r->headers_in.date) {
@@ -520,6 +517,7 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
ngx_uint_t overwrite, slash, dir;
ngx_str_t path, uri;
ngx_tree_ctx_t tree;
+ ngx_copy_file_t cf;
ngx_file_info_t fi;
ngx_table_elt_t *dest, *over;
ngx_ext_rename_file_t ext;
@@ -791,43 +789,24 @@ overwrite_done:
ext.time = -1;
ext.create_path = 1;
ext.delete_file = 0;
- ext.log_rename_error = 0;
ext.log = r->connection->log;
if (ngx_ext_rename_file(&path, &copy.path, &ext) == NGX_OK) {
return NGX_HTTP_NO_CONTENT;
}
- if (ext.rename_error != NGX_EXDEV) {
-
- if (ext.rename_error) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log,
- ext.rename_error,
- ngx_rename_file_n " \"%s\" to \"%s\" failed",
- path.data, copy.path.data);
- }
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
- tree.size = ngx_file_size(&fi);
- tree.mtime = ngx_file_mtime(&fi);
- tree.access = dlcf->access;
- tree.log = r->connection->log;
-
- if (ngx_http_dav_copy_file(&tree, path.data, copy.path.data) == NGX_OK)
- {
- if (r->method == NGX_HTTP_MOVE) {
- rc = ngx_http_dav_delete_path(r, &path, 0);
-
- if (rc != NGX_OK) {
- return rc;
- }
- }
+ cf.size = ngx_file_size(&fi);
+ cf.buf_size = 0;
+ cf.access = dlcf->access;
+ cf.time = ngx_file_mtime(&fi);
+ cf.log = r->connection->log;
+ if (ngx_copy_file(path.data, copy.path.data, &cf) == NGX_OK) {
return NGX_HTTP_NO_CONTENT;
}
}
@@ -941,6 +920,7 @@ ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
{
u_char *p, *file;
size_t len;
+ ngx_copy_file_t cf;
ngx_http_dav_copy_ctx_t *copy;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
@@ -961,7 +941,13 @@ ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
"http copy file to: \"%s\"", file);
- (void) ngx_http_dav_copy_file(ctx, path->data, file);
+ cf.size = ctx->size;
+ cf.buf_size = 0;
+ cf.access = ctx->access;
+ cf.time = ctx->mtime;
+ cf.log = ctx->log;
+
+ (void) ngx_copy_file(path->data, file, &cf);
ngx_free(file);
@@ -970,75 +956,6 @@ ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
static ngx_int_t
-ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to)
-{
- off_t size;
- ssize_t n;
- ngx_fd_t fd, cfd;
- ngx_int_t rc;
- u_char buf[NGX_HTTP_DAV_COPY_BLOCK];
-
- fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
-
- if (fd == NGX_INVALID_FILE) {
- (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n,
- from);
- return NGX_ERROR;
- }
-
- cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
- ctx->access);
-
- rc = NGX_ERROR;
-
- if (cfd == NGX_INVALID_FILE) {
- (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to);
- goto failed;
- }
-
- for (size = ctx->size; size > 0; size -= n) {
-
- n = ngx_read_fd(fd, buf, NGX_HTTP_DAV_COPY_BLOCK);
-
- if (n == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_read_fd_n " \"%s\" failed", from);
- goto failed;
- }
-
- if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_write_fd_n " \"%s\" failed", to);
- goto failed;
- }
- }
-
- if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_set_file_time_n " \"%s\" failed", to);
- goto failed;
- }
-
- if (ngx_close_file(cfd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", to);
- goto failed;
- }
-
- rc = NGX_OK;
-
-failed:
-
- if (ngx_close_file(fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", from);
- }
-
- return rc;
-}
-
-
-static ngx_int_t
ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt)
{
ngx_table_elt_t *depth;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index fc0cf14e1..bdc52b644 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1065,9 +1065,10 @@ ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
static ngx_int_t
ngx_http_fastcgi_process_header(ngx_http_request_t *r)
{
- u_char *p, *start, *last, *part_start, *part_end;
+ u_char *p, *msg, *start, *last,
+ *part_start, *part_end;
size_t size;
- ngx_str_t *status_line, line, *pattern;
+ ngx_str_t *status_line, *pattern;
ngx_int_t rc, status;
ngx_buf_t buf;
ngx_uint_t i;
@@ -1151,40 +1152,39 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
if (f->type == NGX_HTTP_FASTCGI_STDERR) {
if (f->length) {
- line.data = u->buffer.pos;
+ msg = u->buffer.pos;
if (u->buffer.pos + f->length <= u->buffer.last) {
- line.len = f->length;
u->buffer.pos += f->length;
f->length = 0;
f->state = ngx_http_fastcgi_st_padding;
} else {
- line.len = u->buffer.last - u->buffer.pos;
f->length -= u->buffer.last - u->buffer.pos;
u->buffer.pos = u->buffer.last;
}
- while (line.data[line.len - 1] == LF
- || line.data[line.len - 1] == CR
- || line.data[line.len - 1] == '.'
- || line.data[line.len - 1] == ' ')
- {
- line.len--;
+ for (p = u->buffer.pos - 1; msg < p; p--) {
+ if (*p != LF && *p != CR && *p != '.' && *p != ' ') {
+ break;
+ }
}
+ p++;
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "FastCGI sent in stderr: \"%V\"", &line);
+ "FastCGI sent in stderr: \"%*s\"", p - msg, msg);
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
if (flcf->catch_stderr) {
pattern = flcf->catch_stderr->elts;
- line.data[line.len - 1] = '\0';
-
for (i = 0; i < flcf->catch_stderr->nelts; i++) {
- if (ngx_strstr(line.data, pattern[i].data)) {
+ if (ngx_strnstr(msg, (char *) pattern[i].data,
+ p - msg)
+ != NULL)
+ {
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
}
}
@@ -1452,9 +1452,9 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
static ngx_int_t
ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
{
+ u_char *m, *msg;
ngx_int_t rc;
ngx_buf_t *b, **prev;
- ngx_str_t line;
ngx_chain_t *cl;
ngx_http_request_t *r;
ngx_http_fastcgi_ctx_t *f;
@@ -1538,30 +1538,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
break;
}
- line.data = f->pos;
+ msg = f->pos;
if (f->pos + f->length <= f->last) {
- line.len = f->length;
f->pos += f->length;
f->length = 0;
f->state = ngx_http_fastcgi_st_padding;
} else {
- line.len = f->last - f->pos;
f->length -= f->last - f->pos;
f->pos = f->last;
}
- while (line.data[line.len - 1] == LF
- || line.data[line.len - 1] == CR
- || line.data[line.len - 1] == '.'
- || line.data[line.len - 1] == ' ')
- {
- line.len--;
+ for (m = f->pos - 1; msg < m; m--) {
+ if (*m != LF && *m != CR && *m != '.' && *m != ' ') {
+ break;
+ }
}
ngx_log_error(NGX_LOG_ERR, p->log, 0,
- "FastCGI sent in stderr: \"%V\"", &line);
+ "FastCGI sent in stderr: \"%*s\"",
+ m + 1 - msg, msg);
if (f->pos == f->last) {
break;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 52a7bcecc..f3c80a55c 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.8.8';
+our $VERSION = '0.8.9';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index 1ee80751d..6ac6fd876 100644
--- 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
index 8e908a1dc..8972f47dc 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -53,6 +53,7 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data)
ngx_http_file_cache_t *ocache = data;
size_t len;
+ ngx_uint_t n;
ngx_http_file_cache_t *cache;
cache = shm_zone->data;
@@ -68,6 +69,15 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data)
return NGX_ERROR;
}
+ for (n = 0; n < 3; n++) {
+ if (cache->path->level[n] != ocache->path->level[n]) {
+ ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
+ "cache \"%V\" had previously different levels",
+ &shm_zone->shm.name);
+ return NGX_ERROR;
+ }
+ }
+
cache->sh = ocache->sh;
cache->shpool = ocache->shpool;
@@ -75,6 +85,10 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data)
cache->max_size /= cache->bsize;
+ if (!cache->sh->cold || cache->sh->loading) {
+ cache->path->loader = NULL;
+ }
+
return NGX_OK;
}
@@ -100,6 +114,7 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data)
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);
@@ -635,7 +650,6 @@ ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf)
ext.time = -1;
ext.create_path = 1;
ext.delete_file = 1;
- ext.log_rename_error = 1;
ext.log = r->connection->log;
rc = ngx_ext_rename_file(&tf->file.name, &c->file.name, &ext);
@@ -1026,39 +1040,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);
@@ -1088,6 +1071,52 @@ 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) {
+ cache->sh->loading = 0;
+ 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)
{
@@ -1468,6 +1497,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
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/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index e705da6c2..a418eaa2f 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -2635,7 +2635,6 @@ ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
ext.time = -1;
ext.create_path = 1;
ext.delete_file = 1;
- ext.log_rename_error = 1;
ext.log = r->connection->log;
if (u->headers_in.last_modified) {
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index 3dbfa227e..379f36777 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -16,6 +16,7 @@ typedef int ngx_err_t;
#define NGX_EPERM EPERM
#define NGX_ENOENT ENOENT
+#define NGX_ENOPATH ENOENT
#define NGX_ESRCH ESRCH
#define NGX_EINTR EINTR
#define NGX_ECHILD ECHILD
diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c
index 7446c138b..c92802ef9 100644
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -214,21 +214,33 @@ ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
switch (respawn) {
+ case NGX_PROCESS_NORESPAWN:
+ ngx_processes[s].respawn = 0;
+ ngx_processes[s].just_spawn = 0;
+ ngx_processes[s].detached = 0;
+ break;
+
+ case NGX_PROCESS_JUST_SPAWN:
+ ngx_processes[s].respawn = 0;
+ ngx_processes[s].just_spawn = 1;
+ ngx_processes[s].detached = 0;
+ break;
+
case NGX_PROCESS_RESPAWN:
ngx_processes[s].respawn = 1;
- ngx_processes[s].just_respawn = 0;
+ ngx_processes[s].just_spawn = 0;
ngx_processes[s].detached = 0;
break;
case NGX_PROCESS_JUST_RESPAWN:
ngx_processes[s].respawn = 1;
- ngx_processes[s].just_respawn = 1;
+ ngx_processes[s].just_spawn = 1;
ngx_processes[s].detached = 0;
break;
case NGX_PROCESS_DETACHED:
ngx_processes[s].respawn = 0;
- ngx_processes[s].just_respawn = 0;
+ ngx_processes[s].just_spawn = 0;
ngx_processes[s].detached = 1;
break;
}
diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h
index a34ca6142..aba0b5169 100644
--- a/src/os/unix/ngx_process.h
+++ b/src/os/unix/ngx_process.h
@@ -27,7 +27,7 @@ typedef struct {
char *name;
unsigned respawn:1;
- unsigned just_respawn:1;
+ unsigned just_spawn:1;
unsigned detached:1;
unsigned exiting:1;
unsigned exited:1;
@@ -45,9 +45,10 @@ typedef struct {
#define NGX_MAX_PROCESSES 1024
#define NGX_PROCESS_NORESPAWN -1
-#define NGX_PROCESS_RESPAWN -2
-#define NGX_PROCESS_JUST_RESPAWN -3
-#define NGX_PROCESS_DETACHED -4
+#define NGX_PROCESS_JUST_SPAWN -2
+#define NGX_PROCESS_RESPAWN -3
+#define NGX_PROCESS_JUST_RESPAWN -4
+#define NGX_PROCESS_DETACHED -5
#define ngx_getpid getpid
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 92f6bf6f3..c923209d4 100644
--- 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_thread_cycle(void *data);
#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 *cycle)
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 *cycle)
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 *cycle)
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 *cycle)
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 *cycle)
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 *cycle, ngx_int_t n, ngx_int_t type)
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;
+ 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);
- ngx_spawn_process(cycle, ngx_cache_manager_process_cycle, NULL,
- "cache manager process", type);
+ 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);
}
}
@@ -456,14 +480,14 @@ ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
ngx_processes[i].exited,
ngx_processes[i].detached,
ngx_processes[i].respawn,
- ngx_processes[i].just_respawn);
+ ngx_processes[i].just_spawn);
if (ngx_processes[i].detached || ngx_processes[i].pid == -1) {
continue;
}
- if (ngx_processes[i].just_respawn) {
- ngx_processes[i].just_respawn = 0;
+ if (ngx_processes[i].just_spawn) {
+ ngx_processes[i].just_spawn = 0;
continue;
}
@@ -533,7 +557,7 @@ ngx_reap_children(ngx_cycle_t *cycle)
ngx_processes[i].exited,
ngx_processes[i].detached,
ngx_processes[i].respawn,
- ngx_processes[i].just_respawn);
+ ngx_processes[i].just_spawn);
if (ngx_processes[i].pid == -1) {
continue;
@@ -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;
@@ -1012,13 +1017,14 @@ ngx_worker_process_exit(ngx_cycle_t *cycle)
&& !c[i].read->resolver)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
- "open socket #%d left in connection %ui%s",
- c[i].fd, i, ngx_debug_quit ? ", aborting" : "");
- ngx_debug_point();
+ "open socket #%d left in connection %ui",
+ c[i].fd, i);
+ ngx_debug_quit = 1;
}
}
if (ngx_debug_quit) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "aborting");
ngx_debug_point();
}
}
@@ -1265,6 +1271,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 +1283,16 @@ ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data)
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 +1339,29 @@ ngx_cache_manager_process_handler(ngx_event_t *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);
+ }
+ }
+
+ exit(0);
+}
diff --git a/src/os/unix/ngx_process_cycle.h b/src/os/unix/ngx_process_cycle.h
index c52b6f0e1..8ef0c3154 100644
--- 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);