Commit 26ffc5d4 authored by unknown's avatar unknown

auto-magic replication redirection logic support in the client,

compiles, passes test suite, does magic, has bugs, but none that I know 
at this point. Have not tested everything yet, though. Changed
a lot of code in the client, but normal stuff appears to be working.


BUILD/SETUP.sh:
  make sure client link statically
client/mysqltest.c:
  new commands to test replication probe/parse
include/errmsg.h:
  new error messages
include/mysql.h:
  support for replication auto-magic
libmysql/errmsg.c:
  new error messages
libmysql/libmysql.c:
  replication probe/parse auto-magic
mysql-test/mysql-test-run.sh:
  --client-gdb to run the client in debugger
parent 011b1415
......@@ -52,7 +52,8 @@ debug_cflags="-DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DSAFE_MUTEX -O2"
base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti"
base_configs="--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static"
base_configs="--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static \
--with-client-ldflags=-all-static"
alpha_configs="" # Not used yet
pentium_configs=""
sparc_configs=""
......
......@@ -43,7 +43,7 @@
**********************************************************************/
#define MTEST_VERSION "1.8"
#define MTEST_VERSION "1.9"
#include <global.h>
#include <my_sys.h>
......@@ -159,6 +159,8 @@ Q_SYNC_WITH_MASTER, Q_ERROR,
Q_SEND, Q_REAP,
Q_DIRTY_CLOSE, Q_REPLACE,
Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND
......@@ -188,6 +190,8 @@ const char *command_names[] = {
"send", "reap",
"dirty_close", "replace_result",
"ping", "eval",
"rpl_probe", "enable_rpl_parse",
"disable_rpl_parse",
0
};
......@@ -642,6 +646,11 @@ int do_sync_with_master(struct st_query* q)
char query_buf[FN_REFLEN+128];
int offset = 0;
char* p = q->first_argument;
int rpl_parse;
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
if(*p)
offset = atoi(p);
......@@ -658,7 +667,10 @@ int do_sync_with_master(struct st_query* q)
if(!row[0])
die("Error on slave while syncing with master");
mysql_free_result(res);
if(rpl_parse)
mysql_enable_rpl_parse(mysql);
return 0;
}
......@@ -667,6 +679,11 @@ int do_save_master_pos()
MYSQL_RES* res;
MYSQL_ROW row;
MYSQL* mysql = &cur_con->mysql;
int rpl_parse;
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
if(mysql_query(mysql, "show master status"))
die("At line %u: failed in show master status: %d: %s", start_lineno,
mysql_errno(mysql), mysql_error(mysql));
......@@ -678,6 +695,9 @@ int do_save_master_pos()
strncpy(master_pos.file, row[0], sizeof(master_pos.file));
master_pos.pos = strtoul(row[1], (char**) 0, 10);
mysql_free_result(res);
if(rpl_parse)
mysql_enable_rpl_parse(mysql);
return 0;
}
......@@ -702,6 +722,26 @@ int do_let(struct st_query* q)
return var_set(var_name, var_name_end, var_val_start, p);
}
int do_rpl_probe(struct st_query* __attribute__((unused)) q)
{
if(mysql_rpl_probe(&cur_con->mysql))
die("Failed in mysql_rpl_probe(): %s", mysql_error(&cur_con->mysql));
return 0;
}
int do_enable_rpl_parse(struct st_query* __attribute__((unused)) q)
{
mysql_enable_rpl_parse(&cur_con->mysql);
return 0;
}
int do_disable_rpl_parse(struct st_query* __attribute__((unused)) q)
{
mysql_disable_rpl_parse(&cur_con->mysql);
return 0;
}
int do_sleep(struct st_query* q)
{
char* p=q->first_argument;
......@@ -1825,6 +1865,9 @@ int main(int argc, char** argv)
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
close_connection(q); break;
case Q_RPL_PROBE: do_rpl_probe(q); break;
case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
case Q_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q); break;
case Q_INC: do_inc(q); break;
......@@ -1892,7 +1935,7 @@ int main(int argc, char** argv)
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
case Q_COMMENT: /* Ignore row */
case Q_COMMENT_WITH_COMMAND:
case Q_COMMENT_WITH_COMMAND:
case Q_PING:
(void) mysql_ping(&cur_con->mysql);
break;
......
......@@ -54,3 +54,10 @@ extern const char *client_errors[]; /* Error messages */
#define CR_CANT_READ_CHARSET 2019
#define CR_NET_PACKET_TOO_LARGE 2020
#define CR_EMBEDDED_CONNECTION 2021
#define CR_PROBE_SLAVE_STATUS 2022
#define CR_PROBE_SLAVE_HOSTS 2023
#define CR_PROBE_SLAVE_CONNECT 2024
#define CR_PROBE_MASTER_CONNECT 2025
......@@ -154,6 +154,14 @@ enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,
MYSQL_STATUS_USE_RESULT};
/* there are three types of queries - the ones that have to go to
the master, the ones that go to a slave, and the adminstrative
type which must happen on the pivot connectioin
*/
enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE,
MYSQL_RPL_ADMIN };
typedef struct st_mysql {
NET net; /* Communication parameters */
gptr connector_fd; /* ConnectorFd for SSL */
......@@ -183,7 +191,15 @@ typedef struct st_mysql {
struct st_mysql* master, *next_slave;
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
my_bool is_slave; /* will be false for a lone connection */
struct st_mysql* last_used_con; /* needed for send/read/store/use
result to work
correctly with replication
*/
my_bool rpl_pivot; /* set if this is the original connection,
not a master or a slave we have added though
mysql_rpl_probe() or mysql_set_master()/
mysql_add_slave()
*/
} MYSQL;
......@@ -261,9 +277,13 @@ int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
/* perform query on master */
int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
unsigned int length);
int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
unsigned int length);
/* perform query on slave */
int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
unsigned int length);
int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
unsigned int length);
/* enable/disable parsing of all queries to decide
if they go on master or slave */
......@@ -278,11 +298,22 @@ void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
/* get the value of the master read flag */
int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
int STDCALL mysql_query_goes_to_master(const char* q, int len);
enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
/* discover the master and its slaves */
int STDCALL mysql_rpl_probe(MYSQL* mysql);
int STDCALL mysql_rpl_probe(MYSQL* mysql);
/* set the master, close/free the old one, if it is not a pivot */
int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
unsigned int port,
const char* user,
const char* passwd);
int STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
unsigned int port,
const char* user,
const char* passwd);
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_shutdown(MYSQL *mysql);
......
......@@ -16,7 +16,7 @@
MA 02111-1307, USA */
/* Error messages for MySQL clients */
/* error messages for the demon is in share/language/errmsg.sys */
/* error messages for the daemon is in share/language/errmsg.sys */
#include <global.h>
#include <my_sys.h>
......@@ -47,6 +47,10 @@ const char *client_errors[]=
"Can't initialize character set %-.64s (path: %-.64s)",
"Got packet bigger than 'max_allowed_packet'",
"Embedded server",
"Error on SHOW SLAVE STATUS: %-.64s",
"Error on SHOW SLAVE HOSTS: %-.64s",
"Error connecting to slave: %-.64s",
"Error connecting to master: %-.64s"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
......@@ -76,6 +80,10 @@ const char *client_errors[]=
"No pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)",
"Obteve pacote maior do que 'max_allowed_packet'",
"Embedded server"
"Error on SHOW SLAVE STATUS: %-.64s",
"Error on SHOW SLAVE HOSTS: %-.64s",
"Error connecting to slave: %-.64s",
"Error connecting to master: %-.64s"
};
#else /* ENGLISH */
......@@ -102,7 +110,11 @@ const char *client_errors[]=
"Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
"Can't initialize character set %-.64s (path: %-.64s)",
"Got packet bigger than 'max_allowed_packet'",
"Embedded server"
"Embedded server",
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:"
};
#endif
......
This diff is collapsed.
......@@ -124,6 +124,7 @@ USE_RUNNING_SERVER=1
DO_GCOV=""
DO_GDB=""
DO_DDD=""
DO_CLIENT_GDB=""
SLEEP_TIME=2
DBUSER=""
......@@ -165,13 +166,19 @@ while test $# -gt 0; do
;;
--gdb )
if [ x$BINARY_DIST = x1 ] ; then
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with -gdb option"
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --gdb option"
fi
DO_GDB=1
;;
--client-gdb )
if [ x$BINARY_DIST = x1 ] ; then
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --client-gdb option"
fi
DO_CLIENT_GDB=1
;;
--ddd )
if [ x$BINARY_DIST = x1 ] ; then
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with -gdb option"
$ECHO "Note: you will get more meaningful output on a source distribution compiled with debugging option when running tests with --ddd option"
fi
DO_DDD=1
;;
......@@ -273,7 +280,10 @@ then
fi
MYSQL_TEST="$MYSQL_TEST --no-defaults --socket=$MASTER_MYSOCK --database=$DB --user=$DBUSER --password=$DBPASSWD --silent -v --tmpdir=$MYSQL_TMP_DIR"
MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB --user=$DBUSER --password=$DBPASSWD --silent -v --tmpdir=$MYSQL_TMP_DIR"
MYSQL_TEST_BIN=$MYSQL_TEST
MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS"
GDB_CLIENT_INIT=$MYSQL_TMP_DIR/gdbinit.client
GDB_MASTER_INIT=$MYSQL_TMP_DIR/gdbinit.master
GDB_SLAVE_INIT=$MYSQL_TMP_DIR/gdbinit.slave
GCOV_MSG=$MYSQL_TMP_DIR/mysqld-gcov.out
......@@ -316,6 +326,15 @@ show_failed_diff ()
fi
}
do_gdb_test ()
{
mysql_test_args="$MYSQL_TEST_ARGS $1"
$ECHO "set args $mysql_test_args < $2" > $GDB_CLIENT_INIT
echo "Set breakpoints ( if needed) and type 'run' in gdb window"
#this xterm should not be backgrounded
xterm -title "Client" -e gdb -x $GDB_CLIENT_INIT $MYSQL_TEST_BIN
}
error () {
$ECHO "Error: $1"
exit 1
......@@ -694,8 +713,13 @@ run_testcase ()
if [ -f $tf ] ; then
$RM -f r/$tname.*reject
mytime=`$TIME -p $MYSQL_TEST -R r/$tname.result $EXTRA_MYSQL_TEST_OPT \
< $tf 2> $TIMEFILE`
mysql_test_args="-R r/$tname.result $EXTRA_MYSQL_TEST_OPT"
if [ -z "$DO_CLIENT_GDB" ] ; then
mytime=`$TIME -p $MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`
else
do_gdb_test "$mysql_test_args" "$tf"
fi
res=$?
if [ $res = 0 ]; then
......
n
1
2
3
4
5
n
1
2
3
4
n
1
2
3
4
n
1
2
3
4
5
source include/master-slave.inc;
#first, make sure the slave has had enough time to register
connection master;
save_master_pos;
connection slave;
sync_with_master;
#discover slaves
connection master;
rpl_probe;
#turn on master/slave query direction auto-magic
enable_rpl_parse;
drop table if exists t1;
create table t1 ( n int);
insert into t1 values (1),(2),(3),(4);
disable_rpl_parse;
save_master_pos;
enable_rpl_parse;
connection slave;
sync_with_master;
insert into t1 values(5);
connection master;
select * from t1;
select * from t1;
disable_rpl_parse;
select * from t1;
connection slave;
select * from t1;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment