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

Code before:
 * SPDX-License-Identifier: BSD 3-Clause
 */

#include "cluster_slot_stats.h"

#define UNASSIGNED_SLOT 0

typedef enum {
    INVALID,
    KEY_COUNT,
    CPU_USEC,
} slotStatTypes;

/* -----------------------------------------------------------------------------
 * CLUSTER SLOT-STATS command
 * -------------------------------------------------------------------------- */

/* Struct used to temporarily hold slot statistics for sorting. */
typedef struct {
    int slot;
    uint64_t stat;
} slotStatForSort;

/* Struct used for storing slot statistics. */
typedef struct slotStat {
    uint64_t cpu;
} slotStat;

/* Struct used for storing slot statistics, for all slots owned by the current shard. */
struct slotStat cluster_slot_stats[CLUSTER_SLOTS];

static int doesSlotBelongToMyShard(int slot) {
    clusterNode *myself = getMyClusterNode();
    clusterNode *primary = clusterNodeGetPrimary(myself);

    return clusterNodeCoversSlot(primary, slot);
}

static int markSlotsAssignedToMyShard(unsigned char *assigned_slots, int start_slot, int end_slot) {
    int assigned_slots_count = 0;
    for (int slot = start_slot; slot <= end_slot; slot++) {
        if (doesSlotBelongToMyShard(slot)) {
            assigned_slots[slot]++;
            assigned_slots_count++;
        }
    }
    return assigned_slots_count;
}

static uint64_t getSlotStat(int slot, int stat_type) {
    serverAssert(stat_type != INVALID);

Review comment (suggestion):
I'm not sure how many fields we are planning to add to slotStat and the size of slotStat[16384] in stack.
Should we have a `kvstore` backed metadata dictionary to store the statistics. It has a nice property of lazy initialization of the dictionary only when a slot is used. 

Code after:
 * SPDX-License-Identifier: BSD 3-Clause
 */

#include "cluster_slot_stats.h"

#define UNASSIGNED_SLOT 0

typedef enum { KEY_COUNT, CPU_USEC, SLOT_STAT_COUNT, INVALID } slotStatTypes;

/* -----------------------------------------------------------------------------
 * CLUSTER SLOT-STATS command
 * -------------------------------------------------------------------------- */

/* Struct used to temporarily hold slot statistics for sorting. */
typedef struct {
    int slot;
    uint64_t stat;
} slotStatForSort;

static int doesSlotBelongToMyShard(int slot) {
    clusterNode *myself = getMyClusterNode();
    clusterNode *primary = clusterNodeGetPrimary(myself);

    return clusterNodeCoversSlot(primary, slot);
}

static int markSlotsAssignedToMyShard(unsigned char *assigned_slots, int start_slot, int end_slot) {
    int assigned_slots_count = 0;
    for (int slot = start_slot; slot <= end_slot; slot++) {
        if (doesSlotBelongToMyShard(slot)) {
            assigned_slots[slot]++;
            assigned_slots_count++;
        }
    }
    return assigned_slots_count;
}

static uint64_t getSlotStat(int slot, int stat_type) {
    serverAssert(stat_type != INVALID);
    uint64_t slot_stat = 0;
    if (stat_type == KEY_COUNT) {
        slot_stat = countKeysInSlot(slot);
    } else if (stat_type == CPU_USEC) {
        slot_stat = server.cluster->slot_stats[slot].cpu_usec;
    }
    return slot_stat;
}

/* Compare by stat in ascending order. If stat is the same, compare by slot in ascending order. */
static int slotStatForSortAscCmp(const void *a, const void *b) {
    slotStatForSort entry_a = *((slotStatForSort *)a);