redis dict.h源码分析
2012-03-06 19:54
375 查看
/* Hash Tables Implementation. * * This file implements in memory hash tables with insert/del/replace/find/ * get-random-element operations. Hash tables will auto resize if needed * tables of power of two in size are used, collisions are handled by * chaining. */ #ifndef __DICT_H #define __DICT_H #define DICT_OK 0 #define DICT_ERR 1 /* Unused arguments generate annoying warnings... */ #define DICT_NOTUSED(V) ((void) V) /* * dict 是主要是由 struct dictht 的 哈唏表构成的, 之所以定义成长度为2的( dictht ht[2] ) 哈唏表数组, * 是因为 redis 采用渐进的 rehash,即当需要 rehash 时,每次像 hset,hget 等操作前,先执行N 步 rehash. * 这样就把原来一次性的 rehash过程拆散到进行, 防止一次性 rehash 期间 redis 服务能力大幅下降. 这种渐进的 rehash * 需要一个额外的 struct dictht 结构来保存. struct dictht 主要是由一个 struct dictEntry 指针数组组成的, hash 表的冲突是通过链表法来解决的. 在Redis中,hash表被称为字典(dictionary),采用了典型的链式解决冲突方法,即:当有多个key/value的key的映射值(每 对key/value保存之前,会先通过类似HASH(key) MOD N的方法计算一个值,以便确定其对应的hash table的位置)相同时,会将 这些value以单链表的形式保存;同时为了控制哈希表所占内存大小,redis采用了双哈希表(ht[2])结构,并逐步扩大哈希表容量(桶 的大小)的策略,即:刚开始,哈希表ht[0]的桶大小为4,哈希表ht[1]的桶大小为0,待冲突严重(redis有一定的判断条件)后, ht[1]中桶的大小增为ht[0]的两倍,并逐步(注意这个词:”逐步”)将哈希表ht[0]中元素迁移(称为“再次Hash”)到ht[1], 待ht[0]中所有元素全部迁移到ht[1]后,再将ht[1]交给ht[0](这里仅仅是C语言地址交换),之后重复上面的过程。 */ typedef struct dictEntry { void *key; void *val; struct dictEntry *next;//chaining to avoid hash conflict } dictEntry; //每种hash table的类型,里面既有成员函数,又有成员变量,完全是模拟的C++类,注意, //每个函数带有的privdata均为预留参数 typedef struct dictType { unsigned int (*hashFunction)(const void *key); void *(*keyDup)(void *privdata, const void *key); void *(*valDup)(void *privdata, const void *obj); int (*keyCompare)(void *privdata, const void *key1, const void *key2); void (*keyDestructor)(void *privdata, void *key); void (*valDestructor)(void *privdata, void *obj); } dictType; /* This is our hash table structure. Every dictionary has two of this as we * implement incremental rehashing, for the old to the new table. */ typedef struct dictht { dictEntry **table;//hash 表中的数据,以key/value形式,通过单链表保存 //a pointer to dictEntry*, not an array of dictEntry*. //dictEntry can perform chaining work unsigned long size;//桶个数 unsigned long sizemask; //size - 1, //hashresult & sizemask = hashresult % sizemask, result is 0 ~ size - 1 unsigned long used; //实际保存的元素数entry num } dictht; /* * lazy rehashing:在每次对dict进行操作的时候执行一个slot的rehash * active rehashing:每100ms里面使用1ms时间进行rehash。 */ typedef struct dict { dictType *type; void *privdata; dictht ht[2]; int rehashidx; /* rehashidx是下一个需要rehash的项在ht[0]中的索引 rehashing not in progress if rehashidx == -1 */ int iterators; /* number of iterators currently running 记录当前dict中的迭代器数,主要是为了避免在有迭代器时rehash,在有迭代 器时rehash可能会造成值的丢失或重复,*/ } dict; /* If safe is set to 1 this is a safe iteartor, that means, you can call * dictAdd, dictFind, and other functions against the dictionary even while * iterating. Otherwise it is a non safe iterator, and only dictNext() * should be called while iterating. */ typedef struct dictIterator { dict *d; int table;//所在的table int index;//在两个table中的index,可能大于d.table[0]的size int safe; dictEntry *entry, *nextEntry; } dictIterator; /* This is the initial size of every hash table */ #define DICT_HT_INITIAL_SIZE 4 /* ------------------------------- Macros ------------------------------------*/ #define dictFreeEntryVal(d, entry) \ if ((d)->type->valDestructor) \ (d)->type->valDestructor((d)->privdata, (entry)->val) #define dictSetHashVal(d, entry, _val_) do { \ if ((d)->type->valDup) \ entry->val = (d)->type->valDup((d)->privdata, _val_); \ else \ entry->val = (_val_); \ } while(0) #define dictFreeEntryKey(d, entry) \ if ((d)->type->keyDestructor) \ (d)->type->keyDestructor((d)->privdata, (entry)->key) #define dictSetHashKey(d, entry, _key_) do { \ if ((d)->type->keyDup) \ entry->key = (d)->type->keyDup((d)->privdata, _key_); \ else \ entry->key = (_key_); \ } while(0) #define dictCompareHashKeys(d, key1, key2) \ (((d)->type->keyCompare) ? \ (d)->type->keyCompare((d)->privdata, key1, key2) : \ (key1) == (key2)) #define dictHashKey(d, key) (d)->type->hashFunction(key) #define dictGetEntryKey(he) ((he)->key) #define dictGetEntryVal(he) ((he)->val) #define dictSlots(d) ((d)->ht[0].size+(d)->ht[1].size) #define dictSize(d) ((d)->ht[0].used+(d)->ht[1].used) #define dictIsRehashing(ht) ((ht)->rehashidx != -1) /* API */ dict *dictCreate(dictType *type, void *privDataPtr); int dictExpand(dict *d, unsigned long size); int dictAdd(dict *d, void *key, void *val); int dictReplace(dict *d, void *key, void *val); int dictDelete(dict *d, const void *key); int dictDeleteNoFree(dict *d, const void *key); void dictRelease(dict *d); dictEntry * dictFind(dict *d, const void *key); void *dictFetchValue(dict *d, const void *key); int dictResize(dict *d); dictIterator *dictGetIterator(dict *d); dictIterator *dictGetSafeIterator(dict *d); dictEntry *dictNext(dictIterator *iter); void dictReleaseIterator(dictIterator *iter); dictEntry *dictGetRandomKey(dict *d); void dictPrintStats(dict *d); unsigned int dictGenHashFunction(const unsigned char *buf, int len); unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len); void dictEmpty(dict *d); void dictEnableResize(void); void dictDisableResize(void); int dictRehash(dict *d, int n); int dictRehashMilliseconds(dict *d, int ms); /* Hash table types */ extern dictType dictTypeHeapStringCopyKey; extern dictType dictTypeHeapStrings; extern dictType dictTypeHeapStringCopyKeyValue; #endif /* __DICT_H */
相关文章推荐
- Redis源码分析(dict)
- redis源码分析 dict字典的实现和内部应用
- Redis源码分析---字典dict
- 【redis源码分析】字典---dict
- redis源码分析-dict(字典结构)
- Redis源码分析(dict)
- Redis 源码分析:dict.c 和 dict.h
- redis dict.c源码分析
- Redis源码分析(dict)
- redis源码分析(2)----字典dict
- Redis 源码分析:dict.c 和 dict.h
- Redis源码分析系列七:initServer下
- redis源码分析教程之压缩链表ziplist详解
- 基于Redis实现分布式锁,Redisson使用及源码分析
- Redis源码分析系列十:acceptTcpHandler
- Redis的字典(dict)rehash过程源码解析
- 结合redis设计与实现的redis源码学习-4-dict(字典)
- Redis源码分析系列
- redis源码分析(3)sds
- Redis的字典(dict)rehash过程源码解析