Mercurial > hg > nginx
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) |