Beispiel #1
0
 def __init__(self,
              nid=None,
              enable_remoting=False,
              enable_relay=False,
              hub_kwargs={}):
     self.nid = nid
     self._uri = Uri(name=None, parent=None, node=nid)
     self.guardian = Guardian(uri=self._uri, node=self)
     self._hub = (HubWithNoRemoting() if not enable_remoting else Hub(
         nid,
         enable_relay,
         on_node_down=lambda ref, nid: ref << ('_node_down', nid),
         on_receive=self._on_receive,
         **hub_kwargs))
Beispiel #2
0
 def __init__(self, nid=None, enable_remoting=False, enable_relay=False, hub_kwargs={}):
     self.nid = nid
     self._uri = Uri(name=None, parent=None, node=nid)
     self.guardian = Guardian(uri=self._uri, node=self)
     self._hub = (
         HubWithNoRemoting() if not enable_remoting else
         Hub(nid, enable_relay, on_node_down=lambda ref, nid: ref << ('_node_down', nid), on_receive=self._on_receive, **hub_kwargs)
     )
Beispiel #3
0
class Node(object):
    """`Node` is both a singleton instance and a class lookalike, there is thus always available a default global
    `Node` instance but it is possible to create more, non-default, instances of `Node` by simply calling it as if it
    were a class, i.e. using it as a class. This is mainly useful for testing multi-node scenarios without any network
    involved by setting a custom `remoting.Hub` to the `Node`.

    """
    _hub = None

    def __init__(self,
                 nid=None,
                 enable_remoting=False,
                 enable_relay=False,
                 hub_kwargs={}):
        self.nid = nid
        self._uri = Uri(name=None, parent=None, node=nid)
        self.guardian = Guardian(uri=self._uri, node=self)
        self._hub = (HubWithNoRemoting() if not enable_remoting else Hub(
            nid,
            enable_relay,
            on_node_down=lambda ref, nid: ref << ('_node_down', nid),
            on_receive=self._on_receive,
            **hub_kwargs))

    def lookup_str(self, addr):
        if not isinstance(addr, str):
            raise TypeError("%s.lookup_str expects a str" %
                            type(self).__name__)  # pragma: no cover
        return self.lookup(Uri.parse(addr))

    def lookup(self, uri):
        if not uri.node or uri.node == self._uri.node:
            try:
                return self.guardian.lookup_ref(uri)
            except LookupFailed if uri.node else None:
                # for remote lookups that actually try to look up something on the local node, we don't want to raise an
                # exception because the caller might not be statically aware of the localness of the `Uri`, thus we
                # return a mere dead ref:
                return Ref(cell=None, uri=uri, is_local=True)
        elif not uri.root:  # pragma: no cover
            raise TypeError(
                "Node can't look up a relative Uri; did you mean Node.guardian.lookup(%r)?"
                % (uri, ))
        else:
            return Ref(cell=None, uri=uri, node=self, is_local=False)

    def spawn(self, *args, **kwargs):
        if not self.guardian:
            raise RuntimeError("Node already stopped")
        return self.guardian.spawn_actor(*args, **kwargs)

    def send_message(self, message, remote_ref, sender):
        self._hub.send_message(remote_ref.uri.node,
                               _Msg(remote_ref, message, sender))

    def watch_node(self, nid, watcher):
        self._hub.watch_node(nid, watcher)

    def unwatch_node(self, nid, watcher):
        self._hub.unwatch_node(nid, watcher)

    def _on_receive(self, sender_nid, msg_bytes):
        pickler = IncomingMessageUnpickler(self, StringIO(msg_bytes))
        try:
            loaded = pickler.load()
        except Exception:
            return  # malformed input

        try:
            local_path, message, sender = loaded
        except Exception:
            return  # malformed input

        cell = self.guardian.lookup_cell(Uri.parse(local_path))
        if not cell:
            if ('_watched', ANY) == message:
                watched_ref = Ref(cell=None,
                                  node=self,
                                  uri=Uri.parse(self.nid + local_path),
                                  is_local=True)
                _, watcher = message
                watcher << ('terminated', watched_ref)
            elif message in (('terminated', ANY), ('_watched', ANY),
                             ('_unwatched', ANY)):
                pass
            else:
                self._remote_dead_letter(local_path, message, sender)
        else:
            cell.receive(message, sender)

    def _remote_dead_letter(self, path, msg, sender):
        ref = Ref(cell=None,
                  uri=Uri.parse(self.nid + path),
                  node=self,
                  is_local=True)
        if not (msg == ('_unwatched', ANY) or msg == ('_watched', ANY)):
            Events.log(DeadLetter(ref, msg, sender))

    def stop(self):
        if getattr(self, 'guardian', None):
            self.guardian.stop()
            self.guardian = None
        if getattr(self, '_hub', None):
            self._hub.stop()
            self._hub = None
        self.stop = lambda: None
        self.send_message = lambda message, remote_ref: None
        self.watch_node = lambda nid, watcher: None
        self.unwatch_node = lambda nid, watcher: None

    def __getstate__(self):  # pragma: no cover
        raise PicklingError("Node cannot be serialized")

    def __repr__(self):
        return '<node:%s>' % (self._uri if self._hub else 'local')
Beispiel #4
0
class Node(object):
    """`Node` is both a singleton instance and a class lookalike, there is thus always available a default global
    `Node` instance but it is possible to create more, non-default, instances of `Node` by simply calling it as if it
    were a class, i.e. using it as a class. This is mainly useful for testing multi-node scenarios without any network
    involved by setting a custom `remoting.Hub` to the `Node`.

    """
    _hub = None

    def __init__(self, nid=None, enable_remoting=False, enable_relay=False, hub_kwargs={}):
        self.nid = nid
        self._uri = Uri(name=None, parent=None, node=nid)
        self.guardian = Guardian(uri=self._uri, node=self)
        self._hub = (
            HubWithNoRemoting() if not enable_remoting else
            Hub(nid, enable_relay, on_node_down=lambda ref, nid: ref << ('_node_down', nid), on_receive=self._on_receive, **hub_kwargs)
        )

    def lookup_str(self, addr):
        if not isinstance(addr, str):
            raise TypeError("%s.lookup_str expects a str" % type(self).__name__)  # pragma: no cover
        return self.lookup(Uri.parse(addr))

    def lookup(self, uri):
        if not uri.node or uri.node == self._uri.node:
            try:
                return self.guardian.lookup_ref(uri)
            except LookupFailed if uri.node else None:
                # for remote lookups that actually try to look up something on the local node, we don't want to raise an
                # exception because the caller might not be statically aware of the localness of the `Uri`, thus we
                # return a mere dead ref:
                return Ref(cell=None, uri=uri, is_local=True)
        elif not uri.root:  # pragma: no cover
            raise TypeError("Node can't look up a relative Uri; did you mean Node.guardian.lookup(%r)?" % (uri,))
        else:
            return Ref(cell=None, uri=uri, node=self, is_local=False)

    def spawn(self, *args, **kwargs):
        if not self.guardian:
            raise RuntimeError("Node already stopped")
        return self.guardian.spawn_actor(*args, **kwargs)

    def send_message(self, message, remote_ref, sender):
        self._hub.send_message(remote_ref.uri.node, _Msg(remote_ref, message, sender))

    def watch_node(self, nid, watcher):
        self._hub.watch_node(nid, watcher)

    def unwatch_node(self, nid, watcher):
        self._hub.unwatch_node(nid, watcher)

    def _on_receive(self, sender_nid, msg_bytes):
        pickler = IncomingMessageUnpickler(self, StringIO(msg_bytes))
        try:
            loaded = pickler.load()
        except Exception:
            return  # malformed input

        try:
            local_path, message, sender = loaded
        except Exception:
            return  # malformed input

        cell = self.guardian.lookup_cell(Uri.parse(local_path))
        if not cell:
            if ('_watched', ANY) == message:
                watched_ref = Ref(cell=None, node=self, uri=Uri.parse(self.nid + local_path), is_local=True)
                _, watcher = message
                watcher << ('terminated', watched_ref)
            elif message in (('terminated', ANY), ('_watched', ANY), ('_unwatched', ANY)):
                pass
            else:
                self._remote_dead_letter(local_path, message, sender)
        else:
            cell.receive(message, sender)

    def _remote_dead_letter(self, path, msg, sender):
        ref = Ref(cell=None, uri=Uri.parse(self.nid + path), node=self, is_local=True)
        if not (msg == ('_unwatched', ANY) or msg == ('_watched', ANY)):
            Events.log(DeadLetter(ref, msg, sender))

    def stop(self):
        if getattr(self, 'guardian', None):
            self.guardian.stop()
            self.guardian = None
        if getattr(self, '_hub', None):
            self._hub.stop()
            self._hub = None
        self.stop = lambda: None
        self.send_message = lambda message, remote_ref: None
        self.watch_node = lambda nid, watcher: None
        self.unwatch_node = lambda nid, watcher: None

    def __getstate__(self):  # pragma: no cover
        raise PicklingError("Node cannot be serialized")

    def __repr__(self):
        return '<node:%s>' % (self._uri if self._hub else 'local')