From 52633e950020088b110b0a6553a227d40c3ac087 Mon Sep 17 00:00:00 2001 From: Wen Hui Date: Mon, 1 Nov 2021 16:23:43 -0400 Subject: [PATCH] Add gossip and custom name support --- src/cluster.c | 239 ++++++++++++++++++++++---------------- src/cluster.h | 8 +- src/redis-cli.c | 20 ++-- tests/cluster/cluster.tcl | 11 +- tests/support/cluster.tcl | 5 +- 5 files changed, 166 insertions(+), 117 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 42f8a523788..a4537a5a2d5 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -214,20 +214,16 @@ int clusterLoadConfig(char *filename) { clusterAddNode(n); } - /*Check if human readable name is present*/ - int offset = 0; - if (strrchr(argv[1],'_') != NULL){ - n->hname = argv[1]; - offset = 1; - } + /*Human readable name*/ + memcpy(n->human_readable_name, argv[1], strlen(argv[1]) + 1); /* Address and port */ - if ((p = strrchr(argv[offset + 1],':')) == NULL) { + if ((p = strrchr(argv[2],':')) == NULL) { sdsfreesplitres(argv,argc); goto fmterr; } *p = '\0'; - memcpy(n->ip,argv[offset + 1],strlen(argv[offset + 1])+1); + memcpy(n->ip,argv[2],strlen(argv[2])+1); char *port = p+1; char *busp = strchr(port,'@'); if (busp) { @@ -244,7 +240,7 @@ int clusterLoadConfig(char *filename) { * stored in nodes.conf. It is received later over the bus protocol. */ /* Parse flags */ - p = s = argv[offset + 2]; + p = s = argv[3]; while(p) { p = strchr(s,','); if (p) *p = '\0'; @@ -277,25 +273,28 @@ int clusterLoadConfig(char *filename) { /* Get master if any. Set the master and populate master's * slave list. */ - if (argv[offset + 3][0] != '-') { - master = clusterLookupNode(argv[offset + 3]); + if (argv[4][0] != '-') { + master = clusterLookupNode(argv[4]); if (!master) { - master = createClusterNode(argv[offset + 3],0); + master = createClusterNode(argv[4],0); clusterAddNode(master); } n->slaveof = master; clusterNodeAddSlave(master,n); } + /* Custom nodename */ + n->has_human_readable_name = atoi(argv[5]); + /* Set ping sent / pong received timestamps */ - if (atoi(argv[offset + 4])) n->ping_sent = mstime(); - if (atoi(argv[offset + 5])) n->pong_received = mstime(); + if (atoi(argv[6])) n->ping_sent = mstime(); + if (atoi(argv[7])) n->pong_received = mstime(); /* Set configEpoch for this node. */ - n->configEpoch = strtoull(argv[offset + 6],NULL,10); + n->configEpoch = strtoull(argv[8],NULL,10); /* Populate hash slots served by this instance. */ - for (j = offset + 8; j < argc; j++) { + for (j = 10; j < argc; j++) { int start, stop; if (argv[j][0] == '[') { @@ -349,7 +348,7 @@ int clusterLoadConfig(char *filename) { zfree(line); fclose(fp); - serverLog(LL_NOTICE,"Node configuration loaded, I'm %.40s", myself->name); + serverLog(LL_NOTICE,"Node configuration loaded, I'm %.40s %s", myself->name, myself->human_readable_name); /* Something that should never happen: currentEpoch smaller than * the max epoch found in the nodes configuration. However we handle this @@ -597,8 +596,8 @@ void clusterInit(void) { * by the createClusterNode() function. */ myself = server.cluster->myself = createClusterNode(NULL,CLUSTER_NODE_MYSELF|CLUSTER_NODE_MASTER); - serverLog(LL_NOTICE,"No cluster configuration found, I'm %.40s", - myself->name); + serverLog(LL_NOTICE,"No cluster configuration found, I'm %.40s %s", + myself->name, myself->human_readable_name); clusterAddNode(myself); saveconf = 1; } @@ -700,7 +699,7 @@ void clusterReset(int hard) { sdsfree(oldname); getRandomHexChars(myself->name, CLUSTER_NAMELEN); clusterAddNode(myself); - serverLog(LL_NOTICE,"Node hard reset, now I'm %.40s", myself->name); + serverLog(LL_NOTICE,"Node hard reset, now I'm %.40s %s", myself->name, myself->human_readable_name); } /* Make sure to persist the new config and update the state. */ @@ -862,18 +861,21 @@ unsigned int keyHashSlot(char *key, int keylen) { /* Assign a human readable name to nodes for clusters*/ void setClusterNodeName(clusterNode *node) { - char *name; - int post_digits; - if (node->port == 0){ - post_digits = 0; - } - else{ - post_digits = floor(log10(abs(node->port))) + 1; - } - int allocate_len = sizeof(node->ip) + post_digits + 2; - name = zmalloc(allocate_len); - sprintf(name, "%s%s%d", node->ip, "_", node->port); - node->hname = name; + if (node->has_human_readable_name == 1) + return; + char ip[NET_IP_STR_LEN]; + strcpy(ip,node->ip); + sprintf(node->human_readable_name, "%s_%u", ip,(unsigned int)node->port); +} + +/* Manually assign a human readable name to nodes for clusters*/ +int setManualClusterNodeName(clusterNode *node, char * newname) { + if (newname == NULL) + return 0; + memcpy(node->human_readable_name, newname, strlen(newname) + 1); + node->has_human_readable_name = 1; + clusterSaveConfig(1); + return 1; } /* Create a new cluster node, with the specified flags. @@ -896,6 +898,7 @@ clusterNode *createClusterNode(char *nodename, int flags) { memset(node->slots,0,sizeof(node->slots)); node->slots_info = NULL; node->numslots = 0; + node->has_human_readable_name = 0; node->numslaves = 0; node->slaves = NULL; node->slaveof = NULL; @@ -904,6 +907,7 @@ clusterNode *createClusterNode(char *nodename, int flags) { node->fail_time = 0; node->link = NULL; memset(node->ip,0,sizeof(node->ip)); + memset(node->human_readable_name,0,sizeof(node->human_readable_name)); node->port = 0; node->cport = 0; node->pport = 0; @@ -1133,7 +1137,7 @@ clusterNode *clusterLookupNode(const char *name) { de = dictFind(server.cluster->nodes,s); sdsfree(s); - if (de == NULL){ + if (de == NULL) { /* Check if any node has the same human readable name*/ dictIterator *di; dictEntry *de2; @@ -1141,14 +1145,12 @@ clusterNode *clusterLookupNode(const char *name) { di = dictGetSafeIterator(server.cluster->nodes); while((de2 = dictNext(di)) != NULL) { clusterNode *node = dictGetVal(de2); - if (node->hname){ - if (strcmp(node->hname,name ) == 0) - return node; - } + if (strcmp(node->human_readable_name,name) == 0) + return node; } dictReleaseIterator(di); return NULL; - } + } return dictGetVal(de); } @@ -1295,9 +1297,9 @@ void clusterHandleConfigEpochCollision(clusterNode *sender) { myself->configEpoch = server.cluster->currentEpoch; clusterSaveConfigOrDie(1); serverLog(LL_VERBOSE, - "WARNING: configEpoch collision with node %.40s." + "WARNING: configEpoch collision with node %.40s %s." " configEpoch set to %llu", - sender->name, + sender->name, sender->human_readable_name, (unsigned long long) myself->configEpoch); } @@ -1413,7 +1415,7 @@ void markNodeAsFailingIfNeeded(clusterNode *node) { if (failures < needed_quorum) return; /* No weak agreement from masters. */ serverLog(LL_NOTICE, - "Marking node %.40s as failing (quorum reached).", node->name); + "Marking node %.40s %s as failing (quorum reached).", node->name, node ->human_readable_name); /* Mark the node as failing. */ node->flags &= ~CLUSTER_NODE_PFAIL; @@ -1441,8 +1443,8 @@ void clearNodeFailureIfNeeded(clusterNode *node) { * node again. */ if (nodeIsSlave(node) || node->numslots == 0) { serverLog(LL_NOTICE, - "Clear FAIL state for node %.40s: %s is reachable again.", - node->name, + "Clear FAIL state for node %.40s %s: %s is reachable again.", + node->name, node->human_readable_name, nodeIsSlave(node) ? "replica" : "master without slots"); node->flags &= ~CLUSTER_NODE_FAIL; clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG); @@ -1457,8 +1459,8 @@ void clearNodeFailureIfNeeded(clusterNode *node) { (server.cluster_node_timeout * CLUSTER_FAIL_UNDO_TIME_MULT)) { serverLog(LL_NOTICE, - "Clear FAIL state for node %.40s: is reachable again and nobody is serving its slots after some time.", - node->name); + "Clear FAIL state for node %.40s %s: is reachable again and nobody is serving its slots after some time.", + node->name, node->human_readable_name); node->flags &= ~CLUSTER_NODE_FAIL; clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE|CLUSTER_TODO_SAVE_CONFIG); } @@ -1579,15 +1581,15 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { if (flags & (CLUSTER_NODE_FAIL|CLUSTER_NODE_PFAIL)) { if (clusterNodeAddFailureReport(node,sender)) { serverLog(LL_VERBOSE, - "Node %.40s reported node %.40s as not reachable.", - sender->name, node->name); + "Node %.40s %s reported node %.40s %s as not reachable.", + sender->name, sender->human_readable_name, node->name, node->human_readable_name); } markNodeAsFailingIfNeeded(node); } else { if (clusterNodeDelFailureReport(node,sender)) { serverLog(LL_VERBOSE, - "Node %.40s reported node %.40s is back online.", - sender->name, node->name); + "Node %.40s %s reported node %.40s %s is back online.", + sender->name, sender->human_readable_name, node->name, node->human_readable_name); } } } @@ -1632,7 +1634,10 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { node->pport = ntohs(g->pport); node->cport = ntohs(g->cport); node->flags &= ~CLUSTER_NODE_NOADDR; - setClusterNodeName(node); + if (hdr->has_human_readable_name) + setManualClusterNodeName(node, hdr->human_readable_name); + else + setClusterNodeName(node); } } else { /* If it's not in NOADDR state and we don't have it, we @@ -1654,7 +1659,10 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { node->port = ntohs(g->port); node->pport = ntohs(g->pport); node->cport = ntohs(g->cport); - setClusterNodeName(node); + if (hdr->has_human_readable_name) + setManualClusterNodeName(node, hdr->human_readable_name); + else + setClusterNodeName(node); clusterAddNode(node); } } @@ -1713,11 +1721,14 @@ int nodeUpdateAddressIfNeeded(clusterNode *node, clusterLink *link, node->port = port; node->pport = pport; node->cport = cport; - setClusterNodeName(node); + if (hdr->has_human_readable_name) + setManualClusterNodeName(node, hdr->human_readable_name); + else + setClusterNodeName(node); if (node->link) freeClusterLink(node->link); node->flags &= ~CLUSTER_NODE_NOADDR; - serverLog(LL_WARNING,"Address updated for node %.40s, now %s:%d", - node->name, node->ip, node->port); + serverLog(LL_WARNING,"Address updated for node %.40s %s, now %s:%d", + node->name, node->human_readable_name, node->ip, node->port); /* Check if this is our master and we have to change the * replication target as well. */ @@ -1846,7 +1857,7 @@ void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoc sender_slots == migrated_our_slots)) { serverLog(LL_WARNING, "Configuration change detected. Reconfiguring myself " - "as a replica of %.40s", sender->name); + "as a replica of %.40s %s", sender->name, sender->human_readable_name); clusterSetMaster(sender); clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG| CLUSTER_TODO_UPDATE_STATE| @@ -2011,6 +2022,10 @@ int clusterProcessPacket(clusterLink *link) { } } + if (sender && strcmp(sender->human_readable_name,hdr->human_readable_name) != 0) { + strncpy(sender->human_readable_name, hdr->human_readable_name, CLUSTER_HUMAN_NAMELEN); + } + /* Add this node if it is new for us and the msg type is MEET. * In this stage we don't try to add the node with the right * flags, slaveof pointer, and so forth, as this details will be @@ -2051,8 +2066,15 @@ int clusterProcessPacket(clusterLink *link) { * IP/port of the node with the new one. */ if (sender) { serverLog(LL_VERBOSE, - "Handshake: we already know node %.40s, " - "updating the address if needed.", sender->name); + "Handshake: we already know node %.40s %s, " + "updating the address if needed.", sender->name, sender->human_readable_name); + + if (hdr->has_human_readable_name) { + setManualClusterNodeName(sender, hdr->human_readable_name); + } + else + setClusterNodeName(sender); + if (nodeUpdateAddressIfNeeded(sender,link,hdr)) { clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG| @@ -2067,8 +2089,8 @@ int clusterProcessPacket(clusterLink *link) { /* First thing to do is replacing the random name with the * right node name if this was a handshake stage. */ clusterRenameNode(link->node, hdr->sender); - serverLog(LL_DEBUG,"Handshake with node %.40s completed.", - link->node->name); + serverLog(LL_DEBUG,"Handshake with node %.40s %s completed.", + link->node->name, link->node->human_readable_name); link->node->flags &= ~CLUSTER_NODE_HANDSHAKE; link->node->flags |= flags&(CLUSTER_NODE_MASTER|CLUSTER_NODE_SLAVE); clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG); @@ -2078,8 +2100,8 @@ int clusterProcessPacket(clusterLink *link) { /* If the reply has a non matching node ID we * disconnect this node and set it as not having an associated * address. */ - serverLog(LL_DEBUG,"PONG contains mismatching sender ID. About node %.40s added %d ms ago, having flags %d", - link->node->name, + serverLog(LL_DEBUG,"PONG contains mismatching sender ID. About node %.40s %s added %d ms ago, having flags %d", + link->node->name, link->node->human_readable_name, (int)(now-(link->node->ctime)), link->node->flags); link->node->flags |= CLUSTER_NODE_NOADDR; @@ -2225,9 +2247,10 @@ int clusterProcessPacket(clusterLink *link) { senderConfigEpoch) { serverLog(LL_VERBOSE, - "Node %.40s has old slots configuration, sending " - "an UPDATE message about %.40s", - sender->name, server.cluster->slots[j]->name); + "Node %.40s %s has old slots configuration, sending " + "an UPDATE message about %.40s %s", + sender->name, sender->human_readable_name, + server.cluster->slots[j]->name, server.cluster->slots[j]->human_readable_name); clusterSendUpdate(sender->link, server.cluster->slots[j]); @@ -2321,8 +2344,8 @@ int clusterProcessPacket(clusterLink *link) { server.cluster->mf_end = now + CLUSTER_MF_TIMEOUT; server.cluster->mf_slave = sender; pauseClients(now+(CLUSTER_MF_TIMEOUT*CLUSTER_MF_PAUSE_MULT),CLIENT_PAUSE_WRITE); - serverLog(LL_WARNING,"Manual failover requested by replica %.40s.", - sender->name); + serverLog(LL_WARNING,"Manual failover requested by replica %.40s %s.", + sender->name, sender->human_readable_name); /* We need to send a ping message to the replica, as it would carry * `server.cluster->mf_master_offset`, which means the master paused clients * at offset `server.cluster->mf_master_offset`, so that the replica would @@ -2404,8 +2427,8 @@ void clusterLinkConnectHandler(connection *conn) { /* Check if connection succeeded */ if (connGetState(conn) != CONN_STATE_CONNECTED) { - serverLog(LL_VERBOSE, "Connection with Node %.40s at %s:%d failed: %s", - node->name, node->ip, node->cport, + serverLog(LL_VERBOSE, "Connection with Node %.40s %s at %s:%d failed: %s", + node->name, node->human_readable_name, node->ip, node->cport, connGetLastError(conn)); freeClusterLink(link); return; @@ -2436,9 +2459,8 @@ void clusterLinkConnectHandler(connection *conn) { * normal PING packets. */ node->flags &= ~CLUSTER_NODE_MEET; - serverLog(LL_DEBUG,"Connecting with Node %.40s at %s:%d", - node->name, node->ip, node->cport); -} + serverLog(LL_DEBUG,"Connecting with Node %.40s %s at %s:%d", + node->name, node->human_readable_name, node->ip, node->cport); /* Read data. Try to read the first field of the header first to check the * full length of the packet. When a whole packet is in memory this function @@ -2577,6 +2599,8 @@ void clusterBuildMessageHdr(clusterMsg *hdr, int type) { hdr->sig[3] = 'b'; hdr->type = htons(type); memcpy(hdr->sender,myself->name,CLUSTER_NAMELEN); + strncpy(hdr->human_readable_name,myself->human_readable_name,CLUSTER_HUMAN_NAMELEN); + hdr->has_human_readable_name = myself->has_human_readable_name; /* If cluster-announce-ip option is enabled, force the receivers of our * packets to use the specified address for this node. Otherwise if the @@ -2655,6 +2679,7 @@ void clusterSetGossipEntry(clusterMsg *hdr, int i, clusterNode *n) { gossip->cport = htons(n->cport); gossip->flags = htons(n->flags); gossip->pport = htons(n->pport); + gossip->has_human_readable_name = n->has_human_readable_name; gossip->notused1 = 0; } @@ -3044,8 +3069,8 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { * request, if the request epoch was greater. */ if (requestCurrentEpoch < server.cluster->currentEpoch) { serverLog(LL_WARNING, - "Failover auth denied to %.40s: reqEpoch (%llu) < curEpoch(%llu)", - node->name, + "Failover auth denied to %.40s %s: reqEpoch (%llu) < curEpoch(%llu)", + node->name, node->human_readable_name, (unsigned long long) requestCurrentEpoch, (unsigned long long) server.cluster->currentEpoch); return; @@ -3054,8 +3079,8 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { /* I already voted for this epoch? Return ASAP. */ if (server.cluster->lastVoteEpoch == server.cluster->currentEpoch) { serverLog(LL_WARNING, - "Failover auth denied to %.40s: already voted for epoch %llu", - node->name, + "Failover auth denied to %.40s %s: already voted for epoch %llu", + node->name, node->human_readable_name, (unsigned long long) server.cluster->currentEpoch); return; } @@ -3068,16 +3093,16 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { { if (nodeIsMaster(node)) { serverLog(LL_WARNING, - "Failover auth denied to %.40s: it is a master node", - node->name); + "Failover auth denied to %.40s %s: it is a master node", + node->name, node->human_readable_name); } else if (master == NULL) { serverLog(LL_WARNING, - "Failover auth denied to %.40s: I don't know its master", - node->name); + "Failover auth denied to %.40s %s: I don't know its master", + node->name, node->human_readable_name); } else if (!nodeFailed(master)) { serverLog(LL_WARNING, - "Failover auth denied to %.40s: its master is up", - node->name); + "Failover auth denied to %.40s %s: its master is up", + node->name, node->human_readable_name); } return; } @@ -3088,9 +3113,9 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { if (mstime() - node->slaveof->voted_time < server.cluster_node_timeout * 2) { serverLog(LL_WARNING, - "Failover auth denied to %.40s: " + "Failover auth denied to %.40s %s: " "can't vote about this master before %lld milliseconds", - node->name, + node->name, node->human_readable_name, (long long) ((server.cluster_node_timeout*2)- (mstime() - node->slaveof->voted_time))); return; @@ -3110,9 +3135,9 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { * is served by a master with a greater configEpoch than the one claimed * by the slave requesting our vote. Refuse to vote for this slave. */ serverLog(LL_WARNING, - "Failover auth denied to %.40s: " + "Failover auth denied to %.40s %s: " "slot %d epoch (%llu) > reqEpoch (%llu)", - node->name, j, + node->name, node->human_readable_name, j, (unsigned long long) server.cluster->slots[j]->configEpoch, (unsigned long long) requestConfigEpoch); return; @@ -3123,8 +3148,8 @@ void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request) { node->slaveof->voted_time = mstime(); clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG|CLUSTER_TODO_FSYNC_CONFIG); clusterSendFailoverAuth(node); - serverLog(LL_WARNING, "Failover auth granted to %.40s for epoch %llu", - node->name, (unsigned long long) server.cluster->currentEpoch); + serverLog(LL_WARNING, "Failover auth granted to %.40s %s for epoch %llu", + node->name, node->human_readable_name, (unsigned long long) server.cluster->currentEpoch); } /* This function returns the "rank" of this instance, a slave, in the context @@ -3352,7 +3377,7 @@ void clusterHandleSlaveFailover(void) { if (server.cluster->mf_end) { server.cluster->failover_auth_time = mstime(); server.cluster->failover_auth_rank = 0; - clusterDoBeforeSleep(CLUSTER_TODO_HANDLE_FAILOVER); + clusterDoBeforeSleep(CLUSTER_TODO_HANDLE_FAILOVER); } serverLog(LL_WARNING, "Start of election delayed for %lld milliseconds " @@ -3541,8 +3566,8 @@ void clusterHandleSlaveMigration(int max_slaves) { (mstime()-target->orphaned_time) > CLUSTER_SLAVE_MIGRATION_DELAY && !(server.cluster_module_flags & CLUSTER_MODULE_FLAG_NO_FAILOVER)) { - serverLog(LL_WARNING,"Migrating to orphaned master %.40s", - target->name); + serverLog(LL_WARNING,"Migrating to orphaned master %.40s %s", + target->name, target->human_readable_name); clusterSetMaster(target); } } @@ -3739,7 +3764,7 @@ void clusterCron(void) { } } if (min_pong_node) { - serverLog(LL_DEBUG,"Pinging node %.40s", min_pong_node->name); + serverLog(LL_DEBUG,"Pinging node %.40s %s", min_pong_node->name, min_pong_node->human_readable_name); clusterSendPing(min_pong_node->link, CLUSTERMSG_TYPE_PING); } } @@ -3839,8 +3864,8 @@ void clusterCron(void) { /* Timeout reached. Set the node as possibly failing if it is * not already in this state. */ if (!(node->flags & (CLUSTER_NODE_PFAIL|CLUSTER_NODE_FAIL))) { - serverLog(LL_DEBUG,"*** NODE %.40s possibly failing", - node->name); + serverLog(LL_DEBUG,"*** NODE %.40s %s possibly failing", + node->name, node->human_readable_name); node->flags |= CLUSTER_NODE_PFAIL; update_state = 1; } @@ -4298,8 +4323,11 @@ sds clusterGenNodeDescription(clusterNode *node, int use_pport) { /* Node coordinates */ ci = sdscatlen(sdsempty(),node->name,CLUSTER_NAMELEN); - if (node->hname) - ci = sdscatfmt(ci," %s",node->hname); + /* Human readable name of node */ + if (node->human_readable_name[0] == '\0') + ci = sdscatfmt(ci," -",node->human_readable_name); + else + ci = sdscatfmt(ci," %s",node->human_readable_name); ci = sdscatfmt(ci," %s:%i@%i ", node->ip, @@ -4316,6 +4344,9 @@ sds clusterGenNodeDescription(clusterNode *node, int use_pport) { else ci = sdscatlen(ci,"-",1); + /* Adding has human readable name */ + ci = sdscatfmt(ci," %i",node->has_human_readable_name); + unsigned long long nodeEpoch = node->configEpoch; if (nodeIsSlave(node) && node->slaveof) { nodeEpoch = node->slaveof->configEpoch; @@ -4640,10 +4671,12 @@ void clusterCommand(client *c) { "MYID", " Return the node id.", "MYNAME", -" Return the node name.", +" Return the human readable node name.", +"SETNAME ", +" Sets the human-readable node name.", "NODES", " Return cluster configuration seen by node. Output format:", -" ...", +" ...", "REPLICATE ", " Configure current node as replica to .", "RESET [HARD|SOFT]", @@ -4703,11 +4736,17 @@ NULL /* CLUSTER MYID */ addReplyBulkCBuffer(c,myself->name, CLUSTER_NAMELEN); } else if (!strcasecmp(c->argv[1]->ptr,"myname") && c->argc == 2) { - /* CLUSTER MYID */ - if (myself->hname) - addReplyBulkCBuffer(c,myself->hname, strlen(myself->hname)); + /* CLUSTER MYNAME */ + if (myself->human_readable_name[0] != '\0') + addReplyBulkCBuffer(c,myself->human_readable_name, strlen(myself->human_readable_name)); else addReplyError(c,"Node is not assigned name yet."); + } else if (!strcasecmp(c->argv[1]->ptr,"setname") && c->argc == 3) { + /* CLUSTER SETNAME */ + if (setManualClusterNodeName(myself,c->argv[2]->ptr)) + addReply(c,shared.ok); + else + addReplyError(c,"Error setting the name of the node."); } else if (!strcasecmp(c->argv[1]->ptr,"slots") && c->argc == 2) { /* CLUSTER SLOTS */ clusterReplyMultiBulkSlots(c); diff --git a/src/cluster.h b/src/cluster.h index 21a3bec652b..d06c2badb2f 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -9,6 +9,7 @@ #define CLUSTER_OK 0 /* Everything looks ok */ #define CLUSTER_FAIL 1 /* The cluster can't work */ #define CLUSTER_NAMELEN 40 /* sha1 hex length */ +#define CLUSTER_HUMAN_NAMELEN 64 /* Max length of human readable node name */ #define CLUSTER_PORT_INCR 10000 /* Cluster port = baseport + PORT_INCR */ /* The following defines are amount of time, sometimes expressed as @@ -113,7 +114,7 @@ typedef struct clusterNodeFailReport { typedef struct clusterNode { mstime_t ctime; /* Node object creation time. */ char name[CLUSTER_NAMELEN]; /* Node name, hex string, sha1-size */ - char* hname; /* Human readable name for node */ + char human_readable_name[CLUSTER_HUMAN_NAMELEN]; /* Human readable name for node */ int flags; /* CLUSTER_NODE_... */ uint64_t configEpoch; /* Last configEpoch observed for this node */ unsigned char slots[CLUSTER_SLOTS/8]; /* slots handled by this node */ @@ -140,6 +141,7 @@ typedef struct clusterNode { int cport; /* Latest known cluster port of this node. */ clusterLink *link; /* TCP/IP link with this node */ list *fail_reports; /* List of nodes signaling this as failing */ + int has_human_readable_name; /* Indicates whether custom nodename is used */ } clusterNode; /* Slot to keys for a single slot. The keys in the same slot are linked together @@ -210,11 +212,13 @@ typedef struct { uint32_t ping_sent; uint32_t pong_received; char ip[NET_IP_STR_LEN]; /* IP address last time it was seen */ + char human_readable_name[CLUSTER_HUMAN_NAMELEN]; /* Human readable name for node */ uint16_t port; /* base port last time it was seen */ uint16_t cport; /* cluster port last time it was seen */ uint16_t flags; /* node->flags copy */ uint16_t pport; /* plaintext-port, when base port is TLS */ uint16_t notused1; + int has_human_readable_name; /* Indicates whether custom nodename is used */ } clusterMsgDataGossip; typedef struct { @@ -287,6 +291,7 @@ typedef struct { unsigned char myslots[CLUSTER_SLOTS/8]; char slaveof[CLUSTER_NAMELEN]; char myip[NET_IP_STR_LEN]; /* Sender IP, if not all zeroed. */ + char human_readable_name[CLUSTER_HUMAN_NAMELEN]; /* Human readable name assigned to the sender */ char notused1[32]; /* 32 bytes reserved for future usage. */ uint16_t pport; /* Sender TCP plaintext port, if base port is TLS */ uint16_t cport; /* Sender TCP cluster bus port */ @@ -294,6 +299,7 @@ typedef struct { unsigned char state; /* Cluster state from the POV of the sender */ unsigned char mflags[3]; /* Message flags: CLUSTERMSG_FLAG[012]_... */ union clusterMsgData data; + int has_human_readable_name; /* Indicates whether custom nodename is used */ } clusterMsg; #define CLUSTERMSG_MIN_LEN (sizeof(clusterMsg)-sizeof(union clusterMsgData)) diff --git a/src/redis-cli.c b/src/redis-cli.c index b8cb2967160..e3a4419199e 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -4006,9 +4006,10 @@ static int clusterManagerNodeLoadInfo(clusterManagerNode *node, int opts, lines = p + 1; char *name = NULL, *addr = NULL, *flags = NULL, *master_id = NULL, *ping_sent = NULL, *ping_recv = NULL, *config_epoch = NULL, - *link_status = NULL, *hname = NULL; + *link_status = NULL, *human_readable_name = NULL, *has_human_readable_name = NULL; UNUSED(link_status); - UNUSED(hname); + UNUSED(human_readable_name); + UNUSED(has_human_readable_name); int i = 0; while ((p = strchr(line, ' ')) != NULL) { *p = '\0'; @@ -4016,16 +4017,17 @@ static int clusterManagerNodeLoadInfo(clusterManagerNode *node, int opts, line = p + 1; switch(i++){ case 0: name = token; break; - case 1: hname = token; break; + case 1: human_readable_name = token; break; case 2: addr = token; break; case 3: flags = token; break; case 4: master_id = token; break; - case 5: ping_sent = token; break; - case 6: ping_recv = token; break; - case 7: config_epoch = token; break; - case 8: link_status = token; break; + case 5: has_human_readable_name = token; break; + case 6: ping_sent = token; break; + case 7: ping_recv = token; break; + case 8: config_epoch = token; break; + case 9: link_status = token; break; } - if (i == 9) break; // Slots + if (i == 10) break; // Slots } if (!flags) { success = 0; @@ -4037,7 +4039,7 @@ static int clusterManagerNodeLoadInfo(clusterManagerNode *node, int opts, node->flags |= CLUSTER_MANAGER_FLAG_MYSELF; currentNode = node; clusterManagerNodeResetSlots(node); - if (i == 9) { + if (i == 10) { int remaining = strlen(line); while (remaining > 0) { p = strchr(line, ' '); diff --git a/tests/cluster/cluster.tcl b/tests/cluster/cluster.tcl index fddb7ae9e26..91bff65e624 100644 --- a/tests/cluster/cluster.tcl +++ b/tests/cluster/cluster.tcl @@ -22,11 +22,12 @@ proc get_cluster_nodes id { addr [lindex $args 2] \ flags [split [lindex $args 3] ,] \ slaveof [lindex $args 4] \ - ping_sent [lindex $args 5] \ - pong_recv [lindex $args 6] \ - config_epoch [lindex $args 7] \ - linkstate [lindex $args 8] \ - slots [lrange $args 9 end] \ + customName [lindex $args 5] \ + ping_sent [lindex $args 6] \ + pong_recv [lindex $args 7] \ + config_epoch [lindex $args 8] \ + linkstate [lindex $args 9] \ + slots [lrange $args 10 end] \ ] lappend nodes $node } diff --git a/tests/support/cluster.tcl b/tests/support/cluster.tcl index 547b140bc89..25e809ffc49 100644 --- a/tests/support/cluster.tcl +++ b/tests/support/cluster.tcl @@ -102,8 +102,8 @@ proc ::redis_cluster::__method__refresh_nodes_map {id} { set line [string trim $line] if {$line eq {}} continue set args [split $line " "] - lassign $args nodeid name addr flags slaveof pingsent pongrecv configepoch linkstate - set slots [lrange $args 9 end] + lassign $args nodeid name addr flags slaveof customname pingsent pongrecv configepoch linkstate + set slots [lrange $args 10 end] set addr [lindex [split $addr @] 0] if {$addr eq {:0}} { set addr $start_host:$start_port @@ -124,6 +124,7 @@ proc ::redis_cluster::__method__refresh_nodes_map {id} { port $port \ flags $flags \ slaveof $slaveof \ + customname $customname \ slots $slots \ link $link \ ]