def leave(self, pred_node, succ_node): # First update successor of our predecessor # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "UPDATE_SUCC|{0}|{1}|{2}".format( succ_node.hash, succ_node.host, succ_node.port) # the server at succ is contacted, response is the pred node of our # node response = client.attempt_to_connect( pred_node.host, pred_node.port, msg) # the server returned the predecessor if response == "": print("NO INSERT RESPONSE ERROR!") exit(0) # Next, update predecessor of our successor msg = "UPDATE_PRED|{0}|{1}|{2}".format( pred_node.hash, pred_node.host, pred_node.port) # the server at succ is contacted, response is the pred node of our # node response = client.attempt_to_connect( succ_node.host, succ_node.port, msg) # the server returned the successor if response == "": print("NO INSERT RESPONSE ERROR!") exit(0) # Okay return "OK"
def leave(self, pred_node, succ_node): # First update successor of our predecessor # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "UPDATE_SUCC|{0}|{1}|{2}".format(succ_node.hash, succ_node.host, succ_node.port) # the server at succ is contacted, response is the pred node of our # node response = client.attempt_to_connect(pred_node.host, pred_node.port, msg) # the server returned the predecessor if response == "": print("NO INSERT RESPONSE ERROR!") exit(0) # Next, update predecessor of our successor msg = "UPDATE_PRED|{0}|{1}|{2}".format(pred_node.hash, pred_node.host, pred_node.port) # the server at succ is contacted, response is the pred node of our # node response = client.attempt_to_connect(succ_node.host, succ_node.port, msg) # the server returned the successor if response == "": print("NO INSERT RESPONSE ERROR!") exit(0) # Okay return "OK"
def insert(self, hash_code, succ_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "INSERT|{0}|{1}|{2}".format(hash_code, self.host, self.port) # the server at succ is contacted, response is the pred node of our # node response = client.attempt_to_connect(succ_node.host, succ_node.port, msg) # the server returned the predecessor if response == "": print("NO INSERT RESPONSE ERROR!") exit(0) # the response should be a string of strings, separated by ':', but # there is no type checking, sorry # the response contained the pred node after the coord in the network # was complete pred_hash, pred_host, pred_port_str = response.split(':') # pred_port_str was sent as a string and now is converted to an int pred_port = int(pred_port_str) # we create a remote node for this pred pred_node = NetNode(pred_host, (int(pred_port))) # then we stop and return the remote node return pred_node
def insert(self, hash_code, succ_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "INSERT|{0}|{1}|{2}".format(hash_code, self.host, self.port) # the server at succ is contacted, response is the pred node of our # node response = client.attempt_to_connect( succ_node.host, succ_node.port, msg) # the server returned the predecessor if response == "": print("NO INSERT RESPONSE ERROR!") exit(0) # the response should be a string of strings, separated by ':', but # there is no type checking, sorry # the response contained the pred node after the coord in the network # was complete pred_hash, pred_host, pred_port_str = response.split(':') # pred_port_str was sent as a string and now is converted to an int pred_port = int(pred_port_str) # we create a remote node for this pred pred_node = NetNode(pred_host, (int(pred_port))) # then we stop and return the remote node return pred_node
def read(self, key, succ_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "READ_DATA" + "|" + key + "|" + self.host + "|" + str(self.port) # the server at succ is contacted, response is the okay response = client.attempt_to_connect(succ_node.host, succ_node.port, msg) # the server returned the predecessor if response == "": return ("NO READ RESPONSE ERROR!") if response == " ": return None return response
def read(self, key, succ_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "READ_DATA|{0}|{1}|{2}".format(key, self.host, self.port) # the server at succ is contacted, response is the okay response = client.attempt_to_connect(succ_node.host, succ_node.port, msg) # the server returned the predecessor if response == "": return ("NO READ RESPONSE ERROR!") if response == " ": return None return response
def write(self, key, value, succ_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "WRITE_DATA|{0}|{1}|{2}|{3}".format( key, value, self.host, self.port) # the server at succ is contacted, response is the okay response = client.attempt_to_connect( succ_node.host, succ_node.port, msg) # the server returned the predecessor if response == "": return ("NO READ RESPONSE ERROR!") if response == "OK": return True return False
def write(self, key, value, succ_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the insert request is like lookup msg = "WRITE_DATA" + "|" + key + "|" + value + "|" + self.host + "|" + str( self.port) # the server at succ is contacted, response is the okay response = client.attempt_to_connect(succ_node.host, succ_node.port, msg) # the server returned the predecessor if response == "": return ("NO READ RESPONSE ERROR!") if response == "OK": return True return False
def lookup(self, hash_code, net_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the lookup request is always the same msg = "LOOKUP|{0}|{1}|{2}".format(hash_code, self.host, self.port) succ_node = NetNode("None", 0) # since this implementation of lookup is iterative, so we need to keep # track of the nodes we've queried the last hash inits as the code we # are looking for, but is updated as the last node we checked last_hash = hash_code # our successor's hash inits as the entry node of the lookup succ_hash = net_node.hash succ_host = net_node.host succ_port = net_node.port # if the pred and succ hashes ever are equal, it means that the node we # are going to check next is the same node as the one we just checked, # which means we are done searching while not (last_hash == succ_hash): # the server at succ is contacted, response is the succ node to the # hash response = client.attempt_to_connect(succ_host, succ_port, msg) # print ("Lookup:" + response) # since we just checked succ, we can copy that info to last_hash last_hash = succ_hash # the response should be a few strings, separated by ':', but there # is no type checking, sorry if not response == "": # the response contained the next node to check, so it is # assigned to the current successor succ_hash, succ_host, succ_port_str = response.split(':') # succ_port_str was sent as a string and now is converted to an # int succ_port = int(succ_port_str) else: return ("NO LOOKUP RESPONSE ERROR!") # we create a remote node for this succ succ_node = NetNode(succ_host, (int(succ_port))) # the server returned self or its succ, if it returned self, then we # will exit the loop and return return succ_node
def lookup(self, hash_code, net_node): # create a client for this operation client = Simple_Client(self.host, self.port) # the lookup request is always the same msg = "LOOKUP|{0}|{1}|{2}".format(hash_code, self.host, self.port) succ_node = NetNode("None", 0) # since this implementation of lookup is iterative, so we need to keep # track of the nodes we've queried the last hash inits as the code we # are looking for, but is updated as the last node we checked last_hash = hash_code # our successor's hash inits as the entry node of the lookup succ_hash = net_node.hash succ_host = net_node.host succ_port = net_node.port # if the pred and succ hashes ever are equal, it means that the node we # are going to check next is the same node as the one we just checked, # which means we are done searching while not (last_hash == succ_hash): # the server at succ is contacted, response is the succ node to the # hash response = client.attempt_to_connect(succ_host, succ_port, msg) # print ("Lookup:" + response) # since we just checked succ, we can copy that info to last_hash last_hash = succ_hash # the response should be a few strings, separated by ':', but there # is no type checking, sorry if not response == "": # the response contained the next node to check, so it is # assigned to the current successor succ_hash, succ_host, succ_port_str = response.split(':') # succ_port_str was sent as a string and now is converted to an # int succ_port = int(succ_port_str) else: return("NO LOOKUP RESPONSE ERROR!") # we create a remote node for this succ succ_node = NetNode(succ_host, (int(succ_port))) # the server returned self or its succ, if it returned self, then we # will exit the loop and return return succ_node
def performAction(self, msg): m = msg.split('|') if (m[0] == "FIND_PEER"): #return this nodes info, easily done return self.host + ":" + str(self.port) if (m[0] == "LOOKUP"): #lookup() code = m[1] #hash_code being sent as a lookup host = m[2] #host of the requester port = int(m[3]) #port of the requester mine = self.head.node.hash #my hashed ID succ = self.head.router.succ.hash # my succ's hashed ID pred = self.head.router.pred.hash # my pred's hashed ID # 4 ways that the lookup returns my node (SELF RESPONSES INDICATE Completion) # 1: if pred = mine = succ: (one node network) if (pred == mine) and (mine == succ): #send succ(hash_code) = mine ID back to client return (mine + ":" + self.host + ":" + str(self.port)) # 2: if pred < hash_code and hash_code <= self and pred < self: # (no boundary check, if my node is the last, but not the first) if (pred < code) and (code <= mine) and (pred < mine): #send succ(hash_code) = mine ID back to client return (mine + ":" + self.host + ":" + str(self.port)) # 3: if pred < hash_code and hash_code > self and pred > self: # (pred is last node before flip, id first after, hash is before the flip) if (pred < code) and (code > mine) and (pred > mine): #send succ(hash_code) = mine ID back to client return (mine + ":" + self.host + ":" + str(self.port)) # 4: if pred > hash_code and hash_code <= self and pred > self: # (pred is last node before flip, id first after, hash is after the flip) if (pred > code) and (code <= mine) and (pred > mine): #send succ(hash_code) = mine ID back to client return (mine + ":" + self.host + ":" + str(self.port)) # ALL OTHER CASES Return the successor (which implicitly indicates non completion) # Alternate implementations could have server call lookup on successor (recursive) # But this implementation returns the succ for the client to do next lookup (iterative) return (succ + ":" + self.head.router.succ.host + ":" + str(self.head.router.succ.port)) if (m[0] == "INSERT"): #insert() code = m[1] #hash_code being sent in insert host = m[2] #host of the requester port = int(m[3]) #port of the requester # we need to save the old pred info in case we overwrite the object old_pred_code = self.head.router.pred.hash old_pred_host = self.head.router.pred.host old_pred_port = self.head.router.pred.port #creating the new predecessor object from the message new_pred = NetNode(host, port) #if this is a new network, set all to the new node, return self info if ((old_pred_code == self.head.node.hash) and (self.head.router.succ.hash == self.head.node.hash)): self.head.router.setPred(new_pred) self.head.router.setSucc(new_pred) self.head.router.setEntry(new_pred) return (old_pred_code + ":" + old_pred_host + ":" + str(old_pred_port)) #INSERT is the 1st of 3 messages, the 2nd is sent to the pred # we need a temp client for that temp_client = Simple_Client(self.host, self.port) # craft a message for the old_pred server to update its successor to the new pred msg = "UPDATE_SUCC" + "|" + code + "|" + host + "|" + str(port) # connect to the current predecessor to update pointer to succ response = temp_client.attempt_to_connect(old_pred_host, old_pred_port, msg) # if the response was "UPDATED_SUCC_OK" then we set the new_pred and return the old one if (response == "UPDATED_SUCC_OK"): # update the new predecessor self.head.router.setPred(new_pred) # return info on the old predecessor return (old_pred_code + ":" + old_pred_host + ":" + str(old_pred_port)) #else: return "" if (m[0] == "UPDATE_SUCC"): #update_succ() code = m[ 1] #hash_code being sent in update_succ is that of the new succ host = m[2] #host of the new succ port = int(m[3]) #port of the new succ #creating the new successor object from the message new_succ = NetNode(host, port) #updating the app_support node self.head.router.setSucc(new_succ) #no error checking yet return "UPDATED_SUCC_OK" if (m[0] == "WRITE_DATA"): #write() key = m[1] #hash_code being sent in write value = m[2] host = m[3] #host of the requester port = int(m[4]) #port of the requester self.head.data.write(key, value) return "OK" #Implement these handlers if (m[0] == "READ_DATA"): key = m[1] return self.head.data.read(key) #not using this, just write("0") if (m[0] == "DELETE_DATA"): return self.host + str(self.port) + " Reading Data..." return "CMD NOT FOUND"
def performAction(self, msg): m = msg.split('|') if (m[0] == "FIND_PEER"): # return this nodes info, easily done return self.host + ":" + str(self.port) if (m[0] == "LOOKUP"): # lookup() code = m[1] # hash_code being sent as a lookup host = m[2] # host of the requester port = int(m[3]) # port of the requester mine = self.head.node.hash # my hashed ID succ = self.head.router.succ.hash # my succ's hashed ID pred = self.head.router.pred.hash # my pred's hashed ID # 4 ways that the lookup returns my node (SELF RESPONSES INDICATE Completion) # 1: if pred = mine = succ: (one node network) if (pred == mine) and (mine == succ): # send succ(hash_code) = mine ID back to client return "{0}:{1}:{2}".format(mine, self.host, str(self.port)) # 2: if pred < hash_code and hash_code <= self and pred < self: # (no boundary check, if my node is the last, but not the first) if (pred < code) and (code <= mine) and (pred < mine): # send succ(hash_code) = mine ID back to client return "{0}:{1}:{2}".format(mine, self.host, str(self.port)) # 3: if pred < hash_code and hash_code > self and pred > self: # (pred is last node before flip, id first after, hash is before the flip) if (pred < code) and (code > mine) and (pred > mine): # send succ(hash_code) = mine ID back to client return "{0}:{1}:{2}".format(mine, self.host, str(self.port)) # 4: if pred > hash_code and hash_code <= self and pred > self: # (pred is last node before flip, id first after, hash is after the flip) if (pred > code) and (code <= mine) and (pred > mine): # send succ(hash_code) = mine ID back to client return "{0}:{1}:{2}".format(mine, self.host, str(self.port)) # ALL OTHER CASES Return the successor (which implicitly indicates non completion) # Alternate implementations could have server call lookup on successor (recursive) # But this implementation returns the succ for the client to do # next lookup (iterative) return "{0}:{1}:{2}".format(succ, self.head.router.succ.host, str(self.head.router.succ.port)) if (m[0] == "INSERT"): # insert() new_pred_code = m[1] # hash_code being sent in insert new_pred_host = m[2] # host of the requester new_pred_port = int(m[3]) # port of the requester # we need to save the old pred info in case we overwrite the object old_pred_code = self.head.router.pred.hash old_pred_host = self.head.router.pred.host old_pred_port = self.head.router.pred.port # creating the new predecessor object from the message new_pred = NetNode(new_pred_host, new_pred_port) # if this is a new network, set all to the new node, return self # info if ((old_pred_code == self.head.node.hash) and (self.head.router.succ.hash == self.head.node.hash)): self.head.router.setPred(new_pred) self.head.router.setSucc(new_pred) self.head.router.setEntry(new_pred) return "{0}:{1}:{2}".format(old_pred_code, old_pred_host, str(old_pred_port)) # INSERT is the 1st of 3 messages, the 2nd is sent to the pred # we need a temp client for that temp_client = Simple_Client(self.host, self.port) # craft a message for the old_pred server to update its successor # to the new pred msg = "UPDATE_SUCC" + "|" + new_pred_code + \ "|" + new_pred_host + "|" + str(new_pred_port) # connect to the current predecessor to update pointer to succ response = temp_client.attempt_to_connect( old_pred_host, old_pred_port, msg) # if the response was "UPDATED_SUCC_OK" then we set the new_pred # and return the old one if(response == "UPDATED_SUCC_OK"): # update the new predecessor self.head.router.setPred(new_pred) # return info on the old predecessor return "{0}:{1}:{2}".format(old_pred_code, old_pred_host, str(old_pred_port)) # else: return "" if (m[0] == "UPDATE_PRED"): # update_succ() # hash_code being sent in update_pred is that of the new pred code = m[1] host = m[2] # host of the new pred port = int(m[3]) # port of the new pred # creating the new successor object from the message new_pred = NetNode(host, port) # updating the app_support node self.head.router.setPred(new_pred) # no error checking yet return "UPDATED_PRED_OK" if (m[0] == "UPDATE_SUCC"): # update_succ() # hash_code being sent in update_succ is that of the new succ code = m[1] host = m[2] # host of the new succ port = int(m[3]) # port of the new succ # creating the new successor object from the message new_succ = NetNode(host, port) # updating the app_support node self.head.router.setSucc(new_succ) # no error checking yet return "UPDATED_SUCC_OK" if (m[0] == "WRITE_DATA"): # write() key = m[1] # hash_code being sent in write value = m[2] host = m[3] # host of the requester port = int(m[4]) # port of the requester self.head.data.write(key, value) return "OK" # Implement these handlers if (m[0] == "READ_DATA"): key = m[1] return self.head.data.read(key) # not using this, just write("0") if (m[0] == "DELETE_DATA"): return "{0}{1} Reading Data...".format(self.host, str(self.port)) return "CMD NOT FOUND"