Esempio n. 1
0
    def put(self, item, block=True, timeout=None):
        if self.hub is getcurrent():
            if self.getters:
                getter = self.getters.popleft()
                getter.switch(item)
                return
            raise Full

        if not block:
            timeout = 0

        waiter = Waiter()
        item = (item, waiter)
        self.putters.append(item)
        timeout = Timeout.start_new(timeout, Full)
        try:
            if self.getters:
                self._schedule_unlock()
            result = waiter.get()
            assert result is waiter, "Invalid switch into Channel.put: %r" % (
                result, )
        except:
            self._discard(item)
            raise
        finally:
            timeout.cancel()
Esempio n. 2
0
    def kill(self, exception=GreenletExit, block=True, timeout=None):
        """Raise the ``exception`` in the greenlet.

        If ``block`` is ``True`` (the default), wait until the greenlet dies or the optional timeout expires.
        If block is ``False``, the current greenlet is not unscheduled.

        The function always returns ``None`` and never raises an error.

        .. note::

            Depending on what this greenlet is executing and the state of the event loop,
            the exception may or may not be raised immediately when this greenlet resumes
            execution. It may be raised an a subsequent green call, or, if this greenlet
            exits before making such a call, it may not be raised at all. As of 1.1, an example
            where the exception is raised later is if this greenlet had called ``sleep(0)``; an
            example where the exception is raised immediately is if this greenlet had called ``sleep(0.1)``.

        See also :func:`gevent.kill`.

        .. versionchanged:: 0.13.0
            *block* is now ``True`` by default.
        """
        # XXX this function should not switch out if greenlet is not started but it does
        # XXX fix it (will have to override 'dead' property of greenlet.greenlet)
        if self._start_event is None:
            self._start_event = _dummy_event
        else:
            self._start_event.stop()
        if not self.dead:
            waiter = Waiter()
            self.parent.loop.run_callback(_kill, self, exception, waiter)
            if block:
                waiter.get()
                self.join(timeout)
Esempio n. 3
0
 def peek(self, block=True, timeout=None):
     if self.qsize():
         if self.putters:
             self._schedule_unlock()
         return self._peek()
     elif not block and get_hub() is getcurrent():
         # special case to make peek(False) runnable in the mainloop
         # greenlet there are no items in the queue; try to fix the
         # situation by unlocking putters
         while self.putters:
             putter = self.putters.pop()
             if putter:
                 putter.switch(putter)
                 if self.qsize():
                     return self._peek()
         raise Empty
     elif block:
         waiter = Waiter()
         timeout = Timeout.start_new(timeout, Empty)
         try:
             self.getters.add(waiter)
             if self.putters:
                 self._schedule_unlock()
             result = waiter.get()
             assert result is waiter, "Invalid switch into Queue.put: %r" % (
                 result, )
             return self._peek()
         finally:
             self.getters.discard(waiter)
             timeout.cancel()
     else:
         raise Empty
Esempio n. 4
0
    def gethostbyname_ex(self, hostname, family=AF_INET):
        if PY3:
            if isinstance(hostname, str):
                hostname = hostname.encode('idna')
            elif not isinstance(hostname, (bytes, bytearray)):
                raise TypeError('Expected es(idna), not %s' %
                                type(hostname).__name__)
        else:
            if isinstance(hostname, text_type):
                hostname = hostname.encode('ascii')
            elif not isinstance(hostname, str):
                raise TypeError('Expected string, not %s' %
                                type(hostname).__name__)

        while True:
            ares = self.ares
            try:
                waiter = Waiter(self.hub)
                ares.gethostbyname(waiter, hostname, family)
                result = waiter.get()
                if not result[-1]:
                    raise gaierror(-5, 'No address associated with hostname')
                return result
            except gaierror:
                if ares is self.ares:
                    if hostname == b'255.255.255.255':
                        # The stdlib handles this case in 2.7 and 3.x, but ares does not.
                        # It is tested by test_socket.py in 3.4.
                        # HACK: So hardcode the expected return.
                        return ('255.255.255.255', [], ['255.255.255.255'])
                    raise
Esempio n. 5
0
    def __getnameinfo(self, hostname, port, sockaddr, flags):
        result = self.__getaddrinfo(hostname,
                                    port,
                                    family=AF_UNSPEC,
                                    socktype=SOCK_DGRAM,
                                    proto=0,
                                    flags=0,
                                    fill_in_type_proto=False)
        if len(result) != 1:
            raise error('sockaddr resolved to multiple addresses')

        family, _socktype, _proto, _name, address = result[0]

        if family == AF_INET:
            if len(sockaddr) != 2:
                raise error("IPv4 sockaddr must be 2 tuple")
        elif family == AF_INET6:
            address = address[:2] + sockaddr[2:]

        waiter = Waiter(self.hub)
        self.cares.getnameinfo(waiter, address, flags)
        node, service = waiter.get()

        if service is None and PY3:
            # ares docs: "If the query did not complete
            # successfully, or one of the values was not
            # requested, node or service will be NULL ". Python 2
            # allows that for the service, but Python 3 raises
            # an error. This is tested by test_socket in py 3.4
            err = gaierror(EAI_NONAME, self.EAI_NONAME_MSG)
            err.errno = EAI_NONAME
            raise err

        return node, service or '0'
Esempio n. 6
0
    def __get_or_peek(self, method, block, timeout):
        # Internal helper method. The `method` should be either
        # self._get when called from self.get() or self._peek when
        # called from self.peek(). Call this after the initial check
        # to see if there are items in the queue.

        if self.hub is getcurrent():
            # special case to make get_nowait() or peek_nowait() runnable in the mainloop greenlet
            # there are no items in the queue; try to fix the situation by unlocking putters
            while self.putters:
                # Note: get() used popleft(), peek used pop(); popleft
                # is almost certainly correct.
                self.putters.popleft().put_and_switch()
                if self.qsize():
                    return method()
            raise Empty()

        if not block:
            # We can't block, we're not the hub, and we have nothing
            # to return. No choice...
            raise Empty()

        waiter = Waiter()
        timeout = Timeout._start_new_or_dummy(timeout, Empty)
        try:
            self.getters.append(waiter)
            if self.putters:
                self._schedule_unlock()
            result = waiter.get()
            if result is not waiter:
                raise InvalidSwitchError('Invalid switch into Queue.get: %r' % (result, ))
            return method()
        finally:
            timeout.cancel()
            _safe_remove(self.getters, waiter)
Esempio n. 7
0
    def kill(self, exception=GreenletExit, block=True, timeout=None):
        """Raise the ``exception`` in the greenlet.

        If ``block`` is ``True`` (the default), wait until the greenlet dies or the optional timeout expires.
        If block is ``False``, the current greenlet is not unscheduled.

        The function always returns ``None`` and never raises an error.

        .. note::

            Depending on what this greenlet is executing and the state of the event loop,
            the exception may or may not be raised immediately when this greenlet resumes
            execution. It may be raised on a subsequent green call, or, if this greenlet
            exits before making such a call, it may not be raised at all. As of 1.1, an example
            where the exception is raised later is if this greenlet had called ``sleep(0)``; an
            example where the exception is raised immediately is if this greenlet had called ``sleep(0.1)``.

        See also :func:`gevent.kill`.

        .. versionchanged:: 0.13.0
            *block* is now ``True`` by default.
        .. versionchanged:: 1.1a2
            If this greenlet had never been switched to, killing it will prevent it from ever being switched to.
        """
        self.__cancel_start()

        if self.dead:
            self.__handle_death_before_start(exception)
        else:
            waiter = Waiter()
            self.parent.loop.run_callback(_kill, self, exception, waiter)
            if block:
                waiter.get()
                self.join(timeout)
Esempio n. 8
0
    def peek(self, block=True, timeout=None):
        """Return an item from the queue without removing it.

        If optional args *block* is true and *timeout* is ``None`` (the default),
        block if necessary until an item is available. If *timeout* is a positive number,
        it blocks at most *timeout* seconds and raises the :class:`Empty` exception
        if no item was available within that time. Otherwise (*block* is false), return
        an item if one is immediately available, else raise the :class:`Empty` exception
        (*timeout* is ignored in that case).
        """
        if self.qsize():
            return self._peek()
        elif self.hub is getcurrent():
            # special case to make peek(False) runnable in the mainloop greenlet
            # there are no items in the queue; try to fix the situation by unlocking putters
            while self.putters:
                self.putters.pop().put_and_switch()
                if self.qsize():
                    return self._peek()
            raise Empty
        elif block:
            waiter = Waiter()
            timeout = Timeout.start_new(timeout, Empty)
            try:
                self.getters.add(waiter)
                if self.putters:
                    self._schedule_unlock()
                result = waiter.get()
                assert result is waiter, 'Invalid switch into Queue.peek: %r' % (result, )
                return self._peek()
            finally:
                self.getters.discard(waiter)
                timeout.cancel()
        else:
            raise Empty
Esempio n. 9
0
    def _gethostbyaddr(self, ip_address):
        if PY3:
            if isinstance(ip_address, str):
                ip_address = ip_address.encode('idna')
            elif not isinstance(ip_address, (bytes, bytearray)):
                raise TypeError('Expected es(idna), not %s' %
                                type(ip_address).__name__)
        else:
            if isinstance(ip_address, text_type):
                ip_address = ip_address.encode('ascii')
            elif not isinstance(ip_address, str):
                raise TypeError('Expected string, not %s' %
                                type(ip_address).__name__)

        waiter = Waiter(self.hub)
        try:
            self.ares.gethostbyaddr(waiter, ip_address)
            return waiter.get()
        except InvalidIP:
            result = self._getaddrinfo(ip_address,
                                       None,
                                       family=AF_UNSPEC,
                                       socktype=SOCK_DGRAM)
            if not result:
                raise
            _ip_address = result[0][-1][0]
            if isinstance(_ip_address, text_type):
                _ip_address = _ip_address.encode('ascii')
            if _ip_address == ip_address:
                raise
            waiter.clear()
            self.ares.gethostbyaddr(waiter, _ip_address)
            return waiter.get()
Esempio n. 10
0
    def _http_request(self, **kwargs):
        res = super(Bucket, self)._http_request(**kwargs)

        w = Waiter()
        res.callback = lambda x: w.switch(x)
        res.errback = lambda x, c, o, b: w.throw(c, o, b)
        return w.get()
Esempio n. 11
0
def waitany(objects, timeout=None):
    waiter = Waiter()
    switch = waiter.switch

    if not objects:
        return None

    timer = None
    if timeout is not None:
        timer = core.timer(timeout, switch, _NONE)

    try:
        for obj in objects:
            obj.rawlink(switch)

        rst = waiter.get()
        return None if rst is _NONE else rst

    finally:
        timer and timer.cancel()

        for obj in objects:
            unlink = getattr(obj, 'unlink', None)
            if unlink:
                try:
                    unlink(switch)
                except:
                    import traceback
                    traceback.print_exc()
Esempio n. 12
0
    def put(self, item, block=True, timeout=None):
        if self.hub is getcurrent():
            if self.getters:
                getter = self.getters.popleft()
                getter.switch(item)
                return
            raise Full

        if not block:
            timeout = 0

        waiter = Waiter()
        item = (item, waiter)
        self.putters.append(item)
        timeout = Timeout.start_new(timeout, Full) if timeout is not None else None
        try:
            if self.getters:
                self._schedule_unlock()
            result = waiter.get()
            if result is not waiter:
                raise InvalidSwitchError("Invalid switch into Channel.put: %r" % (result, ))
        except:
            _safe_remove(self.putters, item)
            raise
        finally:
            if timeout is not None:
                timeout.cancel()
Esempio n. 13
0
    def gethostbyname_ex(self, hostname, family=AF_INET):
        if PY3:
            if isinstance(hostname, str):
                hostname = hostname.encode('idna')
            elif not isinstance(hostname, (bytes, bytearray)):
                raise TypeError('Expected es(idna), not %s' %
                                type(hostname).__name__)
        else:
            if isinstance(hostname, text_type):
                hostname = hostname.encode('ascii')
            elif not isinstance(hostname, str):
                raise TypeError('Expected string, not %s' %
                                type(hostname).__name__)

        while True:
            ares = self.ares
            try:
                waiter = Waiter(self.hub)
                ares.gethostbyname(waiter, hostname, family)
                result = waiter.get()
                if not result[-1]:
                    raise gaierror(-5, 'No address associated with hostname')
                return result
            except gaierror:
                if ares is self.ares:
                    raise
Esempio n. 14
0
    def _getnameinfo(self, sockaddr, flags):
        if not isinstance(flags, int):
            raise TypeError('an integer is required')
        if not isinstance(sockaddr, tuple):
            raise TypeError('getnameinfo() argument 1 must be a tuple')

        waiter = Waiter(self.hub)
        result = self._getaddrinfo(sockaddr[0],
                                   str(sockaddr[1]),
                                   family=AF_UNSPEC,
                                   socktype=SOCK_DGRAM)
        if not result:
            raise
        elif len(result) != 1:
            raise error('sockaddr resolved to multiple addresses')
        family, socktype, proto, name, address = result[0]

        if family == AF_INET:
            if len(sockaddr) != 2:
                raise error("IPv4 sockaddr must be 2 tuple")
        elif family == AF_INET6:
            address = address[:2] + sockaddr[2:]

        self.ares.getnameinfo(waiter, address, flags)
        node, service = waiter.get()
        if service is None:
            service = '0'
        return node, service
Esempio n. 15
0
    def test(self):
        waiter = Waiter()
        self.assertEqual(str(waiter), '<Waiter greenlet=None>')
        waiter.switch(25)
        self.assertEqual(str(waiter), '<Waiter greenlet=None value=25>')
        self.assertEqual(waiter.get(), 25)

        waiter = Waiter()
        waiter.throw(ZeroDivisionError)
        assert re.match('^<Waiter greenlet=None exc_info=.*ZeroDivisionError.*$', str(waiter)), str(waiter)
        self.assertRaises(ZeroDivisionError, waiter.get)

        waiter = Waiter()
        g = gevent.spawn(waiter.get)
        gevent.sleep(0)
        self.assertTrue(str(waiter).startswith('<Waiter greenlet=<Greenlet "Greenlet-'))

        g.kill()
Esempio n. 16
0
def killall(greenlets, exception=GreenletExit, block=True, polling_period=0.2):
    """Kill all the greenlets with exception (GreenletExit by default).
    Wait for them to die if block is true.
    """
    waiter = Waiter()
    core.active_event(_killall, greenlets, exception, waiter)
    if block:
        alive = waiter.wait()
        if alive:
            joinall(alive, polling_period=polling_period)
Esempio n. 17
0
 def __init__(self, task, pool, *args, **kwargs):
     gevent.greenlet.Greenlet.__init__(self, *args, **kwargs)
     self._pool = pool  # 所属的协程池
     self._task = task  # 当前执行的任务
     self._wait_task = Waiter()  # 在没有任务的时候,在这个waiter上面等待,用于协程的调度
     self._loop = gevent.get_hub().loop  # gevent的主loop,用于在上面注册回调
     self._last_out_time = None  # 当前协程因为业务阻塞被切换出去的时间
     self._some_time_block = False  # 用这个标志为来确定这个协程在执行任务的时候是否曾经阻塞过
     self.start()  # 进入业务循环
     self._init_short_cut()
Esempio n. 18
0
def resolve_reverse_ipv6(packed_ip, flags=0):
    """Lookup a PTR record for a given IPv6 address.
    To disable searching for this query, set *flags* to ``QUERY_NO_SEARCH``.
    """
    waiter = Waiter()
    core.dns_resolve_reverse_ipv6(packed_ip, flags, waiter.switch_args)
    result, _type, ttl, addrs = waiter.get()
    if result != core.DNS_ERR_NONE:
        raise DNSError(result)
    return ttl, addrs
Esempio n. 19
0
def kill(greenlet, exception=GreenletExit, block=True, polling_period=0.2):
    """Kill greenlet with exception (GreenletExit by default).
    Wait for it to die if block is true.
    """
    if not greenlet.dead:
        waiter = Waiter()
        core.active_event(_kill, greenlet, exception, waiter)
        if block:
            waiter.wait()
            join(greenlet, polling_period=polling_period)
Esempio n. 20
0
    def getresponse(self):
        if self.resp is None:
            self.conn.make_request(self.req, self.method, self.uri)
            assert self._waiter is None, self._waiter
            self._waiter = Waiter()
            try:
                self.resp = self._waiter.get()
            finally:
                self._waiter = None

        return self.resp
Esempio n. 21
0
def resolve_ipv6(name, flags=0):
    """Lookup an AAAA record for a given *name*.
    To disable searching for this query, set *flags* to ``QUERY_NO_SEARCH``.

    Returns (ttl, list of packed IPs).
    """
    waiter = Waiter()
    core.dns_resolve_ipv6(name, flags, waiter.switch_args)
    result, _type, ttl, addrs = waiter.get()
    if result != core.DNS_ERR_NONE:
        raise DNSError(result)
    return ttl, addrs
    def __init__(self, *args, **kwargs):
        """
        Subclass of :class:`~couchbase.async.view.AsyncViewBase`
        This doesn't expose an API different from the normal synchronous
        view API. It's just implemented differently
        """
        super(GView, self).__init__(*args, **kwargs)

        # We use __double_underscore to mangle names. This is because
        # the views class has quite a bit of data attached to it.
        self.__waiter = Waiter()
        self.__iterbufs = deque()
        self.__done_called = False
Esempio n. 23
0
 def gethostbyname_ex(self, hostname, family=AF_INET):
     while True:
         ares = self.ares
         try:
             waiter = Waiter(self.hub)
             ares.gethostbyname(waiter, hostname, family)
             result = waiter.get()
             if not result[-1]:
                 raise gaierror(-5, 'No address associated with hostname')
             return result
         except gaierror:
             if ares is self.ares:
                 raise
Esempio n. 24
0
 def perform(self):
     assert getattr(
         self._obj, 'waiter', None
     ) is None, 'This curl object is already used by another greenlet'
     waiter = self._obj.waiter = Waiter()
     try:
         self._multi.add_handle(self)
         try:
             return waiter.get()
         finally:
             self._multi.remove_handle(self)
     finally:
         del self._obj.waiter
Esempio n. 25
0
    def kill(self, exception=GreenletExit, block=False, timeout=None):
        """Raise the exception in the greenlet.

        If block is ``False`` (the default), the current greenlet is not unscheduled.
        If block is ``True``, wait until the greenlet dies or the optional timeout expires.

        Return ``None``.
        """
        if not self.dead:
            waiter = Waiter()
            core.active_event(_kill, self, exception, waiter)
            if block:
                waiter.wait()
                self.join(timeout)
Esempio n. 26
0
def resolve_reverse(packed_ip, flags=0):
    """Lookup a PTR record for a given IP address.
    To disable searching for this query, set *flags* to ``QUERY_NO_SEARCH``.

        >>> packed_ip = socket.inet_aton('82.94.164.162')
        >>> resolve_reverse(packed_ip)
        (10000, 'www.python.org')
    """
    waiter = Waiter()
    core.dns_resolve_reverse(packed_ip, flags, waiter.switch_args)
    result, _type, ttl, addr = waiter.get()
    if result != core.DNS_ERR_NONE:
        raise DNSError(result)
    return ttl, addr
Esempio n. 27
0
    def __init__(self):
        """
        Subclass of :class:`~.AsyncViewBase`
        This doesn't expose an API different from the normal
        synchronous view API. It's just implemented differently
        """

        # We use __double_underscore to mangle names. This is because
        # the views class has quite a bit of data attached to it.
        self.__waiter = Waiter()
        self.__raw_rows = []
        self.__done_called = False
        self.start()
        self.raw.rows_per_call = 100000
Esempio n. 28
0
    def _getnameinfo(self, sockaddr, flags):
        if not isinstance(flags, int):
            raise TypeError('an integer is required')
        if not isinstance(sockaddr, tuple):
            raise TypeError('getnameinfo() argument 1 must be a tuple')

        address = sockaddr[0]
        if not PY3 and isinstance(address, text_type):
            address = address.encode('ascii')

        if not isinstance(address, string_types):
            raise TypeError('sockaddr[0] must be a string, not %s' %
                            type(address).__name__)

        port = sockaddr[1]
        if not isinstance(port, int):
            raise TypeError('port must be an integer, not %s' % type(port))

        waiter = Waiter(self.hub)
        result = self._getaddrinfo(address,
                                   str(sockaddr[1]),
                                   family=AF_UNSPEC,
                                   socktype=SOCK_DGRAM)
        if not result:
            reraise(*sys.exc_info())
        elif len(result) != 1:
            raise error('sockaddr resolved to multiple addresses')
        family, _socktype, _proto, _name, address = result[0]

        if family == AF_INET:
            if len(sockaddr) != 2:
                raise error("IPv4 sockaddr must be 2 tuple")
        elif family == AF_INET6:
            address = address[:2] + sockaddr[2:]

        self.ares.getnameinfo(waiter, address, flags)
        node, service = waiter.get()

        if service is None:
            if PY3:
                # ares docs: "If the query did not complete
                # successfully, or one of the values was not
                # requested, node or service will be NULL ". Python 2
                # allows that for the service, but Python 3 raises
                # an error. This is tested by test_socket in py 3.4
                err = gaierror('nodename nor servname provided, or not known')
                err.errno = 8
                raise err
            service = '0'
        return node, service
Esempio n. 29
0
def killall(greenlets, exception=GreenletExit, block=False, timeout=None):
    if block:
        waiter = Waiter()
        core.active_event(_killall3, greenlets, exception, waiter)
        if block:
            t = Timeout.start_new(timeout)
            try:
                alive = waiter.wait()
                if alive:
                    joinall(alive, raise_error=False)
            finally:
                t.cancel()
    else:
        core.active_event(_killall, greenlets, exception)
Esempio n. 30
0
    def kill(self, exception=GreenletExit, block=True, timeout=None):
        """
        Raise the ``exception`` in the greenlet.

        If ``block`` is ``True`` (the default), wait until the greenlet dies or the optional timeout expires.
        If block is ``False``, the current greenlet is not unscheduled.

        The function always returns ``None`` and never raises an error.

        .. note::

            Depending on what this greenlet is executing and the state
            of the event loop, the exception may or may not be raised
            immediately when this greenlet resumes execution. It may
            be raised on a subsequent green call, or, if this greenlet
            exits before making such a call, it may not be raised at
            all. As of 1.1, an example where the exception is raised
            later is if this greenlet had called :func:`sleep(0)
            <gevent.sleep>`; an example where the exception is raised
            immediately is if this greenlet had called
            :func:`sleep(0.1) <gevent.sleep>`.

        .. caution::

            Use care when killing greenlets. If the code executing is not
            exception safe (e.g., makes proper use of ``finally``) then an
            unexpected exception could result in corrupted state.

        See also :func:`gevent.kill`.

        :keyword type exception: The type of exception to raise in the greenlet. The default
            is :class:`GreenletExit`, which indicates a :meth:`successful` completion
            of the greenlet.

        .. versionchanged:: 0.13.0
            *block* is now ``True`` by default.
        .. versionchanged:: 1.1a2
            If this greenlet had never been switched to, killing it will prevent it from ever being switched to.
        """
        self.__cancel_start()

        if self.dead:
            self.__handle_death_before_start(exception)
        else:
            waiter = Waiter() if block else None
            self.parent.loop.run_callback(_kill, self, exception, waiter)
            if block:
                waiter.get()
                self.join(timeout)