Skip to content

Commit 983e486

Browse files
enjoy-binbinzuiderkwast
authored andcommitted
Fix pre-size hashtables per slot when reading RDB files (#2466)
When reading RDB files with information about the number of keys per cluster slot, we need to create the dicts if they don't exist. Currently, when processing RDB slot-info, our expand has no effect because the dict does not exist (we initialize it only when we need it). We also update kvstoreExpand to use the kvstoreDictExpand to make sure there is only one code path. Also see #1199 for more details. Signed-off-by: Binbin <[email protected]>
1 parent ca45554 commit 983e486

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

src/kvstore.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,11 @@ int kvstoreExpand(kvstore *kvs, uint64_t newsize, int try_expand, kvstoreExpandS
425425
if (newsize == 0) return 1;
426426
for (int i = 0; i < kvs->num_dicts; i++) {
427427
if (skip_cb && skip_cb(i)) continue;
428-
/* If the dictionary doesn't exist, create it */
429-
dict *d = createDictIfNeeded(kvs, i);
430-
int result = try_expand ? dictTryExpand(d, newsize) : dictExpand(d, newsize);
431-
if (try_expand && result == DICT_ERR) return 0;
428+
if (try_expand) {
429+
if (kvstoreDictTryExpand(kvs, i, newsize) == DICT_ERR) return 0;
430+
} else {
431+
kvstoreDictExpand(kvs, i, newsize);
432+
}
432433
}
433434

434435
return 1;
@@ -673,6 +674,12 @@ unsigned long kvstoreDictSize(kvstore *kvs, int didx) {
673674
return dictSize(d);
674675
}
675676

677+
unsigned long kvstoreDictBuckets(kvstore *kvs, int didx) {
678+
dict *d = kvstoreGetDict(kvs, didx);
679+
if (!d) return 0;
680+
return dictBuckets(d);
681+
}
682+
676683
kvstoreDictIterator *kvstoreGetDictIterator(kvstore *kvs, int didx) {
677684
kvstoreDictIterator *kvs_di = zmalloc(sizeof(*kvs_di));
678685
kvs_di->kvs = kvs;
@@ -729,11 +736,17 @@ unsigned int kvstoreDictGetSomeKeys(kvstore *kvs, int didx, dictEntry **des, uns
729736
}
730737

731738
int kvstoreDictExpand(kvstore *kvs, int didx, unsigned long size) {
732-
dict *d = kvstoreGetDict(kvs, didx);
733-
if (!d) return DICT_ERR;
739+
if (size == 0) return DICT_ERR;
740+
dict *d = createDictIfNeeded(kvs, didx);
734741
return dictExpand(d, size);
735742
}
736743

744+
int kvstoreDictTryExpand(kvstore *kvs, int didx, unsigned long size) {
745+
if (size == 0) return DICT_ERR;
746+
dict *d = createDictIfNeeded(kvs, didx);
747+
return dictTryExpand(d, size);
748+
}
749+
737750
unsigned long kvstoreDictScanDefrag(kvstore *kvs,
738751
int didx,
739752
unsigned long v,

src/kvstore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ unsigned long kvstoreDictRehashingCount(kvstore *kvs);
5656

5757
/* Specific dict access by dict-index */
5858
unsigned long kvstoreDictSize(kvstore *kvs, int didx);
59+
unsigned long kvstoreDictBuckets(kvstore *kvs, int didx);
5960
kvstoreDictIterator *kvstoreGetDictIterator(kvstore *kvs, int didx);
6061
kvstoreDictIterator *kvstoreGetDictSafeIterator(kvstore *kvs, int didx);
6162
void kvstoreReleaseDictIterator(kvstoreDictIterator *kvs_id);
@@ -64,6 +65,7 @@ dictEntry *kvstoreDictGetRandomKey(kvstore *kvs, int didx);
6465
dictEntry *kvstoreDictGetFairRandomKey(kvstore *kvs, int didx);
6566
unsigned int kvstoreDictGetSomeKeys(kvstore *kvs, int didx, dictEntry **des, unsigned int count);
6667
int kvstoreDictExpand(kvstore *kvs, int didx, unsigned long size);
68+
int kvstoreDictTryExpand(kvstore *kvs, int didx, unsigned long size);
6769
unsigned long kvstoreDictScanDefrag(kvstore *kvs,
6870
int didx,
6971
unsigned long v,

src/rdb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3157,8 +3157,8 @@ int rdbLoadRioWithLoadingCtx(rio *rdb, int rdbflags, rdbSaveInfo *rsi, rdbLoadin
31573157
if (server.cluster_enabled) {
31583158
/* In cluster mode we resize individual slot specific dictionaries based on the number of keys that
31593159
* slot holds. */
3160-
kvstoreDictExpand(db->keys, slot_id, slot_size);
3161-
kvstoreDictExpand(db->expires, slot_id, expires_slot_size);
3160+
if (slot_size) kvstoreDictExpand(db->keys, slot_id, slot_size);
3161+
if (expires_slot_size) kvstoreDictExpand(db->expires, slot_id, expires_slot_size);
31623162
should_expand_db = 0;
31633163
}
31643164
} else {

src/unit/test_files.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ int test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict(int argc, char **argv, in
3333
int test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict(int argc, char **argv, int flags);
3434
int test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict(int argc, char **argv, int flags);
3535
int test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict(int argc, char **argv, int flags);
36+
int test_kvstoreDictExpand(int argc, char **argv, int flags);
3637
int test_listpackCreateIntList(int argc, char **argv, int flags);
3738
int test_listpackCreateList(int argc, char **argv, int flags);
3839
int test_listpackLpPrepend(int argc, char **argv, int flags);
@@ -144,7 +145,7 @@ unitTest __test_crc64combine_c[] = {{"test_crc64combine", test_crc64combine}, {N
144145
unitTest __test_dict_c[] = {{"test_dictCreate", test_dictCreate}, {"test_dictAdd16Keys", test_dictAdd16Keys}, {"test_dictDisableResize", test_dictDisableResize}, {"test_dictAddOneKeyTriggerResize", test_dictAddOneKeyTriggerResize}, {"test_dictDeleteKeys", test_dictDeleteKeys}, {"test_dictDeleteOneKeyTriggerResize", test_dictDeleteOneKeyTriggerResize}, {"test_dictEmptyDirAdd128Keys", test_dictEmptyDirAdd128Keys}, {"test_dictDisableResizeReduceTo3", test_dictDisableResizeReduceTo3}, {"test_dictDeleteOneKeyTriggerResizeAgain", test_dictDeleteOneKeyTriggerResizeAgain}, {"test_dictBenchmark", test_dictBenchmark}, {NULL, NULL}};
145146
unitTest __test_endianconv_c[] = {{"test_endianconv", test_endianconv}, {NULL, NULL}};
146147
unitTest __test_intset_c[] = {{"test_intsetValueEncodings", test_intsetValueEncodings}, {"test_intsetBasicAdding", test_intsetBasicAdding}, {"test_intsetLargeNumberRandomAdd", test_intsetLargeNumberRandomAdd}, {"test_intsetUpgradeFromint16Toint32", test_intsetUpgradeFromint16Toint32}, {"test_intsetUpgradeFromint16Toint64", test_intsetUpgradeFromint16Toint64}, {"test_intsetUpgradeFromint32Toint64", test_intsetUpgradeFromint32Toint64}, {"test_intsetStressLookups", test_intsetStressLookups}, {"test_intsetStressAddDelete", test_intsetStressAddDelete}, {NULL, NULL}};
147-
unitTest __test_kvstore_c[] = {{"test_kvstoreAdd16Keys", test_kvstoreAdd16Keys}, {"test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict", test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict}, {"test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict", test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict}, {"test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict", test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict}, {"test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict", test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict}, {NULL, NULL}};
148+
unitTest __test_kvstore_c[] = {{"test_kvstoreAdd16Keys", test_kvstoreAdd16Keys}, {"test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict", test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict}, {"test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict", test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict}, {"test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict", test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict}, {"test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict", test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict}, {"test_kvstoreDictExpand", test_kvstoreDictExpand}, {NULL, NULL}};
148149
unitTest __test_listpack_c[] = {{"test_listpackCreateIntList", test_listpackCreateIntList}, {"test_listpackCreateList", test_listpackCreateList}, {"test_listpackLpPrepend", test_listpackLpPrepend}, {"test_listpackLpPrependInteger", test_listpackLpPrependInteger}, {"test_listpackGetELementAtIndex", test_listpackGetELementAtIndex}, {"test_listpackPop", test_listpackPop}, {"test_listpackGetELementAtIndex2", test_listpackGetELementAtIndex2}, {"test_listpackIterate0toEnd", test_listpackIterate0toEnd}, {"test_listpackIterate1toEnd", test_listpackIterate1toEnd}, {"test_listpackIterate2toEnd", test_listpackIterate2toEnd}, {"test_listpackIterateBackToFront", test_listpackIterateBackToFront}, {"test_listpackIterateBackToFrontWithDelete", test_listpackIterateBackToFrontWithDelete}, {"test_listpackDeleteWhenNumIsMinusOne", test_listpackDeleteWhenNumIsMinusOne}, {"test_listpackDeleteWithNegativeIndex", test_listpackDeleteWithNegativeIndex}, {"test_listpackDeleteInclusiveRange0_0", test_listpackDeleteInclusiveRange0_0}, {"test_listpackDeleteInclusiveRange0_1", test_listpackDeleteInclusiveRange0_1}, {"test_listpackDeleteInclusiveRange1_2", test_listpackDeleteInclusiveRange1_2}, {"test_listpackDeleteWitStartIndexOutOfRange", test_listpackDeleteWitStartIndexOutOfRange}, {"test_listpackDeleteWitNumOverflow", test_listpackDeleteWitNumOverflow}, {"test_listpackBatchDelete", test_listpackBatchDelete}, {"test_listpackDeleteFooWhileIterating", test_listpackDeleteFooWhileIterating}, {"test_listpackReplaceWithSameSize", test_listpackReplaceWithSameSize}, {"test_listpackReplaceWithDifferentSize", test_listpackReplaceWithDifferentSize}, {"test_listpackRegressionGt255Bytes", test_listpackRegressionGt255Bytes}, {"test_listpackCreateLongListAndCheckIndices", test_listpackCreateLongListAndCheckIndices}, {"test_listpackCompareStrsWithLpEntries", test_listpackCompareStrsWithLpEntries}, {"test_listpackLpMergeEmptyLps", test_listpackLpMergeEmptyLps}, {"test_listpackLpMergeLp1Larger", test_listpackLpMergeLp1Larger}, {"test_listpackLpMergeLp2Larger", test_listpackLpMergeLp2Larger}, {"test_listpackLpNextRandom", test_listpackLpNextRandom}, {"test_listpackLpNextRandomCC", test_listpackLpNextRandomCC}, {"test_listpackRandomPairWithOneElement", test_listpackRandomPairWithOneElement}, {"test_listpackRandomPairWithManyElements", test_listpackRandomPairWithManyElements}, {"test_listpackRandomPairsWithOneElement", test_listpackRandomPairsWithOneElement}, {"test_listpackRandomPairsWithManyElements", test_listpackRandomPairsWithManyElements}, {"test_listpackRandomPairsUniqueWithOneElement", test_listpackRandomPairsUniqueWithOneElement}, {"test_listpackRandomPairsUniqueWithManyElements", test_listpackRandomPairsUniqueWithManyElements}, {"test_listpackPushVariousEncodings", test_listpackPushVariousEncodings}, {"test_listpackLpFind", test_listpackLpFind}, {"test_listpackLpValidateIntegrity", test_listpackLpValidateIntegrity}, {"test_listpackNumberOfElementsExceedsLP_HDR_NUMELE_UNKNOWN", test_listpackNumberOfElementsExceedsLP_HDR_NUMELE_UNKNOWN}, {"test_listpackStressWithRandom", test_listpackStressWithRandom}, {"test_listpackSTressWithVariableSize", test_listpackSTressWithVariableSize}, {"test_listpackBenchmarkInit", test_listpackBenchmarkInit}, {"test_listpackBenchmarkLpAppend", test_listpackBenchmarkLpAppend}, {"test_listpackBenchmarkLpFindString", test_listpackBenchmarkLpFindString}, {"test_listpackBenchmarkLpFindNumber", test_listpackBenchmarkLpFindNumber}, {"test_listpackBenchmarkLpSeek", test_listpackBenchmarkLpSeek}, {"test_listpackBenchmarkLpValidateIntegrity", test_listpackBenchmarkLpValidateIntegrity}, {"test_listpackBenchmarkLpCompareWithString", test_listpackBenchmarkLpCompareWithString}, {"test_listpackBenchmarkLpCompareWithNumber", test_listpackBenchmarkLpCompareWithNumber}, {"test_listpackBenchmarkFree", test_listpackBenchmarkFree}, {NULL, NULL}};
149150
unitTest __test_rax_c[] = {{"test_raxRecompressHugeKey", test_raxRecompressHugeKey}, {NULL, NULL}};
150151
unitTest __test_sds_c[] = {{"test_sds", test_sds}, {"test_typesAndAllocSize", test_typesAndAllocSize}, {"test_sdsHeaderSizes", test_sdsHeaderSizes}, {NULL, NULL}};

src/unit/test_kvstore.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,20 @@ int test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict(int argc, char **argv,
203203
kvstoreRelease(kvs2);
204204
return 0;
205205
}
206+
207+
int test_kvstoreDictExpand(int argc, char **argv, int flags) {
208+
UNUSED(argc);
209+
UNUSED(argv);
210+
UNUSED(flags);
211+
212+
kvstore *kvs = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND | KVSTORE_FREE_EMPTY_DICTS);
213+
214+
TEST_ASSERT(kvstoreGetDict(kvs, 0) == NULL);
215+
TEST_ASSERT(kvstoreDictExpand(kvs, 0, 10000) == DICT_OK);
216+
TEST_ASSERT(kvstoreGetDict(kvs, 0) != NULL);
217+
TEST_ASSERT(kvstoreBuckets(kvs) > 0);
218+
TEST_ASSERT(kvstoreBuckets(kvs) == kvstoreDictBuckets(kvs, 0));
219+
220+
kvstoreRelease(kvs);
221+
return 0;
222+
}

0 commit comments

Comments
 (0)