comparison src/http/modules/ngx_http_limit_zone_module.c @ 4270:3544987fef85

Limit zone: rbtree lookup moved to a separate function. No functional changes.
author Valentin Bartenev <vbart@nginx.com>
date Thu, 10 Nov 2011 15:51:55 +0000
parents 23d567eabc5d
children b86cceba426a
comparison
equal deleted inserted replaced
4269:d9cffafbe944 4270:3544987fef85
35 ngx_uint_t conn; 35 ngx_uint_t conn;
36 ngx_uint_t log_level; 36 ngx_uint_t log_level;
37 } ngx_http_limit_zone_conf_t; 37 } ngx_http_limit_zone_conf_t;
38 38
39 39
40 static ngx_rbtree_node_t *ngx_http_limit_zone_lookup(ngx_rbtree_t *rbtree,
41 ngx_http_variable_value_t *vv, uint32_t hash);
40 static void ngx_http_limit_zone_cleanup(void *data); 42 static void ngx_http_limit_zone_cleanup(void *data);
41 43
42 static void *ngx_http_limit_zone_create_conf(ngx_conf_t *cf); 44 static void *ngx_http_limit_zone_create_conf(ngx_conf_t *cf);
43 static char *ngx_http_limit_zone_merge_conf(ngx_conf_t *cf, void *parent, 45 static char *ngx_http_limit_zone_merge_conf(ngx_conf_t *cf, void *parent,
44 void *child); 46 void *child);
119 static ngx_int_t 121 static ngx_int_t
120 ngx_http_limit_zone_handler(ngx_http_request_t *r) 122 ngx_http_limit_zone_handler(ngx_http_request_t *r)
121 { 123 {
122 size_t len, n; 124 size_t len, n;
123 uint32_t hash; 125 uint32_t hash;
124 ngx_int_t rc;
125 ngx_slab_pool_t *shpool; 126 ngx_slab_pool_t *shpool;
126 ngx_rbtree_node_t *node, *sentinel; 127 ngx_rbtree_node_t *node;
127 ngx_pool_cleanup_t *cln; 128 ngx_pool_cleanup_t *cln;
128 ngx_http_variable_value_t *vv; 129 ngx_http_variable_value_t *vv;
129 ngx_http_limit_zone_ctx_t *ctx; 130 ngx_http_limit_zone_ctx_t *ctx;
130 ngx_http_limit_zone_node_t *lz; 131 ngx_http_limit_zone_node_t *lz;
131 ngx_http_limit_zone_conf_t *lzcf; 132 ngx_http_limit_zone_conf_t *lzcf;
174 175
175 shpool = (ngx_slab_pool_t *) lzcf->shm_zone->shm.addr; 176 shpool = (ngx_slab_pool_t *) lzcf->shm_zone->shm.addr;
176 177
177 ngx_shmtx_lock(&shpool->mutex); 178 ngx_shmtx_lock(&shpool->mutex);
178 179
179 node = ctx->rbtree->root; 180 node = ngx_http_limit_zone_lookup(ctx->rbtree, vv, hash);
180 sentinel = ctx->rbtree->sentinel; 181
181
182 while (node != sentinel) {
183
184 if (hash < node->key) {
185 node = node->left;
186 continue;
187 }
188
189 if (hash > node->key) {
190 node = node->right;
191 continue;
192 }
193
194 /* hash == node->key */
195
196 do {
197 lz = (ngx_http_limit_zone_node_t *) &node->color;
198
199 rc = ngx_memn2cmp(vv->data, lz->data, len, (size_t) lz->len);
200
201 if (rc == 0) {
202 if ((ngx_uint_t) lz->conn < lzcf->conn) {
203 lz->conn++;
204 goto done;
205 }
206
207 ngx_shmtx_unlock(&shpool->mutex);
208
209 ngx_log_error(lzcf->log_level, r->connection->log, 0,
210 "limiting connections by zone \"%V\"",
211 &lzcf->shm_zone->shm.name);
212
213 return NGX_HTTP_SERVICE_UNAVAILABLE;
214 }
215
216 node = (rc < 0) ? node->left : node->right;
217
218 } while (node != sentinel && hash == node->key);
219
220 break;
221 }
222
223 n = offsetof(ngx_rbtree_node_t, color)
224 + offsetof(ngx_http_limit_zone_node_t, data)
225 + len;
226
227 node = ngx_slab_alloc_locked(shpool, n);
228 if (node == NULL) { 182 if (node == NULL) {
229 ngx_shmtx_unlock(&shpool->mutex); 183
230 return NGX_HTTP_SERVICE_UNAVAILABLE; 184 n = offsetof(ngx_rbtree_node_t, color)
231 } 185 + offsetof(ngx_http_limit_zone_node_t, data)
232 186 + len;
233 lz = (ngx_http_limit_zone_node_t *) &node->color; 187
234 188 node = ngx_slab_alloc_locked(shpool, n);
235 node->key = hash; 189 if (node == NULL) {
236 lz->len = (u_char) len; 190 ngx_shmtx_unlock(&shpool->mutex);
237 lz->conn = 1; 191 return NGX_HTTP_SERVICE_UNAVAILABLE;
238 ngx_memcpy(lz->data, vv->data, len); 192 }
239 193
240 ngx_rbtree_insert(ctx->rbtree, node); 194 lz = (ngx_http_limit_zone_node_t *) &node->color;
241 195
242 done: 196 node->key = hash;
197 lz->len = (u_char) len;
198 lz->conn = 1;
199 ngx_memcpy(lz->data, vv->data, len);
200
201 ngx_rbtree_insert(ctx->rbtree, node);
202
203 } else {
204
205 lz = (ngx_http_limit_zone_node_t *) &node->color;
206
207 if ((ngx_uint_t) lz->conn >= lzcf->conn) {
208
209 ngx_shmtx_unlock(&shpool->mutex);
210
211 ngx_log_error(lzcf->log_level, r->connection->log, 0,
212 "limiting connections by zone \"%V\"",
213 &lzcf->shm_zone->shm.name);
214
215 return NGX_HTTP_SERVICE_UNAVAILABLE;
216 }
217
218 lz->conn++;
219 }
243 220
244 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 221 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
245 "limit zone: %08XD %d", node->key, lz->conn); 222 "limit zone: %08XD %d", node->key, lz->conn);
246 223
247 ngx_shmtx_unlock(&shpool->mutex); 224 ngx_shmtx_unlock(&shpool->mutex);
292 *p = node; 269 *p = node;
293 node->parent = temp; 270 node->parent = temp;
294 node->left = sentinel; 271 node->left = sentinel;
295 node->right = sentinel; 272 node->right = sentinel;
296 ngx_rbt_red(node); 273 ngx_rbt_red(node);
274 }
275
276
277 static ngx_rbtree_node_t *
278 ngx_http_limit_zone_lookup(ngx_rbtree_t *rbtree, ngx_http_variable_value_t *vv,
279 uint32_t hash)
280 {
281 ngx_int_t rc;
282 ngx_rbtree_node_t *node, *sentinel;
283 ngx_http_limit_zone_node_t *lzn;
284
285 node = rbtree->root;
286 sentinel = rbtree->sentinel;
287
288 while (node != sentinel) {
289
290 if (hash < node->key) {
291 node = node->left;
292 continue;
293 }
294
295 if (hash > node->key) {
296 node = node->right;
297 continue;
298 }
299
300 /* hash == node->key */
301
302 do {
303 lzn = (ngx_http_limit_zone_node_t *) &node->color;
304
305 rc = ngx_memn2cmp(vv->data, lzn->data,
306 (size_t) vv->len, (size_t) lzn->len);
307 if (rc == 0) {
308 return node;
309 }
310
311 node = (rc < 0) ? node->left : node->right;
312
313 } while (node != sentinel && hash == node->key);
314
315 break;
316 }
317
318 return NULL;
297 } 319 }
298 320
299 321
300 static void 322 static void
301 ngx_http_limit_zone_cleanup(void *data) 323 ngx_http_limit_zone_cleanup(void *data)