class Proposer (object): _sync = {} _async = ['set_multi', 'prepare', 'promise', 'set_proposal'] _ref = ['set_multi'] _parallel = [] def __init__(self, quorum_size): self.quorum_size = quorum_size self.proposed_value = None self.last_accepted_id = None self.next_proposal_number = 1 #async, ref def set_multi(self, list_acceptors): self.list_acceptors = list_acceptors self.amulti = AMulti(self.list_acceptors) self.smulti = SMulti(self.list_acceptors, self._atom) def set_proposal(self, value): ''' Sets the proposal value for this node if this node is not already aware of another proposal having already been accepted. ''' if self.proposed_value is None: self.proposed_value = value def prepare(self): ''' Sends a prepare request to all Acceptors as the first step in attempting to acquire leadership of the Paxos instance. ''' self.promises_rcvd = set() self.proposal_id = ProposalID(self.next_proposal_number, self.id) print 'holaa', self.proposal_id self.next_proposal_number += 1 #multi to all acceptors!! result = self.smulti.onPrepare(self.proxy, self.proposal_id) self.promise(result) def promise(self, infoAcceptors): ''' Called when a Promise message is received from an Acceptor ''' for a in infoAcceptors: # Ignore the message if it's for an old proposal or we have already received # a response from this Acceptor if a[1] != self.proposal_id or a[0] in self.promises_rcvd: None else: self.promises_rcvd.add( a[0] ) if a[2] > self.last_accepted_id: self.last_accepted_id = a[2] # If the Acceptor has already accepted a value, we MUST set our proposal # to that value. if a[2] is not None: self.proposed_value = a[3] if len(self.promises_rcvd) > self.quorum_size/2: if self.proposed_value is not None: self.amulti.accept(self.id, self.proposal_id, self.proposed_value) break