コード例 #1
0
ファイル: filetransfer.py プロジェクト: mmikulicic/spinoff
    def run(self, service, pub_id, file, send_to):
        self.watch(send_to)

        seek_ptr = 0

        while True:
            try:
                msg = yield with_timeout(OPEN_FILE_TIMEOUT, self.get())
            except Timeout:
                err("Sending of file at %r timed out" % (file,))
                break

            if ('next-chunk', ANY) == msg:
                service << ('touch-file', pub_id)
                _, chunk_size = msg

                chunk = yield read_file_async(file, start=seek_ptr, end=seek_ptr + chunk_size)
                seek_ptr += len(chunk)

                more_coming = len(chunk) == chunk_size

                send_to << ('chunk', chunk, more_coming)

                if not more_coming:
                    break

            elif ('terminated', send_to) == msg:
                break

            else:
                self.unhandled(msg)
コード例 #2
0
ファイル: runner.py プロジェクト: mmikulicic/spinoff
        def start_actor():
            if self._nodeid:
                Events.log(Message("Setting up remoting; node ID = %s" % (self._nodeid,)))
                try:
                    f1 = ZmqFactory()
                    insock = ZmqPullConnection(f1)
                    outsock = lambda: ZmqPushConnection(f1, linger=0)
                    hub = Hub(insock, outsock, nodeid=self._nodeid)
                except Exception:
                    err("Could not set up remoting")
                    traceback.print_exc()
                    reactor.stop()
                    return
            else:
                Events.log(Message("No remoting requested; specify `--remoting/-r <nodeid>` (nodeid=host:port) to set up remoting"))
                hub = HubWithNoRemoting()

            supervision = {'stop': Stop, 'restart': Restart, 'resume': Resume}[self._supervise]
            node = Node(hub=hub, root_supervision=supervision)

            try:
                self._wrapper = node.spawn(Wrapper.using(
                    self._actor_cls.using(**self._init_params),
                    spawn_at=self._name, keep_running=self._keep_running
                ), name='_runner')
            except Exception:
                panic("Failed to start wrapper for %s\n" % (actor_path,),
                      Failure().getTraceback())
                reactor.stop()
            else:
                if self._initial_message is not _EMPTY:
                    self._wrapper << ('_forward', self._initial_message)
コード例 #3
0
ファイル: hub.py プロジェクト: magicbill/spinoff
def naddr_to_zmq_endpoint(nid):
    if '\0' in nid:
        return None
    try:
        host, port = nid.split(':')
    except ValueError:
        return None
    try:
        return 'tcp://%s:%s' % (gethostbyname(host), port)
    except socket.gaierror as e:
        # XXX: perhaps we should retry in a few sec in case of EAI_ERRNO_TEMPORARY_FAILURE_IN_NAME_RESOLUTION?
        if e.errno not in (socket.EAI_NONAME, EAI_ERRNO_TEMPORARY_FAILURE_IN_NAME_RESOLUTION):
            err("%s\n%s" % (e, traceback.format_exc()))
    return None
コード例 #4
0
ファイル: hub.py プロジェクト: cordis/spinoff
def naddr_to_zmq_endpoint(nid):
    if '\0' in nid:
        return None
    try:
        host, port = nid.split(':')
    except ValueError:
        return None
    try:
        return 'tcp://%s:%s' % (gethostbyname(host), port)
    except socket.gaierror as e:
        # XXX: perhaps we should retry in a few sec in case of EAI_ERRNO_TEMPORARY_FAILURE_IN_NAME_RESOLUTION?
        if e.errno not in (socket.EAI_NONAME,
                           EAI_ERRNO_TEMPORARY_FAILURE_IN_NAME_RESOLUTION):
            err("%s\n%s" % (e, traceback.format_exc()))
    return None
コード例 #5
0
ファイル: events.py プロジェクト: mmikulicic/spinoff
    def log(self, event, log_caller=False):
        try:
            (fail if isinstance(event, Error) else log)(event, caller=log_caller)

            consumers = self.consumers.get(type(event))
            if consumers:
                consumer_d = consumers.pop(0)
                consumer_d.callback(event)
                return

            subscriptions = self.subscriptions.get(type(event))
            if subscriptions:
                for fn in subscriptions:
                    try:
                        fn(event)
                    except Exception:  # pragma: no cover
                        err("Error in event handler:\n", traceback.format_exc())
        except Exception:  # pragma: no cover
            print("Events.log failed:\n", traceback.format_exc(), file=sys.stderr)
コード例 #6
0
ファイル: server.py プロジェクト: magicbill/spinoff
 def receive(self, msg):
     if ('serve', ANY, ANY) == msg:
         _, file_path, file_id = msg
         if not os.path.exists(file_path) and not os.path.isdir(file_path):
             err("attempt to publish a file that does not exist")
         elif file_id in self.published:
             err("Attempt to publish %r with ID %r but a file already exists with that ID" % (file_path, file_id))
         else:
             self.published[file_id] = (file_path, datetime.datetime.now())
     elif msg == ('request', ANY) or msg == ('request-local', ANY):
         request, file_id = msg
         if file_id not in self.published:
             err("attempt to get a file with ID %r which has not been published or is not available anymore" % (file_id,))
         else:
             file_path, time_added = self.published[file_id]
             if request == 'request-local':
                 self._touch_file(file_id)
                 self.reply(('local-file', file_path))
             else:
                 response = self.spawn(Response.using(file=file_path, request=self.sender, threadpool=self.threadpool))
                 self.watch(response)
                 self.responses[response] = file_id
     elif 'purge-old' == msg:
         self.send_later(60, 'purge-old')
         t = datetime.datetime.now()
         for file_id, (file_path, time_added) in self.published.items():
             if (t - time_added).total_seconds() > constants.FILE_MAX_LIFETIME and file_id not in self.responses.values():
                 dbg("purging file %r at %r" % (file_id, file_path))
                 del self.published[file_id]
     elif ('terminated', IN(self.responses)) == msg:
         _, sender = msg
         self._touch_file(file_id=self.responses.pop(sender))
コード例 #7
0
    def log(self, event, log_caller=False):
        try:
            (fail if isinstance(event, Error) else log)(event,
                                                        caller=log_caller)

            consumers = self.consumers.get(type(event))
            if consumers:
                consumer_d = consumers.pop(0)
                consumer_d.set(event)
                return

            subscriptions = self.subscriptions.get(type(event))
            if subscriptions:
                for fn in subscriptions:
                    try:
                        fn(event)
                    except Exception:  # pragma: no cover
                        err("Error in event handler:\n",
                            traceback.format_exc())
        except Exception:  # pragma: no cover
            print("Events.log failed:\n",
                  traceback.format_exc(),
                  file=sys.stderr)
コード例 #8
0
ファイル: filetransfer.py プロジェクト: mmikulicic/spinoff
    def receive(self, msg):
        if ('publish', ANY, ANY) == msg:
            _, file_path, pub_id = msg
            if not os.path.exists(file_path) and not os.path.isdir(file_path):
                err("attempt to publish a file that does not exist")
                return

            if pub_id in self.published:
                raise FileAlreadyPublished("Attempt to publish %r with ID %r but a file already exists with that ID" % (file_path, pub_id))
            else:
                self.published[pub_id] = (file_path, datetime.datetime.now())

        elif ('get-file', ANY, ANY) == msg:
            _, pub_id, send_to = msg

            if pub_id not in self.published:
                err("attempt to get a file with ID %r which has not been published or is not available anymore" % (pub_id,))
                return

            self._touch_file(pub_id)

            file_path, time_added = self.published[pub_id]
            sender = self.watch(_Sender.using(service=self.ref, pub_id=pub_id, file=file_path, send_to=send_to))
            self.senders[sender] = pub_id
            # self.senders[sender] = pub_id
            send_to << ('take-file', sender)

        elif ('touch-file', ANY) == msg:
            _, pub_id = msg
            if pub_id not in self.published:
                err("attempt to touch a file with ID %r which has not been published or is not available anymore" % (pub_id,))
                return
            _, pub_id = msg
            self._touch_file(pub_id)

        elif 'purge-old' == msg:
            after(60.0).do(self.send, 'purge-old')

            t = datetime.datetime.now()

            for pub_id, (file_path, time_added) in self.published.items():
                if (t - time_added).total_seconds() > FILE_MAX_LIFETIME and pub_id not in self.senders.values():
                    dbg("purging file %r at %r" % (pub_id, file_path))
                    del self.published[pub_id]

        elif ('terminated', IN(self.senders)) == msg:
            _, sender = msg
            del self.senders[sender]
コード例 #9
0
ファイル: server.py プロジェクト: cordis/spinoff
 def receive(self, msg):
     if ('serve', ANY, ANY) == msg:
         _, file_path, file_id = msg
         if not os.path.exists(file_path) and not os.path.isdir(file_path):
             err("attempt to publish a file that does not exist")
         elif file_id in self.published:
             err("Attempt to publish %r with ID %r but a file already exists with that ID" % (file_path, file_id))
         else:
             self.published[file_id] = (file_path, datetime.datetime.now())
     elif msg == ('request', ANY) or msg == ('request-local', ANY):
         request, file_id = msg
         if file_id not in self.published:
             # TODO: replace with a reply to the requestor, just like in the upload() case
             err("attempt to get a file with ID %r which has not been published or is not available anymore" % (file_id,))
         else:
             file_path, time_added = self.published[file_id]
             if request == 'request-local':
                 self._touch_file(file_id)
                 self.reply(('local-file', file_path))
             else:
                 response = self.spawn(Response.using(file=file_path, request=self.sender, threadpool=self.threadpool))
                 self.watch(response)
                 self.responses[response] = file_id
     elif 'purge-old' == msg:
         self.send_later(60, 'purge-old')
         t = datetime.datetime.now()
         for file_id, (file_path, time_added) in self.published.items():
             if (t - time_added).total_seconds() > constants.FILE_MAX_LIFETIME and file_id not in self.responses.values():
                 dbg("purging file %r at %r" % (file_id, file_path))
                 del self.published[file_id]
     elif ('terminated', IN(self.responses)) == msg:
         _, sender = msg
         self._touch_file(file_id=self.responses.pop(sender))
     elif ('upload', ANY, ANY, ANY, ANY) == msg:
         _, file_id, url, method, expect_response = msg
         if method not in ('POST', 'PUT'):
             self.reply((False, ('bad-method', None)))
         if file_id not in self.published:
             self.reply((False, ('file-not-found', None)))
         else:
             self._touch_file(file_id)
             file_path, _ = self.published[file_id]
             upload = requests.post if method == 'POST' else requests.put
             try:
                 r = upload(url, files={'file': open(file_path, 'rb')})
             except Exception as e:
                 self.reply((False, ('exception', (type(e).__name__, e.message, traceback.format_exc()))))
             else:
                 if r.status_code != expect_response:
                     self.reply((False, ('bad-status-code', r.status_code)))
                 else:
                     self.reply((True, (r.status_code, dict(r.headers), r.text)))
     elif ('delete', ANY) == msg:
         _, file_id = msg
         if file_id not in self.published:
             self.reply((False, ('file-not-found', None)))
         else:
             file_path, _ = self.published[file_id]
             del self.published[file_id]
             try:
                 os.unlink(file_path)
             except BaseException as e:
                 self.reply((False, ('exception', (type(e).__name__, e.message, traceback.format_exc()))))
             else:
                 self.reply((True, None))
コード例 #10
0
ファイル: spin.py プロジェクト: cordis/spinoff
def console():
    class _ImportFailed(Exception):
        pass

    class _InitError(Exception):
        pass

    argparser = argparse.ArgumentParser(
        description="Runs the specified actor",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    argparser.add_argument('actor', metavar='ACTOR',
                           help="The actor to run")
    argparser.add_argument('-using', '--using', metavar='USING', default={},
                           help="Parameters to pass to the actor")
    argparser.add_argument('-msg', '--initial-message', metavar='MSG', nargs='*', default=[],
                           help="Messages to send to the actor. Specify multiple times to send multiple messages. These must be valid Python expressions")
    argparser.add_argument('-keep', '--keep-running', action='store_true',
                           help="Whether to respawn the actor when it terminates")
    argparser.add_argument('-name', '--name', metavar='NAME',
                           help="What to name the actor")
    argparser.add_argument('-nid', '--node-id', metavar='NODEID',
                           help="What to name the actor")
    argparser.add_argument('-relay', '--enable-relay', metavar='RELAY',
                           help="What to name the actor")

    args = argparser.parse_args()

    # where the spin command was invoked
    sys.path.insert(0, os.getcwd())

    try:
        if '.' not in args.actor:
            raise _InitError("Failed to import %s" % (args.actor,))
            sys.exit(1)
        else:
            mod_name, cls_name = args.actor.rsplit('.', 1)
            mod = __import__(mod_name, fromlist=[cls_name])
            actor_cls = getattr(mod, cls_name)

        eval_str = 'dict(%s)' % (args.using,)
        try:
            init_params = eval(eval_str)
        except Exception:
            raise _InitError("Failed to parse value: -init/--init-params")

        initial_messages = []
        for msg_raw in args.initial_message:
            try:
                msg = eval(msg_raw)
            except Exception:
                quote = '\'' if '"' in msg_raw else '"'
                raise _InitError("Failde to parse value: -msg %s%s%s" % (quote, msg_raw, quote))
            else:
                initial_messages.append(msg)
    except _InitError as exc:
        err(exc.args[0])
        sys.exit(exc.args[1] if len(exc.args) > 1 else 1)

    spin(actor_cls, name=args.name, init_params=init_params, node_id=args.node_id,
         initial_messages=initial_messages, keep_running=args.keep_running, enable_relay=args.enable_relay)
コード例 #11
0
ファイル: spin.py プロジェクト: cordis/spinoff
def console():
    class _ImportFailed(Exception):
        pass

    class _InitError(Exception):
        pass

    argparser = argparse.ArgumentParser(
        description="Runs the specified actor",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    argparser.add_argument('actor', metavar='ACTOR', help="The actor to run")
    argparser.add_argument('-using',
                           '--using',
                           metavar='USING',
                           default={},
                           help="Parameters to pass to the actor")
    argparser.add_argument(
        '-msg',
        '--initial-message',
        metavar='MSG',
        nargs='*',
        default=[],
        help=
        "Messages to send to the actor. Specify multiple times to send multiple messages. These must be valid Python expressions"
    )
    argparser.add_argument(
        '-keep',
        '--keep-running',
        action='store_true',
        help="Whether to respawn the actor when it terminates")
    argparser.add_argument('-name',
                           '--name',
                           metavar='NAME',
                           help="What to name the actor")
    argparser.add_argument('-nid',
                           '--node-id',
                           metavar='NODEID',
                           help="What to name the actor")
    argparser.add_argument('-relay',
                           '--enable-relay',
                           metavar='RELAY',
                           help="What to name the actor")

    args = argparser.parse_args()

    # where the spin command was invoked
    sys.path.insert(0, os.getcwd())

    try:
        if '.' not in args.actor:
            raise _InitError("Failed to import %s" % (args.actor, ))
            sys.exit(1)
        else:
            mod_name, cls_name = args.actor.rsplit('.', 1)
            mod = __import__(mod_name, fromlist=[cls_name])
            actor_cls = getattr(mod, cls_name)

        eval_str = 'dict(%s)' % (args.using, )
        try:
            init_params = eval(eval_str)
        except Exception:
            raise _InitError("Failed to parse value: -init/--init-params")

        initial_messages = []
        for msg_raw in args.initial_message:
            try:
                msg = eval(msg_raw)
            except Exception:
                quote = '\'' if '"' in msg_raw else '"'
                raise _InitError("Failde to parse value: -msg %s%s%s" %
                                 (quote, msg_raw, quote))
            else:
                initial_messages.append(msg)
    except _InitError as exc:
        err(exc.args[0])
        sys.exit(exc.args[1] if len(exc.args) > 1 else 1)

    spin(actor_cls,
         name=args.name,
         init_params=init_params,
         node_id=args.node_id,
         initial_messages=initial_messages,
         keep_running=args.keep_running,
         enable_relay=args.enable_relay)