mirror of
https://github.com/fluencelabs/redis
synced 2025-06-23 22:11:33 +00:00
Add SCAN command
This commit is contained in:
committed by
antirez
parent
85f52ebcd8
commit
7f490b197f
92
src/dict.c
92
src/dict.c
@ -648,6 +648,98 @@ dictEntry *dictGetRandomKey(dict *d)
|
||||
return he;
|
||||
}
|
||||
|
||||
/* Function to reverse bits. Algorithm from:
|
||||
* http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel */
|
||||
static unsigned long rev(unsigned long v) {
|
||||
unsigned long s = 8 * sizeof(v); // bit size; must be power of 2
|
||||
unsigned long mask = ~0;
|
||||
while ((s >>= 1) > 0) {
|
||||
mask ^= (mask << s);
|
||||
v = ((v >> s) & mask) | ((v << s) & ~mask);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
unsigned long dictScan(dict *d,
|
||||
unsigned long v,
|
||||
dictScanFunction *fn,
|
||||
void *privdata)
|
||||
{
|
||||
dictht *t0, *t1;
|
||||
const dictEntry *de;
|
||||
unsigned long s0, s1;
|
||||
unsigned long m0, m1;
|
||||
|
||||
if (!dictIsRehashing(d)) {
|
||||
t0 = &(d->ht[0]);
|
||||
m0 = t0->sizemask;
|
||||
|
||||
/* Emit entries at cursor */
|
||||
de = t0->table[v & m0];
|
||||
while (de) {
|
||||
fn(privdata, de);
|
||||
de = de->next;
|
||||
}
|
||||
|
||||
} else {
|
||||
t0 = &d->ht[0];
|
||||
t1 = &d->ht[1];
|
||||
|
||||
/* Make sure t0 is the smaller and t1 is the bigger table */
|
||||
if (t0->size > t1->size) {
|
||||
t0 = &d->ht[1];
|
||||
t1 = &d->ht[0];
|
||||
}
|
||||
|
||||
s0 = t0->size;
|
||||
s1 = t1->size;
|
||||
m0 = t0->sizemask;
|
||||
m1 = t1->sizemask;
|
||||
|
||||
/* Emit entries at cursor */
|
||||
de = t0->table[v & m0];
|
||||
while (de) {
|
||||
fn(privdata, de);
|
||||
de = de->next;
|
||||
}
|
||||
|
||||
/* Iterate over indices in larger table that are the expansion
|
||||
* of the index pointed to by the cursor in the smaller table */
|
||||
do {
|
||||
/* Emit entries at cursor */
|
||||
de = t1->table[v & m1];
|
||||
while (de) {
|
||||
fn(privdata, de);
|
||||
de = de->next;
|
||||
}
|
||||
|
||||
/* Increment bits not covered by the smaller mask */
|
||||
v = (((v | m0) + 1) & ~m0) | (v & m0);
|
||||
|
||||
/* Continue while bits covered by mask difference is non-zero */
|
||||
} while (v & (m0 ^ m1));
|
||||
}
|
||||
|
||||
/* Set unmasked bits so incrementing the reversed cursor
|
||||
* operates on the masked bits of the smaller table */
|
||||
v |= ~m0;
|
||||
|
||||
/* Increment the reverse cursor */
|
||||
v = rev(v);
|
||||
v++;
|
||||
v = rev(v);
|
||||
|
||||
/* Only preprare cursor for the next iteration when it is non-zero,
|
||||
* so that 0 can be used as end-of-scan sentinel. */
|
||||
if (v) {
|
||||
/* Set unmasked bits so the cursor will keep its position
|
||||
* regardless of the mask in the next iterations */
|
||||
v |= ~m0;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/* ------------------------- private functions ------------------------------ */
|
||||
|
||||
/* Expand the hash table if needed */
|
||||
|
Reference in New Issue
Block a user