SYNC and PSYNC command implementation. */
| 717 | |
| 718 | /* SYNC and PSYNC command implementation. */ |
| 719 | void syncCommand(client *c) { |
| 720 | /* ignore SYNC if already slave or in monitor mode */ |
| 721 | if (c->flags & CLIENT_SLAVE) return; |
| 722 | |
| 723 | /* Check if this is a failover request to a replica with the same replid and |
| 724 | * become a master if so. */ |
| 725 | if (c->argc > 3 && !strcasecmp(c->argv[0]->ptr,"psync") && |
| 726 | !strcasecmp(c->argv[3]->ptr,"failover")) |
| 727 | { |
| 728 | serverLog(LL_WARNING, "Failover request received for replid %s.", |
| 729 | (unsigned char *)c->argv[1]->ptr); |
| 730 | if (!server.masterhost) { |
| 731 | addReplyError(c, "PSYNC FAILOVER can't be sent to a master."); |
| 732 | return; |
| 733 | } |
| 734 | |
| 735 | if (!strcasecmp(c->argv[1]->ptr,server.replid)) { |
| 736 | replicationUnsetMaster(); |
| 737 | sds client = catClientInfoString(sdsempty(),c); |
| 738 | serverLog(LL_NOTICE, |
| 739 | "MASTER MODE enabled (failover request from '%s')",client); |
| 740 | sdsfree(client); |
| 741 | } else { |
| 742 | addReplyError(c, "PSYNC FAILOVER replid must match my replid."); |
| 743 | return; |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | /* Don't let replicas sync with us while we're failing over */ |
| 748 | if (server.failover_state != NO_FAILOVER) { |
| 749 | addReplyError(c,"-NOMASTERLINK Can't SYNC while failing over"); |
| 750 | return; |
| 751 | } |
| 752 | |
| 753 | /* Refuse SYNC requests if we are a slave but the link with our master |
| 754 | * is not ok... */ |
| 755 | if (server.masterhost && server.repl_state != REPL_STATE_CONNECTED) { |
| 756 | addReplyError(c,"-NOMASTERLINK Can't SYNC while not connected with my master"); |
| 757 | return; |
| 758 | } |
| 759 | |
| 760 | /* SYNC can't be issued when the server has pending data to send to |
| 761 | * the client about already issued commands. We need a fresh reply |
| 762 | * buffer registering the differences between the BGSAVE and the current |
| 763 | * dataset, so that we can copy to other slaves if needed. */ |
| 764 | if (clientHasPendingReplies(c)) { |
| 765 | addReplyError(c,"SYNC and PSYNC are invalid with pending output"); |
| 766 | return; |
| 767 | } |
| 768 | |
| 769 | serverLog(LL_NOTICE,"Replica %s asks for synchronization", |
| 770 | replicationGetSlaveName(c)); |
| 771 | |
| 772 | /* Try a partial resynchronization if this is a PSYNC command. |
| 773 | * If it fails, we continue with usual full resynchronization, however |
| 774 | * when this happens masterTryPartialResynchronization() already |
| 775 | * replied with: |
| 776 | * |
nothing calls this directly
no test coverage detected