Fix forget to update the dict's node in the kvstore's rehashing list after defragment (#13231)

Introducted by #13013

After defragmenting the dictionary in the kvstore, if the dict is
reallocated, the value of its node in the kvstore rehashing list must be
updated.
This commit is contained in:
debing.sun 2024-04-24 16:15:42 +08:00 committed by GitHub
parent 804110a487
commit 772564fc9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 2 deletions

View File

@ -46,7 +46,7 @@ void* activeDefragAlloc(void *ptr) {
/* move this allocation to a new allocation. /* move this allocation to a new allocation.
* make sure not to use the thread cache. so that we don't get back the same * make sure not to use the thread cache. so that we don't get back the same
* pointers we try to free */ * pointers we try to free */
size = zmalloc_size(ptr); size = zmalloc_usable_size(ptr);
newptr = zmalloc_no_tcache(size); newptr = zmalloc_no_tcache(size);
memcpy(newptr, ptr, size); memcpy(newptr, ptr, size);
zfree_no_tcache(ptr); zfree_no_tcache(ptr);

View File

@ -778,8 +778,15 @@ void kvstoreDictLUTDefrag(kvstore *kvs, kvstoreDictLUTDefragFunction *defragfn)
dict **d = kvstoreGetDictRef(kvs, didx), *newd; dict **d = kvstoreGetDictRef(kvs, didx), *newd;
if (!*d) if (!*d)
continue; continue;
if ((newd = defragfn(*d))) if ((newd = defragfn(*d))) {
*d = newd; *d = newd;
/* After defragmenting the dict, update its corresponding
* rehashing node in the kvstore's rehashing list. */
kvstoreDictMetadata *metadata = (kvstoreDictMetadata *)dictMetadata(*d);
if (metadata->rehashing_node)
metadata->rehashing_node->value = *d;
}
} }
} }
@ -862,6 +869,25 @@ void freeTestCallback(dict *d, void *val) {
zfree(val); zfree(val);
} }
void* defragAllocTest(void *ptr) {
size_t size = zmalloc_size(ptr);
void *newptr = zmalloc(size);
memcpy(newptr, ptr, size);
zfree(ptr);
return newptr;
}
dict *defragLUTTestCallback(dict *d) {
/* handle the dict struct */
d = defragAllocTest(d);
/* handle the first hash table */
d->ht_table[0] = defragAllocTest(d->ht_table[0]);
/* handle the second hash table */
if (d->ht_table[1])
d->ht_table[1] = defragAllocTest(d->ht_table[1]);
return d;
}
dictType KvstoreDictTestType = { dictType KvstoreDictTestType = {
hashTestCallback, hashTestCallback,
NULL, NULL,
@ -988,6 +1014,18 @@ int kvstoreTest(int argc, char **argv, int flags) {
assert(kvstoreSize(kvs2) == 0); assert(kvstoreSize(kvs2) == 0);
} }
TEST("Verify that a rehashing dict's node in the rehashing list is correctly updated after defragmentation") {
kvstore *kvs = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND);
for (i = 0; i < 256; i++) {
de = kvstoreDictAddRaw(kvs, 0, stringFromInt(i), NULL);
if (listLength(kvs->rehashing)) break;
}
assert(listLength(kvs->rehashing));
kvstoreDictLUTDefrag(kvs, defragLUTTestCallback);
while (kvstoreIncrementallyRehash(kvs, 1000)) {}
kvstoreRelease(kvs);
}
kvstoreRelease(kvs1); kvstoreRelease(kvs1);
kvstoreRelease(kvs2); kvstoreRelease(kvs2);
return 0; return 0;