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

Code before:
        case CLUSTER_ENDPOINT_TYPE_UNKNOWN_ENDPOINT:
            return "";
    }
    return "unknown";
}

int clusterAllowFailoverCmd(client *c) {
    if (!server.cluster_enabled) {
        return 1;
    }
    addReplyError(c,"FAILOVER not allowed in cluster mode. "
                    "Use CLUSTER FAILOVER command instead.");
    return 0;
}

void clusterPromoteSelfToMaster(void) {
    replicationUnsetMaster();
}

void updateNodesHealth(void) {
    dictIterator *di;
    dictEntry *de;
    clusterNode *node;
    int overall_health_changed = 0;
    di = dictGetSafeIterator(server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
        node = dictGetVal(de);
        int present_node_health;

        long long node_offset = getNodeOffSet(node);

        if (nodeFailed(node) || (nodeIsSlave(node) && node_offset == 0)) {
            present_node_health = 0;
        } else {
            present_node_health = 1;
        }

        if (present_node_health != node->node_health) {
            overall_health_changed = 1;
        }
        node->node_health = present_node_health;
    }
    dictReleaseIterator(di);

    if (overall_health_changed) clearCachedClusterSlotsResp();
}


Review comment (suggestion):
```suggestion
    dictIterator di;
    dictEntry *de;
    clusterNode *node;
    int overall_health_changed = 0;
    di = dictInitSafeIterator(&di, server.cluster->nodes);
    while((de = dictNext(di)) != NULL) {
```
You can stack allocate this iterator, then we don't need the alloc + free.

Code after:
        unsigned char *slots = zmalloc(CLUSTER_SLOTS);
        int del = !strcasecmp(c->argv[1]->ptr,"delslotsrange");

        memset(slots,0,CLUSTER_SLOTS);
        /* Check that all the arguments are parseable and that all the
         * slots are not already busy. */
        for (j = 2; j < c->argc; j += 2) {
            if ((startslot = getSlotOrReply(c,c->argv[j])) == C_ERR) {
                zfree(slots);
                return 1;
            }
            if ((endslot = getSlotOrReply(c,c->argv[j+1])) == C_ERR) {
                zfree(slots);
                return 1;
            }
            if (startslot > endslot) {
                addReplyErrorFormat(c,"start slot number %d is greater than end slot number %d", startslot, endslot);
                zfree(slots);
                return 1;
            }

            if (checkSlotAssignmentsOrReply(c, slots, del, startslot, endslot) == C_ERR) {
                zfree(slots);
                return 1;
            }
        }
        clusterUpdateSlots(c, slots, del);
        zfree(slots);
        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG);
        addReply(c,shared.ok);
    } else if (!strcasecmp(c->argv[1]->ptr,"setslot") && c->argc >= 4) {
        /* SETSLOT 10 MIGRATING <node ID> */
        /* SETSLOT 10 IMPORTING <node ID> */
        /* SETSLOT 10 STABLE */
        /* SETSLOT 10 NODE <node ID> */
        clusterCommandSetSlot(c);
    } else if (!strcasecmp(c->argv[1]->ptr,"bumpepoch") && c->argc == 2) {
        /* CLUSTER BUMPEPOCH */
        int retval = clusterBumpConfigEpochWithoutConsensus();
        sds reply = sdscatprintf(sdsempty(),"+%s %llu\r\n",
                (retval == C_OK) ? "BUMPED" : "STILL",
                (unsigned long long) myself->configEpoch);
        addReplySds(c,reply);
    } else if (!strcasecmp(c->argv[1]->ptr,"saveconfig") && c->argc == 2) {
        int retval = clusterSaveConfig(1);

        if (retval == 0)
            addReply(c,shared.ok);
        else
            addReplyErrorFormat(c,"error saving the cluster node config: %s",
                strerror(errno));