def FindValue(self, request, context): node = request.node # node object (id, port, address) key = request.idkey # int print("Serving FindKey(" + str(key) + ") request for " + str(node.id)) # create self node to attach to findValue call self_node = csci4220_hw4_pb2.Node(id=self.my_id, port=self.my_port, address=self.my_address) # update the bucket so requesting is the most recent one b = self.my_id ^ node.id b = b.bit_length() - 1 self.UpdateBucket(b, Node(node.address, node.port, node.id)) # if self contains key if key in self.data: return csci4220_hw4_pb2.KV_Node_Wrapper(responding_node=self_node, mode_kv=True, kv=csci4220_hw4_pb2.KeyValue(node=self_node,key=key,value=self.data[key]), nodes=[]) # if self doesn't contain key, ask peers else: # create the nodes list to return nodes_list = [] for item in self.k_buckets.items(): for peer in item[1]: nodes_list.append(csci4220_hw4_pb2.Node(id=peer.node_id, port=peer.port, address=peer.address)) return csci4220_hw4_pb2.KV_Node_Wrapper(responding_node=self_node, mode_kv=False, kv=csci4220_hw4_pb2.KeyValue(node=self_node, key=key, value="None"), nodes=nodes_list)
def SendBootstrap(self, peer_host, peer_port): # temporarily connect with them to get with grpc.insecure_channel(peer_host + ":" + peer_port) as channel: # access the remote server stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) obj = csci4220_hw4_pb2.IDKey(node=csci4220_hw4_pb2.Node(id=self.my_id, port=int(self.my_port), address=self.my_address), idkey=self.my_id) # node contains the return from FindNode node = stub.FindNode(obj) # get the bucket it should be stored in bucket = self.my_id ^ node.responding_node.id bucket = bucket.bit_length() - 1 # create a new node from the responding node and append it n = Node(node.responding_node.address, node.responding_node.port, node.responding_node.id) self.UpdateBucket(bucket,n) # add all the nodes that were neighbors for i in node.nodes: b = self.my_id ^ i.id b = b.bit_length() - 1 if (b >= 0): self.UpdateBucket(b, Node(i.address, i.port, i.id)) print("After BOOTSTRAP(" + str(node.responding_node.id) + "), k_buckets now look like:") self.PrintBuckets()
def Store(self, request, context): node = request.node k = request.key v = request.value # received request, simply add it to the key value store print("Storing key " + str(k) + " value \"" + str(v) + "\"") self.data[k] = v # create the return object toReturn = csci4220_hw4_pb2.IDKey(node=csci4220_hw4_pb2.Node(id=self.my_id, port=self.my_port, address=self.my_address), idkey=self.my_id) # update the location of the sending store command bucket = self.my_id ^ node.id bucket = bucket.bit_length() - 1 found = False # check to make sure that peer exists for item in self.k_buckets[bucket]: if item.node_id == node.id: found = True # if found, update it if found == True: self.UpdateBucket(bucket, Node(node.address,node.port,node.id)) return toReturn
def SendFindValue(self, target_key): if target_key in self.data.keys(): print("Found data \""+ self.data[target_key]+ "\" for key " + str(target_key)) return obj = csci4220_hw4_pb2.IDKey(node=csci4220_hw4_pb2.Node(id=self.my_id, port=int(self.my_port), address=self.my_address), idkey=target_key) visited = [] visited.append(self.my_id) # for all peers to_sort = [] for item in self.k_buckets.items(): for peer in item[1]: to_sort.append(peer) # sort the peers based on distance to target_key to_sort.sort(key=lambda node: (target_key ^ node.node_id).bit_length() -1) # for all peers in order for peer in to_sort: with grpc.insecure_channel(peer.address + ":" + str(peer.port)) as channel: # send find value command stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) R = stub.FindValue(obj) visited.append(peer.node_id) b = peer.node_id ^ self.my_id b = b.bit_length() - 1 # update location of the peer self.UpdateBucket(b, peer) # if found if (R.mode_kv == True): print("Found value \"" + R.kv.value + "\" for key " + str(R.kv.key)) return else: for i in R.nodes: if i.id not in visited: b = self.my_id ^ i.id b = b.bit_length() - 1 self.UpdateBucket(b, Node(i.address, i.port, i.id)) # search through the returned k nearest peers with grpc.insecure_channel(i.address + ":" + str(i.port)) as to_ask: stub = csci4220_hw4_pb2_grpc.KadImplStub(to_ask) response = stub.FindValue(obj) visited.append(i.id) # if found in peer list if (response.mode_kv == True): print("Found value \"" + response.kv.value + "\" for key " + str(response.kv.key)) return # if haven't found at this point, print that it couldn't be found print("Could not find key " + str(target_key))
def run(): if len(sys.argv) != 4: print("Error, correct usage is {} [my id] [my port] [k]".format(sys.argv[0])) sys.exit(-1) local_id = int(sys.argv[1]) my_port = str(int(sys.argv[2])) # add_insecure_port() will want a string k = int(sys.argv[3]) my_hostname = socket.gethostname() # Gets my host name my_address = socket.gethostbyname(my_hostname) # Gets my IP address from my hostname # list of lists of Node objects, initially each list is empty. There are 4 lists hard coded because we # are using 4 bit integers, and therefore 4 k-buckets k_buckets = [[],[],[],[]] # a dictionary to hold the key value pairs we store locally dictionary = dict() meNode = csci4220_hw4_pb2.Node(id=local_id, port=int(my_port), address=my_address) # a new thread is created to handle listening for rpc calls so the UI thread and listening thread can run in parallel # thread must be a daemon thread to have it killed when the main thread ends on QUIT command t = threading.Thread(target=serve, args=(my_port, k_buckets, dictionary, meNode, k,), daemon = True) t.start() #serve(my_port, k_buckets, dictionary, meNode, k) # loop until QUIT command is received, call appropriate function for each other command while(True): command = input('').split() #bootstrap(remote_addr_string, remote_port_string, myId, meNode, k_buckets, k): if command[0] == "BOOTSTRAP": remote_addr_string = command[1] remote_port_string = command[2] bootstrap(remote_addr_string, remote_port_string, meNode.id, meNode, k_buckets, k) elif command[0] == "FIND_NODE": print("Before FIND_NODE command, k-buckets are:") printBuckets(k_buckets) findNode(int(command[1]), k_buckets, k, 4, meNode) elif command[0] == "FIND_VALUE": print("Before FIND_VALUE command, k-buckets are:") printBuckets(k_buckets) findValue(int(command[1]), k_buckets, k, 4, meNode, dictionary) print("After FIND_VALUE command, k-buckets are:") printBuckets(k_buckets) #store(key, value, k_buckets, k, meNode, storedDict) elif command[0] == "STORE": key = int(command[1]) value = command[2] store(key, value, k_buckets, k, meNode, dictionary) elif command[0] == "QUIT": quit(meNode.id, meNode, k_buckets) sys.exit() break
def Quit(self, request, context): global buckets quit_id = int(request.idkey) for i in range(4): for entry in buckets[i]: if int(entry.id) == quit_id: buckets[i].remove(entry) print("Evicting quitting node " + str(quit_id) + " from bucket " + str(i)) return csci4220_hw4_pb2.IDKey(node = csci4220_hw4_pb2.Node(id = int(sys.argv[1]), port = int(sys.argv[2]), address = "127.0.0.1"), idkey = int(sys.argv[1])) print("No record of quitting node " + str(quit_id) + " in k-buckets.") count = 0 for bucket in buckets: sys.stdout.write('{}:'.format(str(count))) for entry in bucket: sys.stdout.write(' {}:{}'.format(str(entry.id), str(entry.port))) sys.stdout.write('\n') count += 1 return csci4220_hw4_pb2.IDKey(node = csci4220_hw4_pb2.Node(id = int(sys.argv[1]), port = int(sys.argv[2]), address = "127.0.0.1"), idkey = int(sys.argv[1]))
def Store(self, request, context): global val global val_key print("storing something") val = request.value val_key = request.key return csci4220_hw4_pb2.IDKey(node = csci4220_hw4_pb2.Node(id = int(sys.argv[1]), port = int(sys.argv[2]), address = "127.0.0.1"), idkey = int(sys.argv[1]))
def FindNode(self, request, context): to_add = request.node request_id = request.idkey print("Serving FindNode("+str(to_add.id) + ") request for " + str(request_id)) # handle bootstrap call if (to_add.id == request_id): # get the bucket bucket = self.my_id ^ to_add.id bucket = bucket.bit_length() - 1 n = Node(to_add.address, to_add.port, to_add.id) self.UpdateBucket(bucket, n) responding = [] for item in self.k_buckets.items(): for peer in item[1]: responding.append(csci4220_hw4_pb2.Node(id=peer.node_id, port=peer.port, address=peer.address)) # create the node list toReturn = csci4220_hw4_pb2.NodeList(responding_node=csci4220_hw4_pb2.Node(id=self.my_id, port=self.my_port, address=self.my_address), nodes=responding) return toReturn else: responding = [] # for all buckets for item in self.k_buckets.items(): # for all peers for peer in item[1]: responding.append(csci4220_hw4_pb2.Node(id=peer.node_id, port=peer.port, address=peer.address)) # create the return object # using the array as the nodelist toReturn = csci4220_hw4_pb2.NodeList(responding_node=csci4220_hw4_pb2.Node(id=self.my_id, port=self.my_port, address=self.my_address), nodes= responding) return toReturn return toReturn
def FindNode(self, request, context): global buckets bit_len = ((int(request.node.id))^(int(sys.argv[1]))).bit_length() bit_len -= 1 print("bitlen is: " + str(bit_len)) if len(buckets[bit_len]) == int(sys.argv[3]): buckets[bit_len].popleft() buckets[bit_len].append(request.node) print('Serving FindNode({}) request for {}'.format(str(request.idkey), str(request.node.id))) id_in = request.idkey k = int(sys.argv[3]) count = 0 temp_list = deque([]) #look at all Nodes in bucket #and insert them into the temp list #in the order of their distance to the #requested ID for bucket in buckets: for entry in bucket: if entry.id == request.node.id: continue if count == 0: #first entry into the temp list temp_list.append(entry) count += 1 else: #make sure things are sorted if (int(entry.id)^int(request.idkey)) <= (int(temp_list[0].id)^int(request.idkey)): temp_list.appendleft(entry) count += 1 else: temp_list.append(entry) count += 1 this_node = csci4220_hw4_pb2.Node(id = int(sys.argv[1]), port = int(sys.argv[2]), address = "127.0.0.1") node_list = None if count <= k: node_list = temp_list else: node_list = temp_list[:(k - 1)] for bucket in buckets: sys.stdout.write('{}:'.format(str(count))) for entry in bucket: sys.stdout.write(' {}:{}'.format(str(entry.id), str(entry.port))) sys.stdout.write('\n') count += 1 return csci4220_hw4_pb2.NodeList(responding_node = this_node, nodes = node_list)
def FindValue(self, request, context): global buckets global val global val_key k = int(sys.argv[3]) this_node = csci4220_hw4_pb2.Node(id = int(sys.argv[1]), port = int(sys.argv[2]), address = "127.0.0.1") if val_key == request.idkey: print("value found with given key") return csci4220_hw4_pb2.KV_Node_Wrapper(responding_node = this_node, mode_kv = True, kv = csci4220_hw4_pb2.KeyValue(node = this_node, key = val_key, value = val), nodes = None) count = 0 temp_list = deque([]) #look at all Nodes in bucket #and insert them into the temp list #in the order of their distance to the #requested ID for bucket in buckets: for entry in bucket: if entry.id == request.node.id: continue if count == 0: #first entry into the temp list temp_list.append(entry) count += 1 else: #make sure things are sorted if (int(entry.id)^int(request.idkey)) <= (int(temp_list[0].id)^int(request.idkey)): temp_list.appendleft(entry) count += 1 else: temp_list.append(entry) count += 1 node_list = None if count <= k: node_list = temp_list else: node_list = temp_list[:(k - 1)] print("value not found, returned a list of closest nodes") return csci4220_hw4_pb2.KV_Node_Wrapper(responding_node = this_node, mode_kv = False, kv = None, nodes = node_list)
def SendQuit(self): obj = csci4220_hw4_pb2.IDKey(node=csci4220_hw4_pb2.Node(id=self.my_id, port=int(self.my_port), address=self.my_address), idkey=self.my_id) # for all peers for item in self.k_buckets.items(): for peer in item[1]: #send a quit to all pears with grpc.insecure_channel(peer.address + ":" + str(peer.port)) as channel: print("Letting "+ str(peer.node_id)+" know I'm quitting.") # send quit to them try: stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) ret = stub.Quit(obj) # if quit does not connect, do nothing # hacky way as of submitty 195 except: pass
def SendFindNode(self, target_id): obj = csci4220_hw4_pb2.IDKey(node=csci4220_hw4_pb2.Node(id=self.my_id, port=int(self.my_port), address=self.my_address), idkey=target_id) # keep track of visited visited = [] for item in self.k_buckets.items(): bucket = item[1] for index in range(len(bucket)): # if already visited if (bucket[index].node_id in visited): print("alerady visited") continue # send the peer the find node command with grpc.insecure_channel(bucket[index].address + ":" + str(bucket[index].port)) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) # make the request R = stub.FindNode(obj) # add this to visited visited.append(bucket[index].node_id) # update the position of this first node self.UpdateBucket(item[0],bucket[index]) # update k buckets with node (move it to the front) for i in R.nodes: b = self.my_id ^ i.id b = b.bit_length() - 1 # make sure not self if (b >= 0): found = False for match in bucket: if match.node_id == i.id: found = True # found it if (target_id == i.id): print("Found destination id " + str(target_id)) self.UpdateBucket(b, Node(i.address, i.port, i.id))
def run(): if len(sys.argv) != 4: print("Error, correct usage is {} [my id] [my port] [k]".format(sys.argv[0])) sys.exit(-1) local_id = int(sys.argv[1]) my_port = str(int(sys.argv[2])) # add_insecure_port() will want a string k = int(sys.argv[3]) my_hostname = socket.gethostname() # Gets my host name my_address = socket.gethostbyname(my_hostname) # Gets my IP address from my hostname ''' Use the following code to convert a hostname to an IP and start a channel Note that every stub needs a channel attached to it When you are done with a channel you should call .close() on the channel. Submitty may kill your program if you have too many file descriptors open at the same time.''' # start the server in the background hash_table = HashTable() hash_table.my_port = int(my_port) hash_table.my_id = local_id hash_table.my_address = my_address server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) csci4220_hw4_pb2_grpc.add_KadImplServicer_to_server(hash_table, server) server.add_insecure_port('[::]:'+my_port) server.start() # initializing the buckets 2^k buckets = pow(2, k) for i in range(buckets): hash_table.k_buckets[i] = [] # main listening loop while (True): stdin = str(input()) arguments = stdin.split(" ") # connect to another peer directly if (arguments[0] == "BOOTSTRAP"): peer_host = arguments[1] peer_port = arguments[2] hash_table.SendBootstrap(peer_host, peer_port) # if the command is to store a value at a key if (arguments[0] == "STORE"): key = int(arguments[1]) value = arguments[2] min_dist = key ^ hash_table.my_id min_key = Node(hash_table.my_address, hash_table.my_port, hash_table.my_id) # get the minimum distance peer to the key for item in hash_table.k_buckets.items(): for peer in item[1]: dist = key ^ peer.node_id if dist < min_dist: min_dist = dist min_key = peer print("Storing key " + str(key) + " at node " + str(min_key.node_id)) if (min_key.node_id == hash_table.my_id): hash_table.data[key] = value else: # send the store command to that remote with grpc.insecure_channel(min_key.address + ":" + str(min_key.port)) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) obj = csci4220_hw4_pb2.KeyValue(node=csci4220_hw4_pb2.Node(id=hash_table.my_id, port=int(hash_table.my_port), address=hash_table.my_address), key=key, value=value) id_key = stub.Store(obj) # command to find a node if (arguments[0] == "FIND_NODE"): target_id = int(arguments[1]) print("Before FIND_NODE command, k-buckets are:") hash_table.PrintBuckets() # perform searching and updating here hash_table.SendFindNode(target_id) print("After FIND_NODE command, k-buckets are:") hash_table.PrintBuckets() # command to find a value if (arguments[0] == "FIND_VALUE"): find_target = int(arguments[1]) print("Before FIND_VALUE command, k-buckets are:") hash_table.PrintBuckets() # perform search and updating here hash_table.SendFindValue(find_target) print("After FIND_VALUE command, k-buckets are:") hash_table.PrintBuckets() # command to quit and unregister self from pers if (arguments[0] == "QUIT"): # send quit to all peers hash_table.SendQuit() print("Shut down node " + str(local_id)) break
def run(): if len(sys.argv) != 4: print("Error, correct usage is {} [my id] [my port] [k]".format(sys.argv[0])) sys.exit(-1) global val global val_key global buckets local_id = int(sys.argv[1]) my_port = str(int(sys.argv[2])) # add_insecure_port() will want a string k = int(sys.argv[3]) #4 buckets needed i = 4 while i > 0: #append 4 empty deques into the bucket, the deques should contain Nodes buckets.append(deque([])) i -= 1 my_hostname = socket.gethostname() # Gets my host name my_address = socket.gethostbyname(my_hostname) # Gets my IP address from my hostname #don't ask, gRPC tutorial said so server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) csci4220_hw4_pb2_grpc.add_KadImplServicer_to_server(KadImplServicer(), server) #listen from the port server.add_insecure_port("127.0.0.1" + ':' + my_port) server.start() # Use the following code to convert a hostname to an IP and start a channel Note that every stub needs a channel attached to it When you are done with a channel you should call .close() on the channel. Submitty may kill your program if you have too many file descriptors open at the same time. #remote_addr = socket.gethostbyname(my_hostname) #remote_port = int(my_port) #channel = grpc.insecure_channel(remote_addr + ':' + str(remote_port)) while True: input_str = str(raw_input()) input_args = input_str.split() if input_args[0] == "BOOTSTRAP": #print("bootstrap") remote_hostname = str(input_args[1]) remote_port = int(input_args[2]) remote_addr = socket.gethostbyname(remote_hostname) #connect to server & create stub channel = grpc.insecure_channel("127.0.0.1" + ':' + str(remote_port)) stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) #create the node object this_node = csci4220_hw4_pb2.Node(id = local_id, port = int(my_port), address = str(my_address)) #call FindNode node_list = stub.FindNode(csci4220_hw4_pb2.IDKey(node = this_node, idkey = local_id)) #add nodes from the list in node_list for node in node_list.nodes: bit_len = ((node.id)^local_id).bit_length() bit_len -= 1 #pop an element if the bucket is full if len(buckets[bit_len]) == k: buckets[bit_len].popleft() buckets[bit_len].append(node) #add the node that it just sent RPC to r_node = node_list.responding_node bit_len = ((r_node.id)^local_id).bit_length() bit_len -= 1 if len(buckets[bit_len]) == k: buckets[bit_len].popleft() buckets[bit_len].append(r_node) #done (hopefully) print('After BOOTSTRAP({}), k_buckets now look like:'.format(str(r_node.id))) count = 0 for bucket in buckets: sys.stdout.write('{}:'.format(str(count))) for entry in bucket: sys.stdout.write(' {}:{}'.format(str(entry.id), str(entry.port))) sys.stdout.write('\n') count += 1 channel.close() if input_args[0] == "STORE": print("store") this_key = int(input_args[1]) this_value = input_args[2] closest_node = csci4220_hw4_pb2.Node(id = local_id, port = int(my_port), address = str(my_address)) distance = abs(local_id - this_key) for bucket in buckets: for entry in bucket: if abs(int(entry.id) - this_key) < distance: closest_node = entry distance = abs(int(entry.id) - this_key) remote_hostname = str(closest_node.id) remote_port = int(closest_node.port) remote_addr = socket.gethostbyname(remote_hostname) #connect to server & create stub this_addr = "127.0.0.1" + ':' + str(remote_port) channel = grpc.insecure_channel(this_addr) stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) print(this_addr) some_idkey = stub.Store(csci4220_hw4_pb2.KeyValue(node = None, key = this_key, value = this_value)) channel.close() if input_args[0] == "QUIT": for bucket in buckets: for entry in bucket: remote_hostname = str(entry.id) remote_port = int(entry.port) remote_addr = socket.gethostbyname(remote_hostname) this_addr = "127.0.0.1" + ':' + str(remote_port) channel = grpc.insecure_channel(this_addr) stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) print("Letting " + remote_hostname + " know I'm quitting.") some_idkey = stub.Quit(csci4220_hw4_pb2.IDKey(node = None, idkey = local_id)) channel.close() print("Shut down node " + str(local_id)) break
def run(): if len(sys.argv) != 4: print("Error, correct usage is {} [my id] [my port] [k]".format( sys.argv[0])) sys.exit(-1) local_id = int(sys.argv[1]) my_port = str(int(sys.argv[2])) # add_insecure_port() will want a string k = int(sys.argv[3]) my_hostname = socket.gethostname() # Gets my host name my_address = socket.gethostbyname( my_hostname) # Gets my IP address from my hostname # Create server server = grpc.server(futures.ThreadPoolExecutor(max_workers=16)) servicer = KadImplServicer() csci4220_hw4_pb2_grpc.add_KadImplServicer_to_server(servicer, server) server.add_insecure_port('[::]:' + my_port) server.start() servicer.k = k for i in range(n): servicer.k_buckets.append([]) servicer.this_node = csci4220_hw4_pb2.Node(id=local_id, port=int(my_port), address=my_address) # Listen for commands from standard input while 1: for line in sys.stdin: command = line.split(" ") for i in range(len(command)): command[i] = command[i].strip() # BOOTSTRAP command if (command[0] == "BOOTSTRAP"): remote_addr = socket.gethostbyname(command[1]) remote_port = int(command[2]) with grpc.insecure_channel(remote_addr + ':' + str(remote_port)) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) nodeList = stub.FindNode( csci4220_hw4_pb2.IDKey(node=servicer.this_node, idkey=servicer.this_node.id)) k_buckets_add(servicer, nodeList.responding_node) # Add nodes in nodeList to k_buckets for node in nodeList.nodes: k_buckets_add(servicer, node) print("After BOOTSTRAP(" + str(nodeList.responding_node.id) + "), k_buckets now look like:") print_k_buckets(servicer.k_buckets) # FIND_NODE command if (command[0] == "FIND_NODE"): print("Before FIND_NODE command, k-buckets are:") print_k_buckets(servicer.k_buckets) key = int(command[1]) found = 0 if local_id == key: print("Found destination id " + str(key)) else: for i in range(n): for j in range(len(servicer.k_buckets[i])): if found == 0: with grpc.insecure_channel( servicer.k_buckets[i][j].address + ':' + str(servicer.k_buckets[i][j].port) ) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub( channel) nodelist = stub.FindNode( csci4220_hw4_pb2.IDKey( node=servicer.this_node, idkey=key)) for node in nodelist.nodes: k_buckets_add(servicer, node) if node.id == key: print("Found destination id " + str(key)) found = 1 if found == 0: print("Could not find destination id " + str(key)) print("After FIND_NODE command, k-buckets are:") print_k_buckets(servicer.k_buckets) # FIND_VALUE command if (command[0] == "FIND_VALUE"): print("Before FIND_VALUE command, k-buckets are:") print_k_buckets(servicer.k_buckets) key = int(command[1]) found = 0 # First check if key is stored locally if key in servicer.values: print('Found data "' + servicer.values[key] + '" for key ' + str(key)) found = 1 else: # Find node with id closest to key closest = None for i in range(n): for j in range(len(servicer.k_buckets[i])): if closest == None: closest = servicer.k_buckets[i][j] if (servicer.k_buckets[i][j].id ^ key) < (closest.id ^ key): closest = servicer.k_buckets[i][j] # Check if bucket is empty if closest != None: # Ask closest node for value with grpc.insecure_channel( closest.address + ':' + str(closest.port)) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) kv_wrapper = stub.FindValue( csci4220_hw4_pb2.IDKey(node=servicer.this_node, idkey=key)) k_buckets_add(servicer, kv_wrapper.responding_node) # If value was found for key if kv_wrapper.mode_kv: print('Found value "' + kv_wrapper.kv.value + '" for key ' + str(key)) found = 1 else: for node in kv_wrapper.nodes: k_buckets_add(servicer, node) # Correct node found, ask for value if node.id == key: with grpc.insecure_channel( node.address + ':' + str(node.port)) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub( channel) kv_wrapper1 = stub.FindValue( csci4220_hw4_pb2.IDKey( node=servicer.this_node, idkey=key)) if kv_wrapper1.mode_kv: print('Found value "' + kv_wrapper1.kv.value + '" for key ' + str(key)) found = 1 if found == 0: print("Could not find key " + str(key)) print("After FIND_VALUE command, k-buckets are:") print_k_buckets(servicer.k_buckets) # STORE command if (command[0] == "STORE"): key = int(command[1]) value = command[2] # Find node with id closest to key closest = servicer.this_node for i in range(n): for j in range(len(servicer.k_buckets[i])): if (servicer.k_buckets[i][j].id ^ key) < (closest.id ^ key): closest = servicer.k_buckets[i][j] # Check if this is the closest node -> store locally if closest.id == servicer.this_node.id: servicer.values[key] = value else: # Send value to closest node with grpc.insecure_channel(closest.address + ':' + str(closest.port)) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) stub.Store( csci4220_hw4_pb2.KeyValue(node=servicer.this_node, key=key, value=value)) print("Storing key " + str(key) + " at node " + str(closest.id)) # QUIT command if (command[0] == "QUIT"): for i in reversed(range(n)): for node in reversed(servicer.k_buckets[i]): with grpc.insecure_channel(node.address + ':' + str(node.port)) as channel: stub = csci4220_hw4_pb2_grpc.KadImplStub(channel) print("Letting " + str(node.id) + " know I'm quitting.") stub.Quit( csci4220_hw4_pb2.IDKey( node=servicer.this_node, idkey=servicer.this_node.id)) print("Shut down node " + str(local_id)) sys.exit()