[nginx] svn commit: r4272 - trunk/src/http/modules
vbart at nginx.com
vbart at nginx.com
Thu Nov 10 16:08:14 UTC 2011
Author: vbart
Date: 2011-11-10 16:08:13 +0000 (Thu, 10 Nov 2011)
New Revision: 4272
Modified:
trunk/src/http/modules/ngx_http_limit_zone_module.c
Log:
Limit zone: support for multiple "limit_conn" limits.
Modified: trunk/src/http/modules/ngx_http_limit_zone_module.c
===================================================================
--- trunk/src/http/modules/ngx_http_limit_zone_module.c 2011-11-10 15:51:55 UTC (rev 4271)
+++ trunk/src/http/modules/ngx_http_limit_zone_module.c 2011-11-10 16:08:13 UTC (rev 4272)
@@ -33,6 +33,11 @@
typedef struct {
ngx_shm_zone_t *shm_zone;
ngx_uint_t conn;
+} ngx_http_limit_zone_limit_t;
+
+
+typedef struct {
+ ngx_array_t limits;
ngx_uint_t log_level;
} ngx_http_limit_zone_conf_t;
@@ -40,6 +45,7 @@
static ngx_rbtree_node_t *ngx_http_limit_zone_lookup(ngx_rbtree_t *rbtree,
ngx_http_variable_value_t *vv, uint32_t hash);
static void ngx_http_limit_zone_cleanup(void *data);
+static ngx_inline void ngx_http_limit_zone_cleanup_all(ngx_pool_t *pool);
static void *ngx_http_limit_zone_create_conf(ngx_conf_t *cf);
static char *ngx_http_limit_zone_merge_conf(ngx_conf_t *cf, void *parent,
@@ -123,6 +129,7 @@
{
size_t len, n;
uint32_t hash;
+ ngx_uint_t i;
ngx_slab_pool_t *shpool;
ngx_rbtree_node_t *node;
ngx_pool_cleanup_t *cln;
@@ -130,6 +137,7 @@
ngx_http_limit_zone_ctx_t *ctx;
ngx_http_limit_zone_node_t *lz;
ngx_http_limit_zone_conf_t *lzcf;
+ ngx_http_limit_zone_limit_t *limits;
ngx_http_limit_zone_cleanup_t *lzcln;
if (r->main->limit_zone_set) {
@@ -137,97 +145,100 @@
}
lzcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_zone_module);
+ limits = lzcf->limits.elts;
- if (lzcf->shm_zone == NULL) {
- return NGX_DECLINED;
- }
+ r->main->limit_zone_set = 1;
- ctx = lzcf->shm_zone->data;
+ for (i = 0; i < lzcf->limits.nelts; i++) {
+ ctx = limits[i].shm_zone->data;
- vv = ngx_http_get_indexed_variable(r, ctx->index);
+ vv = ngx_http_get_indexed_variable(r, ctx->index);
- if (vv == NULL || vv->not_found) {
- return NGX_DECLINED;
- }
+ if (vv == NULL || vv->not_found) {
+ continue;
+ }
- len = vv->len;
+ len = vv->len;
- if (len == 0) {
- return NGX_DECLINED;
- }
+ if (len == 0) {
+ continue;
+ }
- if (len > 255) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the value of the \"%V\" variable "
- "is more than 255 bytes: \"%v\"",
- &ctx->var, vv);
- return NGX_DECLINED;
- }
+ if (len > 255) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "the value of the \"%V\" variable "
+ "is more than 255 bytes: \"%v\"",
+ &ctx->var, vv);
+ continue;
+ }
- r->main->limit_zone_set = 1;
+ hash = ngx_crc32_short(vv->data, len);
- hash = ngx_crc32_short(vv->data, len);
+ shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
- cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_limit_zone_cleanup_t));
- if (cln == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+ ngx_shmtx_lock(&shpool->mutex);
- shpool = (ngx_slab_pool_t *) lzcf->shm_zone->shm.addr;
+ node = ngx_http_limit_zone_lookup(ctx->rbtree, vv, hash);
- ngx_shmtx_lock(&shpool->mutex);
+ if (node == NULL) {
- node = ngx_http_limit_zone_lookup(ctx->rbtree, vv, hash);
+ n = offsetof(ngx_rbtree_node_t, color)
+ + offsetof(ngx_http_limit_zone_node_t, data)
+ + len;
- if (node == NULL) {
+ node = ngx_slab_alloc_locked(shpool, n);
- n = offsetof(ngx_rbtree_node_t, color)
- + offsetof(ngx_http_limit_zone_node_t, data)
- + len;
+ if (node == NULL) {
+ ngx_shmtx_unlock(&shpool->mutex);
+ ngx_http_limit_zone_cleanup_all(r->pool);
+ return NGX_HTTP_SERVICE_UNAVAILABLE;
+ }
- node = ngx_slab_alloc_locked(shpool, n);
- if (node == NULL) {
- ngx_shmtx_unlock(&shpool->mutex);
- return NGX_HTTP_SERVICE_UNAVAILABLE;
- }
+ lz = (ngx_http_limit_zone_node_t *) &node->color;
- lz = (ngx_http_limit_zone_node_t *) &node->color;
+ node->key = hash;
+ lz->len = (u_char) len;
+ lz->conn = 1;
+ ngx_memcpy(lz->data, vv->data, len);
- node->key = hash;
- lz->len = (u_char) len;
- lz->conn = 1;
- ngx_memcpy(lz->data, vv->data, len);
+ ngx_rbtree_insert(ctx->rbtree, node);
- ngx_rbtree_insert(ctx->rbtree, node);
+ } else {
- } else {
+ lz = (ngx_http_limit_zone_node_t *) &node->color;
- lz = (ngx_http_limit_zone_node_t *) &node->color;
+ if ((ngx_uint_t) lz->conn >= limits[i].conn) {
- if ((ngx_uint_t) lz->conn >= lzcf->conn) {
+ ngx_shmtx_unlock(&shpool->mutex);
- ngx_shmtx_unlock(&shpool->mutex);
+ ngx_log_error(lzcf->log_level, r->connection->log, 0,
+ "limiting connections by zone \"%V\"",
+ &limits[i].shm_zone->shm.name);
- ngx_log_error(lzcf->log_level, r->connection->log, 0,
- "limiting connections by zone \"%V\"",
- &lzcf->shm_zone->shm.name);
+ ngx_http_limit_zone_cleanup_all(r->pool);
+ return NGX_HTTP_SERVICE_UNAVAILABLE;
+ }
- return NGX_HTTP_SERVICE_UNAVAILABLE;
+ lz->conn++;
}
- lz->conn++;
- }
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "limit zone: %08XD %d", node->key, lz->conn);
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "limit zone: %08XD %d", node->key, lz->conn);
+ ngx_shmtx_unlock(&shpool->mutex);
- ngx_shmtx_unlock(&shpool->mutex);
+ cln = ngx_pool_cleanup_add(r->pool,
+ sizeof(ngx_http_limit_zone_cleanup_t));
+ if (cln == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
- cln->handler = ngx_http_limit_zone_cleanup;
- lzcln = cln->data;
+ cln->handler = ngx_http_limit_zone_cleanup;
+ lzcln = cln->data;
- lzcln->shm_zone = lzcf->shm_zone;
- lzcln->node = node;
+ lzcln->shm_zone = limits[i].shm_zone;
+ lzcln->node = node;
+ }
return NGX_DECLINED;
}
@@ -350,6 +361,22 @@
}
+static ngx_inline void
+ngx_http_limit_zone_cleanup_all(ngx_pool_t *pool)
+{
+ ngx_pool_cleanup_t *cln;
+
+ cln = pool->cleanup;
+
+ while (cln && cln->handler == ngx_http_limit_zone_cleanup) {
+ ngx_http_limit_zone_cleanup(cln->data);
+ cln = cln->next;
+ }
+
+ pool->cleanup = cln;
+}
+
+
static ngx_int_t
ngx_http_limit_zone_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{
@@ -426,8 +453,7 @@
/*
* set by ngx_pcalloc():
*
- * conf->shm_zone = NULL;
- * conf->conn = 0;
+ * conf->limits.elts = NULL;
*/
conf->log_level = NGX_CONF_UNSET_UINT;
@@ -442,7 +468,7 @@
ngx_http_limit_zone_conf_t *prev = parent;
ngx_http_limit_zone_conf_t *conf = child;
- if (conf->shm_zone == NULL) {
+ if (conf->limits.elts == NULL) {
*conf = *prev;
}
@@ -523,23 +549,39 @@
static char *
ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_limit_zone_conf_t *lzcf = conf;
+ ngx_shm_zone_t *shm_zone;
+ ngx_http_limit_zone_conf_t *lzcf = conf;
+ ngx_http_limit_zone_limit_t *limit, *limits;
+ ngx_str_t *value;
ngx_int_t n;
- ngx_str_t *value;
+ ngx_uint_t i;
- if (lzcf->shm_zone) {
- return "is duplicate";
- }
-
value = cf->args->elts;
- lzcf->shm_zone = ngx_shared_memory_add(cf, &value[1], 0,
- &ngx_http_limit_zone_module);
- if (lzcf->shm_zone == NULL) {
+ shm_zone = ngx_shared_memory_add(cf, &value[1], 0,
+ &ngx_http_limit_zone_module);
+ if (shm_zone == NULL) {
return NGX_CONF_ERROR;
}
+ limits = lzcf->limits.elts;
+
+ if (limits == NULL) {
+ if (ngx_array_init(&lzcf->limits, cf->pool, 1,
+ sizeof(ngx_http_limit_zone_limit_t))
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ for (i = 0; i < lzcf->limits.nelts; i++) {
+ if (shm_zone == limits[i].shm_zone) {
+ return "is duplicate";
+ }
+ }
+
n = ngx_atoi(value[2].data, value[2].len);
if (n <= 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -553,7 +595,9 @@
return NGX_CONF_ERROR;
}
- lzcf->conn = n;
+ limit = ngx_array_push(&lzcf->limits);
+ limit->conn = n;
+ limit->shm_zone = shm_zone;
return NGX_CONF_OK;
}
More information about the nginx-devel
mailing list