Exemplo n.º 1
0
    def SendRPC(self, remoteNode, mod, fun, args, cb):
        """Send an rpc to REMOTE-NODE, MOD, FUN, ARGS. Call CB for the answer.

        REMOTE-NODE     = string | <instance of ErlAtom>
                        The node to send the call to
        MOD             =  string | <instance of ErlAtom>
                        The module
        FUN             = string | <instance of ErlAtom>
                        The name of the function to call
        ARGS            = list(<term>)
                        The argument list
        CB              = <function(RESULT): void>
                          REMOTE-NODE = string
                          RESULT = <term>
                        A callback function to be called when the answer
                        to the rpc callback receives. The callback is called
                        with one arg: the result. Its return value is ignored.
                        If the remote node goes down during execution, the
                        callback is called with this value:
                          tuple(<ErlAtom("EXIT")>,
                                tuple(<ErlAtom("nodedown")>,
                                      <ErlAtom(<REMOTE-NODE-NAME>)>))

        Returns: void
        Throws:  <<to-be-documented>>

        Send an request to execute a function in a module on a remote node.
        As for the Send method, this method returns immediately.
        """
        if type(mod) == types.StringType:
            mod = erl_term.ErlAtom(mod)
        if type(fun) == types.StringType:
            fun = erl_term.ErlAtom(fun)

        # Handle queue of pending callbacks for the remote node
        if type(remoteNode) == types.StringType:
            remoteNodeName = remoteNode
        elif erl_term.IsErlAtom(remoteNode):
            remoteNodeName = remoteNode.atomText
        if self._pendingRPCs.has_key(remoteNodeName):
            self._pendingRPCs[remoteNodeName].append(cb)
        else:
            self._pendingRPCs[remoteNodeName] = [cb]

        # Register a nodedown-callback for this node, so
        # we can call any rpc callbacks in case the node goes down
        if not self._nodeDownSubscriptions.has_key(remoteNodeName):
            id = self._node.NodeDownSubscribe(self._NodeDown)
            self._nodeDownSubscriptions[remoteNodeName] = id

        # Now send the rpc-message
        self.Send(("rex", remoteNode),
                  (self.Self(),
                   (erl_term.ErlAtom("call"),
                    mod, fun, args, erl_term.ErlAtom("user"))))
Exemplo n.º 2
0
 def _SendMsgToRemoteNode(self, pingResult, srcPid, destNode, destPid, msg):
     """This internal routine performs the actual sending."""
     if pingResult != "pong":
         return
     destNodeName = destNode.atomText
     if destNodeName not in self._connections:
         return
     conn = self._connections[destNodeName]
     cookie = erl_term.ErlAtom("")
     if erl_term.IsErlAtom(destPid):
         ctrlMsg = (self.CTRLMSGOP_REG_SEND, srcPid, cookie, destPid)
     else:
         ctrlMsg = (self.CTRLMSGOP_SEND, cookie, destPid)
     conn.SendMsg(ctrlMsg, msg)
Exemplo n.º 3
0
    def Msg(self, sourceNodeName, msg):
        """This routine is intended to be called only from mbox's node.

        SOURCE-NODE-NAME        = string
        MSG                     = <term>

        Returns: void
        Throws:  nothing

        An incoming message
        """
        if type(msg) == tuple and \
           len(msg) == 2 and \
           erl_term.IsErlAtom(msg[0]) and \
           msg[0].atomText == "rex" and \
           len(self._pendingRPCs) > 0:
            self._RPCAnswer(sourceNodeName, msg[1])
        else:
            erl_common.Debug("REX: Unexpected msg: %s" % repr(msg))
Exemplo n.º 4
0
 def is_atom(self, t, v=None):
     return erl_term.IsErlAtom(t) and (v is None or str(t) == v)
Exemplo n.º 5
0
    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)