mirror of
https://github.com/fluencelabs/redis
synced 2025-03-18 00:20:50 +00:00
parent
5e3dcc522b
commit
170e41464d
54
src/dict.c
54
src/dict.c
@ -666,34 +666,42 @@ dictEntry *dictGetRandomKey(dict *d)
|
|||||||
* at producing N elements, and the elements are guaranteed to be non
|
* at producing N elements, and the elements are guaranteed to be non
|
||||||
* repeating. */
|
* repeating. */
|
||||||
unsigned int dictGetRandomKeys(dict *d, dictEntry **des, unsigned int count) {
|
unsigned int dictGetRandomKeys(dict *d, dictEntry **des, unsigned int count) {
|
||||||
int j; /* internal hash table id, 0 or 1. */
|
unsigned int j; /* internal hash table id, 0 or 1. */
|
||||||
unsigned int stored = 0;
|
unsigned int tables; /* 1 or 2 tables? */
|
||||||
|
unsigned int stored = 0, maxsizemask;
|
||||||
|
|
||||||
if (dictSize(d) < count) count = dictSize(d);
|
if (dictSize(d) < count) count = dictSize(d);
|
||||||
while(stored < count) {
|
|
||||||
for (j = 0; j < 2; j++) {
|
|
||||||
/* Pick a random point inside the hash table 0 or 1. */
|
|
||||||
unsigned int i = random() & d->ht[j].sizemask;
|
|
||||||
int size = d->ht[j].size;
|
|
||||||
|
|
||||||
/* Make sure to visit every bucket by iterating 'size' times. */
|
/* Try to do a rehashing work proportional to 'count'. */
|
||||||
while(size--) {
|
for (j = 0; j < count; j++) {
|
||||||
dictEntry *he = d->ht[j].table[i];
|
if (dictIsRehashing(d))
|
||||||
while (he) {
|
_dictRehashStep(d);
|
||||||
/* Collect all the elements of the buckets found non
|
else
|
||||||
* empty while iterating. */
|
break;
|
||||||
*des = he;
|
}
|
||||||
des++;
|
|
||||||
he = he->next;
|
tables = dictIsRehashing(d) ? 2 : 1;
|
||||||
stored++;
|
maxsizemask = d->ht[0].sizemask;
|
||||||
if (stored == count) return stored;
|
if (tables > 1 && maxsizemask < d->ht[1].sizemask)
|
||||||
}
|
maxsizemask = d->ht[1].sizemask;
|
||||||
i = (i+1) & d->ht[j].sizemask;
|
|
||||||
|
/* Pick a random point inside the larger table. */
|
||||||
|
unsigned int i = random() & maxsizemask;
|
||||||
|
while(stored < count) {
|
||||||
|
for (j = 0; j < tables; j++) {
|
||||||
|
if (i >= d->ht[j].size) continue; /* Out of range for this table. */
|
||||||
|
dictEntry *he = d->ht[j].table[i];
|
||||||
|
while (he) {
|
||||||
|
/* Collect all the elements of the buckets found non
|
||||||
|
* empty while iterating. */
|
||||||
|
*des = he;
|
||||||
|
des++;
|
||||||
|
he = he->next;
|
||||||
|
stored++;
|
||||||
|
if (stored == count) return stored;
|
||||||
}
|
}
|
||||||
/* If there is only one table and we iterated it all, we should
|
|
||||||
* already have 'count' elements. Assert this condition. */
|
|
||||||
assert(dictIsRehashing(d) != 0);
|
|
||||||
}
|
}
|
||||||
|
i = (i+1) & maxsizemask;
|
||||||
}
|
}
|
||||||
return stored; /* Never reached. */
|
return stored; /* Never reached. */
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user