# HG changeset patch # User Valentin Bartenev # Date 1320940315 0 # Node ID 3544987fef859613f37e21d281c5b9cf058e0372 # Parent d9cffafbe9442895c69f8d577915c3d9a11afb84 Limit zone: rbtree lookup moved to a separate function. No functional changes. diff --git a/src/http/modules/ngx_http_limit_zone_module.c b/src/http/modules/ngx_http_limit_zone_module.c --- a/src/http/modules/ngx_http_limit_zone_module.c +++ b/src/http/modules/ngx_http_limit_zone_module.c @@ -37,6 +37,8 @@ typedef struct { } ngx_http_limit_zone_conf_t; +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 void *ngx_http_limit_zone_create_conf(ngx_conf_t *cf); @@ -121,9 +123,8 @@ ngx_http_limit_zone_handler(ngx_http_req { size_t len, n; uint32_t hash; - ngx_int_t rc; ngx_slab_pool_t *shpool; - ngx_rbtree_node_t *node, *sentinel; + ngx_rbtree_node_t *node; ngx_pool_cleanup_t *cln; ngx_http_variable_value_t *vv; ngx_http_limit_zone_ctx_t *ctx; @@ -176,70 +177,46 @@ ngx_http_limit_zone_handler(ngx_http_req ngx_shmtx_lock(&shpool->mutex); - node = ctx->rbtree->root; - sentinel = ctx->rbtree->sentinel; + node = ngx_http_limit_zone_lookup(ctx->rbtree, vv, hash); - while (node != sentinel) { + if (node == NULL) { - if (hash < node->key) { - node = node->left; - continue; - } + n = offsetof(ngx_rbtree_node_t, color) + + offsetof(ngx_http_limit_zone_node_t, data) + + len; - if (hash > node->key) { - node = node->right; - continue; + node = ngx_slab_alloc_locked(shpool, n); + if (node == NULL) { + ngx_shmtx_unlock(&shpool->mutex); + return NGX_HTTP_SERVICE_UNAVAILABLE; } - /* hash == node->key */ - - do { - lz = (ngx_http_limit_zone_node_t *) &node->color; - - rc = ngx_memn2cmp(vv->data, lz->data, len, (size_t) lz->len); + lz = (ngx_http_limit_zone_node_t *) &node->color; - if (rc == 0) { - if ((ngx_uint_t) lz->conn < lzcf->conn) { - lz->conn++; - goto done; - } - - ngx_shmtx_unlock(&shpool->mutex); + node->key = hash; + lz->len = (u_char) len; + lz->conn = 1; + ngx_memcpy(lz->data, vv->data, len); - ngx_log_error(lzcf->log_level, r->connection->log, 0, - "limiting connections by zone \"%V\"", - &lzcf->shm_zone->shm.name); + ngx_rbtree_insert(ctx->rbtree, node); - return NGX_HTTP_SERVICE_UNAVAILABLE; - } + } else { - node = (rc < 0) ? node->left : node->right; + lz = (ngx_http_limit_zone_node_t *) &node->color; - } while (node != sentinel && hash == node->key); + if ((ngx_uint_t) lz->conn >= lzcf->conn) { - break; - } - - n = offsetof(ngx_rbtree_node_t, color) - + offsetof(ngx_http_limit_zone_node_t, data) - + len; + ngx_shmtx_unlock(&shpool->mutex); - 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; + ngx_log_error(lzcf->log_level, r->connection->log, 0, + "limiting connections by zone \"%V\"", + &lzcf->shm_zone->shm.name); - node->key = hash; - lz->len = (u_char) len; - lz->conn = 1; - ngx_memcpy(lz->data, vv->data, len); + return NGX_HTTP_SERVICE_UNAVAILABLE; + } - ngx_rbtree_insert(ctx->rbtree, node); - -done: + lz->conn++; + } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "limit zone: %08XD %d", node->key, lz->conn); @@ -297,6 +274,51 @@ ngx_http_limit_zone_rbtree_insert_value( } +static ngx_rbtree_node_t * +ngx_http_limit_zone_lookup(ngx_rbtree_t *rbtree, ngx_http_variable_value_t *vv, + uint32_t hash) +{ + ngx_int_t rc; + ngx_rbtree_node_t *node, *sentinel; + ngx_http_limit_zone_node_t *lzn; + + node = rbtree->root; + sentinel = rbtree->sentinel; + + while (node != sentinel) { + + if (hash < node->key) { + node = node->left; + continue; + } + + if (hash > node->key) { + node = node->right; + continue; + } + + /* hash == node->key */ + + do { + lzn = (ngx_http_limit_zone_node_t *) &node->color; + + rc = ngx_memn2cmp(vv->data, lzn->data, + (size_t) vv->len, (size_t) lzn->len); + if (rc == 0) { + return node; + } + + node = (rc < 0) ? node->left : node->right; + + } while (node != sentinel && hash == node->key); + + break; + } + + return NULL; +} + + static void ngx_http_limit_zone_cleanup(void *data) {