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

Code before:
        char *alloc_ptr = sdsAllocPtr(entry);
        size_t required_size = field_size + value_size;
        size_t alloc_size;
        if (required_size <= CACHE_LINE_SIZE &&
            required_size <= (alloc_size = zmalloc_usable_size(alloc_ptr)) &&
            required_size >= alloc_size * 3 / 4) {
            /* It fits in the allocation and leaves max 25% unused space. */
            sdswrite(alloc_ptr + field_size, alloc_size - field_size, SDS_TYPE_8, value, value_len);
            sdsfree(value);
            return entry;
        }
        hashTypeEntry *new_entry = hashTypeCreateEntry(hashTypeEntryGetField(entry), value);
        freeHashTypeEntry(entry);
        return new_entry;
    }
    case ENTRY_ENC_PTR_VALUE: {
        if (field_size + value_size <= CACHE_LINE_SIZE) {
            /* Convert to entry with embedded value. */
            hashTypeEntry *new_entry = hashTypeCreateEntry(field, value);
            freeHashTypeEntry(entry);
            return new_entry;
        } else {
            /* Not embedded value. */
            hashTypeEntryPtrValue *entry_struct = getEntryStruct(entry);
            sdsfree(entry_struct->value);
            entry_struct->value = value;
            return entry;
        }
    }
    default:
        serverPanic("Unknown type");
    }
}

/* Returns memory usage of a hashTypeEntry, including all allocations owned by
 * the hashTypeEntry. */
size_t hashTypeEntryMemUsage(hashTypeEntry *entry) {
    switch (entryGetEncoding(entry)) {
    case ENTRY_ENC_EMB_VALUE:
        return zmalloc_usable_size(sdsAllocPtr(entry));
    case ENTRY_ENC_PTR_VALUE: {
        hashTypeEntryPtrValue *entry_struct = getEntryStruct(entry);
        return zmalloc_usable_size(entry_struct) + sdsAllocSize(entry_struct->value);
    }
    default:
        serverPanic("Unknown type");
    }
}

/* Defragments a hashtable entry (field-value pair) if needed, using the
 * provided defrag functions. The defrag functions return NULL if the allocation

Review comment (suggestion):
```suggestion
            sds *value_ref = encodedPtrValueEntryGetValueref(entry);
            sdsfree(*value_ref);
            *value_ref = value;
```

Code after:
        /* The value pointer is located before the embedded field. */
        if (field_size + value_size <= EMBED_VALUE_MAX_ALLOC_SIZE) {
            /* Convert to entry with embedded value. */
            hashTypeEntry *new_entry = hashTypeCreateEntry(field, value);
            freeHashTypeEntry(entry);
            return new_entry;
        } else {
            /* Not embedded value. */
            sds *value_ref = hashTypeEntryGetValueRef(entry);
            sdsfree(*value_ref);
            *value_ref = value;
            return entry;
        }
    }
}

/* Returns memory usage of a hashTypeEntry, including all allocations owned by
 * the hashTypeEntry. */
size_t hashTypeEntryMemUsage(hashTypeEntry *entry) {
    size_t mem = 0;
    if (entryHasValuePtr(entry)) {
        /* Alloc size is not stored in the embedded field. */
        mem = zmalloc_usable_size(hashTypeEntryAllocPtr(entry));
        mem += sdsAllocSize(*hashTypeEntryGetValueRef(entry));
    } else {
        /* Remaining alloc size is encoded in the embedded value SDS header. */
        sds field = entry;
        sds value = (char *)entry + sdslen(field) + 1 + sdsHdrSize(SDS_TYPE_8);
        size_t field_size = sdsHdrSize(sdsType(field)) + sdslen(field) + 1;
        size_t value_size = sdsHdrSize(SDS_TYPE_8) + sdsalloc(value) + 1;
        mem = field_size + value_size;
    }
    return mem;
}

/* Defragments a hashtable entry (field-value pair) if needed, using the
 * provided defrag functions. The defrag functions return NULL if the allocation
 * was not moved, otherwise they return a pointer to the new memory location.
 * A separate sds defrag function is needed because of the unique memory layout
 * of sds strings.
 * If the location of the hashTypeEntry changed we return the new location,
 * otherwise we return NULL. */
hashTypeEntry *hashTypeEntryDefrag(hashTypeEntry *entry, void *(*defragfn)(void *), sds (*sdsdefragfn)(sds)) {
    if (entryHasValuePtr(entry)) {
        sds *value_ref = hashTypeEntryGetValueRef(entry);
        sds new_value = sdsdefragfn(*value_ref);
        if (new_value) *value_ref = new_value;
    }
    return defragfn(hashTypeEntryAllocPtr(entry));
}