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,