Example #1
0
 def event(self, x):
     if isinstance(x, Send):
         self.send(x)
         yield Reply()
     elif isinstance(x, Tick):
         if x.id % 330 == 0 and hasattr(self, 'net_stats'):
             rcv = sorted([(k, v) for k, v in self.net_stats.recv.items()])
             snd = sorted([(k, v) for k, v in self.net_stats.send.items()])
             logger.error(
                 f'{self.quorum.replica_id} {self.net_stats.traffic_recv} {self.net_stats.traffic_send} {rcv} {snd}'
             )
         yield Reply()
     else:
         assert False, x
Example #2
0
    def event(self, x):
        if isinstance(x, Tick):

            def lenx(iter_obj):
                i = 0
                for x in iter_obj:
                    i += 1
                return i

            if x.id % 330 == 0:
                instc = sorted((x.name, lenx(y)) for x, y in groupby(
                    sorted(x.state.stage for x in self.store.inst.values())))
                logger.error(f'{self.quorum.replica_id} {instc}')

            yield Reply()
        elif isinstance(x, LoadCommandSlot):
            yield Reply(self.store.load_cmd_slot(x.id))
        elif isinstance(x, Load):
            yield Reply(self.store.load(x.slot).inst)
        elif isinstance(x, Store):
            # todo: all stores modify timeouts
            old, new = self.store.update(x.slot, x.inst)

            self.log(lambda: f'{self.quorum.replica_id}\t{x.slot}\t{new}\n')

            deps_comm = []
            for d in new.state.deps:
                r = self.store.load(d)

                if not r.exists:
                    r_old, r_new = self.store.update(d, r.inst)
                    yield InstanceState(d, r_new)

                deps_comm.append(r.inst.state.stage == Stage.Committed)

            if new.ballot.b > 10:
                logger.error(f'{self.quorum.replica_id} {x.slot} {new} HW')

            yield InstanceState(x.slot, new)
            yield Reply(new)
        elif isinstance(x, CheckpointEvent):
            self.store.set_cp(x.at)
            yield Reply(None)
        else:
            assert False, x
Example #3
0
    def event(self, x):
        if isinstance(x, Packet):
            assert isinstance(x.payload, packet.ClientRequest)

            # we may use the clientrequest as a way of keeping the knowledge of whom to reply.
            # client dests are then

            loaded = yield LoadCommandSlot(x.payload.command.id)

            # todo: this. here we assume that slots are not correlated with commands.

            if loaded is None:
                self.st_starts += 1
                slot = yield LeaderStart(x.payload.command)
            else:
                self.st_restarts += 1
                slot, inst = loaded

                inst: Optional[InstanceStoreState]

                # logger.error(f'{self.quorum.replica_id} Learned about a new client {x.origin} of slot {slot} {inst.state.command}')

                if inst.state.stage >= Stage.Committed:
                    yield Send(x.origin,
                               packet.ClientResponse(inst.state.command))

            slot: Slot

            self.clients[slot] = x.origin

            if x.origin not in self.peers:
                self.peers[x.origin] = []

            self.peers[x.origin].append(slot)
        elif isinstance(x, Tick):
            if x.id % 330 == 0:
                logger.error(
                    f'{self.quorum.replica_id} St={self.st_starts}/{self.st_restarts}'
                )
        elif isinstance(x, InstanceState):
            if x.slot in self.clients and x.inst.state.stage == Stage.Committed:
                # print('REPLY')

                yield Send(self.clients[x.slot],
                           packet.ClientResponse(x.inst.state.command))

                peer = self.peers[self.clients[x.slot]]
                peer.remove(x.slot)

                del self.clients[x.slot]
        else:
            assert False, x
        yield Reply()
Example #4
0
    def event(self, x):
        if isinstance(x, packet.Packet) and isinstance(x.payload,
                                                       PACKET_LEADER):
            slot = x.payload.slot  # type: Slot

            if slot in self.waiting_for:
                yield from self.run_sub(
                    slot, (x.origin,
                           Receive.from_waiting(self.waiting_for.pop(slot),
                                                x.payload)))

            yield Reply()
        elif isinstance(x, InstanceState):
            if x.inst.state.stage >= Stage.Committed:
                if x.slot in self.waiting_for:
                    del self.waiting_for[x.slot]
                if x.slot in self.subs:
                    del self.subs[x.slot]
            yield Reply()
        elif isinstance(x, LeaderStart):
            slot = Slot(self.quorum.replica_id, self.next_instance_id)
            self.next_instance_id += 1

            self.subs[slot] = leader_client_request(self.quorum, slot,
                                                    x.command)

            yield from self.run_sub(slot)
            yield Reply(slot)
        elif isinstance(x, LeaderStop):
            if x.slot in self.waiting_for:
                del self.waiting_for[x.slot]
            if x.slot in self.subs:
                del self.subs[x.slot]
            yield Reply()
        elif isinstance(x, LeaderExplicitPrepare):
            prev = self.subs.get(x.slot) is not None

            self.subs[x.slot] = leader_explicit_prepare(
                self.quorum, x.slot, x.reason)

            yield from self.run_sub(x.slot)
            yield Reply(prev)
        elif isinstance(x, CheckpointEvent):
            ctr = 0

            for slot in between_checkpoints(*self.cp.cycle(x.at)):
                if slot in self.subs:
                    ctr += 1
                    del self.subs[slot]
                if slot in self.waiting_for:
                    ctr += 1
                    del self.waiting_for[slot]

            logger.error(
                f'{self.quorum.replica_id} cleaned old things between {ctr}: {self.cp}'
            )

            yield Reply()
        else:
            assert False, x
Example #5
0
def main():
    q = Quorum([1, 2, 3, 4], 0, 0)

    c = Configuration(1, 3, 33, 10 * 33)

    state = StateActor().run()
    clients = ClientsActor().run()
    leader = LeaderCoroutine(q).run()
    acceptor = AcceptorCoroutine(q, c).run()
    net = NetActor().run()

    next(state)
    next(clients)
    next(leader)
    next(acceptor)
    next(net)

    m = MainCoroutine(
        state,
        clients,
        leader,
        acceptor,
        net,
    ).run()

    # print('S', next(m))
    x = next(m)

    while True:

        assert isinstance(x, Wait), x

        x = m.send(
            Packet(0, 0, 'ClientRequest',
                   ClientRequest(Command(uuid4(), Checkpoint(1)))))

        print(x)

        # while isinstance(x, ClientNetComm):
        #     print(x)
        #     x = m.send(Reply(True))

    print('>>>>>>>>', x)

    x = m.send(Reply(True))

    print(next(m))
Example #6
0
    def event(self, x):
        if isinstance(x, Packet):
            if isinstance(x.payload, packet.PingRequest):
                yield Send(x.origin, packet.PongResponse(x.payload.id))
            elif isinstance(x.payload, packet.PongResponse):
                if x.payload.id == self.last_ping_id.get(x.origin, -1):
                    time = datetime.now() - self.last_ping[x.origin]
                    self.pings_rcvd[x.origin] = self.pings_rcvd.get(
                        x.origin, 0) + 1
                    self.pings_times[x.origin] = (
                        self.pings_times.get(x.origin, []) +
                        [time.total_seconds()])[:self.keep_times]
                else:
                    # todo: reordered pings
                    pass
            else:
                assert False, ''
        elif isinstance(x, Tick):
            if x.id % self.ping_every_tick == 0:
                now = datetime.now()
                for peer in self.quorum.peers:
                    self.last_ping[peer] = now
                    self.last_ping_id[peer] = self.last_ping_id.get(peer, 0)
                    self.pings_sent[peer] = self.pings_sent.get(peer, 0) + 1
                    yield Send(peer,
                               packet.PingRequest(self.last_ping_id[peer]))

            if x.id % 300 == 0:
                pings_repl = sorted((k, f'{sum(v)/len(v)*1000:0.2f}ms')
                                    for k, v in self.pings_times.items())
                pings_recv = sorted((k, f'{v}/{self.pings_sent[k]}')
                                    for k, v in self.pings_rcvd.items())
                logger.error(
                    f'{self.quorum.replica_id} {pings_repl} {pings_recv}')
        else:
            assert False, ''
        yield Reply()
Example #7
0
 def route(self, req, d=0):
     if isinstance(req, STATE_MSGS):
         return self.run_sub(self.state, req, d)
     elif isinstance(req, LEADER_MSGS):
         return self.run_sub(self.leader, req, d)
     elif isinstance(req, STATE_MSGS):
         return self.run_sub(self.state, req, d)
     elif isinstance(req, NET_MSGS):
         return self.run_sub(self.net, req, d)
     elif isinstance(req, STATE_EVENTS):
         self.run_sub(self.clients, req, d)
         self.run_sub(self.acceptor, req, d)
         self.run_sub(self.leader, req, d)
         self.run_sub(self.executor, req, d)
         return Reply(None)
     elif isinstance(req, CHECKPOINT_EVENTS):
         self.run_sub(self.acceptor, req, d)
         self.run_sub(self.state, req, d)
         self.run_sub(self.leader, req, d)
     elif isinstance(req, Reply):
         return req
     else:
         self._trace(f'Unroutable {req}')
         raise Unroutable(req)
Example #8
0
    def event(self, x):
        if isinstance(x, InstanceState):

            if x.inst.state.stage >= Stage.Committed:
                # self.log(lambda: f'{self.quorum.replica_id}\tSTAT\t{x.slot}\t{x.inst}\n')
                if not self.is_executed(x.slot) and not self.is_executing(x.slot):
                    self.executing[x.slot] = True
                    self.ctr += 1
                    self.log(lambda: f'{self.quorum.replica_id}\tDPH0\t{self.dph.ccs}\n')

                    unlocked_list = self.dph.ready(x.slot, [x for x in x.inst.state.deps if not self.is_executed(x)])
                    self.log(lambda: f'{self.quorum.replica_id}\tDPH1\t{self.dph.ccs}\n')
                    self.log(lambda: f'{self.quorum.replica_id}\tDPH2\t{unlocked_list}\n')

                    # if self.ctr % 100:
                    #     self.log(lambda: f'{self.quorum.replica_id}\tDPHX\t{self.dph.ccs}\n')

                    try:
                        for checkpoint in self.build_execute_pending(unlocked_list):
                            xx = self.store.load(checkpoint).inst
                            yield CheckpointEvent(checkpoint, {x.replica_id: x for x in xx.state.deps})
                    except:
                        self.log(lambda: f'{self.quorum.replica_id}\tDPHz\t{self.dph.ccs}\n')
                        raise
        elif isinstance(x, Tick):
            if x.id % 330 == 0:
                totd = sum(x.depth() for _, x in self.dph.ccs.items())
                logger.error(
                    f'{self.quorum.replica_id} Exec={self.st_exec} Deps={len(self.dph.ccs)} Depth={totd}')
                if totd > 10:
                    for cc in self.dph.ccs.values():
                        logger.error(
                            f'{self.quorum.replica_id} {cc}')
        else:
            assert False, x
        yield Reply()
Example #9
0
    def event(self, x):
        if isinstance(x, packet.Packet) and isinstance(x.payload,
                                                       PACKET_ACCEPTOR):
            slot = x.payload.slot

            if slot not in self.subs:
                self.subs[slot] = acceptor_single_ep(self.quorum, slot)
                yield from self.run_sub(slot)

            if slot in self.waiting_for:
                rcv = Receive.from_waiting(self.waiting_for.pop(slot),
                                           x.payload)
                yield from self.run_sub(slot, (x.origin, rcv))
        elif isinstance(x, InstanceState):
            if x.slot in self.slots_timeouts:
                slot_tick = self.slots_timeouts[x.slot]

                del self.timeouts_slots[slot_tick][x.slot]

                if x.inst.state.stage == Stage.Committed:
                    del self.slots_timeouts[x.slot]

            if x.inst.state.stage < Stage.Committed:
                tick = self.tick + self.config.timeout + random.randint(
                    0, self.config.timeout_range)
                # print(self.quorum.replica_id, 'SET TIMEOUT ', self.tick, tick)

                self.slots_timeouts[x.slot] = tick

                if tick not in self.timeouts_slots:
                    self.timeouts_slots[tick] = {}
                self.timeouts_slots[tick][x.slot] = True

            if x.inst.state.stage >= Stage.Committed:
                if x.slot in self.waiting_for:
                    del self.waiting_for[x.slot]
                if x.slot in self.subs:
                    del self.subs[x.slot]

        elif isinstance(x, Tick):
            self.tick = x.id

            # print(self.quorum.replica_id, self.tick)
            if x.id in self.timeouts_slots:
                to_start = []
                for slot, truth in self.timeouts_slots[x.id].items():
                    to_start.append(slot)
                    del self.slots_timeouts[slot]
                del self.timeouts_slots[x.id]

                for slot in to_start:
                    yield LeaderExplicitPrepare(slot, 'TIMEOUT')

            if x.id % self.config.checkpoint_each == 0:
                checkpoint_id = x.id // self.config.checkpoint_each
                r_idx = sorted(self.quorum.peers +
                               [self.quorum.replica_id]).index(
                                   self.quorum.replica_id)

                q_length = self.quorum.full_size

                if checkpoint_id % q_length == r_idx:
                    import sys
                    cp_cmd = Command(
                        CommandID.create(),
                        Checkpoint(checkpoint_id * q_length + r_idx))
                    print('SIZEOF', getsize(cp_cmd))
                    yield LeaderStart(cp_cmd)

                last_tick = x.id

                # fmtd = '\n'.join(f'\t\t{x.name}: {y}' for x, y in sorted((y, len(list(x))) for y, x in
                #                                                          groupby(sorted([v.state.stage for k, v in
                #                                                                          self.replica.store.inst.items()]))))
                #
                # fmtd3 = '\n'.join(
                #     f'\t\t{x}: {y}' for x, y in sorted([(k, v) for k, v in self.state.packet_counts.items()]))

                # fmtd = ''
                # fmtd3 = ''

                # logger.debug(
                #     f'\n{self.quorum.replica_id}\t{x.id}\n\tInstances:\n{fmtd}\n\tPackets:\n{fmtd3}')
        elif isinstance(x, CheckpointEvent):
            ctr = 0
            for slot in between_checkpoints(*self.cp.cycle(x.at)):

                if slot in self.subs:
                    ctr += 1
                    del self.subs[slot]
                if slot in self.waiting_for:
                    ctr += 1
                    del self.waiting_for[slot]

            logger.error(
                f'{self.quorum.replica_id} cleaned old things between {ctr}: {self.cp}'
            )

        else:
            assert False, x

        yield Reply()