// https://github.com/RedisBloom/RedisBloom/blob/bdc753e983aa1e23fea733d75b4e4e54848093c1/src/cuckoo.c
static void getLookupParams(CuckooHash hash, LookupParams *params) {
params->fp = hash % 255 + 1; // 指纹
params->h1 = hash; // 主位置
params->h2 = getAltHash(params->fp, params->h1); // 备选位置
}
static CuckooHash getAltHash(CuckooFingerprint fp, CuckooHash index) {
return ((CuckooHash)(index ^ ((CuckooHash)fp * 0x5bd1e995)));
}
(这感觉有问题啊?指纹居然是根据 hash 值取余算出的。如果两个不同的 key hash 冲突,那么算出下标和指纹都一样,就没法区分了。算指纹应该用一个单独的 hash 函数吧
static CuckooInsertStatus Filter_KOInsert(CuckooFilter *filter, SubCF *curFilter, const LookupParams *params) {
while (counter++ < maxIterations) {
uint8_t *bucket = &curFilter->data[ii * bucketSize]; // 计算元素应放入的bucket
swapFPs(bucket + victimIx, &fp); // 将bucket的头元素和当前元素互换
ii = getAltHash(fp, ii) % numBuckets; // 为换出来的头元素(这里叫受害者)找下一个位置
// Insert the new item in potentially the same bucket
uint8_t *empty = Bucket_FindAvailable(&curFilter->data[ii * bucketSize], bucketSize); // 下一个位置可以在本bucket内
if (empty) { // 如果下个位置是空的,则直接插入
*empty = fp; // 赋值指纹信息
return CuckooInsert_Inserted;
}
victimIx = (victimIx + 1) % bucketSize; // 如果换出来的受害者没有地方去了,换下一个受害者尝试
}
// If we weren't able to insert, we roll back and try to insert new element in new filter
// 超过maxIterations会触发扩容,扩容后这里再试一次
// 扩容会加个 filter
// ...
return CuckooInsert_NoSpace;
}