From 54346b61f91008c5098243b588f184ad92ad29c9 Mon Sep 17 00:00:00 2001 From: Yu Ping Date: Fri, 21 Feb 2020 22:36:20 +0800 Subject: initial version of VSAP Signed-off-by: Yu Ping Change-Id: I04d9150f0c7607ba20de9096b452476eff1622fc --- .../http/modules/ngx_http_upstream_zone_module.c | 325 +++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 nginx/src/http/modules/ngx_http_upstream_zone_module.c (limited to 'nginx/src/http/modules/ngx_http_upstream_zone_module.c') diff --git a/nginx/src/http/modules/ngx_http_upstream_zone_module.c b/nginx/src/http/modules/ngx_http_upstream_zone_module.c new file mode 100644 index 0000000..3229cfe --- /dev/null +++ b/nginx/src/http/modules/ngx_http_upstream_zone_module.c @@ -0,0 +1,325 @@ + +/* + * Copyright (C) Ruslan Ermilov + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +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_http_upstream_rr_peers_t *ngx_http_upstream_zone_copy_peers( + ngx_slab_pool_t *shpool, ngx_http_upstream_srv_conf_t *uscf); +static ngx_http_upstream_rr_peer_t *ngx_http_upstream_zone_copy_peer( + ngx_http_upstream_rr_peers_t *peers, ngx_http_upstream_rr_peer_t *src); + + +static ngx_command_t ngx_http_upstream_zone_commands[] = { + + { ngx_string("zone"), + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, + ngx_http_upstream_zone, + 0, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_upstream_zone_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_upstream_zone_module = { + NGX_MODULE_V1, + &ngx_http_upstream_zone_module_ctx, /* module context */ + ngx_http_upstream_zone_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static char * +ngx_http_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + 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; + + if (!value[1].len) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid zone name \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + + 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 < (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, + &ngx_http_upstream_module); + if (uscf->shm_zone == NULL) { + return NGX_CONF_ERROR; + } + + uscf->shm_zone->init = ngx_http_upstream_init_zone; + uscf->shm_zone->data = umcf; + + uscf->shm_zone->noreuse = 1; + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data) +{ + size_t len; + ngx_uint_t i; + ngx_slab_pool_t *shpool; + ngx_http_upstream_rr_peers_t *peers, **peersp; + ngx_http_upstream_srv_conf_t *uscf, **uscfp; + 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 (shm_zone->shm.exists) { + peers = shpool->data; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + uscf = uscfp[i]; + + if (uscf->shm_zone != shm_zone) { + continue; + } + + uscf->peer.data = peers; + peers = peers->zone_next; + } + + return NGX_OK; + } + + len = sizeof(" in upstream zone \"\"") + shm_zone->shm.name.len; + + shpool->log_ctx = ngx_slab_alloc(shpool, len); + if (shpool->log_ctx == NULL) { + return NGX_ERROR; + } + + ngx_sprintf(shpool->log_ctx, " in upstream zone \"%V\"%Z", + &shm_zone->shm.name); + + + /* copy peers to shared memory */ + + peersp = (ngx_http_upstream_rr_peers_t **) (void *) &shpool->data; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + uscf = uscfp[i]; + + if (uscf->shm_zone != shm_zone) { + continue; + } + + peers = ngx_http_upstream_zone_copy_peers(shpool, uscf); + if (peers == NULL) { + return NGX_ERROR; + } + + *peersp = peers; + peersp = &peers->zone_next; + } + + 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_str_t *name; + 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 NULL; + } + + ngx_memcpy(peers, uscf->peer.data, sizeof(ngx_http_upstream_rr_peers_t)); + + name = ngx_slab_alloc(shpool, sizeof(ngx_str_t)); + if (name == NULL) { + return NULL; + } + + name->data = ngx_slab_alloc(shpool, peers->name->len); + if (name->data == NULL) { + return NULL; + } + + ngx_memcpy(name->data, peers->name->data, peers->name->len); + name->len = peers->name->len; + + peers->name = name; + + peers->shpool = shpool; + + for (peerp = &peers->peer; *peerp; peerp = &peer->next) { + /* pool is unlocked */ + peer = ngx_http_upstream_zone_copy_peer(peers, *peerp); + if (peer == NULL) { + return NULL; + } + + *peerp = peer; + } + + if (peers->next == NULL) { + goto done; + } + + backup = ngx_slab_alloc(shpool, sizeof(ngx_http_upstream_rr_peers_t)); + if (backup == NULL) { + return NULL; + } + + ngx_memcpy(backup, peers->next, sizeof(ngx_http_upstream_rr_peers_t)); + + backup->name = name; + + backup->shpool = shpool; + + for (peerp = &backup->peer; *peerp; peerp = &peer->next) { + /* pool is unlocked */ + peer = ngx_http_upstream_zone_copy_peer(backup, *peerp); + if (peer == NULL) { + return NULL; + } + + *peerp = peer; + } + + peers->next = backup; + +done: + + uscf->peer.data = peers; + + return peers; +} + + +static ngx_http_upstream_rr_peer_t * +ngx_http_upstream_zone_copy_peer(ngx_http_upstream_rr_peers_t *peers, + ngx_http_upstream_rr_peer_t *src) +{ + ngx_slab_pool_t *pool; + ngx_http_upstream_rr_peer_t *dst; + + pool = peers->shpool; + + dst = ngx_slab_calloc_locked(pool, sizeof(ngx_http_upstream_rr_peer_t)); + if (dst == NULL) { + return NULL; + } + + if (src) { + ngx_memcpy(dst, src, sizeof(ngx_http_upstream_rr_peer_t)); + dst->sockaddr = NULL; + dst->name.data = NULL; + dst->server.data = NULL; + } + + dst->sockaddr = ngx_slab_calloc_locked(pool, sizeof(ngx_sockaddr_t)); + if (dst->sockaddr == NULL) { + goto failed; + } + + dst->name.data = ngx_slab_calloc_locked(pool, NGX_SOCKADDR_STRLEN); + if (dst->name.data == NULL) { + goto failed; + } + + if (src) { + ngx_memcpy(dst->sockaddr, src->sockaddr, src->socklen); + ngx_memcpy(dst->name.data, src->name.data, src->name.len); + + dst->server.data = ngx_slab_alloc_locked(pool, src->server.len); + if (dst->server.data == NULL) { + goto failed; + } + + ngx_memcpy(dst->server.data, src->server.data, src->server.len); + } + + return dst; + +failed: + + if (dst->server.data) { + ngx_slab_free_locked(pool, dst->server.data); + } + + if (dst->name.data) { + ngx_slab_free_locked(pool, dst->name.data); + } + + if (dst->sockaddr) { + ngx_slab_free_locked(pool, dst->sockaddr); + } + + ngx_slab_free_locked(pool, dst); + + return NULL; +} -- cgit 1.2.3-korg