Skip to content

Instantly share code, notes, and snippets.

@fjkz
Created October 10, 2015 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fjkz/6239760499a791baba34 to your computer and use it in GitHub Desktop.
Save fjkz/6239760499a791baba34 to your computer and use it in GitHub Desktop.
A simple Paxos implementation for study.
"""
A simple Paxos implementation for study.
"""
from collections import Counter
class Proposer:
def __init__(self, acceptors):
self.acceptors = acceptors
self.number = 0
self.value = 'proposal value'
self.preparing_acceptors = []
def send_prepare_requests(self):
print('Start sending prepare requests.')
self.preparing_acceptors = []
highest_res_num = -1
for acceptor in acceptors:
print(' Send a prepare request to ' + str(acceptor) +
' with no = ' + str(self.number) + '.')
try:
responce = acceptor.prepare(self.number)
except IOError:
print(' Failed to send a prepare request to ' + str(acceptor) + '.')
continue
self.preparing_acceptors.append(acceptor)
res_number = responce[0]
res_value = responce[1]
if res_number > highest_res_num:
highest_res_num = number
# Remember the highest-numbered proposal among the responces.
self.value = value
num_acceptors = len(self.acceptors)
num_preparing = len(self.preparing_acceptors)
print(str(num_preparing) + ' / ' + str(num_acceptors) + ' are preparing.')
if (num_preparing < num_acceptors // 2 + 1):
print('Acceptors that responded to a prepare request are not majority.')
return
print('Finish sending prepare requests.')
def send_accept_requests(self):
print('Start to send accept requests.')
for acceptor in self.preparing_acceptors:
print(' Send a accept request to ' + str(acceptor) +
' with no = ' + str(self.number) +
', value = "' + str(self.value) + '".')
try:
acceptor.accept(self.number, self.value)
except IOError:
print(' Failed to send a accept request to ' + str(acceptor))
print('Finish sending accept requests.')
class Acceptor:
def __init__(self, name, learners):
self.name = name
self.learners = learners
self.prepared_number = -1
self.accepted_number = -1
self.accepted_value = None
def __str__(self):
return self.name
def prepare(self, proposal_number):
if proposal_number <= self.prepared_number:
return None
self.prepared_number = proposal_number
# If not accept any proposal yet, return (-1, None)
return (self.accepted_number, self.accepted_value)
def accept(self, proposal_number, proposal_value):
if proposal_number < self.prepared_number:
return
self.accepted_number = proposal_number
self.accepted_value = proposal_value
for learner in self.learners:
learner.learn_accepted_value(
self.name, proposal_number, proposal_value)
class Learner:
def __init__(self, num_acceptors):
self.num_acceptors = num_acceptors
self.accepting_acceptors = []
self.accepted_value = []
def learn_accepted_value(
self, name, proposal_number, proposal_value):
print(' ' + str(name) + ' accepted "' +
str(proposal_value) + '".')
self.accepting_acceptors.append(name)
self.accepted_value.append(proposal_value)
def get_chosen_value(self):
most_common, num_most_common = \
Counter(self.accepted_value).most_common(1)[0]
if num_most_common < num_acceptors // 2 + 1:
print('The mostly accepted value is "' + str(most_common) + '", but not majority.')
return None
print('The chosen value is "' + str(most_common) + '".')
return most_common
if __name__ == '__main__':
num_acceptors = 2
learner = Learner(2)
acceptors = []
for i in range(num_acceptors):
name = 'a' + str(i)
learners = [learner]
acceptor = Acceptor(name, learners)
acceptors.append(acceptor)
proposer = Proposer(acceptors)
proposer.send_prepare_requests()
proposer.send_accept_requests()
learner.get_chosen_value()
@naman9119
Copy link

hey Brother,
can you help me how to use this code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment