diff --git a/.bzrignore b/.bzrignore index 57fcbdd8f73..b3bc5760f59 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1771,3 +1771,5 @@ vio/viotest.cpp zlib/*.ds? zlib/*.vcproj libmysqld/event_scheduler.cc +mysys/test_atomic +*-t diff --git a/client/Makefile.am b/client/Makefile.am index aa78f825c87..be2888367a6 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -83,13 +83,13 @@ link_sources: for f in $(sql_src) ; do \ rm -f $$f; \ @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ - done; \ - for f in $(strings_src) ; do \ - rm -f $(srcdir)/$$f; \ - @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \ - done; \ - rm -f $(srcdir)/my_user.c; \ - @LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c + done; + for f in $(strings_src) ; do \ + rm -f $(srcdir)/$$f; \ + @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \ + done; + -rm -f $(srcdir)/my_user.c; + @LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c # Don't update the files from bitkeeper diff --git a/client/client_priv.h.rej b/client/client_priv.h.rej deleted file mode 100644 index ac3818bb1e1..00000000000 --- a/client/client_priv.h.rej +++ /dev/null @@ -1,15 +0,0 @@ -*************** -*** 50,55 **** - OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, - #endif - OPT_TRIGGERS, - OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, -! OPT_TZ_UTC, OPT_AUTO_CLOSE - }; ---- 50,55 ---- - OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, - #endif - OPT_TRIGGERS, - OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, -! OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT - }; diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4 index a2f70071e2d..3ed64b5625b 100644 --- a/config/ac-macros/misc.m4 +++ b/config/ac-macros/misc.m4 @@ -155,84 +155,6 @@ fi ]) -#---START: Used in for client configure -AC_DEFUN([MYSQL_CHECK_ULONG], -[AC_MSG_CHECKING(for type ulong) -AC_CACHE_VAL(ac_cv_ulong, -[AC_TRY_RUN([#include -#include -main() -{ - ulong foo; - foo++; - exit(0); -}], ac_cv_ulong=yes, ac_cv_ulong=no, ac_cv_ulong=no)]) -AC_MSG_RESULT($ac_cv_ulong) -if test "$ac_cv_ulong" = "yes" -then - AC_DEFINE([HAVE_ULONG], [1], [system headers define ulong]) -fi -]) - -AC_DEFUN([MYSQL_CHECK_UCHAR], -[AC_MSG_CHECKING(for type uchar) -AC_CACHE_VAL(ac_cv_uchar, -[AC_TRY_RUN([#include -#include -main() -{ - uchar foo; - foo++; - exit(0); -}], ac_cv_uchar=yes, ac_cv_uchar=no, ac_cv_uchar=no)]) -AC_MSG_RESULT($ac_cv_uchar) -if test "$ac_cv_uchar" = "yes" -then - AC_DEFINE([HAVE_UCHAR], [1], [system headers define uchar]) -fi -]) - -AC_DEFUN([MYSQL_CHECK_UINT], -[AC_MSG_CHECKING(for type uint) -AC_CACHE_VAL(ac_cv_uint, -[AC_TRY_RUN([#include -#include -main() -{ - uint foo; - foo++; - exit(0); -}], ac_cv_uint=yes, ac_cv_uint=no, ac_cv_uint=no)]) -AC_MSG_RESULT($ac_cv_uint) -if test "$ac_cv_uint" = "yes" -then - AC_DEFINE([HAVE_UINT], [1], [system headers define uint]) -fi -]) - - -AC_DEFUN([MYSQL_CHECK_IN_ADDR_T], -[AC_MSG_CHECKING(for type in_addr_t) -AC_CACHE_VAL(ac_cv_in_addr_t, -[AC_TRY_RUN([#include -#include -#include -#include -#include - -int main(int argc, char **argv) -{ - in_addr_t foo; - exit(0); -}], ac_cv_in_addr_t=yes, ac_cv_in_addr_t=no, ac_cv_in_addr_t=no)]) -AC_MSG_RESULT($ac_cv_in_addr_t) -if test "$ac_cv_in_addr_t" = "yes" -then - AC_DEFINE([HAVE_IN_ADDR_T], [1], [system headers define in_addr_t]) -fi -]) - - AC_DEFUN([MYSQL_PTHREAD_YIELD], [AC_CACHE_CHECK([if pthread_yield takes zero arguments], ac_cv_pthread_yield_zero_arg, [AC_TRY_LINK([#define _GNU_SOURCE @@ -272,25 +194,6 @@ fi #---END: -AC_DEFUN([MYSQL_CHECK_FP_EXCEPT], -[AC_MSG_CHECKING(for type fp_except) -AC_CACHE_VAL(ac_cv_fp_except, -[AC_TRY_RUN([#include -#include -#include -main() -{ - fp_except foo; - foo++; - exit(0); -}], ac_cv_fp_except=yes, ac_cv_fp_except=no, ac_cv_fp_except=no)]) -AC_MSG_RESULT($ac_cv_fp_except) -if test "$ac_cv_fp_except" = "yes" -then - AC_DEFINE([HAVE_FP_EXCEPT], [1], [fp_except from ieeefp.h]) -fi -]) - # From fileutils-3.14/aclocal.m4 # @defmac AC_PROG_CC_STDC diff --git a/configure.in b/configure.in index 0f0649fd3bc..be6f3c8eaec 100644 --- a/configure.in +++ b/configure.in @@ -778,48 +778,6 @@ struct request_info *req; AC_SUBST(WRAPLIBS) if test "$TARGET_LINUX" = "true"; then - AC_MSG_CHECKING([for atomic operations]) - - AC_LANG_SAVE - AC_LANG_CPLUSPLUS - - atom_ops= - AC_TRY_RUN([ -#include -int main() -{ - atomic_t v; - - atomic_set(&v, 23); - atomic_add(5, &v); - return atomic_read(&v) == 28 ? 0 : -1; -} - ], - [AC_DEFINE([HAVE_ATOMIC_ADD], [1], - [atomic_add() from (Linux only)]) - atom_ops="${atom_ops}atomic_add "], - ) - AC_TRY_RUN([ -#include -int main() -{ - atomic_t v; - - atomic_set(&v, 23); - atomic_sub(5, &v); - return atomic_read(&v) == 18 ? 0 : -1; -} - ], - [AC_DEFINE([HAVE_ATOMIC_SUB], [1], - [atomic_sub() from (Linux only)]) - atom_ops="${atom_ops}atomic_sub "], - ) - - if test -z "$atom_ops"; then atom_ops="no"; fi - AC_MSG_RESULT($atom_ops) - - AC_LANG_RESTORE - AC_ARG_WITH(pstack, [ --with-pstack Use the pstack backtrace library], [ USE_PSTACK=$withval ], @@ -871,38 +829,20 @@ fi # Later in this script LIBS will be augmented with a threads library. NON_THREADED_LIBS="$LIBS" -AC_MSG_CHECKING([for int8]) -case $SYSTEM_TYPE in - *netware) - AC_MSG_RESULT([no]) - ;; - *) -AC_TRY_RUN([ -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef HAVE_STDDEF_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H +AC_CHECK_TYPES([int8, uint8, int16, uint16, int32, uint32, int64, uint64, + uchar, uint, ulong],[],[], [ #include -#endif - -int main() -{ - int8 i; - return 0; -} -], -[AC_DEFINE([HAVE_INT_8_16_32], [1], - [whether int8, int16 and int32 types exist]) -AC_MSG_RESULT([yes])], -[AC_MSG_RESULT([no])] -) - ;; -esac +]) +AC_CHECK_TYPES([in_addr_t], [], [], [ +#include +#include +#include +#include +]) +AC_CHECK_TYPES([fp_except], [], [], [ +#include +#include +]) # # Some system specific hacks @@ -1631,6 +1571,20 @@ then fi fi +AC_ARG_WITH([atomic-ops], + AC_HELP_STRING([--with-atomic-ops=rwlocks|smp|up], + [Implement atomic operations using pthread rwlocks or atomic CPU + instructions for multi-processor (default) or uniprocessor + configuration]), , [with_atomic_ops=smp]) +case "$with_atomic_ops" in + "up") AC_DEFINE([MY_ATOMIC_MODE_DUMMY], [1], + [Assume single-CPU mode, no concurrency]) ;; + "rwlocks") AC_DEFINE([MY_ATOMIC_MODE_RWLOCKS], [1], + [Use pthread rwlocks for atomic ops]) ;; + "smp") ;; + *) AC_MSG_ERROR(["$with_atomic_ops" is not a valid value for --with-atomic-ops]) ;; +esac + # Force static compilation to avoid linking problems/get more speed AC_ARG_WITH(mysqld-ldflags, [ --with-mysqld-ldflags Extra linking arguments for mysqld], @@ -1762,16 +1716,6 @@ MYSQL_FUNC_ALLOCA MYSQL_TIMESPEC_TS # Do we have the tzname variable MYSQL_TZNAME -# Do the system files define ulong -MYSQL_CHECK_ULONG -# Do the system files define uchar -MYSQL_CHECK_UCHAR -# Do the system files define uint -MYSQL_CHECK_UINT -# Check for fp_except in ieeefp.h -MYSQL_CHECK_FP_EXCEPT -# Check for IN_ADDR_T -MYSQL_CHECK_IN_ADDR_T # Do the c++ compiler have a bool type MYSQL_CXX_BOOL # Check some common bugs with gcc 2.8.# on sparc diff --git a/include/Makefile.am b/include/Makefile.am index e1ddadb933a..27b359bb6a3 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -31,7 +31,8 @@ noinst_HEADERS = config-win.h config-netware.h \ my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \ thr_lock.h t_ctype.h violite.h md5.h base64.h \ mysql_version.h.in my_handler.h my_time.h decimal.h \ - my_vle.h my_user.h + my_vle.h my_user.h my_atomic.h atomic/nolock.h \ + atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h # mysql_version.h are generated CLEANFILES = mysql_version.h my_config.h readline openssl diff --git a/include/atomic/nolock.h b/include/atomic/nolock.h new file mode 100644 index 00000000000..cf21a94c7de --- /dev/null +++ b/include/atomic/nolock.h @@ -0,0 +1,169 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +#if defined(__i386__) || defined(_M_IX86) +#ifdef MY_ATOMIC_MODE_DUMMY +# define LOCK "" +#else +# define LOCK "lock " +#endif +#ifdef __GNUC__ +#include "x86-gcc.h" +#elif defined(_MSC_VER) +#include "x86-msvc.h" +#endif +#endif + +#ifdef make_atomic_add_body8 + +#ifdef HAVE_INLINE + +#define make_atomic_add(S) \ +static inline uint ## S _my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v) \ +{ \ + make_atomic_add_body ## S; \ + return v; \ +} + +#define make_atomic_swap(S) \ +static inline uint ## S _my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v) \ +{ \ + make_atomic_swap_body ## S; \ + return v; \ +} + +#define make_atomic_cas(S) \ +static inline uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a,\ + uint ## S *cmp, uint ## S set) \ +{ \ + uint8 ret; \ + make_atomic_cas_body ## S; \ + return ret; \ +} + +#define make_atomic_load(S) \ +static inline uint ## S _my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a) \ +{ \ + uint ## S ret; \ + make_atomic_load_body ## S; \ + return ret; \ +} + +#define make_atomic_store(S) \ +static inline void _my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v) \ +{ \ + make_atomic_store_body ## S; \ +} + +#else /* no inline functions */ + +#define make_atomic_add(S) \ +extern uint ## S _my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v); + +#define make_atomic_swap(S) \ +extern uint ## S _my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v); + +#define make_atomic_cas(S) \ +extern uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \ + uint ## S *cmp, uint ## S set); + +#define make_atomic_load(S) \ +extern uint ## S _my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a); + +#define make_atomic_store(S) \ +extern void _my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v); + +#endif + +make_atomic_add( 8) +make_atomic_add(16) +make_atomic_add(32) + +make_atomic_cas( 8) +make_atomic_cas(16) +make_atomic_cas(32) + +make_atomic_load( 8) +make_atomic_load(16) +make_atomic_load(32) + +make_atomic_store( 8) +make_atomic_store(16) +make_atomic_store(32) + +make_atomic_swap( 8) +make_atomic_swap(16) +make_atomic_swap(32) + +#undef make_atomic_add_body8 +#undef make_atomic_cas_body8 +#undef make_atomic_load_body8 +#undef make_atomic_store_body8 +#undef make_atomic_swap_body8 +#undef make_atomic_add_body16 +#undef make_atomic_cas_body16 +#undef make_atomic_load_body16 +#undef make_atomic_store_body16 +#undef make_atomic_swap_body16 +#undef make_atomic_add_body32 +#undef make_atomic_cas_body32 +#undef make_atomic_load_body32 +#undef make_atomic_store_body32 +#undef make_atomic_swap_body32 +#undef make_atomic_add +#undef make_atomic_cas +#undef make_atomic_load +#undef make_atomic_store +#undef make_atomic_swap + +#define my_atomic_add8(a,v,L) _my_atomic_add8(a,v) +#define my_atomic_add16(a,v,L) _my_atomic_add16(a,v) +#define my_atomic_add32(a,v,L) _my_atomic_add32(a,v) + +#define my_atomic_cas8(a,c,v,L) _my_atomic_cas8(a,c,v) +#define my_atomic_cas16(a,c,v,L) _my_atomic_cas16(a,c,v) +#define my_atomic_cas32(a,c,v,L) _my_atomic_cas32(a,c,v) + +#define my_atomic_load8(a,L) _my_atomic_load8(a) +#define my_atomic_load16(a,L) _my_atomic_load16(a) +#define my_atomic_load32(a,L) _my_atomic_load32(a) + +#define my_atomic_store8(a,v,L) _my_atomic_store8(a,v) +#define my_atomic_store16(a,v,L) _my_atomic_store16(a,v) +#define my_atomic_store32(a,v,L) _my_atomic_store32(a,v) + +#define my_atomic_swap8(a,v,L) _my_atomic_swap8(a,v) +#define my_atomic_swap16(a,v,L) _my_atomic_swap16(a,v) +#define my_atomic_swap32(a,v,L) _my_atomic_swap32(a,v) + +#define my_atomic_rwlock_t typedef int +#define my_atomic_rwlock_destroy(name) +#define my_atomic_rwlock_init(name) +#define my_atomic_rwlock_rdlock(name) +#define my_atomic_rwlock_wrlock(name) +#define my_atomic_rwlock_rdunlock(name) +#define my_atomic_rwlock_wrunlock(name) + +#endif + diff --git a/include/atomic/rwlock.h b/include/atomic/rwlock.h new file mode 100644 index 00000000000..ca5be29ab9b --- /dev/null +++ b/include/atomic/rwlock.h @@ -0,0 +1,161 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t; + +#ifdef MY_ATOMIC_EXTRA_DEBUG +#define CHECK_RW if (rw) if (a->rw) assert(rw == a->rw); else a->rw=rw; +#else +#define CHECK_RW +#endif + +#ifdef MY_ATOMIC_MODE_DUMMY +/* + the following can never be enabled by ./configure, one need to put #define in + a source to trigger the following warning. The resulting code will be broken, + it only makes sense to do it to see now test_atomic detects broken + implementations (another way is to run a UP build on an SMP box). +*/ +#warning MY_ATOMIC_MODE_DUMMY and MY_ATOMIC_MODE_RWLOCKS are incompatible +#define my_atomic_rwlock_destroy(name) +#define my_atomic_rwlock_init(name) +#define my_atomic_rwlock_rdlock(name) +#define my_atomic_rwlock_wrlock(name) +#define my_atomic_rwlock_rdunlock(name) +#define my_atomic_rwlock_wrunlock(name) +#else +#define my_atomic_rwlock_destroy(name) pthread_rwlock_destroy(& (name)->rw) +#define my_atomic_rwlock_init(name) pthread_rwlock_init(& (name)->rw, 0) +#define my_atomic_rwlock_rdlock(name) pthread_rwlock_rdlock(& (name)->rw) +#define my_atomic_rwlock_wrlock(name) pthread_rwlock_wrlock(& (name)->rw) +#define my_atomic_rwlock_rdunlock(name) pthread_rwlock_unlock(& (name)->rw) +#define my_atomic_rwlock_wrunlock(name) pthread_rwlock_unlock(& (name)->rw) +#endif + +#ifdef HAVE_INLINE + +#define make_atomic_add(S) \ +static inline uint ## S my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \ +{ \ + uint ## S ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + ret= a->val; \ + a->val+= v; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_swap(S) \ +static inline uint ## S my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \ +{ \ + uint ## S ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + ret= a->val; \ + a->val= v; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_cas(S) \ +static inline uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \ + uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw) \ +{ \ + uint ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + if (ret= (a->val == *cmp)) a->val= set; else *cmp=a->val; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_load(S) \ +static inline uint ## S my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw) \ +{ \ + uint ## S ret; \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_wrlock(rw); \ + ret= a->val; \ + if (rw) my_atomic_rwlock_wrunlock(rw); \ + return ret; \ +} + +#define make_atomic_store(S) \ +static inline void my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \ +{ \ + CHECK_RW; \ + if (rw) my_atomic_rwlock_rdlock(rw); \ + (a)->val= (v); \ + if (rw) my_atomic_rwlock_rdunlock(rw); \ +} + +#else /* no inline functions */ + +#define make_atomic_add(S) \ +extern uint ## S my_atomic_add ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw); + +#define make_atomic_swap(S) \ +extern uint ## S my_atomic_swap ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw); + +#define make_atomic_cas(S) \ +extern uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \ + uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw); + +#define make_atomic_load(S) \ +extern uint ## S my_atomic_load ## S( \ + my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw); + +#define make_atomic_store(S) \ +extern void my_atomic_store ## S( \ + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw); + +#endif + +make_atomic_add( 8) +make_atomic_add(16) +make_atomic_add(32) +make_atomic_add(64) +make_atomic_cas( 8) +make_atomic_cas(16) +make_atomic_cas(32) +make_atomic_cas(64) +make_atomic_load( 8) +make_atomic_load(16) +make_atomic_load(32) +make_atomic_load(64) +make_atomic_store( 8) +make_atomic_store(16) +make_atomic_store(32) +make_atomic_store(64) +make_atomic_swap( 8) +make_atomic_swap(16) +make_atomic_swap(32) +make_atomic_swap(64) +#undef make_atomic_add +#undef make_atomic_cas +#undef make_atomic_load +#undef make_atomic_store +#undef make_atomic_swap +#undef CHECK_RW + + diff --git a/include/atomic/x86-gcc.h b/include/atomic/x86-gcc.h new file mode 100644 index 00000000000..7576db54d69 --- /dev/null +++ b/include/atomic/x86-gcc.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +/* + XXX 64-bit atomic operations can be implemented using + cmpxchg8b, if necessary +*/ + +/* fix -ansi errors while maintaining readability */ +#define asm __asm__ + +#define make_atomic_add_body8 \ + asm volatile (LOCK "xadd %0, %1;" : "+r" (v) , "+m" (a->val)) +#define make_atomic_swap_body8 \ + asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (a->val)) +#define make_atomic_cas_body8 \ + asm volatile (LOCK "cmpxchg %3, %0; setz %2;" \ + : "+m" (a->val), "+a" (*cmp), "=q" (ret): "r" (set)) + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body8 ret=a->val +#define make_atomic_store_body8 a->val=v +#else +/* + Actually 32-bit reads/writes are always atomic on x86 + But we add LOCK here anyway to force memory barriers +*/ +#define make_atomic_load_body8 \ + ret=0; \ + asm volatile (LOCK "cmpxchg %2, %0" \ + : "+m" (a->val), "+a" (ret): "r" (ret)) +#define make_atomic_store_body8 \ + asm volatile ("xchg %0, %1;" : "+m" (a->val) : "r" (v)) +#endif + +#define make_atomic_add_body16 make_atomic_add_body8 +#define make_atomic_add_body32 make_atomic_add_body8 +#define make_atomic_cas_body16 make_atomic_cas_body8 +#define make_atomic_cas_body32 make_atomic_cas_body8 +#define make_atomic_load_body16 make_atomic_load_body8 +#define make_atomic_load_body32 make_atomic_load_body8 +#define make_atomic_store_body16 make_atomic_store_body8 +#define make_atomic_store_body32 make_atomic_store_body8 +#define make_atomic_swap_body16 make_atomic_swap_body8 +#define make_atomic_swap_body32 make_atomic_swap_body8 + diff --git a/include/atomic/x86-msvc.h b/include/atomic/x86-msvc.h new file mode 100644 index 00000000000..19645551196 --- /dev/null +++ b/include/atomic/x86-msvc.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +/* + XXX 64-bit atomic operations can be implemented using + cmpxchg8b, if necessary +*/ + +// Would it be better to use intrinsics ? +// (InterlockedCompareExchange, InterlockedCompareExchange16 +// InterlockedExchangeAdd, InterlockedExchange) + +#define make_atomic_add_body(REG) \ + _asm { \ + _asm mov REG, v \ + _asm LOCK xadd a->val, REG \ + _asm movzx v, REG \ + } +#define make_atomic_cas_body(AREG,REG2) \ + _asm { \ + _asm mov AREG, *cmp \ + _asm mov REG2, set \ + _asm LOCK cmpxchg a->val, REG2 \ + _asm mov *cmp, AREG \ + _asm setz al \ + _asm movzx ret, al \ + } +#define make_atomic_swap_body(REG) \ + _asm { \ + _asm mov REG, v \ + _asm xchg a->val, REG \ + _asm mov v, REG \ + } + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body(AREG,REG) ret=a->val +#define make_atomic_store_body(REG) a->val=v +#else +/* + Actually 32-bit reads/writes are always atomic on x86 + But we add LOCK here anyway to force memory barriers +*/ +#define make_atomic_load_body(AREG,REG2) \ + _asm { \ + _asm mov AREG, 0 \ + _asm mov REG2, AREG \ + _asm LOCK cmpxchg a->val, REG2 \ + _asm mov ret, AREG \ + } +#define make_atomic_store_body(REG) \ + _asm { \ + _asm mov REG, v \ + _asm xchg a->val, REG \ + } +#endif + +#define make_atomic_add_body8 make_atomic_add_body(al) +#define make_atomic_add_body16 make_atomic_add_body(ax) +#define make_atomic_add_body32 make_atomic_add_body(eax) +#define make_atomic_cas_body8 make_atomic_cas_body(al, bl) +#define make_atomic_cas_body16 make_atomic_cas_body(ax, bx) +#define make_atomic_cas_body32 make_atomic_cas_body(eax, ebx) +#define make_atomic_load_body8 make_atomic_load_body(al, bl) +#define make_atomic_load_body16 make_atomic_load_body(ax, bx) +#define make_atomic_load_body32 make_atomic_load_body(eax, ebx) +#define make_atomic_store_body8 make_atomic_store_body(al) +#define make_atomic_store_body16 make_atomic_store_body(ax) +#define make_atomic_store_body32 make_atomic_store_body(eax) +#define make_atomic_swap_body8 make_atomic_swap_body(al) +#define make_atomic_swap_body16 make_atomic_swap_body(ax) +#define make_atomic_swap_body32 make_atomic_swap_body(eax) + diff --git a/include/my_atomic.h b/include/my_atomic.h new file mode 100644 index 00000000000..091edc0f57b --- /dev/null +++ b/include/my_atomic.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +#ifndef atomic_rwlock_init + +#ifdef MY_ATOMIC_EXTRA_DEBUG +#ifndef MY_ATOMIC_MODE_RWLOCKS +#error MY_ATOMIC_EXTRA_DEBUG can be only used with MY_ATOMIC_MODE_RWLOCKS +#endif +#define LOCK_PTR void *rw; +#else +#define LOCK_PTR +#endif + +typedef volatile struct {uint8 val; LOCK_PTR} my_atomic_8_t; +typedef volatile struct {uint16 val; LOCK_PTR} my_atomic_16_t; +typedef volatile struct {uint32 val; LOCK_PTR} my_atomic_32_t; +typedef volatile struct {uint64 val; LOCK_PTR} my_atomic_64_t; + +#ifndef MY_ATOMIC_MODE_RWLOCKS +#include "atomic/nolock.h" +#endif + +#ifndef my_atomic_rwlock_init +#include "atomic/rwlock.h" +#endif + +#define MY_ATOMIC_OK 0 +#define MY_ATOMIC_NOT_1CPU 1 +extern int my_atomic_initialize(); + +#endif + diff --git a/include/my_global.h b/include/my_global.h index 100e695a0de..f2ad3af0b6f 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -181,6 +181,17 @@ #define HOT_DATA #endif +/* + now let's figure out if inline functions are supported + autoconf defines 'inline' to be empty, if not +*/ +#define inline_test_1(X) X ## 1 +#define inline_test_2(X) inline_test_1(X) +#if inline_test_2(inline) != 1 +#define HAVE_INLINE +#endif +#undef inline_test_2 +#undef inline_test_1 /* The following macros are used to control inlining a bit more than @@ -853,26 +864,36 @@ typedef void *gptr; /* Generic pointer */ #else typedef char *gptr; /* Generic pointer */ #endif -#ifndef HAVE_INT_8_16_32 -typedef signed char int8; /* Signed integer >= 8 bits */ -typedef short int16; /* Signed integer >= 16 bits */ -#endif #ifndef HAVE_UCHAR typedef unsigned char uchar; /* Short for unsigned char */ #endif -typedef unsigned char uint8; /* Short for unsigned integer >= 8 bits */ -typedef unsigned short uint16; /* Short for unsigned integer >= 16 bits */ +#ifndef HAVE_INT8 +typedef signed char int8; /* Signed integer >= 8 bits */ +#endif +#ifndef HAVE_UINT8 +typedef unsigned char uint8; /* Unsigned integer >= 8 bits */ +#endif +#ifndef HAVE_INT16 +typedef short int16; +#endif +#ifndef HAVE_UINT16 +typedef unsigned short uint16; +#endif #if SIZEOF_INT == 4 -#ifndef HAVE_INT_8_16_32 -typedef int int32; +#ifndef HAVE_INT32 +typedef int int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned int uint32; #endif -typedef unsigned int uint32; /* Short for unsigned integer >= 32 bits */ #elif SIZEOF_LONG == 4 -#ifndef HAVE_INT_8_16_32 -typedef long int32; +#ifndef HAVE_INT32 +typedef long int32; +#endif +#ifndef HAVE_UINT32 +typedef unsigned long uint32; #endif -typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */ #else #error "Neither int or long is of 4 bytes width" #endif @@ -889,6 +910,12 @@ typedef unsigned long ulonglong; /* ulong or unsigned long long */ typedef long longlong; #endif #endif +#ifndef HAVE_INT64 +typedef longlong int64; +#endif +#ifndef HAVE_UINT64 +typedef ulonglong uint64; +#endif #if defined(NO_CLIENT_LONG_LONG) typedef unsigned long my_ulonglong; diff --git a/include/my_sys.h b/include/my_sys.h index 5024505a821..4ea7cecf0a1 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -821,8 +821,9 @@ extern ulong crc32(ulong crc, const uchar *buf, uint len); extern uint my_set_max_open_files(uint files); void my_free_open_file_info(void); -ulonglong my_getsystime(void); -my_bool my_gethwaddr(uchar *to); +extern ulonglong my_getsystime(void); +extern my_bool my_gethwaddr(uchar *to); +extern int my_getncpus(); #ifdef HAVE_SYS_MMAN_H #include diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index ab5ca6e7be4..0cee54bffde 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -28,7 +28,7 @@ */ #define MYSQL_UDF_PLUGIN 0 /* User-defined function */ #define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */ -#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text [pre]parser */ +#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */ #define MYSQL_MAX_PLUGIN_TYPE_NUM 3 /* The number of plugin types */ /* @@ -95,12 +95,14 @@ struct st_mysql_plugin }; /************************************************************************* - API for Full-text [pre]parser plugin. (MYSQL_FTPARSER_PLUGIN) + API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN) */ -#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0000 +#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100 /* Parsing modes. Set in MYSQL_FTPARSER_PARAM::mode */ +enum enum_ftparser_mode +{ /* Fast and simple mode. This mode is used for indexing, and natural language queries. @@ -109,7 +111,7 @@ struct st_mysql_plugin index. Stopwords or too short/long words should not be returned. The 'boolean_info' argument of mysql_add_word() does not have to be set. */ -#define MYSQL_FTPARSER_SIMPLE_MODE 0 + MYSQL_FTPARSER_SIMPLE_MODE= 0, /* Parse with stopwords mode. This mode is used in boolean searches for @@ -120,7 +122,7 @@ struct st_mysql_plugin or long. The 'boolean_info' argument of mysql_add_word() does not have to be set. */ -#define MYSQL_FTPARSER_WITH_STOPWORDS 1 + MYSQL_FTPARSER_WITH_STOPWORDS= 1, /* Parse in boolean mode. This mode is used to parse a boolean query string. @@ -133,7 +135,8 @@ struct st_mysql_plugin MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored. Instead, use FT_TOKEN_STOPWORD for the token type of such a word. */ -#define MYSQL_FTPARSER_FULL_BOOLEAN_INFO 2 + MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2 +}; /* Token types for boolean mode searching (used for the type member of @@ -198,6 +201,17 @@ typedef struct st_mysql_ftparser_boolean_info char *quot; } MYSQL_FTPARSER_BOOLEAN_INFO; +/* + The following flag means that buffer with a string (document, word) + may be overwritten by the caller before the end of the parsing (that is + before st_mysql_ftparser::deinit() call). If one needs the string + to survive between two successive calls of the parsing function, she + needs to save a copy of it. The flag may be set by MySQL before calling + st_mysql_ftparser::parse(), or it may be set by a plugin before calling + st_mysql_ftparser_param::mysql_parse() or + st_mysql_ftparser_param::mysql_add_word(). +*/ +#define MYSQL_FTFLAGS_NEED_COPY 1 /* An argument of the full-text parser plugin. This structure is @@ -209,22 +223,20 @@ typedef struct st_mysql_ftparser_boolean_info to invoke the MySQL default parser. If plugin's role is to extract textual data from .doc, .pdf or .xml content, it might extract plaintext from the content, and then pass the text to the default - MySQL parser to be parsed. When mysql_parser is called, its param - argument should be given as the mysql_ftparam value. + MySQL parser to be parsed. mysql_add_word: A server callback to add a new word. When parsing a document, the server sets this to point at a function that adds the word to MySQL full-text index. When parsing a search query, this function will add the new word to the list of words to search - for. When mysql_add_word is called, its param argument should be - given as the mysql_ftparam value. boolean_info can be NULL for all - cases except when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO. + for. The boolean_info argument can be NULL for all cases except + when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO. ftparser_state: A generic pointer. The plugin can set it to point to information to be used internally for its own purposes. - mysql_ftparam: This is set by the server. It is passed as the first - argument to the mysql_parse or mysql_add_word callback. The plugin + mysql_ftparam: This is set by the server. It is used by MySQL functions + called via mysql_parse() and mysql_add_word() callback. The plugin should not modify it. cs: Information about the character set of the document or query string. @@ -233,21 +245,26 @@ typedef struct st_mysql_ftparser_boolean_info length: Length of the document or query string, in bytes. + flags: See MYSQL_FTFLAGS_* constants above. + mode: The parsing mode. With boolean operators, with stopwords, or - nothing. See MYSQL_FTPARSER_* constants above. + nothing. See enum_ftparser_mode above. */ typedef struct st_mysql_ftparser_param { - int (*mysql_parse)(void *param, char *doc, int doc_len); - int (*mysql_add_word)(void *param, char *word, int word_len, + int (*mysql_parse)(struct st_mysql_ftparser_param *, + char *doc, int doc_len); + int (*mysql_add_word)(struct st_mysql_ftparser_param *, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info); void *ftparser_state; void *mysql_ftparam; struct charset_info_st *cs; char *doc; int length; - int mode; + int flags; + enum enum_ftparser_mode mode; } MYSQL_FTPARSER_PARAM; /* @@ -265,5 +282,25 @@ struct st_mysql_ftparser int (*init)(MYSQL_FTPARSER_PARAM *param); int (*deinit)(MYSQL_FTPARSER_PARAM *param); }; + +/************************************************************************* + API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_HANDLERTON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/* + The real API is in the sql/handler.h + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_storage_engine +{ + int interface_version; + struct handlerton *handlerton; +}; + #endif diff --git a/mysql-test/extra/binlog_tests/binlog.test b/mysql-test/extra/binlog_tests/binlog.test index ff43debf967..6f7990893f0 100644 --- a/mysql-test/extra/binlog_tests/binlog.test +++ b/mysql-test/extra/binlog_tests/binlog.test @@ -22,7 +22,7 @@ insert t2 values (5); commit; # first COMMIT must be Query_log_event, second - Xid_log_event --replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; drop table t1,t2; @@ -44,8 +44,8 @@ while ($1) commit; drop table t1; --replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events in 'master-bin.000001' from 102; --replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events in 'master-bin.000002' from 102; diff --git a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test index b75a326d5a8..241c96d078b 100644 --- a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test +++ b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test @@ -30,7 +30,7 @@ insert into t2 select * from t1; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -44,7 +44,7 @@ insert into t2 select * from t1; rollback; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -60,7 +60,7 @@ rollback to savepoint my_savepoint; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -78,7 +78,7 @@ commit; select a from t1 order by a; # check that savepoints work :) --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # and when ROLLBACK is not explicit? @@ -100,7 +100,7 @@ connection con2; # logging has been done, we use a user lock. select get_lock("a",10); --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # and when not in a transact1on? @@ -112,7 +112,7 @@ insert into t1 values(9); insert into t2 select * from t1; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # Check that when the query updat1ng the MyISAM table is the first in the @@ -125,13 +125,13 @@ insert into t1 values(10); # first make t1 non-empty begin; insert into t2 select * from t1; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; insert into t1 values(11); commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; @@ -150,7 +150,7 @@ insert into t2 select * from t1; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -163,7 +163,7 @@ insert into t2 select * from t1; rollback; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -179,7 +179,7 @@ rollback to savepoint my_savepoint; commit; --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; delete from t1; @@ -197,7 +197,7 @@ commit; select a from t1 order by a; # check that savepoints work :) --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; # Test for BUG#5714, where a MyISAM update in the transaction used to @@ -258,7 +258,7 @@ disconnect con2; connection con3; select get_lock("lock1",60); --replace_column 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// show binlog events from 102; do release_lock("lock1"); drop table t0,t2; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8923c032dff..af7bdeb0621 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1172,6 +1172,8 @@ sub executable_setup () { sub environment_setup () { + umask(022); + # -------------------------------------------------------------------------- # We might not use a standard installation directory, like /usr/lib. # Set LD_LIBRARY_PATH to make sure we find our installed libraries. @@ -2603,7 +2605,6 @@ sub mysqld_arguments ($$$$$$) { mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir); mtr_add_arg($args, "%s--core", $prefix); mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix); - mtr_add_arg($args, "%s--loose-binlog-show-xid=0", $prefix); mtr_add_arg($args, "%s--default-character-set=latin1", $prefix); mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); @@ -2749,7 +2750,6 @@ sub mysqld_arguments ($$$$$$) { mtr_add_arg($args, "%s--sort_buffer=256K", $prefix); mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix); mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix); - mtr_add_arg($args, "%s--loose-binlog-show-xid=0", $prefix); if ( $opt_ssl_supported ) { @@ -3281,7 +3281,7 @@ sub run_mysqltest ($) { } my $cmdline_mysql= - "$exe_mysql --host=localhost --user=root --password= " . + "$exe_mysql --no-defaults --host=localhost --user=root --password= " . "--port=$master->[0]->{'path_myport'} " . "--socket=$master->[0]->{'path_mysock'}"; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index f56099f3a49..d4e70054d82 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1345,7 +1345,6 @@ start_master() --innodb_data_file_path=ibdata1:128M:autoextend \ --open-files-limit=1024 \ --log-bin-trust-function-creators \ - --loose-binlog-show-xid=0 \ $MASTER_40_ARGS \ $SMALL_SERVER \ $MASTER_MYSQLD_BINLOG_OPT \ @@ -1369,7 +1368,6 @@ start_master() --language=$LANGUAGE \ --innodb_data_file_path=ibdata1:128M:autoextend \ --log-bin-trust-function-creators \ - --loose-binlog-show-xid=0 \ $MASTER_40_ARGS \ $SMALL_SERVER \ $MASTER_MYSQLD_BINLOG_OPT \ @@ -1542,7 +1540,6 @@ start_slave() --master-retry-count=10 \ -O slave_net_timeout=10 \ --log-bin-trust-function-creators \ - --loose-binlog-show-xid=0 \ $SMALL_SERVER \ $SLAVE_MYSQLD_BINLOG_OPT \ $EXTRA_SLAVE_MYSQLD_OPT $EXTRA_SLAVE_OPT \ diff --git a/mysql-test/r/information_schema_part.result b/mysql-test/r/information_schema_part.result index cf49abf888a..e1bc6ef8700 100644 --- a/mysql-test/r/information_schema_part.result +++ b/mysql-test/r/information_schema_part.result @@ -111,3 +111,32 @@ NULL test t1 p0 NULL 1 NULL LINEAR HASH NULL month(f1) NULL NULL 0 0 0 # 1024 0 NULL test t1 p1 NULL 2 NULL LINEAR HASH NULL month(f1) NULL NULL 0 0 0 # 1024 0 # # NULL NULL default 0 default NULL test t1 p2 NULL 3 NULL LINEAR HASH NULL month(f1) NULL NULL 0 0 0 # 1024 0 # # NULL NULL default 0 default drop table t1; +create table t1 (a int) +PARTITION BY RANGE (a) +SUBPARTITION BY LINEAR HASH (a) +(PARTITION p0 VALUES LESS THAN (10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) SUBPARTITION BY LINEAR HASH (a) (PARTITION p0 VALUES LESS THAN (10) ) +select SUBPARTITION_METHOD FROM information_schema.partitions WHERE +table_schema="test" AND table_name="t1"; +SUBPARTITION_METHOD +LINEAR HASH +drop table t1; +create table t1 (a int) +PARTITION BY LIST (a) +(PARTITION p0 VALUES IN +(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, +32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY LIST (a) (PARTITION p0 VALUES IN (10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM information_schema.partitions WHERE +table_schema = "test" AND table_name = "t1"; +PARTITION_DESCRIPTION +10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53 +drop table t1; diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index b8bafd398fe..631165d9fc8 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -748,3 +748,11 @@ f1 f2 f3 111111 aaaaaa 1 222222 bbbbbb 2 drop table t1; +CREATE TABLE t1 (a VARCHAR(255) NOT NULL, +CONSTRAINT pk_a PRIMARY KEY (a))engine=ndb; +CREATE TABLE t2(a VARCHAR(255) NOT NULL, +b VARCHAR(255) NOT NULL, +c VARCHAR(255) NOT NULL, +CONSTRAINT pk_b_c_id PRIMARY KEY (b,c), +CONSTRAINT fk_a FOREIGN KEY(a) REFERENCES t1(a))engine=ndb; +drop table t1, t2; diff --git a/mysql-test/r/ndb_dd_backuprestore.result b/mysql-test/r/ndb_dd_backuprestore.result index 8c39c8c582f..33edf6783e6 100644 --- a/mysql-test/r/ndb_dd_backuprestore.result +++ b/mysql-test/r/ndb_dd_backuprestore.result @@ -155,3 +155,10 @@ DROP TABLE test.t1; DROP TABLE test.t2; DROP TABLE test.t3; DROP TABLE test.t4; +ALTER TABLESPACE table_space1 +DROP DATAFILE './table_space1/datafile.dat' +ENGINE = NDB; +DROP TABLESPACE table_space1 +ENGINE = NDB; +DROP LOGFILE GROUP log_group1 +ENGINE =NDB; diff --git a/mysql-test/r/ndb_dd_basic.result b/mysql-test/r/ndb_dd_basic.result index 008be3aa79f..6c10fbe63b3 100644 --- a/mysql-test/r/ndb_dd_basic.result +++ b/mysql-test/r/ndb_dd_basic.result @@ -11,7 +11,7 @@ ADD UNDOFILE 'undofile02.dat' INITIAL_SIZE = 4M ENGINE=XYZ; Warnings: -Error 1266 Using storage engine MyISAM for table 'lg1' +Error 1286 Unknown table engine 'XYZ' Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP' CREATE TABLESPACE ts1 ADD DATAFILE 'datafile.dat' diff --git a/mysql-test/r/ndb_rename.result b/mysql-test/r/ndb_rename.result new file mode 100644 index 00000000000..2cc2dfb3ff1 --- /dev/null +++ b/mysql-test/r/ndb_rename.result @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS t1,t2; +drop database if exists mysqltest; +CREATE TABLE t1 ( +pk1 INT NOT NULL PRIMARY KEY, +attr1 INT NOT NULL, +attr2 INT, +attr3 VARCHAR(10), +INDEX i1(attr1) +) ENGINE=ndbcluster; +INSERT INTO t1 VALUES (0,0,0,"zero"),(1,1,1,"one"),(2,2,2,"two"); +SELECT * FROM t1 WHERE attr1 = 1; +pk1 attr1 attr2 attr3 +1 1 1 one +alter table t1 rename t2; +SELECT * FROM t2 WHERE attr1 = 1; +pk1 attr1 attr2 attr3 +1 1 1 one +create database ndbtest; +alter table t2 rename ndbtest.t2; +SELECT * FROM ndbtest.t2 WHERE attr1 = 1; +pk1 attr1 attr2 attr3 +1 1 1 one +drop table ndbtest.t2; +drop database ndbtest; diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 3be9f3edee2..2fb7b6942de 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -936,4 +936,16 @@ OPTIMIZE TABLE t1; Table Op Msg_type Msg_text test.t1 optimize note The storage engine for the table doesn't support optimize drop table t1; +create database db99; +use db99; +create table t1 (a int not null) +engine=archive +partition by list (a) +(partition p0 values in (1), partition p1 values in (2)); +insert into t1 values (1), (2); +create index inx on t1 (a); +alter table t1 add partition (partition p2 values in (3)); +alter table t1 drop partition p2; +use test; +drop database db99; End of 5.1 tests diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 1a0b1dd9b3a..a7ca3d9b2fa 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -554,3 +554,26 @@ PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN(5)); insert into t1 values (10); ERROR HY000: Table has no partition for value 10 drop table t1; +create table t1 (v varchar(12)) +partition by range (ascii(v)) +(partition p0 values less than (10)); +drop table t1; +create table t1 (a int) +partition by hash (rand(a)); +ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +create table t1 (a int) +partition by hash(CURTIME() + a); +ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +create table t1 (a int) +partition by hash (NOW()+a); +ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +create table t1 (a int) +partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); +ERROR HY000: This partition function is not allowed +create table t1 (a int) +partition by range (a + (select count(*) from t1)) +(partition p1 values less than (1)); +ERROR HY000: This partition function is not allowed +create table t1 (a char(10)) +partition by hash (extractvalue(a,'a')); +ERROR HY000: The PARTITION function returns the wrong type diff --git a/mysql-test/r/rpl_ndb_log.result b/mysql-test/r/rpl_ndb_log.result index 5f6f040b715..c435fb37531 100644 --- a/mysql-test/r/rpl_ndb_log.result +++ b/mysql-test/r/rpl_ndb_log.result @@ -47,6 +47,10 @@ master-bin.000001 # Table_map 1 # table_id: # (test.t1) flush logs; create table t3 (a int)ENGINE=NDB; start slave; + +let $result_pattern= '%127.0.0.1%root%master-bin.000002%slave-relay-bin.000005%Yes%Yes%0%0%None%' ; + +--source include/wait_slave_status.inc flush logs; stop slave; create table t2 (n int)ENGINE=NDB; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index d6083ab8bfe..77ca2e29669 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -24,11 +24,11 @@ ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does n rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated rpl_ndb_2myisam : BUG#19227 2006-04-20 pekka pk delete apparently not replicated rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er -rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop +#rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement -rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ +#rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly diff --git a/mysql-test/t/information_schema_part.test b/mysql-test/t/information_schema_part.test index 163b04248b8..4cbf21ca1d3 100644 --- a/mysql-test/t/information_schema_part.test +++ b/mysql-test/t/information_schema_part.test @@ -99,3 +99,25 @@ select * from information_schema.partitions where table_schema="test" and table_name="t1"; drop table t1; +# +# Bug 20161 Partitions: SUBPARTITION METHOD doesn't show LINEAR keyword +# +create table t1 (a int) +PARTITION BY RANGE (a) +SUBPARTITION BY LINEAR HASH (a) +(PARTITION p0 VALUES LESS THAN (10)); + +SHOW CREATE TABLE t1; +select SUBPARTITION_METHOD FROM information_schema.partitions WHERE +table_schema="test" AND table_name="t1"; +drop table t1; + +create table t1 (a int) +PARTITION BY LIST (a) +(PARTITION p0 VALUES IN +(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53)); +SHOW CREATE TABLE t1; +SELECT PARTITION_DESCRIPTION FROM information_schema.partitions WHERE +table_schema = "test" AND table_name = "t1"; +drop table t1; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index d11e30ae97d..c7fa5aeee1e 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -713,3 +713,17 @@ select * from t1 order by f1; select * from t1 order by f2; select * from t1 order by f3; drop table t1; + +# +# Bug #18483 Cannot create table with FK constraint +# ndb does not support foreign key constraint, it is silently ignored +# in line with other storage engines +# +CREATE TABLE t1 (a VARCHAR(255) NOT NULL, + CONSTRAINT pk_a PRIMARY KEY (a))engine=ndb; +CREATE TABLE t2(a VARCHAR(255) NOT NULL, + b VARCHAR(255) NOT NULL, + c VARCHAR(255) NOT NULL, + CONSTRAINT pk_b_c_id PRIMARY KEY (b,c), + CONSTRAINT fk_a FOREIGN KEY(a) REFERENCES t1(a))engine=ndb; +drop table t1, t2; diff --git a/mysql-test/t/ndb_dd_backuprestore.test b/mysql-test/t/ndb_dd_backuprestore.test index 65f141288e7..1508cccb46d 100644 --- a/mysql-test/t/ndb_dd_backuprestore.test +++ b/mysql-test/t/ndb_dd_backuprestore.test @@ -160,4 +160,14 @@ DROP TABLE test.t2; DROP TABLE test.t3; DROP TABLE test.t4; +ALTER TABLESPACE table_space1 +DROP DATAFILE './table_space1/datafile.dat' +ENGINE = NDB; + +DROP TABLESPACE table_space1 +ENGINE = NDB; + +DROP LOGFILE GROUP log_group1 +ENGINE =NDB; + #End 5.1 test case diff --git a/mysql-test/t/ndb_rename.test b/mysql-test/t/ndb_rename.test new file mode 100644 index 00000000000..7f9fd0e6984 --- /dev/null +++ b/mysql-test/t/ndb_rename.test @@ -0,0 +1,36 @@ +-- source include/have_ndb.inc +-- source include/not_embedded.inc + +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +drop database if exists mysqltest; +--enable_warnings + +# +# Table rename tests +# + +# +# Create a normal table with primary key +# +CREATE TABLE t1 ( + pk1 INT NOT NULL PRIMARY KEY, + attr1 INT NOT NULL, + attr2 INT, + attr3 VARCHAR(10), + INDEX i1(attr1) +) ENGINE=ndbcluster; + +INSERT INTO t1 VALUES (0,0,0,"zero"),(1,1,1,"one"),(2,2,2,"two"); +SELECT * FROM t1 WHERE attr1 = 1; +alter table t1 rename t2; +SELECT * FROM t2 WHERE attr1 = 1; + +create database ndbtest; +alter table t2 rename ndbtest.t2; +SELECT * FROM ndbtest.t2 WHERE attr1 = 1; + +drop table ndbtest.t2; +drop database ndbtest; + +# End of 4.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index a24124d3fb5..f7676ca471a 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1077,4 +1077,21 @@ OPTIMIZE TABLE t1; drop table t1; +# +# Bug 17310 Partitions: Bugs with archived partitioned tables +# +create database db99; +use db99; +create table t1 (a int not null) +engine=archive +partition by list (a) +(partition p0 values in (1), partition p1 values in (2)); +insert into t1 values (1), (2); +--error 0, 1005 +create index inx on t1 (a); +alter table t1 add partition (partition p2 values in (3)); +alter table t1 drop partition p2; +use test; +drop database db99; + --echo End of 5.1 tests diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 03a2ab41807..659f0b8cef4 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -747,3 +747,31 @@ CREATE TABLE t1(a int) --error ER_NO_PARTITION_FOR_GIVEN_VALUE insert into t1 values (10); drop table t1; + +# +# Bug 18198 Partitions: Verify that erroneus partition functions doesn't work +# +create table t1 (v varchar(12)) +partition by range (ascii(v)) +(partition p0 values less than (10)); +drop table t1; + +-- error 1064 +create table t1 (a int) +partition by hash (rand(a)); +-- error 1064 +create table t1 (a int) +partition by hash(CURTIME() + a); +-- error 1064 +create table t1 (a int) +partition by hash (NOW()+a); +-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +create table t1 (a int) +partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); +-- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +create table t1 (a int) +partition by range (a + (select count(*) from t1)) +(partition p1 values less than (1)); +-- error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +create table t1 (a char(10)) +partition by hash (extractvalue(a,'a')); diff --git a/mysql-test/t/partition_mgm_err2.test b/mysql-test/t/partition_mgm_err2.test index dd96731ccdd..7d15bd7b19f 100644 --- a/mysql-test/t/partition_mgm_err2.test +++ b/mysql-test/t/partition_mgm_err2.test @@ -15,7 +15,7 @@ enable_query_log; --system mkdir $MYSQLTEST_VARDIR/tmp/bug14354 disable_query_log; eval CREATE TABLE t1 (id int) PARTITION BY RANGE(id) ( -PARTITION p1 VALUES LESS THAN (20) ENGINE=myiasm +PARTITION p1 VALUES LESS THAN (20) ENGINE=myisam DATA DIRECTORY="$MYSQLTEST_VARDIR/tmp/bug14354" INDEX DIRECTORY="$MYSQLTEST_VARDIR/tmp/bug14354"); enable_query_log; diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 1241e8cdded..2838427e9e0 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -20,8 +20,7 @@ MYSQLBASEdir= $(prefix) INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a -LDADD = libmysys.a ../dbug/libdbug.a \ - ../strings/libmystrings.a +LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a noinst_HEADERS = mysys_priv.h my_static.h libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_path.c mf_loadpath.c my_file.c \ @@ -32,7 +31,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ my_alloc.c safemalloc.c my_new.cc \ - my_vle.c \ + my_vle.c my_atomic.c \ my_fopen.c my_fstream.c my_getsystime.c \ my_error.c errors.c my_div.c my_messnc.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ @@ -40,7 +39,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_pack.c mf_unixpath.c mf_strip.c \ mf_wcomp.c mf_wfile.c my_gethwaddr.c \ mf_qsort.c mf_qsort2.c mf_sort.c \ - ptr_cmp.c mf_radix.c queues.c \ + ptr_cmp.c mf_radix.c queues.c my_getncpus.c \ tree.c trie.c list.c hash.c array.c string.c typelib.c \ my_copy.c my_append.c my_lib.c \ my_delete.c my_rename.c my_redel.c \ @@ -64,7 +63,6 @@ libmysys_a_LIBADD = @THREAD_LOBJECTS@ # testhash_DEPENDENCIES= $(LIBRARIES) # test_charset_DEPENDENCIES= $(LIBRARIES) # charset2html_DEPENDENCIES= $(LIBRARIES) -EXTRA_PROGRAMS = DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ diff --git a/mysys/my_atomic.c b/mysys/my_atomic.c new file mode 100644 index 00000000000..21b80f0f6a1 --- /dev/null +++ b/mysys/my_atomic.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 +#include + +#ifndef HAVE_INLINE +/* + the following will cause all inline functions to be instantiated +*/ +#define HAVE_INLINE +#define static extern +#endif + +#include + +/* + checks that the current build of atomic ops + can run on this machine + + RETURN + ATOMIC_xxx values, see my_atomic.h +*/ +int my_atomic_initialize() +{ + /* currently the only thing worth checking is SMP/UP issue */ +#ifdef MY_ATOMIC_MODE_DUMMY + return my_getncpus() == 1 ? MY_ATOMIC_OK : MY_ATOMIC_NOT_1CPU; +#else + return MY_ATOMIC_OK; +#endif +} + diff --git a/mysys/my_getncpus.c b/mysys/my_getncpus.c new file mode 100644 index 00000000000..6c45617e496 --- /dev/null +++ b/mysys/my_getncpus.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 */ + +/* get the number of (online) CPUs */ + +#include "mysys_priv.h" +#include + +static int ncpus=0; + +#ifdef _SC_NPROCESSORS_ONLN +int my_getncpus() +{ + if (!ncpus) + ncpus= sysconf(_SC_NPROCESSORS_ONLN); + return ncpus; +} + +#else +/* unknown */ +int my_getncpus() +{ + return 2; +} + +#endif + diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c index 9b937453ce4..eefb10bd26b 100644 --- a/plugin/fulltext/plugin_example.c +++ b/plugin/fulltext/plugin_example.c @@ -144,10 +144,7 @@ static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len) MYSQL_FTPARSER_BOOLEAN_INFO bool_info= { FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 }; - if (param->mode == MYSQL_FTPARSER_FULL_BOOLEAN_INFO) - param->mysql_add_word(param->mysql_ftparam, word, len, &bool_info); - else - param->mysql_add_word(param->mysql_ftparam, word, len, 0); + param->mysql_add_word(param, word, len, &bool_info); } /* diff --git a/sql/Makefile.am b/sql/Makefile.am index 7f711a1e212..d7a6eac72cc 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -35,7 +35,7 @@ LDADD = $(top_builddir)/vio/libvio.a \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/regex/libregex.a \ $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@ - +mysqld_DEPENDENCIES= @mysql_plugin_libs@ $(LDADD) mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ @pstack_libs@ \ @mysql_plugin_libs@ \ diff --git a/sql/discover.cc b/sql/discover.cc index 2a3da55f154..938a05ff4a7 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -119,8 +119,8 @@ int writefrm(const char *name, const void *frmdata, uint len) { if (my_write(file,(byte*)frmdata,len,MYF(MY_WME | MY_NABP))) error= 2; + VOID(my_close(file,MYF(0))); } - VOID(my_close(file,MYF(0))); DBUG_RETURN(error); } /* writefrm */ diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 473fb149871..9a144066057 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -97,6 +97,9 @@ pthread_mutex_t bdb_mutex; static DB_ENV *db_env; static HASH bdb_open_tables; +static const char berkeley_hton_name[]= "BerkeleyDB"; +static const int berkeley_hton_name_length=sizeof(berkeley_hton_name)-1; + const char *berkeley_lock_names[] = { "DEFAULT", "OLDEST", "RANDOM", "YOUNGEST", "EXPIRE", "MAXLOCKS", "MAXWRITE", "MINLOCKS", "MINWRITE", 0 }; @@ -125,47 +128,7 @@ static int berkeley_savepoint(THD* thd, void *savepoint); static int berkeley_release_savepoint(THD* thd, void *savepoint); static handler *berkeley_create_handler(TABLE_SHARE *table); -static const char berkeley_hton_name[]= "BerkeleyDB"; -static const char berkeley_hton_comment[]= - "Supports transactions and page-level locking"; - -handlerton berkeley_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - berkeley_hton_name, - SHOW_OPTION_YES, - berkeley_hton_comment, - DB_TYPE_BERKELEY_DB, - berkeley_init, - 0, /* slot */ - sizeof(DB_TXN *), /* savepoint size */ - berkeley_close_connection, - berkeley_savepoint, /* savepoint_set */ - berkeley_rollback_to_savepoint, /* savepoint_rollback */ - berkeley_release_savepoint, /* savepoint_release */ - berkeley_commit, - berkeley_rollback, - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - berkeley_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - berkeley_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - berkeley_flush_logs, /* Flush logs */ - berkeley_show_status, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +handlerton berkeley_hton; handler *berkeley_create_handler(TABLE_SHARE *table) { @@ -181,12 +144,27 @@ typedef struct st_berkeley_trx_data { /* General functions */ -bool berkeley_init(void) +int berkeley_init(void) { DBUG_ENTER("berkeley_init"); + berkeley_hton.state=SHOW_OPTION_YES; + berkeley_hton.db_type=DB_TYPE_BERKELEY_DB; + berkeley_hton.savepoint_offset=sizeof(DB_TXN *); + berkeley_hton.close_connection=berkeley_close_connection; + berkeley_hton.savepoint_set=berkeley_savepoint; + berkeley_hton.savepoint_rollback=berkeley_rollback_to_savepoint; + berkeley_hton.savepoint_release=berkeley_release_savepoint; + berkeley_hton.commit=berkeley_commit; + berkeley_hton.rollback=berkeley_rollback; + berkeley_hton.create=berkeley_create_handler; + berkeley_hton.panic=berkeley_end; + berkeley_hton.flush_logs=berkeley_flush_logs; + berkeley_hton.show_status=berkeley_show_status; + berkeley_hton.flags=HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME; + if (have_berkeley_db != SHOW_OPTION_YES) - goto error; + return 0; // nothing else to do if (!berkeley_tmpdir) berkeley_tmpdir=mysql_tmpdir; @@ -373,7 +351,6 @@ static int berkeley_release_savepoint(THD* thd, void *savepoint) static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print) { char **all_logs, **free_logs, **a, **f; - uint hton_name_len= strlen(berkeley_hton.name); int error=1; MEM_ROOT **root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC); MEM_ROOT show_logs_root, *old_mem_root= *root_ptr; @@ -401,15 +378,15 @@ static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print) if (f && *f && strcmp(*a, *f) == 0) { f++; - if ((error= stat_print(thd, berkeley_hton.name, hton_name_len, - *a, strlen(*a), + if ((error= stat_print(thd, berkeley_hton_name, + berkeley_hton_name_length, *a, strlen(*a), STRING_WITH_LEN(SHOW_LOG_STATUS_FREE)))) break; } else { - if ((error= stat_print(thd, berkeley_hton.name, hton_name_len, - *a, strlen(*a), + if ((error= stat_print(thd, berkeley_hton_name, + berkeley_hton_name_length, *a, strlen(*a), STRING_WITH_LEN(SHOW_LOG_STATUS_INUSE)))) break; } @@ -2732,15 +2709,17 @@ bool ha_berkeley::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine berkeley_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &berkeley_hton }; mysql_declare_plugin(berkeley) { MYSQL_STORAGE_ENGINE_PLUGIN, - &berkeley_hton, + &berkeley_storage_engine, berkeley_hton_name, "Sleepycat Software", - berkeley_hton_comment, - NULL, /* Plugin Init */ + "Supports transactions and page-level locking", + berkeley_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 21b618b8d6d..50a2aec3963 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -172,7 +172,7 @@ extern char *berkeley_home, *berkeley_tmpdir, *berkeley_logdir; extern long berkeley_lock_scan_time; extern TYPELIB berkeley_lock_typelib; -bool berkeley_init(void); +int berkeley_init(void); int berkeley_end(ha_panic_function type); bool berkeley_flush_logs(void); bool berkeley_show_status(THD *thd, stat_print_fn *print, enum ha_stat_type); diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index f4fc5f47193..76fa9715ef0 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -370,47 +370,7 @@ static int federated_rollback(THD *thd, bool all); /* Federated storage engine handlerton */ -static const char federated_hton_name[]= "FEDERATED"; -static const char federated_hton_comment[]= "Federated MySQL storage engine"; - -handlerton federated_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - federated_hton_name, - SHOW_OPTION_YES, - federated_hton_comment, - DB_TYPE_FEDERATED_DB, - federated_db_init, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - federated_commit, /* commit */ - federated_rollback, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - federated_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - federated_db_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_ALTER_NOT_SUPPORTED, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - +handlerton federated_hton; static handler *federated_create_handler(TABLE_SHARE *table) { @@ -439,9 +399,18 @@ static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, TRUE Error */ -bool federated_db_init() +int federated_db_init() { DBUG_ENTER("federated_db_init"); + + federated_hton.state= SHOW_OPTION_YES; + federated_hton.db_type= DB_TYPE_FEDERATED_DB; + federated_hton.commit= federated_commit; + federated_hton.rollback= federated_rollback; + federated_hton.create= federated_create_handler; + federated_hton.panic= federated_db_end; + federated_hton.flags= HTON_ALTER_NOT_SUPPORTED; + if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)) goto error; if (!hash_init(&federated_open_tables, system_charset_info, 32, 0, 0, @@ -2797,7 +2766,7 @@ int ha_federated::connection_autocommit(bool state) DBUG_ENTER("ha_federated::connection_autocommit"); text= (state == true) ? "SET AUTOCOMMIT=1" : "SET AUTOCOMMIT=0"; DBUG_RETURN(execute_simple_query(text, 16)); -} +} int ha_federated::execute_simple_query(const char *query, int len) @@ -2811,15 +2780,17 @@ int ha_federated::execute_simple_query(const char *query, int len) DBUG_RETURN(0); } +struct st_mysql_storage_engine federated_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &federated_hton }; mysql_declare_plugin(federated) { MYSQL_STORAGE_ENGINE_PLUGIN, - &federated_hton, - federated_hton_name, + &federated_storage_engine, + "FEDERATED", "Patrick Galbraith and Brian Aker, MySQL AB", - federated_hton_comment, - NULL, /* Plugin Init */ + "Federated MySQL storage engine", + federated_db_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, } diff --git a/sql/ha_federated.h b/sql/ha_federated.h index 458ef42ebda..de7f7c4f178 100644 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -307,6 +307,6 @@ public: int execute_simple_query(const char *query, int len); }; -bool federated_db_init(void); +int federated_db_init(void); int federated_db_end(ha_panic_function type); diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 1a7efb42748..15cec9ec4a6 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -26,47 +26,17 @@ static handler *heap_create_handler(TABLE_SHARE *table); -static const char heap_hton_name[]= "MEMORY"; -static const char heap_hton_comment[]= - "Hash based, stored in memory, useful for temporary tables"; +handlerton heap_hton; -handlerton heap_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - heap_hton_name, - SHOW_OPTION_YES, - heap_hton_comment, - DB_TYPE_HEAP, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - heap_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - heap_panic, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CAN_RECREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +int heap_init() +{ + heap_hton.state= SHOW_OPTION_YES; + heap_hton.db_type= DB_TYPE_HEAP; + heap_hton.create= heap_create_handler; + heap_hton.panic= heap_panic; + heap_hton.flags= HTON_CAN_RECREATE; + return 0; +} static handler *heap_create_handler(TABLE_SHARE *table) { @@ -711,14 +681,17 @@ bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine heap_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &heap_hton}; + mysql_declare_plugin(heap) { MYSQL_STORAGE_ENGINE_PLUGIN, - &heap_hton, - heap_hton_name, + &heap_storage_engine, + "MEMORY", "MySQL AB", - heap_hton_comment, - NULL, + "Hash based, stored in memory, useful for temporary tables", + heap_init, NULL, 0x0100, /* 1.0 */ 0 diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 0b2f561e8c9..4be8a81b845 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -42,7 +42,6 @@ have disables the InnoDB inlining in this file. */ #define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1)) -#ifdef WITH_INNOBASE_STORAGE_ENGINE #include "ha_innodb.h" pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */ @@ -206,47 +205,8 @@ static int innobase_release_savepoint(THD* thd, void *savepoint); static handler *innobase_create_handler(TABLE_SHARE *table); static const char innobase_hton_name[]= "InnoDB"; -static const char innobase_hton_comment[]= - "Supports transactions, row-level locking, and foreign keys"; - -handlerton innobase_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - innobase_hton_name, - SHOW_OPTION_YES, - innobase_hton_comment, - DB_TYPE_INNODB, - innobase_init, - 0, /* slot */ - sizeof(trx_named_savept_t), /* savepoint size. TODO: use it */ - innobase_close_connection, - innobase_savepoint, - innobase_rollback_to_savepoint, - innobase_release_savepoint, - innobase_commit, /* commit */ - innobase_rollback, /* rollback */ - innobase_xa_prepare, /* prepare */ - innobase_xa_recover, /* recover */ - innobase_commit_by_xid, /* commit_by_xid */ - innobase_rollback_by_xid, /* rollback_by_xid */ - innobase_create_cursor_view, - innobase_set_cursor_view, - innobase_close_cursor_view, - innobase_create_handler, /* Create a new handler */ - innobase_drop_database, /* Drop a database */ - innobase_end, /* Panic call */ - innobase_start_trx_and_assign_read_view, /* Start Consistent Snapshot */ - innobase_flush_logs, /* Flush logs */ - innobase_show_status, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* alter_tablespace */ - NULL, /* Fill FILES table */ - HTON_NO_FLAGS, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - innobase_release_temporary_latches -}; +handlerton innobase_hton; static handler *innobase_create_handler(TABLE_SHARE *table) { @@ -1230,10 +1190,9 @@ ha_innobase::init_table_handle_for_HANDLER(void) /************************************************************************* Opens an InnoDB database. */ -bool +int innobase_init(void) /*===============*/ - /* out: &innobase_hton, or NULL on error */ { static char current_dir[3]; /* Set if using current lib */ int err; @@ -1242,8 +1201,33 @@ innobase_init(void) DBUG_ENTER("innobase_init"); + innobase_hton.state=have_innodb; + innobase_hton.db_type= DB_TYPE_INNODB; + innobase_hton.savepoint_offset=sizeof(trx_named_savept_t); + innobase_hton.close_connection=innobase_close_connection; + innobase_hton.savepoint_set=innobase_savepoint; + innobase_hton.savepoint_rollback=innobase_rollback_to_savepoint; + innobase_hton.savepoint_release=innobase_release_savepoint; + innobase_hton.commit=innobase_commit; + innobase_hton.rollback=innobase_rollback; + innobase_hton.prepare=innobase_xa_prepare; + innobase_hton.recover=innobase_xa_recover; + innobase_hton.commit_by_xid=innobase_commit_by_xid; + innobase_hton.rollback_by_xid=innobase_rollback_by_xid; + innobase_hton.create_cursor_read_view=innobase_create_cursor_view; + innobase_hton.set_cursor_read_view=innobase_set_cursor_view; + innobase_hton.close_cursor_read_view=innobase_close_cursor_view; + innobase_hton.create=innobase_create_handler; + innobase_hton.drop_database=innobase_drop_database; + innobase_hton.panic=innobase_end; + innobase_hton.start_consistent_snapshot=innobase_start_trx_and_assign_read_view; + innobase_hton.flush_logs=innobase_flush_logs; + innobase_hton.show_status=innobase_show_status; + innobase_hton.flags=HTON_NO_FLAGS; + innobase_hton.release_temporary_latches=innobase_release_temporary_latches; + if (have_innodb != SHOW_OPTION_YES) - goto error; + DBUG_RETURN(0); // nothing else to do ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); @@ -6473,7 +6457,7 @@ innodb_show_status( bool result = FALSE; - if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name), + if (stat_print(thd, innobase_hton_name, strlen(innobase_hton_name), STRING_WITH_LEN(""), str, flen)) { result= TRUE; } @@ -6500,7 +6484,7 @@ innodb_mutex_show_status( ulint rw_lock_count_os_wait= 0; ulint rw_lock_count_os_yield= 0; ulonglong rw_lock_wait_time= 0; - uint hton_name_len= strlen(innobase_hton.name), buf1len, buf2len; + uint hton_name_len= strlen(innobase_hton_name), buf1len, buf2len; DBUG_ENTER("innodb_mutex_show_status"); #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER @@ -6527,7 +6511,7 @@ innodb_mutex_show_status( mutex->count_os_yield, mutex->lspent_time/1000); - if (stat_print(thd, innobase_hton.name, + if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, buf1len, buf2, buf2len)) { #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER @@ -6557,7 +6541,7 @@ innodb_mutex_show_status( rw_lock_count_os_wait, rw_lock_count_os_yield, rw_lock_wait_time/1000); - if (stat_print(thd, innobase_hton.name, hton_name_len, + if (stat_print(thd, innobase_hton_name, hton_name_len, STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) { DBUG_RETURN(1); } @@ -7459,19 +7443,20 @@ bool ha_innobase::check_if_incompatible_data( return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine innobase_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &innobase_hton}; mysql_declare_plugin(innobase) { MYSQL_STORAGE_ENGINE_PLUGIN, - &innobase_hton, + &innobase_storage_engine, innobase_hton_name, "Innobase OY", - innobase_hton_comment, - NULL, /* Plugin Init */ + "Supports transactions, row-level locking, and foreign keys", + innobase_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, 0 } mysql_declare_plugin_end; -#endif diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 4f0c9eb151b..638ecc432b9 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -249,7 +249,7 @@ extern ulong srv_thread_concurrency; extern ulong srv_commit_concurrency; } -bool innobase_init(void); +int innobase_init(void); int innobase_end(ha_panic_function type); bool innobase_flush_logs(void); uint innobase_get_free_space(void); diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 40081c975c8..d11eb7aa891 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -52,63 +52,11 @@ TYPELIB myisam_stats_method_typelib= { ** MyISAM tables *****************************************************************************/ -static handler *myisam_create_handler(TABLE_SHARE *table); - -/* MyISAM handlerton */ - -static const char myisam_hton_name[]= "MyISAM"; -static const char myisam_hton_comment[]= - "Default engine as of MySQL 3.23 with great performance"; - -handlerton myisam_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - myisam_hton_name, - SHOW_OPTION_YES, - myisam_hton_comment, - DB_TYPE_MYISAM, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - /* - MyISAM doesn't support transactions and doesn't have - transaction-dependent context: cursors can survive a commit. - */ - myisam_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - mi_panic,/* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CAN_RECREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - - static handler *myisam_create_handler(TABLE_SHARE *table) { return new ha_myisam(table); } - // collect errors printed by mi_check routines static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, @@ -1798,17 +1746,32 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +handlerton myisam_hton; + +static int myisam_init() +{ + myisam_hton.state=SHOW_OPTION_YES; + myisam_hton.db_type=DB_TYPE_MYISAM; + myisam_hton.create=myisam_create_handler; + myisam_hton.panic=mi_panic; + myisam_hton.flags=HTON_CAN_RECREATE; + return 0; +} + +struct st_mysql_storage_engine myisam_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &myisam_hton }; mysql_declare_plugin(myisam) { MYSQL_STORAGE_ENGINE_PLUGIN, - &myisam_hton, - myisam_hton_name, + &myisam_storage_engine, + "MyISAM", "MySQL AB", - myisam_hton_comment, - NULL, /* Plugin Init */ + "Default engine as of MySQL 3.23 with great performance", + myisam_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 } mysql_declare_plugin_end; + diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index f4a052cea8a..b874923a077 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -38,47 +38,7 @@ static handler *myisammrg_create_handler(TABLE_SHARE *table); /* MyISAM MERGE handlerton */ -static const char myisammrg_hton_name[]= "MRG_MYISAM"; -static const char myisammrg_hton_comment[]= - "Collection of identical MyISAM tables"; - -handlerton myisammrg_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - myisammrg_hton_name, - SHOW_OPTION_YES, - myisammrg_hton_comment, - DB_TYPE_MRG_MYISAM, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - myisammrg_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - myrg_panic, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill Files Table */ - HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +handlerton myisammrg_hton; static handler *myisammrg_create_handler(TABLE_SHARE *table) { @@ -580,14 +540,27 @@ bool ha_myisammrg::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_NO; } +static int myisammrg_init() +{ + myisammrg_hton.state=SHOW_OPTION_YES; + myisammrg_hton.db_type=DB_TYPE_MRG_MYISAM; + myisammrg_hton.create=myisammrg_create_handler; + myisammrg_hton.panic=myrg_panic; + myisammrg_hton.flags= HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE; + return 0; +} + +struct st_mysql_storage_engine myisammrg_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &myisammrg_hton }; + mysql_declare_plugin(myisammrg) { MYSQL_STORAGE_ENGINE_PLUGIN, - &myisammrg_hton, - myisammrg_hton_name, + &myisammrg_storage_engine, + "MRG_MYISAM", "MySQL AB", - myisammrg_hton_comment, - NULL, /* Plugin Init */ + "Collection of identical MyISAM tables", + myisammrg_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 3425c638005..62a5502d635 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -63,26 +63,13 @@ static const int max_transactions= 3; // should really be 2 but there is a trans static uint ndbcluster_partition_flags(); static uint ndbcluster_alter_table_flags(uint flags); -static bool ndbcluster_init(void); +static int ndbcluster_init(void); static int ndbcluster_end(ha_panic_function flag); static bool ndbcluster_show_status(THD*,stat_print_fn *,enum ha_stat_type); static int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info); static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond); -static const char ndbcluster_hton_name[]= "ndbcluster"; -static const char ndbcluster_hton_comment[]= "Clustered, fault-tolerant tables"; - -handlerton ndbcluster_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - "ndbcluster", - SHOW_OPTION_YES, - "Clustered, fault-tolerant tables", - DB_TYPE_NDBCLUSTER, - ndbcluster_init, - ~(uint)0, /* slot */ - /* below are initialized by name in ndbcluster_init() */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; +handlerton ndbcluster_hton; static handler *ndbcluster_create_handler(TABLE_SHARE *table) { @@ -4661,7 +4648,7 @@ int ha_ndbcluster::create(const char *name, share->db, share->table_name, m_table->getObjectId(), m_table->getObjectVersion(), - SOT_CREATE_TABLE); + SOT_CREATE_TABLE, 0, 0, 1); break; } } @@ -4934,13 +4921,17 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) { NDBDICT *dict; char old_dbname[FN_HEADLEN]; + char new_dbname[FN_HEADLEN]; char new_tabname[FN_HEADLEN]; const NDBTAB *orig_tab; int result; + bool recreate_indexes= FALSE; + NDBDICT::List index_list; DBUG_ENTER("ha_ndbcluster::rename_table"); DBUG_PRINT("info", ("Renaming %s to %s", from, to)); set_dbname(from, old_dbname); + set_dbname(to, new_dbname); set_tabname(from); set_tabname(to, new_tabname); @@ -4965,6 +4956,11 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) DBUG_ASSERT(r == 0); } #endif + if (my_strcasecmp(system_charset_info, new_dbname, old_dbname)) + { + dict->listIndexes(index_list, *orig_tab); + recreate_indexes= TRUE; + } // Change current database to that of target table set_dbname(to); ndb->setDatabaseName(m_dbname); @@ -5043,7 +5039,33 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) old_dbname, m_tabname, ndb_table_id, ndb_table_version, SOT_RENAME_TABLE, - m_dbname, new_tabname); + m_dbname, new_tabname, 1); + } + + // If we are moving tables between databases, we need to recreate + // indexes + if (recreate_indexes) + { + for (unsigned i = 0; i < index_list.count; i++) + { + NDBDICT::List::Element& index_el = index_list.elements[i]; + // Recreate any indexes not stored in the system database + if (my_strcasecmp(system_charset_info, + index_el.database, NDB_SYSTEM_DATABASE)) + { + set_dbname(from); + ndb->setDatabaseName(m_dbname); + const NDBINDEX * index= dict->getIndexGlobal(index_el.name, new_tab); + DBUG_PRINT("info", ("Creating index %s/%s", + index_el.database, index->getName())); + dict->createIndex(*index, new_tab); + DBUG_PRINT("info", ("Dropping index %s/%s", + index_el.database, index->getName())); + set_dbname(from); + ndb->setDatabaseName(m_dbname); + dict->dropIndexGlobal(*index); + } + } } if (share) free_share(&share); @@ -5066,6 +5088,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, const char *db, const char *table_name) { + THD *thd= current_thd; DBUG_ENTER("ha_ndbcluster::ndbcluster_delete_table"); NDBDICT *dict= ndb->getDictionary(); #ifdef HAVE_NDB_BINLOG @@ -5097,7 +5120,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, ndb_table_version= h->m_table->getObjectVersion(); } #endif - h->release_metadata(current_thd, ndb); + h->release_metadata(thd, ndb); } else { @@ -5163,11 +5186,11 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb, if (!IS_TMP_PREFIX(table_name) && share) { - ndbcluster_log_schema_op(current_thd, share, - current_thd->query, current_thd->query_length, + ndbcluster_log_schema_op(thd, share, + thd->query, thd->query_length, share->db, share->table_name, ndb_table_id, ndb_table_version, - SOT_DROP_TABLE); + SOT_DROP_TABLE, 0, 0, 1); } else if (table_dropped && share && share->op) /* ndbcluster_log_schema_op will do a force GCP */ @@ -5746,6 +5769,7 @@ int ndbcluster_drop_database_impl(const char *path) static void ndbcluster_drop_database(char *path) { + THD *thd= current_thd; DBUG_ENTER("ndbcluster_drop_database"); #ifdef HAVE_NDB_BINLOG /* @@ -5763,9 +5787,9 @@ static void ndbcluster_drop_database(char *path) #ifdef HAVE_NDB_BINLOG char db[FN_REFLEN]; ha_ndbcluster::set_dbname(path, db); - ndbcluster_log_schema_op(current_thd, 0, - current_thd->query, current_thd->query_length, - db, "", 0, 0, SOT_DROP_DB); + ndbcluster_log_schema_op(thd, 0, + thd->query, thd->query_length, + db, "", 0, 0, SOT_DROP_DB, 0, 0, 0); #endif DBUG_VOID_RETURN; } @@ -6107,17 +6131,18 @@ static int connect_callback() } extern int ndb_dictionary_is_mysqld; -static bool ndbcluster_init() + +static int ndbcluster_init() { int res; DBUG_ENTER("ndbcluster_init"); ndb_dictionary_is_mysqld= 1; - if (have_ndbcluster != SHOW_OPTION_YES) - goto ndbcluster_init_error; { handlerton &h= ndbcluster_hton; + h.state= have_ndbcluster; + h.db_type= DB_TYPE_NDBCLUSTER; h.close_connection= ndbcluster_close_connection; h.commit= ndbcluster_commit; h.rollback= ndbcluster_rollback; @@ -6135,6 +6160,9 @@ static bool ndbcluster_init() h.flags= HTON_TEMPORARY_NOT_SUPPORTED; } + if (have_ndbcluster != SHOW_OPTION_YES) + DBUG_RETURN(0); // nothing else to do + // Set connectstring if specified if (opt_ndbcluster_connectstring != 0) DBUG_PRINT("connectstring", ("%s", opt_ndbcluster_connectstring)); @@ -6206,7 +6234,7 @@ static bool ndbcluster_init() if (ndbcluster_binlog_start()) goto ndbcluster_init_error; #endif /* HAVE_NDB_BINLOG */ - + pthread_mutex_init(&LOCK_ndb_util_thread, MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_ndb_util_thread, NULL); @@ -6222,7 +6250,7 @@ static bool ndbcluster_init() pthread_cond_destroy(&COND_ndb_util_thread); goto ndbcluster_init_error; } - + ndbcluster_inited= 1; DBUG_RETURN(FALSE); @@ -6840,6 +6868,7 @@ static void dbug_print_open_tables() */ int handle_trailing_share(NDB_SHARE *share) { + THD *thd= current_thd; static ulong trailing_share_id= 0; DBUG_ENTER("handle_trailing_share"); @@ -6850,7 +6879,7 @@ int handle_trailing_share(NDB_SHARE *share) bzero((char*) &table_list,sizeof(table_list)); table_list.db= share->db; table_list.alias= table_list.table_name= share->table_name; - close_cached_tables(current_thd, 0, &table_list, TRUE); + close_cached_tables(thd, 0, &table_list, TRUE); pthread_mutex_lock(&ndbcluster_mutex); if (!--share->use_count) @@ -9383,9 +9412,8 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print, ndb_number_of_storage_nodes, ndb_number_of_ready_storage_nodes, ndb_connect_count); - if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name), - "connection", strlen("connection"), - buf, buflen)) + if (stat_print(thd, ndbcluster_hton_name, ndbcluster_hton_name_length, + STRING_WITH_LEN("connection"), buf, buflen)) DBUG_RETURN(TRUE); if (get_thd_ndb(thd) && get_thd_ndb(thd)->ndb) @@ -9399,7 +9427,7 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print, my_snprintf(buf, sizeof(buf), "created=%u, free=%u, sizeof=%u", tmp.m_created, tmp.m_free, tmp.m_sizeof); - if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name), + if (stat_print(thd, ndbcluster_hton_name, ndbcluster_hton_name_length, tmp.m_name, strlen(tmp.m_name), buf, buflen)) DBUG_RETURN(TRUE); } @@ -9954,13 +9982,13 @@ int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info) thd->query, thd->query_length, "", info->tablespace_name, 0, 0, - SOT_TABLESPACE); + SOT_TABLESPACE, 0, 0, 0); else ndbcluster_log_schema_op(thd, 0, thd->query, thd->query_length, "", info->logfile_group_name, 0, 0, - SOT_LOGFILE_GROUP); + SOT_LOGFILE_GROUP, 0, 0, 0); #endif DBUG_RETURN(FALSE); @@ -10064,8 +10092,8 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond) strlen(ts.getDefaultLogfileGroup()), system_charset_info); table->field[c++]->set_null(); // LOGFILE_GROUP_NUMBER - table->field[c++]->store(ndbcluster_hton.name, - strlen(ndbcluster_hton.name), + table->field[c++]->store(ndbcluster_hton_name, + ndbcluster_hton_name_length, system_charset_info); // ENGINE table->field[c++]->set_null(); // FULLTEXT_KEYS @@ -10158,8 +10186,8 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond) strlen(uf.getLogfileGroup()), system_charset_info); table->field[c++]->store(uf.getLogfileGroupId()); // LOGFILE_GROUP_NUMBER - table->field[c++]->store(ndbcluster_hton.name, - strlen(ndbcluster_hton.name), + table->field[c++]->store(ndbcluster_hton_name, + ndbcluster_hton_name_length, system_charset_info); // ENGINE table->field[c++]->set_null(); // FULLTEXT_KEYS @@ -10205,15 +10233,17 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_RETURN(0); } +struct st_mysql_storage_engine ndbcluster_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &ndbcluster_hton }; mysql_declare_plugin(ndbcluster) { MYSQL_STORAGE_ENGINE_PLUGIN, - &ndbcluster_hton, + &ndbcluster_storage_engine, ndbcluster_hton_name, "MySQL AB", - ndbcluster_hton_comment, - NULL, /* Plugin Init */ + "Clustered, fault-tolerant tables", + ndbcluster_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, 0 diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index badca69941a..3c8a4d260a3 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -903,3 +903,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name); void ndbcluster_print_error(int error, const NdbOperation *error_op); + +static const char ndbcluster_hton_name[]= "ndbcluster"; +static const int ndbcluster_hton_name_length=sizeof(ndbcluster_hton_name)-1; + diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 144c073d565..3f9c5bf993e 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -39,6 +39,12 @@ #define NDB_APPLY_TABLE_FILE "./" NDB_REP_DB "/" NDB_APPLY_TABLE #define NDB_SCHEMA_TABLE_FILE "./" NDB_REP_DB "/" NDB_SCHEMA_TABLE +/* + Timeout for syncing schema events between + mysql servers, and between mysql server and the binlog +*/ +const int opt_ndb_sync_timeout= 120; + /* Flag showing if the ndb injector thread is running, if so == 1 -1 if it was started but later stopped for some reason @@ -498,6 +504,7 @@ ndbcluster_binlog_log_query(THD *thd, enum_binlog_command binlog_command, { case LOGCOM_CREATE_TABLE: type= SOT_CREATE_TABLE; + DBUG_ASSERT(FALSE); break; case LOGCOM_ALTER_TABLE: type= SOT_ALTER_TABLE; @@ -505,9 +512,11 @@ ndbcluster_binlog_log_query(THD *thd, enum_binlog_command binlog_command, break; case LOGCOM_RENAME_TABLE: type= SOT_RENAME_TABLE; + DBUG_ASSERT(FALSE); break; case LOGCOM_DROP_TABLE: type= SOT_DROP_TABLE; + DBUG_ASSERT(FALSE); break; case LOGCOM_CREATE_DB: type= SOT_CREATE_DB; @@ -519,12 +528,14 @@ ndbcluster_binlog_log_query(THD *thd, enum_binlog_command binlog_command, break; case LOGCOM_DROP_DB: type= SOT_DROP_DB; + DBUG_ASSERT(FALSE); break; } if (log) { ndbcluster_log_schema_op(thd, 0, query, query_length, - db, table_name, 0, 0, type); + db, table_name, 0, 0, type, + 0, 0, 0); } DBUG_VOID_RETURN; } @@ -961,354 +972,6 @@ static char *ndb_pack_varchar(const NDBCOL *col, char *buf, return buf; } -/* - log query in schema table -*/ -static void ndb_report_waiting(const char *key, - int the_time, - const char *op, - const char *obj) -{ - ulonglong ndb_latest_epoch= 0; - const char *proc_info= ""; - pthread_mutex_lock(&injector_mutex); - if (injector_ndb) - ndb_latest_epoch= injector_ndb->getLatestGCI(); - if (injector_thd) - proc_info= injector_thd->proc_info; - pthread_mutex_unlock(&injector_mutex); - sql_print_information("NDB %s:" - " waiting max %u sec for %s %s." - " epochs: (%u,%u,%u)" - " injector proc_info: %s" - ,key, the_time, op, obj - ,(uint)ndb_latest_handled_binlog_epoch - ,(uint)ndb_latest_received_binlog_epoch - ,(uint)ndb_latest_epoch - ,proc_info - ); -} - -int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, - const char *query, int query_length, - const char *db, const char *table_name, - uint32 ndb_table_id, - uint32 ndb_table_version, - enum SCHEMA_OP_TYPE type, - const char *new_db, const char *new_table_name) -{ - DBUG_ENTER("ndbcluster_log_schema_op"); - Thd_ndb *thd_ndb= get_thd_ndb(thd); - if (!thd_ndb) - { - if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb())) - { - sql_print_error("Could not allocate Thd_ndb object"); - DBUG_RETURN(1); - } - set_thd_ndb(thd, thd_ndb); - } - - DBUG_PRINT("enter", - ("query: %s db: %s table_name: %s thd_ndb->options: %d", - query, db, table_name, thd_ndb->options)); - if (!schema_share || thd_ndb->options & TNO_NO_LOG_SCHEMA_OP) - { - DBUG_RETURN(0); - } - - char tmp_buf2[FN_REFLEN]; - const char *type_str; - switch (type) - { - case SOT_DROP_TABLE: - /* drop database command, do not log at drop table */ - if (thd->lex->sql_command == SQLCOM_DROP_DB) - DBUG_RETURN(0); - /* redo the drop table query as is may contain several tables */ - query= tmp_buf2; - query_length= (uint) (strxmov(tmp_buf2, "drop table `", - table_name, "`", NullS) - tmp_buf2); - type_str= "drop table"; - break; - case SOT_RENAME_TABLE: - /* redo the rename table query as is may contain several tables */ - query= tmp_buf2; - query_length= (uint) (strxmov(tmp_buf2, "rename table `", - db, ".", table_name, "` to `", - new_db, ".", new_table_name, "`", NullS) - tmp_buf2); - type_str= "rename table"; - break; - case SOT_CREATE_TABLE: - type_str= "create table"; - break; - case SOT_ALTER_TABLE: - type_str= "create table"; - break; - case SOT_DROP_DB: - type_str= "drop db"; - break; - case SOT_CREATE_DB: - type_str= "create db"; - break; - case SOT_ALTER_DB: - type_str= "alter db"; - break; - case SOT_TABLESPACE: - type_str= "tablespace"; - break; - case SOT_LOGFILE_GROUP: - type_str= "logfile group"; - break; - default: - abort(); /* should not happen, programming error */ - } - - NDB_SCHEMA_OBJECT *ndb_schema_object; - { - char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), db, table_name, ""); - ndb_schema_object= ndb_get_schema_object(key, TRUE, FALSE); - } - - const NdbError *ndb_error= 0; - uint32 node_id= g_ndb_cluster_connection->node_id(); - Uint64 epoch= 0; - MY_BITMAP schema_subscribers; - uint32 bitbuf[sizeof(ndb_schema_object->slock)/4]; - uint32 bitbuf_e[sizeof(bitbuf)]; - bzero((char *)bitbuf_e, sizeof(bitbuf_e)); - { - int i, updated= 0; - int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); - bitmap_init(&schema_subscribers, bitbuf, sizeof(bitbuf)*8, false); - bitmap_set_all(&schema_subscribers); - (void) pthread_mutex_lock(&schema_share->mutex); - for (i= 0; i < no_storage_nodes; i++) - { - MY_BITMAP *table_subscribers= &schema_share->subscriber_bitmap[i]; - if (!bitmap_is_clear_all(table_subscribers)) - { - bitmap_intersect(&schema_subscribers, - table_subscribers); - updated= 1; - } - } - (void) pthread_mutex_unlock(&schema_share->mutex); - if (updated) - bitmap_clear_bit(&schema_subscribers, node_id); - else - bitmap_clear_all(&schema_subscribers); - - if (ndb_schema_object) - { - (void) pthread_mutex_lock(&ndb_schema_object->mutex); - memcpy(ndb_schema_object->slock, schema_subscribers.bitmap, - sizeof(ndb_schema_object->slock)); - (void) pthread_mutex_unlock(&ndb_schema_object->mutex); - } - - DBUG_DUMP("schema_subscribers", (char*)schema_subscribers.bitmap, - no_bytes_in_map(&schema_subscribers)); - DBUG_PRINT("info", ("bitmap_is_clear_all(&schema_subscribers): %d", - bitmap_is_clear_all(&schema_subscribers))); - } - - Ndb *ndb= thd_ndb->ndb; - char save_db[FN_REFLEN]; - strcpy(save_db, ndb->getDatabaseName()); - - char tmp_buf[FN_REFLEN]; - NDBDICT *dict= ndb->getDictionary(); - ndb->setDatabaseName(NDB_REP_DB); - Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE); - const NDBTAB *ndbtab= ndbtab_g.get_table(); - NdbTransaction *trans= 0; - int retries= 100; - const NDBCOL *col[SCHEMA_SIZE]; - unsigned sz[SCHEMA_SIZE]; - - if (ndbtab == 0) - { - if (strcmp(NDB_REP_DB, db) != 0 || - strcmp(NDB_SCHEMA_TABLE, table_name)) - { - ndb_error= &dict->getNdbError(); - } - goto end; - } - - { - uint i; - for (i= 0; i < SCHEMA_SIZE; i++) - { - col[i]= ndbtab->getColumn(i); - if (i != SCHEMA_QUERY_I) - { - sz[i]= col[i]->getLength(); - DBUG_ASSERT(sz[i] <= sizeof(tmp_buf)); - } - } - } - - while (1) - { - const char *log_db= db; - const char *log_tab= table_name; - const char *log_subscribers= (char*)schema_subscribers.bitmap; - uint32 log_type= (uint32)type; - if ((trans= ndb->startTransaction()) == 0) - goto err; - while (1) - { - NdbOperation *op= 0; - int r= 0; - r|= (op= trans->getNdbOperation(ndbtab)) == 0; - DBUG_ASSERT(r == 0); - r|= op->writeTuple(); - DBUG_ASSERT(r == 0); - - /* db */ - ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, log_db, strlen(log_db)); - r|= op->equal(SCHEMA_DB_I, tmp_buf); - DBUG_ASSERT(r == 0); - /* name */ - ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, log_tab, - strlen(log_tab)); - r|= op->equal(SCHEMA_NAME_I, tmp_buf); - DBUG_ASSERT(r == 0); - /* slock */ - DBUG_ASSERT(sz[SCHEMA_SLOCK_I] == sizeof(bitbuf)); - r|= op->setValue(SCHEMA_SLOCK_I, log_subscribers); - DBUG_ASSERT(r == 0); - /* query */ - { - NdbBlob *ndb_blob= op->getBlobHandle(SCHEMA_QUERY_I); - DBUG_ASSERT(ndb_blob != 0); - uint blob_len= query_length; - const char* blob_ptr= query; - r|= ndb_blob->setValue(blob_ptr, blob_len); - DBUG_ASSERT(r == 0); - } - /* node_id */ - r|= op->setValue(SCHEMA_NODE_ID_I, node_id); - DBUG_ASSERT(r == 0); - /* epoch */ - r|= op->setValue(SCHEMA_EPOCH_I, epoch); - DBUG_ASSERT(r == 0); - /* id */ - r|= op->setValue(SCHEMA_ID_I, ndb_table_id); - DBUG_ASSERT(r == 0); - /* version */ - r|= op->setValue(SCHEMA_VERSION_I, ndb_table_version); - DBUG_ASSERT(r == 0); - /* type */ - r|= op->setValue(SCHEMA_TYPE_I, log_type); - DBUG_ASSERT(r == 0); - if (log_db != new_db && new_db && new_table_name) - { - log_db= new_db; - log_tab= new_table_name; - log_subscribers= (const char *)bitbuf_e; // no ack expected on this - log_type= (uint32)SOT_RENAME_TABLE_NEW; - continue; - } - break; - } - if (trans->execute(NdbTransaction::Commit) == 0) - { - dict->forceGCPWait(); - DBUG_PRINT("info", ("logged: %s", query)); - break; - } -err: - const NdbError *this_error= trans ? - &trans->getNdbError() : &ndb->getNdbError(); - if (this_error->status == NdbError::TemporaryError) - { - if (retries--) - { - if (trans) - ndb->closeTransaction(trans); - continue; // retry - } - } - ndb_error= this_error; - break; - } -end: - if (ndb_error) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_GET_ERRMSG, ER(ER_GET_ERRMSG), - ndb_error->code, - ndb_error->message, - "Could not log query '%s' on other mysqld's"); - - if (trans) - ndb->closeTransaction(trans); - ndb->setDatabaseName(save_db); - - /* - Wait for other mysqld's to acknowledge the table operation - */ - if (ndb_error == 0 && - !bitmap_is_clear_all(&schema_subscribers)) - { - int max_timeout= 10; - (void) pthread_mutex_lock(&ndb_schema_object->mutex); - while (1) - { - struct timespec abstime; - int i; - int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); - set_timespec(abstime, 1); - int ret= pthread_cond_timedwait(&injector_cond, - &ndb_schema_object->mutex, - &abstime); - - (void) pthread_mutex_lock(&schema_share->mutex); - for (i= 0; i < no_storage_nodes; i++) - { - /* remove any unsubscribed from schema_subscribers */ - MY_BITMAP *tmp= &schema_share->subscriber_bitmap[i]; - if (!bitmap_is_clear_all(tmp)) - bitmap_intersect(&schema_subscribers, tmp); - } - (void) pthread_mutex_unlock(&schema_share->mutex); - - /* remove any unsubscribed from ndb_schema_object->slock */ - bitmap_intersect(&ndb_schema_object->slock_bitmap, &schema_subscribers); - - DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", - (char*)ndb_schema_object->slock_bitmap.bitmap, - no_bytes_in_map(&ndb_schema_object->slock_bitmap)); - - if (bitmap_is_clear_all(&ndb_schema_object->slock_bitmap)) - break; - - if (ret) - { - max_timeout--; - if (max_timeout == 0) - { - sql_print_error("NDB %s: distributing %s timed out. Ignoring...", - type_str, ndb_schema_object->key); - break; - } - if (ndb_extra_logging) - ndb_report_waiting(type_str, max_timeout, - "distributing", ndb_schema_object->key); - } - } - (void) pthread_mutex_unlock(&ndb_schema_object->mutex); - } - - if (ndb_schema_object) - ndb_free_schema_object(&ndb_schema_object, FALSE); - - DBUG_RETURN(0); -} - /* acknowledge handling of schema operation */ @@ -1445,7 +1108,7 @@ ndbcluster_update_slock(THD *thd, } end: if (ndb_error) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), ndb_error->code, ndb_error->message, @@ -1457,6 +1120,383 @@ end: DBUG_RETURN(0); } +/* + log query in schema table +*/ +static void ndb_report_waiting(const char *key, + int the_time, + const char *op, + const char *obj) +{ + ulonglong ndb_latest_epoch= 0; + const char *proc_info= ""; + pthread_mutex_lock(&injector_mutex); + if (injector_ndb) + ndb_latest_epoch= injector_ndb->getLatestGCI(); + if (injector_thd) + proc_info= injector_thd->proc_info; + pthread_mutex_unlock(&injector_mutex); + sql_print_information("NDB %s:" + " waiting max %u sec for %s %s." + " epochs: (%u,%u,%u)" + " injector proc_info: %s" + ,key, the_time, op, obj + ,(uint)ndb_latest_handled_binlog_epoch + ,(uint)ndb_latest_received_binlog_epoch + ,(uint)ndb_latest_epoch + ,proc_info + ); +} + +int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, + const char *query, int query_length, + const char *db, const char *table_name, + uint32 ndb_table_id, + uint32 ndb_table_version, + enum SCHEMA_OP_TYPE type, + const char *new_db, const char *new_table_name, + int have_lock_open) +{ + DBUG_ENTER("ndbcluster_log_schema_op"); + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (!thd_ndb) + { + if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb())) + { + sql_print_error("Could not allocate Thd_ndb object"); + DBUG_RETURN(1); + } + set_thd_ndb(thd, thd_ndb); + } + + DBUG_PRINT("enter", + ("query: %s db: %s table_name: %s thd_ndb->options: %d", + query, db, table_name, thd_ndb->options)); + if (!schema_share || thd_ndb->options & TNO_NO_LOG_SCHEMA_OP) + { + DBUG_RETURN(0); + } + + char tmp_buf2[FN_REFLEN]; + const char *type_str; + switch (type) + { + case SOT_DROP_TABLE: + /* drop database command, do not log at drop table */ + if (thd->lex->sql_command == SQLCOM_DROP_DB) + DBUG_RETURN(0); + /* redo the drop table query as is may contain several tables */ + query= tmp_buf2; + query_length= (uint) (strxmov(tmp_buf2, "drop table `", + table_name, "`", NullS) - tmp_buf2); + type_str= "drop table"; + break; + case SOT_RENAME_TABLE: + /* redo the rename table query as is may contain several tables */ + query= tmp_buf2; + query_length= (uint) (strxmov(tmp_buf2, "rename table `", + db, ".", table_name, "` to `", + new_db, ".", new_table_name, "`", NullS) - tmp_buf2); + type_str= "rename table"; + break; + case SOT_CREATE_TABLE: + type_str= "create table"; + break; + case SOT_ALTER_TABLE: + type_str= "create table"; + break; + case SOT_DROP_DB: + type_str= "drop db"; + break; + case SOT_CREATE_DB: + type_str= "create db"; + break; + case SOT_ALTER_DB: + type_str= "alter db"; + break; + case SOT_TABLESPACE: + type_str= "tablespace"; + break; + case SOT_LOGFILE_GROUP: + type_str= "logfile group"; + break; + default: + abort(); /* should not happen, programming error */ + } + + NDB_SCHEMA_OBJECT *ndb_schema_object; + { + char key[FN_REFLEN]; + build_table_filename(key, sizeof(key), db, table_name, ""); + ndb_schema_object= ndb_get_schema_object(key, TRUE, FALSE); + } + + const NdbError *ndb_error= 0; + uint32 node_id= g_ndb_cluster_connection->node_id(); + Uint64 epoch= 0; + MY_BITMAP schema_subscribers; + uint32 bitbuf[sizeof(ndb_schema_object->slock)/4]; + char bitbuf_e[sizeof(bitbuf)]; + bzero(bitbuf_e, sizeof(bitbuf_e)); + { + int i, updated= 0; + int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); + bitmap_init(&schema_subscribers, bitbuf, sizeof(bitbuf)*8, false); + bitmap_set_all(&schema_subscribers); + (void) pthread_mutex_lock(&schema_share->mutex); + for (i= 0; i < no_storage_nodes; i++) + { + MY_BITMAP *table_subscribers= &schema_share->subscriber_bitmap[i]; + if (!bitmap_is_clear_all(table_subscribers)) + { + bitmap_intersect(&schema_subscribers, + table_subscribers); + updated= 1; + } + } + (void) pthread_mutex_unlock(&schema_share->mutex); + if (updated) + { + bitmap_clear_bit(&schema_subscribers, node_id); + /* + if setting own acknowledge bit it is important that + no other mysqld's are registred, as subsequent code + will cause the original event to be hidden (by blob + merge event code) + */ + if (bitmap_is_clear_all(&schema_subscribers)) + bitmap_set_bit(&schema_subscribers, node_id); + } + else + bitmap_clear_all(&schema_subscribers); + + if (ndb_schema_object) + { + (void) pthread_mutex_lock(&ndb_schema_object->mutex); + memcpy(ndb_schema_object->slock, schema_subscribers.bitmap, + sizeof(ndb_schema_object->slock)); + (void) pthread_mutex_unlock(&ndb_schema_object->mutex); + } + + DBUG_DUMP("schema_subscribers", (char*)schema_subscribers.bitmap, + no_bytes_in_map(&schema_subscribers)); + DBUG_PRINT("info", ("bitmap_is_clear_all(&schema_subscribers): %d", + bitmap_is_clear_all(&schema_subscribers))); + } + + Ndb *ndb= thd_ndb->ndb; + char save_db[FN_REFLEN]; + strcpy(save_db, ndb->getDatabaseName()); + + char tmp_buf[FN_REFLEN]; + NDBDICT *dict= ndb->getDictionary(); + ndb->setDatabaseName(NDB_REP_DB); + Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE); + const NDBTAB *ndbtab= ndbtab_g.get_table(); + NdbTransaction *trans= 0; + int retries= 100; + const NDBCOL *col[SCHEMA_SIZE]; + unsigned sz[SCHEMA_SIZE]; + + if (ndbtab == 0) + { + if (strcmp(NDB_REP_DB, db) != 0 || + strcmp(NDB_SCHEMA_TABLE, table_name)) + { + ndb_error= &dict->getNdbError(); + } + goto end; + } + + { + uint i; + for (i= 0; i < SCHEMA_SIZE; i++) + { + col[i]= ndbtab->getColumn(i); + if (i != SCHEMA_QUERY_I) + { + sz[i]= col[i]->getLength(); + DBUG_ASSERT(sz[i] <= sizeof(tmp_buf)); + } + } + } + + while (1) + { + const char *log_db= db; + const char *log_tab= table_name; + const char *log_subscribers= (char*)schema_subscribers.bitmap; + uint32 log_type= (uint32)type; + if ((trans= ndb->startTransaction()) == 0) + goto err; + while (1) + { + NdbOperation *op= 0; + int r= 0; + r|= (op= trans->getNdbOperation(ndbtab)) == 0; + DBUG_ASSERT(r == 0); + r|= op->writeTuple(); + DBUG_ASSERT(r == 0); + + /* db */ + ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, log_db, strlen(log_db)); + r|= op->equal(SCHEMA_DB_I, tmp_buf); + DBUG_ASSERT(r == 0); + /* name */ + ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, log_tab, + strlen(log_tab)); + r|= op->equal(SCHEMA_NAME_I, tmp_buf); + DBUG_ASSERT(r == 0); + /* slock */ + DBUG_ASSERT(sz[SCHEMA_SLOCK_I] == sizeof(bitbuf)); + r|= op->setValue(SCHEMA_SLOCK_I, log_subscribers); + DBUG_ASSERT(r == 0); + /* query */ + { + NdbBlob *ndb_blob= op->getBlobHandle(SCHEMA_QUERY_I); + DBUG_ASSERT(ndb_blob != 0); + uint blob_len= query_length; + const char* blob_ptr= query; + r|= ndb_blob->setValue(blob_ptr, blob_len); + DBUG_ASSERT(r == 0); + } + /* node_id */ + r|= op->setValue(SCHEMA_NODE_ID_I, node_id); + DBUG_ASSERT(r == 0); + /* epoch */ + r|= op->setValue(SCHEMA_EPOCH_I, epoch); + DBUG_ASSERT(r == 0); + /* id */ + r|= op->setValue(SCHEMA_ID_I, ndb_table_id); + DBUG_ASSERT(r == 0); + /* version */ + r|= op->setValue(SCHEMA_VERSION_I, ndb_table_version); + DBUG_ASSERT(r == 0); + /* type */ + r|= op->setValue(SCHEMA_TYPE_I, log_type); + DBUG_ASSERT(r == 0); + if (log_db != new_db && new_db && new_table_name) + { + log_db= new_db; + log_tab= new_table_name; + log_subscribers= bitbuf_e; // no ack expected on this + log_type= (uint32)SOT_RENAME_TABLE_NEW; + continue; + } + break; + } + if (trans->execute(NdbTransaction::Commit) == 0) + { + DBUG_PRINT("info", ("logged: %s", query)); + break; + } +err: + const NdbError *this_error= trans ? + &trans->getNdbError() : &ndb->getNdbError(); + if (this_error->status == NdbError::TemporaryError) + { + if (retries--) + { + if (trans) + ndb->closeTransaction(trans); + continue; // retry + } + } + ndb_error= this_error; + break; + } +end: + if (ndb_error) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_GET_ERRMSG, ER(ER_GET_ERRMSG), + ndb_error->code, + ndb_error->message, + "Could not log query '%s' on other mysqld's"); + + if (trans) + ndb->closeTransaction(trans); + ndb->setDatabaseName(save_db); + + /* + Wait for other mysqld's to acknowledge the table operation + */ + if (ndb_error == 0 && + !bitmap_is_clear_all(&schema_subscribers)) + { + /* + if own nodeid is set we are a single mysqld registred + as an optimization we update the slock directly + */ + if (bitmap_is_set(&schema_subscribers, node_id)) + ndbcluster_update_slock(thd, db, table_name); + else + dict->forceGCPWait(); + + int max_timeout= opt_ndb_sync_timeout; + (void) pthread_mutex_lock(&ndb_schema_object->mutex); + if (have_lock_open) + { + safe_mutex_assert_owner(&LOCK_open); + (void) pthread_mutex_unlock(&LOCK_open); + } + while (1) + { + struct timespec abstime; + int i; + int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); + set_timespec(abstime, 1); + int ret= pthread_cond_timedwait(&injector_cond, + &ndb_schema_object->mutex, + &abstime); + if (thd->killed) + break; + (void) pthread_mutex_lock(&schema_share->mutex); + for (i= 0; i < no_storage_nodes; i++) + { + /* remove any unsubscribed from schema_subscribers */ + MY_BITMAP *tmp= &schema_share->subscriber_bitmap[i]; + if (!bitmap_is_clear_all(tmp)) + bitmap_intersect(&schema_subscribers, tmp); + } + (void) pthread_mutex_unlock(&schema_share->mutex); + + /* remove any unsubscribed from ndb_schema_object->slock */ + bitmap_intersect(&ndb_schema_object->slock_bitmap, &schema_subscribers); + + DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", + (char*)ndb_schema_object->slock_bitmap.bitmap, + no_bytes_in_map(&ndb_schema_object->slock_bitmap)); + + if (bitmap_is_clear_all(&ndb_schema_object->slock_bitmap)) + break; + + if (ret) + { + max_timeout--; + if (max_timeout == 0) + { + sql_print_error("NDB %s: distributing %s timed out. Ignoring...", + type_str, ndb_schema_object->key); + break; + } + if (ndb_extra_logging) + ndb_report_waiting(type_str, max_timeout, + "distributing", ndb_schema_object->key); + } + } + if (have_lock_open) + { + (void) pthread_mutex_lock(&LOCK_open); + } + (void) pthread_mutex_unlock(&ndb_schema_object->mutex); + } + + if (ndb_schema_object) + ndb_free_schema_object(&ndb_schema_object, FALSE); + + DBUG_RETURN(0); +} + /* Handle _non_ data events from the storage nodes */ @@ -1680,17 +1720,26 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, bitmap_init(&slock, schema->slock, 8*SCHEMA_SLOCK_SIZE, false); uint node_id= g_ndb_cluster_connection->node_id(); ndbcluster_get_schema(tmp_share, schema); + enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type; + DBUG_PRINT("info", + ("%s.%s: log query_length: %d query: '%s' type: %d", + schema->db, schema->name, + schema->query_length, schema->query, + schema_type)); + if (schema_type == SOT_CLEAR_SLOCK) + { + /* + handle slock after epoch is completed to ensure that + schema events get inserted in the binlog after any data + events + */ + post_epoch_log_list->push_back(schema, mem_root); + DBUG_RETURN(0); + } if (schema->node_id != node_id) { int log_query= 0, post_epoch_unlock= 0; - DBUG_PRINT("info", - ("%s.%s: log query_length: %d query: '%s' type: %d", - schema->db, schema->name, - schema->query_length, schema->query, - schema->type)); - char key[FN_REFLEN]; - build_table_filename(key, sizeof(key), schema->db, schema->name, ""); - switch ((enum SCHEMA_OP_TYPE)schema->type) + switch (schema_type) { case SOT_DROP_TABLE: // fall through @@ -1738,30 +1787,12 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, TRUE, /* print error */ FALSE); /* binlog the query */ break; - case SOT_CLEAR_SLOCK: - { - pthread_mutex_lock(&ndbcluster_mutex); - NDB_SCHEMA_OBJECT *ndb_schema_object= - (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, - (byte*) key, strlen(key)); - if (ndb_schema_object) - { - pthread_mutex_lock(&ndb_schema_object->mutex); - memcpy(ndb_schema_object->slock, schema->slock, - sizeof(ndb_schema_object->slock)); - DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", - (char*)ndb_schema_object->slock_bitmap.bitmap, - no_bytes_in_map(&ndb_schema_object->slock_bitmap)); - pthread_mutex_unlock(&ndb_schema_object->mutex); - pthread_cond_signal(&injector_cond); - } - pthread_mutex_unlock(&ndbcluster_mutex); - DBUG_RETURN(0); - } case SOT_TABLESPACE: case SOT_LOGFILE_GROUP: log_query= 1; break; + case SOT_CLEAR_SLOCK: + abort(); } if (log_query && ndb_binlog_running) { @@ -1902,10 +1933,30 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, schema->type)); int log_query= 0; { + enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type; char key[FN_REFLEN]; build_table_filename(key, sizeof(key), schema->db, schema->name, ""); + if (schema_type == SOT_CLEAR_SLOCK) + { + pthread_mutex_lock(&ndbcluster_mutex); + NDB_SCHEMA_OBJECT *ndb_schema_object= + (NDB_SCHEMA_OBJECT*) hash_search(&ndb_schema_objects, + (byte*) key, strlen(key)); + if (ndb_schema_object) + { + pthread_mutex_lock(&ndb_schema_object->mutex); + memcpy(ndb_schema_object->slock, schema->slock, + sizeof(ndb_schema_object->slock)); + DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", + (char*)ndb_schema_object->slock_bitmap.bitmap, + no_bytes_in_map(&ndb_schema_object->slock_bitmap)); + pthread_mutex_unlock(&ndb_schema_object->mutex); + pthread_cond_signal(&injector_cond); + } + pthread_mutex_unlock(&ndbcluster_mutex); + continue; + } NDB_SHARE *share= get_share(key, 0, false, false); - enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type; switch (schema_type) { case SOT_DROP_DB: @@ -2328,6 +2379,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, const char *event_name, NDB_SHARE *share, int push_warning) { + THD *thd= current_thd; DBUG_ENTER("ndbcluster_create_event"); DBUG_PRINT("info", ("table=%s version=%d event=%s share=%s", ndbtab->getName(), ndbtab->getObjectVersion(), @@ -2357,12 +2409,12 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, "with BLOB attribute and no PK is not supported", share->key); if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_ILLEGAL_HA_CREATE_OPTION, ER(ER_ILLEGAL_HA_CREATE_OPTION), - ndbcluster_hton.name, + ndbcluster_hton_name, "Binlog of table with BLOB attribute and no PK"); - + share->flags|= NSF_NO_BINLOG; DBUG_RETURN(-1); } @@ -2401,7 +2453,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, failed, print a warning */ if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2429,7 +2481,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, dict->dropEvent(my_event.getName())) { if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2448,7 +2500,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, if (dict->createEvent(my_event)) { if (push_warning) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2461,7 +2513,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab, DBUG_RETURN(-1); } #ifdef NDB_BINLOG_EXTRA_WARNINGS - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), 0, "NDB Binlog: Removed trailing event", "NDB"); @@ -2490,6 +2542,7 @@ int ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, const char *event_name) { + THD *thd= current_thd; /* we are in either create table or rename table so table should be locked, hence we can work with the share without locks @@ -2563,7 +2616,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, { sql_print_error("NDB Binlog: Creating NdbEventOperation failed for" " %s",event_name); - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), ndb->getNdbError().code, ndb->getNdbError().message, @@ -2613,7 +2666,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, sql_print_error("NDB Binlog: Creating NdbEventOperation" " blob field %u handles failed (code=%d) for %s", j, op->getNdbError().code, event_name); - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), op->getNdbError().code, op->getNdbError().message, @@ -2650,7 +2703,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, retries= 0; if (retries == 0) { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), op->getNdbError().code, op->getNdbError().message, "NDB"); @@ -2698,6 +2751,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, NDB_SHARE *share, const char *type_str) { DBUG_ENTER("ndbcluster_handle_drop_table"); + THD *thd= current_thd; NDBDICT *dict= ndb->getDictionary(); if (event_name && dict->dropEvent(event_name)) @@ -2705,7 +2759,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, if (dict->getNdbError().code != 4710) { /* drop event failed for some reason, issue a warning */ - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_GET_ERRMSG, ER(ER_GET_ERRMSG), dict->getNdbError().code, dict->getNdbError().message, "NDB"); @@ -2743,10 +2797,14 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, these out of order, thus we are keeping the SYNC_DROP_ defined for now. */ + const char *save_proc_info= thd->proc_info; #define SYNC_DROP_ #ifdef SYNC_DROP_ + thd->proc_info= "Syncing ndb table schema operation and binlog"; (void) pthread_mutex_lock(&share->mutex); - int max_timeout= 10; + safe_mutex_assert_owner(&LOCK_open); + (void) pthread_mutex_unlock(&LOCK_open); + int max_timeout= opt_ndb_sync_timeout; while (share->op) { struct timespec abstime; @@ -2754,7 +2812,8 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, int ret= pthread_cond_timedwait(&injector_cond, &share->mutex, &abstime); - if (share->op == 0) + if (thd->killed || + share->op == 0) break; if (ret) { @@ -2770,6 +2829,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, type_str, share->key); } } + (void) pthread_mutex_lock(&LOCK_open); (void) pthread_mutex_unlock(&share->mutex); #else (void) pthread_mutex_lock(&share->mutex); @@ -2777,6 +2837,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, share->op= 0; (void) pthread_mutex_unlock(&share->mutex); #endif + thd->proc_info= save_proc_info; DBUG_RETURN(0); } @@ -3822,7 +3883,7 @@ ndbcluster_show_status_binlog(THD* thd, stat_print_fn *stat_print, ndb_latest_received_binlog_epoch, ndb_latest_handled_binlog_epoch, ndb_latest_applied_binlog_epoch); - if (stat_print(thd, ndbcluster_hton.name, strlen(ndbcluster_hton.name), + if (stat_print(thd, ndbcluster_hton_name, ndbcluster_hton_name_length, "binlog", strlen("binlog"), buf, buflen)) DBUG_RETURN(TRUE); diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h index d82cdccb1b9..7c45dee59d0 100644 --- a/sql/ha_ndbcluster_binlog.h +++ b/sql/ha_ndbcluster_binlog.h @@ -138,8 +138,9 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, uint32 ndb_table_id, uint32 ndb_table_version, enum SCHEMA_OP_TYPE type, - const char *new_db= 0, - const char *new_table_name= 0); + const char *new_db, + const char *new_table_name, + int have_lock_open); int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, NDB_SHARE *share, const char *type_str); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index af0556f1e6f..7fa5b89abf8 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -73,46 +73,18 @@ static handler *partition_create_handler(TABLE_SHARE *share); static uint partition_flags(); static uint alter_table_flags(uint flags); -static const char partition_hton_name[]= "partition"; -static const char partition_hton_comment[]= "Partition Storage Engine Helper"; +handlerton partition_hton; -handlerton partition_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - partition_hton_name, - SHOW_OPTION_YES, - partition_hton_comment, /* A comment used by SHOW to describe an engine */ - DB_TYPE_PARTITION_DB, - 0, /* Method that initializes a storage engine */ - 0, /* slot */ - 0, /* savepoint size */ - NULL /*ndbcluster_close_connection*/, - NULL, /* savepoint_set */ - NULL, /* savepoint_rollback */ - NULL, /* savepoint_release */ - NULL /*ndbcluster_commit*/, - NULL /*ndbcluster_rollback*/, - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, - NULL, - NULL, - partition_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - NULL, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - partition_flags, /* Partition flags */ - alter_table_flags, /* Partition flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_NOT_USER_SELECTABLE | HTON_HIDDEN, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; +static int partition_initialize() +{ + partition_hton.state= SHOW_OPTION_YES; + partition_hton.db_type= DB_TYPE_PARTITION_DB; + partition_hton.create= partition_create_handler; + partition_hton.partition_flags= partition_flags; + partition_hton.alter_table_flags= alter_table_flags; + partition_hton.flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN; + return 0; +} /* Create new partition handler @@ -5523,15 +5495,17 @@ static int free_share(PARTITION_SHARE *share) } #endif /* NOT_USED */ +struct st_mysql_storage_engine partition_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &partition_hton }; mysql_declare_plugin(partition) { MYSQL_STORAGE_ENGINE_PLUGIN, - &partition_hton, - partition_hton_name, + &partition_storage_engine, + "partition", "Mikael Ronstrom, MySQL AB", - partition_hton_comment, - NULL, /* Plugin Init */ + "Partition Storage Engine Helper", + partition_initialize, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100, /* 1.0 */ 0 diff --git a/sql/handler.cc b/sql/handler.cc index f51e91f1882..261925a3a60 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -48,6 +48,7 @@ check for dups and to find handlerton from legacy_db_type. Remove when legacy_db_type is finally gone */ static handlerton *installed_htons[128]; +st_plugin_int *hton2plugin[MAX_HA]; #define BITMAP_STACKBUF_SIZE (128/8) @@ -57,35 +58,14 @@ KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0} }; static handler *create_default(TABLE_SHARE *table); -const handlerton default_hton = -{ - MYSQL_HANDLERTON_INTERFACE_VERSION, - "DEFAULT", - SHOW_OPTION_YES, - NULL, - DB_TYPE_DEFAULT, - NULL, - 0, 0, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, - create_default, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, /* alter_tablespace */ - NULL, /* fill_files_table */ - HTON_NO_FLAGS, /* flags */ - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES; /* number of entries in handlertons[] */ -ulong total_ha; +ulong total_ha= 0; /* number of storage engines (from handlertons[]) that support 2pc */ -ulong total_ha_2pc; +ulong total_ha_2pc= 0; /* size of savepoint storage area (see ha_init) */ -ulong savepoint_alloc_size; +ulong savepoint_alloc_size= 0; struct show_table_alias_st sys_table_aliases[]= { @@ -122,7 +102,7 @@ handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name) if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN))) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (!(hton->flags & HTON_NOT_USER_SELECTABLE)) return hton; plugin_unlock(plugin); @@ -155,7 +135,7 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type) default: if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT && installed_htons[db_type]) - return installed_htons[db_type]->name; + return hton2plugin[installed_htons[db_type]->slot]->name.str; return "*NONE*"; } } @@ -164,8 +144,7 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type) static handler *create_default(TABLE_SHARE *table) { handlerton *hton=ha_resolve_by_legacy_type(current_thd, DB_TYPE_DEFAULT); - return (hton && hton != &default_hton && hton->create) ? - hton->create(table) : NULL; + return (hton && hton->create) ? hton->create(table) : NULL; } @@ -183,7 +162,7 @@ handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type) default: if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT) return installed_htons[db_type]; - return NULL; + return NULL; } } @@ -372,22 +351,19 @@ static int ha_finish_errors(void) int ha_finalize_handlerton(st_plugin_int *plugin) { - handlerton *hton; + handlerton *hton= (handlerton *)plugin->data; DBUG_ENTER("ha_finalize_handlerton"); - if (!(hton= (handlerton *) plugin->plugin->info)) - DBUG_RETURN(1); - switch (hton->state) { case SHOW_OPTION_NO: case SHOW_OPTION_DISABLED: break; case SHOW_OPTION_YES: - if (hton->panic && hton->panic(HA_PANIC_CLOSE)) - DBUG_RETURN(1); if (installed_htons[hton->db_type] == hton) installed_htons[hton->db_type]= NULL; + if (hton->panic && hton->panic(HA_PANIC_CLOSE)) + DBUG_RETURN(1); break; }; DBUG_RETURN(0); @@ -396,37 +372,28 @@ int ha_finalize_handlerton(st_plugin_int *plugin) int ha_initialize_handlerton(st_plugin_int *plugin) { - handlerton *hton; + handlerton *hton= ((st_mysql_storage_engine *)plugin->plugin->info)->handlerton; DBUG_ENTER("ha_initialize_handlerton"); - if (!(hton= (handlerton *) plugin->plugin->info)) - DBUG_RETURN(1); - - /* for the sake of sanity, we set the handlerton name to be the - same as the plugin name */ - hton->name= plugin->name.str; - + plugin->data= hton; // shortcut for the future + /* + the switch below and hton->state should be removed when + command-line options for plugins will be implemented + */ switch (hton->state) { case SHOW_OPTION_NO: break; case SHOW_OPTION_YES: - if (!hton->init || !hton->init()) { - uint tmp= hton->savepoint_offset; - hton->savepoint_offset= savepoint_alloc_size; - savepoint_alloc_size+= tmp; - hton->slot= total_ha++; - if (hton->prepare) - total_ha_2pc++; - + uint tmp; /* now check the db_type for conflict */ - if (hton->db_type <= DB_TYPE_UNKNOWN || + if (hton->db_type <= DB_TYPE_UNKNOWN || hton->db_type >= DB_TYPE_DEFAULT || installed_htons[hton->db_type]) { int idx= (int) DB_TYPE_FIRST_DYNAMIC; - + while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx]) idx++; @@ -437,10 +404,17 @@ int ha_initialize_handlerton(st_plugin_int *plugin) } if (hton->db_type != DB_TYPE_UNKNOWN) sql_print_warning("Storage engine '%s' has conflicting typecode. " - "Assigning value %d.", hton->name, idx); + "Assigning value %d.", plugin->plugin->name, idx); hton->db_type= (enum legacy_db_type) idx; } installed_htons[hton->db_type]= hton; + tmp= hton->savepoint_offset; + hton->savepoint_offset= savepoint_alloc_size; + savepoint_alloc_size+= tmp; + hton->slot= total_ha++; + hton2plugin[hton->slot]=plugin; + if (hton->prepare) + total_ha_2pc++; break; } /* fall through */ @@ -451,33 +425,14 @@ int ha_initialize_handlerton(st_plugin_int *plugin) DBUG_RETURN(0); } - -static my_bool init_handlerton(THD *unused1, st_plugin_int *plugin, - void *unused2) -{ - if (plugin->state == PLUGIN_IS_UNINITIALIZED) - { - ha_initialize_handlerton(plugin); - plugin->state= PLUGIN_IS_READY; - } - return FALSE; -} - - int ha_init() { int error= 0; - total_ha= savepoint_alloc_size= 0; DBUG_ENTER("ha_init"); - bzero(installed_htons, sizeof(installed_htons)); - if (ha_init_errors()) DBUG_RETURN(1); - if (plugin_foreach(NULL, init_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0)) - DBUG_RETURN(1); - DBUG_ASSERT(total_ha < MAX_HA); /* Check if there is a transaction-capable storage engine besides the @@ -489,16 +444,14 @@ int ha_init() DBUG_RETURN(error); } +/* + close, flush or restart databases + Ignore this for other databases than ours +*/ - - - /* close, flush or restart databases */ - /* Ignore this for other databases than ours */ - -static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin, - void *arg) +static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->panic) ((int*)arg)[0]|= hton->panic((enum ha_panic_function)((int*)arg)[1]); return FALSE; @@ -508,10 +461,10 @@ static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin, int ha_panic(enum ha_panic_function flag) { int error[2]; - + error[0]= 0; error[1]= (int)flag; plugin_foreach(NULL, panic_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, error); - + if (flag == HA_PANIC_CLOSE && ha_finish_errors()) error[0]= 1; return error[0]; @@ -520,7 +473,7 @@ int ha_panic(enum ha_panic_function flag) static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin, void *path) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->drop_database) hton->drop_database((char *)path); return FALSE; @@ -536,9 +489,11 @@ void ha_drop_database(char* path) static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin, void *unused) { - handlerton *hton= (handlerton *) plugin->plugin->info; - /* there's no need to rollback here as all transactions must - be rolled back already */ + handlerton *hton= (handlerton *)plugin->data; + /* + there's no need to rollback here as all transactions must + be rolled back already + */ if (hton->state == SHOW_OPTION_YES && hton->close_connection && thd->ha_data[hton->slot]) hton->close_connection(thd); @@ -628,7 +583,8 @@ int ha_prepare(THD *thd) else { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), (*ht)->name); + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), + hton2plugin[(*ht)->slot]->name.str); } } } @@ -867,7 +823,7 @@ struct xahton_st { static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->commit_by_xid(((struct xahton_st *)arg)->xid); @@ -879,7 +835,7 @@ static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin, static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->recover) { hton->rollback_by_xid(((struct xahton_st *)arg)->xid); @@ -894,7 +850,7 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit) struct xahton_st xaop; xaop.xid= xid; xaop.result= 1; - + plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &xaop); @@ -986,16 +942,16 @@ struct xarecover_st static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; struct xarecover_st *info= (struct xarecover_st *) arg; int got; - + if (hton->state == SHOW_OPTION_YES && hton->recover) { while ((got= hton->recover(info->list, info->len)) > 0 ) { sql_print_information("Found %d prepared transaction(s) in %s", - got, hton->name); + got, hton2plugin[hton->slot]->name.str); for (int i=0; i < got; i ++) { my_xid x=info->list[i].get_my_xid(); @@ -1175,7 +1131,7 @@ bool mysql_xa_recover(THD *thd) static my_bool release_temporary_latches(THD *thd, st_plugin_int *plugin, void *unused) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches) hton->release_temporary_latches(thd); @@ -1300,7 +1256,7 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv) static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->start_consistent_snapshot) { @@ -1331,7 +1287,7 @@ int ha_start_consistent_snapshot(THD *thd) static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->flush_logs && hton->flush_logs()) return TRUE; return FALSE; @@ -2642,7 +2598,7 @@ struct binlog_func_st static my_bool binlog_func_list(THD *thd, st_plugin_int *plugin, void *arg) { hton_list_st *hton_list= (hton_list_st *)arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->binlog_func) { uint sz= hton_list->sz; @@ -2732,7 +2688,7 @@ static my_bool binlog_log_query_handlerton(THD *thd, st_plugin_int *plugin, void *args) { - return binlog_log_query_handlerton2(thd, (const handlerton *) plugin->plugin->info, args); + return binlog_log_query_handlerton2(thd, (const handlerton *)plugin->data, args); } void ha_binlog_log_query(THD *thd, const handlerton *hton, @@ -3013,7 +2969,7 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key, SYNOPSIS ha_known_exts() - + NOTES No mutexes, worst case race is a minor surplus memory allocation We have to recreate the extension map if mysqld is restarted (for example @@ -3027,14 +2983,14 @@ static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin, void *arg) { List *found_exts= (List *) arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; handler *file; if (hton->state == SHOW_OPTION_YES && hton->create && (file= hton->create((TABLE_SHARE*) 0))) { List_iterator_fast it(*found_exts); const char **ext, *old_ext; - + for (ext= file->bas_ext(); *ext; ext++) { while ((old_ext= it++)) @@ -3063,14 +3019,14 @@ TYPELIB *ha_known_exts(void) known_extensions_id= mysys_usage_id; found_exts.push_back((char*) triggers_file_ext); found_exts.push_back((char*) trigname_file_ext); - - plugin_foreach(NULL, exts_handlerton, + + plugin_foreach(NULL, exts_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts); ext= (const char **) my_once_alloc(sizeof(char *)* (found_exts.elements+1), MYF(MY_WME | MY_FAE)); - + DBUG_ASSERT(ext != 0); known_extensions.count= found_exts.elements; known_extensions.type_names= ext; @@ -3103,7 +3059,7 @@ static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin, void *arg) { enum ha_stat_type stat= *(enum ha_stat_type *) arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (hton->state == SHOW_OPTION_YES && hton->show_status && hton->show_status(thd, stat_print, stat)) return TRUE; @@ -3126,16 +3082,19 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) if (db_type == NULL) { - result= plugin_foreach(thd, showstat_handlerton, + result= plugin_foreach(thd, showstat_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &stat); } else { if (db_type->state != SHOW_OPTION_YES) - result= stat_print(thd, db_type->name, strlen(db_type->name), + { + const LEX_STRING *name=&hton2plugin[db_type->slot]->name; + result= stat_print(thd, name->str, name->length, "", 0, "DISABLED", 8) ? 1 : 0; + } else - result= db_type->show_status && + result= db_type->show_status && db_type->show_status(thd, stat_print, stat) ? 1 : 0; } diff --git a/sql/handler.h b/sql/handler.h index 9a5a3b04823..564f391ce2d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -177,6 +177,7 @@ so: innodb + bdb + ndb + binlog + myisam + myisammrg + archive + example + csv + heap + blackhole + federated + 0 (yes, the sum is deliberately inaccurate) + TODO remove the limit, use dynarrays */ #define MAX_HA 15 @@ -460,6 +461,7 @@ typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len, const char *file, uint file_len, const char *status, uint status_len); enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; +extern st_plugin_int *hton2plugin[MAX_HA]; /* handlerton is a singleton structure - one instance per storage engine - @@ -475,38 +477,15 @@ enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX }; struct handlerton { /* - handlerton structure version - */ - const int interface_version; -/* last version change: 0x0001 in 5.1.6 */ -#define MYSQL_HANDLERTON_INTERFACE_VERSION 0x0001 - - - /* - storage engine name as it should be printed to a user - */ - const char *name; - - /* - Historical marker for if the engine is available of not + Historical marker for if the engine is available of not */ SHOW_COMP_OPTION state; - /* - A comment used by SHOW to describe an engine. - */ - const char *comment; - /* Historical number used for frm file to determine the correct storage engine. This is going away and new engines will just use "name" for this. */ enum legacy_db_type db_type; - /* - Method that initizlizes a storage engine - */ - bool (*init)(); - /* each storage engine has it's own memory area (actually a pointer) in the thd, for storing per-connection information. @@ -587,8 +566,6 @@ struct handlerton int (*release_temporary_latches)(THD *thd); }; -extern const handlerton default_hton; - struct show_table_alias_st { const char *alias; enum legacy_db_type type; @@ -1553,7 +1530,7 @@ static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type) static inline const char *ha_resolve_storage_engine_name(const handlerton *db_type) { - return db_type == NULL ? "UNKNOWN" : db_type->name; + return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str; } static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag) diff --git a/sql/item.h b/sql/item.h index 2f99034130a..685da3014ef 100644 --- a/sql/item.h +++ b/sql/item.h @@ -783,6 +783,29 @@ public: virtual bool find_item_in_field_list_processor(byte *arg) { return 0; } virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } + /* + Check if a partition function is allowed + SYNOPSIS + check_partition_func_processor() + bool_arg Return argument + RETURN VALUE + 0 + DESCRIPTION + check_partition_func_processor is used to check if a partition function + uses an allowed function. The default is that an item is not allowed + in a partition function. However all mathematical functions, string + manipulation functions, date functions are allowed. Allowed functions + can never depend on server version, they cannot depend on anything + related to the environment. They can also only depend on a set of + fields in the table itself. They cannot depend on other tables and + cannot contain any queries and cannot contain udf's or similar. + If a new Item class is defined and it inherits from a class that is + allowed in a partition function then it is very important to consider + whether this should be inherited to the new class. If not the function + below should be defined in the new Item class. + */ + virtual bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } @@ -1073,6 +1096,7 @@ public: Item::maybe_null= TRUE; } + bool check_partition_func_processor(byte *bool_arg) { return 0; } bool fix_fields(THD *, Item **); enum Type type() const; @@ -1119,6 +1143,7 @@ public: Item_num() {} /* Remove gcc warning */ virtual Item_num *neg()= 0; Item *safe_charset_converter(CHARSET_INFO *tocs); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -1260,6 +1285,7 @@ public: result_field->query_id= field->query_id; return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0; } void cleanup(); Item_equal *find_item_equal(COND_EQUAL *cond_equal); Item *equal_fields_propagator(byte *arg); @@ -1303,6 +1329,7 @@ public: bool is_null() { return 1; } void print(String *str) { str->append(STRING_WITH_LEN("NULL")); } Item *safe_charset_converter(CHARSET_INFO *tocs); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_null_result :public Item_null @@ -1315,6 +1342,8 @@ public: { save_in_field(result_field, no_conversions); } + bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; /* Item represents one placeholder ('?') of prepared statement */ @@ -1605,6 +1634,8 @@ public: {} void print(String *str) { str->append(func_name); } Item *safe_charset_converter(CHARSET_INFO *tocs); + bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1682,6 +1713,7 @@ public: void print(String *str); // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1696,6 +1728,8 @@ public: {} Item *safe_charset_converter(CHARSET_INFO *tocs); void print(String *str) { str->append(func_name); } + bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1708,6 +1742,8 @@ public: &my_charset_bin) { max_length=19;} enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; class Item_empty_string :public Item_string @@ -1730,6 +1766,8 @@ public: unsigned_flag=1; } enum_field_types field_type() const { return int_field_type; } + bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1753,6 +1791,7 @@ public: void cleanup() {} bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1975,6 +2014,8 @@ public: } Item *new_item(); virtual Item *real_item() { return ref; } + bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; #ifdef MYSQL_SERVER diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 1cfdcef02d0..f7da1e5e297 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -239,6 +239,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_not :public Item_bool_func @@ -249,6 +250,7 @@ public: enum Functype functype() const { return NOT_FUNC; } const char *func_name() const { return "not"; } Item *neg_transformer(THD *thd); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_maxmin_subselect; @@ -463,6 +465,7 @@ public: bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } uint decimal_precision() const { return 1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -474,6 +477,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "strcmp"; } void print(String *str) { Item_func::print(str); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -536,6 +540,7 @@ public: const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -576,6 +581,7 @@ public: void print(String *str) { Item_func::print(str); } table_map not_null_tables() const { return 0; } bool is_null(); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -618,6 +624,7 @@ public: void print(String *str); Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -968,6 +975,7 @@ public: bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Functions used by where clause */ @@ -1009,6 +1017,7 @@ public: optimize_type select_optimize() const { return OPTIMIZE_NULL; } Item *neg_transformer(THD *thd); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Functions used by HAVING for rewriting IN subquery */ @@ -1030,6 +1039,8 @@ public: */ table_map used_tables() const { return used_tables_cache | RAND_TABLE_BIT; } + bool check_partition_func_processor(byte *bool_arg) + { *(bool *)bool_arg= FALSE; return 0; } }; @@ -1052,6 +1063,7 @@ public: void print(String *str); CHARSET_INFO *compare_collation() { return args[0]->collation.collation; } void top_level_item() { abort_on_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -1090,6 +1102,7 @@ public: const char *func_name() const { return "like"; } bool fix_fields(THD *thd, Item **ref); void cleanup(); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #ifdef USE_REGEX @@ -1112,6 +1125,7 @@ public: const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #else @@ -1168,6 +1182,7 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_func.h b/sql/item_func.h index 1d8a1bd5e22..9d31b57838c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -247,6 +247,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -259,6 +260,7 @@ class Item_num_op :public Item_func_numhybrid void print(String *str) { print_op(str); } void find_num_type(); String *str_op(String *str) { DBUG_ASSERT(0); return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -309,7 +311,7 @@ public: { max_length=args[0]->max_length; unsigned_flag=0; } void print(String *str); uint decimal_precision() const { return args[0]->decimal_precision(); } - + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -343,6 +345,7 @@ public: void fix_length_and_dec() {}; const char *func_name() const { return "decimal_typecast"; } void print(String *); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -411,6 +414,7 @@ public: const char *func_name() const { return "DIV"; } void fix_length_and_dec(); void print(String *str) { print_op(str); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -483,6 +487,7 @@ public: Item_func_exp(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "exp"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -492,6 +497,7 @@ public: Item_func_ln(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "ln"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -502,6 +508,7 @@ public: Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "log"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -511,6 +518,7 @@ public: Item_func_log2(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log2"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -520,6 +528,7 @@ public: Item_func_log10(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "log10"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -529,6 +538,7 @@ public: Item_func_sqrt(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sqrt"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -538,6 +548,7 @@ public: Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "pow"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -547,6 +558,7 @@ public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_asin :public Item_dec_func @@ -555,6 +567,7 @@ public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_atan :public Item_dec_func @@ -564,6 +577,7 @@ public: Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); const char *func_name() const { return "atan"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_cos :public Item_dec_func @@ -572,6 +586,7 @@ public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_sin :public Item_dec_func @@ -580,6 +595,7 @@ public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_tan :public Item_dec_func @@ -588,6 +604,7 @@ public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_integer :public Item_int_func @@ -664,6 +681,7 @@ public: Item_func_sign(Item *a) :Item_int_func(a) {} const char *func_name() const { return "sign"; } longlong val_int(); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -678,6 +696,7 @@ public: const char *func_name() const { return name; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -695,6 +714,7 @@ public: my_decimal *val_decimal(my_decimal *); void fix_length_and_dec(); enum Item_result result_type () const { return cmp_type; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_min :public Item_func_min_max @@ -720,6 +740,7 @@ public: longlong val_int(); const char *func_name() const { return "length"; } void fix_length_and_dec() { max_length=10; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_bit_length :public Item_func_length @@ -739,6 +760,7 @@ public: longlong val_int(); const char *func_name() const { return "char_length"; } void fix_length_and_dec() { max_length=10; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_coercibility :public Item_int_func @@ -749,6 +771,7 @@ public: const char *func_name() const { return "coercibility"; } void fix_length_and_dec() { max_length=10; maybe_null= 0; } table_map not_null_tables() const { return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_locate :public Item_int_func @@ -762,6 +785,7 @@ public: longlong val_int(); void fix_length_and_dec(); void print(String *str); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -786,6 +810,7 @@ public: longlong val_int(); const char *func_name() const { return "ascii"; } void fix_length_and_dec() { max_length=3; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_ord :public Item_int_func @@ -795,6 +820,7 @@ public: Item_func_ord(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "ord"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_find_in_set :public Item_int_func @@ -808,6 +834,7 @@ public: longlong val_int(); const char *func_name() const { return "find_in_set"; } void fix_length_and_dec(); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -819,6 +846,7 @@ public: Item_func_bit(Item *a) :Item_int_func(a) {} void fix_length_and_dec() { unsigned_flag= 1; } void print(String *str) { print_op(str); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_bit_or :public Item_func_bit @@ -844,6 +872,7 @@ public: longlong val_int(); const char *func_name() const { return "bit_count"; } void fix_length_and_dec() { max_length=2; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_shift_left :public Item_func_bit @@ -1280,6 +1309,7 @@ public: longlong val_int(); const char *func_name() const { return "inet_aton"; } void fix_length_and_dec() { decimals = 0; max_length = 21; maybe_null=1;} + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 90d421a2c68..212c06c45ff 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -47,6 +47,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "md5"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -57,6 +58,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "sha"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_aes_encrypt :public Item_str_func @@ -87,6 +89,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_concat_ws :public Item_str_func @@ -107,6 +110,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "reverse"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -144,6 +148,7 @@ protected: public: Item_str_conv(Item *item) :Item_str_func(item) {} String *val_str(String *); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -207,6 +212,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substr"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -218,6 +224,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "substring_index"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -232,6 +239,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "trim"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -411,6 +419,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "soundex"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -518,6 +527,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "rpad"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -530,6 +540,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "lpad"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -544,6 +555,7 @@ public: collation.set(default_charset()); max_length= 64; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -560,6 +572,7 @@ public: decimals=0; max_length=args[0]->max_length*2*collation.collation->mbmaxlen; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_unhex :public Item_str_func @@ -575,6 +588,7 @@ public: decimals=0; max_length=(1+args[0]->max_length)/2; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -598,6 +612,7 @@ public: } void print(String *str); const char *func_name() const { return "cast_as_binary"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -637,6 +652,7 @@ public: String* val_str(String* str); const char *func_name() const { return "inet_ntoa"; } void fix_length_and_dec() { decimals = 0; max_length=3*8+7; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_quote :public Item_str_func @@ -651,6 +667,7 @@ public: collation.set(args[0]->collation); max_length= args[0]->max_length * 2 + 2; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_conv_charset :public Item_str_func @@ -693,6 +710,7 @@ public: void fix_length_and_dec(); const char *func_name() const { return "convert"; } void print(String *str); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_set_collation :public Item_str_func @@ -725,6 +743,7 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_collation :public Item_str_func @@ -740,6 +759,7 @@ public: maybe_null= 0; }; table_map not_null_tables() const { return 0; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_crc32 :public Item_int_func @@ -750,6 +770,7 @@ public: const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } longlong val_int(); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_uncompressed_length : public Item_int_func @@ -760,6 +781,7 @@ public: const char *func_name() const{return "uncompressed_length";} void fix_length_and_dec() { max_length=10; } longlong val_int(); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #ifdef HAVE_COMPRESS @@ -776,6 +798,7 @@ public: void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;} const char *func_name() const{return "compress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_uncompress: public Item_str_func @@ -786,6 +809,7 @@ public: void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;} const char *func_name() const{return "uncompress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; #define UUID_LENGTH (8+1+4+1+4+1+4+1+12) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index ae0ca1a0445..69c8ec5959a 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -39,6 +39,7 @@ public: { max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -53,6 +54,7 @@ public: decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -69,6 +71,7 @@ public: maybe_null=1; } enum_monotonicity_info get_monotonicity_info() const; + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -84,6 +87,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -108,6 +112,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -140,6 +145,7 @@ public: max_length=3*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -155,6 +161,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -170,6 +177,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -185,6 +193,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -200,6 +209,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -215,6 +225,7 @@ public: max_length=2*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_yearweek :public Item_int_func @@ -229,6 +240,7 @@ public: max_length=6*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -245,6 +257,7 @@ public: max_length=4*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -274,6 +287,7 @@ public: max_length=1*MY_CHARSET_BIN_MB_MAXLEN; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_dayname :public Item_func_weekday @@ -306,6 +320,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -320,6 +335,7 @@ public: decimals=0; max_length=10*MY_CHARSET_BIN_MB_MAXLEN; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -526,6 +542,7 @@ public: Item_func_from_days(Item *a) :Item_date(a) {} const char *func_name() const { return "from_days"; } bool get_date(TIME *res, uint fuzzy_date); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -543,6 +560,7 @@ public: void fix_length_and_dec(); uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const; + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -561,6 +579,7 @@ class Item_func_from_unixtime :public Item_date_func const char *func_name() const { return "from_unixtime"; } void fix_length_and_dec(); bool get_date(TIME *res, uint fuzzy_date); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -627,6 +646,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -649,6 +669,7 @@ public: bool get_date(TIME *res, uint fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -666,6 +687,7 @@ class Item_extract :public Item_int_func void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; void print(String *str); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -702,6 +724,7 @@ public: max_length=args[0]->max_length; maybe_null= 1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -721,6 +744,7 @@ public: String *val_str(String *a); void fix_length_and_dec(); void print(String *str); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -792,6 +816,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -814,6 +839,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_timediff :public Item_str_func @@ -853,6 +879,7 @@ public: { return tmp_table_field_from_field_type(table, 0); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; class Item_func_microsecond :public Item_int_func @@ -866,6 +893,7 @@ public: decimals=0; maybe_null=1; } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -883,6 +911,7 @@ public: maybe_null=1; } void print(String *str); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; @@ -929,6 +958,7 @@ public: { return tmp_table_field_from_field_type(table, 1); } + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index bc47e9c5bb1..e11b4eac1e2 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -42,6 +42,7 @@ public: Item_func_xml_extractvalue(Item *a,Item *b) :Item_xml_str_func(a,b) {} const char *func_name() const { return "extractvalue"; } String *val_str(String *); + bool check_partition_func_processor(byte *bool_arg) { return 0;} }; diff --git a/sql/log.cc b/sql/log.cc index 31133a71757..86a29feb026 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -47,7 +47,7 @@ ulong sync_binlog_counter= 0; static bool test_if_number(const char *str, long *res, bool allow_wildcards); -static bool binlog_init(); +static int binlog_init(); static int binlog_close_connection(THD *thd); static int binlog_savepoint_set(THD *thd, void *sv); static int binlog_savepoint_rollback(THD *thd, void *sv); @@ -78,49 +78,7 @@ struct binlog_trx_data { Rows_log_event *pending; // The pending binrows event }; -static const char binlog_hton_name[]= "binlog"; -static const char binlog_hton_comment[]= - "This is a meta storage engine to represent the binlog in a transaction"; - -handlerton binlog_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - binlog_hton_name, - SHOW_OPTION_YES, - binlog_hton_comment, - DB_TYPE_BINLOG, /* IGNORE for now */ - binlog_init, - 0, - sizeof(my_off_t), /* savepoint size = binlog offset */ - binlog_close_connection, - binlog_savepoint_set, - binlog_savepoint_rollback, - NULL, /* savepoint_release */ - binlog_commit, - binlog_rollback, - binlog_prepare, - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - NULL, /* Create a new handler */ - NULL, /* Drop a database */ - NULL, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_NOT_USER_SELECTABLE | HTON_HIDDEN, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - - +handlerton binlog_hton; /* Open log table of a given type (general or slow log) @@ -1066,9 +1024,20 @@ void Log_to_csv_event_handler:: should be moved here. */ -bool binlog_init() +int binlog_init() { - return !opt_bin_log; + + binlog_hton.state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO; + binlog_hton.db_type=DB_TYPE_BINLOG; + binlog_hton.savepoint_offset= sizeof(my_off_t); + binlog_hton.close_connection= binlog_close_connection; + binlog_hton.savepoint_set= binlog_savepoint_set; + binlog_hton.savepoint_rollback= binlog_savepoint_rollback; + binlog_hton.commit= binlog_commit; + binlog_hton.rollback= binlog_rollback; + binlog_hton.prepare= binlog_prepare; + binlog_hton.flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN; + return 0; } static int binlog_close_connection(THD *thd) @@ -4372,15 +4341,17 @@ err1: return 1; } +struct st_mysql_storage_engine binlog_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &binlog_hton }; mysql_declare_plugin(binlog) { MYSQL_STORAGE_ENGINE_PLUGIN, - &binlog_hton, - binlog_hton_name, + &binlog_storage_engine, + "binlog", "MySQL AB", - binlog_hton_comment, - NULL, /* Plugin Init */ + "This is a pseudo storage engine to represent the binlog in a transaction", + binlog_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, } diff --git a/sql/log_event.cc b/sql/log_event.cc index ab9fa2975a1..cbf1875c9ec 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3481,24 +3481,12 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli) Xid_log_event methods **************************************************************************/ -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) -/* - This static class member could be removed when mysqltest is made to support - a --replace-regex command: then tests which have XIDs in their output can - use this command to suppress non-deterministic XID values. -*/ -my_bool Xid_log_event::show_xid; -#endif - #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) void Xid_log_event::pack_info(Protocol *protocol) { char buf[128], *pos; pos= strmov(buf, "COMMIT /* xid="); -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) - if (show_xid) -#endif - pos= longlong10_to_str(xid, pos, 10); + pos= longlong10_to_str(xid, pos, 10); pos= strmov(pos, " */"); protocol->store(buf, (uint) (pos-buf), &my_charset_bin); } diff --git a/sql/log_event.h b/sql/log_event.h index b24686514e3..36933f4a7dd 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1221,9 +1221,6 @@ class Xid_log_event: public Log_event bool write(IO_CACHE* file); #endif bool is_valid() const { return 1; } -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) - static my_bool show_xid; -#endif }; /***************************************************************************** @@ -1635,6 +1632,8 @@ public: #endif char *str_to_hex(char *to, const char *from, uint len); +#ifdef HAVE_ROW_BASED_REPLICATION + /***************************************************************************** Table map log event class @@ -1643,7 +1642,6 @@ char *str_to_hex(char *to, const char *from, uint len); identifier (an integer number). ****************************************************************************/ - class Table_map_log_event : public Log_event { public: @@ -1750,6 +1748,7 @@ private: ****************************************************************************/ + class Rows_log_event : public Log_event { public: @@ -2121,5 +2120,6 @@ private: #endif }; +#endif /* HAVE_ROW_BASED_REPLICATION */ #endif /* _log_event_h */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e3db96be2e7..499b4a741b6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -504,13 +504,13 @@ typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key, #include "sql_list.h" #include "sql_map.h" #include "my_decimal.h" +#include "sql_plugin.h" #include "handler.h" #include "parse_file.h" #include "table.h" #include "sql_error.h" #include "field.h" /* Field definitions */ #include "protocol.h" -#include "sql_plugin.h" #include "sql_udf.h" #include "sql_partition.h" diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3d061b004e2..f5eb647e600 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -329,7 +329,7 @@ static char *opt_init_slave, *language_ptr, *opt_init_connect; static char *default_character_set_name; static char *character_set_filesystem_name; static char *my_bind_addr_str; -static char *default_collation_name; +static char *default_collation_name, *default_storage_engine_str; static char mysql_data_home_buff[2]; static struct passwd *user_info; static I_List thread_cache; @@ -2651,12 +2651,6 @@ static int init_common_variables(const char *conf_file_name, int argc, if (add_status_vars(status_vars)) return 1; // an error was already reported - if (plugin_init()) - { - sql_print_error("Failed to init plugins."); - return 1; - } - load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; get_options(argc,argv); @@ -3172,6 +3166,12 @@ server."); using_update_log=1; } + if (plugin_init()) + { + sql_print_error("Failed to init plugins."); + return 1; + } + /* We have to initialize the storage engines before CSV logging */ if (ha_init()) { @@ -3218,15 +3218,27 @@ server."); /* Check that the default storage engine is actually available. */ - if (!ha_storage_engine_is_enabled(global_system_variables.table_type)) { - if (!opt_bootstrap) + LEX_STRING name= { default_storage_engine_str, + strlen(default_storage_engine_str) }; + handlerton *hton= ha_resolve_by_name(0, &name); + if (hton == NULL) { - sql_print_error("Default storage engine (%s) is not available", - global_system_variables.table_type->name); + sql_print_error("Unknown/unsupported table type: %s", + default_storage_engine_str); unireg_abort(1); } - global_system_variables.table_type= &myisam_hton; + if (!ha_storage_engine_is_enabled(hton)) + { + if (!opt_bootstrap) + { + sql_print_error("Default storage engine (%s) is not available", + default_storage_engine_str); + unireg_abort(1); + } + hton= &myisam_hton; + } + global_system_variables.table_type= hton; } tc_log= (total_ha_2pc > 1 ? (opt_bin_log ? @@ -4901,14 +4913,6 @@ Disable with --skip-bdb (will save memory).", {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB, "Tells the master that updates to the given database should not be logged tothe binary log.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT) - {"binlog-show-xid", OPT_BINLOG_SHOW_XID, - "Option used by mysql-test for debugging and testing: " - "do not display the XID in SHOW BINLOG EVENTS; " - "may be removed in future versions", - (gptr*) &Xid_log_event::show_xid, (gptr*) &Xid_log_event::show_xid, - 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, -#endif #ifdef HAVE_ROW_BASED_REPLICATION {"binlog-row-event-max-size", OPT_BINLOG_ROWS_EVENT_MAX_SIZE, "The maximum size of a row-based binary log event in bytes. Rows will be " @@ -4975,7 +4979,8 @@ Disable with --skip-bdb (will save memory).", "Set the default storage engine (table type) for tables.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-table-type", OPT_STORAGE_ENGINE, - "(deprecated) Use --default-storage-engine.", 0, 0, + "(deprecated) Use --default-storage-engine.", + (gptr*)default_storage_engine_str, (gptr*)default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.", (gptr*) &default_tz_name, (gptr*) &default_tz_name, @@ -7004,8 +7009,8 @@ static void mysql_init_variables(void) sys_charset_system.value= (char*) system_charset_info->csname; character_set_filesystem_name= (char*) "binary"; - /* Set default values for some option variables */ + default_storage_engine_str="MyISAM"; global_system_variables.table_type= &myisam_hton; global_system_variables.tx_isolation= ISO_REPEATABLE_READ; global_system_variables.select_limit= (ulonglong) HA_POS_ERROR; @@ -7465,17 +7470,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case OPT_BOOTSTRAP: opt_noacl=opt_bootstrap=1; break; - case OPT_STORAGE_ENGINE: - { - LEX_STRING name= { argument, strlen(argument) }; - if ((global_system_variables.table_type= - ha_resolve_by_name(current_thd, &name)) == NULL) - { - fprintf(stderr,"Unknown/unsupported table type: %s\n",argument); - exit(1); - } - break; - } case OPT_SERVER_ID: server_id_supplied = 1; break; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 0924a8adf6e..289296fcac3 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -685,8 +685,20 @@ bool partition_info::check_partition_info(handlerton **eng_type, uint i, tot_partitions; bool result= TRUE; char *same_name; + bool part_expression_ok= TRUE; DBUG_ENTER("partition_info::check_partition_info"); + if (part_type != HASH_PARTITION || !list_of_part_fields) + part_expr->walk(&Item::check_partition_func_processor, + (byte*)(&part_expression_ok)); + if (is_sub_partitioned() && !list_of_subpart_fields) + subpart_expr->walk(&Item::check_partition_func_processor, + (byte*)(&part_expression_ok)); + if (!part_expression_ok) + { + my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); + goto end; + } if (unlikely(!is_sub_partitioned() && !(use_default_subpartitions && use_default_no_subpartitions))) { diff --git a/sql/set_var.cc b/sql/set_var.cc index 242fe0f6068..3dbbd243ee4 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3307,7 +3307,7 @@ byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, handlerton *val; val= (type == OPT_GLOBAL) ? global_system_variables.*offset : thd->variables.*offset; - return (byte *) val->name; + return (byte *) hton2plugin[val->slot]->name.str; } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 5aab951b2ca..58dc107900a 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5832,6 +5832,9 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT eng "The NDB cluster engine does not support changing the binlog format on the fly yet" ER_PARTITION_NO_TEMPORARY eng "Cannot create temporary table with partitions" +ER_PARTITION_FUNCTION_IS_NOT_ALLOWED + eng "This partition function is not allowed" + swe "Denna partitioneringsfunktion är inte tillåten" ER_DDL_LOG_ERROR eng "Error in DDL log" ER_NULL_IN_VALUES_LESS_THAN diff --git a/sql/slave.cc b/sql/slave.cc index 4ab9e951813..5ef91b1f0d4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -95,6 +95,8 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) { bool set_io = mi->slave_running, set_sql = mi->rli.slave_running; register int tmp_mask=0; + DBUG_ENTER("init_thread_mask"); + if (set_io) tmp_mask |= SLAVE_IO; if (set_sql) @@ -102,6 +104,7 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) if (inverse) tmp_mask^= (SLAVE_IO | SLAVE_SQL); *mask = tmp_mask; + DBUG_VOID_RETURN; } @@ -111,9 +114,12 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse) void lock_slave_threads(MASTER_INFO* mi) { + DBUG_ENTER("lock_slave_threads"); + //TODO: see if we can do this without dual mutex pthread_mutex_lock(&mi->run_lock); pthread_mutex_lock(&mi->rli.run_lock); + DBUG_VOID_RETURN; } @@ -123,9 +129,12 @@ void lock_slave_threads(MASTER_INFO* mi) void unlock_slave_threads(MASTER_INFO* mi) { + DBUG_ENTER("unlock_slave_threads"); + //TODO: see if we can do this without dual mutex pthread_mutex_unlock(&mi->rli.run_lock); pthread_mutex_unlock(&mi->run_lock); + DBUG_VOID_RETURN; } @@ -423,6 +432,8 @@ err: void init_slave_skip_errors(const char* arg) { const char *p; + DBUG_ENTER("init_slave_skip_errors"); + if (bitmap_init(&slave_error_mask,0,MAX_SLAVE_ERROR,0)) { fprintf(stderr, "Badly out of memory, please check your system status\n"); @@ -434,7 +445,7 @@ void init_slave_skip_errors(const char* arg) if (!my_strnncoll(system_charset_info,(uchar*)arg,4,(const uchar*)"all",4)) { bitmap_set_all(&slave_error_mask); - return; + DBUG_VOID_RETURN; } for (p= arg ; *p; ) { @@ -446,12 +457,15 @@ void init_slave_skip_errors(const char* arg) while (!my_isdigit(system_charset_info,*p) && *p) p++; } + DBUG_VOID_RETURN; } void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, bool skip_lock) { + DBUG_ENTER("st_relay_log_info::inc_group_relay_log_pos"); + if (!skip_lock) pthread_mutex_lock(&data_lock); inc_event_relay_log_pos(); @@ -500,12 +514,14 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, pthread_cond_broadcast(&data_cond); if (!skip_lock) pthread_mutex_unlock(&data_lock); + DBUG_VOID_RETURN; } void st_relay_log_info::close_temporary_tables() { TABLE *table,*next; + DBUG_ENTER("st_relay_log_info::close_temporary_tables"); for (table=save_temporary_tables ; table ; table=next) { @@ -514,10 +530,12 @@ void st_relay_log_info::close_temporary_tables() Don't ask for disk deletion. For now, anyway they will be deleted when slave restarts, but it is a better intention to not delete them. */ + DBUG_PRINT("info", ("table: %p", table)); close_temporary(table, 1, 0); } save_temporary_tables= 0; slave_open_temp_tables= 0; + DBUG_VOID_RETURN; } /* @@ -613,12 +631,13 @@ err: int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock) { + DBUG_ENTER("terminate_slave_threads"); + if (!mi->inited) - return 0; /* successfully do nothing */ + DBUG_RETURN(0); /* successfully do nothing */ int error,force_all = (thread_mask & SLAVE_FORCE_ALL); pthread_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock; pthread_mutex_t *sql_cond_lock,*io_cond_lock; - DBUG_ENTER("terminate_slave_threads"); sql_cond_lock=sql_lock; io_cond_lock=io_lock; @@ -704,9 +723,10 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, { pthread_t th; ulong start_id; - DBUG_ASSERT(mi->inited); DBUG_ENTER("start_slave_thread"); + DBUG_ASSERT(mi->inited); + if (start_lock) pthread_mutex_lock(start_lock); if (!server_id) @@ -810,8 +830,10 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, #ifdef NOT_USED_YET static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) { + DBUG_ENTER("end_slave_on_walk"); + end_master_info(mi); - return 0; + DBUG_RETURN(0); } #endif @@ -825,6 +847,8 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) void end_slave() { + DBUG_ENTER("end_slave"); + /* This is called when the server terminates, in close_connections(). It terminates slave threads. However, some CHANGE MASTER etc may still be @@ -846,19 +870,24 @@ void end_slave() active_mi= 0; } pthread_mutex_unlock(&LOCK_active_mi); + DBUG_VOID_RETURN; } static bool io_slave_killed(THD* thd, MASTER_INFO* mi) { + DBUG_ENTER("io_slave_killed"); + DBUG_ASSERT(mi->io_thd == thd); DBUG_ASSERT(mi->slave_running); // tracking buffer overrun - return mi->abort_slave || abort_loop || thd->killed; + DBUG_RETURN(mi->abort_slave || abort_loop || thd->killed); } static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) { + DBUG_ENTER("sql_slave_killed"); + DBUG_ASSERT(rli->sql_thd == thd); DBUG_ASSERT(rli->slave_running == 1);// tracking buffer overrun if (abort_loop || thd->killed || rli->abort_slave) @@ -873,7 +902,7 @@ static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) is actively working. */ if (!rli->unsafe_to_stop_at) - return 1; + DBUG_RETURN(1); DBUG_PRINT("info", ("Slave SQL thread is in an unsafe situation, giving " "it some grace period")); if (difftime(time(0), rli->unsafe_to_stop_at) > 60) @@ -885,10 +914,10 @@ static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli) "There is a risk of duplicate updates when the slave " "SQL thread is restarted. Please check your tables' " "contents after restart."); - return 1; + DBUG_RETURN(1); } } - return 0; + DBUG_RETURN(0); } @@ -917,6 +946,8 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, char buff[MAX_SLAVE_ERRMSG], *pbuff= buff; uint pbuffsize= sizeof(buff); va_list args; + DBUG_ENTER("slave_print_msg"); + va_start(args,msg); switch (level) { @@ -943,7 +974,7 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, break; default: DBUG_ASSERT(0); // should not come here - return; // don't crash production builds, just do nothing + DBUG_VOID_RETURN; // don't crash production builds, just do nothing } my_vsnprintf(pbuff, pbuffsize, msg, args); /* If the msg string ends with '.', do not add a ',' it would be ugly */ @@ -951,6 +982,7 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, (*report_function)("Slave: %s Error_code: %d", pbuff, err_code); else (*report_function)("Slave: %s, Error_code: %d", pbuff, err_code); + DBUG_VOID_RETURN; } /* @@ -962,9 +994,12 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, void skip_load_data_infile(NET *net) { + DBUG_ENTER("skip_load_data_infile"); + (void)net_request_file(net, "/dev/null"); (void)my_net_read(net); // discard response (void)net_write_command(net, 0, "", 0, "", 0); // Send ok + DBUG_VOID_RETURN; } @@ -983,13 +1018,17 @@ bool net_request_file(NET* net, const char* fname) const char *print_slave_db_safe(const char* db) { - return (db ? db : ""); + DBUG_ENTER("*print_slave_db_safe"); + + DBUG_RETURN((db ? db : "")); } static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val) { uint length; + DBUG_ENTER("init_strvar_from_file"); + if ((length=my_b_gets(f,var, max_size))) { char* last_p = var + length -1; @@ -1004,32 +1043,34 @@ static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, int c; while (((c=my_b_get(f)) != '\n' && c != my_b_EOF)); } - return 0; + DBUG_RETURN(0); } else if (default_val) { strmake(var, default_val, max_size-1); - return 0; + DBUG_RETURN(0); } - return 1; + DBUG_RETURN(1); } static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) { char buf[32]; + DBUG_ENTER("init_intvar_from_file"); + if (my_b_gets(f, buf, sizeof(buf))) { *var = atoi(buf); - return 0; + DBUG_RETURN(0); } else if (default_val) { *var = default_val; - return 0; + DBUG_RETURN(0); } - return 1; + DBUG_RETURN(1); } /* @@ -1049,6 +1090,7 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) { const char* errmsg= 0; + DBUG_ENTER("get_master_version_and_clock"); /* Free old description_event_for_queue (that is needed if we are in @@ -1104,14 +1146,14 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi) if (errmsg) { sql_print_error(errmsg); - return 1; + DBUG_RETURN(1); } /* as we are here, we tried to allocate the event */ if (!mi->rli.relay_log.description_event_for_queue) { sql_print_error("Slave I/O thread failed to create a default Format_description_log_event"); - return 1; + DBUG_RETURN(1); } /* @@ -1227,10 +1269,10 @@ err: if (errmsg) { sql_print_error(errmsg); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } /* @@ -1257,7 +1299,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, handler *file; ulong save_options; NET *net= &mysql->net; - DBUG_ENTER("create_table_from_dump"); + DBUG_ENTER("create_table_from_dump"); packet_len= my_net_read(net); // read create table statement if (packet_len == packet_error) @@ -1666,7 +1708,6 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) MASTER_INFO* mi = rli->mi; const char *save_proc_info; THD* thd = mi->io_thd; - DBUG_ENTER("wait_for_relay_log_space"); pthread_mutex_lock(&rli->log_space_lock); @@ -1725,6 +1766,8 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) { RELAY_LOG_INFO *rli= &mi->rli; pthread_mutex_t *log_lock= rli->relay_log.get_log_lock(); + DBUG_ENTER("write_ignored_events_info_to_relay_log"); + DBUG_ASSERT(thd == mi->io_thd); pthread_mutex_lock(log_lock); if (rli->ign_master_log_name_end[0]) @@ -1755,11 +1798,14 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) } else pthread_mutex_unlock(log_lock); + DBUG_VOID_RETURN; } void init_master_info_with_options(MASTER_INFO* mi) { + DBUG_ENTER("init_master_info_with_options"); + mi->master_log_name[0] = 0; mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number @@ -1783,13 +1829,17 @@ void init_master_info_with_options(MASTER_INFO* mi) strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1); if (master_ssl_key) strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1); + DBUG_VOID_RETURN; } void clear_slave_error(RELAY_LOG_INFO* rli) { + DBUG_ENTER("clear_slave_error"); + /* Clear the errors displayed by SHOW SLAVE STATUS */ rli->last_slave_error[0]= 0; rli->last_slave_errno= 0; + DBUG_VOID_RETURN; } /* @@ -1800,9 +1850,12 @@ void clear_slave_error(RELAY_LOG_INFO* rli) */ void clear_until_condition(RELAY_LOG_INFO* rli) { + DBUG_ENTER("clear_until_condition"); + rli->until_condition= RELAY_LOG_INFO::UNTIL_NONE; rli->until_log_name[0]= 0; rli->until_log_pos= 0; + DBUG_VOID_RETURN; } @@ -2031,9 +2084,10 @@ int register_slave_on_master(MYSQL* mysql) { char buf[1024], *pos= buf; uint report_host_len, report_user_len=0, report_password_len=0; + DBUG_ENTER("register_slave_on_master"); if (!report_host) - return 0; + DBUG_RETURN(0); report_host_len= strlen(report_host); if (report_user) report_user_len= strlen(report_user); @@ -2042,7 +2096,7 @@ int register_slave_on_master(MYSQL* mysql) /* 30 is a good safety margin */ if (report_host_len + report_user_len + report_password_len + 30 > sizeof(buf)) - return 0; // safety + DBUG_RETURN(0); // safety int4store(pos, server_id); pos+= 4; pos= net_store_data(pos, report_host, report_host_len); @@ -2059,9 +2113,9 @@ int register_slave_on_master(MYSQL* mysql) sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'", mysql_errno(mysql), mysql_error(mysql)); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } @@ -2313,6 +2367,8 @@ st_relay_log_info::st_relay_log_info() m_reload_flags(RELOAD_NONE_F), unsafe_to_stop_at(0) { + DBUG_ENTER("st_relay_log_info::st_relay_log_info"); + group_relay_log_name[0]= event_relay_log_name[0]= group_master_log_name[0]= 0; last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0; @@ -2327,11 +2383,14 @@ st_relay_log_info::st_relay_log_info() pthread_cond_init(&stop_cond, NULL); pthread_cond_init(&log_space_cond, NULL); relay_log.init_pthread_objects(); + DBUG_VOID_RETURN; } st_relay_log_info::~st_relay_log_info() { + DBUG_ENTER("st_relay_log_info::~st_relay_log_info"); + pthread_mutex_destroy(&run_lock); pthread_mutex_destroy(&data_lock); pthread_mutex_destroy(&log_space_lock); @@ -2340,6 +2399,7 @@ st_relay_log_info::~st_relay_log_info() pthread_cond_destroy(&stop_cond); pthread_cond_destroy(&log_space_cond); relay_log.cleanup(); + DBUG_VOID_RETURN; } /* @@ -2371,14 +2431,16 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, longlong log_pos, longlong timeout) { - if (!inited) - return -1; int event_count = 0; ulong init_abort_pos_wait; int error=0; struct timespec abstime; // for timeout checking const char *msg; - DBUG_ENTER("wait_for_pos"); + DBUG_ENTER("st_relay_log_info::wait_for_pos"); + + if (!inited) + DBUG_RETURN(-1); + DBUG_PRINT("enter",("log_name: '%s' log_pos: %lu timeout: %lu", log_name->c_ptr(), (ulong) log_pos, (ulong) timeout)); @@ -2546,13 +2608,18 @@ improper_arguments: %d timed_out: %d", void set_slave_thread_options(THD* thd) { + DBUG_ENTER("set_slave_thread_options"); + thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) | OPTION_AUTO_IS_NULL; thd->variables.completion_type= 0; + DBUG_VOID_RETURN; } void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli) { + DBUG_ENTER("set_slave_thread_default_charset"); + thd->variables.character_set_client= global_system_variables.character_set_client; thd->variables.collation_connection= @@ -2561,6 +2628,7 @@ void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli) global_system_variables.collation_server; thd->update_charset(); rli->cached_charset_invalidate(); + DBUG_VOID_RETURN; } /* @@ -2622,6 +2690,8 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, { int nap_time; thr_alarm_t alarmed; + DBUG_ENTER("safe_sleep"); + thr_alarm_init(&alarmed); time_t start_time= time((time_t*) 0); time_t end_time= start_time+sec; @@ -2639,10 +2709,10 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, thr_end_alarm(&alarmed); if ((*thread_killed)(thd,thread_killed_arg)) - return 1; + DBUG_RETURN(1); start_time=time((time_t*) 0); } - return 0; + DBUG_RETURN(0); } @@ -2684,13 +2754,15 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi, static int request_table_dump(MYSQL* mysql, const char* db, const char* table) { char buf[1024]; + DBUG_ENTER("request_table_dump"); + char * p = buf; uint table_len = (uint) strlen(table); uint db_len = (uint) strlen(db); if (table_len + db_len > sizeof(buf) - 2) { sql_print_error("request_table_dump: Buffer overrun"); - return 1; + DBUG_RETURN(1); } *p++ = db_len; @@ -2703,10 +2775,10 @@ static int request_table_dump(MYSQL* mysql, const char* db, const char* table) { sql_print_error("request_table_dump: Error sending the table dump \ command"); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } @@ -2730,6 +2802,7 @@ command"); static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) { ulong len; + DBUG_ENTER("read_event"); *suppress_warnings= 0; /* @@ -2738,7 +2811,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) */ #ifndef DBUG_OFF if (disconnect_slave_event_count && !(mi->events_till_disconnect--)) - return packet_error; + DBUG_RETURN(packet_error); #endif len = net_safe_read(mysql); @@ -2756,7 +2829,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) else sql_print_error("Error reading packet from server: %s ( server_errno=%d)", mysql_error(mysql), mysql_errno(mysql)); - return packet_error; + DBUG_RETURN(packet_error); } /* Check if eof packet */ @@ -2765,25 +2838,27 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) sql_print_information("Slave: received end packet from server, apparent " "master shutdown: %s", mysql_error(mysql)); - return packet_error; + DBUG_RETURN(packet_error); } DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n", len, mysql->net.read_pos[4])); - return len - 1; + DBUG_RETURN(len - 1); } int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) { + DBUG_ENTER("check_expected_error"); + switch (expected_error) { case ER_NET_READ_ERROR: case ER_NET_ERROR_ON_WRITE: case ER_SERVER_SHUTDOWN: case ER_NEW_ABORTING_CONNECTION: - return 1; + DBUG_RETURN(1); default: - return 0; + DBUG_RETURN(0); } } @@ -2819,6 +2894,7 @@ bool st_relay_log_info::is_until_satisfied() { const char *log_name; ulonglong log_pos; + DBUG_ENTER("st_relay_log_info::is_until_satisfied"); DBUG_ASSERT(until_condition != UNTIL_NONE); @@ -2865,34 +2941,39 @@ bool st_relay_log_info::is_until_satisfied() /* Probably error so we aborting */ sql_print_error("Slave SQL thread is stopped because UNTIL " "condition is bad."); - return TRUE; + DBUG_RETURN(TRUE); } } else - return until_log_pos == 0; + DBUG_RETURN(until_log_pos == 0); } - return ((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && + DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && log_pos >= until_log_pos) || - until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER); + until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); } void st_relay_log_info::cached_charset_invalidate() { + DBUG_ENTER("st_relay_log_info::cached_charset_invalidate"); + /* Full of zeroes means uninitialized. */ bzero(cached_charset, sizeof(cached_charset)); + DBUG_VOID_RETURN; } bool st_relay_log_info::cached_charset_compare(char *charset) { + DBUG_ENTER("st_relay_log_info::cached_charset_compare"); + if (bcmp(cached_charset, charset, sizeof(cached_charset))) { memcpy(cached_charset, charset, sizeof(cached_charset)); - return 1; + DBUG_RETURN(1); } - return 0; + DBUG_RETURN(0); } /* @@ -2904,8 +2985,10 @@ bool st_relay_log_info::cached_charset_compare(char *charset) */ static int has_temporary_error(THD *thd) { + DBUG_ENTER("has_temporary_error"); + if (thd->is_fatal_error) - return 0; + DBUG_RETURN(0); /* Temporary error codes: @@ -2914,7 +2997,7 @@ static int has_temporary_error(THD *thd) */ if (thd->net.last_errno == ER_LOCK_DEADLOCK || thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT) - return 1; + DBUG_RETURN(1); #ifdef HAVE_NDB_BINLOG /* @@ -2928,17 +3011,19 @@ static int has_temporary_error(THD *thd) switch (err->code) { case ER_GET_TEMPORARY_ERRMSG: - return 1; + DBUG_RETURN(1); default: break; } } #endif - return 0; + DBUG_RETURN(0); } static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) { + DBUG_ENTER("exec_relay_log_event"); + /* We acquire this mutex since we need it for all operations except event execution. But we will release it in places where we will @@ -2965,7 +3050,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) */ rli->abort_slave= 1; pthread_mutex_unlock(&rli->data_lock); - return 1; + DBUG_RETURN(1); } Log_event * ev = next_event(rli); @@ -2976,7 +3061,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) { pthread_mutex_unlock(&rli->data_lock); delete ev; - return 1; + DBUG_RETURN(1); } if (ev) { @@ -3044,7 +3129,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) --rli->slave_skip_counter; pthread_mutex_unlock(&rli->data_lock); delete ev; - return 0; // avoid infinite update loops + DBUG_RETURN(0); // avoid infinite update loops } pthread_mutex_unlock(&rli->data_lock); @@ -3125,13 +3210,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) */ rli->trans_retries= 0; // restart from fresh } - } - return exec_res; + } + DBUG_RETURN(exec_res); } - else - { - pthread_mutex_unlock(&rli->data_lock); - slave_print_msg(ERROR_LEVEL, rli, 0, "\ + pthread_mutex_unlock(&rli->data_lock); + slave_print_msg(ERROR_LEVEL, rli, 0, "\ Could not parse relay log event entry. The possible reasons are: the master's \ binary log is corrupted (you can check this by running 'mysqlbinlog' on the \ binary log), the slave's relay log is corrupted (you can check this by running \ @@ -3140,8 +3223,7 @@ or slave's MySQL code. If you want to check the master's binary log or slave's \ relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \ on this slave.\ "); - return 1; - } + DBUG_RETURN(1); } @@ -3461,6 +3543,7 @@ pthread_handler_t handle_slave_sql(void *arg) { THD *thd; /* needs to be first for thread_stack */ char llbuff[22],llbuff1[22]; + RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli; const char *errmsg; @@ -4060,16 +4143,18 @@ err: static int queue_old_event(MASTER_INFO *mi, const char *buf, ulong event_len) { + DBUG_ENTER("queue_old_event"); + switch (mi->rli.relay_log.description_event_for_queue->binlog_version) { case 1: - return queue_binlog_ver_1_event(mi,buf,event_len); + DBUG_RETURN(queue_binlog_ver_1_event(mi,buf,event_len)); case 3: - return queue_binlog_ver_3_event(mi,buf,event_len); + DBUG_RETURN(queue_binlog_ver_3_event(mi,buf,event_len)); default: /* unsupported format; eg version 2 */ DBUG_PRINT("info",("unsupported binlog format %d in queue_old_event()", mi->rli.relay_log.description_event_for_queue->binlog_version)); - return 1; + DBUG_RETURN(1); } } @@ -4282,7 +4367,9 @@ void end_relay_log_info(RELAY_LOG_INFO* rli) static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) { - return connect_to_master(thd, mysql, mi, 0, 0); + DBUG_ENTER("safe_connect"); + + DBUG_RETURN(connect_to_master(thd, mysql, mi, 0, 0)); } @@ -4439,9 +4526,10 @@ static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi, bool flush_relay_log_info(RELAY_LOG_INFO* rli) { bool error=0; + DBUG_ENTER("flush_relay_log_info"); if (unlikely(rli->no_storage)) - return 0; + DBUG_RETURN(0); IO_CACHE *file = &rli->info_file; char buff[FN_REFLEN*2+22*2+4], *pos; @@ -4461,7 +4549,7 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) error=1; /* Flushing the relay log is done by the slave I/O thread */ - return error; + DBUG_RETURN(error); } @@ -4471,9 +4559,9 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg) { + DBUG_ENTER("reopen_relay_log"); DBUG_ASSERT(rli->cur_log != &rli->cache_buf); DBUG_ASSERT(rli->cur_log_fd == -1); - DBUG_ENTER("reopen_relay_log"); IO_CACHE *cur_log = rli->cur_log=&rli->cache_buf; if ((rli->cur_log_fd=open_binlog(cur_log,rli->event_relay_log_name, @@ -4494,11 +4582,11 @@ static Log_event* next_event(RELAY_LOG_INFO* rli) { Log_event* ev; IO_CACHE* cur_log = rli->cur_log; - pthread_mutex_t *log_lock = rli->relay_log.get_log_lock(); + pthread_mutex_t *log_lock = rli->relay_log.get_log_lock(); const char* errmsg=0; THD* thd = rli->sql_thd; - DBUG_ENTER("next_event"); + DBUG_ASSERT(thd != 0); #ifndef DBUG_OFF @@ -4909,12 +4997,16 @@ static int reload_entry_compare(const void *lhs, const void *rhs) { const char *lstr = static_cast(lhs); const char *rstr = static_cast(rhs)->table; - return strcmp(lstr, rstr); + DBUG_ENTER("reload_entry_compare"); + + DBUG_RETURN(strcmp(lstr, rstr)); } void st_relay_log_info::touching_table(char const* db, char const* table, ulong table_id) { + DBUG_ENTER("st_relay_log_info::touching_table"); + if (strcmp(db,"mysql") == 0) { #if defined(HAVE_BSEARCH) && defined(HAVE_SIZE_T) @@ -4935,10 +5027,13 @@ void st_relay_log_info::touching_table(char const* db, char const* table, if (entry) m_reload_flags|= entry->flag; } + DBUG_VOID_RETURN; } void st_relay_log_info::transaction_end(THD* thd) { + DBUG_ENTER("st_relay_log_info::transaction_end"); + if (m_reload_flags != RELOAD_NONE_F) { if (m_reload_flags & RELOAD_ACCESS_F) @@ -4949,11 +5044,14 @@ void st_relay_log_info::transaction_end(THD* thd) m_reload_flags= RELOAD_NONE_F; } + DBUG_VOID_RETURN; } #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) void st_relay_log_info::cleanup_context(THD *thd, bool error) { + DBUG_ENTER("st_relay_log_info::cleanup_context"); + DBUG_ASSERT(sql_thd == thd); /* 1) Instances of Table_map_log_event, if ::exec_event() was called on them, @@ -4976,6 +5074,7 @@ void st_relay_log_info::cleanup_context(THD *thd, bool error) close_thread_tables(thd); clear_tables_to_lock(); unsafe_to_stop_at= 0; + DBUG_VOID_RETURN; } #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3206cfa2d52..9041e713782 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7143,7 +7143,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) HA_CREATE_INFO create_info; DBUG_ENTER("mysql_create_index"); bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= (handlerton*) &default_hton; + create_info.db_type= 0; create_info.default_table_charset= thd->variables.collation_database; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, @@ -7159,7 +7159,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) HA_CREATE_INFO create_info; DBUG_ENTER("mysql_drop_index"); bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= (handlerton*) &default_hton; + create_info.db_type= 0; create_info.default_table_charset= thd->variables.collation_database; alter_info->clear(); alter_info->flags= ALTER_DROP_INDEX; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e946e972968..53536e72961 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1665,8 +1665,8 @@ static int add_keyword_int(File fptr, const char *keyword, longlong num) static int add_engine(File fptr, handlerton *engine_type) { - const char *engine_str= engine_type->name; - DBUG_PRINT("info", ("ENGINE = %s", engine_str)); + const char *engine_str= hton2plugin[engine_type->slot]->name.str; + DBUG_PRINT("info", ("ENGINE: %s", engine_str)); int err= add_string(fptr, "ENGINE = "); return err + add_string(fptr, engine_str); } @@ -1676,7 +1676,7 @@ static int add_partition_options(File fptr, partition_element *p_elem) int err= 0; if (p_elem->tablespace_name) - err+= add_keyword_string(fptr,"TABLESPACE", FALSE, + err+= add_keyword_string(fptr,"TABLESPACE", FALSE, p_elem->tablespace_name); if (p_elem->nodegroup_id != UNDEF_NODEGROUP) err+= add_keyword_int(fptr,"NODEGROUP",(longlong)p_elem->nodegroup_id); @@ -1843,6 +1843,8 @@ char *generate_partition_syntax(partition_info *part_info, { err+= add_subpartition_by(fptr); /* Must be hash partitioning for subpartitioning */ + if (part_info->linear_hash_ind) + err+= add_string(fptr, partition_keywords[PKW_LINEAR].str); if (part_info->list_of_subpart_fields) err+= add_key_partition(fptr, part_info->subpart_field_list); else @@ -3559,17 +3561,9 @@ static bool check_engine_condition(partition_element *p_elem, DBUG_ENTER("check_engine_condition"); DBUG_PRINT("enter", ("def_eng = %u, first = %u", default_engine, *first)); - if (*engine_type) - DBUG_PRINT("info", ("engine_type = %s", (*engine_type)->name)); - else - DBUG_PRINT("info", ("engine_type = NULL")); if (*first && default_engine) { *engine_type= p_elem->engine_type; - if (*engine_type) - DBUG_PRINT("info", ("engine_type changed to = %s", (*engine_type)->name)); - else - DBUG_PRINT("info", ("engine_type changed to = NULL")); } *first= FALSE; if ((!default_engine && @@ -4523,8 +4517,8 @@ the generated partition syntax in a correct manner. DBUG_PRINT("info", ("No explicit engine used")); create_info->db_type= table->part_info->default_engine_type; } - DBUG_PRINT("info", ("New engine type = %s", - create_info->db_type->name)); + DBUG_PRINT("info", ("New engine type: %s", + hton2plugin[create_info->db_type->slot]->name.str)); thd->work_part_info= NULL; *partition_changed= TRUE; } @@ -4586,11 +4580,9 @@ the generated partition syntax in a correct manner. } if (!is_native_partitioned) { - DBUG_ASSERT(create_info->db_type != &default_hton); + DBUG_ASSERT(create_info->db_type); create_info->db_type= &partition_hton; } - DBUG_PRINT("info", ("default_engine_type = %s", - thd->work_part_info->default_engine_type->name)); } } DBUG_RETURN(FALSE); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 01faae22c57..4f5d952eb7b 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -23,12 +23,18 @@ extern struct st_mysql_plugin *mysqld_builtins[]; char *opt_plugin_dir_ptr; char opt_plugin_dir[FN_REFLEN]; -LEX_STRING plugin_type_names[]= +LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= { { (char *)STRING_WITH_LEN("UDF") }, { (char *)STRING_WITH_LEN("STORAGE ENGINE") }, { (char *)STRING_WITH_LEN("FTPARSER") } }; + +plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]= +{ + 0,ha_initialize_handlerton,0 +}; + static const char *plugin_interface_version_sym= "_mysql_plugin_interface_version_"; static const char *sizeof_st_plugin_sym= @@ -41,8 +47,8 @@ static int min_plugin_interface_version= 0x0000; static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= { 0x0000, - 0x0000, - 0x0000 + MYSQL_HANDLERTON_INTERFACE_VERSION, + MYSQL_FTPARSER_INTERFACE_VERSION }; static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= { @@ -50,6 +56,7 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= MYSQL_HANDLERTON_INTERFACE_VERSION, MYSQL_FTPARSER_INTERFACE_VERSION }; + static DYNAMIC_ARRAY plugin_dl_array; static DYNAMIC_ARRAY plugin_array; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; @@ -522,27 +529,15 @@ static int plugin_initialize(struct st_plugin_int *plugin) { sql_print_error("Plugin '%s' init function returned error.", plugin->name.str); - DBUG_PRINT("warning", ("Plugin '%s' init function returned error.", - plugin->name.str)); goto err; } } - - switch (plugin->plugin->type) + if (plugin_type_initialize[plugin->plugin->type] && + (*plugin_type_initialize[plugin->plugin->type])(plugin)) { - case MYSQL_STORAGE_ENGINE_PLUGIN: - if (ha_initialize_handlerton(plugin)) - { - sql_print_error("Plugin '%s' handlerton init returned error.", - plugin->name.str); - DBUG_PRINT("warning", ("Plugin '%s' handlerton init returned error.", - plugin->name.str)); - goto err; - } - break; - - default: - break; + sql_print_error("Plugin '%s' registration as a %s failed.", + plugin->name.str, plugin_type_names[plugin->plugin->type]); + goto err; } DBUG_RETURN(0); @@ -554,14 +549,14 @@ static int plugin_finalize(THD *thd, struct st_plugin_int *plugin) { int rc; DBUG_ENTER("plugin_finalize"); - + if (plugin->ref_count) { push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, "Plugin is busy and will be uninstalled on shutdown"); goto err; } - + switch (plugin->plugin->type) { case MYSQL_STORAGE_ENGINE_PLUGIN: @@ -591,7 +586,7 @@ static int plugin_finalize(THD *thd, struct st_plugin_int *plugin) goto err; } } - + DBUG_RETURN(0); err: DBUG_RETURN(1); @@ -676,7 +671,7 @@ int plugin_init(void) get_hash_key, NULL, 0)) goto err; } - + /* Register all the built-in plugins */ for (builtins= mysqld_builtins; *builtins; builtins++) { @@ -684,6 +679,12 @@ int plugin_init(void) { if (plugin_register_builtin(plugin)) goto err; + struct st_plugin_int *tmp=dynamic_element(&plugin_array, + plugin_array.elements-1, + struct st_plugin_int *); + if (plugin_initialize(tmp)) + goto err; + tmp->state= PLUGIN_IS_READY; } } diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 672db105cd1..b013beaba1f 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -58,9 +58,12 @@ struct st_plugin_int struct st_mysql_plugin *plugin; struct st_plugin_dl *plugin_dl; enum enum_plugin_state state; - uint ref_count; /* number of threads using the plugin */ + uint ref_count; /* number of threads using the plugin */ + void *data; /* plugin type specific, e.g. handlerton */ }; +typedef int (*plugin_type_init)(struct st_plugin_int *); + extern char *opt_plugin_dir_ptr; extern char opt_plugin_dir[FN_REFLEN]; extern LEX_STRING plugin_type_names[]; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index bdf0724ee96..dfa90733739 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -47,7 +47,7 @@ static void store_key_options(THD *thd, String *packet, TABLE *table, KEY *key_info); /*************************************************************************** -** List all table types supported +** List all table types supported ***************************************************************************/ static my_bool show_handlerton(THD *thd, st_plugin_int *plugin, @@ -55,25 +55,26 @@ static my_bool show_handlerton(THD *thd, st_plugin_int *plugin, { handlerton *default_type= (handlerton *) arg; Protocol *protocol= thd->protocol; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if (!(hton->flags & HTON_HIDDEN)) { protocol->prepare_for_resend(); - protocol->store(hton->name, system_charset_info); + protocol->store(plugin->name.str, plugin->name.length, + system_charset_info); const char *option_name= show_comp_option_name[(int) hton->state]; if (hton->state == SHOW_OPTION_YES && default_type == hton) option_name= "DEFAULT"; protocol->store(option_name, system_charset_info); - protocol->store(hton->comment, system_charset_info); + protocol->store(plugin->plugin->descr, system_charset_info); protocol->store(hton->commit ? "YES" : "NO", system_charset_info); protocol->store(hton->prepare ? "YES" : "NO", system_charset_info); protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info); - + return protocol->write() ? 1 : 0; } - return 0; + return 0; } bool mysqld_show_storage_engines(THD *thd) @@ -93,7 +94,7 @@ bool mysqld_show_storage_engines(THD *thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - if (plugin_foreach(thd, show_handlerton, + if (plugin_foreach(thd, show_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type)) DBUG_RETURN(TRUE); @@ -3091,7 +3092,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, void *ptable) { TABLE *table= (TABLE *) ptable; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; CHARSET_INFO *scs= system_charset_info; DBUG_ENTER("iter_schema_engines"); @@ -3099,21 +3100,25 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, if (!(hton->flags & HTON_HIDDEN)) { if (!(wild && wild[0] && - wild_case_compare(scs, hton->name,wild))) + wild_case_compare(scs, plugin->name.str,wild))) { - const char *tmp; + LEX_STRING state[2]={{STRING_WITH_LEN("ENABLED")}, + {STRING_WITH_LEN("DISABLED")}}; + LEX_STRING yesno[2]={{STRING_WITH_LEN("NO")}, {STRING_WITH_LEN("YES")}}; + LEX_STRING *tmp; restore_record(table, s->default_values); - table->field[0]->store(hton->name, strlen(hton->name), scs); - tmp= hton->state ? "DISABLED" : "ENABLED"; - table->field[1]->store( tmp, strlen(tmp), scs); - table->field[2]->store(hton->comment, strlen(hton->comment), scs); - tmp= hton->commit ? "YES" : "NO"; - table->field[3]->store( tmp, strlen(tmp), scs); - tmp= hton->prepare ? "YES" : "NO"; - table->field[4]->store( tmp, strlen(tmp), scs); - tmp= hton->savepoint_set ? "YES" : "NO"; - table->field[5]->store( tmp, strlen(tmp), scs); + table->field[0]->store(plugin->name.str, plugin->name.length, scs); + tmp= &state[test(hton->state)]; + table->field[1]->store(tmp->str, tmp->length, scs); + table->field[2]->store(plugin->plugin->descr, + strlen(plugin->plugin->descr), scs); + tmp= &yesno[test(hton->commit)]; + table->field[3]->store(tmp->str, tmp->length, scs); + tmp= &yesno[test(hton->prepare)]; + table->field[4]->store(tmp->str, tmp->length, scs); + tmp= &yesno[test(hton->savepoint_set)]; + table->field[5]->store(tmp->str, tmp->length, scs); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -3125,7 +3130,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin, int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) { - return plugin_foreach(thd, iter_schema_engines, + return plugin_foreach(thd, iter_schema_engines, MYSQL_STORAGE_ENGINE_PLUGIN, tables->table); } @@ -3140,7 +3145,7 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) { CHARSET_INFO **cl; CHARSET_INFO *tmp_cs= cs[0]; - if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || + if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || (tmp_cs->state & MY_CS_HIDDEN) || !(tmp_cs->state & MY_CS_PRIMARY)) continue; @@ -3911,24 +3916,28 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, { table->field[9]->store(part_info->part_func_string, part_info->part_func_len, cs); - table->field[9]->set_notnull(); } else if (part_info->list_of_part_fields) { collect_partition_expr(part_info->part_field_list, &tmp_str); table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs); - table->field[9]->set_notnull(); } + table->field[9]->set_notnull(); if (part_info->is_sub_partitioned()) { /* Subpartition method */ + tmp_res.length(0); + if (part_info->linear_hash_ind) + tmp_res.append(partition_keywords[PKW_LINEAR].str, + partition_keywords[PKW_LINEAR].length); if (part_info->list_of_subpart_fields) - table->field[8]->store(partition_keywords[PKW_KEY].str, - partition_keywords[PKW_KEY].length, cs); + tmp_res.append(partition_keywords[PKW_KEY].str, + partition_keywords[PKW_KEY].length); else - table->field[8]->store(partition_keywords[PKW_HASH].str, - partition_keywords[PKW_HASH].length, cs); + tmp_res.append(partition_keywords[PKW_HASH].str, + partition_keywords[PKW_HASH].length); + table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs); table->field[8]->set_notnull(); /* Subpartition expression */ @@ -3936,14 +3945,13 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, { table->field[10]->store(part_info->subpart_func_string, part_info->subpart_func_len, cs); - table->field[10]->set_notnull(); } else if (part_info->list_of_subpart_fields) { collect_partition_expr(part_info->subpart_field_list, &tmp_str); table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs); - table->field[10]->set_notnull(); } + table->field[10]->set_notnull(); } while ((part_elem= part_it++)) @@ -5003,7 +5011,7 @@ static my_bool run_hton_fill_schema_files(THD *thd, st_plugin_int *plugin, { struct run_hton_fill_schema_files_args *args= (run_hton_fill_schema_files_args *) arg; - handlerton *hton= (handlerton *) plugin->plugin->info; + handlerton *hton= (handlerton *)plugin->data; if(hton->fill_files_table) hton->fill_files_table(thd, args->tables, args->cond); return false; @@ -5347,7 +5355,7 @@ ST_FIELD_INFO partitions_fields_info[]= {"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, {"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, {"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0}, - {"SUBPARTITION_METHOD", 5, MYSQL_TYPE_STRING, 0, 1, 0}, + {"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0}, {"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, {"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, {"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 289051c2dd1..64523ec6310 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3106,7 +3106,8 @@ bool mysql_create_table_internal(THD *thd, } while ((key= key_iterator++)) { - if (key->type == Key::FOREIGN_KEY) + if (key->type == Key::FOREIGN_KEY && + !part_info->is_auto_partitioned) { my_error(ER_CANNOT_ADD_FOREIGN, MYF(0)); goto err; @@ -4980,7 +4981,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } old_db_type= table->s->db_type; - if (create_info->db_type == (handlerton*) &default_hton) + if (!create_info->db_type) create_info->db_type= old_db_type; #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -6307,7 +6308,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, lex->col_list.empty(); lex->alter_info.reset(); bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type= (handlerton*) &default_hton; + create_info.db_type= 0; create_info.row_type=ROW_TYPE_NOT_USED; create_info.default_table_charset=default_charset_info; /* Force alter table to recreate table */ @@ -6451,7 +6452,7 @@ static bool check_engine(THD *thd, const char *table_name, no_substitution, 1))) return TRUE; - if (req_engine != (handlerton*) &default_hton && req_engine != *new_engine) + if (req_engine && req_engine != *new_engine) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_USING_OTHER_HANDLER, @@ -6464,7 +6465,8 @@ static bool check_engine(THD *thd, const char *table_name, { if (create_info->used_fields & HA_CREATE_USED_ENGINE) { - my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), (*new_engine)->name, "TEMPORARY"); + my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), + hton2plugin[(*new_engine)->slot]->name.str, "TEMPORARY"); *new_engine= 0; return TRUE; } diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index 8bc39ec82c6..94318a67575 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -28,16 +28,16 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) If the user haven't defined an engine, this will fallback to using the default storage engine. */ - if (hton == NULL || hton == &default_hton || hton->state != SHOW_OPTION_YES) + if (hton == NULL || hton->state != SHOW_OPTION_YES) { hton= ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT); if (ts_info->storage_engine != 0) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_WARN_USING_OTHER_HANDLER, ER(ER_WARN_USING_OTHER_HANDLER), - hton->name, - ts_info->tablespace_name - ? ts_info->tablespace_name : ts_info->logfile_group_name); + hton2plugin[hton->slot]->name.str, + ts_info->tablespace_name ? ts_info->tablespace_name + : ts_info->logfile_group_name); } if (hton->alter_tablespace) @@ -64,7 +64,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_ILLEGAL_HA_CREATE_OPTION, ER(ER_ILLEGAL_HA_CREATE_OPTION), - hton->name, + hton2plugin[hton->slot]->name.str, "TABLESPACE or LOGFILE GROUP"); } if (mysql_bin_log.is_open()) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 82dcc758ff0..af2bf8231aa 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3102,11 +3102,11 @@ opt_ts_engine: "STORAGE ENGINE"); YYABORT; } - lex->alter_tablespace_info->storage_engine= $4 ? $4 : &default_hton; + lex->alter_tablespace_info->storage_engine= $4; }; opt_ts_wait: - /* empty */ + /* empty */ | ts_wait ; @@ -3942,12 +3942,18 @@ storage_engines: ident_or_text { $$ = ha_resolve_by_name(YYTHD, &$1); - if ($$ == NULL && - test(YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)) + if ($$ == NULL) + if (YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION) { my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str); YYABORT; } + else + { + push_warning_printf(YYTHD, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_UNKNOWN_STORAGE_ENGINE, + ER(ER_UNKNOWN_STORAGE_ENGINE), $1.str); + } }; row_types: @@ -4624,7 +4630,7 @@ alter: lex->select_lex.db=lex->name= 0; lex->like_name= 0; bzero((char*) &lex->create_info,sizeof(lex->create_info)); - lex->create_info.db_type= (handlerton*) &default_hton; + lex->create_info.db_type= 0; lex->create_info.default_table_charset= NULL; lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->alter_info.reset(); diff --git a/sql/table.cc b/sql/table.cc index d0caba7fe9e..5d7b788c755 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2355,12 +2355,23 @@ table_check_intact(TABLE *table, uint table_f_count, // previous MySQL version error= TRUE; if (MYSQL_VERSION_ID > table->s->mysql_version) + { my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias, table_f_count, table->s->fields, table->s->mysql_version, MYSQL_VERSION_ID); + sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE), + table->alias, table_f_count, table->s->fields, + table->s->mysql_version, MYSQL_VERSION_ID); + DBUG_RETURN(error); + + } else if (MYSQL_VERSION_ID == table->s->mysql_version) + { my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,MYF(0), table->alias, table_f_count, table->s->fields); + sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias, + table_f_count, table->s->fields); + } else /* moving from newer mysql to older one -> let's say not an error but diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index f3f20f6b103..39b887a8001 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -145,49 +145,7 @@ static handler *archive_create_handler(TABLE_SHARE *table); */ #define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2 - -static const char archive_hton_name[]= "ARCHIVE"; -static const char archive_hton_comment[]= "Archive storage engine"; - -/* dummy handlerton - only to have something to return from archive_db_init */ -handlerton archive_hton = { - MYSQL_HANDLERTON_INTERFACE_VERSION, - archive_hton_name, - SHOW_OPTION_YES, - archive_hton_comment, - DB_TYPE_ARCHIVE_DB, - archive_db_init, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* releas savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - archive_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - archive_db_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter interface */ - NULL, /* fill_files_table */ - HTON_NO_FLAGS, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ - -}; +handlerton archive_hton; static handler *archive_create_handler(TABLE_SHARE *table) { @@ -217,11 +175,18 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length, TRUE Error */ -bool archive_db_init() +int archive_db_init() { DBUG_ENTER("archive_db_init"); if (archive_inited) DBUG_RETURN(FALSE); + + archive_hton.state=SHOW_OPTION_YES; + archive_hton.db_type=DB_TYPE_ARCHIVE_DB; + archive_hton.create=archive_create_handler; + archive_hton.panic=archive_db_end; + archive_hton.flags=HTON_NO_FLAGS; + if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST)) goto error; if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0, @@ -701,14 +666,6 @@ int ha_archive::create(const char *name, TABLE *table_arg, create_info->auto_increment_value -1 : (ulonglong) 0); - if ((create_file= my_create(fn_format(name_buff,name,"",ARM, - MY_REPLACE_EXT|MY_UNPACK_FILENAME),0, - O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) - { - error= my_errno; - goto error; - } - for (uint key= 0; key < table_arg->s->keys; key++) { KEY *pos= table_arg->key_info+key; @@ -722,11 +679,20 @@ int ha_archive::create(const char *name, TABLE *table_arg, if (!(field->flags & AUTO_INCREMENT_FLAG)) { error= -1; + DBUG_PRINT("info", ("Index error in creating archive table")); goto error; } } } + if ((create_file= my_create(fn_format(name_buff,name,"",ARM, + MY_REPLACE_EXT|MY_UNPACK_FILENAME),0, + O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) + { + error= my_errno; + goto error; + } + write_meta_file(create_file, 0, auto_increment_value, 0, (char *)create_info->data_file_name, FALSE); @@ -1355,25 +1321,18 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) we don't check rc here because we want to open the file back up even if the optimize failed but we will return rc below so that we will know it failed. + We also need to reopen our read descriptor since it has changed. */ DBUG_PRINT("info", ("Reopening archive data file")); - if (!(azopen(&(share->archive_write), share->data_file_name, - O_WRONLY|O_APPEND|O_BINARY))) + if (!azopen(&(share->archive_write), share->data_file_name, + O_WRONLY|O_APPEND|O_BINARY) || + !azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY)) { DBUG_PRINT("info", ("Could not open archive write file")); rc= HA_ERR_CRASHED_ON_USAGE; - goto error; - } - - /* - Now we need to reopen our read descriptor since it has changed. - */ - if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY))) - { - rc= HA_ERR_CRASHED_ON_USAGE; - goto error; } + DBUG_RETURN(rc); error: azclose(&writer); @@ -1582,16 +1541,19 @@ bool ha_archive::check_and_repair(THD *thd) DBUG_RETURN(repair(thd, &check_opt)); } +struct st_mysql_storage_engine archive_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &archive_hton }; mysql_declare_plugin(archive) { MYSQL_STORAGE_ENGINE_PLUGIN, - &archive_hton, - archive_hton_name, + &archive_storage_engine, + "ARCHIVE", "Brian Aker, MySQL AB", - archive_hton_comment, - NULL, /* Plugin Init */ + "Archive storage engine", + archive_db_init, /* Plugin Init */ archive_db_done, /* Plugin Deinit */ 0x0100 /* 1.0 */, } mysql_declare_plugin_end; + diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h index 4663531b674..4c53c5c4064 100644 --- a/storage/archive/ha_archive.h +++ b/storage/archive/ha_archive.h @@ -136,6 +136,6 @@ public: bool check_and_repair(THD *thd); }; -bool archive_db_init(void); +int archive_db_init(void); int archive_db_end(ha_panic_function type); diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc index 098e44f39ee..3ee784c201f 100644 --- a/storage/blackhole/ha_blackhole.cc +++ b/storage/blackhole/ha_blackhole.cc @@ -22,57 +22,9 @@ #include "mysql_priv.h" #include "ha_blackhole.h" -#include - /* Static declarations for handlerton */ -static handler *blackhole_create_handler(TABLE_SHARE *table); - - -static const char blackhole_hton_name[]= "BLACKHOLE"; -static const char blackhole_hton_comment[]= - "/dev/null storage engine (anything you write to it disappears)"; - -/* Blackhole storage engine handlerton */ - -handlerton blackhole_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - blackhole_hton_name, - SHOW_OPTION_YES, - blackhole_hton_comment, - DB_TYPE_BLACKHOLE_DB, - NULL, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - blackhole_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - NULL, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES table */ - HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE, - NULL, /* binlog_func */ - NULL, /* binlog_log_query */ - NULL /* release_temporary_latches */ -}; - +handlerton blackhole_hton; static handler *blackhole_create_handler(TABLE_SHARE *table) { @@ -256,14 +208,26 @@ int ha_blackhole::index_last(byte * buf) DBUG_RETURN(HA_ERR_END_OF_FILE); } +static int blackhole_init() +{ + blackhole_hton.state= SHOW_OPTION_YES; + blackhole_hton.db_type= DB_TYPE_BLACKHOLE_DB; + blackhole_hton.create= blackhole_create_handler; + blackhole_hton.flags= HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE; + return 0; +} + +struct st_mysql_storage_engine blackhole_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &blackhole_hton }; + mysql_declare_plugin(blackhole) { MYSQL_STORAGE_ENGINE_PLUGIN, - &blackhole_hton, - blackhole_hton_name, + &blackhole_storage_engine, + "BLACKHOLE", "MySQL AB", - blackhole_hton_comment, - NULL, /* Plugin Init */ + "/dev/null storage engine (anything you write to it disappears)", + blackhole_init, /* Plugin Init */ NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, } diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index f15ce7cccb5..7d34571fb1d 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -77,45 +77,7 @@ static int tina_init= 0; static handler *tina_create_handler(TABLE_SHARE *table); static int tina_init_func(); -static const char tina_hton_name[]= "CSV"; -static const char tina_hton_comment[]= "CSV storage engine"; - -handlerton tina_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - tina_hton_name, - SHOW_OPTION_YES, - tina_hton_comment, - DB_TYPE_CSV_DB, - (bool (*)()) tina_init_func, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - tina_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - tina_end, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter Tablespace */ - NULL, /* Fill FILES Table */ - HTON_CAN_RECREATE, - NULL, /* binlog_func */ - NULL /* binlog_log_query */ -}; +handlerton tina_hton; /***************************************************************************** ** TINA tables @@ -197,6 +159,11 @@ static int tina_init_func() VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST)); (void) hash_init(&tina_open_tables,system_charset_info,32,0,0, (hash_get_key) tina_get_key,0,0); + tina_hton.state= SHOW_OPTION_YES; + tina_hton.db_type= DB_TYPE_CSV_DB; + tina_hton.create= tina_create_handler; + tina_hton.panic= tina_end; + tina_hton.flags= HTON_CAN_RECREATE; } return 0; } @@ -1422,14 +1389,16 @@ bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } +struct st_mysql_storage_engine csv_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &tina_hton }; mysql_declare_plugin(csv) { MYSQL_STORAGE_ENGINE_PLUGIN, - &tina_hton, - tina_hton_name, + &csv_storage_engine, + "CSV", "Brian Aker, MySQL AB", - tina_hton_comment, + "CSV storage engine", tina_init_func, /* Plugin Init */ tina_done_func, /* Plugin Deinit */ 0x0100 /* 1.0 */, diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index 2ce543dfbb0..28bccc7df2d 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -77,46 +77,7 @@ static int example_init_func(); static bool example_init_func_for_handlerton(); static int example_panic(enum ha_panic_function flag); -static const char example_hton_name[]= "EXAMPLE"; -static const char example_hton_comment[]= "Example storage engine"; - -handlerton example_hton= { - MYSQL_HANDLERTON_INTERFACE_VERSION, - example_hton_name, - SHOW_OPTION_YES, - example_hton_comment, - DB_TYPE_EXAMPLE_DB, - example_init_func_for_handlerton, - 0, /* slot */ - 0, /* savepoint size. */ - NULL, /* close_connection */ - NULL, /* savepoint */ - NULL, /* rollback to savepoint */ - NULL, /* release savepoint */ - NULL, /* commit */ - NULL, /* rollback */ - NULL, /* prepare */ - NULL, /* recover */ - NULL, /* commit_by_xid */ - NULL, /* rollback_by_xid */ - NULL, /* create_cursor_read_view */ - NULL, /* set_cursor_read_view */ - NULL, /* close_cursor_read_view */ - example_create_handler, /* Create a new handler */ - NULL, /* Drop a database */ - example_panic, /* Panic call */ - NULL, /* Start Consistent Snapshot */ - NULL, /* Flush logs */ - NULL, /* Show status */ - NULL, /* Partition flags */ - NULL, /* Alter table flags */ - NULL, /* Alter tablespace */ - NULL, /* Fill Files table */ - HTON_CAN_RECREATE, - NULL, - NULL, - NULL, -}; +handlerton example_hton; /* Variables for example share methods */ static HASH example_open_tables; // Hash used to track open tables @@ -143,6 +104,11 @@ static int example_init_func() VOID(pthread_mutex_init(&example_mutex,MY_MUTEX_INIT_FAST)); (void) hash_init(&example_open_tables,system_charset_info,32,0,0, (hash_get_key) example_get_key,0,0); + + example_hton.state= SHOW_OPTION_YES; + example_hton.db_type= DB_TYPE_EXAMPLE_DB; + example_hton.create= example_create_handler; + example_hton.flags= HTON_CAN_RECREATE; } DBUG_RETURN(0); } @@ -163,17 +129,6 @@ static int example_done_func() DBUG_RETURN(0); } -static bool example_init_func_for_handlerton() -{ - return example_init_func(); -} - -static int example_panic(enum ha_panic_function flag) -{ - return example_done_func(); -} - - /* Example of simple lock controls. The "share" it creates is structure we will pass to each example handler. Do you have to have one of these? Well, you have @@ -741,18 +696,21 @@ int ha_example::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info) { DBUG_ENTER("ha_example::create"); - /* This is not implemented but we want someone to be able that it works. */ + /* This is not implemented but we want someone to be able to see that it works. */ DBUG_RETURN(0); } +struct st_mysql_storage_engine example_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION, &example_hton }; + mysql_declare_plugin(example) { MYSQL_STORAGE_ENGINE_PLUGIN, - &example_hton, - example_hton_name, + &example_storage_engine, + "EXAMPLE", "Brian Aker, MySQL AB", - example_hton_comment, + "Example storage engine", example_init_func, /* Plugin Init */ example_done_func, /* Plugin Deinit */ 0x0001 /* 0.1 */, diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 8d48f533203..33c4dc705b4 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -160,7 +160,6 @@ static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b) typedef struct st_my_ftb_param { - MYSQL_FTPARSER_PARAM *up; FTB *ftb; FTB_EXPR *ftbe; byte *up_quot; @@ -168,10 +167,11 @@ typedef struct st_my_ftb_param } MY_FTB_PARAM; -static int ftb_query_add_word(void *param, char *word, int word_len, +static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *info) { - MY_FTB_PARAM *ftb_param= (MY_FTB_PARAM *)param; + MY_FTB_PARAM *ftb_param= param->mysql_ftparam; FTB_WORD *ftbw; FTB_EXPR *ftbe, *tmp_expr; FT_WORD *phrase_word; @@ -269,9 +269,10 @@ static int ftb_query_add_word(void *param, char *word, int word_len, } -static int ftb_parse_query_internal(void *param, char *query, int len) +static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param, + char *query, int len) { - MY_FTB_PARAM *ftb_param= (MY_FTB_PARAM *)param; + MY_FTB_PARAM *ftb_param= param->mysql_ftparam; MYSQL_FTPARSER_BOOLEAN_INFO info; CHARSET_INFO *cs= ftb_param->ftb->charset; char **start= &query; @@ -281,7 +282,7 @@ static int ftb_parse_query_internal(void *param, char *query, int len) info.prev= ' '; info.quot= 0; while (ft_get_word(cs, start, end, &w, &info)) - ftb_param->up->mysql_add_word(param, w.pos, w.len, &info); + param->mysql_add_word(param, w.pos, w.len, &info); return(0); } @@ -299,7 +300,6 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len, if (! (param= ftparser_call_initializer(ftb->info, ftb->keynr, 0))) DBUG_VOID_RETURN; - ftb_param.up= param; ftb_param.ftb= ftb; ftb_param.depth= 0; ftb_param.ftbe= ftb->root; @@ -311,6 +311,7 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len, param->cs= ftb->charset; param->doc= query; param->length= len; + param->flags= 0; param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO; parser->parse(param); DBUG_VOID_RETURN; @@ -571,7 +572,6 @@ err: typedef struct st_my_ftb_phrase_param { - MYSQL_FTPARSER_PARAM *up; LIST *phrase; LIST *document; CHARSET_INFO *cs; @@ -581,10 +581,11 @@ typedef struct st_my_ftb_phrase_param } MY_FTB_PHRASE_PARAM; -static int ftb_phrase_add_word(void *param, char *word, int word_len, +static int ftb_phrase_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) { - MY_FTB_PHRASE_PARAM *phrase_param= (MY_FTB_PHRASE_PARAM *)param; + MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam; FT_WORD *w= (FT_WORD *)phrase_param->document->data; LIST *phrase, *document; w->pos= word; @@ -611,14 +612,15 @@ static int ftb_phrase_add_word(void *param, char *word, int word_len, } -static int ftb_check_phrase_internal(void *param, char *document, int len) +static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param, + char *document, int len) { FT_WORD word; - MY_FTB_PHRASE_PARAM *phrase_param= (MY_FTB_PHRASE_PARAM *)param; + MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam; const char *docend= document + len; while (ft_simple_get_word(phrase_param->cs, &document, docend, &word, FALSE)) { - phrase_param->up->mysql_add_word(param, word.pos, word.len, 0); + param->mysql_add_word(param, word.pos, word.len, 0); if (phrase_param->match) return 1; } @@ -651,7 +653,6 @@ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len, if (! (param= ftparser_call_initializer(ftb->info, ftb->keynr, 1))) DBUG_RETURN(0); - ftb_param.up= param; ftb_param.phrase= ftbe->phrase; ftb_param.document= ftbe->document; ftb_param.cs= ftb->charset; @@ -665,6 +666,7 @@ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len, param->cs= ftb->charset; param->doc= (byte *)document; param->length= len; + param->flags= 0; param->mode= MYSQL_FTPARSER_WITH_STOPWORDS; parser->parse(param); DBUG_RETURN(ftb_param.match ? 1 : 0); @@ -820,16 +822,16 @@ err: typedef struct st_my_ftb_find_param { - MYSQL_FTPARSER_PARAM *up; FT_INFO *ftb; FT_SEG_ITERATOR *ftsi; } MY_FTB_FIND_PARAM; -static int ftb_find_relevance_add_word(void *param, char *word, int len, +static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) { - MY_FTB_FIND_PARAM *ftb_param= (MY_FTB_FIND_PARAM *)param; + MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam; FT_INFO *ftb= ftb_param->ftb; FTB_WORD *ftbw; int a, b, c; @@ -859,14 +861,15 @@ static int ftb_find_relevance_add_word(void *param, char *word, int len, } -static int ftb_find_relevance_parse(void *param, char *doc, int len) +static int ftb_find_relevance_parse(MYSQL_FTPARSER_PARAM *param, + char *doc, int len) { - MY_FTB_FIND_PARAM *ftb_param=(MY_FTB_FIND_PARAM *)param; + MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam; FT_INFO *ftb= ftb_param->ftb; char *end= doc + len; FT_WORD w; while (ft_simple_get_word(ftb->charset, &doc, end, &w, TRUE)) - ftb_param->up->mysql_add_word(param, w.pos, w.len, 0); + param->mysql_add_word(param, w.pos, w.len, 0); return(0); } @@ -910,12 +913,12 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) _mi_ft_segiterator_init(ftb->info, ftb->keynr, record, &ftsi); memcpy(&ftsi2, &ftsi, sizeof(ftsi)); - ftb_param.up= param; ftb_param.ftb= ftb; ftb_param.ftsi= &ftsi2; param->mysql_parse= ftb_find_relevance_parse; param->mysql_add_word= ftb_find_relevance_add_word; param->mysql_ftparam= (void *)&ftb_param; + param->flags= 0; param->cs= ftb->charset; param->mode= MYSQL_FTPARSER_SIMPLE_MODE; while (_mi_ft_segiterator(&ftsi)) diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index b8207c1c3d0..53a01003dcd 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -235,7 +235,9 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query, NULL, NULL); ft_parse_init(&wtree, aio.charset); - if (ft_parse(&wtree, query, query_len, 0, parser, ftparser_param)) + ftparser_param->flags= 0; + if (ft_parse(&wtree, query, query_len, parser, ftparser_param, + &wtree.mem_root)) goto err; if (tree_walk(&wtree, (tree_walk_action)&walk_and_match, &aio, @@ -255,7 +257,9 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query, if (!(*info->read_record)(info,docid,record)) { info->update|= HA_STATE_AKTIV; - _mi_ft_parse(&wtree, info, keynr, record, 1, ftparser_param); + ftparser_param->flags= MYSQL_FTFLAGS_NEED_COPY; + _mi_ft_parse(&wtree, info, keynr, record, ftparser_param, + &wtree.mem_root); } } delete_queue(&best); diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index 89ede813a2b..38ac744d4a8 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -24,15 +24,12 @@ typedef struct st_ft_docstat { double sum; } FT_DOCSTAT; - typedef struct st_my_ft_parser_param { - MYSQL_FTPARSER_PARAM *up; - TREE *wtree; - my_bool with_alloc; + TREE *wtree; + MEM_ROOT *mem_root; } MY_FT_PARSER_PARAM; - static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2) { return mi_compare_text(cs, (uchar*) w1->pos, w1->len, @@ -49,14 +46,14 @@ static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat) /* transforms tree of words into the array, applying normalization */ -FT_WORD * ft_linearize(TREE *wtree) +FT_WORD * ft_linearize(TREE *wtree, MEM_ROOT *mem_root) { FT_WORD *wlist,*p; FT_DOCSTAT docstat; DBUG_ENTER("ft_linearize"); - if ((wlist=(FT_WORD *) my_malloc(sizeof(FT_WORD)* - (1+wtree->elements_in_tree),MYF(0)))) + if ((wlist=(FT_WORD *) alloc_root(mem_root, sizeof(FT_WORD)* + (1+wtree->elements_in_tree)))) { docstat.list=wlist; docstat.uniq=wtree->elements_in_tree; @@ -241,19 +238,20 @@ void ft_parse_init(TREE *wtree, CHARSET_INFO *cs) } -static int ft_add_word(void *param, byte *word, uint word_len, +static int ft_add_word(MYSQL_FTPARSER_PARAM *param, + char *word, int word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) { TREE *wtree; FT_WORD w; + MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam; DBUG_ENTER("ft_add_word"); - wtree= ((MY_FT_PARSER_PARAM *)param)->wtree; - if (((MY_FT_PARSER_PARAM *)param)->with_alloc) + wtree= ft_param->wtree; + if (param->flags & MYSQL_FTFLAGS_NEED_COPY) { byte *ptr; - /* allocating the data in the tree - to avoid mallocs and frees */ DBUG_ASSERT(wtree->with_delete == 0); - ptr= (byte *)alloc_root(&wtree->mem_root, word_len); + ptr= (byte *)alloc_root(ft_param->mem_root, word_len); memcpy(ptr, word, word_len); w.pos= ptr; } @@ -269,32 +267,32 @@ static int ft_add_word(void *param, byte *word, uint word_len, } -static int ft_parse_internal(void *param, byte *doc, int doc_len) +static int ft_parse_internal(MYSQL_FTPARSER_PARAM *param, + byte *doc, int doc_len) { byte *end=doc+doc_len; - MY_FT_PARSER_PARAM *ft_param=(MY_FT_PARSER_PARAM *)param; + MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam; TREE *wtree= ft_param->wtree; FT_WORD w; DBUG_ENTER("ft_parse_internal"); while (ft_simple_get_word(wtree->custom_arg, &doc, end, &w, TRUE)) - if (ft_param->up->mysql_add_word(param, w.pos, w.len, 0)) + if (param->mysql_add_word(param, w.pos, w.len, 0)) DBUG_RETURN(1); DBUG_RETURN(0); } -int ft_parse(TREE *wtree, byte *doc, int doclen, my_bool with_alloc, +int ft_parse(TREE *wtree, byte *doc, int doclen, struct st_mysql_ftparser *parser, - MYSQL_FTPARSER_PARAM *param) + MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root) { MY_FT_PARSER_PARAM my_param; DBUG_ENTER("ft_parse"); DBUG_ASSERT(parser); - my_param.up= param; my_param.wtree= wtree; - my_param.with_alloc= with_alloc; + my_param.mem_root= mem_root; param->mysql_parse= ft_parse_internal; param->mysql_add_word= ft_add_word; @@ -356,6 +354,7 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, info->ftparser_param= (MYSQL_FTPARSER_PARAM *) my_malloc(MAX_PARAM_NR * sizeof(MYSQL_FTPARSER_PARAM) * info->s->ftparsers, MYF(MY_WME|MY_ZEROFILL)); + init_alloc_root(&info->ft_memroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); if (! info->ftparser_param) return 0; } @@ -387,6 +386,7 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, void ftparser_call_deinitializer(MI_INFO *info) { uint i, j, keys= info->s->state.header.keys; + free_root(&info->ft_memroot, MYF(0)); if (! info->ftparser_param) return; for (i= 0; i < keys; i++) diff --git a/storage/myisam/ft_static.c b/storage/myisam/ft_static.c index 6cfb0d59e62..61bb7b3c1f7 100644 --- a/storage/myisam/ft_static.c +++ b/storage/myisam/ft_static.c @@ -629,7 +629,7 @@ const char *ft_precompiled_stopwords[] = { static int ft_default_parser_parse(MYSQL_FTPARSER_PARAM *param) { - return param->mysql_parse(param->mysql_ftparam, param->doc, param->length); + return param->mysql_parse(param, param->doc, param->length); } struct st_mysql_ftparser ft_default_parser= diff --git a/storage/myisam/ft_update.c b/storage/myisam/ft_update.c index f5501792dcd..08d605dbcc2 100644 --- a/storage/myisam/ft_update.c +++ b/storage/myisam/ft_update.c @@ -77,7 +77,7 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) { uint pack_length= (ftsi->seg->bit_start); ftsi->len= (pack_length == 1 ? (uint) *(uchar*) ftsi->pos : - uint2korr(ftsi->pos)); + uint2korr(ftsi->pos)); ftsi->pos+= pack_length; /* Skip VARCHAR length */ DBUG_RETURN(1); } @@ -95,9 +95,8 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi) /* parses a document i.e. calls ft_parse for every keyseg */ -uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, - const byte *record, my_bool with_alloc, - MYSQL_FTPARSER_PARAM *param) +uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, const byte *record, + MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root) { FT_SEG_ITERATOR ftsi; struct st_mysql_ftparser *parser; @@ -110,14 +109,14 @@ uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, while (_mi_ft_segiterator(&ftsi)) { if (ftsi.pos) - if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len, with_alloc, parser, - param)) + if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len, parser, param, mem_root)) DBUG_RETURN(1); } DBUG_RETURN(0); } -FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record) +FT_WORD *_mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record, + MEM_ROOT *mem_root) { TREE ptree; MYSQL_FTPARSER_PARAM *param; @@ -125,10 +124,11 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record) if (! (param= ftparser_call_initializer(info, keynr, 0))) DBUG_RETURN(NULL); bzero((char*) &ptree, sizeof(ptree)); - if (_mi_ft_parse(&ptree, info, keynr, record, 0, param)) + param->flags= 0; + if (_mi_ft_parse(&ptree, info, keynr, record, param, mem_root)) DBUG_RETURN(NULL); - DBUG_RETURN(ft_linearize(&ptree)); + DBUG_RETURN(ft_linearize(&ptree, mem_root)); } static int _mi_ft_store(MI_INFO *info, uint keynr, byte *keybuf, @@ -206,10 +206,11 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf, int cmp, cmp2; DBUG_ENTER("_mi_ft_update"); - if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, oldrec))) - goto err0; - if (!(new_word=newlist=_mi_ft_parserecord(info, keynr, newrec))) - goto err1; + if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, oldrec, + &info->ft_memroot)) || + !(new_word=newlist=_mi_ft_parserecord(info, keynr, newrec, + &info->ft_memroot))) + goto err; error=0; while(old_word->pos && new_word->pos) @@ -222,13 +223,13 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf, { key_length=_ft_make_key(info,keynr,keybuf,old_word,pos); if ((error=_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length))) - goto err2; + goto err; } if (cmp > 0 || cmp2) { key_length=_ft_make_key(info,keynr,keybuf,new_word,pos); if ((error=_mi_ck_write(info,keynr,(uchar*) keybuf,key_length))) - goto err2; + goto err; } if (cmp<=0) old_word++; if (cmp>=0) new_word++; @@ -238,11 +239,8 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf, else if (new_word->pos) error=_mi_ft_store(info,keynr,keybuf,new_word,pos); -err2: - my_free((char*) newlist,MYF(0)); -err1: - my_free((char*) oldlist,MYF(0)); -err0: +err: + free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE)); DBUG_RETURN(error); } @@ -255,12 +253,13 @@ int _mi_ft_add(MI_INFO *info, uint keynr, byte *keybuf, const byte *record, int error= -1; FT_WORD *wlist; DBUG_ENTER("_mi_ft_add"); + DBUG_PRINT("enter",("keynr: %d",keynr)); - if ((wlist=_mi_ft_parserecord(info, keynr, record))) - { + if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot))) error=_mi_ft_store(info,keynr,keybuf,wlist,pos); - my_free((char*) wlist,MYF(0)); - } + + free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE)); + DBUG_PRINT("exit",("Return: %d",error)); DBUG_RETURN(error); } @@ -275,11 +274,10 @@ int _mi_ft_del(MI_INFO *info, uint keynr, byte *keybuf, const byte *record, DBUG_ENTER("_mi_ft_del"); DBUG_PRINT("enter",("keynr: %d",keynr)); - if ((wlist=_mi_ft_parserecord(info, keynr, record))) - { + if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot))) error=_mi_ft_erase(info,keynr,keybuf,wlist,pos); - my_free((char*) wlist,MYF(0)); - } + + free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE)); DBUG_PRINT("exit",("Return: %d",error)); DBUG_RETURN(error); } diff --git a/storage/myisam/ftdefs.h b/storage/myisam/ftdefs.h index 2c4cfa1ffd6..108faf4f1a3 100644 --- a/storage/myisam/ftdefs.h +++ b/storage/myisam/ftdefs.h @@ -30,6 +30,8 @@ #define FT_MAX_WORD_LEN_FOR_SORT 31 +#define FTPARSER_MEMROOT_ALLOC_SIZE 65536 + #define COMPILE_STOPWORDS_IN /* Interested readers may consult SMART @@ -119,12 +121,12 @@ void _mi_ft_segiterator_dummy_init(const byte *, uint, FT_SEG_ITERATOR *); uint _mi_ft_segiterator(FT_SEG_ITERATOR *); void ft_parse_init(TREE *, CHARSET_INFO *); -int ft_parse(TREE *, byte *, int, my_bool, struct st_mysql_ftparser *parser, - MYSQL_FTPARSER_PARAM *param); -FT_WORD * ft_linearize(TREE *); -FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *); -uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *, my_bool, - MYSQL_FTPARSER_PARAM *param); +int ft_parse(TREE *, byte *, int, struct st_mysql_ftparser *parser, + MYSQL_FTPARSER_PARAM *, MEM_ROOT *); +FT_WORD * ft_linearize(TREE *, MEM_ROOT *); +FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *, MEM_ROOT *); +uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *, + MYSQL_FTPARSER_PARAM *, MEM_ROOT *); FT_INFO *ft_init_nlq_search(MI_INFO *, uint, byte *, uint, uint, byte *); FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint, CHARSET_INFO *); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 0fa095a21db..ef7b1e6fde3 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2117,6 +2117,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); sort_param.wordlist=NULL; + init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); if (share->data_file_type == DYNAMIC_RECORD) length=max(share->base.min_pack_length+1,share->base.min_block_length); @@ -2179,12 +2180,36 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, { uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT* sort_param.keyinfo->seg->charset->mbmaxlen; - sort_info.max_records= - (ha_rows) (sort_info.filelength/ft_min_word_len+1); + sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; + /* + fulltext indexes may have much more entries than the + number of rows in the table. We estimate the number here. + + Note, built-in parser is always nr. 0 - see ftparser_call_initializer() + */ + if (sort_param.keyinfo->ftparser_nr == 0) + { + /* + for built-in parser the number of generated index entries + cannot be larger than the size of the data file divided + by the minimal word's length + */ + sort_info.max_records= + (ha_rows) (sort_info.filelength/ft_min_word_len+1); + } + else + { + /* + for external plugin parser we cannot tell anything at all :( + so, we'll use all the sort memory and start from ~10 buffpeks. + (see _create_index_by_sort) + */ + sort_info.max_records= + 10*param->sort_buffer_length/sort_param.key_length; + } sort_param.key_read=sort_ft_key_read; sort_param.key_write=sort_ft_key_write; - sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; } else { @@ -2200,6 +2225,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, goto err; } param->calc_checksum=0; /* No need to calc glob_crc */ + free_root(&sort_param.wordroot, MYF(0)); /* Set for next loop */ sort_info.max_records= (ha_rows) info->state->records; @@ -2589,6 +2615,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT* sort_param[i].keyinfo->seg->charset->mbmaxlen; sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; + init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); } } sort_info.total_keys=i; @@ -2810,10 +2837,11 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key) { for (;;) { - my_free((char*) wptr, MYF(MY_ALLOW_ZERO_PTR)); + free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE)); if ((error=sort_get_next_record(sort_param))) DBUG_RETURN(error); - if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record))) + if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record, + &sort_param->wordroot))) DBUG_RETURN(1); if (wptr->pos) break; @@ -2837,7 +2865,7 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key) #endif if (!wptr->pos) { - my_free((char*) sort_param->wordlist, MYF(0)); + free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE)); sort_param->wordlist=0; error=sort_write_record(sort_param); } diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 0b450de9c03..a83fbe8f759 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -235,13 +235,14 @@ struct st_myisam_info { /* accumulate indexfile changes between write's */ TREE *bulk_insert; DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */ - MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ - char *filename; /* parameter to open filename */ - uchar *buff, /* Temp area for key */ - *lastkey,*lastkey2; /* Last used search key */ - uchar *first_mbr_key; /* Searhed spatial key */ - byte *rec_buff; /* Tempbuff for recordpack */ - uchar *int_keypos, /* Save position for next/previous */ + MEM_ROOT ft_memroot; /* used by the parser */ + MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ + char *filename; /* parameter to open filename */ + uchar *buff, /* Temp area for key */ + *lastkey,*lastkey2; /* Last used search key */ + uchar *first_mbr_key; /* Searhed spatial key */ + byte *rec_buff; /* Tempbuff for recordpack */ + uchar *int_keypos, /* Save position for next/previous */ *int_maxpos; /* -""- */ uint int_nod_flag; /* -""- */ uint32 int_keytree_version; /* -""- */ @@ -325,6 +326,7 @@ typedef struct st_mi_sort_param uchar **sort_keys; byte *rec_buff; void *wordlist, *wordptr; + MEM_ROOT wordroot; char *record; MY_TMPDIR *tmpdir; int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *); diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index c9562461f56..44e7e8b464e 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -447,6 +447,7 @@ err: close_cached_file(&info->tempfile_for_exceptions); ok: + free_root(&info->wordroot, MYF(0)); remove_io_thread(&info->read_cache); pthread_mutex_lock(&info->sort_info->mutex); info->sort_info->threads_running--; diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp index 42043fbb93a..c5f699dfd7d 100644 --- a/storage/ndb/include/ndbapi/Ndb.hpp +++ b/storage/ndb/include/ndbapi/Ndb.hpp @@ -1002,6 +1002,9 @@ typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*); #define WAITFOR_RESPONSE_TIMEOUT 120000 // Milliseconds #endif +#define NDB_SYSTEM_DATABASE "sys" +#define NDB_SYSTEM_SCHEMA "def" + /** * @class Ndb * @brief Represents the NDB kernel and is the main class of the NDB API. @@ -1672,6 +1675,8 @@ private: const char * externalizeIndexName(const char * internalIndexName, bool fullyQualifiedNames); const char * externalizeIndexName(const char * internalIndexName); + const BaseString old_internalize_index_name(const NdbTableImpl * table, + const char * external_name) const; const BaseString internalize_index_name(const NdbTableImpl * table, const char * external_name) const; diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp index 865fb506f05..27e0aede36d 100644 --- a/storage/ndb/include/ndbapi/NdbDictionary.hpp +++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp @@ -1635,6 +1635,16 @@ public: int listIndexes(List & list, const char * tableName); int listIndexes(List & list, const char * tableName) const; +#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL + /** + * Fetch list of indexes of given table. + * @param list Reference to list where to store the listed indexes + * @param table Reference to table that index belongs to. + * @return 0 if successful, otherwise -1 + */ + int listIndexes(List & list, const Table &table) const; +#endif + /** @} *******************************************************************/ /** * @name Events diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt index 059c80a960d..d69faa90f72 100644 --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt @@ -63,6 +63,9 @@ Delay GCP_SAVEREQ by 10 secs 7165: Delay INCL_NODE_REQ in starting node yeilding error in GCP_PREPARE +7030: Delay in GCP_PREPARE until node has completed a node failure +7031: Delay in GCP_PREPARE and die 3s later + ERROR CODES FOR TESTING NODE FAILURE, LOCAL CHECKPOINT HANDLING: ----------------------------------------------------------------- diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 9936217bbf3..bb4c2ed197e 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -5601,6 +5601,12 @@ Dbdih::checkLocalNodefailComplete(Signal* signal, Uint32 failedNodeId, return; } + if (ERROR_INSERTED(7030)) + { + ndbout_c("Reenable GCP_PREPARE"); + CLEAR_ERROR_INSERT_VALUE; + } + NFCompleteRep * const nf = (NFCompleteRep *)&signal->theData[0]; nf->blockNo = DBDIH; nf->nodeId = cownNodeId; @@ -7733,6 +7739,16 @@ void Dbdih::execGCP_PREPARE(Signal* signal) { jamEntry(); CRASH_INSERTION(7005); + + if (ERROR_INSERTED(7030)) + { + cgckptflag = true; + ndbout_c("Delayed GCP_PREPARE 5s"); + sendSignalWithDelay(reference(), GSN_GCP_PREPARE, signal, 5000, + signal->getLength()); + return; + } + Uint32 masterNodeId = signal->theData[0]; Uint32 gci = signal->theData[1]; BlockReference retRef = calcDihBlockRef(masterNodeId); @@ -7745,6 +7761,14 @@ void Dbdih::execGCP_PREPARE(Signal* signal) cgcpParticipantState = GCP_PARTICIPANT_PREPARE_RECEIVED; cnewgcp = gci; + if (ERROR_INSERTED(7031)) + { + ndbout_c("Crashing delayed in GCP_PREPARE 3s"); + signal->theData[0] = 9999; + sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 3000, 1); + return; + } + signal->theData[0] = cownNodeId; signal->theData[1] = gci; sendSignal(retRef, GSN_GCP_PREPARECONF, signal, 2, JBA); diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 0989807db4a..869ae116f43 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -7076,18 +7076,20 @@ Dbtc::nodeFailCheckTransactions(Signal* signal, { jam(); Ptr transPtr; + Uint32 TtcTimer = ctcTimer; + Uint32 TapplTimeout = c_appl_timeout_value; for (transPtr.i = transPtrI; transPtr.i < capiConnectFilesize; transPtr.i++) { ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord); if (transPtr.p->m_transaction_nodes.get(failedNodeId)) { jam(); + // Force timeout regardless of state - Uint32 save = c_appl_timeout_value; c_appl_timeout_value = 1; - setApiConTimer(transPtr.i, 0, __LINE__); + setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__); timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT); - c_appl_timeout_value = save; + c_appl_timeout_value = TapplTimeout; } // Send CONTINUEB to continue later diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index 60fdef8111e..5b0a9e9d330 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -1311,6 +1311,35 @@ Ndb::internalize_table_name(const char *external_name) const DBUG_RETURN(ret); } +const BaseString +Ndb::old_internalize_index_name(const NdbTableImpl * table, + const char * external_name) const +{ + BaseString ret; + DBUG_ENTER("old_internalize_index_name"); + DBUG_PRINT("enter", ("external_name: %s, table_id: %d", + external_name, table ? table->m_id : ~0)); + if (!table) + { + DBUG_PRINT("error", ("!table")); + DBUG_RETURN(ret); + } + + if (fullyQualifiedNames) + { + /* Internal index name format /// */ + ret.assfmt("%s%d%c%s", + theImpl->m_prefix.c_str(), + table->m_id, + table_name_separator, + external_name); + } + else + ret.assign(external_name); + + DBUG_PRINT("exit", ("internal_name: %s", ret.c_str())); + DBUG_RETURN(ret); +} const BaseString Ndb::internalize_index_name(const NdbTableImpl * table, @@ -1328,9 +1357,9 @@ Ndb::internalize_index_name(const NdbTableImpl * table, if (fullyQualifiedNames) { - /* Internal index name format ///
*/ + /* Internal index name format sys/def//
*/ ret.assfmt("%s%d%c%s", - theImpl->m_prefix.c_str(), + theImpl->m_systemPrefix.c_str(), table->m_id, table_name_separator, external_name); diff --git a/storage/ndb/src/ndbapi/NdbDictionary.cpp b/storage/ndb/src/ndbapi/NdbDictionary.cpp index e844dc3369e..c71689d2e81 100644 --- a/storage/ndb/src/ndbapi/NdbDictionary.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp @@ -1618,6 +1618,14 @@ NdbDictionary::Dictionary::listIndexes(List& list, return m_impl.listIndexes(list, tab->getTableId()); } +int +NdbDictionary::Dictionary::listIndexes(List& list, + const NdbDictionary::Table &table) const +{ + return m_impl.listIndexes(list, table.getTableId()); +} + + const struct NdbError & NdbDictionary::Dictionary::getNdbError() const { return m_impl.getNdbError(); diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 42428c49e26..22a5d2f20a5 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -56,7 +56,6 @@ DBUG_RETURN(b);\ } -extern Uint64 g_latest_trans_gci; int ndb_dictionary_is_mysqld = 0; bool @@ -1509,9 +1508,21 @@ NdbTableImpl * NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index, NdbTableImpl * table) { + const char *current_db= m_ndb.getDatabaseName(); + NdbTableImpl *index_table; const BaseString internalName( m_ndb.internalize_index_name(table, index->getName())); - return getTable(m_ndb.externalizeTableName(internalName.c_str())); + // Get index table in system database + m_ndb.setDatabaseName(NDB_SYSTEM_DATABASE); + index_table= getTable(m_ndb.externalizeTableName(internalName.c_str())); + m_ndb.setDatabaseName(current_db); + if (!index_table) + { + // Index table not found + // Try geting index table in current database (old format) + index_table= getTable(m_ndb.externalizeTableName(internalName.c_str())); + } + return index_table; } #if 0 @@ -4223,7 +4234,6 @@ NdbDictInterface::execWAIT_GCP_CONF(NdbApiSignal* signal, { const WaitGCPConf * const conf= CAST_CONSTPTR(WaitGCPConf, signal->getDataPtr()); - g_latest_trans_gci= conf->gcp; m_waiter.signal(NO_WAIT); } diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 9b63acf6d36..b6961edd019 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -1020,6 +1020,33 @@ NdbDictionaryImpl::getIndexGlobal(const char * index_name, } break; } + { + // Index not found, try old format + const BaseString + old_internal_indexname(m_ndb.old_internalize_index_name(&ndbtab, + index_name)); + retry= 2; + while (retry) + { + NdbTableImpl *tab= + fetchGlobalTableImplRef(InitIndex(old_internal_indexname, + index_name, ndbtab)); + if (tab) + { + // tab->m_index sould be set. otherwise tab == 0 + NdbIndexImpl *idx= tab->m_index; + if (idx->m_table_id != (unsigned)ndbtab.getObjectId() || + idx->m_table_version != (unsigned)ndbtab.getObjectVersion()) + { + releaseIndexGlobal(*idx, 1); + retry--; + continue; + } + DBUG_RETURN(idx); + } + break; + } + } m_error.code= 4243; DBUG_RETURN(0); } @@ -1086,17 +1113,41 @@ NdbDictionaryImpl::getIndex(const char* index_name, index_name, prim)); if (!tab) - goto err; + goto retry; info= Ndb_local_table_info::create(tab, 0); if (!info) - goto err; + goto retry; m_localHash.put(internal_indexname.c_str(), info); } else tab= info->m_table_impl; return tab->m_index; + +retry: + // Index not found, try fetching it from current database + const BaseString + old_internal_indexname(m_ndb.old_internalize_index_name(&prim, index_name)); + + info= m_localHash.get(old_internal_indexname.c_str()); + if (info == 0) + { + tab= fetchGlobalTableImplRef(InitIndex(old_internal_indexname, + index_name, + prim)); + if (!tab) + goto err; + + info= Ndb_local_table_info::create(tab, 0); + if (!info) + goto err; + m_localHash.put(old_internal_indexname.c_str(), info); + } + else + tab= info->m_table_impl; + + return tab->m_index; err: m_error.code= 4243; diff --git a/storage/ndb/src/ndbapi/NdbImpl.hpp b/storage/ndb/src/ndbapi/NdbImpl.hpp index 82795550381..3b7b8cf44fb 100644 --- a/storage/ndb/src/ndbapi/NdbImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbImpl.hpp @@ -93,6 +93,8 @@ public: m_schemaname.c_str(), table_name_separator); } + BaseString m_systemPrefix; // Buffer for preformatted for // + /** * NOTE free lists must be _after_ theNdbObjectIdMap take * assure that destructors are run in correct order diff --git a/storage/ndb/src/ndbapi/NdbTransaction.cpp b/storage/ndb/src/ndbapi/NdbTransaction.cpp index 3158dca5c40..916135b12d5 100644 --- a/storage/ndb/src/ndbapi/NdbTransaction.cpp +++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp @@ -32,6 +32,8 @@ #include #include +Uint64 g_latest_trans_gci = 0; + /***************************************************************************** NdbTransaction( Ndb* aNdb ); @@ -1568,6 +1570,9 @@ NdbTransaction::receiveTC_COMMITCONF(const TcCommitConf * commitConf) theCommitStatus = Committed; theCompletionStatus = CompletedSuccess; theGlobalCheckpointId = commitConf->gci; + // theGlobalCheckpointId == 0 if NoOp transaction + if (theGlobalCheckpointId) + g_latest_trans_gci = theGlobalCheckpointId; return 0; } else { #ifdef NDB_NO_DROPPED_SIGNAL @@ -1746,6 +1751,8 @@ from other transactions. if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; + assert(tGCI); + g_latest_trans_gci = tGCI; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ @@ -1922,6 +1929,8 @@ NdbTransaction::receiveTCINDXCONF(const TcIndxConf * indxConf, if (tCommitFlag == 1) { theCommitStatus = Committed; theGlobalCheckpointId = tGCI; + assert(tGCI); + g_latest_trans_gci = tGCI; } else if ((tNoComp >= tNoSent) && (theLastExecOpInList->theCommitIndicator == 1)){ /**********************************************************************/ diff --git a/storage/ndb/src/ndbapi/Ndbif.cpp b/storage/ndb/src/ndbapi/Ndbif.cpp index 7799a71749e..ecaf6a3f435 100644 --- a/storage/ndb/src/ndbapi/Ndbif.cpp +++ b/storage/ndb/src/ndbapi/Ndbif.cpp @@ -46,7 +46,6 @@ #include extern EventLogger g_eventLogger; -Uint64 g_latest_trans_gci= 0; /****************************************************************************** * int init( int aNrOfCon, int aNrOfOp ); @@ -367,7 +366,6 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbTransaction::sendTC_OP)) { - g_latest_trans_gci= keyConf->gci; tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); @@ -520,7 +518,6 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) { - g_latest_trans_gci= commitConf->gci; tReturnCode = tCon->receiveTC_COMMITCONF(commitConf); if (tReturnCode != -1) { completedTransaction(tCon); @@ -855,7 +852,6 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) tCon = void2con(tFirstDataPtr); if ((tCon->checkMagicNumber() == 0) && (tCon->theSendStatus == NdbTransaction::sendTC_OP)) { - g_latest_trans_gci= indxConf->gci; tReturnCode = tCon->receiveTCINDXCONF(indxConf, tLen); if (tReturnCode != -1) { completedTransaction(tCon); diff --git a/storage/ndb/src/ndbapi/Ndbinit.cpp b/storage/ndb/src/ndbapi/Ndbinit.cpp index 91567e99c01..5c0fb521c36 100644 --- a/storage/ndb/src/ndbapi/Ndbinit.cpp +++ b/storage/ndb/src/ndbapi/Ndbinit.cpp @@ -219,6 +219,9 @@ NdbImpl::NdbImpl(Ndb_cluster_connection *ndb_cluster_connection, } m_optimized_node_selection= m_ndb_cluster_connection.m_optimized_node_selection; + + m_systemPrefix.assfmt("%s%c%s%c", NDB_SYSTEM_DATABASE, table_name_separator, + NDB_SYSTEM_SCHEMA, table_name_separator); } NdbImpl::~NdbImpl() diff --git a/storage/ndb/test/ndbapi/testNodeRestart.cpp b/storage/ndb/test/ndbapi/testNodeRestart.cpp index aed0b39f196..754b3edc269 100644 --- a/storage/ndb/test/ndbapi/testNodeRestart.cpp +++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp @@ -868,6 +868,56 @@ runBug18612SR(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runBug20185(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + HugoOperations hugoOps(*ctx->getTab()); + Ndb* pNdb = GETNDB(step); + + int dump[] = { 7090, 20 } ; + if (restarter.dumpStateAllNodes(dump, 2)) + return NDBT_FAILED; + + NdbSleep_MilliSleep(3000); + + if(hugoOps.startTransaction(pNdb) != 0) + return NDBT_FAILED; + + if(hugoOps.pkUpdateRecord(pNdb, 1, 1) != 0) + return NDBT_FAILED; + + if (hugoOps.execute_NoCommit(pNdb) != 0) + return NDBT_FAILED; + + int nodeId; + const int node = hugoOps.getTransaction()->getConnectedNodeId(); + do { + nodeId = restarter.getDbNodeId(rand() % restarter.getNumDbNodes()); + } while (nodeId == node); + + if (restarter.insertErrorInAllNodes(7030)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(nodeId, 7031)) + return NDBT_FAILED; + + NdbSleep_MilliSleep(500); + + if (hugoOps.execute_Commit(pNdb) == 0) + return NDBT_FAILED; + + NdbSleep_MilliSleep(3000); + + restarter.waitClusterStarted(); + + if (restarter.dumpStateAllNodes(dump, 1)) + return NDBT_FAILED; + + return NDBT_OK; +} + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", @@ -1175,6 +1225,12 @@ TESTCASE("Bug18612SR", STEP(runBug18612SR); FINALIZER(runClearTable); } +TESTCASE("Bug20185", + ""){ + INITIALIZER(runLoadTable); + STEP(runBug20185); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 3fead45533f..5fe3506dffb 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -473,6 +473,10 @@ max-time: 1000 cmd: testNodeRestart args: -n Bug18612SR T1 +max-time: 1000 +cmd: testNodeRestart +args: -n Bug20185 T1 + # # DICT TESTS max-time: 1500 diff --git a/unittest/Makefile.am b/unittest/Makefile.am index fd7530ee262..dc778aada1c 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -1,27 +1,14 @@ SUBDIRS = mytap . mysys examples noinst_SCRIPTS = unit +#EXTRA_DIST = unit.pl -EXTRA_DIST = unit.pl +unittests = mytap mysys -DISTCLEANFILES = unit - -unittests = mysys examples - -.PHONY: all mytap mysys examples test - -test: unit all - @./unit run $(unittests) - -mytap: - cd mytap && $(MAKE) - -mysys: - cd mysys && $(MAKE) - -examples: - cd examples && $(MAKE) +test: unit + ./unit run $(unittests) unit: $(srcdir)/unit.pl - cp $< $@ - chmod +x $@ + cp $(srcdir)/unit.pl $@ + chmod 700 $@ + diff --git a/unittest/README.txt b/unittest/README.txt index fd9641665c7..0d8bb9025d8 100644 --- a/unittest/README.txt +++ b/unittest/README.txt @@ -7,14 +7,14 @@ will be added over time. mytap Source for the MyTAP library mysys Tests for mysys components - bitmap.t.c Unit test for MY_BITMAP - base64.t.c Unit test for base64 encoding functions + bitmap-t.c Unit test for MY_BITMAP + base64-t.c Unit test for base64 encoding functions examples Example unit tests - simple.t.c Example of a standard TAP unit test - skip.t.c Example where some test points are skipped - skip_all.t.c Example of a test where the entire test is skipped - todo.t.c Example where test contain test points that are TODO - no_plan.t.c Example of a test with no plan (avoid this) + simple-t.c Example of a standard TAP unit test + skip-t.c Example where some test points are skipped + skip_all-t.c Example of a test where the entire test is skipped + todo-t.c Example where test contain test points that are TODO + no_plan-t.c Example of a test with no plan (avoid this) Executing unit tests @@ -28,9 +28,12 @@ To make and execute all unit tests in the directory: Adding unit tests ----------------- -Add a file with a name of the format "foo.t.c" to the appropriate +Add a file with a name of the format "foo-t.c" to the appropriate directory and add the following to the Makefile.am in that directory (where ... denotes stuff already there): - noinst_PROGRAMS = ... foo.t - foo_t_c_SOURCES = foo.t.c + noinst_PROGRAMS = ... foo-t + +Note, it's important to have "-t" at the end of the filename, otherwise the +test won't be executed by 'make test' ! + diff --git a/unittest/examples/Makefile.am b/unittest/examples/Makefile.am index 94a67927d12..f3c70b654a1 100644 --- a/unittest/examples/Makefile.am +++ b/unittest/examples/Makefile.am @@ -5,14 +5,5 @@ AM_LDFLAGS = -L$(top_builddir)/unittest/mytap LDADD = -lmytap -noinst_PROGRAMS = simple.t skip.t todo.t skip_all.t no_plan.t +noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t -simple_t_SOURCES = simple.t.c - -skip_t_SOURCES = skip.t.c - -todo_t_SOURCES = todo.t.c - -skip_all_t_SOURCES = skip_all.t.c - -no_plan_t_SOURCES = no_plan.t.c diff --git a/unittest/examples/no_plan.t.c b/unittest/examples/no_plan-t.c similarity index 100% rename from unittest/examples/no_plan.t.c rename to unittest/examples/no_plan-t.c diff --git a/unittest/examples/simple.t.c b/unittest/examples/simple-t.c similarity index 100% rename from unittest/examples/simple.t.c rename to unittest/examples/simple-t.c diff --git a/unittest/examples/skip.t.c b/unittest/examples/skip-t.c similarity index 100% rename from unittest/examples/skip.t.c rename to unittest/examples/skip-t.c diff --git a/unittest/examples/skip_all.t.c b/unittest/examples/skip_all-t.c similarity index 100% rename from unittest/examples/skip_all.t.c rename to unittest/examples/skip_all-t.c diff --git a/unittest/examples/todo.t.c b/unittest/examples/todo-t.c similarity index 100% rename from unittest/examples/todo.t.c rename to unittest/examples/todo-t.c diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index 010a7845339..b1e0356bac6 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -7,9 +7,5 @@ AM_LDFLAGS += -L$(top_builddir)/strings -L$(top_builddir)/dbug LDADD = -lmytap -lmysys -ldbug -lmystrings -noinst_PROGRAMS = bitmap.t base64.t - -bitmap_t_SOURCES = bitmap.t.c - -base64_t_SOURCES = base64.t.c +noinst_PROGRAMS = bitmap-t base64-t my_atomic-t diff --git a/unittest/mysys/base64.t.c b/unittest/mysys/base64-t.c similarity index 100% rename from unittest/mysys/base64.t.c rename to unittest/mysys/base64-t.c diff --git a/unittest/mysys/bitmap.t.c b/unittest/mysys/bitmap-t.c similarity index 100% rename from unittest/mysys/bitmap.t.c rename to unittest/mysys/bitmap-t.c diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c new file mode 100644 index 00000000000..8a3fe129b07 --- /dev/null +++ b/unittest/mysys/my_atomic-t.c @@ -0,0 +1,149 @@ +/* Copyright (C) 2006 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; either version 2 of the License, or + (at your option) any later version. + + 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 + +#include +#include +#include + +my_atomic_32_t a32,b32,c32; +my_atomic_rwlock_t rwl; + +pthread_attr_t thr_attr; +pthread_mutex_t mutex; +pthread_cond_t cond; +int N; + +/* add and sub a random number in a loop. Must get 0 at the end */ +pthread_handler_t test_atomic_add_handler(void *arg) +{ + int m=*(int *)arg; + int32 x; + for (x=((int)(&m)); m ; m--) + { + x=x*m+0x87654321; + my_atomic_add32(&a32, x, &rwl); + my_atomic_add32(&a32, -x, &rwl); + } + pthread_mutex_lock(&mutex); + N--; + if (!N) pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + return 0; +} + +/* + 1. generate thread number 0..N-1 from b32 + 2. add it to a32 + 3. swap thread numbers in c32 + 4. (optionally) one more swap to avoid 0 as a result + 5. subtract result from a32 + must get 0 in a32 at the end +*/ +pthread_handler_t test_atomic_swap_handler(void *arg) +{ + int m=*(int *)arg; + uint32 x=my_atomic_add32(&b32, 1, &rwl); + + my_atomic_add32(&a32, x, &rwl); + + for (; m ; m--) + x=my_atomic_swap32(&c32, x,&rwl); + + if (!x) + x=my_atomic_swap32(&c32, x,&rwl); + + my_atomic_add32(&a32, -x, &rwl); + + pthread_mutex_lock(&mutex); + N--; + if (!N) pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + return 0; +} + +/* + same as test_atomic_add_handler, but my_atomic_add32 is emulated with + (slower) my_atomic_cas32 +*/ +pthread_handler_t test_atomic_cas_handler(void *arg) +{ + int m=*(int *)arg; + int32 x; + for (x=((int)(&m)); m ; m--) + { + uint32 y=my_atomic_load32(&a32, &rwl); + x=x*m+0x87654321; + while (!my_atomic_cas32(&a32, &y, y+x, &rwl)) ; + while (!my_atomic_cas32(&a32, &y, y-x, &rwl)) ; + } + pthread_mutex_lock(&mutex); + N--; + if (!N) pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + return 0; +} + +void test_atomic(const char *test, pthread_handler handler, int n, int m) +{ + pthread_t t; + ulonglong now=my_getsystime(); + + my_atomic_store32(&a32, 0, &rwl); + my_atomic_store32(&b32, 0, &rwl); + my_atomic_store32(&c32, 0, &rwl); + + diag("Testing %s with %d threads, %d iterations... ", test, n, m); + for (N=n ; n ; n--) + pthread_create(&t, &thr_attr, handler, &m); + + pthread_mutex_lock(&mutex); + while (N) + pthread_cond_wait(&cond, &mutex); + pthread_mutex_unlock(&mutex); + now=my_getsystime()-now; + ok(my_atomic_load32(&a32, &rwl) == 0, + "tested %s in %g secs", test, ((double)now)/1e7); +} + +int main() +{ + int err; + + diag("N CPUs: %d", my_getncpus()); + err= my_atomic_initialize(); + + plan(4); + ok(err == 0, "my_atomic_initialize() returned %d", err); + + pthread_attr_init(&thr_attr); + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); + my_atomic_rwlock_init(&rwl); + + test_atomic("my_atomic_add32", test_atomic_add_handler, 100,1000000); + test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,1000000); + test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,1000000); + + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); + pthread_attr_destroy(&thr_attr); + my_atomic_rwlock_destroy(&rwl); + return exit_status(); +} + diff --git a/unittest/mytap/t/Makefile.am b/unittest/mytap/t/Makefile.am index 88c31cfeb7f..b685ae7dc1c 100644 --- a/unittest/mytap/t/Makefile.am +++ b/unittest/mytap/t/Makefile.am @@ -5,8 +5,5 @@ AM_LDFLAGS = -L$(top_builddir)/unittest/mytap LDADD = -lmytap -noinst_PROGRAMS = basic.t +noinst_PROGRAMS = basic-t -basic_t_SOURCES = basic.t.c - -all: $(noinst_PROGRAMS) diff --git a/unittest/mytap/t/basic.t.c b/unittest/mytap/t/basic-t.c similarity index 100% rename from unittest/mytap/t/basic.t.c rename to unittest/mytap/t/basic-t.c diff --git a/unittest/unit.pl b/unittest/unit.pl index cae394cf9b6..3092a874192 100644 --- a/unittest/unit.pl +++ b/unittest/unit.pl @@ -59,7 +59,7 @@ sub _find_test_files (@) { my @files; find sub { $File::Find::prune = 1 if /^SCCS$/; - push(@files, $File::Find::name) if -x _ && /\.t\z/; + push(@files, $File::Find::name) if -x _ && /-t\z/; }, @dirs; return @files; }