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())
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)
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
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()