class XMLRPCNotificationChannel(Thread): """ Comunication channel used by the node to send notification to its controller. It is a one-way communication channel from the node to the controller. The controller calls the get method, and blocks waiting for a reply. Whenever a new event needs to be sent to the controller, this message is sent back in reply to the get method call and the controller calls back the get method. """ def __init__(self,host, port): """ Constructor. host : ip address of the node port : port used by this XML/RPC server""" Thread.__init__(self) self.host = host self.port = port self.server = SimpleXMLRPCServer((self.host, self.port)) self.server.register_instance(self) self.stopThread = False # Message to send queue self.outgoing = NotificationQueue() # this flag is set to True when we want to stop this thread self.stopThread = False def run(self): while not self.stopThread: self.server.handle_request() def get(self): """ Wait for notification from the node main thread and send back events to the controller. The controller calls the get method and is notified when a network event occurs.""" # get the lock self.outgoing.acquire() # nothing to send, just wait if self.outgoing.empty(): self.outgoing.wait() # the main thread called the notify method to awaken this thread # release the lock and send back the message to the controller. self.outgoing.release() e = self.outgoing.get() response = e.data() return response def send(self, message): """ Send a message to the controller""" self.outgoing.put(message)
def __init__(self, params): """ All informations about this node: host --> ip if the node, network_port, GUI_port, posX, posY, ar, ca, ori --> a point, exp --> expected number of neighbour, pseudo""" # event queue, used for inter-thread communication self.events = NotificationQueue() # network communication with peers is handled by this object netParams = params.getNetParams() self.peerConnector = UDPConnector("peer", self.events, netParams) controlParams = params.getControlParams() self.controlConnector = XMLRPCConnector("control", self.events, controlParams) # set the solipsis protocol used engineParams = params.getEngineParams() self.engine = V0_2_5_Engine(self, engineParams) self.controlEngine = ControlEngine(self, engineParams) self.internalEngine = InternalEngine(self, engineParams) position = [params.posX, params.posY] # call parent class constructor Entity.__init__(self, position, params.ori, params.ar, params.caliber, params.pseudo) self.id = "unknown" # maximum expected number of neighbours. self.exp = params.exp # our IP address or 'localhost' if not specified in config file self.host = params.host self.alive = True self.logger = params.rootLogger # manage all peers peersParams = params.getPeersParams() self.peersManager = PeersManager(self, peersParams) # set world size in Geometry class Geometry.SIZE = params.world_size self.params=params
def __init__(self,host, port): """ Constructor. host : ip address of the node port : port used by this XML/RPC server""" Thread.__init__(self) self.host = host self.port = port self.server = SimpleXMLRPCServer((self.host, self.port)) self.server.register_instance(self) self.stopThread = False # Message to send queue self.outgoing = NotificationQueue() # this flag is set to True when we want to stop this thread self.stopThread = False
class Node(Entity): def __init__(self, params): """ All informations about this node: host --> ip if the node, network_port, GUI_port, posX, posY, ar, ca, ori --> a point, exp --> expected number of neighbour, pseudo""" # event queue, used for inter-thread communication self.events = NotificationQueue() # network communication with peers is handled by this object netParams = params.getNetParams() self.peerConnector = UDPConnector("peer", self.events, netParams) controlParams = params.getControlParams() self.controlConnector = XMLRPCConnector("control", self.events, controlParams) # set the solipsis protocol used engineParams = params.getEngineParams() self.engine = V0_2_5_Engine(self, engineParams) self.controlEngine = ControlEngine(self, engineParams) self.internalEngine = InternalEngine(self, engineParams) position = [params.posX, params.posY] # call parent class constructor Entity.__init__(self, position, params.ori, params.ar, params.caliber, params.pseudo) self.id = "unknown" # maximum expected number of neighbours. self.exp = params.exp # our IP address or 'localhost' if not specified in config file self.host = params.host self.alive = True self.logger = params.rootLogger # manage all peers peersParams = params.getPeersParams() self.peersManager = PeersManager(self, peersParams) # set world size in Geometry class Geometry.SIZE = params.world_size self.params=params def getPeersManager(self): return self.peersManager def updatePosition(self, newPosition): """ update the position of the node newPosition : the new poition of the node , a list [posX, posY] """ self.node.position = newPosition manager = self.getPeersManager() # re compute all positions of neighbours manager.update() def send(self, peer, message): """ Send a message to a peer message : a solispsis message, e.g. 'HEARTBEAT;10.193.161.35:33363' peer : a Peer object resenting the recipient of the message """ #netEvent = NetworkEvent(message) #netEvent.setRecipient(peer.getNetAddress()) #self.net.send(netEvent) self.peerConnector.send(peer, message) def sendController(self, message): self.controlConnector.send(message) def enterSolipsis(self): """ Enter Solipsis world, we consider that we have entered solipsis as soon as have we are connected to one Solipsis entity Raise: SolipsisConnectionError when a timeout expires Return : True if the connection succeded """ time_stamp = time.time() #message = "KNOCK;SOLIPSIS 0.3" message = "HI" timeout = self.params.connection_timeout while True: # retrieve peer manager = self.getPeersManager() peer = manager.getRandomPeer() # send message self.send(peer, message) time.sleep(0.5) # we got an answer, for one of our Hi messages: we have entered Solipsis if not self.events.empty(): self.alive = True return True # Time out : impossible to connect if time.time() > time_stamp + timeout: self.logger.critical("Time out: cannot connect to Solipsis") raise SolipsisConnectionError() def exit(self): """ stop the node and exit """ # stop the network thread self.peerConnector.stop() # we do not need to stop the controlConnector. The controlConnector # stopped after sending us the exit message # --> self.controlConnector.stop() not needed ! # wait for the other threads before exiting self.peerConnector.join() self.controlConnector.join() self.alive = False def mainLoop(self): """ Main loop of the program """ # start control connector self.controlConnector.start() # start peer connector self.peerConnector.start() try: # enter solipsis : send the first message #self.enterSolipsis() pass except: self.logger.critical("cannot enter Solipsis, exiting...") self.exit() raise while self.alive: self.events.acquire() # no events to process - wait for a notification from other threads if self.events.empty(): self.events.wait() # We can immediately release the lock: we know that there is an item available # because this is the only thread that consumes items from the queue. # If other threads can consume item then we must first get the item then # release the lock self.events.release() # process one event in queue event = self.events.get() type = event.type() #self.logger.debug("%s - %s - %s ", event.name(), event.type(), # event.data()) if( type == Event.PEER ): self.engine.process(event) elif( type == Event.CONTROL): self.controlEngine.process(event) elif type == Event.INTERNAL: self.internalEngine.process(event) else: self.logger.critical("Unknown event type" + type) self.logger.debug("end of main loop") def processPeriodicEvent(self, event): """ Process periodic tasks Send heartbeat message Or check global connectivity """ # TO DO self.logger.critical("processPeriodicEvent not implemented")
class Node(Entity): def __init__(self, params): """ All informations about this node: host --> ip if the node, network_port, GUI_port, posX, posY, ar, ca, ori --> a point, exp --> expected number of neighbour, pseudo""" # event queue, used for inter-thread communication self.events = NotificationQueue() # network communication with peers is handled by this object netParams = params.getNetParams() self.peerConnector = UDPConnector("peer", self.events, netParams) controlParams = params.getControlParams() self.controlConnector = XMLRPCConnector("control", self.events, controlParams) intParams = params.getInternalParams() self.internalConnector = InternalConnector('internal', self.events, intParams) position = Position(params.posX, params.posY) # call parent class constructor Entity.__init__(self, position, params.ori, params.ar, params.caliber, params.pseudo) self.id = "unknown" # maximum expected number of neighbours. self.exp = params.exp # our IP address or 'localhost' if not specified in config file self.host = params.host self.alive = True self.logger = params.rootLogger # manage all peers peersParams = params.getPeersParams() self.peersManager = PeersManager(self, peersParams) # set world size in Geometry class Geometry.SIZE = params.world_size self.params=params self.state = None self.setState('NotConnected') def getPeersManager(self): return self.peersManager def setState(self, stateClass): stmt = 'state.' + stateClass + '(self, self.logger)' try: self.state = eval(stmt) except: raise SolipsisInternalError('unknown state ' + stateClass) def fire(self, event): """ Send an event. event : the event to send. """ connector = None type = event.getType() if type == 'peer': connector = self.peerConnector elif type == 'control': connector = self.controlConnector elif type == 'internal': connector = self.internalConnector else: raise SolipsisInternalError('Unknown event type ' + type ) connector.send(event) def exit(self): """ stop the node and exit """ # stop the network thread self.peerConnector.stop() self.internalConnector.stop() # we do not need to stop the controlConnector. The controlConnector # stopped after sending us the exit message # --> self.controlConnector.stop() not needed ! # wait for the other threads before exiting self.peerConnector.join() self.controlConnector.join() self.internalConnector.join() self.alive = False def mainLoop(self): """ Main loop of the program """ # start control connector self.controlConnector.start() # start peer connector self.peerConnector.start() # start internal connected : needed for periodic tasks self.internalConnector.start() while self.alive: self.events.acquire() # no events to process - wait for a notification from other threads if self.events.empty(): self.events.wait() # We can immediately release the lock: we know that there is an item available # because this is the only thread that consumes items from the queue. # If other threads can consume item then we must first get the item then # release the lock self.events.release() # process one event in queue event = self.events.get() request = event.getRequest() try: # process this request according to our current state # e.g.: stmt='self.state.NEAREST(event)' stmt = 'self.state.' + request + '(event)' eval(stmt) except: self.logger.debug(sys.exc_info()[0]) self.logger.debug(sys.exc_info()[1]) self.logger.debug("unknown request "+ stmt) self.logger.debug("end of main loop")