def _start_catchup_if_needed(self, key: CheckpointKey):
        if self._have_own_checkpoint(key):
            return

        unknown_stabilized = self._unknown_stabilized_checkpoints()
        lag_in_checkpoints = len(unknown_stabilized)
        if lag_in_checkpoints <= self.STASHED_CHECKPOINTS_BEFORE_CATCHUP:
            return

        last_key = sorted(unknown_stabilized,
                          key=lambda v: (v.view_no, v.pp_seq_no))[-1]

        if self.is_master:
            if not self._data.is_primary:
                logger.display(
                    '{} has lagged for {} checkpoints so the catchup procedure starts'
                    .format(self, lag_in_checkpoints))
                self._bus.send(NeedMasterCatchup())
        else:
            logger.info(
                '{} has lagged for {} checkpoints so adjust last_ordered_3pc to {}, '
                'shift watermarks and clean collections'.format(
                    self, lag_in_checkpoints, last_key.pp_seq_no))
            # Adjust last_ordered_3pc, shift watermarks, clean operational
            # collections and process stashed messages which now fit between
            # watermarks
            # TODO: Actually we might need to process view_no from last_key as well, however
            #  it wasn't processed before, and it will go away when INDY-1336 gets implemented
            key_3pc = (self.view_no, last_key.pp_seq_no)
            self._bus.send(
                NeedBackupCatchup(inst_id=self._data.inst_id,
                                  caught_up_till_3pc=key_3pc))
            self.caught_up_till_3pc(key_3pc)
Beispiel #2
0
 def check_catchup_started(till_seq_no: int):
     if is_master:
         master_catchup_handler.assert_called_once_with(NeedMasterCatchup())
         backup_catchup_handler.assert_not_called()
     else:
         master_catchup_handler.assert_not_called()
         backup_catchup_handler.assert_called_once_with(
             NeedBackupCatchup(inst_id=checkpoint_service._data.inst_id,
                               caught_up_till_3pc=(checkpoint_service.view_no,
                                                   till_seq_no)))
Beispiel #3
0
def test_start_catchup_on_quorum_of_stashed_checkpoints(
        checkpoint_service, checkpoint, pre_prepare, tconf, ordered,
        validators, is_master):
    master_catchup_handler = Mock()
    backup_catchup_handler = Mock()
    checkpoint_service._bus.subscribe(NeedMasterCatchup,
                                      master_catchup_handler)
    checkpoint_service._bus.subscribe(NeedBackupCatchup,
                                      backup_catchup_handler)

    quorum = checkpoint_service._data.quorums.checkpoint.value
    print(quorum)
    n = len(validators)
    assert quorum == n - getMaxFailures(n) - 1
    senders = ["sender{}".format(i) for i in range(quorum + 1)]

    old_key = (1, tconf.CHK_FREQ)
    key = (old_key[1] + 1, old_key[1] + tconf.CHK_FREQ)

    new_checkpoint = Checkpoint(instId=ordered.instId,
                                viewNo=ordered.viewNo,
                                seqNoStart=key[0],
                                seqNoEnd=key[1],
                                digest=cp_digest(1, 1))

    for sender in senders[:quorum]:
        assert not checkpoint_service._do_process_checkpoint(
            checkpoint, sender)
        assert checkpoint_service._stashed_recvd_checkpoints[
            checkpoint.viewNo][old_key][sender] == checkpoint

    for sender in senders[:quorum - 1]:
        assert not checkpoint_service._do_process_checkpoint(
            new_checkpoint, sender)
        assert checkpoint_service._stashed_recvd_checkpoints[
            checkpoint.viewNo][key][sender] == new_checkpoint

    assert not checkpoint_service._do_process_checkpoint(
        new_checkpoint, senders[quorum - 1])

    if is_master:
        assert checkpoint_service._data.low_watermark == key[1]
        master_catchup_handler.assert_called_once_with(NeedMasterCatchup())
    else:
        backup_catchup_handler.assert_called_once_with(
            NeedBackupCatchup(inst_id=checkpoint_service._data.inst_id,
                              caught_up_till_3pc=(checkpoint_service.view_no,
                                                  key[1])))
    def _start_catchup_if_needed(self):
        stashed_checkpoint_ends = self._stashed_checkpoints_with_quorum()
        lag_in_checkpoints = len(stashed_checkpoint_ends)
        if self._checkpoint_state:
            (s, e) = firstKey(self._checkpoint_state)
            # If the first stored own checkpoint has a not aligned lower bound
            # (this means that it was started after a catch-up), is complete
            # and there is a quorumed stashed checkpoint from other replicas
            # with the same end then don't include this stashed checkpoint
            # into the lag
            if s % self._config.CHK_FREQ != 0 \
                    and self._checkpoint_state[(s, e)].seqNo == e \
                    and e in stashed_checkpoint_ends:
                lag_in_checkpoints -= 1
        is_stashed_enough = \
            lag_in_checkpoints > self.STASHED_CHECKPOINTS_BEFORE_CATCHUP
        if not is_stashed_enough:
            return

        if self.is_master:
            self._logger.display(
                '{} has lagged for {} checkpoints so updating watermarks to {}'
                .format(self, lag_in_checkpoints, stashed_checkpoint_ends[-1]))
            self.set_watermarks(low_watermark=stashed_checkpoint_ends[-1])
            if not self._data.is_primary:
                self._logger.display(
                    '{} has lagged for {} checkpoints so the catchup procedure starts'
                    .format(self, lag_in_checkpoints))
                self._bus.send(NeedMasterCatchup())
        else:
            self._logger.info(
                '{} has lagged for {} checkpoints so adjust last_ordered_3pc to {}, '
                'shift watermarks and clean collections'.format(
                    self, lag_in_checkpoints, stashed_checkpoint_ends[-1]))
            # Adjust last_ordered_3pc, shift watermarks, clean operational
            # collections and process stashed messages which now fit between
            # watermarks
            key_3pc = (self.view_no, stashed_checkpoint_ends[-1])
            self._bus.send(
                NeedBackupCatchup(inst_id=self._data.inst_id,
                                  caught_up_till_3pc=key_3pc))
            self.caught_up_till_3pc(key_3pc)