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

Code before:
}

char *clusterNodeGetShardId(clusterNode *node) {
    return node->shard_id;
}

/* clusterParseSetSlotCommand validates the arguments of the CLUSTER SETSLOT command,
 * extracts the target slot number (slot_out), and determines the target node (node_out)
 * if applicable. It also calculates a timeout value (timeout_out) based on an optional
 * timeout argument. If provided, the timeout is added to the current time to obtain an
 * absolute timestamp; if omitted, the default timeout CLUSTER_OPERATION_TIMEOUT is used;
 * if set to 0, it indicates no timeout. The function returns 1 if successful, and 0
 * otherwise, after sending an error message to the client. */
int clusterParseSetSlotCommand(client *c, int *slot_out, clusterNode **node_out, mstime_t *timeout_out) {
    int slot = -1;
    clusterNode *n = NULL;
    mstime_t timeout = commandTimeSnapshot() + CLUSTER_OPERATION_TIMEOUT;
    int optarg_pos = 0;

    /* Allow primaries to replicate "CLUSTER SETSLOT" */
    if (!c->flag.primary && nodeIsReplica(myself)) {
        addReplyError(c, "Please use SETSLOT only with masters.");
        return 0;
    }

    if (nodeIsReplica(myself)) serverAssert(c == server.primary);

    if ((slot = getSlotOrReply(c, c->argv[2])) == -1) return 0;

    if (!strcasecmp(c->argv[3]->ptr, "migrating") && c->argc >= 5) {
        /* CLUSTER SETSLOT <SLOT> MIGRATING <NODE> */
        if (nodeIsPrimary(myself) && server.cluster->slots[slot] != myself) {
            addReplyErrorFormat(c, "I'm not the owner of hash slot %u", slot);
            return 0;
        }
        n = clusterLookupNode(c->argv[4]->ptr, sdslen(c->argv[4]->ptr));
        if (n == NULL) {
            addReplyErrorFormat(c, "I don't know about node %s", (char *)c->argv[4]->ptr);
            return 0;
        }
        if (nodeIsReplica(n)) {
            addReplyError(c, "Target node is not a master");
            return 0;
        }
        if (c->argc > 5) optarg_pos = 5;
    } else if (!strcasecmp(c->argv[3]->ptr, "importing") && c->argc >= 5) {
        /* CLUSTER SETSLOT <SLOT> IMPORTING <NODE> */
        if (server.cluster->slots[slot] == myself) {
            addReplyErrorFormat(c, "I'm already the owner of hash slot %u", slot);
            return 0;
        }

Review comment (suggestion):
```suggestion
    /* If 'myself' is a replica, 'c' must be the primary client. */
    serverAssert(!nodeIsReplica(myself) || c == server.primary);
```

Code after:
}

char *clusterNodeGetShardId(clusterNode *node) {
    return node->shard_id;
}

/* clusterParseSetSlotCommand validates the arguments of the CLUSTER SETSLOT command,
 * extracts the target slot number (slot_out), and determines the target node (node_out)
 * if applicable. It also calculates a timeout value (timeout_out) based on an optional
 * timeout argument. If provided, the timeout is added to the current time to obtain an
 * absolute timestamp; if omitted, the default timeout CLUSTER_OPERATION_TIMEOUT is used;
 * if set to 0, it indicates no timeout. The function returns 1 if successful, and 0
 * otherwise, after sending an error message to the client. */
int clusterParseSetSlotCommand(client *c, int *slot_out, clusterNode **node_out, mstime_t *timeout_out) {
    int slot = -1;
    clusterNode *n = NULL;
    mstime_t timeout = commandTimeSnapshot() + CLUSTER_OPERATION_TIMEOUT;
    int optarg_pos = 0;

    /* Allow primaries to replicate "CLUSTER SETSLOT" */
    if (!c->flag.primary && nodeIsReplica(myself)) {
        addReplyError(c, "Please use SETSLOT only with masters.");
        return 0;
    }

    /* If 'myself' is a replica, 'c' must be the primary client. */
    serverAssert(!nodeIsReplica(myself) || c == server.primary);

    if ((slot = getSlotOrReply(c, c->argv[2])) == -1) return 0;

    if (!strcasecmp(c->argv[3]->ptr, "migrating") && c->argc >= 5) {
        /* CLUSTER SETSLOT <SLOT> MIGRATING <NODE> */
        if (nodeIsPrimary(myself) && server.cluster->slots[slot] != myself) {
            addReplyErrorFormat(c, "I'm not the owner of hash slot %u", slot);
            return 0;
        }
        n = clusterLookupNode(c->argv[4]->ptr, sdslen(c->argv[4]->ptr));
        if (n == NULL) {
            addReplyErrorFormat(c, "I don't know about node %s", (char *)c->argv[4]->ptr);
            return 0;
        }
        if (nodeIsReplica(n)) {
            addReplyError(c, "Target node is not a master");
            return 0;
        }
        if (c->argc > 5) optarg_pos = 5;
    } else if (!strcasecmp(c->argv[3]->ptr, "importing") && c->argc >= 5) {
        /* CLUSTER SETSLOT <SLOT> IMPORTING <NODE> */
        if (server.cluster->slots[slot] == myself) {
            addReplyErrorFormat(c, "I'm already the owner of hash slot %u", slot);
            return 0;