Mercurial > hg > nginx
comparison src/http/modules/ngx_http_limit_zone_module.c @ 4272:260d591cb6a3
Limit zone: added the "limit_conn_zone" directive.
It supersedes old "limit_zone" directive (deprecated accordingly) and uses
syntax consistent with the "limit_req_zone" directive.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Thu, 10 Nov 2011 16:25:08 +0000 |
parents | b86cceba426a |
children |
comparison
equal
deleted
inserted
replaced
4271:b86cceba426a | 4272:260d591cb6a3 |
---|---|
48 static ngx_inline void ngx_http_limit_zone_cleanup_all(ngx_pool_t *pool); | 48 static ngx_inline void ngx_http_limit_zone_cleanup_all(ngx_pool_t *pool); |
49 | 49 |
50 static void *ngx_http_limit_zone_create_conf(ngx_conf_t *cf); | 50 static void *ngx_http_limit_zone_create_conf(ngx_conf_t *cf); |
51 static char *ngx_http_limit_zone_merge_conf(ngx_conf_t *cf, void *parent, | 51 static char *ngx_http_limit_zone_merge_conf(ngx_conf_t *cf, void *parent, |
52 void *child); | 52 void *child); |
53 static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, | |
54 void *conf); | |
53 static char *ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd, | 55 static char *ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd, |
54 void *conf); | 56 void *conf); |
55 static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, | 57 static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, |
56 void *conf); | 58 void *conf); |
57 static ngx_int_t ngx_http_limit_zone_init(ngx_conf_t *cf); | 59 static ngx_int_t ngx_http_limit_zone_init(ngx_conf_t *cf); |
60 | |
61 | |
62 static ngx_conf_deprecated_t ngx_conf_deprecated_limit_zone = { | |
63 ngx_conf_deprecated, "limit_zone", "limit_conn_zone" | |
64 }; | |
58 | 65 |
59 | 66 |
60 static ngx_conf_enum_t ngx_http_limit_conn_log_levels[] = { | 67 static ngx_conf_enum_t ngx_http_limit_conn_log_levels[] = { |
61 { ngx_string("info"), NGX_LOG_INFO }, | 68 { ngx_string("info"), NGX_LOG_INFO }, |
62 { ngx_string("notice"), NGX_LOG_NOTICE }, | 69 { ngx_string("notice"), NGX_LOG_NOTICE }, |
65 { ngx_null_string, 0 } | 72 { ngx_null_string, 0 } |
66 }; | 73 }; |
67 | 74 |
68 | 75 |
69 static ngx_command_t ngx_http_limit_zone_commands[] = { | 76 static ngx_command_t ngx_http_limit_zone_commands[] = { |
77 | |
78 { ngx_string("limit_conn_zone"), | |
79 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, | |
80 ngx_http_limit_conn_zone, | |
81 0, | |
82 0, | |
83 NULL }, | |
70 | 84 |
71 { ngx_string("limit_zone"), | 85 { ngx_string("limit_zone"), |
72 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3, | 86 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3, |
73 ngx_http_limit_zone, | 87 ngx_http_limit_zone, |
74 0, | 88 0, |
390 ctx = shm_zone->data; | 404 ctx = shm_zone->data; |
391 | 405 |
392 if (octx) { | 406 if (octx) { |
393 if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { | 407 if (ngx_strcmp(ctx->var.data, octx->var.data) != 0) { |
394 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, | 408 ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0, |
395 "limit_zone \"%V\" uses the \"%V\" variable " | 409 "limit_conn_zone \"%V\" uses the \"%V\" variable " |
396 "while previously it used the \"%V\" variable", | 410 "while previously it used the \"%V\" variable", |
397 &shm_zone->shm.name, &ctx->var, &octx->var); | 411 &shm_zone->shm.name, &ctx->var, &octx->var); |
398 return NGX_ERROR; | 412 return NGX_ERROR; |
399 } | 413 } |
400 | 414 |
424 } | 438 } |
425 | 439 |
426 ngx_rbtree_init(ctx->rbtree, sentinel, | 440 ngx_rbtree_init(ctx->rbtree, sentinel, |
427 ngx_http_limit_zone_rbtree_insert_value); | 441 ngx_http_limit_zone_rbtree_insert_value); |
428 | 442 |
429 len = sizeof(" in limit_zone \"\"") + shm_zone->shm.name.len; | 443 len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len; |
430 | 444 |
431 shpool->log_ctx = ngx_slab_alloc(shpool, len); | 445 shpool->log_ctx = ngx_slab_alloc(shpool, len); |
432 if (shpool->log_ctx == NULL) { | 446 if (shpool->log_ctx == NULL) { |
433 return NGX_ERROR; | 447 return NGX_ERROR; |
434 } | 448 } |
435 | 449 |
436 ngx_sprintf(shpool->log_ctx, " in limit_zone \"%V\"%Z", | 450 ngx_sprintf(shpool->log_ctx, " in limit_conn_zone \"%V\"%Z", |
437 &shm_zone->shm.name); | 451 &shm_zone->shm.name); |
438 | 452 |
439 return NGX_OK; | 453 return NGX_OK; |
440 } | 454 } |
441 | 455 |
477 return NGX_CONF_OK; | 491 return NGX_CONF_OK; |
478 } | 492 } |
479 | 493 |
480 | 494 |
481 static char * | 495 static char * |
496 ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
497 { | |
498 u_char *p; | |
499 ssize_t size; | |
500 ngx_str_t *value, name, s; | |
501 ngx_uint_t i; | |
502 ngx_shm_zone_t *shm_zone; | |
503 ngx_http_limit_zone_ctx_t *ctx; | |
504 | |
505 value = cf->args->elts; | |
506 | |
507 ctx = NULL; | |
508 size = 0; | |
509 name.len = 0; | |
510 | |
511 for (i = 1; i < cf->args->nelts; i++) { | |
512 | |
513 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | |
514 | |
515 name.data = value[i].data + 5; | |
516 | |
517 p = (u_char *) ngx_strchr(name.data, ':'); | |
518 | |
519 if (p == NULL) { | |
520 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
521 "invalid zone size \"%V\"", &value[i]); | |
522 return NGX_CONF_ERROR; | |
523 } | |
524 | |
525 name.len = p - name.data; | |
526 | |
527 s.data = p + 1; | |
528 s.len = value[i].data + value[i].len - s.data; | |
529 | |
530 size = ngx_parse_size(&s); | |
531 | |
532 if (size == NGX_ERROR) { | |
533 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
534 "invalid zone size \"%V\"", &value[i]); | |
535 return NGX_CONF_ERROR; | |
536 } | |
537 | |
538 if (size < (ssize_t) (8 * ngx_pagesize)) { | |
539 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
540 "zone \"%V\" is too small", &value[i]); | |
541 return NGX_CONF_ERROR; | |
542 } | |
543 | |
544 continue; | |
545 } | |
546 | |
547 if (value[i].data[0] == '$') { | |
548 | |
549 value[i].len--; | |
550 value[i].data++; | |
551 | |
552 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_zone_ctx_t)); | |
553 if (ctx == NULL) { | |
554 return NGX_CONF_ERROR; | |
555 } | |
556 | |
557 ctx->index = ngx_http_get_variable_index(cf, &value[i]); | |
558 if (ctx->index == NGX_ERROR) { | |
559 return NGX_CONF_ERROR; | |
560 } | |
561 | |
562 ctx->var = value[i]; | |
563 | |
564 continue; | |
565 } | |
566 | |
567 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
568 "invalid parameter \"%V\"", &value[i]); | |
569 return NGX_CONF_ERROR; | |
570 } | |
571 | |
572 if (name.len == 0) { | |
573 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
574 "\"%V\" must have \"zone\" parameter", | |
575 &cmd->name); | |
576 return NGX_CONF_ERROR; | |
577 } | |
578 | |
579 if (ctx == NULL) { | |
580 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
581 "no variable is defined for %V \"%V\"", | |
582 &cmd->name, &name); | |
583 return NGX_CONF_ERROR; | |
584 } | |
585 | |
586 shm_zone = ngx_shared_memory_add(cf, &name, size, | |
587 &ngx_http_limit_zone_module); | |
588 if (shm_zone == NULL) { | |
589 return NGX_CONF_ERROR; | |
590 } | |
591 | |
592 if (shm_zone->data) { | |
593 ctx = shm_zone->data; | |
594 | |
595 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
596 "%V \"%V\" is already bound to variable \"%V\"", | |
597 &cmd->name, &name, &ctx->var); | |
598 return NGX_CONF_ERROR; | |
599 } | |
600 | |
601 shm_zone->init = ngx_http_limit_zone_init_zone; | |
602 shm_zone->data = ctx; | |
603 | |
604 return NGX_CONF_OK; | |
605 } | |
606 | |
607 | |
608 static char * | |
482 ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 609 ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
483 { | 610 { |
484 ssize_t n; | 611 ssize_t n; |
485 ngx_str_t *value; | 612 ngx_str_t *value; |
486 ngx_shm_zone_t *shm_zone; | 613 ngx_shm_zone_t *shm_zone; |
487 ngx_http_limit_zone_ctx_t *ctx; | 614 ngx_http_limit_zone_ctx_t *ctx; |
615 | |
616 ngx_conf_deprecated(cf, &ngx_conf_deprecated_limit_zone, NULL); | |
488 | 617 |
489 value = cf->args->elts; | 618 value = cf->args->elts; |
490 | 619 |
491 if (value[2].data[0] != '$') { | 620 if (value[2].data[0] != '$') { |
492 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 621 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |