设为首页 加入收藏

TOP

Redis源码分析(八)---t_hash哈希转换(二)
2015-07-24 12:04:41 来源: 作者: 【 】 浏览:88
Tags:Redis 源码 分析 ---t_hash 哈希 转换
t the value from a hash table encoded hash, identified by field. * Returns -1 when the field cannot be found. */ /* 获取哈希字典中的某个值 */ int hashTypeGetFromHashTable(robj *o, robj *field, robj **value) { dictEntry *de; redisAssert(o->encoding == REDIS_ENCODING_HT); //通过robj->ptr里面存的dict总类或ziplist类开始寻找 de = dictFind(o->ptr, field); if (de == NULL) return -1; //获取其中的value值 *value = dictGetVal(de); return 0; } 所有关于robj的相关结构体操作都会分成为2种情况处理,ZIPLIST和HASH类型就是dict类型,而且操作ziplist类型的时候要进行转码处理,当然在进行ziplist存入robj的时候要进行编码操作,可见,设计者在考虑到命令传输的时候想得还是很周到了,也考虑了安全的问题。?
/* Add an element, discard the old if the key already exists.
 * Return 0 on insert and 1 on update.
 * This function will take care of incrementing the reference count of the
 * retained fields and value objects. */
/* hashType设置操作,分2种情况,ziplist,和字典hashtable */
int hashTypeSet(robj *o, robj *field, robj *value) {
    int update = 0;

    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        unsigned char *zl, *fptr, *vptr;
        
        //首先对field和value进行解码
        field = getDecodedObject(field);
        value = getDecodedObject(value);

        zl = o->ptr;
        fptr = ziplistIndex(zl, ZIPLIST_HEAD);
        if (fptr != NULL) {
            fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1);
            if (fptr != NULL) {
                /* Grab pointer to the value (fptr points to the field) */
                vptr = ziplistNext(zl, fptr);
                redisAssert(vptr != NULL);
                update = 1;

                //设置的操作,其实先删除,再插入语一个新值
                /* Delete value */
                zl = ziplistDelete(zl, &vptr);

                /* Insert new value */
                zl = ziplistInsert(zl, vptr, value->ptr, sdslen(value->ptr));
            }
        }

        if (!update) {
            /* Push new field/value pair onto the tail of the ziplist */
            zl = ziplistPush(zl, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);
            zl = ziplistPush(zl, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL);
        }
        o->ptr = zl;
        //用完之后,引用计数递减
        decrRefCount(field);
        decrRefCount(value);

        /* Check if the ziplist needs to be converted to a hash table */
        if (hashTypeLength(o) > server.hash_max_ziplist_entries)
            hashTypeConvert(o, REDIS_ENCODING_HT);
    } else if (o->encoding == REDIS_ENCODING_HT) {
    	//如果是字典,直接替换
        if (dictReplace(o->ptr, field, value)) { /* Insert */
            incrRefCount(field);
        } else { /* Update */
            update = 1;
        }
        //用完之后,引用计数递减
        incrRefCount(value);
    } else {
        redisPanic("Unknown hash encoding");
    }
    return update;
}
在这个过程中,redis代码中还用到了一个引用计数的东西,应该是为了合理的内存释放控制,在很多地方可以看到这样的操作;?
/* Higher level function of hashTypeGet*() that always returns a Redis
 * object (either new or with refcount incremented), so that the caller
 * can retain a reference or call decrRefCount after the usage.
 *
 * The lower level function can prevent copy on write so it is
 * the preferred way of doing read operations. */
/* 获取某个key的对象 */
robj *hashTypeGetObject(robj *o, robj *field) {
    robj *value = NULL;

    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        unsigned char *vstr = NULL;
        unsigned int vlen = UINT_MAX;
        long long vll = LLONG_MAX;

        if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) {
        	//在ziplist中获取值
            if (vstr) {
                value = createStringObject((char*)vstr, vlen);
            } else {
                value = createStringObjectFromLongLong(vll);
            }
        }

    } else if (o->encoding == REDIS_ENCODING_HT) {
        robj *aux;

        if (hashTypeGetFromHashTable(o, field, &aux) == 0) {
        	//对象被引用了,计数递增
            incrRefCount(aux);
            value = aux;
        }
    } else {
        redisPanic("Unknown hash encoding");
    }
    return v
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇toadfororacle,格式化配置备份Fm.. 下一篇知道归档日志sequence#,查处该归..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: