redis中的intset

整数集合inset是当一个集合中只包含整数值元素,并且这个集合元素不多时,redis就只用inset来保存
这个集合,inset支持升级操作,所谓升级是值将数据类型有int16升级为int32的动作,但是目前
不支持降级操作。inset中的元素是按照从小到大排列的。
redis中的inset用如下结构体表示
typedef struct intset {
    
    uint32_t encoding;
	//集合中的总的个数,应该等于contents 数组的长度
    uint32_t length;

    // inset中的元素都是保存在这个数组中
    int8_t contents[];

} intset;

intsetNew 函数用于新建一个新的inset。其实现如下:

intset *intsetNew(void) {

    // 为整数集合结构分配空间
    intset *is = zmalloc(sizeof(intset));

    // 设置编码方式,原来encoding 表示保存在inset中的数据类型啊,且默认类型是INT16
    is->encoding = intrev32ifbe(INTSET_ENC_INT16);
    is->length = 0;
	// 返回指针
    return is;
}
inset的查找函数实现如下:
tatic uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {
    int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;
    int64_t cur = -1;

    /* The value can never be found when the set is empty */
    // 如果inset 为null ,则返回零
    if (intrev32ifbe(is->length) == 0) {
        if (pos) *pos = 0;
        return 0;
    } else {
        /* Check for the case where we know we cannot find the value,
         * but do know the insert position. */
		// 检查形参value是否比inset最后一个元素还大
        if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
		// 检查形参value是否比inset的第一个元素还小
        } else if (value < _intsetGet(is,0)) {
            if (pos) *pos = 0;
            return 0;
        }
    }

    // 在从小到大排列的inset 这个有序表中进行二分法查找,可以知道在一个有序表中
	// 二分法的查找效率最高
    while(max >= min) {
        mid = (min+max)/2;
        cur = _intsetGet(is,mid);
        if (value > cur) {
            min = mid+1;
        } else if (value < cur) {
            max = mid-1;
        } else {
            break;
        }
    }

    // 找到这个值的话,返回这个值所在的位置
    if (value == cur) {
        if (pos) *pos = mid;
        return 1;
    } else {
        if (pos) *pos = min;
        return 0;
    }
}

你可能感兴趣的:(redis)