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

Code before:
        if (hashtableIsRehashingPaused(ht)) return 0;
        while (hashtableIsRehashing(ht)) {
            rehashStep(ht);
        }
    }

    /* Allocate the new hash table. */
    bucket *new_table;
    if (malloc_failed) {
        new_table = ztrycalloc(alloc_size);
        if (new_table == NULL) {
            *malloc_failed = 1;
            return 0;
        }
    } else {
        new_table = zcalloc(alloc_size);
    }
    if (ht->type->trackMemUsage) ht->type->trackMemUsage(ht, alloc_size);
    ht->bucket_exp[1] = exp;
    ht->tables[1] = new_table;
    ht->used[1] = 0;
    ht->rehash_idx = 0;
    if (ht->type->rehashingStarted) ht->type->rehashingStarted(ht);

    /* If the old table was empty, the rehashing is completed immediately. */
    if (ht->tables[0] == NULL) {
        rehashingCompleted(ht);
    } else if (ht->type->instant_rehashing) {
        while (hashtableIsRehashing(ht)) {
            rehashStep(ht);
        }
    }
    return 1;
}

/* Returns 1 if the table is expanded, 0 if not expanded. If 0 is returned and
 * 'malloc_failed' is provided, it is set to 1 if malloc failed and 0
 * otherwise. */
static int expand(hashtable *ht, size_t size, int *malloc_failed) {
    if (size < hashtableSize(ht)) {
        return 0;
    }
    return resize(ht, size, malloc_failed);
}

/* Checks if a candidate entry in a bucket matches the given key.
 *
 * This function examines a specific position in a bucket to determine if the
 * entry at that position matches the provided key. If a match is found, it
 * updates the position and table index pointers and returns 1. Otherwise,
 * it returns 0. */

Review comment (suggestion):
If we want to keep the fast path to avoid iterating over the large table, we can add a check for `child_buckets[0] == 0` here. Is it worth it or is it a very unlikely case?

```suggestion
    if (ht->tables[0] == NULL || (ht->used[0] == 0 && ht->child_buckets[0] == 0)) {
```

Code after:
        if (hashtableIsRehashingPaused(ht)) return 0;
        while (hashtableIsRehashing(ht)) {
            rehashStep(ht);
        }
    }

    /* Allocate the new hash table. */
    bucket *new_table;
    if (malloc_failed) {
        new_table = ztrycalloc(alloc_size);
        if (new_table == NULL) {
            *malloc_failed = 1;
            return 0;
        }
    } else {
        new_table = zcalloc(alloc_size);
    }
    if (ht->type->trackMemUsage) ht->type->trackMemUsage(ht, alloc_size);
    ht->bucket_exp[1] = exp;
    ht->tables[1] = new_table;
    ht->used[1] = 0;
    ht->rehash_idx = 0;
    if (ht->type->rehashingStarted) ht->type->rehashingStarted(ht);

    /* If the old table was empty, the rehashing is completed immediately. */
    if (ht->tables[0] == NULL || (ht->used[0] == 0 && ht->child_buckets[0] == 0)) {
        rehashingCompleted(ht);
    } else if (ht->type->instant_rehashing) {
        while (hashtableIsRehashing(ht)) {
            rehashStep(ht);
        }
    }
    return 1;
}

/* Returns 1 if the table is expanded, 0 if not expanded. If 0 is returned and
 * 'malloc_failed' is provided, it is set to 1 if malloc failed and 0
 * otherwise. */
static int expand(hashtable *ht, size_t size, int *malloc_failed) {
    if (size < hashtableSize(ht)) {
        return 0;
    }
    return resize(ht, size, malloc_failed);
}

/* Checks if a candidate entry in a bucket matches the given key.
 *
 * This function examines a specific position in a bucket to determine if the
 * entry at that position matches the provided key. If a match is found, it
 * updates the position and table index pointers and returns 1. Otherwise,
 * it returns 0. */