コード例 #1
0
ファイル: intsup.py プロジェクト: ask/cyme
class gSup(gThread):

    def __init__(self, thread, signal, interval=5, timeout=600):
        self.thread = thread
        self.interval = interval
        self.timeout = timeout
        self.signal = signal
        super(gSup, self).__init__()

    def start_wait_child(self):
        self._ready_event = Event()
        self.signal.connect(self._on_thread_ready, sender=self.thread)
        self.thread.start()
        self._ready_event.wait()
        assert self._ready_event.ready()
        return self.thread

    def _on_thread_ready(self, **kwargs):
        self._ready_event.send(1)
        self.signal.disconnect(self._on_thread_ready)

    def run(self):
        self.debug("starting")
        interval = self.interval
        thread = self.start_wait_child()
        self.info("started")
        timeout = self.timeout
        critical = self.critical

        while not self.should_stop:
            try:
                pong = thread.ping(timeout)
            except (self.Timeout, Exception), exc:
                critical(SUP_ERROR_PING_TIMEOUT % (exc, ))
                _exit(0)
            if not pong:
                critical(SUP_ERROR_NOT_STARTED)
                _exit(0)
            sleep(interval)
コード例 #2
0
ファイル: __init__.py プロジェクト: fish2000/cyme
class Branch(gThread):
    controller_cls = '.controller.Controller'
    httpd_cls = '.httpd.HttpServer'
    supervisor_cls = '.supervisor.Supervisor'
    intsup_cls = '.intsup.gSup'

    _components_ready = {}
    _components_shutdown = {}
    _presence_ready = 0
    _ready = False

    def __init__(self, addrport='', id=None, loglevel=logging.INFO,
            logfile=None, without_httpd=False, numc=2, sup_interval=None,
            ready_event=None, colored=None, **kwargs):
        self.id = id or gen_unique_id()
        if isinstance(addrport, basestring):
            addr, _, port = addrport.partition(':')
            addrport = (addr, int(port) if port else 8000)
        self.addrport = addrport
        self.connection = celery.broker_connection()
        self.without_httpd = without_httpd
        self.logfile = logfile
        self.loglevel = loglevel
        self.numc = numc
        self.ready_event = ready_event
        self.exit_request = Event()
        self.colored = colored or term.colored(enabled=False)
        self.httpd = None
        gSup = find_symbol(self, self.intsup_cls)
        if not self.without_httpd:
            self.httpd = MockSup(instantiate(self, self.httpd_cls, addrport),
                              signals.httpd_ready)
        self.supervisor = gSup(instantiate(self, self.supervisor_cls,
                                sup_interval), signals.supervisor_ready)
        self.controllers = [gSup(instantiate(self, self.controller_cls,
                                   id='%s.%s' % (self.id, i),
                                   connection=self.connection,
                                   branch=self),
                                 signals.controller_ready)
                                for i in xrange(1, numc + 1)]
        c = [self.supervisor] + self.controllers + [self.httpd]
        c = self.components = list(filter(None, c))
        self._components_ready = dict(zip([z.thread for z in c],
                                          [False] * len(c)))
        for controller in self.controllers:
            if hasattr(controller.thread, 'presence'):
                self._components_ready[controller.thread.presence] = False
        self._components_shutdown = dict(self._components_ready)
        super(Branch, self).__init__()

    def _component_ready(self, sender=None, **kwargs):
        if not self._ready:
            self._components_ready[sender] = True
            if all(self._components_ready.values()):
                signals.branch_ready.send(sender=self)
                if self.ready_event:
                    self.ready_event.send()
                    self.ready_event = None
                self._ready = True

    def on_ready(self, **kwargs):
        pass

    def prepare_signals(self):
        signals.controller_ready.connect(self._component_ready)
        signals.httpd_ready.connect(self._component_ready)
        signals.supervisor_ready.connect(self._component_ready)
        signals.presence_ready.connect(self._component_ready)
        signals.branch_ready.connect(self.on_ready)
        signals.thread_post_shutdown.connect(self._component_shutdown)

    def run(self):
        state.is_branch = True
        signals.branch_startup_request.send(sender=self)
        self.prepare_signals()
        self.info('Starting with id %r', self.id)
        [g.start() for g in self.components]
        self.exit_request.wait()

    def stop(self):
        self.exit_request.send(1)
        super(Branch, self).stop()

    def after(self):
        for component in reversed(self.components):
            if self._components_ready[component.thread]:
                try:
                    component.stop()
                except KeyboardInterrupt:
                    pass
                except BaseException, exc:
                    component.error('Error in shutdown: %r', exc)
コード例 #3
0
ファイル: thread.py プロジェクト: fish2000/cyme
class gThread(LogMixin):
    AlreadyStarted = AlreadyStartedError
    Timeout = Timeout

    #: Name of the thread, used in logs and such.
    name = None

    #: Greenlet instance of the thread, set when the thread is started.
    g = None

    #: Set when the thread is requested to stop.
    should_stop = False

    #: Set this to False if it is not possible to join the thread.
    joinable = True

    _exit_event = None
    _ping_queue = None
    _timers = None
    extra_startup_steps = 0
    extra_shutdown_steps = 0

    def __init__(self):
        self.name = self.name or self.__class__.__name__
        # the exit event is sent when the thread exits,
        # and used by `join` to detect this.
        self._exit_event = Event()

        # we maintain a list of timers started by the thread,
        # so these can be cancelled at shutdown.
        self._timers = []

    def before(self):
        """Called at the beginning of :meth:`start`."""
        pass

    def run(self):
        raise NotImplementedError("gThreads must implement 'run'")

    def after(self):
        """Call after the thread has shut down."""
        pass

    def start_periodic_timer(self, interval, fun, *args, **kwargs):
        """Apply function every ``interval`` seconds.

        :param interval: Interval in seconds (int/float).
        :param fun: The function to apply.
        :param \*args: Additional arguments to pass.
        :keyword \*\*kwargs: Additional keyword arguments to pass.

        :returns: entry object, with ``cancel`` and ``kill`` methods.

        """
        entry = timer(interval, fun, *args, **kwargs)
        self._timers.append(entry)
        return entry

    def start(self):
        """Spawn green thread, and returns
        :class:`~eventlet.greenthread.GreenThread` instance."""
        if self.g is None:
            self.before()
            signals.thread_pre_start.send(sender=self)
            self._ping_queue = Queue()
            g = self.g = self.spawn(self._crashsafe, self.run)
            g.link(self._on_exit)
            self.debug('%s spawned', self.name)
            signals.thread_post_start.send(sender=self)
            return g
        raise self.AlreadyStarted('cannot start thread twice')

    def stop(self, join=True, timeout=1e100):
        """Shutdown the thread.

        This will also cancel+kill any periodic timers registered
        by the thread.

        :keyword join: Given that the thread is :attr:`joinable`, if
            true will also wait until the thread exits
            (by calling :meth:`join`).
        :keyword timeout: Timeout for join (default is 1e+100).

        """
        self.debug('shutdown initiated')
        signals.thread_pre_shutdown.send(sender=self)
        self.should_stop = True
        for entry in self._timers:
            self.debug('killing timer %r' % (entry, ))
            entry.cancel()
            entry.kill()
        if join and self.joinable:
            try:
                self.join(timeout)
            except self.Timeout:
                self.error(
                    'exceeded exit timeout (%s), will try to kill', timeout)
                self.kill()
        self.after()
        signals.thread_post_shutdown.send(sender=self)

    def join(self, timeout=None):
        """Wait until the thread exits.

        :keyword timeout: Timeout in seconds (int/float).

        :raises eventlet.Timeout: if the thread can't be joined
            before the provided timeout.


        """
        with self.Timeout(timeout):
            signals.thread_pre_join.send(sender=self, timeout=timeout)
            self.debug('joining (%s)', timeout)
            self._exit_event.wait()
            signals.thread_post_join.send(sender=self)

    def respond_to_ping(self):
        try:
            self._ping_queue.get_nowait().send()
        except Empty:
            pass

    def _do_ping(self, timeout=None):
        with self.Timeout(timeout):
            event = Event()
            self._ping_queue.put_nowait(event)
            event.wait()
            return event.ready()

    def ping(self, timeout=None):
        if self.g and self._ping_queue is not None:
            return self._do_ping(timeout)
        return False

    def _on_exit(self, g):
        # called when the thread exits to unblock `join`.
        self._exit_event.send()

    def kill(self):
        """Kill the green thread."""
        if self.g is not None:
            self.g.kill()

    def _crashsafe(self, fun, *args, **kwargs):
        try:
            fun(*args, **kwargs)
            signals.thread_exit.send(sender=self)
            self.debug('exiting')
        except Exception, exc:
            self.error('Thread crash detected: %r', exc)
            os._exit(0)
        except self.Timeout, exc:
            self.error('Thread raised timeout: %r', exc)
            os._exit(0)
コード例 #4
0
ファイル: thread.py プロジェクト: fish2000/cyme
 def _do_ping(self, timeout=None):
     with self.Timeout(timeout):
         event = Event()
         self._ping_queue.put_nowait(event)
         event.wait()
         return event.ready()