本文为作者原创,转载请注明出处: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