def handover(self, peer_id) -> dict: storage = dict() replica = dict() for k in list(self.storage): key = int(k) if Key.between(key, peer_id, self.id): storage[k] = self.storage.pop(k) for k in list(self.replica): key = int(k) if Key.between(key, self.predecessor[0], peer_id): replica[k] = self.replica.pop(k) return (storage, replica)
def notify(self, id: int, peer: tuple): if self.predecessor is None or Key.between(id, self.predecessor[0], self.id): self.predecessor = (id, peer[0]) logging.debug(f"Got a new predecessor: [{self.predecessor}]") return self.handover(id) return None
def lookup(self, data: int) -> None: """ Processes the lookup of key-value pair request. _data_ is an int key to find. """ if not isinstance(data, int): logging.warn(f"Received key is not an integer: {data}.") return "bad request" client, key = data if Key.between(key, self.predecessor[0], self.id): return self.storage.get(str(key), None) else: to = (self.successor[1], self.port) return self.create_request(to, "lookup", data, get_res=True)
def stabilize(self, peer: tuple, pred, succ) -> None: """ Try to stabilize the ring on my part by notifying my successor, or successor's predecessor, of my existence. Creates a new request, if necessary. _data_ is a tuple of my current successor's predecessor and successor. """ if pred is None: # My peer has no predecessor # Notify of my existence: if self.next and peer[0] == self.next[0]: self.successor = peer self.next = succ self.create_request(peer, "notify", self.id, res_wait=True) elif isinstance(pred, (tuple, list)) and len(pred) == 2: # My peer has a predecessor... pred_id = pred[0] if pred_id == self.successor[0]: # ...but it's pointing to itself. # Notify of my existence: if self.next and peer[0] == self.next[0]: self.successor = peer self.next = succ self.create_request(peer, "notify", self.id, res_wait=True) else: # ...and it's pointing to some other node. # > Determine where I am in respect to my current # > successor (peer) and its predecessor... if Key.between(pred_id, self.id, self.successor[0]): # ...I am before both of them. self.next = self.successor self.successor = pred self.create_request(peer, "request", self.id, res_wait=True) else: # ...I am between them. # Adopt my peer's successor self.next = succ if self.next and peer[0] == self.next[0]: self.successor = peer # Notify of my existence: self.create_request(peer, "notify", self.id, res_wait=True)
def add(self, data: tuple) -> None: """ Processes the insertion of key-value pair request. _data_ is a tuple containing the key-value pair to store. """ if not (isinstance(data, tuple) and len(data) == 2): logging.warn(f"Malformatted data of key-value pair: {data}.") return "bad request" key, value = data predecessor = self.predecessor[0] if self.predecessor else self.id if Key.between(key, predecessor, self.id): k = str(key) self.storage[k] = value logging.info( f"{key}:{value} stored successfully.\nClient and predecessor will be notified." ) self.create_request((self.successor[1], self.port), "replicate", data) return key else: to = (self.successor[1], self.port) return self.create_request(to, "add", data, get_res=True)