Mercurial > hg > nginx
comparison src/http/modules/ngx_http_limit_req_module.c @ 4418:aac79fc948cc
Limit req: allocation and initialization of a new node moved to the lookup
function.
No functional changes.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Mon, 30 Jan 2012 09:41:49 +0000 |
parents | 9e9d2e06f933 |
children | 7084faa7a4b4 |
comparison
equal
deleted
inserted
replaced
4417:9e9d2e06f933 | 4418:aac79fc948cc |
---|---|
134 | 134 |
135 | 135 |
136 static ngx_int_t | 136 static ngx_int_t |
137 ngx_http_limit_req_handler(ngx_http_request_t *r) | 137 ngx_http_limit_req_handler(ngx_http_request_t *r) |
138 { | 138 { |
139 size_t len, n; | 139 size_t len; |
140 uint32_t hash; | 140 uint32_t hash; |
141 ngx_int_t rc; | 141 ngx_int_t rc; |
142 ngx_uint_t excess; | 142 ngx_uint_t excess; |
143 ngx_time_t *tp; | |
144 ngx_rbtree_node_t *node; | |
145 ngx_http_variable_value_t *vv; | 143 ngx_http_variable_value_t *vv; |
146 ngx_http_limit_req_ctx_t *ctx; | 144 ngx_http_limit_req_ctx_t *ctx; |
147 ngx_http_limit_req_node_t *lr; | |
148 ngx_http_limit_req_conf_t *lrcf; | 145 ngx_http_limit_req_conf_t *lrcf; |
149 | 146 |
150 if (r->main->limit_req_set) { | 147 if (r->main->limit_req_set) { |
151 return NGX_DECLINED; | 148 return NGX_DECLINED; |
152 } | 149 } |
187 | 184 |
188 ngx_http_limit_req_expire(ctx, 1); | 185 ngx_http_limit_req_expire(ctx, 1); |
189 | 186 |
190 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess); | 187 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess); |
191 | 188 |
189 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
190 | |
192 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 191 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
193 "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000); | 192 "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000); |
194 | 193 |
195 if (rc == NGX_DECLINED) { | |
196 | |
197 n = offsetof(ngx_rbtree_node_t, color) | |
198 + offsetof(ngx_http_limit_req_node_t, data) | |
199 + len; | |
200 | |
201 node = ngx_slab_alloc_locked(ctx->shpool, n); | |
202 if (node == NULL) { | |
203 | |
204 ngx_http_limit_req_expire(ctx, 0); | |
205 | |
206 node = ngx_slab_alloc_locked(ctx->shpool, n); | |
207 if (node == NULL) { | |
208 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
209 return NGX_HTTP_SERVICE_UNAVAILABLE; | |
210 } | |
211 } | |
212 | |
213 lr = (ngx_http_limit_req_node_t *) &node->color; | |
214 | |
215 node->key = hash; | |
216 lr->len = (u_char) len; | |
217 | |
218 tp = ngx_timeofday(); | |
219 lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
220 | |
221 lr->excess = 0; | |
222 ngx_memcpy(lr->data, vv->data, len); | |
223 | |
224 ngx_rbtree_insert(&ctx->sh->rbtree, node); | |
225 | |
226 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); | |
227 | |
228 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
229 | |
230 return NGX_DECLINED; | |
231 } | |
232 | |
233 ngx_shmtx_unlock(&ctx->shpool->mutex); | |
234 | |
235 if (rc == NGX_OK) { | 194 if (rc == NGX_OK) { |
236 return NGX_DECLINED; | 195 return NGX_DECLINED; |
237 } | 196 } |
238 | 197 |
239 if (rc == NGX_BUSY) { | 198 if (rc == NGX_BUSY || rc == NGX_ERROR) { |
240 ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, | 199 |
241 "limiting requests, excess: %ui.%03ui by zone \"%V\"", | 200 if (rc == NGX_BUSY) { |
242 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); | 201 ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, |
202 "limiting requests, excess: %ui.%03ui by zone \"%V\"", | |
203 excess / 1000, excess % 1000, | |
204 &lrcf->shm_zone->shm.name); | |
205 } | |
243 | 206 |
244 return NGX_HTTP_SERVICE_UNAVAILABLE; | 207 return NGX_HTTP_SERVICE_UNAVAILABLE; |
245 } | 208 } |
246 | 209 |
247 /* rc == NGX_AGAIN */ | 210 /* rc == NGX_AGAIN */ |
343 | 306 |
344 static ngx_int_t | 307 static ngx_int_t |
345 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, | 308 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, |
346 u_char *data, size_t len, ngx_uint_t *ep) | 309 u_char *data, size_t len, ngx_uint_t *ep) |
347 { | 310 { |
311 size_t size; | |
348 ngx_int_t rc, excess; | 312 ngx_int_t rc, excess; |
349 ngx_time_t *tp; | 313 ngx_time_t *tp; |
350 ngx_msec_t now; | 314 ngx_msec_t now; |
351 ngx_msec_int_t ms; | 315 ngx_msec_int_t ms; |
352 ngx_rbtree_node_t *node, *sentinel; | 316 ngx_rbtree_node_t *node, *sentinel; |
353 ngx_http_limit_req_ctx_t *ctx; | 317 ngx_http_limit_req_ctx_t *ctx; |
354 ngx_http_limit_req_node_t *lr; | 318 ngx_http_limit_req_node_t *lr; |
355 | 319 |
320 tp = ngx_timeofday(); | |
321 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
322 | |
356 ctx = lrcf->shm_zone->data; | 323 ctx = lrcf->shm_zone->data; |
357 | 324 |
358 node = ctx->sh->rbtree.root; | 325 node = ctx->sh->rbtree.root; |
359 sentinel = ctx->sh->rbtree.sentinel; | 326 sentinel = ctx->sh->rbtree.sentinel; |
360 | 327 |
379 | 346 |
380 if (rc == 0) { | 347 if (rc == 0) { |
381 ngx_queue_remove(&lr->queue); | 348 ngx_queue_remove(&lr->queue); |
382 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); | 349 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
383 | 350 |
384 tp = ngx_timeofday(); | |
385 | |
386 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | |
387 ms = (ngx_msec_int_t) (now - lr->last); | 351 ms = (ngx_msec_int_t) (now - lr->last); |
388 | 352 |
389 excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; | 353 excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; |
390 | 354 |
391 if (excess < 0) { | 355 if (excess < 0) { |
415 break; | 379 break; |
416 } | 380 } |
417 | 381 |
418 *ep = 0; | 382 *ep = 0; |
419 | 383 |
420 return NGX_DECLINED; | 384 size = offsetof(ngx_rbtree_node_t, color) |
385 + offsetof(ngx_http_limit_req_node_t, data) | |
386 + len; | |
387 | |
388 node = ngx_slab_alloc_locked(ctx->shpool, size); | |
389 | |
390 if (node == NULL) { | |
391 ngx_http_limit_req_expire(ctx, 0); | |
392 | |
393 node = ngx_slab_alloc_locked(ctx->shpool, size); | |
394 if (node == NULL) { | |
395 return NGX_ERROR; | |
396 } | |
397 } | |
398 | |
399 node->key = hash; | |
400 | |
401 ngx_rbtree_insert(&ctx->sh->rbtree, node); | |
402 | |
403 lr = (ngx_http_limit_req_node_t *) &node->color; | |
404 | |
405 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); | |
406 | |
407 lr->len = (u_char) len; | |
408 lr->excess = 0; | |
409 lr->last = now; | |
410 | |
411 ngx_memcpy(lr->data, data, len); | |
412 | |
413 return NGX_OK; | |
421 } | 414 } |
422 | 415 |
423 | 416 |
424 static void | 417 static void |
425 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) | 418 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) |