diff --git a/src/cluster.c b/src/cluster.c index c985d0b18..112cacbd0 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -2627,9 +2627,7 @@ uint32_t writePingExt(clusterMsg *hdr, int gossipcount) { extensions++; if (hdr != NULL) { - if (extensions != 0) { - hdr->mflags[0] |= CLUSTERMSG_FLAG0_EXT_DATA; - } + hdr->mflags[0] |= CLUSTERMSG_FLAG0_EXT_DATA; hdr->extensions = htons(extensions); } @@ -2821,6 +2819,10 @@ int clusterProcessPacket(clusterLink *link) { sender = getNodeFromLinkAndMsg(link, hdr); + if (sender && (hdr->mflags[0] & CLUSTERMSG_FLAG0_EXT_DATA)) { + sender->flags |= CLUSTER_NODE_EXTENSIONS_SUPPORTED; + } + /* Update the last time we saw any data from this node. We * use this in order to avoid detecting a timeout from a node that * is just sending a lot of data in the cluster bus, for instance @@ -3621,7 +3623,9 @@ void clusterSendPing(clusterLink *link, int type) { * to put inside the packet. */ estlen = sizeof(clusterMsg) - sizeof(union clusterMsgData); estlen += (sizeof(clusterMsgDataGossip)*(wanted + pfail_wanted)); - estlen += writePingExt(NULL, 0); + if (link->node && nodeSupportsExtensions(link->node)) { + estlen += writePingExt(NULL, 0); + } /* Note: clusterBuildMessageHdr() expects the buffer to be always at least * sizeof(clusterMsg) or more. */ if (estlen < (int)sizeof(clusterMsg)) estlen = sizeof(clusterMsg); @@ -3689,7 +3693,13 @@ void clusterSendPing(clusterLink *link, int type) { /* Compute the actual total length and send! */ uint32_t totlen = 0; - totlen += writePingExt(hdr, gossipcount); + + if (link->node && nodeSupportsExtensions(link->node)) { + totlen += writePingExt(hdr, gossipcount); + } else { + serverLog(LL_DEBUG, "Unable to send extensions data, however setting ext data flag to true"); + hdr->mflags[0] |= CLUSTERMSG_FLAG0_EXT_DATA; + } totlen += sizeof(clusterMsg)-sizeof(union clusterMsgData); totlen += (sizeof(clusterMsgDataGossip)*gossipcount); serverAssert(gossipcount < USHRT_MAX); diff --git a/src/cluster.h b/src/cluster.h index db05ebcab..a8fcb69d2 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -56,6 +56,7 @@ typedef struct clusterLink { #define CLUSTER_NODE_MEET 128 /* Send a MEET message to this node */ #define CLUSTER_NODE_MIGRATE_TO 256 /* Master eligible for replica migration. */ #define CLUSTER_NODE_NOFAILOVER 512 /* Slave will not try to failover. */ +#define CLUSTER_NODE_EXTENSIONS_SUPPORTED 1024 /* This node supports extensions. */ #define CLUSTER_NODE_NULL_NAME "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" #define nodeIsMaster(n) ((n)->flags & CLUSTER_NODE_MASTER) @@ -66,6 +67,7 @@ typedef struct clusterLink { #define nodeTimedOut(n) ((n)->flags & CLUSTER_NODE_PFAIL) #define nodeFailed(n) ((n)->flags & CLUSTER_NODE_FAIL) #define nodeCantFailover(n) ((n)->flags & CLUSTER_NODE_NOFAILOVER) +#define nodeSupportsExtensions(n) ((n)->flags & CLUSTER_NODE_EXTENSIONS_SUPPORTED) /* Reasons why a slave is not able to failover. */ #define CLUSTER_CANT_FAILOVER_NONE 0 diff --git a/tests/unit/cluster/hostnames.tcl b/tests/unit/cluster/hostnames.tcl index f31824062..f08c9cfa8 100644 --- a/tests/unit/cluster/hostnames.tcl +++ b/tests/unit/cluster/hostnames.tcl @@ -116,10 +116,11 @@ test "Verify the nodes configured with prefer hostname only show hostname for ne # Have everyone forget node 6 and isolate it from the cluster. isolate_node 6 - # Set hostnames for the masters, now that the node is isolated - R 0 config set cluster-announce-hostname "shard-1.com" - R 1 config set cluster-announce-hostname "shard-2.com" - R 2 config set cluster-announce-hostname "shard-3.com" + set primaries 3 + for {set j 0} {$j < $primaries} {incr j} { + # Set hostnames for the masters, now that the node is isolated + R $j config set cluster-announce-hostname "shard-$j.com" + } # Prevent Node 0 and Node 6 from properly meeting, # they'll hang in the handshake phase. This allows us to @@ -149,9 +150,17 @@ test "Verify the nodes configured with prefer hostname only show hostname for ne } else { fail "Node did not learn about the 2 shards it can talk to" } - set slot_result [R 6 CLUSTER SLOTS] - assert_equal [lindex [get_slot_field $slot_result 0 2 3] 1] "shard-2.com" - assert_equal [lindex [get_slot_field $slot_result 1 2 3] 1] "shard-3.com" + wait_for_condition 50 100 { + [lindex [get_slot_field [R 6 CLUSTER SLOTS] 0 2 3] 1] eq "shard-1.com" + } else { + fail "hostname for shard-1 didn't reach node 6" + } + + wait_for_condition 50 100 { + [lindex [get_slot_field [R 6 CLUSTER SLOTS] 1 2 3] 1] eq "shard-2.com" + } else { + fail "hostname for shard-2 didn't reach node 6" + } # Also make sure we know about the isolated master, we # just can't reach it. @@ -170,10 +179,14 @@ test "Verify the nodes configured with prefer hostname only show hostname for ne } else { fail "Node did not learn about the 2 shards it can talk to" } - set slot_result [R 6 CLUSTER SLOTS] - assert_equal [lindex [get_slot_field $slot_result 0 2 3] 1] "shard-1.com" - assert_equal [lindex [get_slot_field $slot_result 1 2 3] 1] "shard-2.com" - assert_equal [lindex [get_slot_field $slot_result 2 2 3] 1] "shard-3.com" + + for {set j 0} {$j < $primaries} {incr j} { + wait_for_condition 50 100 { + [lindex [get_slot_field [R 6 CLUSTER SLOTS] $j 2 3] 1] eq "shard-$j.com" + } else { + fail "hostname information for shard-$j didn't reach node 6" + } + } } test "Test restart will keep hostname information" {