comparison src/http/modules/ngx_http_limit_req_module.c @ 4418:aac79fc948cc

Limit req: allocation and initialization of a new node moved to the lookup function. No functional changes.
author Valentin Bartenev <vbart@nginx.com>
date Mon, 30 Jan 2012 09:41:49 +0000
parents 9e9d2e06f933
children 7084faa7a4b4
comparison
equal deleted inserted replaced
4417:9e9d2e06f933 4418:aac79fc948cc
134 134
135 135
136 static ngx_int_t 136 static ngx_int_t
137 ngx_http_limit_req_handler(ngx_http_request_t *r) 137 ngx_http_limit_req_handler(ngx_http_request_t *r)
138 { 138 {
139 size_t len, n; 139 size_t len;
140 uint32_t hash; 140 uint32_t hash;
141 ngx_int_t rc; 141 ngx_int_t rc;
142 ngx_uint_t excess; 142 ngx_uint_t excess;
143 ngx_time_t *tp;
144 ngx_rbtree_node_t *node;
145 ngx_http_variable_value_t *vv; 143 ngx_http_variable_value_t *vv;
146 ngx_http_limit_req_ctx_t *ctx; 144 ngx_http_limit_req_ctx_t *ctx;
147 ngx_http_limit_req_node_t *lr;
148 ngx_http_limit_req_conf_t *lrcf; 145 ngx_http_limit_req_conf_t *lrcf;
149 146
150 if (r->main->limit_req_set) { 147 if (r->main->limit_req_set) {
151 return NGX_DECLINED; 148 return NGX_DECLINED;
152 } 149 }
187 184
188 ngx_http_limit_req_expire(ctx, 1); 185 ngx_http_limit_req_expire(ctx, 1);
189 186
190 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess); 187 rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess);
191 188
189 ngx_shmtx_unlock(&ctx->shpool->mutex);
190
192 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 191 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
193 "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000); 192 "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000);
194 193
195 if (rc == NGX_DECLINED) {
196
197 n = offsetof(ngx_rbtree_node_t, color)
198 + offsetof(ngx_http_limit_req_node_t, data)
199 + len;
200
201 node = ngx_slab_alloc_locked(ctx->shpool, n);
202 if (node == NULL) {
203
204 ngx_http_limit_req_expire(ctx, 0);
205
206 node = ngx_slab_alloc_locked(ctx->shpool, n);
207 if (node == NULL) {
208 ngx_shmtx_unlock(&ctx->shpool->mutex);
209 return NGX_HTTP_SERVICE_UNAVAILABLE;
210 }
211 }
212
213 lr = (ngx_http_limit_req_node_t *) &node->color;
214
215 node->key = hash;
216 lr->len = (u_char) len;
217
218 tp = ngx_timeofday();
219 lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
220
221 lr->excess = 0;
222 ngx_memcpy(lr->data, vv->data, len);
223
224 ngx_rbtree_insert(&ctx->sh->rbtree, node);
225
226 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
227
228 ngx_shmtx_unlock(&ctx->shpool->mutex);
229
230 return NGX_DECLINED;
231 }
232
233 ngx_shmtx_unlock(&ctx->shpool->mutex);
234
235 if (rc == NGX_OK) { 194 if (rc == NGX_OK) {
236 return NGX_DECLINED; 195 return NGX_DECLINED;
237 } 196 }
238 197
239 if (rc == NGX_BUSY) { 198 if (rc == NGX_BUSY || rc == NGX_ERROR) {
240 ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, 199
241 "limiting requests, excess: %ui.%03ui by zone \"%V\"", 200 if (rc == NGX_BUSY) {
242 excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); 201 ngx_log_error(lrcf->limit_log_level, r->connection->log, 0,
202 "limiting requests, excess: %ui.%03ui by zone \"%V\"",
203 excess / 1000, excess % 1000,
204 &lrcf->shm_zone->shm.name);
205 }
243 206
244 return NGX_HTTP_SERVICE_UNAVAILABLE; 207 return NGX_HTTP_SERVICE_UNAVAILABLE;
245 } 208 }
246 209
247 /* rc == NGX_AGAIN */ 210 /* rc == NGX_AGAIN */
343 306
344 static ngx_int_t 307 static ngx_int_t
345 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, 308 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
346 u_char *data, size_t len, ngx_uint_t *ep) 309 u_char *data, size_t len, ngx_uint_t *ep)
347 { 310 {
311 size_t size;
348 ngx_int_t rc, excess; 312 ngx_int_t rc, excess;
349 ngx_time_t *tp; 313 ngx_time_t *tp;
350 ngx_msec_t now; 314 ngx_msec_t now;
351 ngx_msec_int_t ms; 315 ngx_msec_int_t ms;
352 ngx_rbtree_node_t *node, *sentinel; 316 ngx_rbtree_node_t *node, *sentinel;
353 ngx_http_limit_req_ctx_t *ctx; 317 ngx_http_limit_req_ctx_t *ctx;
354 ngx_http_limit_req_node_t *lr; 318 ngx_http_limit_req_node_t *lr;
355 319
320 tp = ngx_timeofday();
321 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
322
356 ctx = lrcf->shm_zone->data; 323 ctx = lrcf->shm_zone->data;
357 324
358 node = ctx->sh->rbtree.root; 325 node = ctx->sh->rbtree.root;
359 sentinel = ctx->sh->rbtree.sentinel; 326 sentinel = ctx->sh->rbtree.sentinel;
360 327
379 346
380 if (rc == 0) { 347 if (rc == 0) {
381 ngx_queue_remove(&lr->queue); 348 ngx_queue_remove(&lr->queue);
382 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); 349 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
383 350
384 tp = ngx_timeofday();
385
386 now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
387 ms = (ngx_msec_int_t) (now - lr->last); 351 ms = (ngx_msec_int_t) (now - lr->last);
388 352
389 excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000; 353 excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
390 354
391 if (excess < 0) { 355 if (excess < 0) {
415 break; 379 break;
416 } 380 }
417 381
418 *ep = 0; 382 *ep = 0;
419 383
420 return NGX_DECLINED; 384 size = offsetof(ngx_rbtree_node_t, color)
385 + offsetof(ngx_http_limit_req_node_t, data)
386 + len;
387
388 node = ngx_slab_alloc_locked(ctx->shpool, size);
389
390 if (node == NULL) {
391 ngx_http_limit_req_expire(ctx, 0);
392
393 node = ngx_slab_alloc_locked(ctx->shpool, size);
394 if (node == NULL) {
395 return NGX_ERROR;
396 }
397 }
398
399 node->key = hash;
400
401 ngx_rbtree_insert(&ctx->sh->rbtree, node);
402
403 lr = (ngx_http_limit_req_node_t *) &node->color;
404
405 ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
406
407 lr->len = (u_char) len;
408 lr->excess = 0;
409 lr->last = now;
410
411 ngx_memcpy(lr->data, data, len);
412
413 return NGX_OK;
421 } 414 }
422 415
423 416
424 static void 417 static void
425 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) 418 ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)