Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
6bda18ff
Commit
6bda18ff
authored
Feb 04, 2015
by
antirez
Browse files
Less blocking dictGetRandomKeys().
Related to issue #2306.
parent
cfe21852
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/dict.c
View file @
6bda18ff
...
@@ -666,34 +666,42 @@ dictEntry *dictGetRandomKey(dict *d)
...
@@ -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
);
/* Try to do a rehashing work proportional to 'count'. */
for
(
j
=
0
;
j
<
count
;
j
++
)
{
if
(
dictIsRehashing
(
d
))
_dictRehashStep
(
d
);
else
break
;
}
tables
=
dictIsRehashing
(
d
)
?
2
:
1
;
maxsizemask
=
d
->
ht
[
0
].
sizemask
;
if
(
tables
>
1
&&
maxsizemask
<
d
->
ht
[
1
].
sizemask
)
maxsizemask
=
d
->
ht
[
1
].
sizemask
;
/* Pick a random point inside the larger table. */
unsigned
int
i
=
random
()
&
maxsizemask
;
while
(
stored
<
count
)
{
while
(
stored
<
count
)
{
for
(
j
=
0
;
j
<
2
;
j
++
)
{
for
(
j
=
0
;
j
<
tables
;
j
++
)
{
/* Pick a random point inside the hash table 0 or 1. */
if
(
i
>=
d
->
ht
[
j
].
size
)
continue
;
/* Out of range for this table. */
unsigned
int
i
=
random
()
&
d
->
ht
[
j
].
sizemask
;
dictEntry
*
he
=
d
->
ht
[
j
].
table
[
i
];
int
size
=
d
->
ht
[
j
].
size
;
while
(
he
)
{
/* Collect all the elements of the buckets found non
/* Make sure to visit every bucket by iterating 'size' times. */
* empty while iterating. */
while
(
size
--
)
{
*
des
=
he
;
dictEntry
*
he
=
d
->
ht
[
j
].
table
[
i
];
des
++
;
while
(
he
)
{
he
=
he
->
next
;
/* Collect all the elements of the buckets found non
stored
++
;
* empty while iterating. */
if
(
stored
==
count
)
return
stored
;
*
des
=
he
;
des
++
;
he
=
he
->
next
;
stored
++
;
if
(
stored
==
count
)
return
stored
;
}
i
=
(
i
+
1
)
&
d
->
ht
[
j
].
sizemask
;
}
}
/* 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. */
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment