def dispatch_insert(source, req_code, req_type, data): #data = {'key': key, 'value': value, resp_ip_port:"None" , 'index': 0} key = data['key'] value = data['value'] index = data['index'] resp_ip_port = data['resp_ip_port'] if is_responsible(key): resp_ip_port = node.ip_port text = node.insert(key, value, index) #check if last --> if so respond to source and return if index == int( node.get_replicas()) - 1 or node.succ_ip_port == resp_ip_port: resp_text = text + " at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) #its important to return here return else: #if type == eventual respond to source if node.get_rep_type() == "eventual": resp_text = text + " at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) #now forward request to next node new_req = make_same_req( source, req_type, { 'key': key, 'value': value, 'resp_ip_port': resp_ip_port, 'index': index + 1 }, req_code) post_req_thread(node.succ_ip_port, new_req) elif index == 0: #request hasnt reached responsible yet--> just forward it to next new_req = make_same_req(source, req_type, data, req_code) post_req_thread(node.succ_ip_port, new_req) else: text = node.insert(key, value, index) # if last_node dont forward , also if linear.. respond to source if index == node.get_replicas( ) - 1 or node.succ_ip_port == resp_ip_port: if node.get_rep_type() == "linearizability": resp_text = text + " at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) else: #if not last node --> forward changed req to succ new_req = make_same_req( source, req_type, { 'key': key, 'value': value, 'resp_ip_port': resp_ip_port, 'index': index + 1 }, req_code) post_req_thread(node.succ_ip_port, new_req) return
def ntwresp(): global number_of_nodes resp_dict = json.loads(request.data) if resp_dict['type'] == 'set_neighboors': prev_ip_port = resp_dict['prev'] succ_ip_port = resp_dict['succ'] node.set_neighboors(prev_ip_port, succ_ip_port) elif resp_dict['type'] == 'join_vars': repn = resp_dict['data']['repn'] rep_type = resp_dict['data']['rep_type'] node.join_set_vars(repn, rep_type) elif resp_dict['type'] == 'K_nodes': if (node.get_replicas() == number_of_nodes): return {'K_nodes': 'True'} else: return {'K_nodes': 'False'} elif (resp_dict['type'] == 'inc_number'): number_of_nodes += 1 elif (resp_dict['type'] == 'dec_number'): number_of_nodes -= 1 elif (resp_dict['type'] == 'nodes_in_chord'): return {'nodes_in_chord': number_of_nodes} else: seqn = resp_dict['seqn'] responses_dict[seqn] = resp_dict return {}
def join(): # its important to stall join request so that our server has started properly and then we can get the boot server response global seqn seqn = seqn + 1 req_code = str(seqn) # 1) kane join to node sto chord kai ftiakse tous pointers tou kai twn geitonwn tou kai dwstou kai ta kleidia tou epomenou same keys new_keys # 2) gia tous epomenous k nodes ektelese new ntw_req --> ( source, type="join_upd_chain" , req_code, data { index:0 , same_keys, new_keys } ) # 3) pare ta keys_vals tou prevs stis theseis 0 ews k-1 kai valta stis dikes sou 1 ews k-1 # 4) respond to user data = {'key': node.id} req = make_req('join', data, req_code) post_req_thread(node.boot_ip_port, req) while responses_dict.get(req_code, "None") == "None": {} # pop response from dict and handle it resp = responses_dict.pop(req_code) # apo to response pairnw ta same_keys, new_keys, kai ftiaxnw kai tous geitones mou same_keys = resp['data']['same_keys'] new_keys = resp['data']['new_keys'] node.prev_ip_port = resp['data']['prev'] node.succ_ip_port = resp['data']['succ'] # ta new_keys einai ta keys gia ta opoia twra tha eisai responsible node.keys_vals[0] = new_keys data = {'index': 0, 'same_keys': same_keys, 'new_keys': new_keys} req = make_req('join_upd_chain', data, req_code) # post request to next node so that all chain of replicas updates post_req_thread(node.succ_ip_port, req) while responses_dict.get(req_code, "None") == "None": {} responses_dict.pop(req_code) # get_keys request from prev req = make_req('get_keys', {}, req_code) post_req_thread(node.prev_ip_port, req) while responses_dict.get(req_code, "None") == "None": {} resp = responses_dict.pop(req_code) prev_keys = resp['data']['keys'] post_resp_to(node.boot_ip_port, {'type': 'inc_number'}) # vale ta keys 0--k-2 tou prev sta dika sou 1--k-1 # if nodes_in_chord < k then go till nodes_in_chord -1 element nodes_in_chord = requests.post("http://" + node.boot_ip_port + "/ntwresp", json={'type': 'nodes_in_chord'}) nodes_in_chord = json.loads(nodes_in_chord.text)['nodes_in_chord'] limit = min(nodes_in_chord, node.get_replicas()) for i in range(limit - 1): node.keys_vals[i + 1] = prev_keys[i] msg = ("Node joined succesfully") return msg
def dispatch_depart(source, req_code, req_type, data): #update data --> first node has to add his keys[0] to new_keys , every node has to put his last keys to last_keys #if node isnt last forward next #else respond to source index = data['index'] new_keys = data['new_keys'] last_keys = data['last_keys'] K_nodes = data['K_nodes'] if (index == 0): new_keys.update(node.keys_vals[index]) node.keys_vals[index] = new_keys if (index + 1 < node.get_replicas() - 1): node.pushup(index + 1) if (index + 1 <= node.get_replicas() - 1): #if there are K nodes then we should put {} to last keys else do what we do if (K_nodes == 'True'): node.keys_vals[node.get_replicas() - 1] = {} else: node.keys_vals[node.get_replicas() - 1] = last_keys #check if last_node if (index == node.get_replicas() - 1 or node.succ_ip_port == source): resp = make_resp(source, req_type, {}, req_code) post_resp_thread(source, resp) else: new_data = { 'index': index + 1, 'new_keys': new_keys, 'last_keys': node.keys_vals[node.get_replicas() - 2], 'K_nodes': K_nodes } req = make_same_req(source, req_type, new_data, req_code) post_req_thread(node.succ_ip_port, req) return
def dispatch_join(source, req_code, req_type, data): #if this node is prev ( this.succ== is_responsible ) update its next to source put its ip to prev datum and forward request to next #if this node is_resp === is next update its prev to source put its ip to succ datum and get same_keys , new_keys and respond to source #if nothing of the above just forward to next node #### THIS IS ONLY FOR BOOTSTRAP NODE --> IT SENDS THE NODE THAT JOINS REPN AND REP_TYPE INFORMATION#### resp = make_resp(source, 'join_vars', { 'repn': node.get_replicas(), 'rep_type': node.get_rep_type() }, req_code) post_resp_to(source, resp) ####################################################################################################### if (is_responsible(data['key'])): ######only for bootstrap cause he is the first to receive join req ######if he is responsible its the only case when we dont pass from the prev ######so we must set the data['prev']=node.prev_ip_port ###### and also send request to prev to update its succ to the source data['prev'] = node.prev_ip_port post_resp_to(node.prev_ip_port, { 'type': 'set_neighboors', 'prev': "None", 'succ': source }) ###### data['succ'] = node.ip_port same_new = node.get_same_new_keys(data['key']) data['same_keys'] = same_new[0] data['new_keys'] = same_new[1] if (node.is_alone()): # special case --> here we are previous also so we must fix those values too node.succ_ip_port = source node.prev_ip_port = source data['prev'] = node.ip_port #respond to source node.prev_ip_port = source resp = make_resp(source, req_type, data, req_code) post_resp_thread(source, resp) elif (succ_is_responsible(data['key'])): temp = node.succ_ip_port node.succ_ip_port = source data['prev'] = node.ip_port req = make_same_req(source, req_type, data, req_code) post_req_thread(temp, req) else: req = make_same_req(source, req_type, data, req_code) post_req_thread(node.succ_ip_port, req) return
def dispatch_join_upd_chain(source, req_code, req_type, data): #exei ginei idi to join tou komvou kai exoun enimerwthei oloi oi pointers same_keys = data['same_keys'] new_keys = data['new_keys'] index = data['index'] # update data node.keys_vals[index] = same_keys if (index + 2 < node.get_replicas()): node.pushdown(index + 2) if (index + 1 < node.get_replicas()): node.keys_vals[index + 1] = new_keys # if not last node forward next if (index != node.get_replicas() - 1 and node.succ_ip_port != source): req = make_same_req(source, req_type, { 'index': index + 1, 'same_keys': same_keys, 'new_keys': new_keys }, req_code) post_req_thread(node.succ_ip_port, req) else: #make response forward source resp = make_resp(source, req_type, {}, req_code) post_resp_thread(source, resp) return
def dispatch_query(source, req_code, req_type, data): #data = {'key': key, 'value': "None", "resp_ip_port": "None", 'index': 0} key = data['key'] value = data['value'] resp_ip_port = data['resp_ip_port'] index = data['index'] # for eventual consistency, if not found once we dont search for key again until it reaches resp, there is no point #make this an array of one element so i can change it later failed_to_find = data['failed_to_find'] k = node.get_replicas() if is_responsible(key): resp_ip_port = node.ip_port value = node.query(key) if node.get_rep_type() == "eventual": if value != "None": resp_text = "has value:" + value + " found at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) return #if node isnt last forward request if index != k - 1 and node.succ_ip_port != resp_ip_port: req = make_same_req( source, req_type, { 'key': key, 'value': value, 'resp_ip_port': resp_ip_port, 'index': index + 1, 'failed_to_find': failed_to_find }, req_code) post_req_thread(node.succ_ip_port, req) else: #is last node respond to source if value == "None": resp_text = "not found at node " + node.ip_port else: resp_text = "has value:" + value + " found at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) else: #isnt responsible if index == 0: #hasnt reached resposible yet if node.get_rep_type() == "eventual": if not failed_to_find[0]: #this query should be executed only once! value = node.query(key) if (value != "None"): resp_text = "has value:" + value + " found at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) return else: failed_to_find[0] = True req = make_same_req( source, req_type, { 'key': key, 'value': value, 'resp_ip_port': resp_ip_port, 'index': index, 'failed_to_find': failed_to_find }, req_code) post_req_thread(node.succ_ip_port, req) else: #it has reached responsible new_val = node.query(key) if new_val != "None": value = new_val if node.get_rep_type() == "eventual": resp_text = "has value:" + value + " found at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) return if index != k - 1 and node.succ_ip_port != resp_ip_port: #its not last node-->forward request req = make_same_req( source, req_type, { 'key': key, 'value': value, 'resp_ip_port': resp_ip_port, 'index': index + 1, 'failed_to_find': failed_to_find }, req_code) post_req_thread(node.succ_ip_port, req) else: #its last node respond to source if value == "None": resp_text = "not found at node " + node.ip_port else: resp_text = "has value:" + value + " found at node:" + node.ip_port resp = make_resp(source, req_type, {'resp_text': resp_text}, req_code) post_resp_thread(source, resp) return
def depart(): if request.method == 'POST': if not node.get_isInChord(): return 'This node does not participate in Chord!\n' else: # Στις επόμενες 4 γραμμές, μαζεύω τα data που θα στείλω στον successor global seqn seqn = seqn + 1 req_code = str(seqn) new_keys = node.keys_vals[0] last_keys = node.keys_vals[node.get_replicas() - 1] #send message to boot to find out K_nodes value boot_resp = requests.post("http://" + node.boot_ip_port + "/ntwresp", json={'type': 'K_nodes'}) K_nodes = json.loads(boot_resp.text)['K_nodes'] data = { 'index': 0, 'new_keys': new_keys, 'last_keys': last_keys, 'K_nodes': K_nodes } if node.is_alone(): node.init_state() return f"Node {node.ip_port} departed from the Chord!\n" else: #make depart request and post to next node--> it will update all the rm chain req = make_req('depart', data, req_code) post_req_thread(node.succ_ip_port, req) while responses_dict.get(req_code, "None") == "None": {} responses_dict.pop(req_code) # then take care of the neighbour pointers # data = {'prev': node.prev_ip_port, 'succ': node.succ_ip_port, 'type':'set_neighboors'} prev = node.prev_ip_port succ = node.succ_ip_port if node.is_duo(): # an exoume mono 2 nodes tote prepei na steiloume na enimerwsei kai ton next kai ton prev o enas mas geitonas #to parakatw tha perimenei mexri na lavoume apantisi post_resp_to(node.prev_ip_port, { 'prev': prev, 'succ': succ, 'type': 'set_neighboors' }) else: #an uparxoun toul 3 komvoi stelnoume kai ston prev kai ston next na enimerwsoun mono ton enan geitona tous ekastos post_resp_to(node.prev_ip_port, { 'prev': "None", 'succ': succ, 'type': 'set_neighboors' }) post_resp_to(node.succ_ip_port, { 'prev': prev, 'succ': "None", 'type': 'set_neighboors' }) # Then return the node to dafault state node.init_state() post_resp_to(node.boot_ip_port, {'type': 'dec_number'}) return f"Node {node.ip_port} successfully departed from Chord!\n"