Fix resize hash table dictionary iterator (#12660)

Dictionary iterator logic in the `tryResizeHashTables` method is picking the next
(incorrect) dictionary while the cursor is at a given slot. This could lead to some
dictionary/slot getting skipped from resizing.

Also stabilize the test.

problem introduced recently in #11695
This commit is contained in:
Harkrishn Patro 2023-10-19 03:58:32 -07:00 committed by GitHub
parent 03345ddc7f
commit f3bf8485d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 5 additions and 17 deletions

View File

@ -608,8 +608,9 @@ void tryResizeHashTables(int dbid) {
for (dbKeyType subdict = DB_MAIN; subdict <= DB_EXPIRES; subdict++) {
dbIterator *dbit = dbIteratorInitFromSlot(db, subdict, db->sub_dict[subdict].resize_cursor);
for (int i = 0; i < CRON_DBS_PER_CALL; i++) {
dict *d = dbIteratorNextDict(dbit);
dict *d = dbGetDictFromIterator(dbit);
slot = dbIteratorGetCurrentSlot(dbit);
dbIteratorNextDict(dbit);
if (!d) break;
if (htNeedsResize(d))
dictResize(d);

View File

@ -2428,6 +2428,7 @@ typedef struct dbIterator dbIterator;
dbIterator *dbIteratorInit(redisDb *db, dbKeyType keyType);
dbIterator *dbIteratorInitFromSlot(redisDb *db, dbKeyType keyType, int slot);
dict *dbIteratorNextDict(dbIterator *dbit);
dict *dbGetDictFromIterator(dbIterator *dbit);
int dbIteratorGetCurrentSlot(dbIterator *dbit);
dictEntry *dbIteratorNext(dbIterator *iter);

View File

@ -834,7 +834,7 @@ start_server {tags {"expire"}} {
} {} {needs:debug}
}
start_cluster 1 0 {tags {"expire external:skip cluster"}} {
start_cluster 1 0 {tags {"expire external:skip cluster slow"}} {
test "expire scan should skip dictionaries with lot's of empty buckets" {
# Collect two slots to help determine the expiry scan logic is able
# to go past certain slots which aren't valid for scanning at the given point of time.
@ -851,8 +851,6 @@ start_cluster 1 0 {tags {"expire external:skip cluster"}} {
# hashslot(key) is 12539
r psetex key 500 val
assert_equal 102 [r dbsize]
# disable resizing
r config set rdb-key-save-delay 10000000
r bgsave
@ -882,23 +880,11 @@ start_cluster 1 0 {tags {"expire external:skip cluster"}} {
fail "bgsave did not stop in time."
}
# Verify dict is under rehashing
set htstats [r debug HTSTATS 0]
assert_match {*rehashing target*} $htstats
# put some data into slot 12182 and trigger the resize
r psetex "{foo}0" 500 a
# Verify dict rehashing has completed
set htstats [r debug HTSTATS 0]
wait_for_condition 20 100 {
![string match {*rehashing target*} $htstats]
} else {
fail "rehashing didn't complete"
}
# Verify all keys have expired
wait_for_condition 20 100 {
wait_for_condition 200 100 {
[r dbsize] eq 0
} else {
fail "Keys did not actively expire."