comparison src/http/modules/ngx_http_limit_zone_module.c @ 1026:38be15c1379a

fix duplicate rbtree keys case
author Igor Sysoev <igor@sysoev.ru>
date Fri, 12 Jan 2007 20:38:17 +0000
parents 11ffb8e4753f
children ce08bc4cb97b
comparison
equal deleted inserted replaced
1025:f88651afad40 1026:38be15c1379a
102 static ngx_int_t 102 static ngx_int_t
103 ngx_http_limit_zone_handler(ngx_http_request_t *r) 103 ngx_http_limit_zone_handler(ngx_http_request_t *r)
104 { 104 {
105 size_t len, n; 105 size_t len, n;
106 uint32_t hash; 106 uint32_t hash;
107 ngx_int_t rc;
107 ngx_slab_pool_t *shpool; 108 ngx_slab_pool_t *shpool;
108 ngx_rbtree_node_t *node, *sentinel; 109 ngx_rbtree_node_t *node, *sentinel;
109 ngx_pool_cleanup_t *cln; 110 ngx_pool_cleanup_t *cln;
110 ngx_http_variable_value_t *vv; 111 ngx_http_variable_value_t *vv;
111 ngx_http_limit_zone_ctx_t *ctx; 112 ngx_http_limit_zone_ctx_t *ctx;
176 /* hash == node->key */ 177 /* hash == node->key */
177 178
178 do { 179 do {
179 lz = (ngx_http_limit_zone_node_t *) &node->color; 180 lz = (ngx_http_limit_zone_node_t *) &node->color;
180 181
181 if (len == (size_t) lz->len 182 rc = ngx_strn2cmp(lz->data, vv->data, (size_t) lz->len, len);
182 && ngx_strncmp(lz->data, vv->data, len) == 0) 183
183 { 184 if (rc == 0) {
184 if ((ngx_uint_t) lz->conn < lzcf->conn) { 185 if ((ngx_uint_t) lz->conn < lzcf->conn) {
185 lz->conn++; 186 lz->conn++;
186 goto done; 187 goto done;
187 } 188 }
188 189
189 ngx_shmtx_unlock(&shpool->mutex); 190 ngx_shmtx_unlock(&shpool->mutex);
190 191
191 return NGX_HTTP_SERVICE_UNAVAILABLE; 192 return NGX_HTTP_SERVICE_UNAVAILABLE;
192 } 193 }
193 194
194 node = node->right; 195 node = (rc < 0) ? node->left : node->right;
195 196
196 } while (node != sentinel && hash == node->key); 197 } while (node != sentinel && hash == node->key);
197 198
198 break; 199 break;
199 } 200 }
229 230
230 lzcln->shm_zone = lzcf->shm_zone; 231 lzcln->shm_zone = lzcf->shm_zone;
231 lzcln->node = node; 232 lzcln->node = node;
232 233
233 return NGX_DECLINED; 234 return NGX_DECLINED;
235 }
236
237
238 static void
239 ngx_http_limit_zone_rbtree_insert_value(ngx_rbtree_node_t *temp,
240 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
241 {
242 ngx_http_limit_zone_node_t *lzn, *lznt;
243
244 for ( ;; ) {
245
246 if (node->key < temp->key) {
247
248 if (temp->left == sentinel) {
249 temp->left = node;
250 break;
251 }
252
253 temp = temp->left;
254
255 } else if (node->key > temp->key) {
256
257 if (temp->right == sentinel) {
258 temp->right = node;
259 break;
260 }
261
262 temp = temp->right;
263
264 } else { /* node->key == temp->key */
265
266 lzn = (ngx_http_limit_zone_node_t *) &node->color;
267 lznt = (ngx_http_limit_zone_node_t *) &temp->color;
268
269 if (ngx_strn2cmp(lzn->data, lznt->data, lzn->len, lznt->len) < 0) {
270
271 if (temp->left == sentinel) {
272 temp->left = node;
273 break;
274 }
275
276 temp = temp->left;
277
278 } else {
279
280 if (temp->right == sentinel) {
281 temp->right = node;
282 break;
283 }
284
285 temp = temp->right;
286 }
287 }
288 }
289
290 node->parent = temp;
291 node->left = sentinel;
292 node->right = sentinel;
293 ngx_rbt_red(node);
234 } 294 }
235 295
236 296
237 static void 297 static void
238 ngx_http_limit_zone_cleanup(void *data) 298 ngx_http_limit_zone_cleanup(void *data)
304 364
305 ngx_rbtree_sentinel_init(sentinel); 365 ngx_rbtree_sentinel_init(sentinel);
306 366
307 ctx->rbtree->root = sentinel; 367 ctx->rbtree->root = sentinel;
308 ctx->rbtree->sentinel = sentinel; 368 ctx->rbtree->sentinel = sentinel;
309 ctx->rbtree->insert = ngx_rbtree_insert_value; 369 ctx->rbtree->insert = ngx_http_limit_zone_rbtree_insert_value;
310 370
311 return NGX_OK; 371 return NGX_OK;
312 } 372 }
313 373
314 374