# HG changeset patch # User Ruslan Ermilov # Date 1429717054 -10800 # Node ID caa103acf18018c5931b8f0ee304f2cdde704786 # Parent 85f00678e54a54d2ca3017a8ec852c973f40dc7e Upstream: allow multiple upstreams to use the same shared zone. diff --git a/src/http/modules/ngx_http_upstream_zone_module.c b/src/http/modules/ngx_http_upstream_zone_module.c --- a/src/http/modules/ngx_http_upstream_zone_module.c +++ b/src/http/modules/ngx_http_upstream_zone_module.c @@ -14,12 +14,14 @@ static char *ngx_http_upstream_zone(ngx_ 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_copy_peers(ngx_slab_pool_t *shpool, + ngx_http_upstream_srv_conf_t *uscf); static ngx_command_t ngx_http_upstream_zone_commands[] = { { ngx_string("zone"), - NGX_HTTP_UPS_CONF|NGX_CONF_TAKE2, + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, ngx_http_upstream_zone, 0, 0, @@ -63,11 +65,13 @@ ngx_module_t ngx_http_upstream_zone_mod static char * ngx_http_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_upstream_srv_conf_t *uscf; - ssize_t size; - ngx_str_t *value; + ssize_t size; + ngx_str_t *value; + ngx_http_upstream_srv_conf_t *uscf; + ngx_http_upstream_main_conf_t *umcf; uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module); value = cf->args->elts; @@ -77,18 +81,23 @@ ngx_http_upstream_zone(ngx_conf_t *cf, n return NGX_CONF_ERROR; } - size = ngx_parse_size(&value[2]); + if (cf->args->nelts == 3) { + size = ngx_parse_size(&value[2]); + + if (size == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid zone size \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } - if (size == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid zone size \"%V\"", &value[2]); - return NGX_CONF_ERROR; - } + if (size < (ssize_t) (8 * ngx_pagesize)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "zone \"%V\" is too small", &value[1]); + return NGX_CONF_ERROR; + } - if (size < (ssize_t) (8 * ngx_pagesize)) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "zone \"%V\" is too small", &value[1]); - return NGX_CONF_ERROR; + } else { + size = 0; } uscf->shm_zone = ngx_shared_memory_add(cf, &value[1], size, @@ -97,19 +106,8 @@ ngx_http_upstream_zone(ngx_conf_t *cf, n return NGX_CONF_ERROR; } - if (uscf->shm_zone->data) { - uscf = uscf->shm_zone->data; - - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "upstream \"%V\" in %s:%ui " - "is already bound to zone \"%V\"", - &uscf->host, uscf->file_name, uscf->line, - &value[1]); - return NGX_CONF_ERROR; - } - uscf->shm_zone->init = ngx_http_upstream_init_zone; - uscf->shm_zone->data = uscf; + uscf->shm_zone->data = umcf; uscf->shm_zone->noreuse = 1; @@ -120,21 +118,11 @@ ngx_http_upstream_zone(ngx_conf_t *cf, n static ngx_int_t ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data) { - ngx_http_upstream_srv_conf_t *ouscf = data; - size_t len; + ngx_uint_t i; ngx_slab_pool_t *shpool; - ngx_http_upstream_rr_peer_t *peer, **peerp; - ngx_http_upstream_rr_peers_t *peers, *backup; - ngx_http_upstream_srv_conf_t *uscf; - - uscf = shm_zone->data; - - if (ouscf) { - ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, - "zone \"%V\" cannot be reused", &shm_zone->shm.name); - return NGX_ERROR; - } + ngx_http_upstream_srv_conf_t *uscf, **uscfp; + ngx_http_upstream_main_conf_t *umcf; shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; @@ -142,9 +130,6 @@ ngx_http_upstream_init_zone(ngx_shm_zone return NGX_ERROR; } - - /* copy peers to shared memory */ - len = sizeof(" in upstream zone \"\"") + shm_zone->shm.name.len; shpool->log_ctx = ngx_slab_alloc(shpool, len); @@ -155,6 +140,35 @@ ngx_http_upstream_init_zone(ngx_shm_zone ngx_sprintf(shpool->log_ctx, " in upstream zone \"%V\"%Z", &shm_zone->shm.name); + + /* copy peers to shared memory */ + + umcf = shm_zone->data; + uscfp = umcf->upstreams.elts; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + uscf = uscfp[i]; + + if (uscf->shm_zone != shm_zone) { + continue; + } + + if (ngx_http_upstream_zone_copy_peers(shpool, uscf) != NGX_OK) { + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, + ngx_http_upstream_srv_conf_t *uscf) +{ + ngx_http_upstream_rr_peer_t *peer, **peerp; + ngx_http_upstream_rr_peers_t *peers, *backup; + peers = ngx_slab_alloc(shpool, sizeof(ngx_http_upstream_rr_peers_t)); if (peers == NULL) { return NGX_ERROR; diff --git a/src/stream/ngx_stream_upstream_zone_module.c b/src/stream/ngx_stream_upstream_zone_module.c --- a/src/stream/ngx_stream_upstream_zone_module.c +++ b/src/stream/ngx_stream_upstream_zone_module.c @@ -14,12 +14,14 @@ static char *ngx_stream_upstream_zone(ng 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_copy_peers(ngx_slab_pool_t *shpool, + ngx_stream_upstream_srv_conf_t *uscf); static ngx_command_t ngx_stream_upstream_zone_commands[] = { { ngx_string("zone"), - NGX_STREAM_UPS_CONF|NGX_CONF_TAKE2, + NGX_STREAM_UPS_CONF|NGX_CONF_TAKE12, ngx_stream_upstream_zone, 0, 0, @@ -57,11 +59,13 @@ ngx_module_t ngx_stream_upstream_zone_m static char * ngx_stream_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ssize_t size; - ngx_str_t *value; - ngx_stream_upstream_srv_conf_t *uscf; + ssize_t size; + ngx_str_t *value; + ngx_stream_upstream_srv_conf_t *uscf; + ngx_stream_upstream_main_conf_t *umcf; uscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_upstream_module); + umcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_upstream_module); value = cf->args->elts; @@ -71,18 +75,23 @@ ngx_stream_upstream_zone(ngx_conf_t *cf, return NGX_CONF_ERROR; } - size = ngx_parse_size(&value[2]); + if (cf->args->nelts == 3) { + size = ngx_parse_size(&value[2]); + + if (size == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid zone size \"%V\"", &value[2]); + return NGX_CONF_ERROR; + } - if (size == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid zone size \"%V\"", &value[2]); - return NGX_CONF_ERROR; - } + if (size < (ssize_t) (8 * ngx_pagesize)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "zone \"%V\" is too small", &value[1]); + return NGX_CONF_ERROR; + } - if (size < (ssize_t) (8 * ngx_pagesize)) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "zone \"%V\" is too small", &value[1]); - return NGX_CONF_ERROR; + } else { + size = 0; } uscf->shm_zone = ngx_shared_memory_add(cf, &value[1], size, @@ -91,19 +100,8 @@ ngx_stream_upstream_zone(ngx_conf_t *cf, return NGX_CONF_ERROR; } - if (uscf->shm_zone->data) { - uscf = uscf->shm_zone->data; - - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "upstream \"%V\" in %s:%ui " - "is already bound to zone \"%V\"", - &uscf->host, uscf->file_name, uscf->line, - &value[1]); - return NGX_CONF_ERROR; - } - uscf->shm_zone->init = ngx_stream_upstream_init_zone; - uscf->shm_zone->data = uscf; + uscf->shm_zone->data = umcf; uscf->shm_zone->noreuse = 1; @@ -114,21 +112,11 @@ ngx_stream_upstream_zone(ngx_conf_t *cf, static ngx_int_t ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data) { - ngx_stream_upstream_srv_conf_t *ouscf = data; - size_t len; + ngx_uint_t i; ngx_slab_pool_t *shpool; - ngx_stream_upstream_rr_peer_t *peer, **peerp; - ngx_stream_upstream_rr_peers_t *peers, *backup; - ngx_stream_upstream_srv_conf_t *uscf; - - uscf = shm_zone->data; - - if (ouscf) { - ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, - "zone \"%V\" cannot be reused", &shm_zone->shm.name); - return NGX_ERROR; - } + ngx_stream_upstream_srv_conf_t *uscf, **uscfp; + ngx_stream_upstream_main_conf_t *umcf; shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; @@ -136,9 +124,6 @@ ngx_stream_upstream_init_zone(ngx_shm_zo return NGX_ERROR; } - - /* copy peers to shared memory */ - len = sizeof(" in upstream zone \"\"") + shm_zone->shm.name.len; shpool->log_ctx = ngx_slab_alloc(shpool, len); @@ -149,6 +134,35 @@ ngx_stream_upstream_init_zone(ngx_shm_zo ngx_sprintf(shpool->log_ctx, " in upstream zone \"%V\"%Z", &shm_zone->shm.name); + + /* copy peers to shared memory */ + + umcf = shm_zone->data; + uscfp = umcf->upstreams.elts; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + uscf = uscfp[i]; + + if (uscf->shm_zone != shm_zone) { + continue; + } + + if (ngx_stream_upstream_zone_copy_peers(shpool, uscf) != NGX_OK) { + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, + ngx_stream_upstream_srv_conf_t *uscf) +{ + ngx_stream_upstream_rr_peer_t *peer, **peerp; + ngx_stream_upstream_rr_peers_t *peers, *backup; + peers = ngx_slab_alloc(shpool, sizeof(ngx_stream_upstream_rr_peers_t)); if (peers == NULL) { return NGX_ERROR;