在前面两篇博文中分别介绍了nginx中普通hash表和带有通配符的hash表的建立和查找,今天主要是介绍建立hash表的前提条件,并在后面附上一个完整的hash表的实现(该部分代码为转载)。
一、建立hash表的前提条件
(1)为hash表提供数据的数据结构
ngx_hash_keys_arrays_t不负责构造hash表,但是它是使用ngx_hash_init和ngx_hash_wildcard_init的前提条件,也就是说,如果先构造好了ngx_hash_keys_arrays_t就可以简单地创造支持通配符的hash表了。
//哈希key数组
typedef struct
{
ngx_uint_t hsize;//hash表桶个数
ngx_pool_t *pool;//为nginx中永久存放的hash结构体分配空间的内存
ngx_pool_t *temp_pool;//分配临时数据空间的内存池
ngx_array_t keys;//保存不含通配符元素中间key的动态数组
ngx_array_t *keys_hash;//处理不含通配符元素的简易hash表(动态数组)
ngx_array_t dns_wc_head;//保存前置通配符元素中间key的动态数组
ngx_array_t *dns_wc_head_hash;//处理前置通配符元素的简易hash表(动态数组)
ngx_array_t dns_wc_tail;//保存后置通配符元素中间key的动态数组
ngx_array_t *dns_wc_tail_hash;//处理后置通配符元素的简易hash表(动态数组)
} ngx_hash_keys_arrays_t;
//哈希key数组初始化
ngx_int_t ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type)
{
ngx_uint_t asize;
//初始化元素较少
if (type == NGX_HASH_SMALL)
{
asize = 4;
ha->hsize = 107;
}
//初始化元素较多
else
{
asize = NGX_HASH_LARGE_ASIZE;
ha->hsize = NGX_HASH_LARGE_HSIZE;
}
//初始化存放非通配符key元素的动态数组
if (ngx_array_init(&ha->keys, ha->temp_pool, asize, sizeof(ngx_hash_key_t))!= NGX_OK)
{
return NGX_ERROR;
}
//初始化存放前缀通配符key元素的动态数组
if (ngx_array_init(&ha->dns_wc_head, ha->temp_pool, asize, sizeof(ngx_hash_key_t)) != NGX_OK)
{
return NGX_ERROR;
}
//初始化存放后缀通配符key元素的动态数组
if (ngx_array_init(&ha->dns_wc_tail, ha->temp_pool, asize, sizeof(ngx_hash_key_t)) != NGX_OK)
{
return NGX_ERROR;
}
//初始化不含通配符key的简易hash表(实质是存放动态数组的固定数组)
ha->keys_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize);
if (ha->keys_hash == NULL)
{
return NGX_ERROR;
}
//初始化前缀通配符key的简易hash表(实质是存放动态数组的固定数组)
ha->dns_wc_head_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize);
if (ha->dns_wc_head_hash == NULL)
{
return NGX_ERROR;
}
//初始化后缀通配符key的简易hash表(实质是存放动态数组的固定数组)
ha->dns_wc_tail_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize);
if (ha->dns_wc_tail_hash == NULL)
{
return NGX_ERROR;
}
return NGX_OK;
}
if (flags & NGX_HASH_WILDCARD_KEY)
{
//key中“*”出现次数
n = 0;
for (i = 0; i < key->len; i++)
{
if (key->data[i] == '*')
{
//key中“*”超过一个
if (++n > 1)
{
return NGX_DECLINED;
}
}
//key中有两个连续的"."
if (key->data[i] == '.' && key->data[i + 1] == '.')
{
return NGX_DECLINED;
}
}
//以"."开头的key,形如".example.com"
if (key->len > 1 && key->data[0] == '.')
{
skip = 1;
goto wildcard;
}
if (key->len > 2)
{
//以"*."开头的key,形如"*.example.com"
if (key->data[0] == '*' && key->data[1] == '.')
{
skip = 2;
goto wildcard;
}
//以".*"结尾的key,形如"www.example.*"
if (key->data[i - 2] == '.' && key->data[i - 1] == '*')
{
skip = 0;
last -= 2;
goto wildcard;
}
}
//出现过"*"号,又不满足以上几种情况
if (n)
{
return NGX_DECLINED;
}
}
if (skip)
{
//将"*.example.com"转换成"com.example."
//或将".example.com" 转换成"com.example"
p = ngx_pnalloc(ha->temp_pool, last);
if (p == NULL)
{
return NGX_ERROR;
}
len = 0;
n = 0;
for (i = last - 1; i; i--)
{
if (key->data[i] == '.')
{
ngx_memcpy(&p[n], &key->data[i + 1], len);
n += len;
p[n++] = '.';
len = 0;
continue;
}
len++;
}
if (len)
{
ngx_memcpy(&p[n], &key->data[1], len);
n += len;
}
p[n] = '\0';
......
}
else
{
//将"www.example.*"转换成"www.example"
last++;
p = ngx_pnalloc(ha->temp_pool, last);
if (p == NULL)
{
return NGX_ERROR;
}
ngx_cpystrn(p, key->data, last);
......
}
//对不含通配符key的元素的处理
k = 0;
for (i = 0; i < last; i++)
{
if (!(flags & NGX_HASH_READONLY_KEY))
{
key->data[i] = ngx_tolower(key->data[i]);
}
//计算该key的hash值
k = ngx_hash(k, key->data[i]);
}
//在不含通配符的简易hash表中查找相应的桶(动态数组)下标
k %= ha->hsize;
name = ha->keys_hash[k].elts;
//该桶(动态数组)已经存在(之前已经初始化并存放过key)
if (name)
{
//查找桶中是否存在和当前要存放的key相同的key
for (i = 0; i < ha->keys_hash[k].nelts; i++)
{
//长度不一样,一定不冲突
if (last != name[i].len)
{
continue;
}
//桶内之前已经存放过相同的key,冲突
if (ngx_strncmp(key->data, name[i].data, last) == 0)
{
return NGX_BUSY;
}
}
}
//初始化该元素要存放的桶(动态数组)
else
{
if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK)
{
return NGX_ERROR;
}
}
//将key存放到不含通配符的hash表keys_hash中
name = ngx_array_push(&ha->keys_hash[k]);
if (name == NULL)
{
return NGX_ERROR;
}
*name = *key;
//将元素(key-value对)存放到不含通配符的动态数组keys中
hk = ngx_array_push(&ha->keys);
if (hk == NULL)
{
return NGX_ERROR;
}
hk->key = *key;
hk->key_hash = ngx_hash_key(key->data, last);
hk->value = value;
return NGX_OK;
#ifndef HASH_TEST_H
#define HASH_TEST_H
#include
#include "ngx_config.h"
#include "ngx_conf_file.h"
#include "nginx.h"
#include "ngx_core.h"
#include "ngx_string.h"
#include "ngx_palloc.h"
#include "ngx_array.h"
#include "ngx_hash.h"
#include "ngx_log.h"
#define DEEPTH 4
#define MAX_NUM 18
#define MAX_SIZE 1024
#define BUCKET_SIZE 64
#define MAX_URL_LEN 15
#define MAX_IP_LEN 15
#define MAX_NUM2 3
#define NGX_HASH_ELT_SIZE(name) (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *)))
static ngx_str_t urls[MAX_NUM] = {
ngx_string("*..com."), //1.1.1.1
ngx_string("*.baidu.com.cn"),//180.97.33.107
ngx_string("*.baidu.com"),//180.97.33.107
ngx_string(".baidu.com"),//180.97.33.107
ngx_string("www.qq.*"),//14.17.42.40
ngx_string("*.google.com"),//93.46.8.89
ngx_string("www.qq.com"),//14.17.42.40
ngx_string("www.baidu.com"),//180.97.33.107
ngx_string("www.taobao.com"),//116.207.117.62
ngx_string("www.360.cn"),//119.84.14.199
ngx_string("www.google.com"), //93.46.8.89
ngx_string("www.sina.com.cn"), //121.14.1.189
ngx_string("www.163.com"), //61.136.167.72
ngx_string("www.sohu.com"), //119.97.155.2
ngx_string("test.yexin.com"), //255.255.255.1
ngx_string(".baidu.com"), //180.97.33.107
ngx_string("test.yexin.*"),//255.255.255.255
ngx_string("www.qq.*"),//14.17.42.40
};
static ngx_str_t values[MAX_NUM] = {
ngx_string("1.1.1.1"),
ngx_string("180.97.33.107"),
ngx_string("180.97.33.107"),
ngx_string("180.97.33.107"),
ngx_string("14.17.42.40"),
ngx_string("93.46.8.89"),
ngx_string("14.17.42.40"),
ngx_string("180.97.33.107"),
ngx_string("116.207.117.62"),
ngx_string("119.84.14.199"),
ngx_string("93.46.8.89"),
ngx_string("121.14.1.189"),
ngx_string("61.136.167.72"),
ngx_string("119.97.155.2"),
ngx_string("255.255.255.1"),
ngx_string("180.97.33.107"),
ngx_string("255.255.255.255"),
ngx_string("14.17.42.40")
};
/* for finding test */
static ngx_str_t urls2[MAX_NUM2] = {
ngx_string("*.xx.xx"), //60.217.58.79
ngx_string("www.baidu.com"), //117.79.157.242
ngx_string("www.baidu.") //117.79.157.242
};
void* init_hash(ngx_pool_t *pool, ngx_hash_keys_arrays_t *ha, ngx_hash_combined_t *hash);
void dump_pool(ngx_pool_t* pool);
void dump_hash_array(ngx_array_t* a);
void dump_combined_hash(ngx_hash_combined_t *hash, ngx_hash_keys_arrays_t *array);
void dump_hash(ngx_hash_t *hash, ngx_array_t *array);
void* add_urls_to_array(ngx_pool_t *pool, ngx_hash_keys_arrays_t *ha, ngx_array_t *url, ngx_array_t *value);
void find_test(ngx_hash_combined_t *hash, ngx_str_t addr[], int num);
void dump_hash_wildcard(ngx_hash_wildcard_t *wc_hash, ngx_uint_t deepth);
#endif
hash_test.c
#include "hash_test.h"
volatile ngx_cycle_t *ngx_cycle;
ngx_log_t ngx_log;
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...)
{
}
static int ngx_http_cmp_dns_wildcards(const void *one, const void *two)
{
ngx_hash_key_t *first, *second;
first = (ngx_hash_key_t *) one;
second = (ngx_hash_key_t *) two;
return ngx_dns_strcmp(first->key.data, second->key.data);
}
int main(/* int argc, char **argv */)
{
ngx_pool_t *pool = NULL;
ngx_hash_keys_arrays_t array;
ngx_hash_combined_t hash;
ngx_array_t *key, *value;
hash.wc_head = hash.wc_tail = NULL;
printf("--------------------------------\n");
printf(" the pool:\n");
printf("--------------------------------\n");
//create a new pool
pool = ngx_create_pool(1024, &ngx_log);
dump_pool(pool);
ngx_int_t loop;
printf("--------------------------------\n");
printf("create and add urls to it:\n");
printf("--------------------------------\n");
if ((key = ngx_array_create(pool, MAX_NUM, sizeof(ngx_str_t))) == NULL)
{
printf("Failed to initialize url!\n");
return -1;
}
if ((value = ngx_array_create(pool, MAX_NUM, sizeof(ngx_str_t))) == NULL)
{
printf("Failed to initialize value!\n");
return -1;
}
ngx_str_t *temp;
//常量字符串是不可修改的,而后面需要修改,所以重新拷贝一份
for (loop = 0; loop < MAX_NUM; loop++)
{
temp = ngx_array_push(key);
temp->len = urls[loop].len;
temp->data = ngx_palloc(pool, urls[loop].len);
ngx_memcpy(temp->data, urls[loop].data, temp->len);
}
//由于key-value中的value的地址必须是4对齐的,所以需要重新拷贝一份vaule
for (loop = 0; loop < MAX_NUM; loop++)
{
temp = ngx_array_push(value);
temp->len = values[loop].len;
temp->data = ngx_palloc(pool, values[loop].len);
ngx_memcpy(temp->data, values[loop].data, temp->len);
}
if (add_urls_to_array(pool, &array, key, value) == NULL)
{
printf("Failed to initialize array!\n");
return -1;
}
printf("--------------------------------\n");
printf(" array.keys :\n");
printf("--------------------------------\n");
dump_hash_array(&array.keys);
printf("--------------------------------\n");
printf(" array.dns_wc_head :\n");
printf("--------------------------------\n");
dump_hash_array(&array.dns_wc_head);
printf("--------------------------------\n");
printf(" array.dns_wc_tail :\n");
printf("--------------------------------\n");
dump_hash_array(&array.dns_wc_tail);
printf("--------------------------------\n");
printf(" array.keys_hash :\n");
printf("--------------------------------\n");
for (int i = 0; i < 10007; i++)
{
if (array.keys_hash[i].nelts != 0)
{
printf("i = %d\n", i);
dump_hash_array(&(array.keys_hash[i]));
}
}
printf("--------------------------------\n");
printf(" array.dns_wc_head_hash :\n");
printf("--------------------------------\n");
for (int i = 0; i < 10007; i++)
{
if (array.dns_wc_head_hash[i].nelts != 0)
{
printf("i = %d\n", i);
dump_hash_array(&(array.dns_wc_head_hash[i]));
}
}
printf("--------------------------------\n");
printf(" array.dns_wc_tail_hash :\n");
printf("--------------------------------\n");
for (int i = 0; i < 10007; i++)
{
if (array.dns_wc_tail_hash[i].nelts != 0)
{
printf("i = %d\n", i);
dump_hash_array(&(array.dns_wc_tail_hash[i]));
}
}
printf("--------------------------------\n");
printf(" the pool:\n");
printf("--------------------------------\n");
dump_pool(pool);
if (init_hash(pool, &array, &hash) == NULL)
{
printf("Failed to initialize hash!\n");
return -1;
}
printf("--------------------------------\n");
printf("the hash:\n");
printf("--------------------------------\n");
dump_combined_hash(&hash, &array);
printf("\n");
printf("--------------------------------\n");
printf("the pool:\n");
printf("--------------------------------\n");
dump_pool(pool);
//find test
printf("--------------------------------\n");
printf("find test:\n");
printf("--------------------------------\n");
find_test(&hash, urls, MAX_NUM);
printf("\n");
find_test(&hash, urls2, MAX_NUM2);
//release
return 0;
}
void* init_hash(ngx_pool_t *pool, ngx_hash_keys_arrays_t *ha, ngx_hash_combined_t *hash)
{
ngx_hash_init_t hinit;
ngx_cacheline_size = 32; //here this variable for nginx must be defined
hinit.hash = NULL; //if hinit.hash is NULL, it will alloc memory for it in ngx_hash_init
hinit.key = &ngx_hash_key_lc; //hash function
hinit.max_size = MAX_SIZE;
hinit.bucket_size = BUCKET_SIZE;
hinit.name = "my_hash_sample";
hinit.pool = pool; //the hash table exists in the memory pool
hinit.temp_pool = ha->temp_pool;
if (ha->keys.nelts) { //无通配
hinit.hash = &hash->hash;
if (ngx_hash_init(&hinit, ha->keys.elts, ha->keys.nelts) != NGX_OK) {
goto failed;
}
}
if (ha->dns_wc_head.nelts) { //前缀通配
hinit.hash = NULL;
ngx_qsort(ha->dns_wc_head.elts, (size_t) ha->dns_wc_head.nelts,
sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
printf("--------------------------------\n");
printf(" array.dns_wc_head after sort:\n");
printf("--------------------------------\n");
dump_hash_array(&ha->dns_wc_head);
if (ngx_hash_wildcard_init(&hinit, ha->dns_wc_head.elts,
ha->dns_wc_head.nelts)
!= NGX_OK)
{
goto failed;
}
hash->wc_head = (ngx_hash_wildcard_t *) hinit.hash;
}
if (ha->dns_wc_tail.nelts) { //后缀通配
ngx_qsort(ha->dns_wc_tail.elts, (size_t) ha->dns_wc_tail.nelts,
sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
printf("--------------------------------\n");
printf(" array.dns_wc_tail after sort:\n");
printf("--------------------------------\n");
dump_hash_array(&ha->dns_wc_tail);
hinit.hash = NULL;
if (ngx_hash_wildcard_init(&hinit, ha->dns_wc_tail.elts,
ha->dns_wc_tail.nelts)
!= NGX_OK)
{
goto failed;
}
hash->wc_tail = (ngx_hash_wildcard_t *) hinit.hash;
}
//ngx_destroy_pool(ha->temp_pool);
return hash;
failed:
//ngx_destroy_pool(ha->temp_pool);
return NULL;
}
void dump_pool(ngx_pool_t* pool)
{
while (pool)
{
printf("pool = %p\n", pool);
printf(" .d\n");
printf(" .last = %p\n", pool->d.last);
printf(" .end = %p\n", pool->d.end);
printf(" .next = %p\n", pool->d.next);
printf(" .failed = %d\n", pool->d.failed);
printf(" .max = %d\n", pool->max);
printf(" .current = %p\n", pool->current);
printf(" .chain = %p\n", pool->chain);
printf(" .large = %p\n", pool->large);
printf(" .cleanup = %p\n", pool->cleanup);
printf(" .log = %p\n", pool->log);
printf("available pool memory = %d\n\n", pool->d.end - pool->d.last);
pool = pool->d.next;
}
}
void dump_hash_array(ngx_array_t* a)
{
char prefix[] = " ";
ngx_uint_t i;
if (a == NULL)
return;
printf("array = %p\n", a);
printf(" .elts = %p\n", a->elts);
printf(" .nelts = %d\n", a->nelts);
printf(" .size = %d\n", a->size);
printf(" .nalloc = %d\n", a->nalloc);
printf(" .pool = %p\n", a->pool);
printf(" elements:\n");
ngx_hash_key_t *ptr = a->elts;
for (i = 0; i < a->nelts; i++)
{
if (ptr[i].value)
{
printf(" %p: {key = (\"%.*s\"%.*s, %-2d), key_hash = %-11d , value = \"%.*s\"%.*s}\n", ptr + i, ptr[i].key.len, ptr[i].key.data, MAX_URL_LEN - ptr[i].key.len, prefix, ptr[i].key.len, ptr[i].key_hash, ((ngx_str_t*)ptr[i].value)->len, ((ngx_str_t*)ptr[i].value)->data, MAX_IP_LEN - ((ngx_str_t*)ptr[i].value)->len, prefix);
}
else
{
printf(" %p: {key = (\"%.*s\"%.*s, %-2d), key_hash = %-11d }\n", ptr + i, ptr[i].key.len, ptr[i].key.data, MAX_URL_LEN - ptr[i].key.len, prefix, ptr[i].key.len, ptr[i].key_hash);
}
}
printf("\n");
}
void display_str_data(ngx_str_t *str)
{
int len = str->len;
for (int i = 0; i < len; i++)
{
printf("%c", str->data[i]);
}
printf("\0");
}
/**
* pass array pointer to read elts[i].key_hash, then for getting the position - key
*/
void dump_combined_hash(ngx_hash_combined_t *hash, ngx_hash_keys_arrays_t *array)
{
dump_hash(&hash->hash, &array->keys);
dump_hash_wildcard(hash->wc_head, 0);
dump_hash_wildcard(hash->wc_tail, 0);
}
void dump_hash_wildcard(ngx_hash_wildcard_t *wc_hash, ngx_uint_t deepth)
{
ngx_uint_t loop;
char prefix[] = " ";
ngx_hash_wildcard_t *wdc;
ngx_hash_t *hash = &wc_hash->hash;
if (wc_hash == NULL)
return;
if (wc_hash->value != NULL)
printf("%.*svalue = \"%.*s\"\n", deepth * DEEPTH, prefix, ((ngx_str_t*)wc_hash->value)->len,
((ngx_str_t*)wc_hash->value)->data);
else
printf("%.*svalue = NULL\n", deepth * DEEPTH, prefix);
printf("%.*shash = %p: **buckets = %p, size = %d\n", deepth * DEEPTH, prefix, hash, hash->buckets, hash->size);
for (loop = 0; loop < hash->size; loop++)
{
ngx_hash_elt_t *elt = hash->buckets[loop];
printf("%.*s%p: buckets[%d] = %p\n", deepth * DEEPTH * 2, prefix, &(hash->buckets[loop]), loop, elt);
if (elt)
{
while (elt->value)
{
uintptr_t value = (uintptr_t)elt->value;
if ((value & 3) == 0 || (value & 3) == 1) //注意位操作与逻辑运算符的优先级
{
value &= (uintptr_t)~3;
//值得参考的是%.*s的输出,通过参数控制输出字符的个数
printf("%.*sbuckets %d: %p {value = \"%.*s\"%.*s, len = %d, name = \"%.*s\"%.*s}\n",
deepth * DEEPTH * 2, prefix, loop, elt, ((ngx_str_t*)value)->len, ((ngx_str_t*)value)->data, MAX_IP_LEN - ((ngx_str_t*)value)->len, prefix,
elt->len, elt->len, elt->name, MAX_URL_LEN - elt->len, prefix);
}
else
{
wdc = (ngx_hash_wildcard_t *)(value & (uintptr_t)~3);
printf("%.*sbuckets %d: %p: {value = \"%-16p\", len = %d, name = \"%.*s\"%.*s}\n",
deepth * DEEPTH * 2, prefix, loop, elt, wdc, elt->len, elt->len, elt->name, MAX_URL_LEN - elt->len, prefix);
dump_hash_wildcard(wdc, deepth + 1);
}
elt = (ngx_hash_elt_t *)ngx_align_ptr(&elt->name[0] + elt->len, sizeof(void *));
}
}
}
}
void dump_hash(ngx_hash_t *hash, ngx_array_t *array)
{
ngx_uint_t loop;
char prefix[] = " ";
u_short test[MAX_NUM] = {0};
ngx_uint_t key;
ngx_hash_key_t* elts;
if (hash == NULL)
return;
printf("hash = %p: **buckets = %p, size = %d\n", hash, hash->buckets, hash->size);
for (loop = 0; loop < hash->size; loop++)
{
ngx_hash_elt_t *elt = hash->buckets[loop];
printf(" %p: buckets[%d] = %p\n", &(hash->buckets[loop]), loop, elt);
}
printf("\n");
elts = (ngx_hash_key_t*)array->elts;
for (loop = 0; loop < array->nelts; loop++)
{
key = elts[loop].key_hash % hash->size;
ngx_hash_elt_t *elt = (ngx_hash_elt_t *) ((u_char *) hash->buckets[key] + test[key]);
//值得参考的是%.*s的输出,通过参数控制输出字符的个数
printf(" key %-10d: buckets %d: %p: {value = \"%.*s\"%.*s, len = %d, name = \"%.*s\"%.*s}\n",
elts[loop].key_hash, key, elt, ((ngx_str_t*)elt->value)->len, ((ngx_str_t*)elt->value)->data, MAX_IP_LEN - ((ngx_str_t*)elt->value)->len, prefix, elt->len,
elt->len, elt->name, MAX_URL_LEN - elt->len, prefix); //replace elt->name with url
test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&elts[loop]));
}
}
void* add_urls_to_array(ngx_pool_t *pool, ngx_hash_keys_arrays_t *ha, ngx_array_t *url, ngx_array_t *value)
{
ngx_uint_t loop;
ngx_int_t rc;
ngx_str_t *strUrl, *strValue;
memset(ha, 0, sizeof(ngx_hash_keys_arrays_t));
ha->temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, &ngx_log);
ha->pool = pool;
if (ngx_hash_keys_array_init(ha, NGX_HASH_LARGE) != NGX_OK) {
goto failed;
}
strUrl = url->elts;
strValue = value->elts;
for (loop = 0; loop < url->nelts; loop++)
{
rc = ngx_hash_add_key(ha, &strUrl[loop], &strValue[loop],
NGX_HASH_WILDCARD_KEY);
if (rc == NGX_ERROR) {
goto failed;
}
}
return ha;
failed:
ngx_destroy_pool(ha->temp_pool);
return NULL;
}
void find_test(ngx_hash_combined_t *hash, ngx_str_t addr[], int num)
{
ngx_uint_t key;
int loop;
char prefix[] = " ";
for (loop = 0; loop < num; loop++)
{
key = ngx_hash_key_lc(addr[loop].data, addr[loop].len);
ngx_str_t *value = ngx_hash_find_combined(hash, key, addr[loop].data, addr[loop].len);
if (value)
{
printf("(url = \"%s\"%.*s, key = %-11d) found, (ip = \"%.*s%.*s\")\n",
addr[loop].data, MAX_URL_LEN - addr[loop].len, prefix, key, value->len, value->data, MAX_IP_LEN - value->len, prefix);
}
else
{
printf("(url = \"%s\"%.*s, key = %-11d) not found!\n",
addr[loop].data, MAX_URL_LEN - addr[loop].len, prefix, key);
}
}
}
测试结果:
--------------------------------
the pool:
--------------------------------
pool = 0x20b7020
.d
.last = 0x20b7070
.end = 0x20b7420
.next = (nil)
.failed = 0
.max = 944
.current = 0x20b7020
.chain = (nil)
.large = (nil)
.cleanup = (nil)
.log = 0x608700
available pool memory = 944
--------------------------------
create and add urls to it:
--------------------------------
--------------------------------
array.keys :
--------------------------------
array = 0x7ffce5196448
.elts = 0x7f04ed9bc010
.nelts = 9
.size = 32
.nalloc = 16384
.pool = 0x20b7840
elements:
0x7f04ed9bc010: {key = ("www.qq.com" , 10), key_hash = 203430122 , value = "14.17.42.40" }
0x7f04ed9bc030: {key = ("www.baidu.com" , 13), key_hash = 270263191 , value = "180.97.33.107" }
0x7f04ed9bc050: {key = ("www.taobao.com" , 14), key_hash = 123724152 , value = "116.207.117.62" }
0x7f04ed9bc070: {key = ("www.360.cn" , 10), key_hash = -1626056701 , value = "119.84.14.199" }
0x7f04ed9bc090: {key = ("www.google.com" , 14), key_hash = -702889725 , value = "93.46.8.89" }
0x7f04ed9bc0b0: {key = ("www.sina.com.cn", 15), key_hash = 1528635686 , value = "121.14.1.189" }
0x7f04ed9bc0d0: {key = ("www.163.com" , 11), key_hash = -640386838 , value = "61.136.167.72" }
0x7f04ed9bc0f0: {key = ("www.sohu.com" , 12), key_hash = 1313636595 , value = "119.97.155.2" }
0x7f04ed9bc110: {key = ("test.yexin.com" , 14), key_hash = -650258232 , value = "255.255.255.1" }
--------------------------------
array.dns_wc_head :
--------------------------------
array = 0x7ffce5196478
.elts = 0x7f04ed93b010
.nelts = 3
.size = 32
.nalloc = 16384
.pool = 0x20b7840
elements:
0x7f04ed93b010: {key = ("cn.com.baidu." , 13), key_hash = 0 , value = "180.97.33.107" }
0x7f04ed93b030: {key = ("com.baidu." , 10), key_hash = 0 , value = "180.97.33.107" }
0x7f04ed93b050: {key = ("com.google." , 11), key_hash = 0 , value = "93.46.8.89" }
--------------------------------
array.dns_wc_tail :
--------------------------------
array = 0x7ffce51964a8
.elts = 0x7f04ed8ba010
.nelts = 2
.size = 32
.nalloc = 16384
.pool = 0x20b7840
elements:
0x7f04ed8ba010: {key = ("www.qq" , 6 ), key_hash = 0 , value = "14.17.42.40" }
0x7f04ed8ba030: {key = ("test.yexin" , 10), key_hash = 0 , value = "255.255.255.255"}
--------------------------------
array.keys_hash :
--------------------------------
i = 474
array = 0x7f04ed40da20
.elts = 0x20b7bb0
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7bb0: {key = ("www.google.com" , 14), key_hash = 0 , value = NULL}
i = 2741
array = 0x7f04ed423c58
.elts = 0x20b7bf0
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7bf0: {key = ("www.sina.com.cn", 15), key_hash = 0 , value = NULL}
i = 2876
array = 0x7f04ed425170
.elts = 0x20b7c70
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7c70: {key = ("www.sohu.com" , 12), key_hash = 0 , value = NULL}
i = 3339
array = 0x7f04ed4299c8
.elts = 0x20b7c30
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7c30: {key = ("www.163.com" , 11), key_hash = 0 , value = NULL}
i = 5437
array = 0x7f04ed43e198
.elts = 0x20b7b30
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7b30: {key = ("www.taobao.com" , 14), key_hash = 0 , value = NULL}
i = 6447
array = 0x7f04ed447f68
.elts = 0x20b7ab0
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7ab0: {key = ("www.qq.com" , 10), key_hash = 0 , value = NULL}
i = 7515
array = 0x7f04ed452648
.elts = 0x20b7af0
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7af0: {key = ("www.baidu.com" , 13), key_hash = 0 , value = NULL}
i = 7611
array = 0x7f04ed453548
.elts = 0x20b7cb0
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7cb0: {key = ("test.yexin.com" , 14), key_hash = 0 , value = NULL}
i = 7759
array = 0x7f04ed454c68
.elts = 0x20b79a8
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b79a8: {key = ("baidu.com" , 9 ), key_hash = 0 , value = NULL}
i = 9371
array = 0x7f04ed464848
.elts = 0x20b7b70
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7b70: {key = ("www.360.cn" , 10), key_hash = 0 , value = NULL}
--------------------------------
array.dns_wc_head_hash :
--------------------------------
i = 4033
array = 0x7f04ed3ce638
.elts = 0x20b7900
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7900: {key = ("baidu.com.cn" , 12), key_hash = 0 , value = NULL}
i = 4603
array = 0x7f04ed3d3f48
.elts = 0x20b7a60
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7a60: {key = ("google.com" , 10), key_hash = 0 , value = NULL}
i = 7759
array = 0x7f04ed3f2c68
.elts = 0x20b7958
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7958: {key = ("baidu.com" , 9 ), key_hash = 0 , value = NULL}
--------------------------------
array.dns_wc_tail_hash :
--------------------------------
i = 2198
array = 0x7f04ed35a780
.elts = 0x20b7d00
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7d00: {key = ("test.yexin." , 11), key_hash = 0 , value = NULL}
i = 8396
array = 0x7f04ed396ff0
.elts = 0x20b7a08
.nelts = 1
.size = 16
.nalloc = 4
.pool = 0x20b7840
elements:
0x20b7a08: {key = ("www.qq." , 7 ), key_hash = 0 , value = NULL}
--------------------------------
the pool:
--------------------------------
pool = 0x20b7020
.d
.last = 0x20b741d
.end = 0x20b7420
.next = 0x20b7430
.failed = 0
.max = 944
.current = 0x20b7020
.chain = (nil)
.large = (nil)
.cleanup = (nil)
.log = 0x608700
available pool memory = 3
pool = 0x20b7430
.d
.last = 0x20b754b
.end = 0x20b7830
.next = (nil)
.failed = 0
.max = 774912049
.current = 0x3730312e33
.chain = 0x332e37392e303831
.large = 0x3730312e33
.cleanup = 0x32342e37312e3431
.log = 0x30342e
available pool memory = 741
--------------------------------
array.dns_wc_head after sort:
--------------------------------
array = 0x7ffce5196478
.elts = 0x7f04ed93b010
.nelts = 3
.size = 32
.nalloc = 16384
.pool = 0x20b7840
elements:
0x7f04ed93b010: {key = ("cn.com.baidu." , 13), key_hash = 0 , value = "180.97.33.107" }
0x7f04ed93b030: {key = ("com.baidu." , 10), key_hash = 0 , value = "180.97.33.107" }
0x7f04ed93b050: {key = ("com.google." , 11), key_hash = 0 , value = "93.46.8.89" }
--------------------------------
array.dns_wc_tail after sort:
--------------------------------
array = 0x7ffce51964a8
.elts = 0x7f04ed8ba010
.nelts = 2
.size = 32
.nalloc = 16384
.pool = 0x20b7840
elements:
0x7f04ed8ba010: {key = ("test.yexin" , 10), key_hash = 0 , value = "255.255.255.255"}
0x7f04ed8ba030: {key = ("www.qq" , 6 ), key_hash = 0 , value = "14.17.42.40" }
--------------------------------
the hash:
--------------------------------
hash = 0x7ffce5196410: **buckets = 0x20b7550, size = 9
0x20b7550: buckets[0] = 0x20b75a0
0x20b7558: buckets[1] = 0x20b75c0
0x20b7560: buckets[2] = 0x20b75e0
0x20b7568: buckets[3] = 0x20b7600
0x20b7570: buckets[4] = 0x20b7620
0x20b7578: buckets[5] = 0x20b7660
0x20b7580: buckets[6] = (nil)
0x20b7588: buckets[7] = 0x20b76a0
0x20b7590: buckets[8] = (nil)
key 203430122 : buckets 4: 0x20b7620: {value = "14.17.42.40" , len = 10, name = "www.qq.com" }
key 270263191 : buckets 2: 0x20b75e0: {value = "180.97.33.107" , len = 13, name = "www.baidu.com" }
key 123724152 : buckets 0: 0x20b75a0: {value = "116.207.117.62" , len = 14, name = "www.taobao.com" }
key -1626056701: buckets 7: 0x20b76a0: {value = "119.84.14.199" , len = 10, name = "www.360.cn" }
key -702889725: buckets 1: 0x20b75c0: {value = "93.46.8.89" , len = 14, name = "www.google.com" }
key 1528635686: buckets 5: 0x20b7660: {value = "121.14.1.189" , len = 15, name = "www.sina.com.cn"}
key -640386838: buckets 7: 0x20b76b8: {value = "61.136.167.72" , len = 11, name = "www.163.com" }
key 1313636595: buckets 3: 0x20b7600: {value = "119.97.155.2" , len = 12, name = "www.sohu.com" }
key -650258232: buckets 4: 0x20b7638: {value = "255.255.255.1" , len = 14, name = "test.yexin.com" }
value = NULL
hash = 0x20b77d8: **buckets = 0x20b77f0, size = 1
0x20b77f0: buckets[0] = 0x20bc0e0
buckets 0: 0x20bc0e0: {value = "0x20b7758 ", len = 2, name = "cn" }
value = NULL
hash = 0x20b7758: **buckets = 0x20b7770, size = 1
0x20b7770: buckets[0] = 0x20b7780
buckets 0: 0x20b7780: {value = "0x20b76f8 ", len = 3, name = "com" }
value = NULL
hash = 0x20b76f8: **buckets = 0x20b7710, size = 1
0x20b7710: buckets[0] = 0x20b7720
buckets 0: 0x20b7720 {value = "180.97.33.107" , len = 5, name = "baidu" }
buckets 0: 0x20bc0f0: {value = "0x20b77b8 ", len = 3, name = "com" }
value = NULL
hash = 0x20b77b8: **buckets = 0x20b77d0, size = 1
0x20b77d0: buckets[0] = 0x20bc080
buckets 0: 0x20bc080 {value = "180.97.33.107" , len = 5, name = "baidu" }
buckets 0: 0x20bc090 {value = "93.46.8.89" , len = 6, name = "google" }
value = NULL
hash = 0x20bc1e0: **buckets = 0x20bc1f8, size = 1
0x20bc1f8: buckets[0] = 0x20bc200
buckets 0: 0x20bc200: {value = "0x20b77f8 ", len = 4, name = "test" }
value = NULL
hash = 0x20b77f8: **buckets = 0x20b7810, size = 1
0x20b7810: buckets[0] = 0x20bc140
buckets 0: 0x20bc140 {value = "255.255.255.255", len = 5, name = "yexin" }
buckets 0: 0x20bc210: {value = "0x20bc180 ", len = 3, name = "www" }
value = NULL
hash = 0x20bc180: **buckets = 0x20bc198, size = 1
0x20bc198: buckets[0] = 0x20bc1a0
buckets 0: 0x20bc1a0 {value = "14.17.42.40" , len = 2, name = "qq" }
--------------------------------
the pool:
--------------------------------
pool = 0x20b7020
.d
.last = 0x20b741d
.end = 0x20b7420
.next = 0x20b7430
.failed = 1
.max = 944
.current = 0x20b7020
.chain = (nil)
.large = (nil)
.cleanup = (nil)
.log = 0x608700
available pool memory = 3
pool = 0x20b7430
.d
.last = 0x20b7818
.end = 0x20b7830
.next = 0x20bc060
.failed = 0
.max = 774912049
.current = 0x3730312e33
.chain = 0x332e37392e303831
.large = 0x3730312e33
.cleanup = 0x32342e37312e3431
.log = 0x30342e
available pool memory = 24
pool = 0x20bc060
.d
.last = 0x20bc260
.end = 0x20bc460
.next = (nil)
.failed = 0
.max = 34304513
.current = 0x75646961620005
.chain = 0x20b7231
.large = 0x656c676f6f670006
.cleanup = (nil)
.log = (nil)
available pool memory = 512
--------------------------------
find test:
--------------------------------
(url = "*..com." , key = -17068745 ) not found!
(url = "*.baidu.com.cn" , key = 234385007 ) found, (ip = "180.97.33.107 ")
(url = "*.baidu.com" , key = -724157846 ) found, (ip = "180.97.33.107 ")
(url = ".baidu.com" , key = 1733355200 ) found, (ip = "180.97.33.107 ")
(url = "www.qq.*" , key = -1367384621) found, (ip = "14.17.42.40 ")
(url = "*.google.com" , key = -1465170800) found, (ip = "93.46.8.89 ")
(url = "www.qq.com" , key = 203430122 ) found, (ip = "14.17.42.40 ")
(url = "www.baidu.com" , key = 270263191 ) found, (ip = "180.97.33.107 ")
(url = "www.taobao.com" , key = 123724152 ) found, (ip = "116.207.117.62 ")
(url = "www.360.cn" , key = -1626056701) found, (ip = "119.84.14.199 ")
(url = "www.google.com" , key = -702889725 ) found, (ip = "93.46.8.89 ")
(url = "www.sina.com.cn", key = 1528635686 ) found, (ip = "121.14.1.189 ")
(url = "www.163.com" , key = -640386838 ) found, (ip = "61.136.167.72 ")
(url = "www.sohu.com" , key = 1313636595 ) found, (ip = "119.97.155.2 ")
(url = "test.yexin.com" , key = -650258232 ) found, (ip = "255.255.255.1 ")
(url = ".baidu.com" , key = 1733355200 ) found, (ip = "180.97.33.107 ")
(url = "test.yexin.*" , key = -2061009615) found, (ip = "255.255.255.255")
(url = "www.qq.*" , key = -1367384621) found, (ip = "14.17.42.40 ")
(url = "*.xx.xx" , key = 51835370 ) not found!
(url = "www.baidu.com" , key = 270263191 ) found, (ip = "180.97.33.107 ")
(url = "www.baidu." , key = -239024726 ) not found!