def __init__(self, clientId: str, nodeReg: Dict[str, HA]=None, ha: Union[HA, Tuple[str, int]]=None, lastReqId: int = 0, signer: Signer=None, basedirpath: str=None): """ Creates a new client. :param clientId: unique identifier for the client :param nodeReg: names and host addresses of all nodes in the pool :param lastReqId: Request Id of the last request sent by client :param stack: node stack or dictionary of node constructor kwargs :param signer: Helper for signer (defines sign method) """ self.clientId = clientId self.lastReqId = lastReqId self._clientStack = None cha = ha if isinstance(ha, HA) else HA(*ha) stackargs = dict(name=clientId, ha=cha, main=False, # stops incoming vacuous joins auto=AutoMode.always) if basedirpath: stackargs['basedirpath'] = basedirpath self.created = time.perf_counter() NodeStacked.__init__(self, stackParams=stackargs, nodeReg=nodeReg) logger.info("Client initialized with the following node registry:") lengths = [max(x) for x in zip(*[ (len(name), len(host), len(str(port))) for name, (host, port) in nodeReg.items()])] fmt = " {{:<{}}} listens at {{:<{}}} on port {{:>{}}}".format( *lengths) for name, (host, port) in nodeReg.items(): logger.info(fmt.format(name, host, port)) Motor.__init__(self) self.inBox = deque() self.signer = signer if signer else SimpleSigner(self.clientId)
def __init__(self, name: str, nodeRegistry: Dict[str, HA], clientAuthNr: ClientAuthNr=None, ha: HA=None, cliname: str=None, cliha: HA=None, basedirpath: str=None, primaryDecider: PrimaryDecider = None): """ Create a new node. :param nodeRegistry: names and host addresses of all nodes in the pool :param clientAuthNr: client authenticator implementation to be used :param basedirpath: path to the base directory used by `nstack` and `cstack` :param primaryDecider: the mechanism to be used to decide the primary of a protocol instance """ self.primaryDecider = primaryDecider me = nodeRegistry[name] self.allNodeNames = list(nodeRegistry.keys()) if isinstance(me, NodeDetail): sha = me.ha scliname = me.cliname scliha = me.cliha nodeReg = {k: v.ha for k, v in nodeRegistry.items()} else: sha = me if isinstance(me, HA) else HA(*me) scliname = None scliha = None nodeReg = {k: HA(*v) for k, v in nodeRegistry.items()} if not ha: # pull it from the registry ha = sha if not cliname: # default to the name plus the suffix cliname = scliname if scliname else name + CLIENT_STACK_SUFFIX if not cliha: # default to same ip, port + 1 cliha = scliha if scliha else HA(ha[0], ha[1]+1) nstack = dict(name=name, ha=ha, main=True, auto=AutoMode.never) cstack = dict(name=cliname, ha=cliha, main=True, auto=AutoMode.always) if basedirpath: nstack['basedirpath'] = basedirpath cstack['basedirpath'] = basedirpath self.clientAuthNr = clientAuthNr or SimpleAuthNr() self.nodeInBox = deque() self.clientInBox = deque() self.created = time.perf_counter() HasActionQueue.__init__(self) NodeStacked.__init__(self, nstack, nodeReg) ClientStacked.__init__(self, cstack) Motor.__init__(self) Propagator.__init__(self) self.totalNodes = len(nodeRegistry) self.f = getMaxFailures(self.totalNodes) self.requiredNumberOfInstances = self.f + 1 # per RBFT self.minimumNodes = (2 * self.f) + 1 # minimum for a functional pool self.txnStore = TransactionStore() # Stores which protocol instance is master self._masterInst = None # type: Optional[int] self.replicas = [] # type: List[replica.Replica] self.instanceChanges = InstanceChanges() self.viewNo = 0 # type: int self.rank = self.getRank(self.name, nodeRegistry) self.elector = None # type: PrimaryDecider self.forwardedRequests = set() # type: Set[Tuple[(str, int)]] self.monitor = Monitor(.9, 60, 5) # Requests that are to be given to the replicas by the node. Each # element of the list is a deque for the replica with number equal to # its index in the list and each element of the deque is a named tuple self.msgsToReplicas = [] # type: List[deque] # Requests that are to be given to the elector by the node self.msgsToElector = deque() nodeRoutes = [(Propagate, self.processPropagate), (InstanceChange, self.processInstanceChange)] nodeRoutes.extend((msgTyp, self.sendToElector) for msgTyp in [Nomination, Primary, Reelection]) nodeRoutes.extend((msgTyp, self.sendToReplica) for msgTyp in [PrePrepare, Prepare, Commit]) self.nodeMsgRouter = Router(*nodeRoutes) self.clientMsgRouter = Router((Request, self.processRequest)) self.perfCheckFreq = 10 self._schedule(self.checkPerformance, self.perfCheckFreq) self.clientBlacklister = SimpleBlacklister( self.name + CLIENT_BLACKLISTER_SUFFIX) # type: Blacklister self.nodeBlacklister = SimpleBlacklister( self.name + NODE_BLACKLISTER_SUFFIX) # type: Blacklister # BE CAREFUL HERE # This controls which message types are excluded from signature # verification. These are still subject to RAET's signature verification # but client signatures will not be checked on these. Expressly # prohibited from being in this is ClientRequest and Propagation, # which both require client signature verification self.authnWhitelist = (Nomination, Primary, Reelection, Batch, PrePrepare, Prepare, Commit, InstanceChange) self.addReplicas()