Пример #1
0
class Controller(object):
    def __init__(self, my_id, peer_ids, no_ping=False):
        # store my_id
        self.my_id = my_id
        # set up the peer object
        self.peer = Peer(my_id)
        if not no_ping:
            # when we debug it, we don't want ping to border us
            self.workers = [self.add_suc(t) for t in peer_ids]
            # start the info server (TCP server)
            # to receive the information
            InfoSer().start()

        # start up this ping server to accept pign
        self.ping_ser = UdpServer()
        self.ping_ser.start()
        # start to accept the user input
        InputWorker().start()

        # exit approve count
        self.exit_approve = 0
        self.exit_approve_lock = Lock()

    def add_suc(self, peer_id):
        """
        start the client
        and record the new successor
        """
        self.peer.add_suc(peer_id)
        worker = UdpClient(peer_id)
        worker.start()
        return worker

    def get_suc(self, index):
        # just pass the implementation to reduce
        # coupling
        return self.peer.get_suc(index)

    def prompt_sus(self):
        # prompt the new relationship
        print("My first successor is now peer " + str(self.peer.get_suc(0)) +
              ".")
        print("My second successor is now peer " + str(self.peer.get_suc(1)) +
              ".")

    def departure(self):
        """
        This client will leave, kill all ping client send message by TCP
        """
        # stop pinging
        [w.stop() for w in self.workers]

        # Inform the preseccor to exit
        InfoClient(self.peer.get_pre(0), INFO_PEER_EXIT,
                   self.peer.get_suc(1)).start()
        InfoClient(self.peer.get_pre(1), INFO_PEER_EXIT,
                   self.peer.get_suc(0)).start()

    def handle_allow_exit(self):
        # other peer tell me I can exit
        self.exit_approve_lock.acquire()
        self.exit_approve += 1
        if self.exit_approve == 2:
            # exit the main thread
            os._exit(0)
        self.exit_approve_lock.release()

    def handle_peer_departure(self, depart_id: int, new_next: int):
        # prompt the depart
        print("Peer " + str(depart_id) + " will depart from the network.")
        # print("Debug: new sus: "+ str(new_next))

        # remove the old successor
        self.peer.del_suc(depart_id)
        # stop the ping to depart server
        [w.stop() for w in self.workers if w.server_id == depart_id]
        # update the worker list
        self.workers = [w for w in self.workers if w.server_id != depart_id]

        # add a worker for new successor
        self.handle_new_sus(new_next)

    def suc_leave(self, depart_id: int):
        # leaving of succsor
        self.workers = [w for w in self.workers if w.server_id != depart_id]
        self.peer.del_suc(depart_id)
        # get the current alive succsor
        """
        Send a request for new successor via TCP
        """
        # print("Debug: I get help from " + str(self.peer.get_suc(0)))
        InfoClient(self.peer.get_suc(0), INFO_PEER_LOSS, depart_id).start()

    def handle_new_sus(self, new_next: int):
        # print("Debug: I will get a new suc: " + str(new_next))
        self.workers.append(self.add_suc(new_next))
        self.prompt_sus()

    def add_pre(self, pre_id):
        """
        Call by Pingserver to record the presessor        
        """
        self.peer.add_pre(pre_id)

    def pre_leave(self, pre, new_pre):
        """
        Pre seccsor ask to depreacate a precessor
        This will not use
        """
        # leaving of presuccor
        self.peer.del_pre(pre)
        self.peer.add_pre(new_pre)

    def handle_file_request(self, requester_id: int, file_id: int):
        if self.peer.has_file(file_id):
            # prompt
            print("File " + str(file_id) + " is here.")

            # send to the recevier to open the port
            InfoClient(requester_id, INFO_FILE_RES, file_id).start()

            # startup the file tr
            FileSender(requester_id, str(file_id) + ".pdf").start()
        else:
            # print File not here promet
            print("File " + str(file_id) + " is not stored here.")
            print("File request message has been forwarded to my successor.")
            InfoClient(self.peer.get_suc(0), INFO_FILE_REQ, file_id,
                       requester_id).start()

    def handle_file_waiting(self, from_id: int, file_id: int):
        print("Received a response message from peer " + str(from_id) +
              ", which has the file " + str(file_id) + ".")
        self.ping_ser.wait_file(file_id)

    def request_file(self, file_id: int):
        if self.peer.has_file(file_id):
            print("This peer have file " + str(file_id) +
                  " no need for request.")
            return
        print("File request message for " + str(file_id) +
              " has been sent to my successor.")
        # send to the recevier to open the port
        InfoClient(self.peer.get_suc(0), INFO_FILE_REQ, file_id,
                   self.my_id).start()