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
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
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
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, ))
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)
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))
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()
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()
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
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
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))
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()
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
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,))