Exemplo n.º 1
0
/* Low level add. This function adds the entry but instead of setting
 * a value returns the dictEntry structure to the user, that will make
 * sure to fill the value field as he wishes.
 *
 * This function is also directly exposed to the user API to be called
 * mainly in order to store non-pointers inside the hash value, example:
 *
 * entry = dictAddRaw(dict,mykey);
 * if (entry != NULL) dictSetSignedIntegerVal(entry,1000);
 *
 * Return values:
 *
 * If key already exists NULL is returned.
 * If key was added, the hash entry is returned to be manipulated by the caller.
 */
dictEntry *dictAddRaw(dict *d, void *key)
{
    int index;
    dictEntry *entry;
    dictht *ht;

    if (dictIsRehashing(d)) _dictRehashStep(d);

    /* Get the index of the new element, or -1 if
     * the element already exists. */
    if ((index = _dictKeyIndex(d, key)) == -1)
        return NULL;

    /* Allocate the memory and store the new entry */
    ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
    entry = zmalloc(sizeof(*entry));
    entry->next = ht->table[index];
    ht->table[index] = entry;
    ht->used++;

    /* Set the hash entry fields. */
    //使用dictType中的keyDup函数
    dictSetKey(d, entry, key);
    return entry;
}
Exemplo n.º 2
0
/* Add an element to the target hash table */
int dictAdd(dict *d, void *key, void *val)
{
    int index;
    dictEntry *entry;
    dictht *ht;

    if (dictIsRehashing(d)) _dictRehashStep(d);

    /* Get the index of the new element, or -1 if
     * the element already exists. */
    if ((index = _dictKeyIndex(d, key)) == -1)
        return DICT_ERR;

    /* Allocates the memory and stores key */
    ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
    entry = zmalloc(sizeof(*entry));
    entry->next = ht->table[index];
    ht->table[index] = entry;
    ht->used++;

    /* Set the hash entry fields. */
    dictSetHashKey(d, entry, key);
    dictSetHashVal(d, entry, val);
    return DICT_OK;
}
Exemplo n.º 3
0
/* 从字典中查找给定 key 
 *
 * 查找过程是典型的 separate chaining find 操作
 * 具体参见:http://en.wikipedia.org/wiki/Hash_table#Separate_chaining
 */
dictEntry *dictFind(dict *d, const void *key)
{
    dictEntry *he;
    unsigned int h, idx, table;

    // 哈希表为空,直接返回 NULL
    if (d->ht[0].size == 0) return NULL; /* We don't have a table at all */

    // 检查字典(的哈希表)能否执行 rehash 操作
    // 如果可以的话,执行平摊 rehash 操作
    if (dictIsRehashing(d)) _dictRehashStep(d);

    // 查找 
    h = dictHashKey(d, key);                     // 计算哈希值
    for (table = 0; table <= 1; table++) {       // 遍历两个哈希表
        idx = h & d->ht[table].sizemask;         // 计算地址
        he = d->ht[table].table[idx];            // he 指向链表头
        while(he) {                              // 遍历链查找 key
            if (dictCompareKeys(d, key, he->key))
                return he;
            he = he->next;
        }

        if (!dictIsRehashing(d)) return NULL;
    }

    return NULL;
}
Exemplo n.º 4
0
/* 添加元素的底层实现函数(由 dictAdd 调用)
 * 
 * 新元素的添加操作被分为两步:
 * 1) 创建节点并设置节点的 key ,然后返回节点
 * 2) 设置节点的值
 * 这个函数执行第一步,第二步由函数 dictSetVal 进行
 * 
 * Args:
 *  d 字典
 *  key 新节点的关键字
 *
 * Returns:
 *  NULL 关键字已经存在
 *  entry 设置了关键字的新节点,返回给调用者进行进一步的处理
 */
dictEntry *dictAddRaw(dict *d, void *key)
{
    int index;
    dictEntry *entry;
    dictht *ht;

    // 检查字典(的哈希表)能否执行 rehash 操作
    // 如果可以的话,执行平摊 rehash 操作
    if (dictIsRehashing(d)) _dictRehashStep(d);

    // 计算 key 的 index 值
    // 如果 key 已经存在,_dictKeyIndex 返回 -1 
    if ((index = _dictKeyIndex(d, key)) == -1)
        return NULL;

    // 如果字典正在进行 rehash ,那么将新元素添加到 1 号哈希表,
    // 否则,使用 0 号哈希表
    ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];

    entry = zmalloc(sizeof(*entry));    // 为新节点分配内存
    entry->next = ht->table[index];     // 调整节点的 next 指针
    ht->table[index] = entry;           // 然后将新节点设为链头
    ht->used++;                         // 更新正在使用的节点数量

    // 设置节点的 key 域
    dictSetKey(d, entry, key);

    return entry;   // 返回新节点
}
Exemplo n.º 5
0
//这个函数也可以作为向外部提供的API使用,外部用户可以添加一个键值不为void*类型的值
//它向字典中添加一个key值并且返回新创建的 entry对象,这个对象交给调用者操作
dictEntry *dictAddRaw(dict *d, void *key)
{
    int index;
    dictEntry *entry;
    dictht *ht;

    if (dictIsRehashing(d)) _dictRehashStep(d);

    /* Get the index of the new element, or -1 if
     * the element already exists. */
    //获取对应key的bucket索引
    if ((index = _dictKeyIndex(d, key)) == -1)
        return NULL;

    /* Allocate the memory and store the new entry */
    //如果当前在执行rehash,说明需要将ht[0]上的entry转移到ht[1]上,并且尚未执行结束
    //这时候就需要加入到ht[1]中,否则加入到ht[0]中
    ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
    entry = zmalloc(sizeof(*entry));
    //加入到链表的表头
    entry->next = ht->table[index];
    ht->table[index] = entry;
    ht->used++;

    /* Set the hash entry fields. */
    //最后设置该项的key
    dictSetKey(d, entry, key);
    return entry;
}
Exemplo n.º 6
0
/* 删除指定元素的底层实现代码
 *
 * Args:
 *  d
 *  key
 *  nofree 指示是否释放被删除元素的键和值
 *
 * Returns:
 *  DICT_ERR 字典为空,删除失败
 *  DICT_OK 删除成功
 */
static int dictGenericDelete(dict *d, const void *key, int nofree)
{
    unsigned int h, idx;
    dictEntry *he, *prevHe;
    int table;

    // 字典为空,删除失败
    if (d->ht[0].size == 0)
        return DICT_ERR;

    // 平摊 rehash
    if (dictIsRehashing(d))
        _dictRehashStep(d);

    // 哈希值
    h = dictHashKey(d, key);

    // 遍历
    for (table = 0; table <= 1; table++) {
        idx = h & d->ht[table].sizemask;    // 地址索引
        he = d->ht[table].table[idx];       // 表头节点
        prevHe = NULL;
        while(he) {
            if (dictCompareKeys(d, key, he->key)) {
                /* Unlink the element from the list */
                if (prevHe)
                    prevHe->next = he->next;
                else
                    d->ht[table].table[idx] = he->next;

                if (!nofree) {
                    dictFreeKey(d, he);
                    dictFreeVal(d, he);
                }

                zfree(he);
                d->ht[table].used--;

                return DICT_OK;
            }
            // 推进指针
            prevHe = he;
            he = he->next;
        }
        if (!dictIsRehashing(d)) break;
    }

    return DICT_ERR; /* not found */
}
Exemplo n.º 7
0
/* Expand or create the hashtable */
int dictExpand(dict *d, unsigned long size)
{
    dictht n; /* the new hashtable */
    unsigned long realsize = _dictNextPower(size);

    /* the size is invalid if it is smaller than the number of
     * elements already inside the hashtable */
    if (dictIsRehashing(d) || d->ht[0].used > size)
        return DICT_ERR;

    /* Allocate the new hashtable and initialize all pointers to NULL */
    n.size = realsize;
    n.sizemask = realsize-1;
    n.table = zcalloc(1, realsize*sizeof(dictEntry*));
    n.used = 0;

    /* Is this the first initialization? If so it's not really a rehashing
     * we just set the first hash table so that it can accept keys. */
    if (d->ht[0].table == NULL) {
        d->ht[0] = n;
        return DICT_OK;
    }

    /* Prepare a second hash table for incremental rehashing */
    d->ht[1] = n;
    d->rehashidx = 0;
    return DICT_OK;
}
Exemplo n.º 8
0
dictEntry *dictNext(dictIterator *iter)
{
    while (1) {
        if (iter->entry == NULL) {
            dictht *ht = &iter->d->ht[iter->table];
            if (iter->safe && iter->index == -1 && iter->table == 0)
                iter->d->iterators++;
            iter->index++;
            if (iter->index >= (signed) ht->size) {
                if (dictIsRehashing(iter->d) && iter->table == 0) {
                    iter->table++;
                    iter->index = 0;
                    ht = &iter->d->ht[1];
                } else {
                    break;
                }
            }
            iter->entry = ht->table[iter->index];
        } else {
            iter->entry = iter->nextEntry;
        }
        if (iter->entry) {
            /* We need to save the 'next' here, the iterator user
             * may delete the entry we are returning. */
            iter->nextEntry = iter->entry->next;
            return iter->entry;
        }
    }
    return NULL;
}
Exemplo n.º 9
0
/*************************************************************
* Function		:	RehashStep
* Author 		:       bulldozer.ma
* Date 		 	:       2015-11-01
* Input 		:       dict *pHeader
* Output 		:       N/A
* Return 		:       void 
* Other 		:       N/A
* Description		:      	RehashStep 
**************************************************************/
static void RehashStep(dict *pHeader) 
{
    if (dictIsRehashing(pHeader))
	{
		Rehash(pHeader,1);
	}
}
Exemplo n.º 10
0
/* 对字典进行扩展
 *
 * 这个函数完成以下两个工作的其中之一:
 * 1) 如果字典的 0 号哈希表不存在,那么创建它
 * 2) 如果字典的 0 号哈希表存在,那么创建字典的 1 号哈希表
 *
 * 这个函数的作用,对于第一件任务来说,是创建字典(的哈希表)。
 * 而对于第二个任务来说,则是扩展字典(的哈希表)。
 */
int dictExpand(dict *d, unsigned long size)
{
    // 一般调用函数已经进行了检查,为了安全起见再次对参数进行检查
    if (dictIsRehashing(d) || d->ht[0].used > size)
        return DICT_ERR;

    // 计算哈希表的(真正)大小
    unsigned long realsize = _dictNextPower(size);

    // 创建新哈希表
    dictht n; 
    n.size = realsize;
    n.sizemask = realsize-1;
    n.table = zcalloc(realsize*sizeof(dictEntry*));
    n.used = 0;

    // 字典的 0 号哈希表是否已经初始化?
    // 如果没有的话,我们将新建哈希表作为字典的 0 号哈希表
    if (d->ht[0].table == NULL) {
        d->ht[0] = n;
    } else {
    // 否则,将新建哈希表作为字典的 1 号哈希表,并将它用于 rehash
        d->ht[1] = n;
        d->rehashidx = 0;
    }

    return DICT_OK;
}
Exemplo n.º 11
0
//扩展字典,在检查到需要扩展的时候,这里包含了检测的过程
static int _dictExpandIfNeeded(dict *d)
{
    /* Incremental rehashing already in progress. Return. */
    //如果正在执行rehash操作,直接返回
    if (dictIsRehashing(d)) return DICT_OK;

    /* If the hash table is empty expand it to the initial size. */
    //第一次添加元素,执行扩展
    if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);

    /* If we reached the 1:1 ratio, and we are allowed to resize the hash
     * table (global setting) or we should avoid it but the ratio between
     * elements/buckets is over the "safe" threshold, we resize doubling
     * the number of buckets. */
    //如果设置了resize标记,那么在USED/BUCKET的比率大于1的时候就会执行扩展
    //如果没有设置该标志,在该比率超过dict_force_resize_ratio的时候再进行扩展
    if (d->ht[0].used >= d->ht[0].size &&
        (dict_can_resize ||
         d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))
    {
        //扩展的结果是bucket的数目增大一倍
        return dictExpand(d, ((d->ht[0].size > d->ht[0].used) ?
                                    d->ht[0].size : d->ht[0].used)*2);
    }
    return DICT_OK;
}
Exemplo n.º 12
0
void dictPrintStats(dict *d) {
    _dictPrintStatsHt(&d->ht[0]);
    if (dictIsRehashing(d)) {
        printf("-- Rehashing into ht[1]:\n");
        _dictPrintStatsHt(&d->ht[1]);
    }
}
Exemplo n.º 13
0
/* Returns the index of a free slot that can be populated with
 * an hash entry for the given 'key'.
 * If the key already exists, -1 is returned.
 *
 * Note that if we are in the process of rehashing the hash table, the
 * index is always returned in the context of the second (new) hash table. */
static int _dictKeyIndex(dict *d, const void *key)
{
    unsigned int h, idx, table;
    dictEntry *he;

    /* Expand the hash table if needed */
    //在添加之前检查是否需要扩展
    if (_dictExpandIfNeeded(d) == DICT_ERR)
        return -1;
    /* Compute the key hash value */
    //得到对应的bucket索引值
    h = dictHashKey(d, key);
    //这里之所以需要遍历两个哈希表,是因为有rehash的需求
    //必须保证在字典中key是唯一的,并且是不变的
    for (table = 0; table <= 1; table++) {
        idx = h & d->ht[table].sizemask;
        /* Search if this slot does not already contain the given key */
        he = d->ht[table].table[idx];
        //如果这个bucket中已经存在相同的key,直接返回错误
        while(he) {
            if (dictCompareKeys(d, key, he->key))
                return -1;
            he = he->next;
        }
        //如果当前未执行rehash操作(-1),说明所有的key-value都存放在ht[0]中
        //所以这里避免了第二次的遍历
        if (!dictIsRehashing(d)) break;
    }
    return idx;
}
Exemplo n.º 14
0
//该函数会在真正创建哈希表或者扩展哈希表的时候被调用
int dictExpand(dict *d, unsigned long size)
{
    dictht n; /* the new hash table */
    //新的哈希表的bucket数目是大于当前used entry的数目的最小的2的指数
    unsigned long realsize = _dictNextPower(size);

    /* the size is invalid if it is smaller than the number of
     * elements already inside the hash table */
    //保证该字典未进行rehash,并且保证USED/BUCKETS的比率小于1
    if (dictIsRehashing(d) || d->ht[0].used > size)
        return DICT_ERR;

    /* Allocate the new hash table and initialize all pointers to NULL */
    //分配并初始化一个新的哈希表
    n.size = realsize;
    n.sizemask = realsize-1;
    n.table = zcalloc(realsize*sizeof(dictEntry*));
    n.used = 0;

    /* Is this the first initialization? If so it's not really a rehashing
     * we just set the first hash table so that it can accept keys. */
    //既然不是在rehash状态中,那么当前使用的哈希表应该是ht[0],如果它为NULL
    //说明这是在第一次分配该哈希表,所以将它保存在ht[0]中
    if (d->ht[0].table == NULL) {
        d->ht[0] = n;
        return DICT_OK;
    }

    /* Prepare a second hash table for incremental rehashing */
    //否则将新分配的哈希表保存在ht[1]中,因为不在rehash,所以当前ht[1]为空
    //并且标记rehash标志,在接下来的哈希表操作中会进行rehash操作
    d->ht[1] = n;
    d->rehashidx = 0;
    return DICT_OK;
}
Exemplo n.º 15
0
/* Resize the table to the minimal size that contains all the elements,
 * but with the invariant of a USER/BUCKETS ratio near to <= 1 */
int dictResize(dict *d)
{
    int minimal;

    if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR;
    minimal = d->ht[0].used;
    if (minimal < DICT_HT_INITIAL_SIZE)
        minimal = DICT_HT_INITIAL_SIZE;
    return dictExpand(d, minimal);
}
Exemplo n.º 16
0
dictEntry *dictFind(dict *d, const void *key)
{
    dictEntry *he;
    unsigned int h, idx, table;

    if (d->ht[0].size == 0) return NULL; /* We don't have a table at all */
    if (dictIsRehashing(d)) _dictRehashStep(d);
    h = dictHashKey(d, key);
    for (table = 0; table <= 1; table++) {
        idx = h & d->ht[table].sizemask;
        he = d->ht[table].table[idx];
        while(he) {
            if (dictCompareHashKeys(d, key, he->key))
                return he;
            he = he->next;
        }
        if (!dictIsRehashing(d)) return NULL;
    }
    return NULL;
}
Exemplo n.º 17
0
/* Return a random entry from the hash table. Useful to
 * implement randomized algorithms */
dictEntry *dictGetRandomKey(dict *d)
{
    dictEntry *he, *orighe;
    unsigned int h;
    int listlen, listele;

    if (dictSize(d) == 0) return NULL;
    //该操作也会引起rehash,step by step...
    if (dictIsRehashing(d)) _dictRehashStep(d);
    if (dictIsRehashing(d)) {
        //如果正在执行rehash,则将两个哈希表都考虑在随机的方位内,找到bucket链表
        do {
            h = random() % (d->ht[0].size+d->ht[1].size);
            he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] :
                                      d->ht[0].table[h];
        } while(he == NULL);
    } else {
        //否则只从第一个哈希表中随机找到一个bucket
        do {
            h = random() & d->ht[0].sizemask;
            he = d->ht[0].table[h];
        } while(he == NULL);
    }

    /* Now we found a non empty bucket, but it is a linked
     * list and we need to get a random element from the list.
     * The only sane way to do so is counting the elements and
     * select a random index. */
    listlen = 0;
    orighe = he;
    //首先得到这个链表的长度,然后再随机的走k步...
    //这样最科学撒...
    while(he) {
        he = he->next;
        listlen++;
    }
    listele = random() % listlen;
    he = orighe;
    while(listele--) he = he->next;
    return he;
}
Exemplo n.º 18
0
/* Expand the hash table if needed */
static int _dictExpandIfNeeded(dict *d)
{
    /* If the hash table is empty expand it to the intial size,
     * if the table is "full" dobule its size. */
    if (dictIsRehashing(d)) return DICT_OK;
    if (d->ht[0].size == 0)
        return dictExpand(d, DICT_HT_INITIAL_SIZE);
    if (d->ht[0].used >= d->ht[0].size && dict_can_resize)
        return dictExpand(d, ((d->ht[0].size > d->ht[0].used) ?
                                    d->ht[0].size : d->ht[0].used)*2);
    return DICT_OK;
}
Exemplo n.º 19
0
/* 字典(的哈希表) rehash 函数
 *
 * Args:
 *  d
 *  n 要执行 rehash 的元素数量
 *
 * Returns:
 *  0 所有元素 rehash 完毕
 *  1 还有元素没有 rehash
 */
int dictRehash(dict *d, int n) {
    if (!dictIsRehashing(d))
        return 0;

    while(n--) {
        dictEntry *de, *nextde;

        // 0 号哈希表的所有元素 rehash 完毕?
        if (d->ht[0].used == 0) {
            zfree(d->ht[0].table);  // 替换 1 号为 0 号
            d->ht[0] = d->ht[1];

            _dictReset(&d->ht[1]);  // 重置 1 号哈希表

            d->rehashidx = -1;      // 重置 rehash flag

            return 0;
        }

        /* Note that rehashidx can't overflow as we are sure there are more
         * elements because ht[0].used != 0 */
        assert(d->ht[0].size > (unsigned)d->rehashidx);

        // 略过所有空链
        while(d->ht[0].table[d->rehashidx] == NULL)
            d->rehashidx++;

        // 指向链头
        de = d->ht[0].table[d->rehashidx];
        // 将链表内的所有节点移动到 1 号哈希表
        while(de) {
            unsigned int h;

            nextde = de->next;

            // 计算新的地址(用于 1 号哈希表)
            h = dictHashKey(d, de->key) & d->ht[1].sizemask;

            de->next = d->ht[1].table[h];   // 更新 next 指针
            d->ht[1].table[h] = de;         // 移动
            d->ht[0].used--;                // 更新 0 号表计算器
            d->ht[1].used++;                // 更新 1 号表计算器

            de = nextde;
        }

        d->ht[0].table[d->rehashidx] = NULL;    // 清空链头
        d->rehashidx++; // 更新索引
    }

    return 1;
}
Exemplo n.º 20
0
/* Resize the table to the minimal size that contains all the elements,
 * but with the invariant of a USED/BUCKETS ratio near to <= 1 */
int dictResize(dict *d)
{
    int minimal;

    //在未设置resize标记和rehash进行中的字典不能进行扩展
    if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR;
    //扩展之后的bucket数目将大于当前哈希表中的entry的总数,这样可以使USED/BUCKETS的
    //比率小于1,尽量达到O(1)查询的效率
    minimal = d->ht[0].used;
    if (minimal < DICT_HT_INITIAL_SIZE)
        minimal = DICT_HT_INITIAL_SIZE;
    return dictExpand(d, minimal);
}
Exemplo n.º 21
0
/* Return a random entry from the hash table. Useful to
 * implement randomized algorithms */
dictEntry *dictGetRandomKey(dict *d)
{
    dictEntry *he, *orighe;
    unsigned int h;
    int listlen, listele;

    if (dictSize(d) == 0) return NULL;
    if (dictIsRehashing(d)) _dictRehashStep(d);
    if (dictIsRehashing(d)) {
        do {
            h = random() % (d->ht[0].size+d->ht[1].size);
            he = (h >= d->ht[0].size) ? d->ht[1].table[h - d->ht[0].size] :
                                      d->ht[0].table[h];
        } while(he == NULL);
    } else {
        do {
            h = random() & d->ht[0].sizemask;
            he = d->ht[0].table[h];
        } while(he == NULL);
    }

    /* Now we found a non empty bucket, but it is a linked
     * list and we need to get a random element from the list.
     * The only sane way to do so is counting the elements and
     * select a random index. */
    listlen = 0;
    orighe = he;
    while(he) {
        he = he->next;
        listlen++;
    }

    listele = random() % listlen;
    he = orighe;
    while(listele--) he = he->next;
    return he;
}
Exemplo n.º 22
0
/*************************************************************
* Function		:	dictShow
* Author 		:       bulldozer.ma
* Date			:       2015-11-01
* Input 		:       dict *pHeader
* Output		:       N/A
* Return		:       int 
* Other 		:       N/A
* Description 		:      	show all
**************************************************************/
int dictShow(dict *pHeader)
{
	int iRet = DICT_ERROR;
	if (NULL == pHeader)
	{
		return DICT_ERROR;
	}
	
	iRet = ShowValue(pHeader->ht[0]);
	if (dictIsRehashing(pHeader))
	{
		iRet = ShowValue(pHeader->ht[1]);
	}
	return iRet;
}
Exemplo n.º 23
0
/*************************************************************
* Function		:	ExpandIfNeeded
* Author 		:       bulldozer.ma
* Date 			:       2015-11-01
* Input 		:       dict *pHeader
* Output 		:       N/A
* Return 		:       int 
* Other 		:       N/A
* Description 		:      	ExpandIfNeeded 
**************************************************************/
static int ExpandIfNeeded(dict *pHeader)
{
	if (NULL == pHeader || dictIsRehashing(pHeader))
	{
		return DICT_ERROR;
	}
	unsigned int uiUsed = 0, uiSize = 0;
	uiSize = pHeader->ht[0]->size;
	uiUsed = pHeader->ht[0]->used;
	if (uiUsed > uiSize &&  1 <= uiUsed / uiSize)
	{
		return dictExpand(pHeader, pHeader->ht[1]->size);
	}
	return DICT_ERROR;
}
Exemplo n.º 24
0
//执行一次rehash操作,一般在检查到该字典的rehash标记被设置之后调用该函数
//这里的参数n表示至少执行多少bucket的移动(reahash),每次移动从rehashidx开始
int dictRehash(dict *d, int n) {
    if (!dictIsRehashing(d)) return 0;

    while(n--) {
        dictEntry *de, *nextde;

        /* Check if we already rehashed the whole table... */
        //如果已经全部移动了,说明这一次rehash操作执行完成了
        //释放ht[0],然后重新将移动之后的ht[1]替换,这样保证不再rehash操作
        //的时候都是使用ht[0]保存新添加的元素
        if (d->ht[0].used == 0) {
            zfree(d->ht[0].table);
            //复制&重置
            d->ht[0] = d->ht[1];
            _dictReset(&d->ht[1]);
            d->rehashidx = -1;
            return 0;
        }

        /* Note that rehashidx can't overflow as we are sure there are more
         * elements because ht[0].used != 0 */
        //在rehash过程中,rehashidx保存的是上一次移动的bucket的下标
        //这样在下一次移动的时候从rehashidx开始
        assert(d->ht[0].size > (unsigned)d->rehashidx);
        //跳过没有任何元素的bucket
        while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++;
        de = d->ht[0].table[d->rehashidx];
        /* Move all the keys in this bucket from the old to the new hash HT */
        //将旧哈希表ht[0]中的每一个bucket上的每一个entry都移动到ht[1]上
        //因为同一个entry在两个表定位的bucket不同,所以需要重新hash,然后添加到bucket
        //中entry链表的表头
        while(de) {
            unsigned int h;

            nextde = de->next;
            /* Get the index in the new hash table */
            h = dictHashKey(d, de->key) & d->ht[1].sizemask;
            de->next = d->ht[1].table[h];
            d->ht[1].table[h] = de;
            d->ht[0].used--;
            d->ht[1].used++;
            de = nextde;
        }
        d->ht[0].table[d->rehashidx] = NULL;
        d->rehashidx++;
    }
    return 1;
}
Exemplo n.º 25
0
Arquivo: lrw_dict.c Projeto: fizx/sit
void
lrw_dict_put(LRWDict *d, const Term *key, const void *value) {
	dictEntry *entry = dictFind(d->dict, key);
  //   pstring *t = term_to_s(key);
  // printf("adding %.*s to size %d\n", t->len, t->val,dictSize(d->dict));
	if(entry == NULL) {
		if(dictSize(d->dict) >= d->capacity) {
      _truncate(d);
		}
		entry = dictAddRaw(d->dict, (void *) key);
		if(!entry && dictIsRehashing(d->dict)) {
			entry = dictFind(d->dict, key);
		}
		assert(entry);
	}
	dictSetVal(d->dict, entry, (void *) value);
	_bump(d, entry->key);
}
Exemplo n.º 26
0
/* 迭代器的推进函数 */
dictEntry *dictNext(dictIterator *iter)
{
    while (1) {
        // 如果迭代器是新的(未使用过),那么初始化新迭代器
        if (iter->entry == NULL) {
            dictht *ht = &iter->d->ht[iter->table];

            // 在第一次迭代的时候增加字典 iterators 属性的计数
            if (iter->safe && iter->index == -1 && iter->table == 0)
                iter->d->iterators++;

            iter->index++;

            // 当迭代器的 index 值超过哈希表的 index 值时。。。
            if (iter->index >= (signed) ht->size) {
                // 如果字典正在进行 rehash ,那么转移阵地
                // 到 1 号哈希表继续迭代
                if (dictIsRehashing(iter->d) && iter->table == 0) {
                    iter->table++;
                    iter->index = 0;
                    ht = &iter->d->ht[1];
                // 否则,退出迭代
                } else {
                    break;
                }
            }

            // 设置指针,方便下一次迭代
            iter->entry = ht->table[iter->index];
        } else {
        // 这个不是新迭代器
            iter->entry = iter->nextEntry;
        }

        if (iter->entry) {
            /* We need to save the 'next' here, the iterator user
             * may delete the entry we are returning. */
            iter->nextEntry = iter->entry->next;
            return iter->entry;
        }
    }

    return NULL;
}
Exemplo n.º 27
0
static int dictExpand(dict *pHeader, unsigned int size)
{
	if (NULL == pHeader || 0 >= size || dictIsRehashing(pHeader))
	{
		return DICT_ERROR;
	}
	size *= 2;
	pHeader->ht[1]->table = (dictEntry**)realloc((void *)pHeader->ht[1]->table,(sizeof(dictEntry *)*size));
	if (NULL == pHeader->ht[1]->table)
	{
		return DICT_ERROR;
	}
	memset(pHeader->ht[1]->table, 0, (sizeof(dictEntry *) * size));
	pHeader->ht[1]->size = size;
	pHeader->ht[1]->used = 0;
	
	pHeader->rehashidx = 0;
	return DICT_OK;
}
Exemplo n.º 28
0
/*************************************************************
* Function		:	Rehash
* Author 		:       bulldozer.ma
* Date 			:       2015-11-01
* Input 		:       dict *pHeader, int n
* Output 		:		N/A
* Return 		:       int 
* Other 		:       N/A
* Description 		:      	Rehash 
**************************************************************/
int Rehash(dict *pHeader, int n) 
{
	if (NULL == pHeader || !dictIsRehashing(pHeader)|| 0 >= n)
	{
		return DICT_ERROR;
	}
	while (n --)
	{
		dictEntry *node=  NULL, *nextnode = NULL;
		unsigned int uiKey = 0;
		if (0 == pHeader->ht[0]->used)
		{
			dictht *pTemp = pHeader->ht[0];
			pHeader->ht[0] = pHeader->ht[1];
			pHeader->ht[1] = pTemp;
			pHeader->rehashidx = -1;
			return DICT_ERROR;
		}
		while (NULL == pHeader->ht[0]->table[pHeader->rehashidx])
		{
			pHeader->rehashidx++;
		}
		node = pHeader->ht[0]->table[pHeader->rehashidx];
		while (node)
		{
			nextnode = node->next;
			uiKey = getKey(node->value, strlen (node->value), pHeader->ht[1]);
			
			node->key = uiKey;
			node->next = pHeader->ht[1]->table[uiKey];
			pHeader->ht[1]->table[uiKey] = node;
			pHeader->ht[0]->used--;
			pHeader->ht[1]->used++;
			node = nextnode;
		}
		pHeader->ht[0]->table[pHeader->rehashidx] = NULL;
      		pHeader->rehashidx++;
		
    }
   
	return DICT_OK;
}
Exemplo n.º 29
0
/* Expand the hash table if needed */
static int _dictExpandIfNeeded(dict *d)
{
    /* Incremental rehashing already in progress. Return. */
    if (dictIsRehashing(d)) return DICT_OK;

    /* If the hash table is empty expand it to the initial size. */
    if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);

    /* If we reached the 1:1 ratio, and we are allowed to resize the hash
     * table (global setting) or we should avoid it but the ratio between
     * elements/buckets is over the "safe" threshold, we resize doubling
     * the number of buckets. */
    if (d->ht[0].used >= d->ht[0].size &&
        (dict_can_resize ||
         d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))
    {
        return dictExpand(d, d->ht[0].used*2);
    }
    return DICT_OK;
}
Exemplo n.º 30
0
//下一个迭代项的entry,从上面的迭代器初始化可以看出
//迭代器在初始化的时候是不指向任何entry的,需要执行next操作获entry的指针
dictEntry *dictNext(dictIterator *iter)
{
    while (1) {
        //第一次next
        if (iter->entry == NULL) {
            dictht *ht = &iter->d->ht[iter->table];
            //这里说明是一个安全的迭代器第一次next操作,增加字典中的计数
            //之所以对着三项都进行判断,因为只有这样才能够唯一得标志该状态
            if (iter->safe && iter->index == -1 && iter->table == 0)
                iter->d->iterators++;
            iter->index++;
            //这里说明bucket的index已经超出当前的最大值了
            if (iter->index >= (signed) ht->size) {
                //如果执行rehash,切换哈希表,这个指挥执行一次
                //并且是对于是否安全的迭代器都会执行该操作
                //那么安全迭代器的安全体现在哪里呢?!!!
                if (dictIsRehashing(iter->d) && iter->table == 0) {
                    iter->table++;
                    iter->index = 0;
                    ht = &iter->d->ht[1];
                } else {
                    //没有rehash操作,说明已经到达了最后一个元素
                    break;
                }
            }
            iter->entry = ht->table[iter->index];
        } else {
            iter->entry = iter->nextEntry;
        }
        if (iter->entry) {
            /* We need to save the 'next' here, the iterator user
             * may delete the entry we are returning. */
            //这里在得到迭代器的entry之后会继续得到nextEntry,当值entry被删除
            //但是如果这两个元素都被删除了呢?
            //如何让迭代器感应到这种变化?
            iter->nextEntry = iter->entry->next;
            return iter->entry;
        }
    }
    return NULL;
}