Merge of r4498:

Fix of rbtree lookup on hash collisions.

Previous code incorrectly assumed that nodes with identical keys are linked
together.  This might not be true after tree rebalance.

Patch by Lanshun Zhou.
This commit is contained in:
Maxim Dounin 2012-03-05 13:17:56 +00:00
parent 0275596328
commit 02b4f0abed
6 changed files with 93 additions and 128 deletions

View File

@ -837,20 +837,15 @@ ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name,
/* hash == node->key */
do {
file = (ngx_cached_open_file_t *) node;
file = (ngx_cached_open_file_t *) node;
rc = ngx_strcmp(name->data, file->name);
rc = ngx_strcmp(name->data, file->name);
if (rc == 0) {
return file;
}
if (rc == 0) {
return file;
}
node = (rc < 0) ? node->left : node->right;
} while (node != sentinel && hash == node->key);
break;
node = (rc < 0) ? node->left : node->right;
}
return NULL;

View File

@ -1626,20 +1626,15 @@ ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
/* hash == node->key */
do {
rn = (ngx_resolver_node_t *) node;
rn = (ngx_resolver_node_t *) node;
rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
if (rc == 0) {
return rn;
}
if (rc == 0) {
return rn;
}
node = (rc < 0) ? node->left : node->right;
} while (node != sentinel && hash == node->key);
break;
node = (rc < 0) ? node->left : node->right;
}
/* not found */

View File

@ -1801,44 +1801,39 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len,
/* hash == node->key */
do {
sess_id = (ngx_ssl_sess_id_t *) node;
sess_id = (ngx_ssl_sess_id_t *) node;
rc = ngx_memn2cmp(id, sess_id->id,
(size_t) len, (size_t) node->data);
if (rc == 0) {
rc = ngx_memn2cmp(id, sess_id->id, (size_t) len, (size_t) node->data);
if (sess_id->expire > ngx_time()) {
ngx_memcpy(buf, sess_id->session, sess_id->len);
if (rc == 0) {
ngx_shmtx_unlock(&shpool->mutex);
if (sess_id->expire > ngx_time()) {
ngx_memcpy(buf, sess_id->session, sess_id->len);
p = buf;
sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
ngx_shmtx_unlock(&shpool->mutex);
return sess;
}
p = buf;
sess = d2i_SSL_SESSION(NULL, &p, sess_id->len);
ngx_queue_remove(&sess_id->queue);
ngx_rbtree_delete(&cache->session_rbtree, node);
ngx_slab_free_locked(shpool, sess_id->session);
#if (NGX_PTR_SIZE == 4)
ngx_slab_free_locked(shpool, sess_id->id);
#endif
ngx_slab_free_locked(shpool, sess_id);
sess = NULL;
goto done;
return sess;
}
node = (rc < 0) ? node->left : node->right;
ngx_queue_remove(&sess_id->queue);
} while (node != sentinel && hash == node->key);
ngx_rbtree_delete(&cache->session_rbtree, node);
break;
ngx_slab_free_locked(shpool, sess_id->session);
#if (NGX_PTR_SIZE == 4)
ngx_slab_free_locked(shpool, sess_id->id);
#endif
ngx_slab_free_locked(shpool, sess_id);
sess = NULL;
goto done;
}
node = (rc < 0) ? node->left : node->right;
}
done:
@ -1908,31 +1903,26 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess)
/* hash == node->key */
do {
sess_id = (ngx_ssl_sess_id_t *) node;
sess_id = (ngx_ssl_sess_id_t *) node;
rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
rc = ngx_memn2cmp(id, sess_id->id, len, (size_t) node->data);
if (rc == 0) {
if (rc == 0) {
ngx_queue_remove(&sess_id->queue);
ngx_queue_remove(&sess_id->queue);
ngx_rbtree_delete(&cache->session_rbtree, node);
ngx_rbtree_delete(&cache->session_rbtree, node);
ngx_slab_free_locked(shpool, sess_id->session);
ngx_slab_free_locked(shpool, sess_id->session);
#if (NGX_PTR_SIZE == 4)
ngx_slab_free_locked(shpool, sess_id->id);
ngx_slab_free_locked(shpool, sess_id->id);
#endif
ngx_slab_free_locked(shpool, sess_id);
ngx_slab_free_locked(shpool, sess_id);
goto done;
}
goto done;
}
node = (rc < 0) ? node->left : node->right;
} while (node != sentinel && hash == node->key);
break;
node = (rc < 0) ? node->left : node->right;
}
done:

View File

@ -372,47 +372,42 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
/* hash == node->key */
do {
lr = (ngx_http_limit_req_node_t *) &node->color;
lr = (ngx_http_limit_req_node_t *) &node->color;
rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len);
rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len);
if (rc == 0) {
ngx_queue_remove(&lr->queue);
ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
if (rc == 0) {
ngx_queue_remove(&lr->queue);
ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
tp = ngx_timeofday();
tp = ngx_timeofday();
now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
ms = (ngx_msec_int_t) (now - lr->last);
now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
ms = (ngx_msec_int_t) (now - lr->last);
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
if (excess < 0) {
excess = 0;
}
*ep = excess;
if ((ngx_uint_t) excess > lrcf->burst) {
return NGX_BUSY;
}
lr->excess = excess;
lr->last = now;
if (excess) {
return NGX_AGAIN;
}
return NGX_OK;
if (excess < 0) {
excess = 0;
}
node = (rc < 0) ? node->left : node->right;
*ep = excess;
} while (node != sentinel && hash == node->key);
if ((ngx_uint_t) excess > lrcf->burst) {
return NGX_BUSY;
}
break;
lr->excess = excess;
lr->last = now;
if (excess) {
return NGX_AGAIN;
}
return NGX_OK;
}
node = (rc < 0) ? node->left : node->right;
}
*ep = 0;

View File

@ -194,31 +194,26 @@ ngx_http_limit_zone_handler(ngx_http_request_t *r)
/* hash == node->key */
do {
lz = (ngx_http_limit_zone_node_t *) &node->color;
lz = (ngx_http_limit_zone_node_t *) &node->color;
rc = ngx_memn2cmp(vv->data, lz->data, len, (size_t) lz->len);
rc = ngx_memn2cmp(vv->data, lz->data, len, (size_t) lz->len);
if (rc == 0) {
if ((ngx_uint_t) lz->conn < lzcf->conn) {
lz->conn++;
goto done;
}
ngx_shmtx_unlock(&shpool->mutex);
ngx_log_error(lzcf->log_level, r->connection->log, 0,
"limiting connections by zone \"%V\"",
&lzcf->shm_zone->shm.name);
return NGX_HTTP_SERVICE_UNAVAILABLE;
if (rc == 0) {
if ((ngx_uint_t) lz->conn < lzcf->conn) {
lz->conn++;
goto done;
}
node = (rc < 0) ? node->left : node->right;
ngx_shmtx_unlock(&shpool->mutex);
} while (node != sentinel && hash == node->key);
ngx_log_error(lzcf->log_level, r->connection->log, 0,
"limiting connections by zone \"%V\"",
&lzcf->shm_zone->shm.name);
break;
return NGX_HTTP_SERVICE_UNAVAILABLE;
}
node = (rc < 0) ? node->left : node->right;
}
n = offsetof(ngx_rbtree_node_t, color)

View File

@ -673,21 +673,16 @@ ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key)
/* node_key == node->key */
do {
fcn = (ngx_http_file_cache_node_t *) node;
fcn = (ngx_http_file_cache_node_t *) node;
rc = ngx_memcmp(&key[sizeof(ngx_rbtree_key_t)], fcn->key,
NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
rc = ngx_memcmp(&key[sizeof(ngx_rbtree_key_t)], fcn->key,
NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
if (rc == 0) {
return fcn;
}
if (rc == 0) {
return fcn;
}
node = (rc < 0) ? node->left : node->right;
} while (node != sentinel && node_key == node->key);
break;
node = (rc < 0) ? node->left : node->right;
}
/* not found */