本文为作者原创,转载请注明出处:http://my.oschina.net/fuckphp/blog/277226
/**
* 32数混淆函数(没看到哪里有用这个函数)
* unsigned int key 需要混淆的数字
* return 混淆后的数字
*/
unsigned int dictIntHashFunction(unsigned int key);
/**
* 设置hash函数的随机种子
* uint32_t seed 随机种子默认 5381
* return void
*/
void dictSetHashFunctionSeed(uint32_t seed);
/**
* 获取hash函数的随机种子
* return 返回随机种子
*/
uint32_t dictGetHashFunctionSeed(void);
/**
* MurmurHash2 算法的实现
* const void *key 需要进行hash的字符串
* int len 需要进行hash的字符串长度
* return 返回hash后的结果
*/
unsigned int dictGenHashFunction(const void *key, int len);
/**
* DjbHash 算法的实现
* const unsigned char *buf 需要进行hash的字符串
* int len 需要进行hash的字符串长度
* return 返回hash后的结果
*/
unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len);
/**
* 对 hashtable 进行重置操作 私有函数
* dictht *ht 需要初始化的 hashtable
* return 返回hash后的结果
*/
static void _dictReset(dictht *ht);
/**
* 创建一个新的字典
* dictType *type 字典操作函数类型(type是一个包含一组回调函数的结构)
* void *privDataPtr 设置为不同类型回调函数提供的 私有参数
* return 返回一个新的字典
*/
dict *dictCreate(dictType *type, void *privDataPtr);
/**
* 对新的字典进行初始化操作 对字典中的hashtable进行重置操作,并对其他属性设置默认值 私有函数
* dict *d 需要初始化操作的字典
* dictType *type 字典操作函数类型(type是一个包含一组回调函数的结构)
* void *privDataPtr 设置为不同类型回调函数提供的 私有参数
* return 返回初始化的状态
*/
int _dictInit(dict *d, dictType *type, void *privDataPtr);
/**
* 重新设置桶的大小 如果 dict_can_resize 为 0 或者 正在进行rehash则不进行重新设置
* dict *d 需要扩展的字典
* return 返回扩展结果的状态
*/
int dictResize(dict *d);
/**
* 将字典创建hashable,并对hashtable桶的个数进行扩展,如果正在rehash 或者 当前节点数 小于传递过来的节点数 则不进行rehash
* dict *d 需要扩展的字典
* unsigned long size 当前的节点数 最小为 DICT_HT_INITIAL_SIZE
* return 返回扩展结果的状态
*/
int dictExpand(dict *d, unsigned long size);
/**
* 对字典的n个桶进行rehash,计算每个桶内链表所有key并计算hash后,存放在ht[1]中,并将ht[0]中处理过的桶指针指向空
* dict *d 需要rehash的字典
* int n 进行rehash的桶的的个数
* return 返回0表示rehash结束 否则表示 还没有完全rehash结束
*/
int dictRehash(dict *d, int n);
/**
* 获取以毫秒为单位的时间戳
* return 返回 以毫秒为单位的时间戳 例如:1401352736541
*/
long long timeInMilliseconds(void);
/**
* 对字典进行rehash操作,每次rehash 100个桶,知道rehash时间超过 ms毫秒
* dict *d 进行rehash的字典
* int ms rehash的时间限制
* return 返回执行rehash的桶的个数
*/
int dictRehashMilliseconds(dict *d, int ms);
/**
* 如果没有进行迭代操作,则进行一次rehash操作(渐进式rehash,将rehash操作分不到每一个操作上)
* dict *d 进行rehash的字典
* return void
*/
static void _dictRehashStep(dict *d);
/**
* 向hashtable中加入一个新的节点
* dict *d 加入节点的字典
* void *key 节点的key
* void *val 节点的value
* return 返回 成功或失败
*/
int dictAdd(dict *d, void *key, void *val);
/**
* 创建一个包含KEY的dictEntry对象,如果正在进行Rehash,会执行一个桶的Rehash操作(在检查key的时候会判断是否处罚rehash)
* dict *d 加入节点的字典
* void *key 节点的key
* return 返回创建成功包含key的dictEntry
*/
dictEntry *dictAddRaw(dict *d, void *key);
/**
* 创建一个包含KEY的dictEntry对象,如果key已经存在则覆盖,如果正在进行Rehash,会执行一个桶的Rehash操作(在检查key的时候会判断是否处罚rehash)
* dict *d 加入节点的字典
* void *key 节点的key
* void *val 节点的val
* return 返回 成功或失败
*/
int dictReplace(dict *d, void *key, void *val);
/**
* 查找如果存在key则返回key对应的结构,否则 创建一个包含key的新的结构并返回
* dict *d 加入节点的字典
* void *key 节点的key
* return 返回 查找到的或新创建的 dictEntry
*/
dictEntry *dictReplaceRaw(dict *d, void *key);
/**
* 查找并在hashtable删除某个key所对应的结构
* dict *d 加入节点的字典
* void *key 要删除的节点的key
* int nofree 如果为1 则删除的某个key的结构不进行内存释放
* return 返回 成功或失败
*/
static int dictGenericDelete(dict *d, const void *key, int nofree);
/**
* 查找并在hashtable删除某个key所对应的结构,并不释放内存
* dict *d 加入节点的字典
* void *key 要删除的节点的key
* return 返回 成功或失败
*/
int dictDeleteNoFree(dict *ht, const void *key);
/**
* 将字典中的某个ht中所有节点全部删除
* dict *d 要进行删除操作的的字典
* dictht *ht dictht[0] 或 dictht[1]
* void(callback)(void *) 回调函数,void *参数为 dict结构中的pridata
* return 返回 成功或失败
*/
int _dictClear(dict *d, dictht *ht, void(callback)(void *));
/**
* 将字典所有节点清空,并释放字典
* dict *d 要删除的字典
* return 返回 成功或失败
*/
void dictRelease(dict *d);
/**
* 在字典中查找key并返回找到的entry(会遍历 ht[0]和ht[1])
* dict *d 被查找的字典
* const void *key 要查找的key
* return 返回 找到的entry
*/
dictEntry *dictFind(dict *d, const void *key);
/**
* 查找并返回指定key对应的val
* dict *d 被查找的字典
* const void *key 要查找的key
* return 返回 相应key对应的val
*/
void *dictFetchValue(dict *d, const void *key);
/**
* 根据dict生成该字典的指纹信息
* dict *d 生成的字典
* return 返回 生成的指纹信息
*/
long long dictFingerprint(dict *d);
/**
* 创建字典迭代器
* dict *d 字典
* return 返回 字典迭代器结构
*/
dictIterator *dictGetIterator(dict *d);
/**
* 创建安全字典迭代器
* dict *d 字典
* return 返回 创建安全字典迭代器
*/
dictIterator *dictGetSafeIterator(dict *d);
/**
* 根据迭代器结构对字典进行迭代,获取迭代器指向的当前entry结构(安全迭代将字典的iterators++结束的时候在减去,非安全则设置字典的指纹信息)
* dictIterator *iter 字典迭代器
* return 返回当前dictEntry结构
*/
dictEntry *dictNext(dictIterator *iter);
/**
* 释放字典迭代器对象
* dictIterator *iter 字典迭代器
* return void
*/
void dictReleaseIterator(dictIterator *iter);
/**
* 根据字典随机获取一个key
* dict *d 字典
* return 随机返回一个 entry
*/
dictEntry *dictGetRandomKey(dict *d);
/**
* 遍历字典每个元素,使用 Pieter Noordhuis 的一个算法
* dict *d 字典
* unsigned long v 游标值
* dictScanFunction *fn 处理每个元素的回调函数
* void *privdata 处理每个元素的回调函数的值
* return 返回新的游标值
*/
unsigned long dictScan(dict *d, unsigned long v, dictScanFunction *fn, void *privdata);
/**
* 判断字典是否需要进行扩展操作
* dict *d 需要判断的字典
* return 返回状态
*/
static int _dictExpandIfNeeded(dict *d);
/**
* 根据当前节点数量,计算hashtable扩展桶的数量,最大扩展桶的数量为 LONG_MAX 最小为 DICT_HT_INITIAL_SIZE,设置桶的个数为2的N次方大于节点数的最小值
* unsigned long size 当前节点数
* return 返回新计算的桶的大小
*/
static unsigned long _dictNextPower(unsigned long size);
/**
* 查找指定key存在于哪个桶里
* dict *d 需要判断的字典
* void *key 需要查找的key
* return 返回 桶的索引
*/
static int _dictKeyIndex(dict *d, const void *key);
/**
* 将字典清空重置
* dict *d 需要清空的字典
* void(callback)(void*)
* return 返回 桶的索引
*/
void dictEmpty(dict *d, void(callback)(void*));
测试方法和代码:
为了减少依赖,需要稍微修改一点点代码来完成测试,单独运行dict.c
删除如下代码:
#include "redisassert.h"
在删除的代码出加入以下宏定义:
#define assert(c) (c)
在页面底部加入如下main的测试代码:
//定义一组字典回调函数
unsigned int test_hash(const void *key) {
return dictGenHashFunction(key, strlen((char *)key));
}
/*
void *test_keyDup(void *privdata, const void *key);
void *test_valDup(void *privdata, const void *obj);
int test_keyCompare(void *privdata, const void *key1, const void *key2);
void test_keyDestructor(void *privdata, void *key);
void test_valDestructor(void *privdata, void *obj);
*/
#define htLengthOut(info, d) ( \
printf("%s: ht[0].size:%d\tht[1].size:%d\tht[0].used:%d\tht[1].used:%d\n", (info), (d)->ht[0].size, (d)->ht[1].size, (d)->ht[0].used, (d)->ht[1].used)\
)
int main (void) {
dict *d;
dictEntry *de;
dictType type = {
test_hash,
NULL,
NULL,
NULL,
NULL
};
dictIterator *di;
d = dictCreate(&type, NULL);
htLengthOut(" empty dict", d);
//向字典中加入元素,并触发rehash进行扩展
dictAdd(d, "logbird", "123234123");
dictAdd(d, "logbird2", "23434123");
dictAdd(d, "logbird3", "123452453");
dictAdd(d, "logbird4", "1345234523");
dictAdd(d, "logbird5", "1457623");
dictAdd(d, "logbird6", "12345234523");
htLengthOut("start rehash", d);
//进行5毫秒的rehash处理
dictRehashMilliseconds(d, 5);
htLengthOut("after rehash", d);
//随机获取一条数据
srand(timeInMilliseconds());
de = dictGetRandomKey(d);
printf("Random KEY: %s, VAL: %s\n", dictGetKey(de), dictGetVal(de));
//获取某个key的val
printf("KEY: 'logbird' VALUE: %s\n", (char *)dictFetchValue(d, "logbird"));
//删除一个key
dictDeleteNoFree(d, "logbird");
htLengthOut("one key removed", d);
//遍历字典所有数据
di = dictGetIterator(d);
printf("---------------------------Iterator Start----------------------\n");
while ((de = dictNext(di))) {
do {
printf("KEY: %s VALUE: %s\n", dictGetKey(de), dictGetVal(de));
} while((de = de->next));
}
dictReleaseIterator(di);
//释放字典
dictRelease(d);
}
最后执行以下代码进行编译执行:
gcc zmalloc.c sds.c dict.c
./a.out