⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 network-mysqld-proto.c

📁 Mysql Proxy本身是个很好的mysql负载均衡工具,但是其本身有bug:当多个mysql 做slave的时候,如果一个slave死掉,会影响别的slave也死掉!这个文件修复了这个bug!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2007 MySQL AB   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; version 2 of the License.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */ #include <string.h>#include "network-mysqld-proto.h"#include "sys-pedantic.h"/** @file * * decoders and encoders for the MySQL packets * * - basic data-types *   - fixed length integers *   - variable length integers *   - variable length strings * - packet types *   - OK packets *   - EOF packets *   - ERR packets * *//** * force a crash for gdb and valgrind to get a stacktrace */#define CRASHME() do { char *_crashme = NULL; *_crashme = 0; } while(0);/** * a handy marco for constant strings  */#define C(x) x, sizeof(x) - 1/** @defgroup proto MySQL Protocol *  * decoders and encoders for the MySQL packets as described in  * http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol * * *//*@{*//** * decode a length-encoded integer from a network packet * * _off is incremented on success  * * @param packet   the MySQL-packet to decode * @param _off     offset in into the packet  * @return the decoded number * */guint64 network_mysqld_proto_get_lenenc_int(GString *packet, guint *_off) {	guint off = *_off;	guint64 ret = 0;	unsigned char *bytestream = (unsigned char *)packet->str;	g_assert(off < packet->len);		if (bytestream[off] < 251) { /* */		ret = bytestream[off];	} else if (bytestream[off] == 251) { /* NULL in row-data */		ret = bytestream[off];	} else if (bytestream[off] == 252) { /* 2 byte length*/		g_assert(off + 2 < packet->len);		ret = (bytestream[off + 1] << 0) | 			(bytestream[off + 2] << 8) ;		off += 2;	} else if (bytestream[off] == 253) { /* 3 byte */		g_assert(off + 3 < packet->len);		ret = (bytestream[off + 1]   <<  0) | 			(bytestream[off + 2] <<  8) |			(bytestream[off + 3] << 16);		off += 3;	} else if (bytestream[off] == 254) { /* 8 byte */		g_assert(off + 8 < packet->len);		ret = (bytestream[off + 5] << 0) |			(bytestream[off + 6] << 8) |			(bytestream[off + 7] << 16) |			(bytestream[off + 8] << 24);		ret <<= 32;		ret |= (bytestream[off + 1] <<  0) | 			(bytestream[off + 2] <<  8) |			(bytestream[off + 3] << 16) |			(bytestream[off + 4] << 24);				off += 8;	} else {		g_error("%s.%d: bytestream[%d] is %d", 			__FILE__, __LINE__,			off, bytestream[off]);	}	off += 1;	*_off = off;	return ret;}/** * decode a OK packet from the network packet */int network_mysqld_proto_get_ok_packet(GString *packet, guint64 *affected, guint64 *insert_id, int *server_status, int *warning_count, char **msg) {	guint off = 0;	guint64 dest;	guint field_count;	field_count = network_mysqld_proto_get_int8(packet, &off);	g_assert(field_count == 0);	dest = network_mysqld_proto_get_lenenc_int(packet, &off); if (affected) *affected = dest;	dest = network_mysqld_proto_get_lenenc_int(packet, &off); if (insert_id) *insert_id = dest;	dest = network_mysqld_proto_get_int16(packet, &off);      if (server_status) *server_status = dest;	dest = network_mysqld_proto_get_int16(packet, &off);      if (warning_count) *warning_count = dest;	if (msg) *msg = NULL;	return 0;}int network_mysqld_proto_append_ok_packet(GString *packet, guint64 affected_rows, guint64 insert_id, guint16 server_status, guint16 warnings) {	network_mysqld_proto_append_int8(packet, 0); /* no fields */	network_mysqld_proto_append_lenenc_int(packet, affected_rows);	network_mysqld_proto_append_lenenc_int(packet, insert_id);	network_mysqld_proto_append_int16(packet, server_status); /* autocommit */	network_mysqld_proto_append_int16(packet, warnings); /* no warnings */	return 0;}/** * create a ERR packet * * @note the sqlstate has to match the SQL standard. If no matching SQL state is known, leave it at NULL * * @param packet      network packet * @param errmsg      the error message * @param errmsg_len  byte-len of the error-message * @param errorcode   mysql error-code we want to send * @param sqlstate    if none-NULL, 5-char SQL state to send, if NULL, default SQL state is used * * @return 0 on success */int network_mysqld_proto_append_error_packet(GString *packet, const char *errmsg, gsize errmsg_len, guint errorcode, const gchar *sqlstate) {	network_mysqld_proto_append_int8(packet, 0xff); /* ERR */	network_mysqld_proto_append_int16(packet, errorcode); /* errorcode */	g_string_append_c(packet, '#');	if (!sqlstate) {		g_string_append_len(packet, C("07000"));	} else {		g_string_append_len(packet, sqlstate, 5);	}	if (errmsg_len < 512) {		g_string_append_len(packet, errmsg, errmsg_len);	} else {		/* truncate the err-msg */		g_string_append_len(packet, errmsg, 512);	}	return 0;}/** * skip bytes in the network packet * * a assertion makes sure that we can't skip over the end of the packet  * * @param packet the MySQL network packet * @param _off   offset into the packet * @param size   bytes to skip * */void network_mysqld_proto_skip(GString *packet, guint *_off, gsize size) {	g_assert(*_off + size <= packet->len);		*_off += size;}/** * get a fixed-length integer from the network packet  * * @param packet the MySQL network packet * @param _off   offset into the packet * @param size   byte-len of the integer to decode * @return a the decoded integer */guint64 network_mysqld_proto_get_int_len(GString *packet, guint *_off, gsize size) {	gsize i;	int shift;	guint64 r = 0;	guint off = *_off;	g_assert(*_off < packet->len);	if (*_off + size > packet->len) {		CRASHME();	}	g_assert(*_off + size <= packet->len);	for (i = 0, shift = 0; i < size; i++, shift += 8) {		r += (unsigned char)(packet->str[off + i]) << shift;	}	*_off += size;	return r;}/** * get a 8-bit integer from the network packet * * @param packet the MySQL network packet * @param _off   offset into the packet * @return a the decoded integer * @see network_mysqld_proto_get_int_len() */guint8 network_mysqld_proto_get_int8(GString *packet, guint *_off) {	return network_mysqld_proto_get_int_len(packet, _off, 1);}/** * get a 16-bit integer from the network packet * * @param packet the MySQL network packet * @param _off   offset into the packet * @return a the decoded integer * @see network_mysqld_proto_get_int_len() */guint16 network_mysqld_proto_get_int16(GString *packet, guint *_off) {	return network_mysqld_proto_get_int_len(packet, _off, 2);}/** * get a 32-bit integer from the network packet * * @param packet the MySQL network packet * @param _off   offset into the packet * @return a the decoded integer * @see network_mysqld_proto_get_int_len() */guint32 network_mysqld_proto_get_int32(GString *packet, guint *_off) {	return network_mysqld_proto_get_int_len(packet, _off, 4);}/** * get a string from the network packet * * @param packet the MySQL network packet * @param _off   offset into the packet * @param len    length of the string * @return the string (allocated) or NULL of len is 0 */gchar *network_mysqld_proto_get_string_len(GString *packet, guint *_off, gsize len) {	gchar *str;	g_assert(*_off < packet->len);	if (*_off + len > packet->len) {		g_error("packet-offset out of range: %u + "F_SIZE_T" > "F_SIZE_T, *_off, len, packet->len);	}	str = len ? g_strndup(packet->str + *_off, len) : NULL; 	*_off += len;	return str;}/** * get a variable-length string from the network packet * * variable length strings are prefixed with variable-length integer defining the length of the string * * @param packet the MySQL network packet * @param _off   offset into the packet * @return the string * @see network_mysqld_proto_get_string_len(), network_mysqld_proto_get_lenenc_int() */gchar *network_mysqld_proto_get_lenenc_string(GString *packet, guint *_off) {	guint64 len;	len = network_mysqld_proto_get_lenenc_int(packet, _off);		g_assert(*_off < packet->len);	g_assert(*_off + len <= packet->len);		return network_mysqld_proto_get_string_len(packet, _off, len);}/** * get a NUL-terminated string from the network packet * * @param packet the MySQL network packet * @param _off   offset into the packet * @return       the string * @see network_mysqld_proto_get_string_len() */gchar *network_mysqld_proto_get_string(GString *packet, guint *_off) {	guint len;	gchar *r = NULL;	for (len = 0; *_off + len < packet->len && *(packet->str + *_off + len); len++);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -