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

Code before:
        /* If `n` is already my primary, there is no need to re-establish the
         * replication connection. */
        if (myself->replicaof == n) {
            addReply(c, shared.ok);
            return 1;
        }

        /* Set the primary.
         * If the instance is a primary, it is an empty primary.
         * If the instance is a replica, it had a totally different replication history.
         * In these both cases, myself as a replica has to do a full sync. */
        clusterSetPrimary(n, 1, 1);
        clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE | CLUSTER_TODO_SAVE_CONFIG | CLUSTER_TODO_BROADCAST_ALL);
        addReply(c, shared.ok);
    } else if (!strcasecmp(c->argv[1]->ptr, "count-failure-reports") && c->argc == 3) {
        /* CLUSTER COUNT-FAILURE-REPORTS <NODE ID> */
        clusterNode *n = clusterLookupNode(c->argv[2]->ptr, sdslen(c->argv[2]->ptr));

        if (!n) {
            addReplyErrorFormat(c, "Unknown node %s", (char *)c->argv[2]->ptr);
            return 1;
        } else {
            addReplyLongLong(c, clusterNodeFailureReportsCount(n));
        }
    } else if (!strcasecmp(c->argv[1]->ptr, "failover") && (c->argc >= 2)) {
        /* CLUSTER FAILOVER [FORCE|TAKEOVER] [replicaid <node id>] */
        int force = 0, takeover = 0;
        robj *replicaid = NULL;

        for (int j = 2; j < c->argc; j++) {
            int moreargs = (c->argc - 1) - j;
            if (!strcasecmp(c->argv[j]->ptr, "force")) {
                force = 1;
            } else if (!strcasecmp(c->argv[j]->ptr, "takeover")) {
                takeover = 1;
                force = 1; /* Takeover also implies force. */
            } else if (!strcasecmp(c->argv[j]->ptr, "replicaid") && moreargs) {
                j++;
                replicaid = c->argv[j];
            } else {
                addReplyErrorObject(c, shared.syntaxerr);
                return 1;
            }
        }

        /* Check if it should be executed by myself. */
        if (replicaid != NULL) {
            clusterNode *n = clusterLookupNode(replicaid->ptr, sdslen(replicaid->ptr));
            if (n != myself) {
                /* Ignore this command, including the sanity check and the process. */
                addReply(c, shared.ok);

Review comment (bug):
```suggestion
        /* CLUSTER FAILOVER [FORCE|TAKEOVER] [REPLICAID <node id>] */
```

Code after:
        for (j = 2; j < c->argc; j++) {
            if ((slot = getSlotOrReply(c, c->argv[j])) == -1) {
                zfree(slots);
                return 1;
            }
        }
        /* Check that the slots are not already busy. */
        for (j = 2; j < c->argc; j++) {
            slot = getSlotOrReply(c, c->argv[j]);
            if (checkSlotAssignmentsOrReply(c, slots, del, slot, slot) == 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, "addslotsrange") || !strcasecmp(c->argv[1]->ptr, "delslotsrange")) &&
               c->argc >= 4) {
        if (c->argc % 2 == 1) {
            addReplyErrorArity(c);
            return 1;
        }
        /* CLUSTER ADDSLOTSRANGE <start slot> <end slot> [<start slot> <end slot> ...] */
        /* CLUSTER DELSLOTSRANGE <start slot> <end slot> [<start slot> <end slot> ...] */
        int j, startslot, endslot;
        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])) == -1) {
                zfree(slots);
                return 1;
            }
            if ((endslot = getSlotOrReply(c, c->argv[j + 1])) == -1) {
                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;