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. */
| 522 | * On success return C_OK, otherwise C_ERR is returned and we proceed |
| 523 | * with the usual full resync. */ |
| 524 | int masterTryPartialResynchronization(client *c) { |
| 525 | long long psync_offset, psync_len; |
| 526 | char *master_replid = c->argv[1]->ptr; |
| 527 | char buf[128]; |
| 528 | int buflen; |
| 529 | |
| 530 | /* Parse the replication offset asked by the slave. Go to full sync |
| 531 | * on parse error: this should never happen but we try to handle |
| 532 | * it in a robust way compared to aborting. */ |
| 533 | if (getLongLongFromObjectOrReply(c,c->argv[2],&psync_offset,NULL) != |
| 534 | C_OK) goto need_full_resync; |
| 535 | |
| 536 | /* Is the replication ID of this master the same advertised by the wannabe |
| 537 | * slave via PSYNC? If the replication ID changed this master has a |
| 538 | * different replication history, and there is no way to continue. |
| 539 | * |
| 540 | * Note that there are two potentially valid replication IDs: the ID1 |
| 541 | * and the ID2. The ID2 however is only valid up to a specific offset. */ |
| 542 | if (strcasecmp(master_replid, server.replid) && |
| 543 | (strcasecmp(master_replid, server.replid2) || |
| 544 | psync_offset > server.second_replid_offset)) |
| 545 | { |
| 546 | /* Replid "?" is used by slaves that want to force a full resync. */ |
| 547 | if (master_replid[0] != '?') { |
| 548 | if (strcasecmp(master_replid, server.replid) && |
| 549 | strcasecmp(master_replid, server.replid2)) |
| 550 | { |
| 551 | serverLog(LL_NOTICE,"Partial resynchronization not accepted: " |
| 552 | "Replication ID mismatch (Replica asked for '%s', my " |
| 553 | "replication IDs are '%s' and '%s')", |
| 554 | master_replid, server.replid, server.replid2); |
| 555 | } else { |
| 556 | serverLog(LL_NOTICE,"Partial resynchronization not accepted: " |
| 557 | "Requested offset for second ID was %lld, but I can reply " |
| 558 | "up to %lld", psync_offset, server.second_replid_offset); |
| 559 | } |
| 560 | } else { |
| 561 | serverLog(LL_NOTICE,"Full resync requested by replica %s", |
| 562 | replicationGetSlaveName(c)); |
| 563 | } |
| 564 | goto need_full_resync; |
| 565 | } |
| 566 | |
| 567 | /* We still have the data our slave is asking for? */ |
| 568 | if (!server.repl_backlog || |
| 569 | psync_offset < server.repl_backlog_off || |
| 570 | psync_offset > (server.repl_backlog_off + server.repl_backlog_histlen)) |
| 571 | { |
| 572 | serverLog(LL_NOTICE, |
| 573 | "Unable to partial resync with replica %s for lack of backlog (Replica request was: %lld).", replicationGetSlaveName(c), psync_offset); |
| 574 | if (psync_offset > server.master_repl_offset) { |
| 575 | serverLog(LL_WARNING, |
| 576 | "Warning: replica %s tried to PSYNC with an offset that is greater than the master replication offset.", replicationGetSlaveName(c)); |
| 577 | } |
| 578 | goto need_full_resync; |
| 579 | } |
| 580 | |
| 581 | /* If we reached this point, we are able to perform a partial resync: |
no test coverage detected