Chinaunix首页 | 论坛 | 博客
  • 博客访问: 871376
  • 博文数量: 87
  • 博客积分: 3324
  • 博客等级: 中校
  • 技术积分: 1003
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-17 11:37
文章分类

全部博文(87)

文章存档

2014年(3)

2013年(5)

2012年(21)

2011年(13)

2010年(7)

2009年(9)

2008年(4)

2007年(14)

2006年(11)

分类: C/C++

2012-10-31 11:13:11

大家看到在构建一个ngx_hash_wildcard_t的时候,需要对通配符的哪些key进行预处理。这个处理起来比较麻烦。而当有一组key,这些里面既有无通配符的key,也有包含通配符的key的时候。我们就需要构建三个hash表,一个包含普通的keyhash表,一个包含前向通配符的hash表,一个包含后向通配符的hash表(或者也可以把这三个hash表组合成一个ngx_hash_combined_t)。在这种情况下,为了让大家方便的构造这些hash表,nginx提供给了此辅助类型。

 

该类型以及相关的操作函数也定义在src/core/ngx_hash.h|c里。我们先来看一下该类型的定义。

typedef struct {

    ngx_uint_t        hsize;

 

    ngx_pool_t       *pool;

    ngx_pool_t       *temp_pool;

 

    ngx_array_t       keys;

    ngx_array_t      *keys_hash;

 

    ngx_array_t       dns_wc_head;

    ngx_array_t      *dns_wc_head_hash;

 

    ngx_array_t       dns_wc_tail;

    ngx_array_t      *dns_wc_tail_hash;

} ngx_hash_keys_arrays_t;

 

 

hsize: 将要构建的hash表的桶的个数。对于使用这个结构中包含的信息构建的三种类型的hash表都会使用此参数。

pool: 构建这些hash表使用的pool

temp_pool:在构建这个类型以及最终的三个hash表过程中可能用到临时pool。该temp_pool可以在构建完成以后,被销毁掉。这里只是存放临时的一些内存消耗。

keys: 存放所有非通配符key的数组。

keys_hash: 这是个二维数组,第一个维度代表的是bucket的编号,那么keys_hash[i]中存放的是所有的key算出来的hash值对hsize取模以后的值为ikey。假设有3key,分别是key1,key2key3假设hash值算出来以后对hsize取模的值都是i,那么这三个key的值就顺序存放在keys_hash[i][0],keys_hash[i][1], keys_hash[i][2]。该值在调用的过程中用来保存和检测是否有冲突的key值,也就是是否有重复。

dns_wc_head: 存放前向通配符key被处理完成以后的值。比如:“*.abc.com”被处理完成以后,变成“com.abc.”被存放在此数组中。

dns_wc_tail: 存放后向通配符key被处理完成以后的值。比如:“mail.xxx.*”被处理完成以后,变成“mail.xxx.”被存放在此数组中。

 

dns_wc_head_hash: 该值在调用的过程中用来保存和检测是否有冲突的前向通配符的key值,也就是是否有重复。

 

dns_wc_tail_hash: 该值在调用的过程中用来保存和检测是否有冲突的后向通配符的key值,也就是是否有重复。

 

在定义一个这个类型的变量,并对字段pooltemp_pool赋值以后,就可以调用函数ngx_hash_add_key把所有的key加入到这个结构中了,该函数会自动实现普通key,带前向通配符的key和带后向通配符的key的分类和检查,并将这个些值存放到对应的字段中去,

然后就可以通过检查这个结构体中的keysdns_wc_headdns_wc_tail三个数组是否为空,来决定是否构建普通hash表,前向通配符hash表和后向通配符hash表了(在构建这三个类型的hash表的时候,可以分别使用keysdns_wc_headdns_wc_tail三个数组)。

 

构建出这三个hash表以后,可以组合在一个ngx_hash_combined_t对象中,使用ngx_hash_find_combined进行查找。或者是仍然保持三个独立的变量对应这三个hash表,自I机决定何时以及在哪个hash表中进行查询。

 

ngx_int_t ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type);

初始化这个结构,主要是对这个结构中的ngx_array_t类型的字段进行初始化,成功返回NGX_OK

 

ha: 该结构的对象指针。

type: 该字段有2个值可选择,即NGX_HASH_SMALLNGX_HASH_LARGE。用来指明将要建立的hash表的类型,如果是NGX_HASH_SMALL,则有比较小的桶的个数和数组元素大小。NGX_HASH_LARGE则相反。

 

ngx_int_t ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key,

void *value, ngx_uint_t flags);

一般是循环调用这个函数,把一组键值对加入到这个结构体中。返回NGX_OK是加入成功。返回NGX_BUSY意味着key值重复。

 

ha: 该结构的对象指针。

key: 参数名自解释了。

value: 参数名自解释了。

flags: 有两个标志位可以设置,NGX_HASH_WILDCARD_KEYNGX_HASH_READONLY_KEY。同时要设置的使用逻辑与操作符就可以了。NGX_HASH_READONLY_KEY被设置的时候,在计算hash值的时候,key的值不会被转成小写字符,否则会。NGX_HASH_WILDCARD_KEY被设置的时候,说明key里面可能含有通配符,会进行相应的处理。如果两个标志位都不设置,传0

 

有关于这个数据结构的使用,可以参考src/http/ngx_http.c中的ngx_http_server_names函数。

阅读(2165) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~