@@ -98,7 +98,6 @@ void moduleCallClusterReceivers(const char *sender_id,
9898const char * clusterGetMessageTypeString (int type );
9999void removeChannelsInSlot (unsigned int slot );
100100unsigned int countChannelsInSlot (unsigned int hashslot );
101- unsigned int delKeysInSlot (unsigned int hashslot );
102101void clusterAddNodeToShard (const char * shard_id , clusterNode * node );
103102list * clusterLookupNodeListByShardId (const char * shard_id );
104103void clusterRemoveNodeFromShard (clusterNode * node );
@@ -127,6 +126,7 @@ int verifyClusterNodeId(const char *name, int length);
127126sds clusterEncodeOpenSlotsAuxField (int rdbflags );
128127int clusterDecodeOpenSlotsAuxField (int rdbflags , sds s );
129128static int nodeExceedsHandshakeTimeout (clusterNode * node , mstime_t now );
129+ void clusterCommandFlushslot (client * c );
130130
131131/* Only primaries that own slots have voting rights.
132132 * Returns 1 if the node has voting rights, otherwise returns 0. */
@@ -327,7 +327,7 @@ int auxShardIdSetter(clusterNode *n, void *value, size_t length) {
327327}
328328
329329sds auxShardIdGetter (clusterNode * n , sds s ) {
330- return sdscatprintf (s , "%.40s" , n -> shard_id );
330+ return sdscatlen (s , n -> shard_id , CLUSTER_NAMELEN );
331331}
332332
333333int auxShardIdPresent (clusterNode * n ) {
@@ -344,7 +344,7 @@ int auxHumanNodenameSetter(clusterNode *n, void *value, size_t length) {
344344}
345345
346346sds auxHumanNodenameGetter (clusterNode * n , sds s ) {
347- return sdscatprintf ( s , "%s" , n -> human_nodename );
347+ return sdscat ( s , n -> human_nodename );
348348}
349349
350350int auxHumanNodenamePresent (clusterNode * n ) {
@@ -370,7 +370,7 @@ int auxAnnounceClientIpV4Setter(clusterNode *n, void *value, size_t length) {
370370}
371371
372372sds auxAnnounceClientIpV4Getter (clusterNode * n , sds s ) {
373- return sdscatprintf ( s , "%s" , n -> announce_client_ipv4 );
373+ return sdscat ( s , n -> announce_client_ipv4 );
374374}
375375
376376int auxAnnounceClientIpV4Present (clusterNode * n ) {
@@ -396,7 +396,7 @@ int auxAnnounceClientIpV6Setter(clusterNode *n, void *value, size_t length) {
396396}
397397
398398sds auxAnnounceClientIpV6Getter (clusterNode * n , sds s ) {
399- return sdscatprintf ( s , "%s" , n -> announce_client_ipv6 );
399+ return sdscat ( s , n -> announce_client_ipv6 );
400400}
401401
402402int auxAnnounceClientIpV6Present (clusterNode * n ) {
@@ -415,7 +415,7 @@ int auxTcpPortSetter(clusterNode *n, void *value, size_t length) {
415415}
416416
417417sds auxTcpPortGetter (clusterNode * n , sds s ) {
418- return sdscatprintf (s , "%d " , n -> tcp_port );
418+ return sdscatfmt (s , "%i " , n -> tcp_port );
419419}
420420
421421int auxTcpPortPresent (clusterNode * n ) {
@@ -434,7 +434,7 @@ int auxTlsPortSetter(clusterNode *n, void *value, size_t length) {
434434}
435435
436436sds auxTlsPortGetter (clusterNode * n , sds s ) {
437- return sdscatprintf (s , "%d " , n -> tls_port );
437+ return sdscatfmt (s , "%i " , n -> tls_port );
438438}
439439
440440int auxTlsPortPresent (clusterNode * n ) {
@@ -2144,11 +2144,12 @@ void clusterBlacklistAddNode(clusterNode *node) {
21442144/* Return non-zero if the specified node ID exists in the blacklist.
21452145 * You don't need to pass an sds string here, any pointer to 40 bytes
21462146 * will work. */
2147- int clusterBlacklistExists (char * nodeid ) {
2148- sds id = sdsnewlen (nodeid , CLUSTER_NAMELEN );
2147+ int clusterBlacklistExists (char * nodeid , size_t len ) {
2148+ sds id = sdsnewlen (nodeid , len );
21492149 int retval ;
21502150
21512151 clusterBlacklistCleanup ();
2152+
21522153 retval = dictFind (server .cluster -> nodes_black_list , id ) != NULL ;
21532154 sdsfree (id );
21542155 return retval ;
@@ -2484,7 +2485,7 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) {
24842485 * Note that we require that the sender of this gossip message
24852486 * is a well known node in our cluster, otherwise we risk
24862487 * joining another cluster. */
2487- if (sender && !(flags & CLUSTER_NODE_NOADDR ) && !clusterBlacklistExists (g -> nodename )) {
2488+ if (sender && !(flags & CLUSTER_NODE_NOADDR ) && !clusterBlacklistExists (g -> nodename , CLUSTER_NAMELEN )) {
24882489 clusterNode * node ;
24892490 node = createClusterNode (g -> nodename , flags );
24902491 memcpy (node -> ip , g -> ip , NET_IP_STR_LEN );
@@ -2861,7 +2862,7 @@ void clusterUpdateSlotsConfigWith(clusterNode *sender, uint64_t senderConfigEpoc
28612862 for (int j = 0 ; j < dirty_slots_count ; j ++ ) {
28622863 serverLog (LL_NOTICE , "Deleting keys in dirty slot %d on node %.40s (%s) in shard %.40s" , dirty_slots [j ],
28632864 myself -> name , myself -> human_nodename , myself -> shard_id );
2864- delKeysInSlot (dirty_slots [j ]);
2865+ delKeysInSlot (dirty_slots [j ], server . lazyfree_lazy_server_del , true, false );
28652866 }
28662867 }
28672868}
@@ -3196,7 +3197,7 @@ int clusterIsValidPacket(clusterLink *link) {
31963197 if (hdr -> mflags [0 ] & CLUSTERMSG_FLAG0_EXT_DATA ) {
31973198 clusterMsgPingExt * ext = getInitialPingExt (hdr , count );
31983199 while (extensions -- ) {
3199- uint16_t extlen = getPingExtLength (ext );
3200+ uint32_t extlen = getPingExtLength (ext );
32003201 if (extlen % 8 != 0 ) {
32013202 serverLog (LL_WARNING , "Received a %s packet without proper padding (%d bytes)" ,
32023203 clusterGetMessageTypeString (type ), (int )extlen );
@@ -3534,6 +3535,7 @@ int clusterProcessPacket(clusterLink *link) {
35343535 * the clients, and the replica will never initiate a failover since the
35353536 * node is not actually in FAIL state. */
35363537 if (!nodeFailed (noaddr_node )) {
3538+ noaddr_node -> flags &= ~CLUSTER_NODE_PFAIL ;
35373539 noaddr_node -> flags |= CLUSTER_NODE_FAIL ;
35383540 noaddr_node -> fail_time = now ;
35393541 clusterSendFail (noaddr_node -> name );
@@ -5915,7 +5917,7 @@ int verifyClusterConfigWithData(void) {
59155917 server .cluster -> importing_slots_from [j ]-> shard_id , j , server .cluster -> slots [j ]-> name ,
59165918 server .cluster -> slots [j ]-> human_nodename , server .cluster -> slots [j ]-> shard_id );
59175919 }
5918- delKeysInSlot (j );
5920+ delKeysInSlot (j , server . lazyfree_lazy_server_del , true, false );
59195921 }
59205922 }
59215923 if (update_config ) clusterSaveConfigOrDie (1 );
@@ -6045,7 +6047,7 @@ sds clusterGenNodeDescription(client *c, clusterNode *node, int tls_primary) {
60456047 continue ;
60466048 }
60476049 if (auxFieldHandlers [i ].isPresent (node )) {
6048- ci = sdscatprintf (ci , ",%s=" , auxFieldHandlers [i ].field );
6050+ ci = sdscatfmt (ci , ",%s=" , auxFieldHandlers [i ].field );
60496051 ci = auxFieldHandlers [i ].getter (node , ci );
60506052 }
60516053 }
@@ -6097,9 +6099,13 @@ sds clusterGenNodeDescription(client *c, clusterNode *node, int tls_primary) {
60976099 if (node -> flags & CLUSTER_NODE_MYSELF ) {
60986100 for (j = 0 ; j < CLUSTER_SLOTS ; j ++ ) {
60996101 if (server .cluster -> migrating_slots_to [j ]) {
6100- ci = sdscatprintf (ci , " [%d->-%.40s]" , j , server .cluster -> migrating_slots_to [j ]-> name );
6102+ ci = sdscatfmt (ci , " [%i->-" , j );
6103+ ci = sdscatlen (ci , server .cluster -> migrating_slots_to [j ]-> name , CLUSTER_NAMELEN );
6104+ ci = sdscat (ci , "]" );
61016105 } else if (server .cluster -> importing_slots_from [j ]) {
6102- ci = sdscatprintf (ci , " [%d-<-%.40s]" , j , server .cluster -> importing_slots_from [j ]-> name );
6106+ ci = sdscatfmt (ci , " [%i-<-" , j );
6107+ ci = sdscatlen (ci , server .cluster -> importing_slots_from [j ]-> name , CLUSTER_NAMELEN );
6108+ ci = sdscat (ci , "]" );
61036109 }
61046110 }
61056111 }
@@ -6530,13 +6536,14 @@ void removeChannelsInSlot(unsigned int slot) {
65306536
65316537/* Remove all the keys in the specified hash slot.
65326538 * The number of removed items is returned. */
6533- unsigned int delKeysInSlot (unsigned int hashslot ) {
6539+ unsigned int delKeysInSlot (unsigned int hashslot , int lazy , bool propagate_del , bool send_del_event ) {
65346540 if (!countKeysInSlot (hashslot )) return 0 ;
65356541
65366542 /* We may lose a slot during the pause. We need to track this
65376543 * state so that we don't assert in propagateNow(). */
65386544 server .server_del_keys_in_slot = 1 ;
65396545 unsigned int j = 0 ;
6546+ int before_execution_nesting = server .execution_nesting ;
65406547
65416548 for (int i = 0 ; i < server .dbnum ; i ++ ) {
65426549 kvstoreHashtableIterator * kvs_di = NULL ;
@@ -6548,13 +6555,23 @@ unsigned int delKeysInSlot(unsigned int hashslot) {
65486555 enterExecutionUnit (1 , 0 );
65496556 sds sdskey = objectGetKey (valkey );
65506557 robj * key = createStringObject (sdskey , sdslen (sdskey ));
6551- dbDelete (& db , key );
6552- propagateDeletion (& db , key , server .lazyfree_lazy_server_del );
6558+ if (lazy ) {
6559+ dbAsyncDelete (& db , key );
6560+ } else {
6561+ dbSyncDelete (& db , key );
6562+ }
6563+ // if is command, skip del propagate
6564+ if (propagate_del ) propagateDeletion (& db , key , lazy );
65536565 signalModifiedKey (NULL , & db , key );
6554- /* The keys are not actually logically deleted from the database, just moved to another node.
6555- * The modules needs to know that these keys are no longer available locally, so just send the
6556- * keyspace notification to the modules, but not to clients. */
6557- moduleNotifyKeyspaceEvent (NOTIFY_GENERIC , "del" , key , db .id );
6566+ if (send_del_event ) {
6567+ /* In the `cluster flushslot` scenario, the keys are actually deleted so notify everyone. */
6568+ notifyKeyspaceEvent (NOTIFY_GENERIC , "del" , key , db .id );
6569+ } else {
6570+ /* The keys are not actually logically deleted from the database, just moved to another node.
6571+ * The modules needs to know that these keys are no longer available locally, so just send the
6572+ * keyspace notification to the modules, but not to clients. */
6573+ moduleNotifyKeyspaceEvent (NOTIFY_GENERIC , "del" , key , db .id );
6574+ }
65586575 exitExecutionUnit ();
65596576 postExecutionUnitOperations ();
65606577 decrRefCount (key );
@@ -6564,7 +6581,7 @@ unsigned int delKeysInSlot(unsigned int hashslot) {
65646581 kvstoreReleaseHashtableIterator (kvs_di );
65656582 }
65666583 server .server_del_keys_in_slot = 0 ;
6567- serverAssert (server .execution_nesting == 0 );
6584+ serverAssert (server .execution_nesting == before_execution_nesting );
65686585 return j ;
65696586}
65706587
@@ -7127,7 +7144,7 @@ int clusterCommandSpecial(client *c) {
71277144 /* CLUSTER FORGET <NODE ID> */
71287145 clusterNode * n = clusterLookupNode (c -> argv [2 ]-> ptr , sdslen (c -> argv [2 ]-> ptr ));
71297146 if (!n ) {
7130- if (clusterBlacklistExists ((char * )c -> argv [2 ]-> ptr ))
7147+ if (clusterBlacklistExists ((char * )c -> argv [2 ]-> ptr , sdslen ( c -> argv [ 2 ] -> ptr ) ))
71317148 /* Already forgotten. The deletion may have been gossipped by
71327149 * another node, so we pretend it succeeded. */
71337150 addReply (c , shared .ok );
@@ -7366,6 +7383,9 @@ int clusterCommandSpecial(client *c) {
73667383 } else if (!strcasecmp (c -> argv [1 ]-> ptr , "links" ) && c -> argc == 2 ) {
73677384 /* CLUSTER LINKS */
73687385 addReplyClusterLinksDescription (c );
7386+ } else if (!strcasecmp (c -> argv [1 ]-> ptr , "flushslot" ) && (c -> argc == 3 || c -> argc == 4 )) {
7387+ /* CLUSTER FLUSHSLOT <slot> [ASYNC|SYNC] */
7388+ clusterCommandFlushslot (c );
73697389 } else {
73707390 return 0 ;
73717391 }
@@ -7558,6 +7578,5 @@ int clusterDecodeOpenSlotsAuxField(int rdbflags, sds s) {
75587578 server .cluster -> migrating_slots_to [slot ] = node ;
75597579 }
75607580 }
7561-
75627581 return C_OK ;
75637582}
0 commit comments