Ejemplo n.º 1
0
 def accept_value(self, leaderNum, req_id, seqNum,
                  value):  # leaderNum, value
     # TODO: could be bug to not have greather than or equal...
     # int(seqNum) not in self.seq_dict:#
     #if int(leaderNum) >= self.selected_leaderNum and int(seqNum) > int(self.accepted_seqNum):
     seqNum = int(seqNum)
     if int(leaderNum) >= self.selected_leaderNum and int(
             seqNum
     ) not in self.locked_seq_nums:  # and int(seqNum) not in self.seq_dict: #DREW DEBUG? DOES TIS NEED TO BE HERE?
         # D2
         #if req_id in self.req_dict and self.req_dict[req_id] != int(seqNum): # if you already gave this req_id a different seq_num, send a NOP for this seq_num
         #	self.learner.acceptValue(leaderNum, self.idnum, "NOP", seqNum, "NOP")
         #	self.send_value(leaderNum, "NOP", seqNum, "NOP")
         #else: # else accept as usual
         self.accepted_lastVal = value
         self.accepted_req_id = req_id
         self.accepted_seqNum = seqNum
         self.seq_dict[int(seqNum)] = (req_id, value)
         self.locked_seq_nums.add(int(seqNum))
         self.learner.acceptValue(leaderNum, self.idnum, req_id, seqNum,
                                  value)
         self.send_value(leaderNum, req_id, seqNum, value)
         #self.req_dict[req_id] = int(seqNum) #D2
     else:
         printd(
             "Acceptor {} did not accept value with leaderNum = {} and sequence number = {}, while message has been proposed from leaderNum: {} with seq_number {}"
             .format(self.idnum, self.selected_leaderNum,
                     self.accepted_seqNum, leaderNum, seqNum))
Ejemplo n.º 2
0
    def acceptRequest(
        self, origin_socket, client_name, client_seq_number, value
    ):  # value, seq_number, seq_number_override=-1): self.client_name, self.client_seq_number, value
        self.value = value
        req_id = str(client_name) + '-' + str(client_seq_number)

        if self.am_leader == True:
            #if ( (client_name,client_seq_number) not in self.request_history ):  # if you've never seen this client_name, client_seq_num pair, it is a new request
            self.seq_number += 1
            if self.seq_number in self.skips:  # skip logic: set up leader 0 to skip seq_num 3, then be killed on seq_num 5
                print("\nMANUALLY SKIPPING SEQ_NUM {}".format(self.seq_number))
                self.seq_number += 1

            msg = str(self.leaderNum)
            msg += "," + req_id
            msg += "," + str(self.seq_number)
            msg += "," + str(self.value)
            full_msg = str(MessageType.COMMAND.value) + ":" + msg

            printd("Leader " + str(self.leaderNum) + "'s sequence number is " +
                   str(self.seq_number))
            self.acceptor.accept_value(
                self.leaderNum, req_id, self.seq_number,
                self.value)  # We should also accept a value locally

            Messenger.broadcast_message(self.socket_connections_list, full_msg)
            printd("Request accepted on replica {} (leader number: {})".format(
                str(self.idnum), str(self.leaderNum)))
Ejemplo n.º 3
0
	def execute_command (self, command):
		seq_number = command[0]
		value = command[1]
		req_id = command[2]

		self.add_msg_to_chat_log(seq_number, value, req_id)
		self.last_executed_seq_number = max(self.last_executed_seq_number,int(seq_number))

		printd(str(self.idnum) + " EXECUTES COMMAND " + str(command))
Ejemplo n.º 4
0
    def setup_server(self, numb_replicas):
        i = 0
        while i < numb_replicas:  # We know we should accept connections from all other replicas
            (clientsocket, address) = self.serversocket.accept()
            self.connections_list.append(clientsocket)
            printd(
                str(self.idnum) + " Accepted connection " +
                str(clientsocket.getsockname()))
            i += 1

        printd("Server is set up for " + str(self.idnum))
Ejemplo n.º 5
0
	def reply_to_client (self, req_id, value):
		if req_id == "NOP" or req_id == "NONE":
			return # no client to reply to
		client_name, client_seq_number = req_id.split('-')

		if client_name in self.client_mapping: # This client name must be in the client mapping
			clientsock = self.client_mapping[client_name]
			printd("Responding to client {} with client_seq_number {}.".format(client_name, client_seq_number))
			Messenger.send_message(clientsock, req_id)
		else:
			raise RuntimeError("This client name: {}, is not in our mapping for replica {}.".format(client_name, self.idnum))
Ejemplo n.º 6
0
def recv_message(aSocket):
    try:
        msg_size = recv_header(aSocket)
        chunk = aSocket.recv(msg_size)

        if chunk == '':
            raise RuntimeError("Receiving message failed")
        return chunk
    except (SocketError, ValueError) as e:
        printd(
            "Socket error in receive but should be no problem if you're killing a process"
        )
        return ''
Ejemplo n.º 7
0
    def wait_for_message(self):
        while self.active:  # Should just continue to wait for messages
            rd, wd, ed = select.select(self.connections_list, [], [],
                                       (self.timeout * int(self.idnum)) +
                                       self.timeout)

            if len(rd) == 0:  # We haven't received a message in a while...
                printd("Creating a new proposer on replica " + str(self.idnum))
                self.initialize_proposer()

            # Handle received messages
            for s in rd:
                self.recv_message(s)
Ejemplo n.º 8
0
 def wait_for_client_connections(self):
     while 1:
         (clientsock, address) = self.serversocket.accept()
         printd("Accept new client on socket " +
                str(clientsock.getsockname()))
         # Receive clients name and add it to learners name->socket mapping
         clientname = Messenger.recv_message(clientsock)
         printd("Replica {} received connection to client {}.".format(
             self.idnum, clientname))
         self.learner.add_client(clientname, clientsock)
         ct = threading.Thread(target=self.client_thread,
                               args=(clientsock, ))
         ct.start()
Ejemplo n.º 9
0
def send_message(aSocket, msg):
    try:
        if not should_drop_message():
            header = '%8s' % len(msg)
            sent = aSocket.send(header + msg)
            #printd("socket {} sent msg: {} to: {}".format(socket.getsockname(),msg, socket.getpeername()))
            if sent == 0:
                raise RuntimeError("Send message failed")
        else:
            printd("Dropped message ".upper() + str(msg))
    except SocketError as e:
        printd(
            "Socket error in send but should be no problem if you're killing a process"
        )
        return ''
Ejemplo n.º 10
0
	def acceptValue (self, leaderNum, idnum, req_id, seq_number, value):
		seq = int(seq_number)

		if seq > self.last_executed_seq_number:# or req_id == "NOP": # Else we should ignore

			self.seq_dict[seq].add(int(idnum)) # We've now seen one of these values

			if len(self.seq_dict[seq]) == self.majority_numb:
				printd(str(self.idnum) + " has majority for value at {} of {} (last exec seq num = {})".format(seq_number,str(value),self.last_executed_seq_number))
				self.reply_to_client(req_id, value)				   # so we can go ahead and reply to the client
				self.add_and_execute_seq_command(seq, value, req_id)
				del self.seq_dict[seq]
				return True
			else:
				printd("{} cannot execute for {},{} because we've only seen messages from{}.".format(self.idnum, seq_number, value, self.seq_dict[seq]))
				return False
Ejemplo n.º 11
0
    def operate (self, num_messages, manual_messages):
        printd("Client {} is operating".format(self.client_name))


        for i in range(num_messages):
            if manual_messages:
                msg = raw_input("What is Client {}'s msg? ".format(self.client_name))
            else:
                msg = self.generate_msg_text()

            self.send_message(str(msg))#self.client_seq_number) + ":" + msg)
            recvd_msg = str(self.recv_message())
            printd("Client received message {}.".format(recvd_msg))
            time.sleep(.1)

        # after completion, wait for the os to shut off client
        while not False: time.sleep(1)
Ejemplo n.º 12
0
    def get_value_at_seq_number(self, missing_seq_number):
        missing_seq_number = int(missing_seq_number)
        if missing_seq_number in self.seq_dict.keys():
            printd(
                "Replica {}'s acceptor is sending value {} for sequence number {}."
                .format(self.idnum, self.seq_dict[missing_seq_number][1],
                        missing_seq_number))
            seq_number_found = "True"
            missing_req_id = self.seq_dict[missing_seq_number][0]
            missing_value = self.seq_dict[missing_seq_number][1]
        else:
            printd("Replica {}'s accpetor is also behind sequence number {}.".
                   format(self.idnum, missing_seq_number))
            seq_number_found = "False"
            missing_req_id = "NONE"
            missing_value = ''

        self.locked_seq_nums.add(int(missing_seq_number))
        return (seq_number_found, missing_req_id, missing_value)
Ejemplo n.º 13
0
    def __init__(self,
                 idnum,
                 ip,
                 port,
                 server_pairs,
                 semaphore,
                 test_cases,
                 proposer=False):

        self.idnum = idnum
        self.ip = ip
        self.port = int(port)
        self.semaphore = semaphore  # This semaphore is shared with all processes to wait till all connections are made

        self.num_replicas = len(server_pairs)
        self.majority = (len(server_pairs) //
                         2) + 1  # interger division rounds down, so add one

        self.other_replicas = [
            x for x in server_pairs if x != (ip, str(port))
        ]  # List of tuples (ip, port)

        printd("\nREPLICA {}\nServer Pairs: {}\nOther Replicas: {}".format(
            self.idnum, server_pairs, self.other_replicas))

        self.learner = Learner.Learner(self.num_replicas, self.majority,
                                       self.idnum)
        self.acceptor = Acceptor.Acceptor(self.idnum, self.learner)
        self.learner.set_acceptor(self.acceptor)  # This is nauseating...

        self.proposer = None
        self.should_kill = False

        self.skips = []
        self.kills = []

        for case in test_cases:
            if case[0] == "kill":  # if kill case active, put the seq_num into kills list
                self.kills.append(case[1])
            if case[0] == "skip":  # if skip test case active, put the seq_num into skips list
                self.skips.append(case[1])

        self.kill_next_round = False
Ejemplo n.º 14
0
    def acceptLeader(self, newLeaderNum, socket):
        # send YOU_ARE_LEADER to proposer with seqNum, accepted_lastVal, and selected_leaderNum
        # We must only promise to follow leaders with leader numbers higher than our current leader
        if int(newLeaderNum) > self.selected_leaderNum:
            self.selected_leaderNum = int(newLeaderNum)

            printd("Replica " + str(self.idnum) +
                   " accepts leader number {}".format(newLeaderNum))
            msg = "{}:{},{},{},{},{}".format(MessageType.YOU_ARE_LEADER.value,
                                             self.selected_leaderNum,
                                             self.idnum, self.accepted_req_id,
                                             self.accepted_seqNum,
                                             self.accepted_lastVal)
        else:
            msg = "{}:{},{}".format(MessageType.NACK.value,
                                    self.selected_leaderNum, self.idnum)
            printd("Not a high enough leader id {} because our current id {}.".
                   format(newLeaderNum, self.selected_leaderNum))

        Messenger.send_message(socket, msg)
Ejemplo n.º 15
0
    def send_iamleader_message(self):
        self.follower_collection = []
        # need to add its own acceptor to collection
        self.followers = set()
        self.followers.add(self.idnum)  # Let's include ourselves
        self.am_leader = False
        if self.acceptor.selected_leaderNum > self.leaderNum:
            self.leaderNum = self.acceptor.leaderNum
            self.value = self.acceptor.accepted_lastVal
        else:
            self.acceptor.selected_leaderNum = self.leaderNum

        printd("Sending message with leader value " + str(self.leaderNum))
        full_msg = str(MessageType.I_AM_LEADER.value) + ":" + str(
            self.leaderNum)
        if self.socket_connections_list:
            Messenger.broadcast_message(self.socket_connections_list, full_msg)
        else:
            raise RuntimeError(
                "Socket connections list has not been initialized for the proposer"
            )
Ejemplo n.º 16
0
	def try_to_execute_commands (self):
		if not self.commands_to_execute.empty() and self.last_executed_seq_number + 1 < int(self.commands_to_execute.queue[0][0]):
			printd("Replica {} sending catchup because it's missing {}.".format(self.idnum, self.last_executed_seq_number + 1).upper())
			(seq_number_found, missing_req_id, missing_value) = self.acceptor.get_value_at_seq_number(self.last_executed_seq_number + 1)
			self.fill_missing_value(seq_number_found, self.idnum, missing_req_id, self.last_executed_seq_number + 1, missing_value)
			if self.proposer:
				self.proposer.note_missing_value(seq_number_found, self.idnum, self.last_executed_seq_number + 1
				)
			else:
				printd("NO PROPOSER FOR " + str(self.idnum))

			msg = "{}:{}".format(MessageType.CATCHUP.value, self.last_executed_seq_number + 1)
			Messenger.broadcast_message (self.connections_list, msg)

			# keep track of how many times you request catchup. After so many, timeout
			if self.last_executed_seq_number + 1 in self.catchup_requests_count:
				self.catchup_requests_count[self.last_executed_seq_number + 1] += 1
			else:
				self.catchup_requests_count[self.last_executed_seq_number + 1] = 1
			printd("CATCHUP ATTEMPT COUNT: {}".format(self.catchup_requests_count[self.last_executed_seq_number + 1]))
			return

		# Convoluted way to peek at PriorityQueue
		while not self.commands_to_execute.empty() and int(self.commands_to_execute.queue[0][0]) == self.last_executed_seq_number + 1:
			command = self.commands_to_execute.get()
			self.execute_command(command)
Ejemplo n.º 17
0
    def recv_message (self):

        while 1:
            rd, wd, ed = select.select(self.connection_sockets, [], [], self.client_timeout)

            if len(rd) == 0: # Haven't received a message in a while...
                printd("Client {} timed-out and is resending {}." .format(self.client_name, self.msg))
                Messenger.broadcast_message(self.connection_sockets, self.msg)

            # Handle received messages
            for s in rd:

                message = Messenger.recv_message(s)

                if int(message.split('-')[1]) < int(self.client_seq_number): # Only should accept one message back
                    pass
                elif message is not '':
                    self.client_seq_number += 1 # move on to next client sequence number and next command
                    self.msg = None
                    return message
                else: # We got a socket disconnection from one of our replicas which means its kaputs for good...
                    self.connection_sockets.remove(s)
Ejemplo n.º 18
0
 def send_value_at_seq_number(self, socket, missing_seq_number):
     missing_seq_number = int(missing_seq_number)
     if missing_seq_number in self.seq_dict.keys():
         printd(
             "Replica {}'s acceptor is sending value {} for sequence number {}."
             .format(self.idnum, self.seq_dict[missing_seq_number],
                     missing_seq_number))
         seq_number_found = "True"
         missing_req_id = self.seq_dict[missing_seq_number][0]
         missing_value = self.seq_dict[missing_seq_number][1]
     else:
         printd("Replica {}'s acceptor is also behind sequence number {}.".
                format(self.idnum, missing_seq_number))
         seq_number_found = "False"
         missing_req_id = "NONE"
         missing_value = ''
     msg = "{}:{},{},{},{},{}".format(MessageType.MISSING_VALUE.value,
                                      seq_number_found, self.idnum,
                                      missing_req_id, missing_seq_number,
                                      missing_value)
     #Messenger.broadcast_message(self.connections_list, msg)
     Messenger.send_message(socket, msg)
     self.locked_seq_nums.add(int(missing_seq_number))
Ejemplo n.º 19
0
	def fill_missing_value (self, seq_number_found, acceptor_id, missing_req_id, missing_seq_number, missing_value):
		#if missing_seq_number in self.missing_vals_of_learners: # if we have not already resolved this issue
		missing_seq_number = int(missing_seq_number)
		if missing_req_id not in self.prev_leader_nums[missing_seq_number]:
			self.prev_leader_nums[missing_seq_number][missing_req_id] = set()

		self.prev_leader_nums[missing_seq_number][missing_req_id].add(acceptor_id)
		printd("{} IN MISSING VALUE, NUM UNIQUE REQ_IDS = {}".format(self.idnum,len(self.prev_leader_nums[missing_seq_number])))

		if missing_seq_number in self.prev_leader_nums:

					# do not need to iterate through req_ids. In this call, only the current req_id could have attained majority
			#for i in range(len(self.prev_leader_nums[missing_seq_number])): # iterate through each unique req_id
			#	if i not in self.prev_leader_nums[missing_seq_number]:
			#		continue
			sum_of_votes = 0
			for i in self.prev_leader_nums[missing_seq_number].values():
				sum_of_votes += len(i)
			printd("{} has {} votes for req_id: {} at seq_num: {} (total num votes = {})".format(self.idnum,len(self.prev_leader_nums[missing_seq_number][missing_req_id]),missing_req_id,missing_seq_number,sum_of_votes))
			if len(self.prev_leader_nums[missing_seq_number][missing_req_id]) == self.majority_numb: # if this seq_num, req_id combo has majority
				value = missing_value #max(self.prev_leader_nums[missing_seq_number], key=itemgetter(0))[1]
				del self.prev_leader_nums[missing_seq_number]

				if missing_seq_number > self.last_executed_seq_number and self.commands_to_execute.queue and missing_seq_number < int(self.commands_to_execute.queue[0][0]): # ignore previous messages
					#self.chat_log[missing_seq_number] = missing_value
					# DREW: why is this the case? The last executed command shouldn't change, right? #
					#self.last_executed_seq_number = missing_seq_number # + 1

					#del self.missing_vals_of_learners[missing_seq_number]
					printd("A different learner had the missing value. Fixing internal to the learners")
					if seq_number_found == "True":
						self.add_and_execute_seq_command(missing_seq_number, value, missing_req_id)
					else:
						self.add_and_execute_seq_command(missing_seq_number, "NOP5", "NOP")
						#print("Defaulted to NOP when seq_num = {}, val = {}, and req_id ={}".format(missing_seq_number, value, missing_req_id))
					#self.commands_to_execute.put((missing_seq_number, value, "NONE"))
					#self.try_to_execute_commands() # Now try to process commands again

			else: # need to check if majority impossible. If so, take NOP
				sum_of_votes = 0
				for i in self.prev_leader_nums[missing_seq_number].values():
					sum_of_votes += len(i)
					# if this is true, it is unable to achieve majority and all learners should execute NOP (catchup_requests_count acts as timeout)
					if sum_of_votes >= self.majority_numb and self.catchup_requests_count[missing_seq_number] > 20:
						#print("Catchup attempts: {}".format(self.catchup_requests_count[missing_seq_number]))
						self.add_and_execute_seq_command(missing_seq_number, "NOP6", "NOP")

			'''
Ejemplo n.º 20
0
    def note_missing_value(self, seq_number_found, learner_id,
                           missing_seq_number):

        printd("NOTE MISSING VALUE {}".format(missing_seq_number))
        missing_seq_number = int(missing_seq_number)
        learner_id = int(learner_id)

        self.missing_vals_of_learners[missing_seq_number].add(learner_id)

        if seq_number_found == "True":
            self.missing_vals_of_learners[missing_seq_number] = set()
            return
        elif seq_number_found == "False":
            printd(self.missing_vals_of_learners[missing_seq_number])
            if len(self.missing_vals_of_learners[missing_seq_number]
                   ) >= self.majority_numb:  # Count ourselves too
                self.acceptor.accept_value(
                    self.leaderNum, "NOP-SHOULD NOT HAPPEN",
                    missing_seq_number, "NOP-SHOULD NOT HAPPEN"
                )  # We should also accept a value locally
                if int(missing_seq_number) == self.seq_number + 1:
                    printd("INCREMENTING SEQ NUMBER IN PROPOSER")
                    self.seq_number += 1

                full_msg = str(
                    MessageType.COMMAND.value) + ":{},NOP,{},NOP1".format(
                        self.leaderNum, missing_seq_number)
                Messenger.broadcast_message(self.socket_connections_list,
                                            full_msg)
                self.missing_vals_of_learners[missing_seq_number] = set()
                printd("Leader num {} is proposing NOP at seq_num {}".format(
                    self.leaderNum, missing_seq_number))
        else:
            raise RuntimeError(
                "Error: invalid seq_number_found arg for MISSING_VALUE command"
            )
Ejemplo n.º 21
0
    def connect_to_replicas(self, replicas):
        i = 0
        printd(
            str(self.idnum) + " will connect to replicas: " + str(replicas) +
            "- len = " + str(len(replicas)))
        for replica in replicas:
            connected = False
            while not connected:
                try:
                    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    s.connect(
                        (replica[0], int(replica[1])))  # Connect to (ip, port)
                    connected = True
                except Exception as e:
                    time.sleep(0.1)  # yield thread

            printd(
                str(self.idnum) + " successfuly connected on (ip, port) " +
                str(replica))
            self.connections_list.append(s)

        printd(
            str(len(replicas)) + " connections set up for " + str(self.idnum))
Ejemplo n.º 22
0
                        '--replicas',
                        help='The pairs of all replicas already in the system')

    args = parser.parse_args()

    if args.mode == 'manual':
        man_mode = True
    else:  # default or automatic mode
        man_mode = False

    if args.number_messages:  # use config file
        num_messages = int(args.number_messages)
    else:  # default number of messages is 50
        num_messages = 50

    if args.replicas:
        config = Config(None, 1, args.replicas, None)
    else:
        raise RuntimeError("No replicas provided to the client")

    printd("Client server pairs:")
    printd(config.server_pairs)
    printd("client name: " + args.client_name)
    client1 = Client(config.server_pairs, args.client_name)
    client1.connect_to_all_replicas(
    )  # Connect to all replicas even if they don't have a proposer yet

    time.sleep(2)

    client1.operate(num_messages, man_mode)
Ejemplo n.º 23
0
    def newFollower(self, prev_leaderNum, acceptor_id, req_id, seq_number,
                    last_value):
        self.follower_collection.append(
            (int(prev_leaderNum), str(req_id), int(seq_number),
             str(last_value)))  # add follower info to collection
        if not self.am_leader and acceptor_id not in self.followers:  # if not leader

            self.followers.add(
                acceptor_id)  # We have another follower who's joined us

            if len(
                    self.followers
            ) == self.majority_numb:  # time to become leader since we have enough followers
                self.am_leader = True
                self.seq_number = int(seq_number)
                # do not repeat manual kills
                if int(seq_number) in self.kills:
                    self.kills.remove(int(seq_number))
                if int(seq_number) + 1 in self.kills:
                    self.kills.remove(int(seq_number) + 1)

                # need to decide most relavant last value.
                # find follower with highest prevLeaderNum. Break ties with seq_num, then val.
                max_last_follower = [-1, ".-.", -1, '']
                max_prevLeader = -1
                max_prevSeqNum = -1
                max_prevVal = ''
                for follower in self.follower_collection:
                    if follower[0] > max_last_follower[
                            0]:  # if prev_leaderNum > max_prevLeader
                        max_last_follower = follower
                        continue
                    if follower[0] == max_last_follower[
                            0] and follower[2] > max_last_follower[2]:
                        max_last_follower = follower
                        continue
                    if follower[0] == max_last_follower[0] and follower[
                            2] == max_last_follower[
                                2] and follower[3] > max_last_follower[3]:
                        max_last_follower = follower
                        continue
                # As first order of business as new leader, broadcast the most recent/relavant message you got back from accepts
                if (int(max_last_follower[0]) != -1
                        and int(max_last_follower[2]) != -1):

                    # do not repeat manual kills
                    self.seq_number = max_last_follower[2] - 1
                    if int(self.seq_number) in self.kills:
                        self.kills.remove(int(self.seq_number))
                    if int(self.seq_number) + 1 in self.kills:
                        self.kills.remove(int(self.seq_number + 1))
                    n_client_name = max_last_follower[1].split('-')[0]
                    n_client_seq_num = max_last_follower[1].split('-')[1]
                    n_val = max_last_follower[3]
                    self.acceptRequest(None, n_client_name, n_client_seq_num,
                                       n_val)

                    printd(
                        "Replica {} just became the leader with value = {}, sequence number = {}, req_id = {}"
                        .format(self.idnum, n_val, self.seq_number,
                                max_last_follower[1]))
                else:
                    printd(
                        "Replica {} just became the leader with default values"
                        .format(self.idnum))

        else:
            printd(str(self.idnum) + " was already the leader!")
Ejemplo n.º 24
0
 def send_message (self, value):
     self.msg = "{}:{},{},{}".format(MessageType.REQUEST.value, self.client_name, self.client_seq_number, value)
     Messenger.broadcast_message(self.connection_sockets, self.msg)
     #Messenger.send_message(self.connection_socket, full_msg)
     printd("Client {} sent message to all replicas with value {}".format(self.client_name,str(value)))
Ejemplo n.º 25
0
        description="Initialize a replica for paxos based chat service")
    parser.add_argument('-f',
                        '--tolerated_faults',
                        help='Total number of tolerated faults')
    parser.add_argument('-i', '--rep_id', help='Unique ID of this replica')
    parser.add_argument('-r',
                        '--replicas',
                        help='The pairs of all replicas already in the system')
    parser.add_argument('-t',
                        '--tests',
                        help="Message loss and other test cases to perform")

    args = parser.parse_args()

    if args.tolerated_faults:  # use config file
        printd("tolerated_faults = " + args.tolerated_faults)
        tolerated_faults = int(args.tolerated_faults)

    if args.rep_id:
        printd("rep_id = " + args.rep_id)
        rep_id = int(args.rep_id)

    if args.replicas:
        config = Config(None, tolerated_faults, args.replicas, args.tests)
        rep_ip = config.server_pairs[rep_id][0]
        rep_port = int(config.server_pairs[rep_id][1])
    else:  # if no replicas or given
        config = Config(None, tolerated_faults, None, args.tests)
        rep_ip = "127.0.0.1"
        rep_port = 4003
Ejemplo n.º 26
0
    def recv_message(self, origin_socket):
        if self.active:
            msg = Messenger.recv_message(origin_socket)
            printd("Message is " + str(msg))
            cmd, info = msg.split(":", 1)
            args = info.split(",")

            if cmd != MessageType.HEARTBEAT.value:
                printd("Replica: {} received cmd = {}, info={}".format(
                    self.idnum,
                    MessageType(cmd).name, info))
                if MessageType(
                        cmd
                ).name == "REQUEST" and self.proposer and self.proposer.am_leader:
                    printd("...and {} thinks its leader".format(self.idnum))

            if cmd == MessageType.REQUEST.value:
                # from: Client
                # to:   Proposer
                # args: client_name, client_seqnum, value
                # TODO: definite bug when there's multiple clients but for now we'll leave it
                if self.proposer:
                    self.proposer.acceptRequest(origin_socket, args[0],
                                                args[1], args[2])

                # printd("Received request message")

            elif cmd == MessageType.I_AM_LEADER.value:
                # from: Proposer
                # to:   Acceptor
                # args: leaderNum
                self.acceptor.acceptLeader(args[0], origin_socket)

            elif cmd == MessageType.YOU_ARE_LEADER.value:
                # from: Acceptor
                # to:   Proposer
                # args: prev_leaderNum, idnum, req_id, seq_number, current value
                #printd("Received You are Leader message")
                if not self.proposer:
                    raise RuntimeError(
                        "Non-proposer recieved YOU_ARE_LEADER msg")
                if self.proposer:
                    self.proposer.newFollower(args[0], args[1], args[2],
                                              args[3], args[4])

            elif cmd == MessageType.COMMAND.value:
                # acceptor should decide to accept leader command or not, then broadcast accept message to all learners
                # from: Proposer
                # to:   Acceptor
                # args: leaderNum, req_id, seqNum, value
                self.acceptor.accept_value(args[0], args[1], args[2], args[3])
                printd("Received command message to replica id " +
                       str(self.idnum) + " has leader num " +
                       str(int(self.acceptor.selected_leaderNum)))

            elif cmd == MessageType.ACCEPT.value:
                # Acceptor should now send message
                # from: Acceptor
                # to: Learner
                # info: leaderNum, idnum, req_id, sequence number, value
                #printd(str(self.idnum) + " sending accept message to learner with args " + str(args[0]) + " : " + str(args[1]))
                accepted = self.learner.acceptValue(
                    args[0], args[1], args[2], args[3],
                    args[4])  # True == majority achieved; False == no majority
                if self.proposer and self.proposer.am_leader and self.proposer.seq_number == int(
                        args[3]) and int(args[3]) + 1 in self.kills:
                    self.kill_next_round = True
                this_is_a_kill = (int(args[3])
                                  in self.kills) and self.kill_next_round
                if (
                        accepted == True and self.proposer
                        and self.proposer.am_leader
                        and (int(args[3]) in self.kills or
                             (int(args[3]) - 1 in self.skips))
                ):  #accepted == True and self.proposer and ( this_is_a_kill or (int(args[3])-1 in self.skips)) ):
                    # This is just a test of killing the primary again and again
                    if int(args[3]) in self.kills:
                        self.kills.remove(int(args[3]))
                        self.kill_next_round = False
                    if int(args[3]) - 1 in self.skips:
                        self.skips.remove(int(args[3]) - 1)
                    print("\nMANUALLY KILLING REPLICA " + str(self.idnum) +
                          ' at sequence number {}\n'.format(args[3]))
                    self.active = False

            elif cmd == MessageType.NACK.value:
                # from: Acceptor
                # to: Proposer
                # info: highest_leader_num, idnum
                self.proposer.set_leader_num(args[0], args[1])
            elif cmd == MessageType.CATCHUP.value:
                # from: Learner
                # to: Other learners
                # info: missing_seq_number
                self.acceptor.send_value_at_seq_number(origin_socket, args[0])
                #self.learner.send_value_at_seq_number(origin_socket, args[0])
            elif cmd == MessageType.MISSING_VALUE.value:
                # from: Other learners
                # to : Learner
                # info: seq_number_found, self.idnum, missing_req_id, missing_seq_number, missing_value
                self.learner.fill_missing_value(args[0], args[1], args[2],
                                                args[3], args[4])
                if self.proposer:
                    self.proposer.note_missing_value(args[0], args[1], args[3])

            elif cmd == MessageType.HEARTBEAT.value:  # Just a HEARTBEAT
                pass
            else:
                printd("The replica " + str(self.idnum) +
                       " did not recognize the message " + str(cmd))