mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Add some examples for using libmysqld, including a hack for running the
mysql test suite. A few minor libmysqld fixes. Add mysql_server_init() and _end() to mysql.cc and mysqltest.c, so they can be linked against libmysqlclient or libmysqld.
This commit is contained in:
@ -400,3 +400,4 @@ vio/test-sslclient
|
||||
vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
tools/mysqlmanager
|
||||
linked_libmysqldex_sources
|
||||
|
@ -29,7 +29,8 @@ SUBDIRS = include @docs_dirs@ @readline_dir@ \
|
||||
# Relink after clean
|
||||
linked_sources = linked_client_sources linked_server_sources \
|
||||
linked_libmysql_sources linked_libmysql_r_sources \
|
||||
linked_libmysqld_sources linked_include_sources
|
||||
linked_libmysqld_sources linked_libmysqldex_sources \
|
||||
linked_include_sources
|
||||
|
||||
CLEANFILES = $(linked_sources)
|
||||
|
||||
@ -56,6 +57,10 @@ linked_libmysqld_sources:
|
||||
cd libmysqld; $(MAKE) link_sources
|
||||
echo timestamp > linked_libmysqld_sources
|
||||
|
||||
linked_libmysqldex_sources:
|
||||
cd libmysqld/examples; $(MAKE) link_sources
|
||||
echo timestamp > linked_libmysqldex_sources
|
||||
|
||||
#avoid recursive make calls in sql directory
|
||||
linked_server_sources:
|
||||
cd sql; rm -f mini_client_errors.c;@LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c
|
||||
|
72
acinclude.m4
72
acinclude.m4
@ -1071,42 +1071,42 @@ AC_DEFUN([MYSQL_CHECK_INNODB], [
|
||||
dnl Some libs are listed several times, in order for gcc to sort out
|
||||
dnl circular references.
|
||||
innodb_libs="\
|
||||
../innobase/usr/libusr.a\
|
||||
../innobase/odbc/libodbc.a\
|
||||
../innobase/srv/libsrv.a\
|
||||
../innobase/que/libque.a\
|
||||
../innobase/srv/libsrv.a\
|
||||
../innobase/dict/libdict.a\
|
||||
../innobase/ibuf/libibuf.a\
|
||||
../innobase/row/librow.a\
|
||||
../innobase/pars/libpars.a\
|
||||
../innobase/btr/libbtr.a\
|
||||
../innobase/trx/libtrx.a\
|
||||
../innobase/read/libread.a\
|
||||
../innobase/usr/libusr.a\
|
||||
../innobase/buf/libbuf.a\
|
||||
../innobase/ibuf/libibuf.a\
|
||||
../innobase/eval/libeval.a\
|
||||
../innobase/log/liblog.a\
|
||||
../innobase/fsp/libfsp.a\
|
||||
../innobase/fut/libfut.a\
|
||||
../innobase/fil/libfil.a\
|
||||
../innobase/lock/liblock.a\
|
||||
../innobase/mtr/libmtr.a\
|
||||
../innobase/page/libpage.a\
|
||||
../innobase/rem/librem.a\
|
||||
../innobase/thr/libthr.a\
|
||||
../innobase/com/libcom.a\
|
||||
../innobase/sync/libsync.a\
|
||||
../innobase/data/libdata.a\
|
||||
../innobase/mach/libmach.a\
|
||||
../innobase/ha/libha.a\
|
||||
../innobase/dyn/libdyn.a\
|
||||
../innobase/mem/libmem.a\
|
||||
../innobase/sync/libsync.a\
|
||||
../innobase/ut/libut.a\
|
||||
../innobase/os/libos.a\
|
||||
../innobase/ut/libut.a"
|
||||
$(top_builddir)/innobase/usr/libusr.a\
|
||||
$(top_builddir)/innobase/odbc/libodbc.a\
|
||||
$(top_builddir)/innobase/srv/libsrv.a\
|
||||
$(top_builddir)/innobase/que/libque.a\
|
||||
$(top_builddir)/innobase/srv/libsrv.a\
|
||||
$(top_builddir)/innobase/dict/libdict.a\
|
||||
$(top_builddir)/innobase/ibuf/libibuf.a\
|
||||
$(top_builddir)/innobase/row/librow.a\
|
||||
$(top_builddir)/innobase/pars/libpars.a\
|
||||
$(top_builddir)/innobase/btr/libbtr.a\
|
||||
$(top_builddir)/innobase/trx/libtrx.a\
|
||||
$(top_builddir)/innobase/read/libread.a\
|
||||
$(top_builddir)/innobase/usr/libusr.a\
|
||||
$(top_builddir)/innobase/buf/libbuf.a\
|
||||
$(top_builddir)/innobase/ibuf/libibuf.a\
|
||||
$(top_builddir)/innobase/eval/libeval.a\
|
||||
$(top_builddir)/innobase/log/liblog.a\
|
||||
$(top_builddir)/innobase/fsp/libfsp.a\
|
||||
$(top_builddir)/innobase/fut/libfut.a\
|
||||
$(top_builddir)/innobase/fil/libfil.a\
|
||||
$(top_builddir)/innobase/lock/liblock.a\
|
||||
$(top_builddir)/innobase/mtr/libmtr.a\
|
||||
$(top_builddir)/innobase/page/libpage.a\
|
||||
$(top_builddir)/innobase/rem/librem.a\
|
||||
$(top_builddir)/innobase/thr/libthr.a\
|
||||
$(top_builddir)/innobase/com/libcom.a\
|
||||
$(top_builddir)/innobase/sync/libsync.a\
|
||||
$(top_builddir)/innobase/data/libdata.a\
|
||||
$(top_builddir)/innobase/mach/libmach.a\
|
||||
$(top_builddir)/innobase/ha/libha.a\
|
||||
$(top_builddir)/innobase/dyn/libdyn.a\
|
||||
$(top_builddir)/innobase/mem/libmem.a\
|
||||
$(top_builddir)/innobase/sync/libsync.a\
|
||||
$(top_builddir)/innobase/ut/libut.a\
|
||||
$(top_builddir)/innobase/os/libos.a\
|
||||
$(top_builddir)/innobase/ut/libut.a"
|
||||
|
||||
AC_CHECK_LIB(rt, aio_read, [innodb_libs="$innodb_libs -lrt"])
|
||||
;;
|
||||
|
@ -248,6 +248,7 @@ static COMMANDS commands[] = {
|
||||
};
|
||||
|
||||
static const char *load_default_groups[]= { "mysql","client",0 };
|
||||
static const char *server_default_groups[]= { "server", "mysql_SERVER", 0 };
|
||||
|
||||
#ifdef HAVE_READLINE
|
||||
extern "C" void add_history(char *command); /* From readline directory */
|
||||
@ -275,6 +276,7 @@ int main(int argc,char *argv[])
|
||||
{
|
||||
char buff[80];
|
||||
|
||||
mysql_server_init(0, NULL, server_default_groups);
|
||||
MY_INIT(argv[0]);
|
||||
DBUG_ENTER("main");
|
||||
DBUG_PROCESS(argv[0]);
|
||||
@ -368,6 +370,7 @@ int main(int argc,char *argv[])
|
||||
if (opt_outfile)
|
||||
end_tee();
|
||||
mysql_end(0);
|
||||
mysql_server_end();
|
||||
#ifndef _lint
|
||||
DBUG_RETURN(0); // Keep compiler happy
|
||||
#endif
|
||||
@ -377,9 +380,11 @@ sig_handler mysql_end(int sig)
|
||||
{
|
||||
if (connected)
|
||||
mysql_close(&mysql);
|
||||
#ifdef HAVE_OPENSSL
|
||||
else
|
||||
mysql_ssl_clear(&mysql); /* SSL data structres should be freed
|
||||
even if connection was not made */
|
||||
#endif
|
||||
#ifdef HAVE_READLINE
|
||||
if (!status.batch && !quick && !opt_html && !opt_xml)
|
||||
{
|
||||
@ -2217,9 +2222,11 @@ sql_real_connect(char *host,char *database,char *user,char *password,
|
||||
mysql_close(&mysql);
|
||||
connected= 0;
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
else
|
||||
mysql_ssl_clear(&mysql); /* SSL data structres should be freed
|
||||
even if connection was not made */
|
||||
#endif
|
||||
mysql_init(&mysql);
|
||||
if (opt_connect_timeout)
|
||||
{
|
||||
@ -2571,6 +2578,7 @@ static void mysql_end_timer(ulong start_time,char *buff)
|
||||
strmov(strend(buff),")");
|
||||
}
|
||||
|
||||
#ifndef EMBEDDED_SERVER
|
||||
/* Keep sql_string library happy */
|
||||
|
||||
gptr sql_alloc(unsigned int Size)
|
||||
@ -2582,3 +2590,4 @@ void sql_element_free(void *ptr)
|
||||
{
|
||||
my_free((gptr) ptr,MYF(0));
|
||||
}
|
||||
#endif /* EMBEDDED_SERVER */
|
||||
|
@ -1931,12 +1931,26 @@ static void init_var_hash()
|
||||
var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
|
||||
}
|
||||
|
||||
static const char *embedded_server_args[] = {
|
||||
"", /* XXX: argv[0] is program name - we should fix the API */
|
||||
"--datadir=.",
|
||||
"--language=/home/tim/my/4/sql/share/english",
|
||||
"--skip-innodb",
|
||||
NullS
|
||||
};
|
||||
static const char *embedded_server_groups[] = {
|
||||
"mysql-test-server",
|
||||
NullS
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int error = 0;
|
||||
struct st_query* q;
|
||||
my_bool require_file=0, q_send_flag=0;
|
||||
char save_file[FN_REFLEN];
|
||||
mysql_server_init(sizeof(embedded_server_args) / sizeof(char *) - 1,
|
||||
embedded_server_args, embedded_server_groups);
|
||||
MY_INIT(argv[0]);
|
||||
|
||||
save_file[0]=0;
|
||||
@ -2100,6 +2114,7 @@ int main(int argc, char** argv)
|
||||
printf("ok\n");
|
||||
}
|
||||
|
||||
mysql_server_end();
|
||||
free_used_memory();
|
||||
exit(error ? 1 : 0);
|
||||
return error ? 1 : 0; /* Keep compiler happy */
|
||||
|
@ -1804,7 +1804,7 @@ AC_ARG_WITH(readline,
|
||||
if test "$with_readline" = "yes"
|
||||
then
|
||||
readline_dir="readline"
|
||||
readline_link="../readline/libreadline.a"
|
||||
readline_link="\$(top_builddir)/readline/libreadline.a"
|
||||
else
|
||||
# This requires readline to be in a standard place. Mosty for linux
|
||||
# there readline may be a shared library.
|
||||
@ -2219,7 +2219,8 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile \
|
||||
bdb/Makefile \
|
||||
myisam/Makefile myisammrg/Makefile \
|
||||
man/Makefile readline/Makefile vio/Makefile \
|
||||
libmysql_r/Makefile libmysqld/Makefile libmysql/Makefile client/Makefile \
|
||||
libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile \
|
||||
libmysql/Makefile client/Makefile \
|
||||
pstack/Makefile sql/Makefile sql/share/Makefile \
|
||||
merge/Makefile dbug/Makefile scripts/Makefile \
|
||||
include/Makefile sql-bench/Makefile tools/Makefile \
|
||||
|
33
libmysqld/examples/Makefile.am
Normal file
33
libmysqld/examples/Makefile.am
Normal file
@ -0,0 +1,33 @@
|
||||
bin_PROGRAMS = mysqltest mysql
|
||||
client_sources = $(mysqltest_SOURCES) $(mysql_SOURCES)
|
||||
link_sources:
|
||||
for f in $(client_sources); do \
|
||||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ $(srcdir)/../../client/$$f $(srcdir)/$$f; \
|
||||
done;
|
||||
|
||||
DEFS = -DEMBEDDED_SERVER
|
||||
INCLUDES = -I$(top_srcdir)/include $(openssl_includes) \
|
||||
-I$(srcdir) -I$(top_srcdir) -I..
|
||||
LIBS = @LIBS@
|
||||
LDADD = $(top_builddir)/libmysqld/libmysqld.la \
|
||||
$(top_builddir)/isam/libnisam.a \
|
||||
$(top_builddir)/myisam/libmyisam.a \
|
||||
$(top_builddir)/heap/libheap.a \
|
||||
$(top_builddir)/merge/libmerge.a \
|
||||
$(top_builddir)/myisammrg/libmyisammrg.a \
|
||||
@innodb_libs@ @bdb_libs@ \
|
||||
$(top_builddir)/mysys/libmysys.a \
|
||||
$(top_builddir)/strings/libmystrings.a \
|
||||
$(top_builddir)/dbug/libdbug.a \
|
||||
$(top_builddir)/regex/libregex.a
|
||||
|
||||
mysqltest_DEPENDENCIES = ../libmysqld.la
|
||||
mysqltest_SOURCES = mysqltest.c
|
||||
|
||||
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc \
|
||||
my_readline.h sql_string.h completion_hash.h
|
||||
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD)
|
||||
|
||||
clean:
|
||||
rm -f $(client_sources)
|
131
libmysqld/examples/test-run
Executable file
131
libmysqld/examples/test-run
Executable file
@ -0,0 +1,131 @@
|
||||
#! /bin/sh
|
||||
|
||||
# This is slapped together as a quick way to run the tests and
|
||||
# is not meant for prime time. Please hack at it and submit
|
||||
# changes, though, so we can gradually turn it into something
|
||||
# that will run on all platforms (or incorporate it into the
|
||||
# standard mysql-test-run).
|
||||
|
||||
#test_data_dir=/tmp/mysql-data
|
||||
test_data_dir=../../mysql-test/var/master-data
|
||||
cd "$test_data_dir" || {
|
||||
echo "can't cd to $test_data_dir" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# All paths below must be relative to $test_data_dir
|
||||
#top_builddir=/home/tim/my/4
|
||||
top_builddir=../../..
|
||||
mysql_test_dir=$top_builddir/mysql-test
|
||||
examples=$top_builddir/libmysqld/examples
|
||||
mysqltest=$examples/mysqltest
|
||||
testdir=./test
|
||||
|
||||
gdb=0
|
||||
list=0
|
||||
run=
|
||||
tests=
|
||||
start=
|
||||
|
||||
cr="
|
||||
"
|
||||
er="\b\b\b\b\b\b\b\b"
|
||||
|
||||
usage () {
|
||||
cat <<EOF
|
||||
usage: $0 [-g|-h|-r] [test-name ...]
|
||||
|
||||
-g | --gdb run $mysqltest in gdb
|
||||
-h | --help show this help
|
||||
-l | --list ) list all available tests
|
||||
-r | --run automatically 'run' program in gdb
|
||||
-s t | --start=t start with test t (skip all tests before t)
|
||||
EOF
|
||||
}
|
||||
|
||||
while test $# -gt 0
|
||||
do
|
||||
arg=
|
||||
argset=0
|
||||
case "$1" in
|
||||
--?*=* ) arg=`echo "$1" | sed -e 's,^[^=][^=]*=,,'`; argset=1 ;;
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
-g | --gdb ) gdb=1; shift;;
|
||||
-h | --help | -\? ) usage; exit 0;;
|
||||
-l | --list ) list=1 ; shift ;;
|
||||
-r | --run ) run="${cr}run"; shift;;
|
||||
-s | --start=* )
|
||||
test $argset -eq 0 && { shift; arg="$1"; }
|
||||
start="$arg"
|
||||
shift
|
||||
;;
|
||||
-* ) usage; exit 1;;
|
||||
* ) tests="$tests $1"; shift;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -d "$mysql_test_dir/t" -a -d "$mysql_test_dir/r" -a \
|
||||
-f $mysqltest -a -d $testdir || {
|
||||
echo "bad setup (is '$testdir', from '$test_data_dir', missing?)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
test -n "$tests" ||
|
||||
tests=`/bin/ls -1 "$mysql_test_dir"/t/*.test | grep -v '^.*/rpl[^/]*$' | \
|
||||
sed -e 's,^.*/,,' -e 's,.test$,,'`
|
||||
|
||||
echo "cleaning data directory '$test_data_dir'"
|
||||
rm -f $test_data_dir/ib_* $test_data_dir/ibdata* log.*
|
||||
echo "cleaning test directory '$testdir'"
|
||||
rm -f $testdir/*
|
||||
|
||||
rm -f test-gdbinit
|
||||
|
||||
TZ=GMT-3; export TZ
|
||||
|
||||
skip=1
|
||||
test -z "$start" && skip=0
|
||||
|
||||
for b in $tests
|
||||
do
|
||||
test $list -eq 1 && { echo " $b"; continue; }
|
||||
test $skip -eq 1 && test -n "$start" && test "$start" = "$b" && skip=0
|
||||
test $skip -eq 1 && { echo "skipping '$b'"; continue; }
|
||||
|
||||
t="$mysql_test_dir/t/$b.test"
|
||||
r="$mysql_test_dir/r/$b.result"
|
||||
c="$mysql_test_dir/r/$b.reject"
|
||||
|
||||
# Only test if $t exists; there is no $r for some tests
|
||||
test -f $t || {
|
||||
echo "test '$b' doesn't exist" >&2
|
||||
continue
|
||||
}
|
||||
args="-v -S /tmp/mysql.sock -R $r -x $t test"
|
||||
echo "set args $args$run" > test-gdbinit
|
||||
#if false && test -n "$run"
|
||||
if test -n "$run" -o $gdb -eq 1
|
||||
then
|
||||
echo -e "$er>>> $b"
|
||||
else
|
||||
echo -e "$er>>> $b> \c"
|
||||
read junk
|
||||
fi
|
||||
if test $gdb -eq 1
|
||||
then
|
||||
if [ -x "$top_builddir/libtool" ]; then
|
||||
$top_builddir/libtool gdb -x test-gdbinit -q $mysqltest
|
||||
else
|
||||
gdb -x test-gdbinit -q $mysqltest
|
||||
fi
|
||||
res=$?
|
||||
rm -f test-gdbinit
|
||||
else
|
||||
$mysqltest $args
|
||||
res=$?
|
||||
fi
|
||||
|
||||
test $res -eq 0 || echo "!!! error: $res"
|
||||
done
|
@ -98,6 +98,11 @@ static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
|
||||
#define set_sigpipe(mysql)
|
||||
#define reset_sigpipe(mysql)
|
||||
|
||||
static MYSQL* spawn_init(MYSQL* parent, const char* host,
|
||||
unsigned int port,
|
||||
const char* user,
|
||||
const char* passwd);
|
||||
|
||||
/*****************************************************************************
|
||||
** read a packet from server. Give error message if socket was down
|
||||
** or packet is an error message
|
||||
@ -762,6 +767,301 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* perform query on master */
|
||||
int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
|
||||
unsigned int length)
|
||||
{
|
||||
if(mysql_master_send_query(mysql, q, length))
|
||||
return 1;
|
||||
return mysql_read_query_result(mysql);
|
||||
}
|
||||
|
||||
int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned int length)
|
||||
{
|
||||
MYSQL*master = mysql->master;
|
||||
if (!length)
|
||||
length = strlen(q);
|
||||
if (!master->net.vio && !mysql_real_connect(master,0,0,0,0,0,0,0))
|
||||
return 1;
|
||||
mysql->last_used_con = master;
|
||||
return simple_command(master, COM_QUERY, q, length, 1);
|
||||
}
|
||||
|
||||
|
||||
/* perform query on slave */
|
||||
int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
|
||||
unsigned int length)
|
||||
{
|
||||
if(mysql_slave_send_query(mysql, q, length))
|
||||
return 1;
|
||||
return mysql_read_query_result(mysql);
|
||||
}
|
||||
|
||||
int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
|
||||
unsigned int length)
|
||||
{
|
||||
MYSQL* last_used_slave, *slave_to_use = 0;
|
||||
|
||||
if((last_used_slave = mysql->last_used_slave))
|
||||
slave_to_use = last_used_slave->next_slave;
|
||||
else
|
||||
slave_to_use = mysql->next_slave;
|
||||
/* next_slave is always safe to use - we have a circular list of slaves
|
||||
if there are no slaves, mysql->next_slave == mysql
|
||||
*/
|
||||
mysql->last_used_con = mysql->last_used_slave = slave_to_use;
|
||||
if(!length)
|
||||
length = strlen(q);
|
||||
if(!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0,
|
||||
0,0,0,0))
|
||||
return 1;
|
||||
return simple_command(slave_to_use, COM_QUERY, q, length, 1);
|
||||
}
|
||||
|
||||
|
||||
/* enable/disable parsing of all queries to decide
|
||||
if they go on master or slave */
|
||||
void STDCALL mysql_enable_rpl_parse(MYSQL* mysql)
|
||||
{
|
||||
mysql->options.rpl_parse = 1;
|
||||
}
|
||||
|
||||
void STDCALL mysql_disable_rpl_parse(MYSQL* mysql)
|
||||
{
|
||||
mysql->options.rpl_parse = 0;
|
||||
}
|
||||
|
||||
/* get the value of the parse flag */
|
||||
int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql)
|
||||
{
|
||||
return mysql->options.rpl_parse;
|
||||
}
|
||||
|
||||
/* enable/disable reads from master */
|
||||
void STDCALL mysql_enable_reads_from_master(MYSQL* mysql)
|
||||
{
|
||||
mysql->options.no_master_reads = 0;
|
||||
}
|
||||
|
||||
void STDCALL mysql_disable_reads_from_master(MYSQL* mysql)
|
||||
{
|
||||
mysql->options.no_master_reads = 1;
|
||||
}
|
||||
|
||||
/* get the value of the master read flag */
|
||||
int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
|
||||
{
|
||||
return !(mysql->options.no_master_reads);
|
||||
}
|
||||
|
||||
/* We may get an error while doing replication internals.
|
||||
In this case, we add a special explanation to the original
|
||||
error
|
||||
*/
|
||||
static inline void expand_error(MYSQL* mysql, int error)
|
||||
{
|
||||
char tmp[MYSQL_ERRMSG_SIZE];
|
||||
char* p, *tmp_end;
|
||||
tmp_end = strnmov(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE);
|
||||
p = strnmov(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE);
|
||||
memcpy(p, tmp, tmp_end - tmp);
|
||||
mysql->net.last_errno = error;
|
||||
}
|
||||
|
||||
/* This function assumes we have just called SHOW SLAVE STATUS and have
|
||||
read the given result and row
|
||||
*/
|
||||
static inline int get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
|
||||
{
|
||||
MYSQL* master;
|
||||
if(mysql_num_fields(res) < 3)
|
||||
return 1; /* safety */
|
||||
|
||||
/* use the same username and password as the original connection */
|
||||
if(!(master = spawn_init(mysql, row[0], atoi(row[2]), 0, 0)))
|
||||
return 1;
|
||||
mysql->master = master;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* assuming we already know that mysql points to a master connection,
|
||||
retrieve all the slaves
|
||||
*/
|
||||
static inline int get_slaves_from_master(MYSQL* mysql)
|
||||
{
|
||||
MYSQL_RES* res = 0;
|
||||
MYSQL_ROW row;
|
||||
int error = 1;
|
||||
int has_auth_info;
|
||||
if (!mysql->net.vio && !mysql_real_connect(mysql,0,0,0,0,0,0,0))
|
||||
{
|
||||
expand_error(mysql, CR_PROBE_MASTER_CONNECT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mysql_query(mysql, "SHOW SLAVE HOSTS") ||
|
||||
!(res = mysql_store_result(mysql)))
|
||||
{
|
||||
expand_error(mysql, CR_PROBE_SLAVE_HOSTS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (mysql_num_fields(res))
|
||||
{
|
||||
case 3: has_auth_info = 0; break;
|
||||
case 5: has_auth_info = 1; break;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
|
||||
while ((row = mysql_fetch_row(res)))
|
||||
{
|
||||
MYSQL* slave;
|
||||
const char* tmp_user, *tmp_pass;
|
||||
|
||||
if (has_auth_info)
|
||||
{
|
||||
tmp_user = row[3];
|
||||
tmp_pass = row[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_user = mysql->user;
|
||||
tmp_pass = mysql->passwd;
|
||||
}
|
||||
|
||||
if(!(slave = spawn_init(mysql, row[1], atoi(row[2]),
|
||||
tmp_user, tmp_pass)))
|
||||
goto err;
|
||||
|
||||
/* Now add slave into the circular linked list */
|
||||
slave->next_slave = mysql->next_slave;
|
||||
mysql->next_slave = slave;
|
||||
}
|
||||
error = 0;
|
||||
err:
|
||||
if(res)
|
||||
mysql_free_result(res);
|
||||
return error;
|
||||
}
|
||||
|
||||
int STDCALL mysql_rpl_probe(MYSQL* mysql)
|
||||
{
|
||||
MYSQL_RES* res = 0;
|
||||
MYSQL_ROW row;
|
||||
int error = 1;
|
||||
/* first determine the replication role of the server we connected to
|
||||
the most reliable way to do this is to run SHOW SLAVE STATUS and see
|
||||
if we have a non-empty master host. This is still not fool-proof -
|
||||
it is not a sin to have a master that has a dormant slave thread with
|
||||
a non-empty master host. However, it is more reliable to check
|
||||
for empty master than whether the slave thread is actually running
|
||||
*/
|
||||
if (mysql_query(mysql, "SHOW SLAVE STATUS") ||
|
||||
!(res = mysql_store_result(mysql)))
|
||||
{
|
||||
expand_error(mysql, CR_PROBE_SLAVE_STATUS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(row = mysql_fetch_row(res)))
|
||||
goto err;
|
||||
|
||||
/* check master host for emptiness/NULL */
|
||||
if (row[0] && *(row[0]))
|
||||
{
|
||||
/* this is a slave, ask it for the master */
|
||||
if (get_master(mysql, res, row) || get_slaves_from_master(mysql))
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
mysql->master = mysql;
|
||||
if (get_slaves_from_master(mysql))
|
||||
goto err;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
err:
|
||||
if(res)
|
||||
mysql_free_result(res);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* make a not so fool-proof decision on where the query should go, to
|
||||
the master or the slave. Ideally the user should always make this
|
||||
decision himself with mysql_master_query() or mysql_slave_query().
|
||||
However, to be able to more easily port the old code, we support the
|
||||
option of an educated guess - this should work for most applications,
|
||||
however, it may make the wrong decision in some particular cases. If
|
||||
that happens, the user would have to change the code to call
|
||||
mysql_master_query() or mysql_slave_query() explicitly in the place
|
||||
where we have made the wrong decision
|
||||
*/
|
||||
enum mysql_rpl_type
|
||||
STDCALL mysql_rpl_query_type(const char* q, int len)
|
||||
{
|
||||
const char* q_end;
|
||||
q_end = (len) ? q + len : strend(q);
|
||||
for(; q < q_end; ++q)
|
||||
{
|
||||
char c;
|
||||
if(isalpha(c=*q))
|
||||
switch(tolower(c))
|
||||
{
|
||||
case 'i': /* insert */
|
||||
case 'u': /* update or unlock tables */
|
||||
case 'l': /* lock tables or load data infile */
|
||||
case 'd': /* drop or delete */
|
||||
case 'a': /* alter */
|
||||
return MYSQL_RPL_MASTER;
|
||||
case 'c': /* create or check */
|
||||
return tolower(q[1]) == 'h' ? MYSQL_RPL_ADMIN : MYSQL_RPL_MASTER ;
|
||||
case 's': /* select or show */
|
||||
return tolower(q[1] == 'h') ? MYSQL_RPL_ADMIN : MYSQL_RPL_SLAVE;
|
||||
case 'f': /* flush */
|
||||
case 'r': /* repair */
|
||||
case 'g': /* grant */
|
||||
return MYSQL_RPL_ADMIN;
|
||||
default:
|
||||
return MYSQL_RPL_SLAVE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MYSQL* spawn_init(MYSQL* parent, const char* host,
|
||||
unsigned int port,
|
||||
const char* user,
|
||||
const char* passwd)
|
||||
{
|
||||
MYSQL* child;
|
||||
if (!(child = mysql_init(0)))
|
||||
return 0;
|
||||
|
||||
child->options.user = my_strdup((user) ? user :
|
||||
(parent->user ? parent->user :
|
||||
parent->options.user), MYF(0));
|
||||
child->options.password = my_strdup((passwd) ? passwd : (parent->passwd ?
|
||||
parent->passwd :
|
||||
parent->options.password), MYF(0));
|
||||
child->options.port = port;
|
||||
child->options.host = my_strdup((host) ? host : (parent->host ?
|
||||
parent->host :
|
||||
parent->options.host), MYF(0));
|
||||
if(parent->db)
|
||||
child->options.db = my_strdup(parent->db, MYF(0));
|
||||
else if(parent->options.db)
|
||||
child->options.db = my_strdup(parent->options.db, MYF(0));
|
||||
|
||||
child->options.rpl_parse = child->options.rpl_probe = child->rpl_pivot = 0;
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
** Init MySQL structure or allocate one
|
||||
****************************************************************************/
|
||||
|
@ -128,7 +128,7 @@ DO_GDB=""
|
||||
DO_DDD=""
|
||||
DO_CLIENT_GDB=""
|
||||
SLEEP_TIME=2
|
||||
CHARACTER_SET=latin1_de
|
||||
CHARACTER_SET=latin1
|
||||
DBUSER=""
|
||||
|
||||
while test $# -gt 0; do
|
||||
|
@ -684,7 +684,9 @@ static sig_handler print_signal_warning(int sig)
|
||||
void unireg_end(int signal_number __attribute__((unused)))
|
||||
{
|
||||
clean_up();
|
||||
#ifndef OS2
|
||||
#if defined(EMBEDDED_LIBRARY)
|
||||
exit(0); // XXX QQ: this is a temporary hack (I hope)
|
||||
#elif !defined(OS2)
|
||||
pthread_exit(0); // Exit is in main thread
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user