示例#1
0
    def __init__(self, server_pid, nodes, loop):
        self.router = MessageRouter(server_pid)

        self.server_pid = server_pid
        self.port = nodes[server_pid]["port"]
        self.cliport = nodes[server_pid]["cliport"]
        self.histfile = nodes[server_pid]["histfile"]
        self.nodes = nodes

        self.files = dict()  # name -> string

        self.zoo = Zookeeper.Zookeeper(self.router, self.histfile)

        # Async listeners
        self.server = loop.run_until_complete(
            asyncio.start_server(self.accept_peer_connection,
                                 "",
                                 self.port,
                                 loop=loop))
        self.cliserver = loop.run_until_complete(
            asyncio.start_server(self.accept_cli_connection,
                                 "",
                                 self.cliport,
                                 loop=loop))
        loop.run_until_complete(self.connect_to_peers())
示例#2
0
    def __init__(self, aCritter):
        """Initializes the post office.

        Arguments:
            aCritter: The critter.

        """
        self.mCritter = aCritter

        settings = self.mCritter.getSettings()

        # Configuring the logger.
        self.mLogger = logging.getLogger(self.__class__.__name__)
        self.mLogger.propagate = False
        # TODO: Remove the hardcoded value of the path.
        handler = logging.FileHandler('/tmp/' + self.mCritter.mCrittnick + '.log')
        # TODO: Remove the hardcoded value of the formatter.
        formatter = logging.Formatter('[%(asctime)s][%(threadName)28s][%(levelname)8s] - %(message)s')
        handler.setFormatter(formatter)
        self.mLogger.addHandler(handler)
        self.mLogger.setLevel(self.mCritter.mSettings.get('logging', 'level'))

        policy = settings.get('crittwork', 'policy')

        addressPublisher = addressSubscriber = ''

        # TODO: Now this is an ifology, it should be a real policy.
        if policy == 'multicast':
            addressPublisher = addressSubscriber = settings.get('crittwork', 'multicast')
        elif policy == 'broker':
            addressPublisher  = settings.get('crittwork', 'brokerPublisher')
            addressSubscriber = settings.get('crittwork', 'brokerSubscriber')
        else:
            assert False, "Invalid crittwork policy selected."

        # TODO: Get from the factory.
        self.mTransport = TransportZMQ(addressPublisher, addressSubscriber)

        self.mOutgoingAnnouncementsQueue = Queue()
        self.mIncomingAnnouncementsQueue = Queue()

        self.mRiteConnector = RiteConnector(aCritter.mRites)

        self.mMessageEncoder = MessageEncoder()

        # Spawning the announcement publisher.
        self.mLogger.debug("Spawning the announcement publisher.")
        self.mAnnouncementPublisher = AnnouncementPublisher(self)
        self.mAnnouncementPublisher.setDaemon(True)

        # Spawning the announcement subscriber.
        self.mLogger.debug("Spawning the announcement subscriber.")
        self.mAnnouncementSubscriber = AnnouncementSubscriber(self)
        self.mAnnouncementSubscriber.setDaemon(True)

        # Spawning the message router.
        # FIXME: Jealous.
        self.mLogger.debug("Spawning the message router.")
        self.mMessageRouter = MessageRouter(self)
        self.mMessageRouter.setDaemon(True)
示例#3
0
class PostOffice(object):
    """The PostOffice that handles all the communication.

    Attributes:
        mCritter:                    The critter.
        mIncomingAnnouncementsQueue: The queue of incoming announcements.
        mLogger:                     The logger.
        mMessageEncoder:             The message encoder.
        mOutgoingAnnouncementsQueue: The queue of outgoing announcements.
        mAnnouncementPublisher:      The announcement publisher.
        mAnnouncementSubscriber:     The announcement subscriber.
        mMessageRouter:              The message router.
        mRiteConnector:              The rite connector.
        mTransport:                  The transport.

    """

    def __init__(self, aCritter):
        """Initializes the post office.

        Arguments:
            aCritter: The critter.

        """
        self.mCritter = aCritter

        settings = self.mCritter.getSettings()

        # Configuring the logger.
        self.mLogger = logging.getLogger(self.__class__.__name__)
        self.mLogger.propagate = False
        # TODO: Remove the hardcoded value of the path.
        handler = logging.FileHandler('/tmp/' + self.mCritter.mCrittnick + '.log')
        # TODO: Remove the hardcoded value of the formatter.
        formatter = logging.Formatter('[%(asctime)s][%(threadName)28s][%(levelname)8s] - %(message)s')
        handler.setFormatter(formatter)
        self.mLogger.addHandler(handler)
        self.mLogger.setLevel(self.mCritter.mSettings.get('logging', 'level'))

        policy = settings.get('crittwork', 'policy')

        addressPublisher = addressSubscriber = ''

        # TODO: Now this is an ifology, it should be a real policy.
        if policy == 'multicast':
            addressPublisher = addressSubscriber = settings.get('crittwork', 'multicast')
        elif policy == 'broker':
            addressPublisher  = settings.get('crittwork', 'brokerPublisher')
            addressSubscriber = settings.get('crittwork', 'brokerSubscriber')
        else:
            assert False, "Invalid crittwork policy selected."

        # TODO: Get from the factory.
        self.mTransport = TransportZMQ(addressPublisher, addressSubscriber)

        self.mOutgoingAnnouncementsQueue = Queue()
        self.mIncomingAnnouncementsQueue = Queue()

        self.mRiteConnector = RiteConnector(aCritter.mRites)

        self.mMessageEncoder = MessageEncoder()

        # Spawning the announcement publisher.
        self.mLogger.debug("Spawning the announcement publisher.")
        self.mAnnouncementPublisher = AnnouncementPublisher(self)
        self.mAnnouncementPublisher.setDaemon(True)

        # Spawning the announcement subscriber.
        self.mLogger.debug("Spawning the announcement subscriber.")
        self.mAnnouncementSubscriber = AnnouncementSubscriber(self)
        self.mAnnouncementSubscriber.setDaemon(True)

        # Spawning the message router.
        # FIXME: Jealous.
        self.mLogger.debug("Spawning the message router.")
        self.mMessageRouter = MessageRouter(self)
        self.mMessageRouter.setDaemon(True)

    def start(self):
        """Starts the post office by starting its threads."""
        self.mAnnouncementPublisher.start()
        self.mAnnouncementSubscriber.start()
        self.mMessageRouter.start()

    def encode(self, aData):
        """A facade method to hide message encoder from clients.

        Arguments:
            aData: The dictionary of parameters.

        Returns:
            A message.

        """
        return self.mMessageEncoder.encode(aData)

    def putIntoAnEnvelope(self, aMessage):
        return self.mMessageEncoder.putIntoAnEnvelope(aMessage)

    def putIncomingAnnouncement(self, aMessage):
        """Puts an incoming announcement (in the form of a message) into the queue.

        Arguments:
            aMessage The message to be processed.

        """
        self.mIncomingAnnouncementsQueue.put(aMessage)

    def putOutgoingAnnouncement(self, aMessage):
        """Puts an outgoing announcement (in the form of a message) into the queue.

        Arguments:
            aMessage The message to be sent.

        """
        self.mOutgoingAnnouncementsQueue.put(aMessage)

    def getIncomingAnnouncement(self):
        """Gets an incoming announcement (in the form of a message) from the queue.

        Returns The message to be processed.

        """
        return self.mIncomingAnnouncementsQueue.get()

    def getOutgoingAnnouncement(self):
        """Gets an outgoing announcement (in the form of a message) from the queue.

        Returns The message to be sent.

        """
        return self.mOutgoingAnnouncementsQueue.get()

    def putCommand(self, aRite, aCommand, aPriority=PRIORITY_DEFAULT):
        self.mRiteConnector.putCommand(aRite, aCommand, aPriority)

    def putMessage(self, aRite, aMessage, aPriority=PRIORITY_DEFAULT):
        self.mRiteConnector.putMessage(aRite, aMessage, aPriority)

    def addSubscriptionChannel(self, aSubscriptionChannel):
        self.mTransport.addSubscriptionChannel(aSubscriptionChannel)

    def removeSubscriptionChannel(self, aSubscriptionChannel):
        self.mTransport.removeSubscriptionChannel(aSubscriptionChannel)

    def getCorrespondingSubscriptionChannel(self, aMessage):
        return SUBSCRIPTION_CHANNEL_ALL
示例#4
0
class ListenerServer:
    def __init__(self, server_pid, nodes, loop):
        self.router = MessageRouter(server_pid)

        self.server_pid = server_pid
        self.port = nodes[server_pid]["port"]
        self.cliport = nodes[server_pid]["cliport"]
        self.histfile = nodes[server_pid]["histfile"]
        self.nodes = nodes

        self.files = dict()  # name -> string

        self.zoo = Zookeeper.Zookeeper(self.router, self.histfile)

        # Async listeners
        self.server = loop.run_until_complete(
            asyncio.start_server(self.accept_peer_connection,
                                 "",
                                 self.port,
                                 loop=loop))
        self.cliserver = loop.run_until_complete(
            asyncio.start_server(self.accept_cli_connection,
                                 "",
                                 self.cliport,
                                 loop=loop))
        loop.run_until_complete(self.connect_to_peers())

    @asyncio.coroutine
    def connect_to_peers(self):
        for pid, node in self.nodes.items():
            if pid == self.server_pid:
                continue
            if not self.router.is_connected(pid):
                try:
                    reader, writer = yield from asyncio.open_connection(
                        node["ip"], node["port"])
                    writer.write(
                        MessageFactory.PID(str(self.server_pid) +
                                           "\n").encode("utf-8"))
                    print("Connected to PID %d\n" % pid)
                    self.router.add_peer(pid, reader, writer)
                    self.zoo.recover_from_failure()
                    asyncio.ensure_future(
                        self.handle_peer_connection(reader, writer))
                except Exception as e:
                    print(e)
                    pass

    @asyncio.coroutine
    def handle_peer_connection(self, reader, writer):
        while True:
            data = (yield from reader.readline()).decode("utf-8")
            print("RECEIVED %s\n" % data)
            self.zoo.recv_message(data, self.router.get_pid(reader))
            if not data:
                return None

    @asyncio.coroutine
    def accept_peer_connection(self, reader, writer):
        print("Accepted peer connection\n")
        #if checks should probs be here instead
        data = (yield from reader.readline()).decode("utf-8")
        print("recvd PID %s\n" % data)
        pid = int(data.split()[1])

        self.router.add_peer(pid, reader, writer)
        #Connected
        yield from self.handle_peer_connection(reader, writer)
        #disconnected
        yield from writer.drain()

    @asyncio.coroutine
    def handle_cli_connection(self, reader, writer):
        while True:
            data = (yield from reader.readline()).decode("utf-8")

            print("received %s" % data)
            # self.recv_cli_message(data)
            self.router.broadcast_to_cli("received %s" % data)
            self.router.broadcast_to_peers("HEARTBEAT")
            if not data:
                self.router.del_cli(reader)
                return None

    @asyncio.coroutine
    def accept_cli_connection(self, reader, writer):
        writer.write(("Welcome to server " + str(self.server_pid) +
                      "\n").encode("utf-8"))
        self.router.add_cli(reader, writer)
        #Connected
        yield from self.handle_cli_connection(reader, writer)
        #Disconnected
        yield from writer.drain()