aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAditya Naik2017-12-02 13:23:05 -0500
committerAditya Naik2017-12-02 13:23:05 -0500
commite0c30290bfdb64f7a8bda3612b4d12bc47bf9877 (patch)
tree9ff817568cd82afe6a17d45a6388c61a67b048e4
parent4db5586e749fe7a5043009cbe590a8dd7a46e429 (diff)
steps 1 and 2 work for a single ballot, some issues with initiating with 0 entries in messagebooks and/or ledgers
-rw-r--r--prelim.py187
1 files changed, 137 insertions, 50 deletions
diff --git a/prelim.py b/prelim.py
index 192ccca..e8055d7 100644
--- a/prelim.py
+++ b/prelim.py
@@ -1,13 +1,15 @@
import pandas as pd
-import random as rand
-import string
+import random
+import time
+from threading import Thread
+
"""
===============================
priest ledger format:
-voted or not, ballot number, promised or not, times led
-0/1,n,0/1,x
+ballot number, voted or not, promised or not, times led
+n,0/1,0/1,x
promised or not explanation: whether or not this priest has promised to not
respond to maxvote requests after this ballot
@@ -18,25 +20,34 @@ times led explanation: number of times she's been leader
priest messagebook format:
(priests will track these for changes by messenger)
-from,code
-n,1/2/3
+from,code,voted_at_ballot=-1
+n,1/2/3,ballot_num
-codes (not leader):
-1: next ballot
+voted_at_ballot: responding to next_ballot from priests
+
+codes (to leader):
+1: last vote
2: begin ballot
3: successful ballot
-codes (leader):
-
+codes (from leader):
+1: next ballot
+2: begin ballot
+3: succesful ballot
===============================
-sequence of code writing (may provide intuition for future folks):
+sequence of function writing:
- skeleton
- priest init
- leader_main
- god init
- next_ballot
+- messenger init
- send_next_ballot
+- priest_main
+
+TODO next:
+- send_last_vote
===============================
"""
@@ -51,16 +62,26 @@ paxons are very religious; god controls anything and everything
class god:
num_priests = 0
- priests = {}
-
+ priests = {} #key:value ~ priest name : priest instance
+ messengers = []
def __init__(self, num_priests, num_ballots, offset=100):
self.num_priests = num_priests
self.num_ballots = num_ballots
+
+ random_leader = random.randint(0,num_priests-1)
+ #create and name the priests and messengers (quite godly)
+ for name in range(0, self.num_priests):
+ if name == random_leader:
+ self.priests[name] = priest(name, (name+1)*offset, True)
+ else:
+ self.priests[name] = priest(name, (name+1)*offset, False)
+
+ for priest_name in self.priests.keys():
+ self.priests[priest_name].start()
- #create and name the priests (quite godly)
- for x in range(0, self.num_priests):
- self.priests[x] = priest(name, (x+1)*offset)
-
+ for priest_name in self.priests.keys():
+ self.priests[priest_name].join()
+
"""
messenger relays messages to and from the leader and the priest
@@ -71,23 +92,33 @@ each priest (including the leader) has a personal messenger (instance)
class messenger(god):
+ def __init__(self, serving_priest):
+ self.serving_priest = serving_priest
+
"""
leader messenger functions
- """
- def send_next_ballot(current_list, ballot_num):
- pass
-
-
- def send_begin_ballot():
+ """
+ def send_next_ballot(self,current_list, ballot_num):
+ message = [[self.serving_priest,1]]
+ msg_df = pd.DataFrame(data = message)
+ for priest_name in current_list:
+ if str(priest_name) == str(self.serving_priest):
+ pass
+ else:
+ print("LOG: leader sending message to priest #" + str(priest_name))
+ with open('messages/'+str(priest_name), 'a') as f:
+ msg_df.to_csv(f, header=False, index=False)
+
+ def send_begin_ballot(self):
pass
- def send_on_success():
+ def send_on_success(self):
pass
"""
priest messenger functions
"""
- def send_last_vote():
+ def send_last_vote(self,ballot_num):
pass
def send_vote():
@@ -106,32 +137,58 @@ ex. priests (A, B, C) have offsets (100, 200, 300) (this assumes maximum of 99 b
leader sequence (determined randomly by god): A B A C B A
resulting ballot numbers: 100 200 101 300 201 102
"""
-class priest(messenger):
-
- def __init__(self, name, start_offset):
+class priest(messenger, Thread):
+ def __init__(self, name, start_offset, is_leader): #is_leader: temporary var for single ballot test
+ Thread.__init__(self)
self.name = name #write this name in the ledger in case it gets lost (ledger fileaname)
- self.messenger = messenger() #hire a messenger
- self.ledger = open("ledgers/" + self.name, "+")
- self.offset = offset
+ self.messenger = messenger(self.name) #hire a messenger
+ self.ledger = "ledgers/" + self.name
+ self.messagebook = "messages/" + self.name
- #=====================leader functions===================
- def leader_main():
- times_led = self.ledger.at[self.ledger.shape[0]-1,'times_led'] #last col of last row of ledger
- ballot_num = self.offset + times_led #B1 is satisfied assuming num_ballots < difference between offsets
+ self.messages_recieved = 0
+ # with open(self.ledger, 'w') as ledgerfile:
+ # ledgerfile.write("ballot_num,voted,promised,times_led")
+
+ with open(self.messagebook, 'w') as msgbookfile:
+ msgbookfile.write("from,code\n")
+
+ self.offset = start_offset
+ self.is_leader = is_leader
+
+ def run(self):
+ if(self.is_leader):
+ self.leader_main()
+ else:
+ self.priest_main()
+ #=====================leader functions===================
+ def leader_main(self):
+ print("LOG: " + self.name + " is the leader")
+ try:
+ ledger_data = pd.read_csv(self.ledger)
+ times_led = ledger_data.at[ledger_data.shape[0]-1,'times_led'] #last col of last row of ledger
+ except pd.errors.EmptyDataError:
+ times_led = 0
+
+ ballot_num = self.offset + int(times_led) #B1 is satisfied assuming num_ballots < difference between offsets
+ print("LOG: Leader initiating ballot #" + str(ballot_num))
self.next_ballot(ballot_num)
self.begin_ballot()
- def next_ballot(ballot_num):
+ def next_ballot(self,ballot_num):
#randomly choose a number of priests: 40% - 100% of total priests
- rand_num = random.randrange(num_priests*0.4, num_priests+1)
- current_priests = random.sample(priests.keys(), rand_num)
+ #rand_num = random.randrange(self.num_priests*0.4, self.num_priests+1)
+
+ #current_priests = random.sample(self.priests.keys(), rand_num)
+ current_priests = self.priests.keys()
#Send the nextBallot message to the priests and wait for their responses
- messenger.send_next_ballot(current_list, ballot_num)
+ self.messenger.send_next_ballot(current_priests, ballot_num)
+
- def begin_ballot():
+ def begin_ballot(self):
+ pass
#wait for all threads to respond
#send message to every priest indicating that his vote is requested
@@ -143,26 +200,56 @@ class priest(messenger):
#====================regular priest functions======================
- def priest_main():
- pass
- def last_vote():
- pass
- #responding to a next_ballot request from the leader
+ def priest_main(self):
+ print("LOG: " + self.name + " is a priest")
+ msg_from = self.new_message() #recieved msg from msg_from
+ print("LOG: priest #" + self.name + " recieved msg from #" + str(msg_from))
+ self.last_vote(msg_from)
+
+ def last_vote(self,leader_num):
#determine the lastVote and send it to the leader (if not promised to another leader) (might
- #need another function for this)
+ #need another function for this)
+ ledger = pd.read_csv(self.ledger)
+ last_voted = -1
+ for entry in reversed(range(ledger.shape[0],0)):
+ if(entry['voted']==1):
+ last_voted = entry['ballot_num']
+ break
+
+ #responding to a next_ballot request from the leader
+ #TODO: check for promieses before responding
+ self.messenger.send_last_vote(last_voted)
+ #TODO: if responded, set promise to 1 for the relevant maxVote in the ledger
- #if responded, set promise to 1 for the relevant maxVote in the ledger
def vote():
pass
+
#choose (randomly) whether or not to vote on this ballot
- #send the vote to the leader (another function "voted"?)
+ #send the vote to the leader (maybe put another function "voted")
def on_success():
pass
#do something if the messenger brings the good news of a ballot success
+
+ #======================general functions============================
+
+ def new_message(self):
+ #block till new message read
+
+ while True:
+ time.sleep(0.4)
+ try:
+ msgbook_data = pd.read_csv(self.messagebook)
+ if(msgbook_data.shape[0]>self.messages_recieved):
+ return msgbook_data.at[msgbook_data.shape[0]-1,'from']
+
+ except pd.errors.EmptyDataError:
+ pass
+
-
-
+
+if __name__ == '__main__':
+ god_instance = god(3,5)