This commit is contained in:
Roman Arutyunyan 2025-12-16 13:58:52 -08:00 committed by GitHub
commit a06f182407
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 1624 additions and 113 deletions

2
auto/configure vendored
View File

@ -59,8 +59,8 @@ if [ "$NGX_PLATFORM" != win32 ]; then
. auto/unix
fi
. auto/threads
. auto/modules
. auto/threads
. auto/lib/conf
case ".$NGX_PREFIX" in

View File

@ -1406,6 +1406,15 @@ fi
modules="$CORE_MODULES $EVENT_MODULES"
if [ $NGX_DYNAMIC_CONF = YES ]; then
USE_THREADS=YES
have=NGX_DYNAMIC_CONF . auto/have
modules="$modules $DYNAMIC_CONF_MODULE"
CORE_DEPS="$CORE_DEPS $DYNAMIC_CONF_DEPS"
CORE_SRCS="$CORE_SRCS $DYNAMIC_CONF_SRCS"
fi
# thread pool module should be initialized after events
if [ $USE_THREADS = YES ]; then
modules="$modules $THREAD_POOL_MODULE"

View File

@ -45,6 +45,8 @@ USE_THREADS=NO
NGX_FILE_AIO=NO
NGX_DYNAMIC_CONF=NO
QUIC_BPF=NO
HTTP=YES
@ -218,6 +220,8 @@ do
--with-file-aio) NGX_FILE_AIO=YES ;;
--with-dynamic-conf) NGX_DYNAMIC_CONF=YES ;;
--without-quic_bpf_module) QUIC_BPF=NONE ;;
--with-ipv6)
@ -454,6 +458,8 @@ cat << END
--with-file-aio enable file AIO support
--with-dynamic-conf enable dynamic configuration support
--without-quic_bpf_module disable ngx_quic_bpf_module
--with-http_ssl_module enable ngx_http_ssl_module

View File

@ -191,6 +191,10 @@ THREAD_POOL_SRCS="src/core/ngx_thread_pool.c
src/os/unix/ngx_thread_mutex.c
src/os/unix/ngx_thread_id.c"
DYNAMIC_CONF_MODULE=ngx_dynamic_conf_module
DYNAMIC_CONF_DEPS=src/core/ngx_dynamic_conf.h
DYNAMIC_CONF_SRCS="src/core/ngx_dynamic_conf.c"
FREEBSD_DEPS="src/os/unix/ngx_freebsd_config.h src/os/unix/ngx_freebsd.h"
FREEBSD_SRCS=src/os/unix/ngx_freebsd_init.c
FREEBSD_SENDFILE_SRCS=src/os/unix/ngx_freebsd_sendfile_chain.c

View File

@ -7,7 +7,7 @@ if [ $USE_THREADS = YES ]; then
if [ "$NGX_PLATFORM" = win32 ]; then
cat << END
$0: --with-threads is not supported on Windows
$0: threads are not supported on Windows
END
exit 1

View File

@ -409,7 +409,11 @@ ngx_show_version_info(void)
" -q : suppress non-error messages "
"during configuration testing" NGX_LINEFEED
" -s signal : send signal to a master process: "
"stop, quit, reopen, reload" NGX_LINEFEED
"stop, quit, reopen, reload"
#if (NGX_DYNAMIC_CONF)
", update"
#endif
NGX_LINEFEED
#ifdef NGX_PREFIX
" -p prefix : set prefix path (default: " NGX_PREFIX ")"
NGX_LINEFEED
@ -920,7 +924,11 @@ ngx_get_options(int argc, char *const *argv)
if (ngx_strcmp(ngx_signal, "stop") == 0
|| ngx_strcmp(ngx_signal, "quit") == 0
|| ngx_strcmp(ngx_signal, "reopen") == 0
|| ngx_strcmp(ngx_signal, "reload") == 0)
|| ngx_strcmp(ngx_signal, "reload") == 0
#if (NGX_DYNAMIC_CONF)
|| ngx_strcmp(ngx_signal, "update") == 0
#endif
)
{
ngx_process = NGX_PROCESS_SIGNALLER;
goto next;
@ -1148,6 +1156,26 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
ngx_conf_init_value(ccf->worker_processes, 1);
ngx_conf_init_value(ccf->debug_points, 0);
#if (NGX_DYNAMIC_CONF)
if (cycle->dynamic) {
ngx_core_conf_t *occf;
occf = (ngx_core_conf_t *) ngx_get_conf(cycle->old_cycle->conf_ctx,
ngx_core_module);
ccf->username = occf->username;
ccf->user = occf->user;
ccf->group = occf->group;
ccf->pid = occf->pid;
ccf->lock_file = occf->lock_file;
return NGX_CONF_OK;
}
#endif
#if (NGX_HAVE_CPU_AFFINITY)
if (!ccf->cpu_affinity_auto
@ -1283,6 +1311,12 @@ ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
struct group *grp;
ngx_str_t *value;
#if (NGX_DYNAMIC_CONF)
if (cf->cycle->dynamic) {
return NGX_CONF_OK;
}
#endif
if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
return "is duplicate";
}
@ -1589,6 +1623,12 @@ ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_module_t *module, **modules;
ngx_pool_cleanup_t *cln;
#if (NGX_DYNAMIC_CONF)
if (cf->cycle->dynamic) {
return NGX_CONF_OK;
}
#endif
if (cf->cycle->modules_used) {
return "is specified too late";
}

View File

@ -70,6 +70,10 @@
#define NGX_CHANGEBIN_SIGNAL USR2
#endif
#if (NGX_DYNAMIC_CONF)
#define NGX_UPDATE_SIGNAL URG
#endif
#define ngx_cdecl
#define ngx_libc_cdecl

View File

@ -47,6 +47,7 @@ struct ngx_listening_s {
size_t post_accept_buffer_size;
ngx_listening_t *previous;
ngx_listening_t *next;
ngx_connection_t *connection;
ngx_rbtree_t rbtree;

View File

@ -41,6 +41,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
void *rv, *data;
char **senv;
ngx_uint_t i, n;
ngx_int_t rc;
ngx_log_t *log;
ngx_time_t *tp;
ngx_conf_t conf;
@ -476,9 +477,18 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
shm_zone[i].shm.handle = oshm_zone[n].shm.handle;
#endif
if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data)
!= NGX_OK)
{
rc = shm_zone[i].init(&shm_zone[i], oshm_zone[n].data);
if (rc == NGX_DECLINED) {
shm_zone[i].shm.addr = NULL;
#if (NGX_WIN32)
shm_zone[i].shm.handle = NULL;
#endif
data = oshm_zone[n].data;
break;
}
if (rc != NGX_OK) {
goto failed;
}

View File

@ -76,6 +76,8 @@ struct ngx_cycle_s {
ngx_cycle_t *old_cycle;
ngx_uint_t dynamic; /* unsigned dynamic:1; */
ngx_str_t conf_file;
ngx_str_t conf_param;
ngx_str_t conf_prefix;

955
src/core/ngx_dynamic_conf.c Normal file
View File

@ -0,0 +1,955 @@
/*
* Copyright (C) Roman Arutyunyan
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <nginx.h>
#include <ngx_thread_pool.h>
#include <ngx_dynamic_conf.h>
typedef struct {
ngx_pool_t *pool;
ngx_log_t *log;
ngx_cycle_t *main_cycle;
ngx_cycle_t *cycle;
ngx_thread_task_t *task;
ngx_uint_t count;
#if (NGX_DEBUG)
ngx_uint_t id;
#endif
} ngx_dynamic_conf_ctx_t;
typedef struct {
ngx_str_t threads;
#if (NGX_DYNAMIC_CONF_PRELOAD)
ngx_flag_t preload;
#endif
ngx_thread_pool_t *thread_pool;
ngx_dynamic_conf_ctx_t *ctx;
#if (NGX_DEBUG)
ngx_uint_t id;
#endif
} ngx_dynamic_conf_t;
static void *ngx_dynamic_conf_create_conf(ngx_cycle_t *cycle);
static char *ngx_dynamic_conf_init_conf(ngx_cycle_t *cycle, void *conf);
#if (NGX_DYNAMIC_CONF_PRELOAD)
static ngx_int_t ngx_dynamic_conf_init_worker(ngx_cycle_t *cycle);
#endif
static void ngx_dynamic_conf_exit_worker(ngx_cycle_t *cycle);
static void ngx_dynamic_conf_load_handler(void *data, ngx_log_t *log);
static void ngx_dynamic_conf_loaded(ngx_event_t *event);
static void ngx_dynamic_conf_cleanup(void *data);
static void ngx_dynamic_conf_unload(ngx_dynamic_conf_ctx_t *ctx);
static void ngx_dynamic_conf_install(ngx_dynamic_conf_ctx_t *ctx);
static void ngx_dynamic_conf_pass_connection(ngx_connection_t *c);
static ngx_command_t ngx_dynamic_conf_commands[] = {
{ ngx_string("dynamic_conf_threads"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_dynamic_conf_t, threads),
NULL },
#if (NGX_DYNAMIC_CONF_PRELOAD)
{ ngx_string("dynamic_conf_preload"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
0,
offsetof(ngx_dynamic_conf_t, preload),
NULL },
#endif
ngx_null_command
};
static ngx_core_module_t ngx_dynamic_conf_module_ctx = {
ngx_string("dynamic_conf"),
ngx_dynamic_conf_create_conf,
ngx_dynamic_conf_init_conf
};
ngx_module_t ngx_dynamic_conf_module = {
NGX_MODULE_V1,
&ngx_dynamic_conf_module_ctx, /* module context */
ngx_dynamic_conf_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
#if (NGX_DYNAMIC_CONF_PRELOAD)
ngx_dynamic_conf_init_worker, /* init process */
#else
NULL, /* init process */
#endif
NULL, /* init thread */
NULL, /* exit thread */
ngx_dynamic_conf_exit_worker, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static void *
ngx_dynamic_conf_create_conf(ngx_cycle_t *cycle)
{
ngx_dynamic_conf_t *dcf;
dcf = ngx_pcalloc(cycle->pool, sizeof(ngx_dynamic_conf_t));
if (dcf == NULL) {
return NULL;
}
/*
* set by ngx_pcalloc():
*
* dcf->threads = { 0, NULL };
*/
#if (NGX_DYNAMIC_CONF_PRELOAD)
dcf->preload = NGX_CONF_UNSET;
#endif
return dcf;
}
static char *
ngx_dynamic_conf_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_dynamic_conf_t *dcf = conf;
#if (NGX_DYNAMIC_CONF_PRELOAD)
ngx_conf_init_value(dcf->preload, 0);
#endif
if (dcf->threads.data == NULL) {
dcf->thread_pool = ngx_thread_pool_add(cycle, NULL);
} else {
dcf->thread_pool = ngx_thread_pool_add(cycle, &dcf->threads);
}
if (dcf->thread_pool == NULL) {
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
#if (NGX_DYNAMIC_CONF_PRELOAD)
static ngx_int_t
ngx_dynamic_conf_init_worker(ngx_cycle_t *cycle)
{
ngx_pool_t *pool;
ngx_dynamic_conf_t *dcf;
ngx_dynamic_conf_ctx_t *ctx;
if (ngx_process != NGX_PROCESS_WORKER
&& ngx_process != NGX_PROCESS_SINGLE)
{
return NGX_OK;
}
dcf = (ngx_dynamic_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_dynamic_conf_module);
if (!dcf->preload) {
return NGX_OK;
}
ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "dynamic conf preload");
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, cycle->log);
if (pool == NULL) {
return NGX_ERROR;
}
ctx = ngx_pcalloc(pool, sizeof(ngx_dynamic_conf_ctx_t));
if (ctx == NULL) {
ngx_destroy_pool(pool);
return NGX_ERROR;
}
ctx->pool = pool;
ctx->log = cycle->log;
ctx->main_cycle = cycle;
#if (NGX_DEBUG)
ctx->id = dcf->id++;
#endif
ngx_dynamic_conf_load_handler(ctx, cycle->log);
if (ctx->cycle == NULL) {
ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
"dynamic configuration preload failed");
ngx_destroy_pool(pool);
return NGX_ERROR;
}
ngx_dynamic_conf_install(ctx);
dcf->ctx = ctx;
ctx->count = 1;
return NGX_OK;
}
#endif
static void
ngx_dynamic_conf_exit_worker(ngx_cycle_t *cycle)
{
ngx_dynamic_conf_t *dcf;
ngx_dynamic_conf_ctx_t *ctx;
if (ngx_process != NGX_PROCESS_WORKER
&& ngx_process != NGX_PROCESS_SINGLE)
{
return;
}
dcf = (ngx_dynamic_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_dynamic_conf_module);
ctx = dcf->ctx;
if (ctx == NULL) {
return;
}
if (ctx->cycle == NULL) {
ngx_destroy_pool(ctx->pool);
return;
}
ngx_dynamic_conf_unload(ctx);
}
ngx_int_t
ngx_dynamic_conf_update(ngx_cycle_t *cycle)
{
ngx_pool_t *pool;
ngx_thread_task_t *task;
ngx_dynamic_conf_t *dcf;
ngx_dynamic_conf_ctx_t *ctx;
ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "dynamic conf update");
pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, cycle->log);
if (pool == NULL) {
return NGX_ERROR;
}
task = ngx_thread_task_alloc(pool, sizeof(ngx_dynamic_conf_ctx_t));
if (task == NULL) {
ngx_destroy_pool(pool);
return NGX_ERROR;
}
task->handler = ngx_dynamic_conf_load_handler;
task->event.handler = ngx_dynamic_conf_loaded;
task->event.log = cycle->log;
task->event.data = task->ctx;
ctx = task->ctx;
ctx->pool = pool;
ctx->log = cycle->log;
ctx->main_cycle = cycle;
ctx->task = task;
dcf = (ngx_dynamic_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_dynamic_conf_module);
#if (NGX_DEBUG)
ctx->id = dcf->id++;
#endif
return ngx_thread_task_post(dcf->thread_pool, task);
}
static void
ngx_dynamic_conf_load_handler(void *data, ngx_log_t *log)
{
ngx_dynamic_conf_ctx_t *ctx = data;
void *rv;
ngx_int_t rc;
ngx_uint_t i, n;
ngx_conf_t conf;
ngx_pool_t *pool;
ngx_cycle_t *cycle, *main_cycle;
ngx_shm_zone_t *shm_zone, *oshm_zone;
ngx_listening_t *ls, *nls;
ngx_list_part_t *part, *opart;
ngx_open_file_t *file, *ofile;
ngx_core_conf_t *main_ccf;
ngx_core_module_t *module;
main_cycle = ctx->main_cycle;
pool = ctx->pool;
cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
if (cycle == NULL) {
return;
}
cycle->pool = pool;
cycle->log = pool->log;
cycle->old_cycle = main_cycle;
cycle->dynamic = 1;
cycle->conf_prefix = main_cycle->conf_prefix;
cycle->prefix = main_cycle->prefix;
cycle->error_log = main_cycle->error_log;
cycle->conf_file = main_cycle->conf_file;
cycle->conf_param = main_cycle->conf_param;
cycle->hostname = main_cycle->hostname;
cycle->modules = main_cycle->modules;
cycle->modules_n = main_cycle->modules_n;
n = main_cycle->paths.nelts;
if (ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *))
!= NGX_OK)
{
return;
}
ngx_memzero(cycle->paths.elts, n * sizeof(ngx_path_t *));
if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t))
!= NGX_OK)
{
return;
}
ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel,
ngx_str_rbtree_insert_value);
if (main_cycle->open_files.part.nelts) {
n = main_cycle->open_files.part.nelts;
for (part = main_cycle->open_files.part.next; part; part = part->next) {
n += part->nelts;
}
} else {
n = 20;
}
if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
!= NGX_OK)
{
return;
}
if (main_cycle->shared_memory.part.nelts) {
n = main_cycle->shared_memory.part.nelts;
for (part = main_cycle->shared_memory.part.next; part;
part = part->next)
{
n += part->nelts;
}
} else {
n = 1;
}
if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
!= NGX_OK)
{
return;
}
n = main_cycle->listening.nelts ? main_cycle->listening.nelts : 1;
if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t))
!= NGX_OK)
{
return;
}
ngx_memzero(cycle->listening.elts, n * sizeof(ngx_listening_t));
cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
if (cycle->conf_ctx == NULL) {
return;
}
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = cycle->modules[i]->ctx;
if (module->create_conf) {
rv = module->create_conf(cycle);
if (rv == NULL) {
return;
}
cycle->conf_ctx[cycle->modules[i]->index] = rv;
}
}
ngx_memzero(&conf, sizeof(ngx_conf_t));
/* STUB: init array ? */
conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
if (conf.args == NULL) {
return;
}
conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
if (conf.temp_pool == NULL) {
return;
}
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
conf.log = log;
conf.module_type = NGX_CORE_MODULE;
conf.cmd_type = NGX_MAIN_CONF;
#if 0
log->log_level = NGX_LOG_DEBUG_ALL;
#endif
if (ngx_conf_param(&conf) != NGX_CONF_OK) {
goto destroy_pools;
}
if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
goto destroy_pools;
}
for (i = 0; cycle->modules[i]; i++) {
if (cycle->modules[i]->type != NGX_CORE_MODULE) {
continue;
}
module = cycle->modules[i]->ctx;
if (module->init_conf) {
if (module->init_conf(cycle,
cycle->conf_ctx[cycle->modules[i]->index])
== NGX_CONF_ERROR)
{
goto destroy_pools;
}
}
}
main_ccf = (ngx_core_conf_t *) ngx_get_conf(main_cycle->conf_ctx,
ngx_core_module);
if (ngx_create_paths(cycle, main_ccf->user) != NGX_OK) {
goto failed;
}
if (ngx_log_open_default(cycle) != NGX_OK) {
goto failed;
}
/* open the new files */
part = &cycle->open_files.part;
file = part->elts;
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
file = part->elts;
i = 0;
}
if (file[i].name.len == 0) {
continue;
}
opart = (ngx_list_part_t *) &main_cycle->open_files.part;
ofile = opart->elts;
for (n = 0; /* void */ ; n++) {
if (n >= opart->nelts) {
if (opart->next == NULL) {
break;
}
opart = opart->next;
ofile = opart->elts;
n = 0;
}
if (file[i].name.len != ofile[n].name.len) {
continue;
}
if (ngx_strncmp(file[i].name.data, ofile[n].name.data,
file[i].name.len)
!= 0)
{
continue;
}
file[i].fd = ngx_dup(ofile[n].fd);
ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0,
"log: %p %d (dup %d) \"%s\"",
&file[i], file[i].fd, ofile[i].fd,
file[i].name.data);
if (file[i].fd == NGX_INVALID_FILE) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
ngx_dup_n " \"%s\" failed",
file[i].name.data);
goto failed;
}
goto file_found;
}
file[i].fd = ngx_open_file(file[i].name.data,
NGX_FILE_APPEND,
NGX_FILE_CREATE_OR_OPEN,
NGX_FILE_DEFAULT_ACCESS);
ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,
"log: %p %d \"%s\"",
&file[i], file[i].fd, file[i].name.data);
if (file[i].fd == NGX_INVALID_FILE) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
ngx_open_file_n " \"%s\" failed",
file[i].name.data);
goto failed;
}
file_found:
continue;
}
cycle->log = &cycle->new_log;
pool->log = &cycle->new_log;
/* create shared memory */
part = &cycle->shared_memory.part;
shm_zone = part->elts;
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
shm_zone = part->elts;
i = 0;
}
shm_zone[i].shm.log = cycle->log;
opart = (ngx_list_part_t *) &main_cycle->shared_memory.part;
oshm_zone = opart->elts;
for (n = 0; /* void */ ; n++) {
if (n >= opart->nelts) {
if (opart->next == NULL) {
break;
}
opart = opart->next;
oshm_zone = opart->elts;
n = 0;
}
if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {
continue;
}
if (ngx_strncmp(shm_zone[i].shm.name.data,
oshm_zone[n].shm.name.data,
shm_zone[i].shm.name.len)
!= 0)
{
continue;
}
if (shm_zone[i].tag == oshm_zone[n].tag && shm_zone[i].noreuse) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"non-reusable shared zone \"%V\"",
&shm_zone[i].shm.name);
goto failed;
}
if (shm_zone[i].tag == oshm_zone[n].tag
&& shm_zone[i].shm.size == oshm_zone[n].shm.size)
{
shm_zone[i].shm.addr = oshm_zone[n].shm.addr;
#if (NGX_WIN32)
shm_zone[i].shm.handle = oshm_zone[n].shm.handle;
#endif
rc = shm_zone[i].init(&shm_zone[i], oshm_zone[n].data);
if (rc == NGX_DECLINED) {
shm_zone[i].shm.addr = NULL;
#if (NGX_WIN32)
shm_zone[i].shm.handle = NULL;
#endif
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"cannot reuse shared zone \"%V\"",
&shm_zone[i].shm.name);
goto failed;
}
if (rc != NGX_OK) {
goto failed;
}
goto shm_zone_found;
}
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"cannot reuse shared zone \"%V\"",
&shm_zone[i].shm.name);
goto failed;
}
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"cannot find a matching shared zone \"%V\"",
&shm_zone[i].shm.name);
goto failed;
shm_zone_found:
continue;
}
/* handle the listening sockets */
ls = (ngx_listening_t *) main_cycle->listening.elts;
nls = cycle->listening.elts;
for (n = 0; n < cycle->listening.nelts; n++) {
for (i = 0; i < main_cycle->listening.nelts; i++) {
#if (NGX_HAVE_REUSEPORT)
if (ls[i].reuseport && ls[i].worker != ngx_worker) {
continue;
}
#endif
if (ls[i].type != nls[n].type) {
continue;
}
#if (NGX_QUIC)
if (ls[i].quic != nls[n].quic) {
continue;
}
#endif
#if (NGX_HAVE_REUSEPORT)
if (ls[i].reuseport != nls[n].reuseport) {
continue;
}
#endif
if (ngx_cmp_sockaddr(ls[i].sockaddr, ls[i].socklen,
nls[n].sockaddr, nls[n].socklen, 1)
!= NGX_OK)
{
continue;
}
nls[n].previous = &ls[i];
#if (NGX_HAVE_REUSEPORT)
if (nls[n].reuseport) {
nls[n].worker = ngx_worker;
}
#endif
goto listening_found;
}
if (ngx_exiting) {
/*
* An exiting worker calls ngx_close_listening_sockets()
* which resets the c->listening array. Avoid logging an
* error in this case
*/
goto failed;
}
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"unexpected listen port for \"%V\"", &nls[n].addr_text);
goto failed;
listening_found:
continue;
}
/* commit the new cycle configuration */
pool->log = cycle->log;
if (ngx_init_modules(cycle) != NGX_OK) {
/* fatal */
exit(1);
}
ngx_destroy_pool(conf.temp_pool);
ctx->cycle = cycle;
return;
failed:
/* rollback the new cycle configuration */
part = &cycle->open_files.part;
file = part->elts;
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
file = part->elts;
i = 0;
}
if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {
continue;
}
if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
ngx_close_file_n " \"%s\" failed",
file[i].name.data);
}
}
destroy_pools:
ngx_destroy_pool(conf.temp_pool);
}
static void
ngx_dynamic_conf_loaded(ngx_event_t *event)
{
ngx_dynamic_conf_t *dcf;
ngx_dynamic_conf_ctx_t *ctx;
ctx = event->data;
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0,
"dynamic conf load %p n:%ui", ctx->cycle, ctx->id);
if (ctx->cycle == NULL && !ngx_exiting) {
ngx_log_error(NGX_LOG_ALERT, ctx->log, 0,
"dynamic configuration load failed");
}
if (ctx->cycle == NULL || ngx_exiting) {
ngx_destroy_pool(ctx->pool);
return;
}
ngx_dynamic_conf_install(ctx);
dcf = (ngx_dynamic_conf_t *) ngx_get_conf(ctx->main_cycle->conf_ctx,
ngx_dynamic_conf_module);
if (dcf->ctx) {
ngx_dynamic_conf_cleanup(dcf->ctx);
}
dcf->ctx = ctx;
ctx->count++;
}
static void
ngx_dynamic_conf_cleanup(void *data)
{
ngx_dynamic_conf_ctx_t *ctx = data;
if (--ctx->count) {
ngx_log_debug3(NGX_LOG_DEBUG_CORE, ctx->log, 0,
"dynamic conf hold %p n:%ui c:%ui",
ctx->cycle, ctx->id, ctx->count);
return;
}
ngx_dynamic_conf_unload(ctx);
}
static void
ngx_dynamic_conf_unload(ngx_dynamic_conf_ctx_t *ctx)
{
ngx_uint_t i;
ngx_list_part_t *part;
ngx_open_file_t *file;
part = &ctx->cycle->open_files.part;
file = part->elts;
for (i = 0; /* void */ ; i++) {
if (i >= part->nelts) {
if (part->next == NULL) {
break;
}
part = part->next;
file = part->elts;
i = 0;
}
if (file[i].flush) {
file[i].flush(&file[i], ctx->log);
}
if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) {
continue;
}
if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_EMERG, ctx->log, ngx_errno,
ngx_close_file_n " \"%s\" failed", file[i].name.data);
}
}
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0,
"dynamic conf free %p n:%ui",
ctx->cycle, ctx->id);
ngx_destroy_pool(ctx->pool);
}
static void
ngx_dynamic_conf_install(ngx_dynamic_conf_ctx_t *ctx)
{
ngx_uint_t n, i;
ngx_listening_t *ls, *nls;
ls = (ngx_listening_t *) ctx->main_cycle->listening.elts;
nls = (ngx_listening_t *) ctx->cycle->listening.elts;
for (n = 0; n < ctx->main_cycle->listening.nelts; n++) {
ls[n].handler = ngx_dynamic_conf_pass_connection;
ls[n].next = NULL;
for (i = 0; i < ctx->cycle->listening.nelts; i++) {
if (&ls[n] == nls[i].previous) {
ls[n].next = &nls[i];
break;
}
}
}
}
static void
ngx_dynamic_conf_pass_connection(ngx_connection_t *c)
{
ngx_pool_t *pool;
ngx_pool_cleanup_t *cln;
ngx_dynamic_conf_t *dcf;
ngx_dynamic_conf_ctx_t *ctx;
dcf = (ngx_dynamic_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
ngx_dynamic_conf_module);
ctx = dcf->ctx;
if (ctx == NULL || c->listening->next == NULL) {
goto close;
}
ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
"dynamic conf pass %p n:%ui", ctx->cycle, ctx->id);
cln = ngx_pool_cleanup_add(c->pool, 0);
if (cln == NULL) {
goto close;
}
cln->handler = ngx_dynamic_conf_cleanup;
cln->data = ctx;
ctx->count++;
c->listening = c->listening->next;
c->listening->handler(c);
return;
close:
pool = c->pool;
ngx_close_connection(c);
ngx_destroy_pool(pool);
}
void
ngx_dynamic_conf_reopen_files(ngx_cycle_t *cycle)
{
ngx_dynamic_conf_t *dcf;
ngx_dynamic_conf_ctx_t *ctx;
dcf = (ngx_dynamic_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_dynamic_conf_module);
ctx = dcf->ctx;
if (ctx == NULL || ctx->cycle == NULL) {
return;
}
ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"dynamic conf reopen files %p n:%ui", ctx->cycle, ctx->id);
ngx_reopen_files(ctx->cycle, -1);
}

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) Roman Arutyunyan
* Copyright (C) Nginx, Inc.
*/
#ifndef _NGX_DYNAMIC_CONF_H_INCLUDED_
#define _NGX_DYNAMIC_CONF_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <nginx.h>
ngx_int_t ngx_dynamic_conf_update(ngx_cycle_t *cycle);
void ngx_dynamic_conf_reopen_files(ngx_cycle_t *cycle);
#endif /* _NGX_DYNAMIC_CONF_H_INCLUDED_ */

View File

@ -37,9 +37,6 @@ struct ngx_thread_pool_s {
ngx_str_t name;
ngx_uint_t threads;
ngx_int_t max_queue;
u_char *file;
ngx_uint_t line;
};
@ -427,6 +424,38 @@ ngx_thread_pool_init_conf(ngx_cycle_t *cycle, void *conf)
for (i = 0; i < tcf->pools.nelts; i++) {
#if (NGX_DYNAMIC_CONF)
if (cycle->dynamic) {
ngx_uint_t j;
ngx_thread_pool_t **otpp;
ngx_thread_pool_conf_t *otcf;
otcf = (ngx_thread_pool_conf_t *) ngx_get_conf(
cycle->old_cycle->conf_ctx,
ngx_thread_pool_module);
otpp = otcf->pools.elts;
for (j = 0; j < otcf->pools.nelts; j++) {
if (tpp[i]->name.len == otpp[j]->name.len
&& ngx_strncmp(tpp[i]->name.data, otpp[j]->name.data,
tpp[i]->name.len)
== 0)
{
tpp[i] = otpp[j];
break;
}
}
if (j == otcf->pools.nelts) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"thread pool \"%V\" not found", &tpp[i]->name);
return NGX_CONF_ERROR;
}
}
#endif
if (tpp[i]->threads) {
continue;
}
@ -442,8 +471,7 @@ ngx_thread_pool_init_conf(ngx_cycle_t *cycle, void *conf)
}
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"unknown thread pool \"%V\" in %s:%ui",
&tpp[i]->name, tpp[i]->file, tpp[i]->line);
"unknown thread pool \"%V\"", &tpp[i]->name);
return NGX_CONF_ERROR;
}
@ -461,7 +489,7 @@ ngx_thread_pool(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
tp = ngx_thread_pool_add(cf, &value[1]);
tp = ngx_thread_pool_add(cf->cycle, &value[1]);
if (tp == NULL) {
return NGX_CONF_ERROR;
@ -516,7 +544,7 @@ ngx_thread_pool(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_thread_pool_t *
ngx_thread_pool_add(ngx_conf_t *cf, ngx_str_t *name)
ngx_thread_pool_add(ngx_cycle_t *cycle, ngx_str_t *name)
{
ngx_thread_pool_t *tp, **tpp;
ngx_thread_pool_conf_t *tcf;
@ -525,22 +553,20 @@ ngx_thread_pool_add(ngx_conf_t *cf, ngx_str_t *name)
name = &ngx_thread_pool_default;
}
tp = ngx_thread_pool_get(cf->cycle, name);
tp = ngx_thread_pool_get(cycle, name);
if (tp) {
return tp;
}
tp = ngx_pcalloc(cf->pool, sizeof(ngx_thread_pool_t));
tp = ngx_pcalloc(cycle->pool, sizeof(ngx_thread_pool_t));
if (tp == NULL) {
return NULL;
}
tp->name = *name;
tp->file = cf->conf_file->file.name.data;
tp->line = cf->conf_file->line;
tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cf->cycle->conf_ctx,
tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
ngx_thread_pool_module);
tpp = ngx_array_push(&tcf->pools);

View File

@ -26,7 +26,7 @@ struct ngx_thread_task_s {
typedef struct ngx_thread_pool_s ngx_thread_pool_t;
ngx_thread_pool_t *ngx_thread_pool_add(ngx_conf_t *cf, ngx_str_t *name);
ngx_thread_pool_t *ngx_thread_pool_add(ngx_cycle_t *cycle, ngx_str_t *name);
ngx_thread_pool_t *ngx_thread_pool_get(ngx_cycle_t *cycle, ngx_str_t *name);
ngx_thread_task_t *ngx_thread_task_alloc(ngx_pool_t *pool, size_t size);

View File

@ -438,6 +438,12 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
ngx_listening_t *ls;
#endif
#if (NGX_DYNAMIC_CONF)
if (cycle->dynamic) {
return NGX_CONF_OK;
}
#endif
if (ngx_get_conf(cycle->conf_ctx, ngx_events_module) == NULL) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"no \"events\" section in configuration");

View File

@ -459,6 +459,7 @@ ngx_insert_udp_connection(ngx_connection_t *c)
return NGX_ERROR;
}
udp->rbtree = &c->listening->rbtree;
udp->connection = c;
ngx_crc32_init(hash);
@ -482,7 +483,7 @@ ngx_insert_udp_connection(ngx_connection_t *c)
cln->data = c;
cln->handler = ngx_delete_udp_connection;
ngx_rbtree_insert(&c->listening->rbtree, &udp->node);
ngx_rbtree_insert(udp->rbtree, &udp->node);
c->udp = udp;
@ -499,7 +500,7 @@ ngx_delete_udp_connection(void *data)
return;
}
ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node);
ngx_rbtree_delete(c->udp->rbtree, &c->udp->node);
c->udp = NULL;
}

View File

@ -25,6 +25,7 @@
struct ngx_udp_connection_s {
ngx_rbtree_node_t node;
ngx_rbtree_t *rbtree;
ngx_connection_t *connection;
ngx_buf_t *buffer;
ngx_str_t key;

View File

@ -51,7 +51,7 @@ ngx_quic_bpf_attach_id(ngx_connection_t *c, u_char *id)
uint64_t cookie;
socklen_t optlen;
fd = c->listening->fd;
fd = c->fd;
optlen = sizeof(cookie);

View File

@ -62,6 +62,7 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc,
ngx_memcpy(qc->tp.initial_scid.data, qsock->sid.id, qsock->sid.len);
/* for all packets except first, this is set at udp layer */
tmp = (ngx_quic_socket_t *) c->udp;
c->udp = &qsock->udp;
/* ngx_quic_get_connection(c) macro is now usable */
@ -86,13 +87,6 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc,
ngx_quic_path_dbg(c, "set active", qc->path);
tmp = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t));
if (tmp == NULL) {
goto failed;
}
tmp->sid.seqnum = NGX_QUIC_UNSET_PN; /* temporary socket */
ngx_memcpy(tmp->sid.id, pkt->dcid.data, pkt->dcid.len);
tmp->sid.len = pkt->dcid.len;
@ -104,7 +98,7 @@ ngx_quic_open_sockets(ngx_connection_t *c, ngx_quic_connection_t *qc,
failed:
ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node);
ngx_rbtree_delete(qsock->udp.rbtree, &qsock->udp.node);
c->udp = NULL;
return NGX_ERROR;
@ -155,7 +149,7 @@ ngx_quic_close_socket(ngx_connection_t *c, ngx_quic_socket_t *qsock)
ngx_queue_remove(&qsock->queue);
ngx_queue_insert_head(&qc->free_sockets, &qsock->queue);
ngx_rbtree_delete(&c->listening->rbtree, &qsock->udp.node);
ngx_rbtree_delete(qsock->udp.rbtree, &qsock->udp.node);
qc->nsockets--;
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
@ -176,11 +170,12 @@ ngx_quic_listen(ngx_connection_t *c, ngx_quic_connection_t *qc,
id.data = sid->id;
id.len = sid->len;
qsock->udp.rbtree = c->udp->rbtree;
qsock->udp.connection = c;
qsock->udp.node.key = ngx_crc32_long(id.data, id.len);
qsock->udp.key = id;
ngx_rbtree_insert(&c->listening->rbtree, &qsock->udp.node);
ngx_rbtree_insert(qsock->udp.rbtree, &qsock->udp.node);
ngx_queue_insert_tail(&qc->sockets, &qsock->queue);

View File

@ -14,6 +14,7 @@
static void ngx_quic_close_accepted_connection(ngx_connection_t *c);
static ngx_connection_t *ngx_quic_lookup_connection(ngx_listening_t *ls,
ngx_str_t *key, struct sockaddr *local_sockaddr, socklen_t local_socklen);
static ngx_int_t ngx_quic_insert_connection(ngx_connection_t *c);
void
@ -333,6 +334,11 @@ ngx_quic_recvmsg(ngx_event_t *ev)
}
#endif
if (ngx_quic_insert_connection(c) != NGX_OK) {
ngx_quic_close_accepted_connection(c);
return;
}
log->data = NULL;
log->handler = NULL;
@ -418,3 +424,24 @@ ngx_quic_lookup_connection(ngx_listening_t *ls, ngx_str_t *key,
return NULL;
}
static ngx_int_t
ngx_quic_insert_connection(ngx_connection_t *c)
{
ngx_quic_socket_t *qsock;
qsock = ngx_pcalloc(c->pool, sizeof(ngx_quic_socket_t));
if (qsock == NULL) {
return NGX_ERROR;
}
qsock->sid.seqnum = NGX_QUIC_UNSET_PN;
qsock->udp.rbtree = &c->listening->rbtree;
qsock->udp.connection = c;
c->udp = &qsock->udp;
return NGX_OK;
}

View File

@ -14,6 +14,8 @@ static char *ngx_http_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone,
void *data);
static ngx_int_t ngx_http_upstream_zone_servers_equal(
ngx_http_upstream_srv_conf_t *uscf, ngx_http_upstream_srv_conf_t *ouscf);
static ngx_http_upstream_rr_peers_t *ngx_http_upstream_zone_copy_peers(
ngx_slab_pool_t *shpool, ngx_http_upstream_srv_conf_t *uscf,
ngx_http_upstream_srv_conf_t *ouscf);
@ -124,8 +126,6 @@ ngx_http_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
uscf->shm_zone->init = ngx_http_upstream_init_zone;
uscf->shm_zone->data = umcf;
uscf->shm_zone->noreuse = 1;
return NGX_CONF_OK;
}
@ -133,17 +133,74 @@ ngx_http_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static ngx_int_t
ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{
ngx_http_upstream_main_conf_t *oumcf = data;
size_t len;
ngx_uint_t i, j;
ngx_slab_pool_t *shpool;
ngx_http_upstream_rr_peers_t *peers, **peersp;
ngx_http_upstream_srv_conf_t *uscf, *ouscf, **uscfp, **ouscfp;
ngx_http_upstream_main_conf_t *umcf, *oumcf;
ngx_http_upstream_main_conf_t *umcf;
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
umcf = shm_zone->data;
uscfp = umcf->upstreams.elts;
if (oumcf && shpool->data) {
for (i = 0; i < umcf->upstreams.nelts; i++) {
uscf = uscfp[i];
if (uscf->shm_zone != shm_zone) {
continue;
}
for (j = 0; j < oumcf->upstreams.nelts; j++) {
ouscfp = oumcf->upstreams.elts;
if (ouscfp[j]->shm_zone == NULL) {
continue;
}
if (ouscfp[j]->shm_zone->shm.name.len != shm_zone->shm.name.len
|| ngx_memcmp(ouscfp[j]->shm_zone->shm.name.data,
shm_zone->shm.name.data,
shm_zone->shm.name.len)
!= 0)
{
continue;
}
if (ngx_http_upstream_zone_servers_equal(uscf, ouscfp[j])
== NGX_OK)
{
uscf->peer.data = ouscfp[j]->peer.data;
goto server_found;
}
}
/* new or modified upstream, decline zone reuse */
for ( /* void */ ; i > 0; i--) {
uscf = uscfp[i - 1];
if (uscf->shm_zone != shm_zone) {
continue;
}
uscf->peer.data = NULL;
}
return NGX_DECLINED;
server_found:
continue;
}
return NGX_OK;
}
if (shm_zone->shm.exists) {
peers = shpool->data;
@ -175,7 +232,6 @@ ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
/* copy peers to shared memory */
peersp = (ngx_http_upstream_rr_peers_t **) (void *) &shpool->data;
oumcf = data;
for (i = 0; i < umcf->upstreams.nelts; i++) {
uscf = uscfp[i];
@ -228,6 +284,66 @@ ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
}
static ngx_int_t
ngx_http_upstream_zone_servers_equal(ngx_http_upstream_srv_conf_t *uscf,
ngx_http_upstream_srv_conf_t *ouscf)
{
ngx_uint_t n;
ngx_http_upstream_server_t *us, *ous;
if (uscf->host.len != ouscf->host.len
|| ngx_strncmp(uscf->host.data, ouscf->host.data, uscf->host.len) != 0)
{
return NGX_DECLINED;
}
if (uscf->servers == NULL
|| ouscf->servers == NULL
|| uscf->servers->nelts != ouscf->servers->nelts)
{
return NGX_DECLINED;
}
us = uscf->servers->elts;
ous = ouscf->servers->elts;
for (n = 0; n < uscf->servers->nelts; n++) {
if (us->name.len != ous->name.len
|| ngx_strncmp(us->name.data, ous->name.data, us->name.len) != 0)
{
return NGX_DECLINED;
}
if (us->host.len != ous->host.len
|| ngx_strncmp(us->host.data, ous->host.data, us->host.len) != 0)
{
return NGX_DECLINED;
}
if (us->service.len != ous->service.len
|| ngx_strncmp(us->service.data, ous->service.data, us->service.len)
!= 0)
{
return NGX_DECLINED;
}
if (us->weight != ous->weight
|| us->max_conns != ous->max_conns
|| us->max_fails != ous->max_fails
|| us->fail_timeout != ous->fail_timeout
|| us->slow_start != ous->slow_start
|| us->down != ous->down
|| us->backup != ous->backup)
{
return NGX_DECLINED;
}
}
return NGX_OK;
}
static ngx_http_upstream_rr_peers_t *
ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool,
ngx_http_upstream_srv_conf_t *uscf, ngx_http_upstream_srv_conf_t *ouscf)

View File

@ -314,6 +314,10 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
if (ngx_http_init_filters(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}
if (ngx_http_variables_init_vars(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}

View File

@ -172,6 +172,8 @@ char *ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys,
ngx_int_t ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
ngx_str_t *default_type);
char *ngx_http_init_filters(ngx_conf_t *cf);
#if (NGX_HTTP_DEGRADATION)
ngx_uint_t ngx_http_degraded(ngx_http_request_t *);
#endif

View File

@ -1845,6 +1845,8 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
ngx_int_t
ngx_http_send_header(ngx_http_request_t *r)
{
ngx_http_core_main_conf_t *cmcf;
if (r->post_action) {
return NGX_OK;
}
@ -1860,7 +1862,9 @@ ngx_http_send_header(ngx_http_request_t *r)
r->headers_out.status_line.len = 0;
}
return ngx_http_top_header_filter(r);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
return cmcf->top_header_filter(r);
}
@ -1898,15 +1902,18 @@ ngx_http_send_early_hints(ngx_http_request_t *r)
ngx_int_t
ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_int_t rc;
ngx_connection_t *c;
ngx_int_t rc;
ngx_connection_t *c;
ngx_http_core_main_conf_t *cmcf;
c = r->connection;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http output filter \"%V?%V\"", &r->uri, &r->args);
rc = ngx_http_top_body_filter(r, in);
rc = cmcf->top_body_filter(r, in);
if (rc == NGX_ERROR) {
/* NGX_ERROR may be returned by any filter */
@ -4832,10 +4839,10 @@ ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
}
tp = ngx_thread_pool_add(cf, &name);
tp = ngx_thread_pool_add(cf->cycle, &name);
} else {
tp = ngx_thread_pool_add(cf, NULL);
tp = ngx_thread_pool_add(cf->cycle, NULL);
}
if (tp == NULL) {
@ -5406,3 +5413,22 @@ ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
return NGX_CONF_OK;
}
char *
ngx_http_init_filters(ngx_conf_t *cf)
{
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
cmcf->top_header_filter = ngx_http_top_header_filter;
cmcf->top_body_filter = ngx_http_top_body_filter;
cmcf->top_request_body_filter = ngx_http_top_request_body_filter;
ngx_http_top_header_filter = NULL;
ngx_http_top_body_filter = NULL;
ngx_http_top_request_body_filter = NULL;
return NGX_CONF_OK;
}

View File

@ -64,6 +64,13 @@ typedef struct ngx_http_location_tree_node_s ngx_http_location_tree_node_t;
typedef struct ngx_http_core_loc_conf_s ngx_http_core_loc_conf_t;
typedef ngx_int_t (*ngx_http_output_header_filter_pt)(ngx_http_request_t *r);
typedef ngx_int_t (*ngx_http_output_body_filter_pt)
(ngx_http_request_t *r, ngx_chain_t *chain);
typedef ngx_int_t (*ngx_http_request_body_filter_pt)
(ngx_http_request_t *r, ngx_chain_t *chain);
typedef struct {
struct sockaddr *sockaddr;
socklen_t socklen;
@ -175,6 +182,10 @@ typedef struct {
ngx_array_t *ports;
ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1];
ngx_http_output_header_filter_pt top_header_filter;
ngx_http_output_body_filter_pt top_body_filter;
ngx_http_request_body_filter_pt top_request_body_filter;
} ngx_http_core_main_conf_t;
@ -524,13 +535,6 @@ ngx_int_t ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name);
ngx_http_cleanup_t *ngx_http_cleanup_add(ngx_http_request_t *r, size_t size);
typedef ngx_int_t (*ngx_http_output_header_filter_pt)(ngx_http_request_t *r);
typedef ngx_int_t (*ngx_http_output_body_filter_pt)
(ngx_http_request_t *r, ngx_chain_t *chain);
typedef ngx_int_t (*ngx_http_request_body_filter_pt)
(ngx_http_request_t *r, ngx_chain_t *chain);
ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *chain);
ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *chain);
ngx_int_t ngx_http_request_body_save_filter(ngx_http_request_t *r,

View File

@ -1000,11 +1000,12 @@ ngx_http_request_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
static ngx_int_t
ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
size_t size;
ngx_int_t rc;
ngx_buf_t *b;
ngx_chain_t *cl, *tl, *out, **ll;
ngx_http_request_body_t *rb;
size_t size;
ngx_int_t rc;
ngx_buf_t *b;
ngx_chain_t *cl, *tl, *out, **ll;
ngx_http_request_body_t *rb;
ngx_http_core_main_conf_t *cmcf;
rb = r->request_body;
@ -1075,7 +1076,9 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
ll = &tl->next;
}
rc = ngx_http_top_request_body_filter(r, out);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
rc = cmcf->top_request_body_filter(r, out);
ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &out,
(ngx_buf_tag_t) &ngx_http_read_client_request_body);
@ -1087,13 +1090,14 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
static ngx_int_t
ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
size_t size;
ngx_int_t rc;
ngx_buf_t *b;
ngx_chain_t *cl, *out, *tl, **ll;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
size_t size;
ngx_int_t rc;
ngx_buf_t *b;
ngx_chain_t *cl, *out, *tl, **ll;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_main_conf_t *cmcf;
rb = r->request_body;
@ -1259,7 +1263,9 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
rc = ngx_http_top_request_body_filter(r, out);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
rc = cmcf->top_request_body_filter(r, out);
ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &out,
(ngx_buf_tag_t) &ngx_http_read_client_request_body);

View File

@ -3898,15 +3898,16 @@ failed:
ngx_int_t
ngx_http_v2_read_request_body(ngx_http_request_t *r)
{
off_t len;
size_t size;
ngx_buf_t *buf;
ngx_int_t rc;
ngx_http_v2_stream_t *stream;
ngx_http_v2_srv_conf_t *h2scf;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_v2_connection_t *h2c;
off_t len;
size_t size;
ngx_buf_t *buf;
ngx_int_t rc;
ngx_http_v2_stream_t *stream;
ngx_http_v2_srv_conf_t *h2scf;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_v2_connection_t *h2c;
ngx_http_core_main_conf_t *cmcf;
stream = r->stream;
rb = r->request_body;
@ -3921,7 +3922,9 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r)
/* set rb->filter_need_buffering */
rc = ngx_http_top_request_body_filter(r, NULL);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
rc = cmcf->top_request_body_filter(r, NULL);
if (rc != NGX_OK) {
stream->skip_data = 1;
@ -4175,11 +4178,12 @@ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos,
static ngx_int_t
ngx_http_v2_filter_request_body(ngx_http_request_t *r)
{
ngx_buf_t *b, *buf;
ngx_int_t rc;
ngx_chain_t *cl;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_buf_t *b, *buf;
ngx_int_t rc;
ngx_chain_t *cl;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_main_conf_t *cmcf;
rb = r->request_body;
buf = rb->buf;
@ -4255,7 +4259,9 @@ ngx_http_v2_filter_request_body(ngx_http_request_t *r)
update:
rc = ngx_http_top_request_body_filter(r, cl);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
rc = cmcf->top_request_body_filter(r, cl);
ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &cl,
(ngx_buf_tag_t) &ngx_http_v2_filter_request_body);

View File

@ -1494,18 +1494,19 @@ ngx_http_v3_do_read_client_request_body(ngx_http_request_t *r)
static ngx_int_t
ngx_http_v3_request_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
off_t max;
size_t size;
u_char *p;
ngx_int_t rc;
ngx_buf_t *b;
ngx_uint_t last;
ngx_chain_t *cl, *out, *tl, **ll;
ngx_http_v3_session_t *h3c;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
ngx_http_v3_parse_data_t *st;
off_t max;
size_t size;
u_char *p;
ngx_int_t rc;
ngx_buf_t *b;
ngx_uint_t last;
ngx_chain_t *cl, *out, *tl, **ll;
ngx_http_v3_session_t *h3c;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
ngx_http_v3_parse_data_t *st;
ngx_http_core_main_conf_t *cmcf;
rb = r->request_body;
st = &r->v3_parse->body;
@ -1723,7 +1724,9 @@ done:
rb->rest = (off_t) cscf->large_client_header_buffers.size;
}
rc = ngx_http_top_request_body_filter(r, out);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
rc = cmcf->top_request_body_filter(r, out);
ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &out,
(ngx_buf_tag_t) &ngx_http_read_client_request_body);

View File

@ -114,6 +114,10 @@ typedef struct {
#define ngx_delete_file_n "unlink()"
#define ngx_dup dup
#define ngx_dup_n "dup()"
ngx_fd_t ngx_open_tempfile(u_char *name, ngx_uint_t persistent,
ngx_uint_t access);
#define ngx_open_tempfile_n "open()"

View File

@ -67,6 +67,13 @@ ngx_signal_t signals[] = {
"",
ngx_signal_handler },
#if (NGX_DYNAMIC_CONF)
{ ngx_signal_value(NGX_UPDATE_SIGNAL),
"SIG" ngx_value(NGX_UPDATE_SIGNAL),
"update",
ngx_signal_handler },
#endif
{ SIGALRM, "SIGALRM", "", ngx_signal_handler },
{ SIGINT, "SIGINT", "", ngx_signal_handler },
@ -390,6 +397,13 @@ ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext)
action = ", changing binary";
break;
#if (NGX_DYNAMIC_CONF)
case ngx_signal_value(NGX_UPDATE_SIGNAL):
ngx_update = 1;
action = ", updating configuration";
break;
#endif
case SIGALRM:
ngx_sigalrm = 1;
break;
@ -431,6 +445,13 @@ ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext)
action = ", reopening logs";
break;
#if (NGX_DYNAMIC_CONF)
case ngx_signal_value(NGX_UPDATE_SIGNAL):
ngx_update = 1;
action = ", updating configuration";
break;
#endif
case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
case SIGIO:

View File

@ -10,6 +10,10 @@
#include <ngx_event.h>
#include <ngx_channel.h>
#if (NGX_DYNAMIC_CONF)
#include <ngx_dynamic_conf.h>
#endif
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
ngx_int_t type);
@ -43,6 +47,10 @@ ngx_uint_t ngx_exiting;
sig_atomic_t ngx_reconfigure;
sig_atomic_t ngx_reopen;
#if (NGX_DYNAMIC_CONF)
sig_atomic_t ngx_update;
#endif
sig_atomic_t ngx_change_binary;
ngx_pid_t ngx_new_binary;
ngx_uint_t ngx_inherited;
@ -95,6 +103,9 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
#if (NGX_DYNAMIC_CONF)
sigaddset(&set, ngx_signal_value(NGX_UPDATE_SIGNAL));
#endif
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
@ -259,6 +270,16 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
ngx_signal_value(NGX_REOPEN_SIGNAL));
}
#if (NGX_DYNAMIC_CONF)
if (ngx_update) {
ngx_update = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"updating configuration");
ngx_signal_worker_processes(cycle,
ngx_signal_value(NGX_UPDATE_SIGNAL));
}
#endif
if (ngx_change_binary) {
ngx_change_binary = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
@ -327,7 +348,19 @@ ngx_single_process_cycle(ngx_cycle_t *cycle)
ngx_reopen = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
ngx_reopen_files(cycle, (ngx_uid_t) -1);
#if (NGX_DYNAMIC_CONF)
ngx_dynamic_conf_reopen_files(cycle);
#endif
}
#if (NGX_DYNAMIC_CONF)
if (ngx_update) {
ngx_update = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"updating configuration");
(void) ngx_dynamic_conf_update(cycle);
}
#endif
}
}
@ -457,6 +490,12 @@ ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
ch.command = NGX_CMD_REOPEN;
break;
#if (NGX_DYNAMIC_CONF)
case ngx_signal_value(NGX_UPDATE_SIGNAL):
ch.command = NGX_CMD_UPDATE;
break;
#endif
default:
ch.command = 0;
}
@ -498,7 +537,12 @@ ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
&ch, sizeof(ngx_channel_t), cycle->log)
== NGX_OK)
{
if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)
#if (NGX_DYNAMIC_CONF)
&& signo != ngx_signal_value(NGX_UPDATE_SIGNAL)
#endif
)
{
ngx_processes[i].exiting = 1;
}
@ -523,9 +567,14 @@ ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
continue;
}
if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
if (signo != ngx_signal_value(NGX_REOPEN_SIGNAL)
#if (NGX_DYNAMIC_CONF)
&& signo != ngx_signal_value(NGX_UPDATE_SIGNAL)
#endif
)
{
ngx_processes[i].exiting = 1;
}
}
}
}
@ -744,7 +793,19 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
ngx_reopen = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
ngx_reopen_files(cycle, -1);
#if (NGX_DYNAMIC_CONF)
ngx_dynamic_conf_reopen_files(cycle);
#endif
}
#if (NGX_DYNAMIC_CONF)
if (ngx_update) {
ngx_update = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"updating configuration");
(void) ngx_dynamic_conf_update(cycle);
}
#endif
}
}
@ -1056,6 +1117,12 @@ ngx_channel_handler(ngx_event_t *ev)
ngx_reopen = 1;
break;
#if (NGX_DYNAMIC_CONF)
case NGX_CMD_UPDATE:
ngx_update = 1;
break;
#endif
case NGX_CMD_OPEN_CHANNEL:
ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,

View File

@ -18,6 +18,7 @@
#define NGX_CMD_QUIT 3
#define NGX_CMD_TERMINATE 4
#define NGX_CMD_REOPEN 5
#define NGX_CMD_UPDATE 6
#define NGX_PROCESS_SINGLE 0
@ -56,6 +57,9 @@ extern sig_atomic_t ngx_noaccept;
extern sig_atomic_t ngx_reconfigure;
extern sig_atomic_t ngx_reopen;
extern sig_atomic_t ngx_change_binary;
#if (NGX_DYNAMIC_CONF)
extern sig_atomic_t ngx_update;
#endif
#endif /* _NGX_PROCESS_CYCLE_H_INCLUDED_ */

View File

@ -257,6 +257,10 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
if (ngx_stream_init_filters(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}
if (ngx_stream_variables_init_vars(cf) != NGX_OK) {
return NGX_CONF_ERROR;
}

View File

@ -97,6 +97,8 @@ typedef ngx_int_t (*ngx_stream_phase_handler_pt)(ngx_stream_session_t *s,
ngx_stream_phase_handler_t *ph);
typedef ngx_int_t (*ngx_stream_handler_pt)(ngx_stream_session_t *s);
typedef void (*ngx_stream_content_handler_pt)(ngx_stream_session_t *s);
typedef ngx_int_t (*ngx_stream_filter_pt)(ngx_stream_session_t *s,
ngx_chain_t *chain, ngx_uint_t from_upstream);
struct ngx_stream_phase_handler_s {
@ -138,6 +140,8 @@ typedef struct {
ngx_array_t *ports;
ngx_stream_phase_t phases[NGX_STREAM_LOG_PHASE + 1];
ngx_stream_filter_pt top_filter;
} ngx_stream_core_main_conf_t;
@ -363,6 +367,8 @@ ngx_int_t ngx_stream_validate_host(ngx_str_t *host, ngx_pool_t *pool,
ngx_int_t ngx_stream_find_virtual_server(ngx_stream_session_t *s,
ngx_str_t *host, ngx_stream_core_srv_conf_t **cscfp);
char *ngx_stream_init_filters(ngx_conf_t *cf);
void ngx_stream_init_connection(ngx_connection_t *c);
void ngx_stream_session_handler(ngx_event_t *rev);
void ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc);
@ -373,10 +379,6 @@ extern ngx_uint_t ngx_stream_max_module;
extern ngx_module_t ngx_stream_core_module;
typedef ngx_int_t (*ngx_stream_filter_pt)(ngx_stream_session_t *s,
ngx_chain_t *chain, ngx_uint_t from_upstream);
extern ngx_stream_filter_pt ngx_stream_top_filter;

View File

@ -1502,3 +1502,18 @@ ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
}
char *
ngx_stream_init_filters(ngx_conf_t *cf)
{
ngx_stream_core_main_conf_t *cmcf;
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
cmcf->top_filter = ngx_stream_top_filter;
ngx_stream_top_filter = NULL;
return NGX_CONF_OK;
}

View File

@ -222,10 +222,6 @@ ngx_stream_pass_cleanup(void *data)
static ngx_int_t
ngx_stream_pass_match(ngx_listening_t *ls, ngx_addr_t *addr)
{
if (ls->type == SOCK_DGRAM) {
return NGX_DECLINED;
}
if (!ls->wildcard) {
return ngx_cmp_sockaddr(ls->sockaddr, ls->socklen,
addr->sockaddr, addr->socklen, 1);

View File

@ -1729,6 +1729,7 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
ngx_log_handler_pt handler;
ngx_stream_upstream_t *u;
ngx_stream_proxy_srv_conf_t *pscf;
ngx_stream_core_main_conf_t *cmcf;
u = s->upstream;
@ -1777,6 +1778,8 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
send_action = "proxying and sending to upstream";
}
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
for ( ;; ) {
if (do_write && dst) {
@ -1784,7 +1787,7 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,
if (*out || *busy || dst->buffered) {
c->log->action = send_action;
rc = ngx_stream_top_filter(s, *out, from_upstream);
rc = cmcf->top_filter(s, *out, from_upstream);
if (rc == NGX_ERROR) {
ngx_stream_proxy_finalize(s, NGX_STREAM_OK);

View File

@ -133,9 +133,10 @@ ngx_stream_return_handler(ngx_stream_session_t *s)
static void
ngx_stream_return_write_handler(ngx_event_t *ev)
{
ngx_connection_t *c;
ngx_stream_session_t *s;
ngx_stream_return_ctx_t *ctx;
ngx_connection_t *c;
ngx_stream_session_t *s;
ngx_stream_return_ctx_t *ctx;
ngx_stream_core_main_conf_t *cmcf;
c = ev->data;
s = c->data;
@ -146,9 +147,11 @@ ngx_stream_return_write_handler(ngx_event_t *ev)
return;
}
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
ctx = ngx_stream_get_module_ctx(s, ngx_stream_return_module);
if (ngx_stream_top_filter(s, ctx->out, 1) == NGX_ERROR) {
if (cmcf->top_filter(s, ctx->out, 1) == NGX_ERROR) {
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
}

View File

@ -14,6 +14,9 @@ static char *ngx_stream_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone,
void *data);
static ngx_int_t ngx_stream_upstream_zone_servers_equal(
ngx_stream_upstream_srv_conf_t *uscf,
ngx_stream_upstream_srv_conf_t *ouscf);
static ngx_stream_upstream_rr_peers_t *ngx_stream_upstream_zone_copy_peers(
ngx_slab_pool_t *shpool, ngx_stream_upstream_srv_conf_t *uscf,
ngx_stream_upstream_srv_conf_t *ouscf);
@ -121,8 +124,6 @@ ngx_stream_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
uscf->shm_zone->init = ngx_stream_upstream_init_zone;
uscf->shm_zone->data = umcf;
uscf->shm_zone->noreuse = 1;
return NGX_CONF_OK;
}
@ -130,17 +131,74 @@ ngx_stream_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static ngx_int_t
ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{
ngx_stream_upstream_main_conf_t *oumcf = data;
size_t len;
ngx_uint_t i, j;
ngx_slab_pool_t *shpool;
ngx_stream_upstream_rr_peers_t *peers, **peersp;
ngx_stream_upstream_srv_conf_t *uscf, *ouscf, **uscfp, **ouscfp;
ngx_stream_upstream_main_conf_t *umcf, *oumcf;
ngx_stream_upstream_main_conf_t *umcf;
shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
umcf = shm_zone->data;
uscfp = umcf->upstreams.elts;
if (oumcf && shpool->data) {
for (i = 0; i < umcf->upstreams.nelts; i++) {
uscf = uscfp[i];
if (uscf->shm_zone != shm_zone) {
continue;
}
for (j = 0; j < oumcf->upstreams.nelts; j++) {
ouscfp = oumcf->upstreams.elts;
if (ouscfp[j]->shm_zone == NULL) {
continue;
}
if (ouscfp[j]->shm_zone->shm.name.len != shm_zone->shm.name.len
|| ngx_memcmp(ouscfp[j]->shm_zone->shm.name.data,
shm_zone->shm.name.data,
shm_zone->shm.name.len)
!= 0)
{
continue;
}
if (ngx_stream_upstream_zone_servers_equal(uscf, ouscfp[j])
== NGX_OK)
{
uscf->peer.data = ouscfp[j]->peer.data;
goto server_found;
}
}
/* new or modified upstream, decline zone reuse */
for ( /* void */ ; i > 0; i--) {
uscf = uscfp[i - 1];
if (uscf->shm_zone != shm_zone) {
continue;
}
uscf->peer.data = NULL;
}
return NGX_DECLINED;
server_found:
continue;
}
return NGX_OK;
}
if (shm_zone->shm.exists) {
peers = shpool->data;
@ -172,7 +230,6 @@ ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
/* copy peers to shared memory */
peersp = (ngx_stream_upstream_rr_peers_t **) (void *) &shpool->data;
oumcf = data;
for (i = 0; i < umcf->upstreams.nelts; i++) {
uscf = uscfp[i];
@ -225,6 +282,66 @@ ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
}
static ngx_int_t
ngx_stream_upstream_zone_servers_equal(ngx_stream_upstream_srv_conf_t *uscf,
ngx_stream_upstream_srv_conf_t *ouscf)
{
ngx_uint_t n;
ngx_stream_upstream_server_t *us, *ous;
if (uscf->host.len != ouscf->host.len
|| ngx_strncmp(uscf->host.data, ouscf->host.data, uscf->host.len) != 0)
{
return NGX_DECLINED;
}
if (uscf->servers == NULL
|| ouscf->servers == NULL
|| uscf->servers->nelts != ouscf->servers->nelts)
{
return NGX_DECLINED;
}
us = uscf->servers->elts;
ous = ouscf->servers->elts;
for (n = 0; n < uscf->servers->nelts; n++) {
if (us->name.len != ous->name.len
|| ngx_strncmp(us->name.data, ous->name.data, us->name.len) != 0)
{
return NGX_DECLINED;
}
if (us->host.len != ous->host.len
|| ngx_strncmp(us->host.data, ous->host.data, us->host.len) != 0)
{
return NGX_DECLINED;
}
if (us->service.len != ous->service.len
|| ngx_strncmp(us->service.data, ous->service.data, us->service.len)
!= 0)
{
return NGX_DECLINED;
}
if (us->weight != ous->weight
|| us->max_conns != ous->max_conns
|| us->max_fails != ous->max_fails
|| us->fail_timeout != ous->fail_timeout
|| us->slow_start != ous->slow_start
|| us->down != ous->down
|| us->backup != ous->backup)
{
return NGX_DECLINED;
}
}
return NGX_OK;
}
static ngx_stream_upstream_rr_peers_t *
ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool,
ngx_stream_upstream_srv_conf_t *uscf, ngx_stream_upstream_srv_conf_t *ouscf)