Ejemplo n.º 1
0
    def __init__(self, *args, **kwargs):
        guv.hubs.get_hub()

        super().__init__(*args, **kwargs)

        self.connected_event = TEvent()
        self._write_queue = Queue()

        self._callbacks = {}
        self._push_watchers = defaultdict(set)

        sockerr = None
        addresses = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM)
        for (af, socktype, proto, canonname, sockaddr) in addresses:
            try:
                self._socket = socket.socket(af, socktype, proto)
                if self.ssl_options:
                    self._socket = ssl.wrap_socket(self._socket, **self.ssl_options)
                self._socket.settimeout(1.0)
                self._socket.connect(sockaddr)
                sockerr = None
                break
            except socket.error as err:
                sockerr = err
        if sockerr:
            msg = 'Tried connecting to {}. Last error: {}'.format([a[4] for a in addresses],
                                                                  sockerr.strerror)
            raise socket.error(sockerr.errno, msg)

        if self.sockopts:
            for args in self.sockopts:
                self._socket.setsockopt(*args)

        self._read_watcher = guv.spawn(self.handle_read)
        self._write_watcher = guv.spawn(self.handle_write)
        self._send_options_message()

        log.debug('Create Cassandra GuvConnection ({})'.format(id(self)))
Ejemplo n.º 2
0
class GuvConnection(Connection):
    """
    An implementation of :class:`.Connection` that utilizes ``guv``.
    """

    _total_reqd_bytes = 0
    _read_watcher = None
    _write_watcher = None
    _socket = None

    @classmethod
    def factory(cls, *args, **kwargs):
        timeout = kwargs.pop('timeout', 5.0)
        conn = cls(*args, **kwargs)
        conn.connected_event.wait(timeout)
        if conn.last_error:
            raise conn.last_error
        elif not conn.connected_event.is_set():
            conn.close()
            raise OperationTimedOut('Timed out creating connection')
        else:
            return conn

    def __init__(self, *args, **kwargs):
        guv.hubs.get_hub()

        super().__init__(*args, **kwargs)

        self.connected_event = TEvent()
        self._write_queue = Queue()

        self._callbacks = {}
        self._push_watchers = defaultdict(set)

        sockerr = None
        addresses = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM)
        for (af, socktype, proto, canonname, sockaddr) in addresses:
            try:
                self._socket = socket.socket(af, socktype, proto)
                if self.ssl_options:
                    self._socket = ssl.wrap_socket(self._socket, **self.ssl_options)
                self._socket.settimeout(1.0)
                self._socket.connect(sockaddr)
                sockerr = None
                break
            except socket.error as err:
                sockerr = err
        if sockerr:
            msg = 'Tried connecting to {}. Last error: {}'.format([a[4] for a in addresses],
                                                                  sockerr.strerror)
            raise socket.error(sockerr.errno, msg)

        if self.sockopts:
            for args in self.sockopts:
                self._socket.setsockopt(*args)

        self._read_watcher = guv.spawn(self.handle_read)
        self._write_watcher = guv.spawn(self.handle_write)
        self._send_options_message()

        log.debug('Create Cassandra GuvConnection ({})'.format(id(self)))

    def close(self):
        with self.lock:
            if self.is_closed:
                return
            self.is_closed = True

        log.debug('Closing connection (%s) to %s' % (id(self), self.host))
        if self._read_watcher:
            self._read_watcher.kill()
        if self._write_watcher:
            self._write_watcher.kill()
        if self._socket:
            self._socket.close()
        log.debug('Closed socket to %s' % (self.host,))

        if not self.is_defunct:
            self.error_all_callbacks(ConnectionShutdown('Connection to %s was closed' % self.host))
            # don't leave in-progress operations hanging
            self.connected_event.set()

    def handle_close(self):
        log.debug('connection closed by server')
        self.close()

    def handle_write(self):
        while True:
            try:
                next_msg = self._write_queue.get()
                # FIXME: trampoline with WRITE here causes a core dump (why???)
                # python: src/unix/core.c:823: uv__io_stop: Assertion `loop->watchers[w->fd] ==
                # w' failed.
                # [1]    9736 abort (core dumped)  python cassandra_db.py
                # log.debug('Trampoline on fd: {}, WRITE'.format(self._socket.fileno()))
                # trampoline(self._socket.fileno(), WRITE)
            except Exception as e:
                if not self.is_closed:
                    log.debug('Exception during write trampoline() for %s: %s', self, e)
                    self.defunct(e)
                return

            try:
                self._socket.sendall(next_msg)
            except socket.error as err:
                log.debug('Exception during socket sendall for %s: %s', self, err)
                self.defunct(err)
                return  # leave the write loop

    def handle_read(self):
        while True:
            try:
                log.debug('Trampoline on fd: {}, READ'.format(self._socket.fileno()))
                trampoline(self._socket.fileno(), READ)
            except Exception as exc:
                if not self.is_closed:
                    log.debug("Exception during read trampoline() for %s: %s", self, exc)
                    self.defunct(exc)
                    return

            try:
                while True:
                    buf = self._socket.recv(self.in_buffer_size)
                    self._iobuf.write(buf)
                    if len(buf) < self.in_buffer_size:
                        break
            except socket.error as err:
                if not get_errno(err) in CONNECT_ERR:
                    log.debug('Exception during socket recv for %s: %s', self, err)
                    self.defunct(err)
                    return  # leave the read loop

            if self._iobuf.tell():
                self.process_io_buffer()
            else:
                log.debug('Connection %s closed by server', self)
                self.close()
                return

    def push(self, data):
        chunk_size = self.out_buffer_size
        for i in range(0, len(data), chunk_size):
            self._write_queue.put(data[i:i + chunk_size])

    def register_watcher(self, event_type, callback, register_timeout=None):
        self._push_watchers[event_type].add(callback)
        self.wait_for_response(RegisterMessage(event_list=[event_type]),
                               timeout=register_timeout)

    def register_watchers(self, type_callback_dict, register_timeout=None):
        for event_type, callback in type_callback_dict.items():
            self._push_watchers[event_type].add(callback)

        self.wait_for_response(RegisterMessage(event_list=type_callback_dict.keys()),
                               timeout=register_timeout)