Esempio n. 1
0
def _read_bytes(self, num_bytes):
    self._sock.set_readtimeout(self._read_timeout)
    while True:
        try:
            data = self._rfile.read(num_bytes)
            break
        except (IOError, OSError) as e:
            if e.errno == errno.EINTR:
                continue
            raise err.OperationalError(
                2013,
                "Lost connection to MySQL server during query (%s)" % (e, ))
    if len(data) < num_bytes:
        raise err.OperationalError(
            2013, "Lost connection to MySQL server during query")
    return data
Esempio n. 2
0
    def _read_packet_raw(self):
        buff = b''
        while True:
            packet_header = self._read_bytes(4)
            #if DEBUG: dump_packet(packet_header)

            btrl, btrh, packet_number = struct.unpack('<HBB', packet_header)
            bytes_to_read = btrl + (btrh << 16)
            if packet_number != self._next_seq_id:
                self._force_close()
                if packet_number == 0:
                    # MariaDB sends error packet with seqno==0 when shutdown
                    raise err.OperationalError(
                        CR.CR_SERVER_LOST,
                        "Lost connection to MySQL server during query")
                raise err.InternalError(
                    "Packet sequence number wrong - got %d expected %d" %
                    (packet_number, self._next_seq_id))
            self._next_seq_id = (self._next_seq_id + 1) % 256

            recv_data = self._read_bytes(bytes_to_read)
            if DEBUG: dump_packet(recv_data)
            buff += recv_data
            # https://dev.mysql.com/doc/internals/en/sending-more-than-16mbyte.html
            if bytes_to_read == 0xffffff:
                continue
            if bytes_to_read < MAX_PACKET_LEN:
                break

        return packet_header + buff
Esempio n. 3
0
    def connect(self):
        self._closed = False
        self._loop = platform.current_ioloop()
        try:
            if self.unix_socket:
                self.host_info = "Localhost via UNIX socket"
                address = self.unix_socket
                self._secure = True
            else:
                self.host_info = "socket %s:%d" % (self.host, self.port)
                address = (self.host, self.port)
            sock = platform.IOStream(address, self.bind_address)
            sock.set_close_callback(self.stream_close_callback)

            child_gr = greenlet.getcurrent()
            main = child_gr.parent
            assert main is not None, "Execut must be running in child greenlet"

            def connected(future):
                if (hasattr(future, "_exc_info") and future._exc_info is not None) \
                        or (hasattr(future, "_exception") and future._exception is not None):
                    child_gr.throw(future.exception())
                else:
                    self._sock = sock
                    child_gr.switch()

            future = sock.connect(address, self.connect_timeout)
            future.add_done_callback(connected)
            main.switch()

            self._rfile = self._sock
            self._next_seq_id = 0

            self._get_server_information()
            self._request_authentication()

            if self.sql_mode is not None:
                c = self.cursor()
                c.execute("SET sql_mode=%s", (self.sql_mode, ))

            if self.init_command is not None:
                c = self.cursor()
                c.execute(self.init_command)
                self.commit()

            if self.autocommit_mode is not None:
                self.autocommit(self.autocommit_mode)
        except Exception as e:
            if self._sock:
                self._rfile = None
                self._sock.close()
                self._sock = None
            exc = err.OperationalError(
                2003, "Can't connect to MySQL server on %s (%r)" %
                (self.unix_socket or ("%s:%s" % (self.host, self.port)), e))
            # Keep original exception and traceback to investigate error.
            exc.original_exception = e
            exc.traceback = traceback.format_exc()
            raise exc
Esempio n. 4
0
 def _write_bytes(self, data):
     try:
         self._sock.write(data)
     except (AttributeError, IOError) as e:
         self._force_close()
         raise err.OperationalError(
             CR.CR_SERVER_GONE_ERROR,
             "MySQL server has gone away (%r)" % (e, ))
Esempio n. 5
0
        def read_callback(future):
            if future._exc_info is not None:
                return child_gr.throw(err.OperationalError(2006, "MySQL server has gone away (%r)" % (future.exception(),)))

            data = future.result()
            last_buf = b''
            if self._rbuffer_size > 0:
                last_buf += self._rbuffer.read()
            self._rbuffer_size = 0
            return child_gr.switch(last_buf + data)
Esempio n. 6
0
        def read_callback(future):
            if future._exc_info is not None:
                return child_gr.throw(err.OperationalError(2006, "MySQL server has gone away (%r)" % (future.exception(),)))

            data = future.result()
            if len(data) == num_bytes:
                return child_gr.switch(data)

            self._rbuffer_size = len(data) - num_bytes
            self._rbuffer = StringIO(data)
            return child_gr.switch(self._rbuffer.read(num_bytes))
Esempio n. 7
0
    def _read_bytes(self, num_bytes):
        if num_bytes <= self._rbuffer_size:
            self._rbuffer_size -= num_bytes
            return self._rbuffer.read(num_bytes)

        if self._rbuffer_size > 0:
            self._sock._read_buffer = self._rbuffer.read(
            ) + self._sock._read_buffer
            self._sock._read_buffer_size += self._rbuffer_size
            self._rbuffer_size = 0

        if num_bytes <= self._sock._read_buffer_size:
            data, data_len = self._sock._read_buffer, self._sock._read_buffer_size
            self._sock._read_buffer = bytearray()
            self._sock._read_buffer_size = 0

            if data_len == num_bytes:
                return data

            self._rbuffer_size = data_len - num_bytes
            self._rbuffer = StringIO(data)
            return self._rbuffer.read(num_bytes)

        child_gr = greenlet.getcurrent()
        main = child_gr.parent
        assert main is not None, "Execut must be running in child greenlet"

        def read_callback(future):
            try:
                data = future.result()
                if len(data) == num_bytes:
                    return child_gr.switch(data)

                self._rbuffer_size = len(data) - num_bytes
                self._rbuffer = StringIO(data)
                return child_gr.switch(self._rbuffer.read(num_bytes))
            except Exception as e:
                self._force_close()
                return child_gr.throw(
                    err.OperationalError(
                        CR.CR_SERVER_LOST,
                        "Lost connection to MySQL server during query (%s)" %
                        (e, )))

        try:
            future = self._sock.read_bytes(num_bytes)
            future.add_done_callback(read_callback)
        except (AttributeError, IOError) as e:
            self._force_close()
            raise err.OperationalError(
                CR.CR_SERVER_LOST,
                "Lost connection to MySQL server during query (%s)" % (e, ))
        return main.switch()
Esempio n. 8
0
    def _read_bytes(self, num_bytes):
        if num_bytes <= self._rbuffer_size:
            self._rbuffer_size -= num_bytes
            return self._rbuffer.read(num_bytes)

        if self._rbuffer_size > 0:
            self._rfile._read_buffer.appendleft(self._rbuffer.read())
            self._rfile._read_buffer_size += self._rbuffer_size
            self._rbuffer_size = 0

        if num_bytes <= self._rfile._read_buffer_size:
            data, data_len = b''.join(
                self._rfile._read_buffer), self._rfile._read_buffer_size
            self._rfile._read_buffer.clear()
            self._rfile._read_buffer_size = 0

            if data_len == num_bytes:
                return data

            self._rbuffer_size = data_len - num_bytes
            self._rbuffer = StringIO(data)
            return self._rbuffer.read(num_bytes)

        child_gr = greenlet.getcurrent()
        main = child_gr.parent
        assert main is not None, "Execut must be running in child greenlet"

        def read_callback(future):
            if future._exc_info is not None:
                self._force_close()
                return child_gr.throw(
                    err.OperationalError(
                        CR.CR_SERVER_LOST,
                        "Lost connection to MySQL server during query (%s)" %
                        (future.exception(), )))

            data = future.result()
            if len(data) == num_bytes:
                return child_gr.switch(data)

            self._rbuffer_size = len(data) - num_bytes
            self._rbuffer = StringIO(data)
            return child_gr.switch(self._rbuffer.read(num_bytes))

        try:
            future = self._rfile.read_bytes(num_bytes)
            self._loop.add_future(future, read_callback)
        except (AttributeError, StreamClosedError) as e:
            self._force_close()
            raise err.OperationalError(
                CR.CR_SERVER_LOST,
                "Lost connection to MySQL server during query (%s)" % (e, ))
        return main.switch()
Esempio n. 9
0
 def _read_bytes(self, num_bytes):
     while True:
         try:
             data = self._rfile.read(num_bytes)
             break
         except (IOError, OSError) as e:
             if e.errno == errno.EINTR:
                 continue
             self._force_close()
             raise err.OperationalError(
                 CR.CR_SERVER_LOST,
                 "Lost connection to MySQL server during query (%s)" %
                 (e, ))
         except BaseException:
             # Don't convert unknown exception to MySQLError.
             self._force_close()
             raise
     if len(data) < num_bytes:
         self._force_close()
         raise err.OperationalError(
             CR.CR_SERVER_LOST,
             "Lost connection to MySQL server during query")
     return data
Esempio n. 10
0
def _connect(self, sock=None):
    try:
        if sock is None:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock = AsyncSocket(sock)
            sock.set_connecttimeout(self.connect_timeout)
            sock.connect((self.host, self.port))
            sock.set_nodelay(True)
        self._sock = sock
        # self._rfile = _makefile(sock, 'rb')
        self._rfile = sock
        self._next_seq_id = 0

        self._get_server_information()
        self._request_authentication()

        if self.sql_mode is not None:
            c = self.cursor()
            c.execute("SET sql_mode=%s", (self.sql_mode, ))

        if self.init_command is not None:
            c = self.cursor()
            c.execute(self.init_command)
            c.close()
            self.commit()

        if self.autocommit_mode is not None:
            self.autocommit(self.autocommit_mode)
    except BaseException as e:
        self._rfile = None
        if sock is not None:
            try:
                sock.close()
            except:
                pass

        if isinstance(e, (OSError, IOError, socket.error)):
            exc = err.OperationalError(
                2003,
                "Can't connect to MySQL server on %r (%s)" % (self.host, e))
            # Keep original exception and traceback to investigate error.
            exc.original_exception = e
            exc.traceback = traceback.format_exc()
            if DEBUG: print exc.traceback
            raise exc

        # If e is neither DatabaseError or IOError, It's a bug.
        # But raising AssertionError hides original error.
        # So just reraise it.
        raise
Esempio n. 11
0
        def read_callback(future):
            if future._exc_info is not None:
                self._force_close()
                return child_gr.throw(err.OperationalError(
                    CR.CR_SERVER_LOST,
                    "Lost connection to MySQL server during query (%s)" % (future.exception(),)))

            data = future.result()
            if len(data) == num_bytes:
                return child_gr.switch(data)

            self._rbuffer_size = len(data) - num_bytes
            self._rbuffer = StringIO(data)
            return child_gr.switch(self._rbuffer.read(num_bytes))
Esempio n. 12
0
    def _read_bytes(self, num_bytes):
        if num_bytes <= self._rbuffer_size:
            self._rbuffer_size -= num_bytes
            return self._rbuffer.read(num_bytes)

        if num_bytes <= self._rfile._read_buffer_size + self._rbuffer_size:
            last_buf = b''
            if self._rbuffer_size > 0:
                last_buf += self._rbuffer.read()
            self._rbuffer_size = self._rfile._read_buffer_size + self._rbuffer_size - num_bytes
            self._rbuffer = StringIO(last_buf + b''.join(self._rfile._read_buffer))
            self._rfile._read_buffer.clear()
            self._rfile._read_buffer_size = 0
            if self._rfile._state and (self._rfile._state & self._rfile.io_loop.READ == 0):
                self._rfile._state |= self._rfile.io_loop.READ
                self._rfile.io_loop.update_handler(self._rfile.fileno(), self._rfile._state)
            return self._rbuffer.read(num_bytes)

        child_gr = greenlet.getcurrent()
        main = child_gr.parent
        assert main is not None, "Execut must be running in child greenlet"

        def read_callback(future):
            if future._exc_info is not None:
                return child_gr.throw(err.OperationalError(2006, "MySQL server has gone away (%r)" % (future.exception(),)))

            data = future.result()
            last_buf = b''
            if self._rbuffer_size > 0:
                last_buf += self._rbuffer.read()
            self._rbuffer_size = 0
            return child_gr.switch(last_buf + data)
        try:
            future = self._rfile.read_bytes(num_bytes - self._rbuffer_size)
            self._loop.add_future(future, read_callback)
        except (AttributeError, StreamClosedError) as e:
            raise err.OperationalError(2006, "MySQL server has gone away (%r)" % (e,))
        return main.switch()
Esempio n. 13
0
    def connect(self):
        self._loop = IOLoop.current()
        try:
            if self.unix_socket and self.host in ('localhost', '127.0.0.1'):
                sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
                self.host_info = "Localhost via UNIX socket"
                address = self.unix_socket
            else:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
                self.host_info = "socket %s:%d" % (self.host, self.port)
                address = (self.host, self.port)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
            sock = IOStream(sock)
            sock.set_close_callback(self.stream_close_callback)

            child_gr = greenlet.getcurrent()
            main = child_gr.parent
            assert main is not None, "Execut must be running in child greenlet"

            if self.connect_timeout:
                def timeout():
                    if not self.socket:
                        sock.close((None, IOError("connect timeout"), None))
                self._loop.call_later(self.connect_timeout, timeout)

            def connected(future):
                if future._exc_info is not None:
                    child_gr.throw(future.exception())
                else:
                    self.socket = sock
                    child_gr.switch()

            future = sock.connect(address)
            self._loop.add_future(future, connected)
            main.switch()

            self._rfile = self.socket
            self._next_seq_id = 0

            self._get_server_information()
            self._request_authentication()

            if self.sql_mode is not None:
                c = self.cursor()
                c.execute("SET sql_mode=%s", (self.sql_mode,))

            if self.init_command is not None:
                c = self.cursor()
                c.execute(self.init_command)
                self.commit()

            if self.autocommit_mode is not None:
                self.autocommit(self.autocommit_mode)
        except Exception as e:
            if self.socket:
                self._rfile = None
                self.socket.close()
                self.socket = None
            exc = err.OperationalError(
                2003, "Can't connect to MySQL server on %s (%r)" % (self.unix_socket or ("%s:%s" % (self.host, self.port)), e))
            # Keep original exception and traceback to investigate error.
            exc.original_exception = e
            exc.traceback = traceback.format_exc()
            raise exc
Esempio n. 14
0
 def _write_bytes(self, data):
     try:
         self.socket.write(data)
     except (AttributeError, StreamClosedError) as e:
         raise err.OperationalError(2006, "MySQL server has gone away (%r)" % (e,))