Mercurial > hg > nginx
comparison src/http/modules/ngx_http_limit_req_module.c @ 2720:b3b8c66bd520
support attaching to an existent Win32 shared memory
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 18 Apr 2009 19:27:28 +0000 |
parents | d5896f6608e8 |
children | c7d57b539248 |
comparison
equal
deleted
inserted
replaced
2719:9237cf8b400b | 2720:b3b8c66bd520 |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 | 10 |
11 | 11 |
12 typedef struct { | 12 typedef struct { |
13 u_char color; | 13 u_char color; |
14 u_char dummy; | 14 u_char dummy; |
15 u_short len; | 15 u_short len; |
16 ngx_queue_t queue; | 16 ngx_queue_t queue; |
17 ngx_msec_t last; | 17 ngx_msec_t last; |
18 ngx_uint_t excess; /* integer value, 1 corresponds to 0.001 r/s */ | 18 /* integer value, 1 corresponds to 0.001 r/s */ |
19 u_char data[1]; | 19 ngx_uint_t excess; |
20 u_char data[1]; | |
20 } ngx_http_limit_req_node_t; | 21 } ngx_http_limit_req_node_t; |
21 | 22 |
22 | 23 |
23 typedef struct { | 24 typedef struct { |
24 ngx_rbtree_t *rbtree; | 25 ngx_rbtree_t rbtree; |
25 ngx_queue_t *queue; | 26 ngx_rbtree_node_t sentinel; |
26 ngx_slab_pool_t *shpool; | 27 ngx_queue_t queue; |
27 ngx_uint_t rate; /* integer value, 1 corresponds to 0.001 r/s */ | 28 } ngx_http_limit_req_shctx_t; |
28 ngx_int_t index; | 29 |
29 ngx_str_t var; | 30 |
31 typedef struct { | |
32 ngx_http_limit_req_shctx_t *sh; | |
33 ngx_slab_pool_t *shpool; | |
34 /* integer value, 1 corresponds to 0.001 r/s */ | |
35 ngx_uint_t rate; | |
36 ngx_int_t index; | |
37 ngx_str_t var; | |
30 } ngx_http_limit_req_ctx_t; | 38 } ngx_http_limit_req_ctx_t; |
31 | 39 |
32 | 40 |
33 typedef struct { | 41 typedef struct { |
34 ngx_shm_zone_t *shm_zone; | 42 ngx_shm_zone_t *shm_zone; |
35 ngx_uint_t burst; /* integer value, 1 corresponds to 0.001 r/s */ | 43 /* integer value, 1 corresponds to 0.001 r/s */ |
36 ngx_uint_t nodelay;/* unsigned nodelay:1 */ | 44 ngx_uint_t burst; |
45 ngx_uint_t nodelay;/* unsigned nodelay:1 */ | |
37 } ngx_http_limit_req_conf_t; | 46 } ngx_http_limit_req_conf_t; |
38 | 47 |
39 | 48 |
40 static void ngx_http_limit_req_delay(ngx_http_request_t *r); | 49 static void ngx_http_limit_req_delay(ngx_http_request_t *r); |
41 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, | 50 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, |
161 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr); | 170 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr); |
162 | 171 |
163 if (lr) { | 172 if (lr) { |
164 ngx_queue_remove(&lr->queue); | 173 ngx_queue_remove(&lr->queue); |
165 | 174 |
166 ngx_queue_insert_head(ctx->queue, &lr->queue); | 175 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
167 | 176 |
168 excess = lr->excess; | 177 excess = lr->excess; |
169 | 178 |
170 } else { | 179 } else { |
171 excess = 0; | 180 excess = 0; |
237 lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); | 246 lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); |
238 | 247 |
239 lr->excess = 0; | 248 lr->excess = 0; |
240 ngx_memcpy(lr->data, vv->data, len); | 249 ngx_memcpy(lr->data, vv->data, len); |
241 | 250 |
242 ngx_rbtree_insert(ctx->rbtree, node); | 251 ngx_rbtree_insert(&ctx->sh->rbtree, node); |
243 | 252 |
244 ngx_queue_insert_head(ctx->queue, &lr->queue); | 253 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); |
245 | 254 |
246 done: | 255 done: |
247 | 256 |
248 ngx_shmtx_unlock(&ctx->shpool->mutex); | 257 ngx_shmtx_unlock(&ctx->shpool->mutex); |
249 | 258 |
322 ngx_http_limit_req_ctx_t *ctx; | 331 ngx_http_limit_req_ctx_t *ctx; |
323 ngx_http_limit_req_node_t *lr; | 332 ngx_http_limit_req_node_t *lr; |
324 | 333 |
325 ctx = lrcf->shm_zone->data; | 334 ctx = lrcf->shm_zone->data; |
326 | 335 |
327 node = ctx->rbtree->root; | 336 node = ctx->sh->rbtree.root; |
328 sentinel = ctx->rbtree->sentinel; | 337 sentinel = ctx->sh->rbtree.sentinel; |
329 | 338 |
330 while (node != sentinel) { | 339 while (node != sentinel) { |
331 | 340 |
332 if (hash < node->key) { | 341 if (hash < node->key) { |
333 node = node->left; | 342 node = node->left; |
409 * and one or two zero rate entries | 418 * and one or two zero rate entries |
410 */ | 419 */ |
411 | 420 |
412 while (n < 3) { | 421 while (n < 3) { |
413 | 422 |
414 if (ngx_queue_empty(ctx->queue)) { | 423 if (ngx_queue_empty(&ctx->sh->queue)) { |
415 return; | 424 return; |
416 } | 425 } |
417 | 426 |
418 q = ngx_queue_last(ctx->queue); | 427 q = ngx_queue_last(&ctx->sh->queue); |
419 | 428 |
420 lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); | 429 lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue); |
421 | 430 |
422 if (n++ != 0) { | 431 if (n++ != 0) { |
423 | 432 |
438 ngx_queue_remove(q); | 447 ngx_queue_remove(q); |
439 | 448 |
440 node = (ngx_rbtree_node_t *) | 449 node = (ngx_rbtree_node_t *) |
441 ((u_char *) lr - offsetof(ngx_rbtree_node_t, color)); | 450 ((u_char *) lr - offsetof(ngx_rbtree_node_t, color)); |
442 | 451 |
443 ngx_rbtree_delete(ctx->rbtree, node); | 452 ngx_rbtree_delete(&ctx->sh->rbtree, node); |
444 | 453 |
445 ngx_slab_free_locked(ctx->shpool, node); | 454 ngx_slab_free_locked(ctx->shpool, node); |
446 } | 455 } |
447 } | 456 } |
448 | 457 |
451 ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data) | 460 ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data) |
452 { | 461 { |
453 ngx_http_limit_req_ctx_t *octx = data; | 462 ngx_http_limit_req_ctx_t *octx = data; |
454 | 463 |
455 size_t len; | 464 size_t len; |
456 ngx_rbtree_node_t *sentinel; | |
457 ngx_http_limit_req_ctx_t *ctx; | 465 ngx_http_limit_req_ctx_t *ctx; |
458 | 466 |
459 ctx = shm_zone->data; | 467 ctx = shm_zone->data; |
460 | 468 |
461 if (octx) { | 469 if (octx) { |
465 "while previously it used the \"%V\" variable", | 473 "while previously it used the \"%V\" variable", |
466 &shm_zone->shm.name, &ctx->var, &octx->var); | 474 &shm_zone->shm.name, &ctx->var, &octx->var); |
467 return NGX_ERROR; | 475 return NGX_ERROR; |
468 } | 476 } |
469 | 477 |
470 ctx->rbtree = octx->rbtree; | 478 ctx->sh = octx->sh; |
471 ctx->queue = octx->queue; | |
472 ctx->shpool = octx->shpool; | 479 ctx->shpool = octx->shpool; |
473 | 480 |
474 return NGX_OK; | 481 return NGX_OK; |
475 } | 482 } |
476 | 483 |
477 ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; | 484 ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; |
478 | 485 |
479 ctx->rbtree = ngx_slab_alloc(ctx->shpool, sizeof(ngx_rbtree_t)); | 486 if (shm_zone->shm.exists) { |
480 if (ctx->rbtree == NULL) { | 487 ctx->sh = ctx->shpool->data; |
488 | |
489 return NGX_OK; | |
490 } | |
491 | |
492 ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_req_shctx_t)); | |
493 if (ctx->sh == NULL) { | |
481 return NGX_ERROR; | 494 return NGX_ERROR; |
482 } | 495 } |
483 | 496 |
484 sentinel = ngx_slab_alloc(ctx->shpool, sizeof(ngx_rbtree_node_t)); | 497 ctx->shpool->data = ctx->sh; |
485 if (sentinel == NULL) { | 498 |
486 return NGX_ERROR; | 499 ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel, |
487 } | |
488 | |
489 ngx_rbtree_init(ctx->rbtree, sentinel, | |
490 ngx_http_limit_req_rbtree_insert_value); | 500 ngx_http_limit_req_rbtree_insert_value); |
491 | 501 |
492 ctx->queue = ngx_slab_alloc(ctx->shpool, sizeof(ngx_queue_t)); | 502 ngx_queue_init(&ctx->sh->queue); |
493 if (ctx->queue == NULL) { | |
494 return NGX_ERROR; | |
495 } | |
496 | |
497 ngx_queue_init(ctx->queue); | |
498 | 503 |
499 len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len; | 504 len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len; |
500 | 505 |
501 ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len); | 506 ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len); |
502 if (ctx->shpool->log_ctx == NULL) { | 507 if (ctx->shpool->log_ctx == NULL) { |