def _PingEpmdResponse(self, result, portNum, nodeType, proto, distVSNRange, nodeNameNoHost, extra, remoteNodeName): """This callback is called when the lookup for a nodename at a host has returned, whether it was successful or not. If it was successful, then RESULT != 0 and the other parameters are valid. If it was not successful, then the other parameters have undefined values.""" if result != 0: callbacks = self._ongoingPings[remoteNodeName] del self._ongoingPings[remoteNodeName] for cb in callbacks: cb("pang") else: [otherNode, otherHost] = remoteNodeName.split("@") out = erl_node_conn.ErlNodeOutConnection(self._nodeName, self._opts) connectedOkCb = erl_common.Callback(self._PingSucceeded, out, remoteNodeName) connectFailedCb = erl_common.Callback(self._PingFailed, out, remoteNodeName) connectionBrokenCb = erl_common.Callback(self._NodeDown, out, remoteNodeName) passThroughMsgCb = erl_common.Callback(self._PassThroughMsg, out, remoteNodeName) out.InitiateConnection(otherHost, portNum, connectedOkCb, connectFailedCb, connectionBrokenCb, self._PassThroughMsg)
def Ping(self, remoteNodeName, pingCallback): """Ping a remote node. REMOTE-NODE-NAME = string | <instance of ErlAtom> The node to ping PING-CALLBACK = <function(RESULT): void> A callback to call for deliverance of the ping result. RESULT = "pong" | "pang". Returns: void Throws: <<to-be-documented>> Try to ping a remote node. A connection to that node is established unless already connected. Whether or not the remote node is up or down is indicated as by the argument to the callback function: "pong": the remote node is alive and there is a connection to it "pang": the remote node is down. """ if not "@" in remoteNodeName: raise ErlNodeBadPeerNameError(remoteNodeName) if remoteNodeName in self._ongoingPings: pingCallbacks = self._ongoingPings[remoteNodeName] self._ongoingPings[remoteNodeName] = pingCallbacks + [pingCallback] else: self._ongoingPings[remoteNodeName] = [pingCallback] [nodeName, hostName] = remoteNodeName.split("@") e = erl_epmd.ErlEpmd(hostName) cb = erl_common.Callback(self._PingEpmdResponse, remoteNodeName) e.PortPlease2Req(nodeName, cb)
def main(argv): global mb, quiet, node_to_connect_to try: opts, args = getopt.getopt(argv[1:], "?dn:c:qr:") except getopt.error as info: print(info) sys.exit(1) hostName = "localhost" ownNodeName = "py_interface_test" cookie = "cookie" doDebug = 0 for (optchar, optarg) in opts: if optchar == "-?": print("Usage: %s erlnode" % argv[0]) sys.exit(1) elif optchar == "-c": cookie = optarg elif optchar == "-d": doDebug = 1 elif optchar == "-q": quiet = 1 elif optchar == "-n": ownNodeName = optarg elif optchar == "-r": global res_pidname res_pidname = optarg if len(args) >= 4: node_to_connect_to = args[0] mod = args[1] fn = args[2] args = eval(args[3]) else: print("Error: missing args: " + "node_to_connect_to mod fn args") sys.exit(1) if doDebug: erl_common.DebugOnAll() print("Creating node...") n = erl_node.ErlNode(ownNodeName, erl_opts.ErlNodeOpts(cookie=cookie)) n.SetEpmdConnectedOkCb( erl_common.Callback(__EpmdConnectedOk, node_to_connect_to, mod, fn, args, __RpcResult)) print("Publishing node...") n.Publish() print("Creating mbox...") mb = n.CreateMBox(None) m = n.CreateMBox(__TestMBoxCallback) evhand = erl_eventhandler.GetEventHandler() evhand.PushReadEvent(sys.stdin, __FlushStdout) print("-GOING LOOPING-") # Erlang side will pick this text up sys.stdout.flush() evhand.Loop()
def KillReq(self, callback): """Issue a Kill request CALLBACK = <function(RESPONSE): void RESPONSE = string Calls the CALLBACK when the answer is available. """ msg = self.PackInt1(self._KILL_REQ) unpackcb = erl_common.Callback(self._UnpackKillResp, callback) self._SendOneShotReq(msg, unpackcb)
def DumpReq(self, callback): """Issue a Dump request CALLBACK = <function(EPMD-PORT-NUM, NODE-INFO): void EPMD-PORT-NUM = NODE-INFO = integer Calls the CALLBACK when the answer is available. """ msg = self.PackInt1(self._DUMP_REQ) unpackcb = erl_common.Callback(self._UnpackDumpResp, callback) self._SendOneShotReq(msg, unpackcb)
def send_async_rpc(self, remote_node, module, function, args, callback=_TestMBoxRPCResponse): self._event_handler.AddTimerEvent(0.001, erl_common.Callback(send_rpc, self._mbox, remote_node, module, function, args, callback))
def PortPleaseReq(self, nodeName, callback): """Issue a PortPlease request. NODE-NAME = string CALLBACK = <function(PORT-NUMBER): void> PORT-NUMBER = integer Calls the CALLBACK function with argument PORT-NUMBER when the answer is available. """ msg = self.PackInt1(self._PORT_PLEASE_REQ) + nodeName unpackcb = erl_common.Callback(self._UnpackPortPleaseResp, callback) self._SendOneShotReq(msg, unpackcb)
def __init__(self, nodeName, opts=erl_opts.ErlNodeOpts()): """Constructor. NODE-NAME = string The name for this node. OPTS = <instance of ErlNodeOpts> Creates an ErlNode. The name of the node is determined by NODE-NAME as described below. A node-name consists of two parts: an alive-name and a host-name, separated by an `@'. The host-name can be short (not including the domain) or long (including the domain). Short and long node-names must not be mixed among the nodes in a system, see the erlang documentation for further details. 1. If the NODE-NAME contains an `@', then NODE-NAME is used unchanged as name for the node. 2. If the NODE-NAME does not contain an `@', then the node's name is constructed as NODE-NAME + "@" + host-name, where host-name is either on short or long form, depending on what is specified in the OPTS. """ shortNodeNames = opts.GetShortNodeNames() self._nodeName = erl_common.AlignNodeName(nodeName, shortNodeNames) self._opts = opts self._creation = 0 self._connections = {} self._epmd = erl_epmd.ErlEpmd(hostName=opts.GetEpmdHost(), portNum=opts.GetEpmdPort()) self._ongoingPings = {} self._isServerPublished = 0 self._pids = {} # mapping pid --> ErlMBox() self._mboxes = {} # mapping ErlMBox --> pid self._registeredNames = {} # mapping name --> pid self._registeredPids = {} # mapping pid --> name self._nodeUpCb = [] # stores (id, callback) self._nodeDownCb = [] # stores (id, callback) self._cbId = 0 self._server = erl_node_conn.ErlNodeServerSocket( self._nodeName, self._opts) self._portNum = self._server.Start(self._NodeUp, self._NodeDown, self._PassThroughMsg) self._epmd.SetOwnPortNum(self._portNum) self._epmd.SetOwnNodeName(self._nodeName) self._epmdConnectedOkCb = erl_common.Callback(self._Sink) self._CreateRex()
def send_async_rpcs(self, rpcs): output_queue = Queue.Queue() def callback(msg): output_queue.put(msg) for rpc in rpcs: self._event_handler.AddTimerEvent(0.001, erl_common.Callback(send_rpc, self._mbox, rpc[0], # remote_node, rpc[1], # module, rpc[2], # function, rpc[3], # args, callback)) return output_queue
def PortPlease2Req(self, nodeName, callback): """Issue a PortPlease2 request. NODE-NAME = string CALLBACK = <function(RESULT, NODE-TYPE, PROTOCOL, DISTR-VSN-RANGE, RNODE-NAME, EXTRA): void> RESULT = 1 | 0 NODE-TYPE = integer PROTOCOL = integer DISTR-VSN-RANGE = tuple(LO, HI) LO = HI = integer RNODE-NAME = string EXTRA = string Calls the CALLBACK function when the answer is available from the EPMD. If the RESULT is 0, then the values of the rest of the arguments are undefined. If the result is 1, then the rest of the arguments have the values as reported from the EPMD. Calls the CALLBACK function with argument PORT-NUMBER when the answer is available. """ msg = self.PackInt1(self._PORT_PLEASE2_REQ) + nodeName unpackcb = erl_common.Callback(self._UnpackPortPlease2Resp, callback) self._SendOneShotReq(msg, unpackcb)
def send_sync_rpc(self, remote_node, module, function, args, timeout=None): # Cleaning queue in case callback called right after timeout if self._sync_rpc_queue.full(): LOGGER.debug("Cleaning sync rpc queue") self._sync_rpc_queue.get() timer_id = self._event_handler.AddTimerEvent(0.001, erl_common.Callback(send_rpc, self._mbox, remote_node, module, function, args, self._sync_rpc_callback)) if timeout is None: timeout = self._timeout try: msg = self._sync_rpc_queue.get(True, timeout) except Queue.Empty as error: self._event_handler.DelTimerEvent(timer_id) raise Timeout("No response for sync rpc.") return msg
def set_timeout(event_handler, timeout): event_handler.AddTimerEvent(timeout, erl_common.Callback(_DoTimeout, event_handler))
print "Publishing node..." n.Publish() print "Creating mbox..." m = n.CreateMBox(__TestMBoxCallback) print "Registering mbox as p..." m.RegisterName("p") evhand = erl_eventhandler.GetEventHandler() eh = evhand evhand.AddTimerEvent(timeout, DoTimeout) # Schedule to run the RPC after we've started looping evhand.AddTimerEvent( 0.001, erl_common.Callback(SendTheRPC, m, remoteNode, module, function, map(lambda x: ExprRebuildAtoms(eval(x)), fargs))) """import threading threading.Thread(target = evhand.AddTimerEvent,args=(0.001, erl_common.Callback( SendTheRPC, m, remoteNode, module, function, map(lambda x: ExprRebuildAtoms(eval(x)), fargs)))).start()""" print "Looping..." #threading.Thread(target=evhand.Loop,args=()).start() evhand.Loop() sys.exit(0) try: main(sys.argv)
def StopReq(self, nodeName, callback): raise "Not used" msg = self.PackInt1(self._STOP_REQ) + nodeName unpackcb = erl_common.Callback(self._UnpackStopResp, callback) self._SendOneShotReq(msg, unpackcb)
def SendMsgFromMBox(self, sourceMBox, dest, msg): """This routine is intended to be called from an ErlMBox instance SOURCE-MBOX = <instance of ErlMBox> DEST = <instance of ErlPid> | string | <instance of ErlAtom> | tuple(DEST-REGNAME, DEST-NODE) DEST-REGNAME = DEST-NODE = string | <instance of ErlAtom> MSG = <term> Returns: void THrows: <<to-be-documented>> """ ## Possible dest types: ## - A tuple: (registered_name, node_name) ## - An atom: registered_name ## - A pid: <erlpid ...> (note: the pid contains the pid's node) sourcePid = self._mboxes[sourceMBox] ## First check for strings in the dest argument. ## Convert any strings to to atoms. if type(dest) == str or type(dest) == bytes: dest = erl_term.ErlAtom(dest) elif type(dest) == tuple: destPidName = dest[0] destNode = dest[1] if type(destPidName) == str or type(destPidName) == bytes: destPidName = erl_term.ErlAtom(destPidName) if type(destNode) == str or type(destNode) == bytes: destNode = erl_term.ErlAtom(destNode) dest = (destPidName, destNode) ## Then split the dest into: ## destPid/destPidName and destNode ## depending on its type. if type(dest) == tuple: destPid = dest[0] destNode = dest[1] elif erl_term.IsErlAtom(dest): destNode = self name = dest.atomText if name not in self._registeredNames: return destPid = self._registeredNames[name] elif erl_term.IsErlPid(dest): destPid = dest destNode = dest.node else: return ## Now do the sending... if destNode == self: if destPid not in self._registeredPids: return mbox = self._registredPids[destPid] mbox.Msg(msg) else: # dest node is remote # First make sure we are online # FIXME: Will this really work??? # Publish might register callbacks, but # this code continues after the Publish... self.Publish() destNodeName = destNode.atomText if destNodeName not in self._connections: # We don't have a connection to the destination # We must open a connection. # This is done by pinging with the ping-callback # being a function that sends the message. cb = erl_common.Callback(self._SendMsgToRemoteNode, sourcePid, destNode, destPid, msg) destNodeName = destNode.atomText self.Ping(destNodeName, cb) else: ## We have contact with the remote node. Send at once! self._SendMsgToRemoteNode("pong", sourcePid, destNode, destPid, msg)
def StopReq(self, nodeName, callback): nodeName = nodeName.encode("latin1") msg = self.PackInt1(self._STOP_REQ) + nodeName unpackcb = erl_common.Callback(self._UnpackStopResp, callback) self._SendOneShotReq(msg, unpackcb)