comparison src/http/modules/ngx_http_limit_zone_module.c @ 987:14e68f471d02

new syntax
author Igor Sysoev <igor@sysoev.ru>
date Sun, 07 Jan 2007 18:52:34 +0000
parents dd128232e6ba
children 1b9a4d92173f
comparison
equal deleted inserted replaced
986:68c85f283043 987:14e68f471d02
22 ngx_rbtree_node_t *node; 22 ngx_rbtree_node_t *node;
23 } ngx_http_limit_zone_cleanup_t; 23 } ngx_http_limit_zone_cleanup_t;
24 24
25 25
26 typedef struct { 26 typedef struct {
27 ngx_rbtree_t *rbtree;
28 ngx_int_t index;
29 ngx_str_t var;
30 } ngx_http_limit_zone_ctx_t;
31
32
33 typedef struct {
27 ngx_shm_zone_t *shm_zone; 34 ngx_shm_zone_t *shm_zone;
28 ngx_int_t index;
29 ngx_uint_t conn; 35 ngx_uint_t conn;
30 } ngx_http_limit_zone_conf_t; 36 } ngx_http_limit_zone_conf_t;
31 37
32 38
33 static void ngx_http_limit_zone_cleanup(void *data); 39 static void ngx_http_limit_zone_cleanup(void *data);
43 49
44 50
45 static ngx_command_t ngx_http_limit_zone_commands[] = { 51 static ngx_command_t ngx_http_limit_zone_commands[] = {
46 52
47 { ngx_string("limit_zone"), 53 { ngx_string("limit_zone"),
48 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, 54 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3,
49 ngx_http_limit_zone, 55 ngx_http_limit_zone,
50 0, 56 0,
51 0, 57 0,
52 NULL }, 58 NULL },
53 59
54 { ngx_string("limit_conn"), 60 { ngx_string("limit_conn"),
55 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3, 61 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
56 ngx_http_limit_conn, 62 ngx_http_limit_conn,
57 NGX_HTTP_LOC_CONF_OFFSET, 63 NGX_HTTP_LOC_CONF_OFFSET,
58 0, 64 0,
59 NULL }, 65 NULL },
60 66
96 static ngx_int_t 102 static ngx_int_t
97 ngx_http_limit_zone_handler(ngx_http_request_t *r) 103 ngx_http_limit_zone_handler(ngx_http_request_t *r)
98 { 104 {
99 size_t len, n; 105 size_t len, n;
100 uint32_t hash; 106 uint32_t hash;
101 ngx_rbtree_t *rbtree;
102 ngx_slab_pool_t *shpool; 107 ngx_slab_pool_t *shpool;
103 ngx_rbtree_node_t *node, *sentinel; 108 ngx_rbtree_node_t *node, *sentinel;
104 ngx_pool_cleanup_t *cln; 109 ngx_pool_cleanup_t *cln;
105 ngx_http_variable_value_t *vv; 110 ngx_http_variable_value_t *vv;
111 ngx_http_limit_zone_ctx_t *ctx;
106 ngx_http_limit_zone_node_t *lz; 112 ngx_http_limit_zone_node_t *lz;
107 ngx_http_limit_zone_conf_t *lzcf; 113 ngx_http_limit_zone_conf_t *lzcf;
108 ngx_http_limit_zone_cleanup_t *lzcln; 114 ngx_http_limit_zone_cleanup_t *lzcln;
109 115
110 if (r->limit_zone_set) { 116 if (r->limit_zone_set) {
115 121
116 if (lzcf->shm_zone == NULL) { 122 if (lzcf->shm_zone == NULL) {
117 return NGX_DECLINED; 123 return NGX_DECLINED;
118 } 124 }
119 125
120 vv = ngx_http_get_indexed_variable(r, lzcf->index); 126 ctx = lzcf->shm_zone->data;
127
128 vv = ngx_http_get_indexed_variable(r, ctx->index);
121 129
122 if (vv == NULL || vv->not_found) { 130 if (vv == NULL || vv->not_found) {
123 return NGX_DECLINED; 131 return NGX_DECLINED;
124 } 132 }
125 133
132 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_limit_zone_cleanup_t)); 140 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_limit_zone_cleanup_t));
133 if (cln == NULL) { 141 if (cln == NULL) {
134 return NGX_HTTP_INTERNAL_SERVER_ERROR; 142 return NGX_HTTP_INTERNAL_SERVER_ERROR;
135 } 143 }
136 144
137 rbtree = lzcf->shm_zone->data;
138 shpool = (ngx_slab_pool_t *) lzcf->shm_zone->shm.addr; 145 shpool = (ngx_slab_pool_t *) lzcf->shm_zone->shm.addr;
139 146
140 ngx_shmtx_lock(&shpool->mutex); 147 ngx_shmtx_lock(&shpool->mutex);
141 148
142 node = rbtree->root; 149 node = ctx->rbtree->root;
143 sentinel = rbtree->sentinel; 150 sentinel = ctx->rbtree->sentinel;
144 151
145 while (node != sentinel) { 152 while (node != sentinel) {
146 153
147 if (hash < node->key) { 154 if (hash < node->key) {
148 node = node->left; 155 node = node->left;
187 node->key = hash; 194 node->key = hash;
188 lz->len = (u_char) len; 195 lz->len = (u_char) len;
189 lz->conn = 1; 196 lz->conn = 1;
190 ngx_memcpy(lz->data, vv->data, len); 197 ngx_memcpy(lz->data, vv->data, len);
191 198
192 ngx_rbtree_insert(rbtree, node); 199 ngx_rbtree_insert(ctx->rbtree, node);
193 200
194 done: 201 done:
195 202
196 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 203 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
197 "limit zone: %08XD %d", node->key, lz->conn); 204 "limit zone: %08XD %d", node->key, lz->conn);
211 static void 218 static void
212 ngx_http_limit_zone_cleanup(void *data) 219 ngx_http_limit_zone_cleanup(void *data)
213 { 220 {
214 ngx_http_limit_zone_cleanup_t *lzcln = data; 221 ngx_http_limit_zone_cleanup_t *lzcln = data;
215 222
216 ngx_rbtree_t *rbtree;
217 ngx_slab_pool_t *shpool; 223 ngx_slab_pool_t *shpool;
218 ngx_rbtree_node_t *node; 224 ngx_rbtree_node_t *node;
225 ngx_http_limit_zone_ctx_t *ctx;
219 ngx_http_limit_zone_node_t *lz; 226 ngx_http_limit_zone_node_t *lz;
220 227
221 rbtree = lzcln->shm_zone->data; 228 ctx = lzcln->shm_zone->data;
222 shpool = (ngx_slab_pool_t *) lzcln->shm_zone->shm.addr; 229 shpool = (ngx_slab_pool_t *) lzcln->shm_zone->shm.addr;
223 node = lzcln->node; 230 node = lzcln->node;
224 lz = (ngx_http_limit_zone_node_t *) &node->color; 231 lz = (ngx_http_limit_zone_node_t *) &node->color;
225 232
226 ngx_shmtx_lock(&shpool->mutex); 233 ngx_shmtx_lock(&shpool->mutex);
229 "limit zone cleanup: %08XD %d", node->key, lz->conn); 236 "limit zone cleanup: %08XD %d", node->key, lz->conn);
230 237
231 lz->conn--; 238 lz->conn--;
232 239
233 if (lz->conn == 0) { 240 if (lz->conn == 0) {
234 ngx_rbtree_delete(rbtree, node); 241 ngx_rbtree_delete(ctx->rbtree, node);
235 ngx_slab_free_locked(shpool, node); 242 ngx_slab_free_locked(shpool, node);
236 } 243 }
237 244
238 ngx_shmtx_unlock(&shpool->mutex); 245 ngx_shmtx_unlock(&shpool->mutex);
239 } 246 }
240 247
241 248
242 static ngx_int_t 249 static ngx_int_t
243 ngx_http_limit_zone_init_zone(ngx_shm_zone_t *shm_zone) 250 ngx_http_limit_zone_init_zone(ngx_shm_zone_t *shm_zone)
244 { 251 {
245 ngx_rbtree_t *rbtree; 252 ngx_slab_pool_t *shpool;
246 ngx_slab_pool_t *shpool; 253 ngx_rbtree_node_t *sentinel;
247 ngx_rbtree_node_t *sentinel; 254 ngx_http_limit_zone_ctx_t *ctx;
248 255
249 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 256 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
250 257 ctx = shm_zone->data;
251 rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t)); 258
252 if (rbtree == NULL) { 259 ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
260 if (ctx->rbtree == NULL) {
253 return NGX_ERROR; 261 return NGX_ERROR;
254 } 262 }
255 263
256 sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t)); 264 sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
257 if (sentinel == NULL) { 265 if (sentinel == NULL) {
258 return NGX_ERROR; 266 return NGX_ERROR;
259 } 267 }
260 268
261 ngx_rbtree_sentinel_init(sentinel); 269 ngx_rbtree_sentinel_init(sentinel);
262 270
263 rbtree->root = sentinel; 271 ctx->rbtree->root = sentinel;
264 rbtree->sentinel = sentinel; 272 ctx->rbtree->sentinel = sentinel;
265 rbtree->insert = ngx_rbtree_insert_value; 273 ctx->rbtree->insert = ngx_rbtree_insert_value;
266
267 shm_zone->data = rbtree;
268 274
269 return NGX_OK; 275 return NGX_OK;
270 } 276 }
271 277
272 278
282 288
283 /* 289 /*
284 * set by ngx_pcalloc(): 290 * set by ngx_pcalloc():
285 * 291 *
286 * conf->shm_zone = NULL; 292 * conf->shm_zone = NULL;
287 * conf->index = 0;
288 * conf->conn = 0; 293 * conf->conn = 0;
289 */ 294 */
290 295
291 return conf; 296 return conf;
292 } 297 }
307 312
308 313
309 static char * 314 static char *
310 ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 315 ngx_http_limit_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
311 { 316 {
312 ssize_t n; 317 ssize_t n;
313 ngx_str_t *value; 318 ngx_str_t *value;
314 ngx_shm_zone_t *shm_zone; 319 ngx_shm_zone_t *shm_zone;
320 ngx_http_limit_zone_ctx_t *ctx;
315 321
316 value = cf->args->elts; 322 value = cf->args->elts;
317 323
318 n = ngx_parse_size(&value[2]); 324 if (value[2].data[0] != '$') {
325 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
326 "invalid variable name \"%V\"", &value[2]);
327 return NGX_CONF_ERROR;
328 }
329
330 value[2].len--;
331 value[2].data++;
332
333 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_zone_ctx_t));
334 if (ctx == NULL) {
335 return NGX_CONF_ERROR;
336 }
337
338 ctx->index = ngx_http_get_variable_index(cf, &value[2]);
339 if (ctx->index == NGX_ERROR) {
340 return NGX_CONF_ERROR;
341 }
342
343 ctx->var = value[2];
344
345 n = ngx_parse_size(&value[3]);
319 346
320 if (n == NGX_ERROR) { 347 if (n == NGX_ERROR) {
321 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 348 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
322 "invalid size of limit_zone \"%V\"", &value[2]); 349 "invalid size of limit_zone \"%V\"", &value[3]);
323 return NGX_CONF_ERROR; 350 return NGX_CONF_ERROR;
324 } 351 }
325 352
326 if (n < (ngx_int_t) (8 * ngx_pagesize)) { 353 if (n < (ngx_int_t) (8 * ngx_pagesize)) {
327 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 354 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
334 &ngx_http_limit_zone_module); 361 &ngx_http_limit_zone_module);
335 if (shm_zone == NULL) { 362 if (shm_zone == NULL) {
336 return NGX_CONF_ERROR; 363 return NGX_CONF_ERROR;
337 } 364 }
338 365
366 if (shm_zone->data) {
367 ctx = shm_zone->data;
368
369 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
370 "limit_zone \"%V\" is already bound to variable \"%V\"",
371 &value[1], &ctx->var);
372 return NGX_CONF_ERROR;
373 }
374
339 shm_zone->init = ngx_http_limit_zone_init_zone; 375 shm_zone->init = ngx_http_limit_zone_init_zone;
376 shm_zone->data = ctx;
340 377
341 return NGX_CONF_OK; 378 return NGX_CONF_OK;
342 } 379 }
343 380
344 381
350 ngx_int_t n; 387 ngx_int_t n;
351 ngx_str_t *value; 388 ngx_str_t *value;
352 389
353 value = cf->args->elts; 390 value = cf->args->elts;
354 391
355 n = ngx_atoi(value[1].data, value[1].len); 392 lzcf->shm_zone = ngx_shared_memory_add(cf, &value[1], 0,
393 &ngx_http_limit_zone_module);
394 if (lzcf->shm_zone == NULL) {
395 return NGX_CONF_ERROR;
396 }
397
398 n = ngx_atoi(value[2].data, value[2].len);
356 if (n <= 0) { 399 if (n <= 0) {
357 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 400 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
358 "invalid number of connections"); 401 "invalid number of connections \"%V\"", &value[2]);
359 return NGX_CONF_ERROR;
360 }
361
362 if (value[2].data[0] != '$') {
363 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
364 "invalid variable name \"%V\"", &value[2]);
365 return NGX_CONF_ERROR;
366 }
367
368 value[2].len--;
369 value[2].data++;
370
371 lzcf->index = ngx_http_get_variable_index(cf, &value[2]);
372 if (lzcf->index == NGX_ERROR) {
373 return NGX_CONF_ERROR;
374 }
375
376 lzcf->shm_zone = ngx_shared_memory_add(cf, &value[3], 0,
377 &ngx_http_limit_zone_module);
378 if (lzcf->shm_zone == NULL) {
379 return NGX_CONF_ERROR; 402 return NGX_CONF_ERROR;
380 } 403 }
381 404
382 lzcf->conn = n; 405 lzcf->conn = n;
383 406