mirror of
https://github.com/nginx/nginx.git
synced 2024-12-15 21:39:00 +08:00
aa8286101a
*) Workaround: the default values of the devpoll_events and the devpoll_changes directives changed from 512 to 32 to be compatible with Solaris 10. *) Bugfix: the proxy_set_x_var and fastcgi_set_var directives were not inherited. *) Bugfix: in the redirect rewrite directive the arguments were concatenated with URI by the "&" rather than the "?". *) Bugfix: the lines without trailing ";" in the file being included by the ngx_http_geo_module were silently ignored. *) Feature: the ngx_http_stub_status_module. *) Bugfix: the unknown log format in the access_log directive caused the segmentation fault. *) Feature: the new "document_root" parameter of the fastcgi_params directive. *) Feature: the fastcgi_redirect_errors directive. *) Feature: the new "break" modifier of the "rewrite" directive allows to stop the rewrite/location cycle and sets the current configuration to the request.
249 lines
4.5 KiB
C
249 lines
4.5 KiB
C
|
|
/*
|
|
* Copyright (C) Igor Sysoev
|
|
*/
|
|
|
|
|
|
#include <ngx_config.h>
|
|
#include <ngx_core.h>
|
|
|
|
|
|
static void *ngx_radix_alloc(ngx_radix_tree_t *tree);
|
|
|
|
|
|
ngx_radix_tree_t *
|
|
ngx_radix_tree_create(ngx_pool_t *pool, ngx_uint_t preallocate)
|
|
{
|
|
uint32_t key, mask, inc;
|
|
ngx_radix_tree_t *tree;
|
|
|
|
if (!(tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t)))) {
|
|
return NULL;
|
|
}
|
|
|
|
tree->pool = pool;
|
|
tree->free = NULL;
|
|
tree->start = NULL;
|
|
tree->size = 0;
|
|
|
|
if (!(tree->root = ngx_radix_alloc(tree))) {
|
|
return NULL;
|
|
}
|
|
|
|
tree->root->right = NULL;
|
|
tree->root->left = NULL;
|
|
tree->root->parent = NULL;
|
|
tree->root->value = NGX_RADIX_NO_VALUE;
|
|
|
|
/*
|
|
* We preallocate the first nodes: 0, 1, 00, 01, 10, 11, 000, 001, etc.,
|
|
* to increase the TLB hits even if for the first lookup iterations.
|
|
* On the 32-bit platforms the 7 preallocated bits takes continuous 4K,
|
|
* 8 - 8K, 9 - 16K, etc.
|
|
*/
|
|
|
|
mask = 0;
|
|
inc = 0x80000000;
|
|
|
|
while (preallocate--) {
|
|
|
|
key = 0;
|
|
mask >>= 1;
|
|
mask |= 0x80000000;
|
|
|
|
do {
|
|
if (ngx_radix32tree_insert(tree, key, mask, NGX_RADIX_NO_VALUE)
|
|
!= NGX_OK)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
key += inc;
|
|
|
|
} while (key);
|
|
|
|
inc >>= 1;
|
|
}
|
|
|
|
return tree;
|
|
}
|
|
|
|
|
|
ngx_int_t
|
|
ngx_radix32tree_insert(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask,
|
|
uintptr_t value)
|
|
{
|
|
uint32_t bit;
|
|
ngx_radix_node_t *node, *next;
|
|
|
|
bit = 0x80000000;
|
|
|
|
node = tree->root;
|
|
next = tree->root;
|
|
|
|
while (bit & mask) {
|
|
if (key & bit) {
|
|
next = node->right;
|
|
|
|
} else {
|
|
next = node->left;
|
|
}
|
|
|
|
if (next == NULL) {
|
|
break;
|
|
}
|
|
|
|
bit >>= 1;
|
|
node = next;
|
|
}
|
|
|
|
if (next) {
|
|
if (node->value != NGX_RADIX_NO_VALUE) {
|
|
return NGX_BUSY;
|
|
}
|
|
|
|
node->value = value;
|
|
return NGX_OK;
|
|
}
|
|
|
|
while (bit & mask) {
|
|
if (!(next = ngx_radix_alloc(tree))) {
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
next->right = NULL;
|
|
next->left = NULL;
|
|
next->parent = node;
|
|
next->value = NGX_RADIX_NO_VALUE;
|
|
|
|
if (key & bit) {
|
|
node->right = next;
|
|
|
|
} else {
|
|
node->left = next;
|
|
}
|
|
|
|
bit >>= 1;
|
|
node = next;
|
|
}
|
|
|
|
node->value = value;
|
|
|
|
return NGX_OK;
|
|
}
|
|
|
|
|
|
ngx_int_t
|
|
ngx_radix32tree_delete(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask)
|
|
{
|
|
uint32_t bit;
|
|
ngx_radix_node_t *node;
|
|
|
|
bit = 0x80000000;
|
|
node = tree->root;
|
|
|
|
while (node && (bit & mask)) {
|
|
if (key & bit) {
|
|
node = node->right;
|
|
|
|
} else {
|
|
node = node->left;
|
|
}
|
|
|
|
bit >>= 1;
|
|
}
|
|
|
|
if (node == NULL) {
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
if (node->right || node->left) {
|
|
if (node->value != NGX_RADIX_NO_VALUE) {
|
|
node->value = NGX_RADIX_NO_VALUE;
|
|
return NGX_OK;
|
|
}
|
|
|
|
return NGX_ERROR;
|
|
}
|
|
|
|
for ( ;; ) {
|
|
if (node->parent->right == node) {
|
|
node->parent->right = NULL;
|
|
} else {
|
|
node->parent->left = NULL;
|
|
}
|
|
|
|
node->right = tree->free;
|
|
tree->free = node;
|
|
|
|
node = node->parent;
|
|
|
|
if (node->right
|
|
|| node->left
|
|
|| node->value != NGX_RADIX_NO_VALUE
|
|
|| node->parent == NULL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NGX_OK;
|
|
}
|
|
|
|
|
|
uintptr_t
|
|
ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
|
|
{
|
|
uint32_t bit;
|
|
uintptr_t value;
|
|
ngx_radix_node_t *node;
|
|
|
|
bit = 0x80000000;
|
|
value = NGX_RADIX_NO_VALUE;
|
|
node = tree->root;
|
|
|
|
while (node) {
|
|
if (node->value != NGX_RADIX_NO_VALUE) {
|
|
value = node->value;
|
|
}
|
|
|
|
if (key & bit) {
|
|
node = node->right;
|
|
|
|
} else {
|
|
node = node->left;
|
|
}
|
|
|
|
bit >>= 1;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
static void *
|
|
ngx_radix_alloc(ngx_radix_tree_t *tree)
|
|
{
|
|
char *p;
|
|
|
|
if (tree->free) {
|
|
p = (char *) tree->free;
|
|
tree->free = tree->free->right;
|
|
return p;
|
|
}
|
|
|
|
if (tree->size < sizeof(ngx_radix_node_t)) {
|
|
if (!(tree->start = ngx_palloc(tree->pool, ngx_pagesize))) {
|
|
return NULL;
|
|
}
|
|
|
|
tree->size = ngx_pagesize;
|
|
}
|
|
|
|
p = tree->start;
|
|
tree->start += sizeof(ngx_radix_node_t);
|
|
tree->size -= sizeof(ngx_radix_node_t);
|
|
|
|
return p;
|
|
}
|