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) {