This function handles the PSYNC command from the point of view of a * master receiving a request for partial resynchronization. * * On success return C_OK, otherwise C_ERR is returned and we proceed * with the usual full resync. */
| 892 | * On success return C_OK, otherwise C_ERR is returned and we proceed |
| 893 | * with the usual full resync. */ |
| 894 | int masterTryPartialResynchronization(client *c) { |
| 895 | serverAssert(GlobalLocksAcquired()); |
| 896 | long long psync_offset, psync_len; |
| 897 | char *master_replid = (char*)ptrFromObj(c->argv[1]); |
| 898 | char buf[128]; |
| 899 | int buflen; |
| 900 | |
| 901 | /* Parse the replication offset asked by the replica. Go to full sync |
| 902 | * on parse error: this should never happen but we try to handle |
| 903 | * it in a robust way compared to aborting. */ |
| 904 | if (getLongLongFromObjectOrReply(c,c->argv[2],&psync_offset,NULL) != |
| 905 | C_OK) goto need_full_resync; |
| 906 | |
| 907 | /* Is the replication ID of this master the same advertised by the wannabe |
| 908 | * replica via PSYNC? If the replication ID changed this master has a |
| 909 | * different replication history, and there is no way to continue. |
| 910 | * |
| 911 | * Note that there are two potentially valid replication IDs: the ID1 |
| 912 | * and the ID2. The ID2 however is only valid up to a specific offset. */ |
| 913 | if (strcasecmp(master_replid, g_pserver->replid) && |
| 914 | (strcasecmp(master_replid, g_pserver->replid2) || |
| 915 | psync_offset > g_pserver->second_replid_offset)) |
| 916 | { |
| 917 | /* Replid "?" is used by slaves that want to force a full resync. */ |
| 918 | if (master_replid[0] != '?') { |
| 919 | if (strcasecmp(master_replid, g_pserver->replid) && |
| 920 | strcasecmp(master_replid, g_pserver->replid2)) |
| 921 | { |
| 922 | serverLog(LL_NOTICE,"Partial resynchronization not accepted: " |
| 923 | "Replication ID mismatch (Replica asked for '%s', my " |
| 924 | "replication IDs are '%s' and '%s')", |
| 925 | master_replid, g_pserver->replid, g_pserver->replid2); |
| 926 | } else { |
| 927 | serverLog(LL_NOTICE,"Partial resynchronization not accepted: " |
| 928 | "Requested offset for second ID was %lld, but I can reply " |
| 929 | "up to %lld", psync_offset, g_pserver->second_replid_offset); |
| 930 | } |
| 931 | } else { |
| 932 | serverLog(LL_NOTICE,"Full resync requested by replica %s", |
| 933 | replicationGetSlaveName(c)); |
| 934 | } |
| 935 | goto need_full_resync; |
| 936 | } |
| 937 | |
| 938 | /* We still have the data our replica is asking for? */ |
| 939 | if (!g_pserver->repl_backlog || |
| 940 | psync_offset < g_pserver->repl_backlog_off || |
| 941 | psync_offset > (g_pserver->repl_backlog_off + g_pserver->repl_backlog_histlen)) |
| 942 | { |
| 943 | serverLog(LL_NOTICE, |
| 944 | "Unable to partial resync with replica %s for lack of backlog (Replica request was: %lld).", replicationGetSlaveName(c), psync_offset); |
| 945 | if (psync_offset > g_pserver->master_repl_offset) { |
| 946 | serverLog(LL_WARNING, |
| 947 | "Warning: replica %s tried to PSYNC with an offset that is greater than the master replication offset.", replicationGetSlaveName(c)); |
| 948 | } |
| 949 | goto need_full_resync; |
| 950 | } |
| 951 |
no test coverage detected