Пример #1
0
    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)
Пример #2
0
 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
Пример #3
0
    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)
Пример #4
0
    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)
Пример #5
0
    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)