| 513 | } |
| 514 | |
| 515 | Future<bool> catchup(uint64_t begin, uint64_t end) |
| 516 | { |
| 517 | // We reach here either because the log is empty (uninitialized), |
| 518 | // or the log is not empty but a previous unfinished catch-up |
| 519 | // attempt has been detected (the process crashes/killed when |
| 520 | // catching up). In either case, the local replica may have lost |
| 521 | // some data and Paxos states, and should not be allowed to vote. |
| 522 | // Otherwise, we may introduce inconsistency in the log as the |
| 523 | // local replica could have accepted a write which it would not |
| 524 | // have accepted if the data and the Paxos states were not lost. |
| 525 | // Now, the question is how many positions the local replica |
| 526 | // should catch up before it can be allowed to vote. We find that |
| 527 | // it is sufficient to catch-up positions from _begin_ to _end_ |
| 528 | // where _begin_ is the smallest position seen in a quorum of |
| 529 | // VOTING replicas and _end_ is the largest position seen in a |
| 530 | // quorum of VOTING replicas. Here is the correctness argument. |
| 531 | // For a position _e_ larger than _end_, obviously no value has |
| 532 | // been agreed on for that position. Otherwise, we should find at |
| 533 | // least one VOTING replica in a quorum of replicas such that its |
| 534 | // end position is larger than _end_. For the same reason, a |
| 535 | // coordinator should not have collected enough promises for |
| 536 | // position _e_. Therefore, it's safe for the local replica to |
| 537 | // vote for that position. For a position _b_ smaller than |
| 538 | // _begin_, it should have already been truncated and the |
| 539 | // truncation should have already been agreed. Therefore, allowing |
| 540 | // the local replica to vote for that position is safe. |
| 541 | CHECK_LE(begin, end); |
| 542 | |
| 543 | LOG(INFO) << "Starting catch-up from position " << begin << " to " << end; |
| 544 | |
| 545 | IntervalSet<uint64_t> positions( |
| 546 | Bound<uint64_t>::closed(begin), |
| 547 | Bound<uint64_t>::closed(end)); |
| 548 | |
| 549 | // Share the ownership of the replica. From this point until the |
| 550 | // point where the ownership of the replica is regained, we should |
| 551 | // not access the 'replica' field. |
| 552 | Shared<Replica> shared = replica.share(); |
| 553 | |
| 554 | // Since we do not know what proposal number to use (the log is |
| 555 | // empty), we use none and leave log::catchup to automatically |
| 556 | // bump the proposal number. |
| 557 | return log::catchup(quorum, shared, network, None(), positions) |
| 558 | .then(defer(self(), &Self::getReplicaOwnership, shared)) |
| 559 | .then(defer(self(), &Self::updateReplicaStatus, Metadata::VOTING)); |
| 560 | } |
| 561 | |
| 562 | Future<bool> updateReplicaStatus(const Metadata::Status& status) |
| 563 | { |