redis整数集合有固定的数据类型,比如是整数集合是int32_t类型,新增一个int64_t类型的整数,就需要对整个集合进行升级。
redis的程序值得学习的地方太多。
一、升级
升级分为两步:扩容 + 填数
1.1 新增值的类型判断
static uint8_t _intsetValueEncoding(int64_t v) {
if (v < INT32_MIN || v > INT32_MAX)
return INTSET_ENC_INT64;
else if (v < INT16_MIN || v > INT16_MAX)
return INTSET_ENC_INT32;
else
return INTSET_ENC_INT16;
}
C中int类型是32位的,范围是 INT32_MIN=-2147483648到 INT32_MAX=2147483647 。
1.2 扩容
进行扩容在原有空间上增加1个新增数的位置
is = intsetResize(is,intrev32ifbe(is->length)+1);
static intset *intsetResize(intset *is, uint32_t len) {
uint32_t size = len*intrev32ifbe(is->encoding);
is = zrealloc(is,sizeof(intset)+size);
return is;
}
1.3 填数
数据依次后移
while(length--)
_intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));
static void _intsetSet(intset *is, int pos, int64_t value) {//按照新类型进行填数
uint32_t encoding = intrev32ifbe(is->encoding);
if (encoding == INTSET_ENC_INT64) {
((int64_t*)is->contents)[pos] = value;
memrev64ifbe(((int64_t*)is->contents)+pos);
} else if (encoding == INTSET_ENC_INT32) {
((int32_t*)is->contents)[pos] = value;
memrev32ifbe(((int32_t*)is->contents)+pos);
} else {
((int16_t*)is->contents)[pos] = value;
m