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
ed138c0a
Commit
ed138c0a
authored
Mar 24, 2023
by
Vitaly Arbuzov
Browse files
Use binary index in slot iteration instead of maintaining an intset
parent
af1bb938
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/db.c
View file @
ed138c0a
...
@@ -51,15 +51,10 @@ void cumulativeKeyCountAdd(redisDb *db, int idx, long delta);
...
@@ -51,15 +51,10 @@ void cumulativeKeyCountAdd(redisDb *db, int idx, long delta);
/* Returns next dictionary from the iterator, or NULL if iteration is complete. */
/* Returns next dictionary from the iterator, or NULL if iteration is complete. */
dict
*
dbIteratorNextDict
(
dbIterator
*
dbit
)
{
dict
*
dbIteratorNextDict
(
dbIterator
*
dbit
)
{
int64_t
slot
;
if
(
dbit
->
next_slot
==
-
1
)
return
NULL
;
dbit
->
cur_slot
=
-
1
;
dbit
->
slot
=
dbit
->
next_slot
;
if
(
!
server
.
cluster_enabled
)
{
dbit
->
next_slot
=
dbGetNextNonEmptySlot
(
dbit
->
db
,
dbit
->
slot
);
dbit
->
cur_slot
=
dbit
->
index
++
?
-
1
:
0
;
return
dbit
->
db
->
dict
[
dbit
->
slot
];
}
else
if
(
intsetGet
(
dbit
->
db
->
non_empty_dicts
,
dbit
->
index
++
,
&
slot
)){
dbit
->
cur_slot
=
(
int
)
slot
;
return
dbit
->
db
->
dict
[
slot
];
}
return
dbit
->
cur_slot
>=
0
?
dbit
->
db
->
dict
[
dbit
->
cur_slot
]
:
NULL
;
}
}
/* Returns next entry from the multi slot db. */
/* Returns next entry from the multi slot db. */
...
@@ -69,7 +64,7 @@ dictEntry *dbIteratorNext(dbIterator *dbit) {
...
@@ -69,7 +64,7 @@ dictEntry *dbIteratorNext(dbIterator *dbit) {
dict
*
d
=
dbIteratorNextDict
(
dbit
);
dict
*
d
=
dbIteratorNextDict
(
dbit
);
if
(
!
d
)
return
NULL
;
if
(
!
d
)
return
NULL
;
dictInitSafeIterator
(
&
dbit
->
di
,
d
);
dictInitSafeIterator
(
&
dbit
->
di
,
d
);
return
dictNext
(
&
dbit
->
di
);
de
=
dictNext
(
&
dbit
->
di
);
}
}
return
de
;
return
de
;
}
}
...
@@ -79,25 +74,15 @@ dictEntry *dbIteratorNext(dbIterator *dbit) {
...
@@ -79,25 +74,15 @@ dictEntry *dbIteratorNext(dbIterator *dbit) {
* or 16k dictionaries (one per slot) when node runs with cluster mode enabled. */
* or 16k dictionaries (one per slot) when node runs with cluster mode enabled. */
void
dbIteratorInit
(
dbIterator
*
dbit
,
redisDb
*
db
)
{
void
dbIteratorInit
(
dbIterator
*
dbit
,
redisDb
*
db
)
{
dbit
->
db
=
db
;
dbit
->
db
=
db
;
dbit
->
index
=
0
;
dbit
->
slot
=
-
1
;
dbit
->
cur
_slot
=
-
1
;
dbit
->
next
_slot
=
findSlotByKeyIndex
(
dbit
->
db
,
1
);
/* Finds first non-empty slot. */
dictInitSafeIterator
(
&
dbit
->
di
,
NULL
);
dictInitSafeIterator
(
&
dbit
->
di
,
NULL
);
}
}
/* Returns next non-empty dictionary strictly after provided slot and updates slot id in the supplied reference. */
/* Returns next non-empty slot strictly after given one, or -1 if provided slot is the last one. */
dict
*
dbGetNextNonEmptySlot
(
redisDb
*
db
,
int
*
slot
)
{
int
dbGetNextNonEmptySlot
(
redisDb
*
db
,
int
slot
)
{
if
(
server
.
cluster_enabled
)
{
unsigned
long
long
next_key
=
cumulativeKeyCountRead
(
db
,
slot
)
+
1
;
uint32_t
pos
;
return
next_key
<=
dbSize
(
db
)
?
findSlotByKeyIndex
(
db
,
next_key
)
:
-
1
;
int
found
=
intsetSearch
(
db
->
non_empty_dicts
,
*
slot
,
&
pos
);
if
(
found
)
pos
++
;
/* If current slot exists in the non-empty list, then we want next one, otherwise pos already points to it. */
int64_t
next_slot
;
if
(
intsetGet
(
db
->
non_empty_dicts
,
pos
,
&
next_slot
))
{
*
slot
=
(
int
)
next_slot
;
return
db
->
dict
[
*
slot
];
}
}
*
slot
=
-
1
;
return
NULL
;
}
}
...
@@ -245,17 +230,10 @@ void dbAdd(redisDb *db, robj *key, robj *val) {
...
@@ -245,17 +230,10 @@ void dbAdd(redisDb *db, robj *key, robj *val) {
sds
copy
=
sdsdup
(
key
->
ptr
);
sds
copy
=
sdsdup
(
key
->
ptr
);
int
slot
=
getKeySlot
(
key
->
ptr
);
int
slot
=
getKeySlot
(
key
->
ptr
);
dict
*
d
=
db
->
dict
[
slot
];
dict
*
d
=
db
->
dict
[
slot
];
int
new_dict
=
server
.
cluster_enabled
&&
dictIsEmpty
(
d
);
dictEntry
*
de
=
dictAddRaw
(
d
,
copy
,
NULL
);
dictEntry
*
de
=
dictAddRaw
(
d
,
copy
,
NULL
);
serverAssertWithInfo
(
NULL
,
key
,
de
!=
NULL
);
serverAssertWithInfo
(
NULL
,
key
,
de
!=
NULL
);
dictSetVal
(
d
,
de
,
val
);
dictSetVal
(
d
,
de
,
val
);
db
->
key_count
++
;
db
->
key_count
++
;
/* If dict transitioned from empty to non-empty, we should add it to the list of owned slots. Cluster mode only. */
if
(
new_dict
)
{
uint8_t
success
=
0
;
db
->
non_empty_dicts
=
intsetAdd
(
db
->
non_empty_dicts
,
slot
,
&
success
);
serverAssert
(
success
);
}
if
(
server
.
cluster_enabled
)
{
if
(
server
.
cluster_enabled
)
{
cumulativeKeyCountAdd
(
db
,
slot
,
1
);
cumulativeKeyCountAdd
(
db
,
slot
,
1
);
}
}
...
@@ -288,17 +266,10 @@ int getKeySlot(sds key) {
...
@@ -288,17 +266,10 @@ int getKeySlot(sds key) {
int
dbAddRDBLoad
(
redisDb
*
db
,
sds
key
,
robj
*
val
)
{
int
dbAddRDBLoad
(
redisDb
*
db
,
sds
key
,
robj
*
val
)
{
int
slot
=
getKeySlot
(
key
);
int
slot
=
getKeySlot
(
key
);
dict
*
d
=
db
->
dict
[
slot
];
dict
*
d
=
db
->
dict
[
slot
];
int
new_dict
=
server
.
cluster_enabled
&&
dictIsEmpty
(
d
);
dictEntry
*
de
=
dictAddRaw
(
d
,
key
,
NULL
);
dictEntry
*
de
=
dictAddRaw
(
d
,
key
,
NULL
);
if
(
de
==
NULL
)
return
0
;
if
(
de
==
NULL
)
return
0
;
dictSetVal
(
d
,
de
,
val
);
dictSetVal
(
d
,
de
,
val
);
db
->
key_count
++
;
db
->
key_count
++
;
/* If dict transitioned from empty to non-empty, we should add it to the list of owned slots. */
if
(
new_dict
)
{
uint8_t
success
=
0
;
db
->
non_empty_dicts
=
intsetAdd
(
db
->
non_empty_dicts
,
slot
,
&
success
);
serverAssert
(
success
);
}
if
(
server
.
cluster_enabled
)
{
if
(
server
.
cluster_enabled
)
{
cumulativeKeyCountAdd
(
db
,
slot
,
1
);
cumulativeKeyCountAdd
(
db
,
slot
,
1
);
}
}
...
@@ -456,21 +427,27 @@ unsigned long long cumulativeKeyCountRead(redisDb *db, int slot) {
...
@@ -456,21 +427,27 @@ unsigned long long cumulativeKeyCountRead(redisDb *db, int slot) {
* Implementation uses binary search on top of binary index tree.
* Implementation uses binary search on top of binary index tree.
* Time complexity of this function is O(log^2(CLUSTER_SLOTS)). */
* Time complexity of this function is O(log^2(CLUSTER_SLOTS)). */
dict
*
getFairRandomDict
(
redisDb
*
db
)
{
dict
*
getFairRandomDict
(
redisDb
*
db
)
{
if
(
!
server
.
cluster_enabled
||
dbSize
(
db
)
==
0
)
return
db
->
dict
[
0
];
unsigned
long
target
=
dbSize
(
db
)
?
(
randomULong
()
%
dbSize
(
db
))
+
1
:
0
;
/* We want to find a slot containing target-th element in a key space ordered by slot id.
int
slot
=
findSlotByKeyIndex
(
db
,
target
);
* Consider this example. Slots are represented by brackets and keys by dots:
return
db
->
dict
[
slot
];
* #0 #1 #2 #3 #4
}
* [..][....][...][.......][.]
* ^
/* Finds a slot containing target element in a key space ordered by slot id.
* target
* Consider this example. Slots are represented by brackets and keys by dots:
*
* #0 #1 #2 #3 #4
* In this case slot #3 contains key that we are trying to find.
* [..][....][...][.......][.]
* */
* ^
unsigned
long
target
=
(
randomULong
()
%
dbSize
(
db
))
+
1
;
* target
*
* In this case slot #3 contains key that we are trying to find.
* */
int
findSlotByKeyIndex
(
redisDb
*
db
,
unsigned
long
target
)
{
if
(
!
server
.
cluster_enabled
||
dbSize
(
db
)
==
0
)
return
0
;
serverAssert
(
target
<=
dbSize
(
db
));
int
lo
=
0
,
hi
=
CLUSTER_SLOTS
-
1
;
int
lo
=
0
,
hi
=
CLUSTER_SLOTS
-
1
;
/* We use binary search to find a slot, we are allowed to do this, because we have a quick way to find a total number of keys
/* We use binary search to find a slot, we are allowed to do this, because we have a quick way to find a total number of keys
* up until certain slot, using binary index tree. */
* up until certain slot, using binary index tree. */
while
(
lo
<
hi
)
{
while
(
lo
<
=
hi
)
{
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
int
mid
=
lo
+
(
hi
-
lo
)
/
2
;
unsigned
long
keys_up_to_mid
=
cumulativeKeyCountRead
(
db
,
mid
);
/* Total number of keys up until a given slot (inclusive). */
unsigned
long
keys_up_to_mid
=
cumulativeKeyCountRead
(
db
,
mid
);
/* Total number of keys up until a given slot (inclusive). */
unsigned
long
keys_in_mid
=
dictSize
(
db
->
dict
[
mid
]);
/* Number of keys in the slot. */
unsigned
long
keys_in_mid
=
dictSize
(
db
->
dict
[
mid
]);
/* Number of keys in the slot. */
...
@@ -479,13 +456,10 @@ dict *getFairRandomDict(redisDb *db) {
...
@@ -479,13 +456,10 @@ dict *getFairRandomDict(redisDb *db) {
}
else
if
(
target
<=
keys_up_to_mid
-
keys_in_mid
)
{
/* Target is to the left from mid. */
}
else
if
(
target
<=
keys_up_to_mid
-
keys_in_mid
)
{
/* Target is to the left from mid. */
hi
=
mid
-
1
;
hi
=
mid
-
1
;
}
else
{
/* Located target. */
}
else
{
/* Located target. */
b
re
ak
;
re
turn
mid
;
}
}
}
}
int
slot
=
lo
+
(
hi
-
lo
)
/
2
;
serverPanic
(
"Unable to find a slot that contains target key."
);
dict
*
result
=
db
->
dict
[
slot
];
serverAssert
(
!
dictIsEmpty
(
result
));
return
result
;
}
}
/* Helper for sync and async delete. */
/* Helper for sync and async delete. */
...
@@ -516,12 +490,6 @@ int dbGenericDelete(redisDb *db, robj *key, int async, int flags) {
...
@@ -516,12 +490,6 @@ int dbGenericDelete(redisDb *db, robj *key, int async, int flags) {
* the key, because it is shared with the main dictionary. */
* the key, because it is shared with the main dictionary. */
if
(
dictSize
(
db
->
expires
)
>
0
)
dictDelete
(
db
->
expires
,
key
->
ptr
);
if
(
dictSize
(
db
->
expires
)
>
0
)
dictDelete
(
db
->
expires
,
key
->
ptr
);
dictTwoPhaseUnlinkFree
(
d
,
de
,
plink
,
table
);
dictTwoPhaseUnlinkFree
(
d
,
de
,
plink
,
table
);
/* If we've removed last entry from the dict, then we need to also remove it from the list of owned non-empty slots. */
if
(
server
.
cluster_enabled
&&
dictIsEmpty
(
d
))
{
int
success
=
0
;
db
->
non_empty_dicts
=
intsetRemove
(
db
->
non_empty_dicts
,
slot
,
&
success
);
serverAssert
(
success
);
}
if
(
server
.
cluster_enabled
)
{
if
(
server
.
cluster_enabled
)
{
cumulativeKeyCountAdd
(
db
,
slot
,
-
1
);
cumulativeKeyCountAdd
(
db
,
slot
,
-
1
);
}
}
...
@@ -624,8 +592,6 @@ long long emptyDbStructure(redisDb *dbarray, int dbnum, int async,
...
@@ -624,8 +592,6 @@ long long emptyDbStructure(redisDb *dbarray, int dbnum, int async,
if
(
server
.
cluster_enabled
)
{
if
(
server
.
cluster_enabled
)
{
zfree
(
dbarray
[
j
].
binary_index
);
zfree
(
dbarray
[
j
].
binary_index
);
dbarray
[
j
].
binary_index
=
zcalloc
(
sizeof
(
unsigned
long
long
)
*
(
CLUSTER_SLOTS
+
1
));
dbarray
[
j
].
binary_index
=
zcalloc
(
sizeof
(
unsigned
long
long
)
*
(
CLUSTER_SLOTS
+
1
));
zfree
(
dbarray
[
j
].
non_empty_dicts
);
dbarray
[
j
].
non_empty_dicts
=
intsetNew
();
}
}
}
}
...
@@ -694,7 +660,6 @@ redisDb *initTempDb(void) {
...
@@ -694,7 +660,6 @@ redisDb *initTempDb(void) {
tempDb
[
i
].
dict_count
=
(
server
.
cluster_enabled
)
?
CLUSTER_SLOTS
:
1
;
tempDb
[
i
].
dict_count
=
(
server
.
cluster_enabled
)
?
CLUSTER_SLOTS
:
1
;
tempDb
[
i
].
dict
=
dictCreateMultiple
(
&
dbDictType
,
tempDb
[
i
].
dict_count
);
tempDb
[
i
].
dict
=
dictCreateMultiple
(
&
dbDictType
,
tempDb
[
i
].
dict_count
);
tempDb
[
i
].
expires
=
dictCreate
(
&
dbExpiresDictType
);
tempDb
[
i
].
expires
=
dictCreate
(
&
dbExpiresDictType
);
tempDb
[
i
].
non_empty_dicts
=
server
.
cluster_enabled
?
intsetNew
()
:
NULL
;
tempDb
[
i
].
binary_index
=
server
.
cluster_enabled
?
zcalloc
(
sizeof
(
unsigned
long
long
)
*
(
CLUSTER_SLOTS
+
1
))
:
NULL
;
tempDb
[
i
].
binary_index
=
server
.
cluster_enabled
?
zcalloc
(
sizeof
(
unsigned
long
long
)
*
(
CLUSTER_SLOTS
+
1
))
:
NULL
;
}
}
...
@@ -715,7 +680,6 @@ void discardTempDb(redisDb *tempDb, void(callback)(dict*)) {
...
@@ -715,7 +680,6 @@ void discardTempDb(redisDb *tempDb, void(callback)(dict*)) {
dictRelease
(
tempDb
[
i
].
expires
);
dictRelease
(
tempDb
[
i
].
expires
);
if
(
server
.
cluster_enabled
)
{
if
(
server
.
cluster_enabled
)
{
zfree
(
tempDb
[
i
].
binary_index
);
zfree
(
tempDb
[
i
].
binary_index
);
zfree
(
tempDb
[
i
].
non_empty_dicts
);
}
}
}
}
...
@@ -1117,7 +1081,8 @@ void scanGenericCommand(client *c, robj *o, unsigned long long cursor) {
...
@@ -1117,7 +1081,8 @@ void scanGenericCommand(client *c, robj *o, unsigned long long cursor) {
/* In cluster mode there is a separate dictionary for each slot.
/* In cluster mode there is a separate dictionary for each slot.
* If cursor is empty, we should try exploring next non-empty slot. */
* If cursor is empty, we should try exploring next non-empty slot. */
if
(
o
==
NULL
&&
!
cursor
)
{
if
(
o
==
NULL
&&
!
cursor
)
{
ht
=
dbGetNextNonEmptySlot
(
c
->
db
,
&
slot
);
slot
=
dbGetNextNonEmptySlot
(
c
->
db
,
slot
);
ht
=
slot
!=
-
1
?
c
->
db
->
dict
[
slot
]
:
NULL
;
}
}
}
while
((
cursor
||
slot
>
0
)
&&
/* Continue iteration if there are more slots to visit, or cursor hasn't reached the end of dict yet. */
}
while
((
cursor
||
slot
>
0
)
&&
/* Continue iteration if there are more slots to visit, or cursor hasn't reached the end of dict yet. */
maxiterations
--
&&
maxiterations
--
&&
...
@@ -1660,7 +1625,6 @@ int dbSwapDatabases(int id1, int id2) {
...
@@ -1660,7 +1625,6 @@ int dbSwapDatabases(int id1, int id2) {
db1
->
resize_cursor
=
db2
->
resize_cursor
;
db1
->
resize_cursor
=
db2
->
resize_cursor
;
db1
->
dict_count
=
db2
->
dict_count
;
db1
->
dict_count
=
db2
->
dict_count
;
db1
->
key_count
=
db2
->
key_count
;
db1
->
key_count
=
db2
->
key_count
;
db1
->
non_empty_dicts
=
db2
->
non_empty_dicts
;
db1
->
binary_index
=
db2
->
binary_index
;
db1
->
binary_index
=
db2
->
binary_index
;
db2
->
dict
=
aux
.
dict
;
db2
->
dict
=
aux
.
dict
;
...
@@ -1670,7 +1634,6 @@ int dbSwapDatabases(int id1, int id2) {
...
@@ -1670,7 +1634,6 @@ int dbSwapDatabases(int id1, int id2) {
db2
->
resize_cursor
=
aux
.
resize_cursor
;
db2
->
resize_cursor
=
aux
.
resize_cursor
;
db2
->
dict_count
=
aux
.
dict_count
;
db2
->
dict_count
=
aux
.
dict_count
;
db2
->
key_count
=
aux
.
key_count
;
db2
->
key_count
=
aux
.
key_count
;
db2
->
non_empty_dicts
=
aux
.
non_empty_dicts
;
db2
->
binary_index
=
aux
.
binary_index
;
db2
->
binary_index
=
aux
.
binary_index
;
/* Now we need to handle clients blocked on lists: as an effect
/* Now we need to handle clients blocked on lists: as an effect
...
@@ -1712,7 +1675,6 @@ void swapMainDbWithTempDb(redisDb *tempDb) {
...
@@ -1712,7 +1675,6 @@ void swapMainDbWithTempDb(redisDb *tempDb) {
activedb
->
resize_cursor
=
newdb
->
resize_cursor
;
activedb
->
resize_cursor
=
newdb
->
resize_cursor
;
activedb
->
dict_count
=
newdb
->
dict_count
;
activedb
->
dict_count
=
newdb
->
dict_count
;
activedb
->
key_count
=
newdb
->
key_count
;
activedb
->
key_count
=
newdb
->
key_count
;
activedb
->
non_empty_dicts
=
newdb
->
non_empty_dicts
;
activedb
->
binary_index
=
newdb
->
binary_index
;
activedb
->
binary_index
=
newdb
->
binary_index
;
newdb
->
dict
=
aux
.
dict
;
newdb
->
dict
=
aux
.
dict
;
...
@@ -1722,7 +1684,6 @@ void swapMainDbWithTempDb(redisDb *tempDb) {
...
@@ -1722,7 +1684,6 @@ void swapMainDbWithTempDb(redisDb *tempDb) {
newdb
->
resize_cursor
=
aux
.
resize_cursor
;
newdb
->
resize_cursor
=
aux
.
resize_cursor
;
newdb
->
dict_count
=
aux
.
dict_count
;
newdb
->
dict_count
=
aux
.
dict_count
;
newdb
->
key_count
=
aux
.
key_count
;
newdb
->
key_count
=
aux
.
key_count
;
newdb
->
non_empty_dicts
=
aux
.
non_empty_dicts
;
newdb
->
binary_index
=
aux
.
binary_index
;
newdb
->
binary_index
=
aux
.
binary_index
;
/* Now we need to handle clients blocked on lists: as an effect
/* Now we need to handle clients blocked on lists: as an effect
...
...
src/defrag.c
View file @
ed138c0a
...
@@ -1007,9 +1007,9 @@ void activeDefragCycle(void) {
...
@@ -1007,9 +1007,9 @@ void activeDefragCycle(void) {
db
=
&
server
.
db
[
current_db
];
db
=
&
server
.
db
[
current_db
];
cursor
=
0
;
cursor
=
0
;
}
}
int
slot
=
0
;
int
slot
=
findSlotByKeyIndex
(
db
,
1
);
dict
*
d
=
db
->
dict
[
slot
];
do
{
do
{
dict
*
d
=
db
->
dict
[
slot
];
/* before scanning the next bucket, see if we have big keys left from the previous bucket to scan */
/* before scanning the next bucket, see if we have big keys left from the previous bucket to scan */
if
(
defragLaterStep
(
db
,
endtime
))
{
if
(
defragLaterStep
(
db
,
endtime
))
{
quit
=
1
;
/* time is up, we didn't finish all the work */
quit
=
1
;
/* time is up, we didn't finish all the work */
...
@@ -1020,7 +1020,7 @@ void activeDefragCycle(void) {
...
@@ -1020,7 +1020,7 @@ void activeDefragCycle(void) {
if
(
!
expires_cursor
)
if
(
!
expires_cursor
)
cursor
=
dictScanDefrag
(
d
,
cursor
,
defragScanCallback
,
cursor
=
dictScanDefrag
(
d
,
cursor
,
defragScanCallback
,
&
defragfns
,
db
);
&
defragfns
,
db
);
if
(
!
cursor
)
d
=
dbGetNextNonEmptySlot
(
db
,
&
slot
);
if
(
!
cursor
)
slot
=
dbGetNextNonEmptySlot
(
db
,
slot
);
/* When done scanning the keyspace dict, we scan the expire dict. */
/* When done scanning the keyspace dict, we scan the expire dict. */
if
(
!
cursor
&&
slot
>
-
1
)
if
(
!
cursor
&&
slot
>
-
1
)
expires_cursor
=
dictScanDefrag
(
db
->
expires
,
expires_cursor
,
expires_cursor
=
dictScanDefrag
(
db
->
expires
,
expires_cursor
,
...
...
src/module.c
View file @
ed138c0a
...
@@ -10847,8 +10847,8 @@ int RM_Scan(RedisModuleCtx *ctx, RedisModuleScanCursor *cursor, RedisModuleScanC
...
@@ -10847,8 +10847,8 @@ int RM_Scan(RedisModuleCtx *ctx, RedisModuleScanCursor *cursor, RedisModuleScanC
dict *dict = ctx->client->db->dict[slot];
dict *dict = ctx->client->db->dict[slot];
cursor->cursor = dictScan(dict, cursor->cursor, moduleScanCallback, &data);
cursor->cursor = dictScan(dict, cursor->cursor, moduleScanCallback, &data);
if (cursor->cursor == 0) {
if (cursor->cursor == 0) {
dic
t = dbGetNextNonEmptySlot(ctx->client->db,
&
slot);
slo
t = dbGetNextNonEmptySlot(ctx->client->db, slot);
if (
dic
t ==
NULL
) {
if (
slo
t ==
-1
) {
cursor->done = 1;
cursor->done = 1;
ret = 0;
ret = 0;
}
}
...
...
src/rdb.c
View file @
ed138c0a
...
@@ -1325,15 +1325,15 @@ ssize_t rdbSaveDb(rio *rdb, int dbid, int rdbflags, long *key_counter) {
...
@@ -1325,15 +1325,15 @@ ssize_t rdbSaveDb(rio *rdb, int dbid, int rdbflags, long *key_counter) {
/* Iterate this DB writing every entry */
/* Iterate this DB writing every entry */
while
((
de
=
dbIteratorNext
(
&
dbit
))
!=
NULL
)
{
while
((
de
=
dbIteratorNext
(
&
dbit
))
!=
NULL
)
{
/* Save slot info. */
/* Save slot info. */
if
(
server
.
cluster_enabled
&&
dbit
.
cur_
slot
!=
last_slot
)
{
if
(
server
.
cluster_enabled
&&
dbit
.
slot
!=
last_slot
)
{
serverAssert
(
dbit
.
cur_
slot
>=
0
&&
dbit
.
cur_
slot
<
CLUSTER_SLOTS
);
serverAssert
(
dbit
.
slot
>=
0
&&
dbit
.
slot
<
CLUSTER_SLOTS
);
if
((
res
=
rdbSaveType
(
rdb
,
RDB_OPCODE_SLOT_INFO
))
<
0
)
goto
werr
;
if
((
res
=
rdbSaveType
(
rdb
,
RDB_OPCODE_SLOT_INFO
))
<
0
)
goto
werr
;
written
+=
res
;
written
+=
res
;
if
((
res
=
rdbSaveLen
(
rdb
,
dbit
.
cur_
slot
))
<
0
)
goto
werr
;
if
((
res
=
rdbSaveLen
(
rdb
,
dbit
.
slot
))
<
0
)
goto
werr
;
written
+=
res
;
written
+=
res
;
if
((
res
=
rdbSaveLen
(
rdb
,
dictSize
(
db
->
dict
[
dbit
.
cur_
slot
])))
<
0
)
goto
werr
;
if
((
res
=
rdbSaveLen
(
rdb
,
dictSize
(
db
->
dict
[
dbit
.
slot
])))
<
0
)
goto
werr
;
written
+=
res
;
written
+=
res
;
last_slot
=
dbit
.
cur_
slot
;
last_slot
=
dbit
.
slot
;
}
}
sds
keystr
=
dictGetKey
(
de
);
sds
keystr
=
dictGetKey
(
de
);
robj
key
,
*
o
=
dictGetVal
(
de
);
robj
key
,
*
o
=
dictGetVal
(
de
);
...
...
src/server.c
View file @
ed138c0a
...
@@ -592,15 +592,17 @@ void tryResizeHashTables(int dbid) {
...
@@ -592,15 +592,17 @@ void tryResizeHashTables(int dbid) {
dbIterator
dbit
;
dbIterator
dbit
;
redisDb
*
db
=
&
server
.
db
[
dbid
];
redisDb
*
db
=
&
server
.
db
[
dbid
];
dbIteratorInit
(
&
dbit
,
db
);
dbIteratorInit
(
&
dbit
,
db
);
dbit
.
index
=
db
->
resize_cursor
;
if
(
db
->
resize_cursor
!=
-
1
)
{
dbit
.
next_slot
=
db
->
resize_cursor
;
}
for
(
int
i
=
0
;
i
<
CRON_DICTS_PER_CALL
;
i
++
)
{
for
(
int
i
=
0
;
i
<
CRON_DICTS_PER_CALL
;
i
++
)
{
d
=
dbIteratorNextDict
(
&
dbit
);
d
=
dbIteratorNextDict
(
&
dbit
);
if
(
d
==
NULL
)
break
;
if
(
!
d
)
break
;
if
(
htNeedsResize
(
d
))
if
(
htNeedsResize
(
d
))
dictResize
(
d
);
dictResize
(
d
);
}
}
/* Save current i
ndex
in the resize
cursor
, or start over if we've reached the end
.*/
/* Save current i
terator position
in the resize
_
cursor.
*/
db
->
resize_cursor
=
dbit
.
cur
_slot
==
-
1
?
0
:
dbit
.
index
;
db
->
resize_cursor
=
dbit
.
next
_slot
;
if
(
htNeedsResize
(
db
->
expires
))
if
(
htNeedsResize
(
db
->
expires
))
dictResize
(
db
->
expires
);
dictResize
(
db
->
expires
);
...
@@ -2633,7 +2635,6 @@ void initServer(void) {
...
@@ -2633,7 +2635,6 @@ void initServer(void) {
server
.
db
[
j
].
rehashing
=
listCreate
();
server
.
db
[
j
].
rehashing
=
listCreate
();
server
.
db
[
j
].
dict_count
=
slotCount
;
server
.
db
[
j
].
dict_count
=
slotCount
;
server
.
db
[
j
].
key_count
=
0
;
server
.
db
[
j
].
key_count
=
0
;
server
.
db
[
j
].
non_empty_dicts
=
server
.
cluster_enabled
?
intsetNew
()
:
NULL
;
server
.
db
[
j
].
binary_index
=
server
.
cluster_enabled
?
zcalloc
(
sizeof
(
unsigned
long
long
)
*
(
CLUSTER_SLOTS
+
1
))
:
NULL
;
server
.
db
[
j
].
binary_index
=
server
.
cluster_enabled
?
zcalloc
(
sizeof
(
unsigned
long
long
)
*
(
CLUSTER_SLOTS
+
1
))
:
NULL
;
listSetFreeMethod
(
server
.
db
[
j
].
defrag_later
,(
void
(
*
)(
void
*
))
sdsfree
);
listSetFreeMethod
(
server
.
db
[
j
].
defrag_later
,(
void
(
*
)(
void
*
))
sdsfree
);
}
}
...
...
src/server.h
View file @
ed138c0a
...
@@ -975,7 +975,6 @@ typedef struct redisDb {
...
@@ -975,7 +975,6 @@ typedef struct redisDb {
list
*
rehashing
;
/* List of dictionaries in this DB that are currently rehashing. */
list
*
rehashing
;
/* List of dictionaries in this DB that are currently rehashing. */
int
dict_count
;
/* Indicates total number of dictionaires owned by this DB, 1 dict per slot in cluster mode. */
int
dict_count
;
/* Indicates total number of dictionaires owned by this DB, 1 dict per slot in cluster mode. */
unsigned
long
long
key_count
;
/* Total number of keys in this DB. */
unsigned
long
long
key_count
;
/* Total number of keys in this DB. */
intset
*
non_empty_dicts
;
/* Set of non-empty dictionaries. */
unsigned
long
long
*
binary_index
;
/* Binary indexed tree (BIT) that describes cumulative key frequencies up until given slot. */
unsigned
long
long
*
binary_index
;
/* Binary indexed tree (BIT) that describes cumulative key frequencies up until given slot. */
}
redisDb
;
}
redisDb
;
...
@@ -2437,8 +2436,8 @@ typedef struct {
...
@@ -2437,8 +2436,8 @@ typedef struct {
/* Structure for DB iterator that allows iterating across multiple slot specific dictionaries in cluster mode. */
/* Structure for DB iterator that allows iterating across multiple slot specific dictionaries in cluster mode. */
typedef
struct
dbIterator
{
typedef
struct
dbIterator
{
redisDb
*
db
;
redisDb
*
db
;
int
index
;
int
slot
;
int
cur
_slot
;
int
next
_slot
;
dictIterator
di
;
dictIterator
di
;
}
dbIterator
;
}
dbIterator
;
...
@@ -2446,7 +2445,8 @@ typedef struct dbIterator {
...
@@ -2446,7 +2445,8 @@ typedef struct dbIterator {
void
dbIteratorInit
(
dbIterator
*
dbit
,
redisDb
*
db
);
void
dbIteratorInit
(
dbIterator
*
dbit
,
redisDb
*
db
);
dict
*
dbIteratorNextDict
(
dbIterator
*
dbit
);
dict
*
dbIteratorNextDict
(
dbIterator
*
dbit
);
dictEntry
*
dbIteratorNext
(
dbIterator
*
iter
);
dictEntry
*
dbIteratorNext
(
dbIterator
*
iter
);
dict
*
dbGetNextNonEmptySlot
(
redisDb
*
db
,
int
*
slot
);
int
dbGetNextNonEmptySlot
(
redisDb
*
db
,
int
slot
);
int
findSlotByKeyIndex
(
redisDb
*
db
,
unsigned
long
target
);
/* SCAN specific commands for easy cursor manipulation, shared between main code and modules. */
/* SCAN specific commands for easy cursor manipulation, shared between main code and modules. */
int
getAndClearSlotIdFromCursor
(
unsigned
long
long
int
*
cursor
);
int
getAndClearSlotIdFromCursor
(
unsigned
long
long
int
*
cursor
);
...
...
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