Repository: valkey-io/valkey
File: src/kvstore.c (C)

Code before:

bool kvstoreHashtableAdd(kvstore *kvs, int didx, void *entry) {
    hashtable *ht = createHashtableIfNeeded(kvs, didx);
    bool ret = hashtableAdd(ht, entry);
    if (ret) cumulativeKeyCountAdd(kvs, didx, 1);
    return ret;
}

bool kvstoreHashtableFindPositionForInsert(kvstore *kvs, int didx, void *key, hashtablePosition *position, void **existing) {
    hashtable *ht = createHashtableIfNeeded(kvs, didx);
    return hashtableFindPositionForInsert(ht, key, position, existing);
}

/* Must be used together with kvstoreHashtableFindPositionForInsert, with returned
 * position and with the same didx. */
void kvstoreHashtableInsertAtPosition(kvstore *kvs, int didx, void *entry, void *position) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    hashtableInsertAtPosition(ht, entry, position);
    cumulativeKeyCountAdd(kvs, didx, 1);
}

void **kvstoreHashtableTwoPhasePopFindRef(kvstore *kvs, int didx, const void *key, void *position) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    if (!ht) return NULL;
    return hashtableTwoPhasePopFindRef(ht, key, position);
}

void kvstoreHashtableTwoPhasePopDelete(kvstore *kvs, int didx, void *position) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    hashtableTwoPhasePopDelete(ht, position);
    cumulativeKeyCountAdd(kvs, didx, -1);
    freeHashtableIfNeeded(kvs, didx);
}

bool kvstoreHashtablePop(kvstore *kvs, int didx, const void *key, void **popped) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    if (!ht) return false;
    bool ret = hashtablePop(ht, key, popped);
    if (ret) {
        cumulativeKeyCountAdd(kvs, didx, -1);
        freeHashtableIfNeeded(kvs, didx);
    }
    return ret;
}

bool kvstoreHashtableDelete(kvstore *kvs, int didx, const void *key) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    if (!ht) return false;
    bool ret = hashtableDelete(ht, key);
    if (ret) {
        cumulativeKeyCountAdd(kvs, didx, -1);

Review comment (suggestion):
Skip if `size == 0`?

```suggestion
    if (size == 0) return false;
    hashtable *ht = createHashtableIfNeeded(kvs, didx);
```

Code after:
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    if (!ht) return false;
    return hashtableRandomEntry(ht, entry);
}

bool kvstoreHashtableFairRandomEntry(kvstore *kvs, int didx, void **entry) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    if (!ht) return false;
    return hashtableFairRandomEntry(ht, entry);
}

unsigned int kvstoreHashtableSampleEntries(kvstore *kvs, int didx, void **dst, unsigned int count) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    if (!ht) return 0;
    return hashtableSampleEntries(ht, dst, count);
}

bool kvstoreHashtableExpand(kvstore *kvs, int didx, unsigned long size) {
    if (size == 0) return false;
    hashtable *ht = createHashtableIfNeeded(kvs, didx);
    return hashtableExpand(ht, size);
}

bool kvstoreHashtableTryExpand(kvstore *kvs, int didx, unsigned long size) {
    if (size == 0) return false;
    hashtable *ht = createHashtableIfNeeded(kvs, didx);
    return hashtableTryExpand(ht, size);
}

unsigned long kvstoreHashtableScanDefrag(kvstore *kvs,
                                         int didx,
                                         unsigned long v,
                                         hashtableScanFunction fn,
                                         void *privdata,
                                         void *(*defragfn)(void *),
                                         int flags) {
    hashtable *ht = kvstoreGetHashtable(kvs, didx);
    if (!ht) return 0;
    return hashtableScanDefrag(ht, v, fn, privdata, defragfn, flags);
}

/* This function doesn't defrag the data (keys and values) within hashtable. It
 * only reallocates the memory used by the hashtable structure itself using the
 * provided allocation function. This feature was added for the active defrag
 * feature.
 *
 * A "cursor" is used to perform the operation iteratively.  When first called, a
 * cursor value of 0 should be provided.  The return value is an updated cursor which should be
 * provided on the next iteration.  The operation is complete when 0 is returned.
 *
 * The provided defragfn callback should return either NULL (if reallocation