diff options
author | Vladislav Vaintroub <wlad@sol> | 2009-12-04 20:05:04 +0000 |
---|---|---|
committer | Vladislav Vaintroub <wlad@sol> | 2009-12-04 20:05:04 +0000 |
commit | a426f50f5c77086f50d1853f48159c391bcd633f (patch) | |
tree | 88f8eb36158b237cddb8fd5b1c7ee5283f8124f6 | |
parent | 131d1e6fdd88090dde6144be3c3d5150449efb95 (diff) | |
parent | 560e76c567c3551f5a4320acfc954200e8330ad8 (diff) | |
download | mariadb-git-a426f50f5c77086f50d1853f48159c391bcd633f.tar.gz |
merge
78 files changed, 7784 insertions, 404 deletions
diff --git a/Makefile.am b/Makefile.am index 7675c58ecf8..56b4cdb5795 100644 --- a/Makefile.am +++ b/Makefile.am @@ -272,11 +272,12 @@ test-full-qa: # API_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \ - $(top_srcdir)/include/mysql.h + $(top_srcdir)/include/mysql.h \ + $(top_srcdir)/include/mysql/psi/psi_abi_v1.h \ + $(top_srcdir)/include/mysql/psi/psi_abi_v2.h -TEST_PREPROCESSOR_HEADER = $(top_srcdir)/include/mysql/plugin.h \ - $(top_srcdir)/sql/mysql_priv.h \ - $(top_srcdir)/include/mysql.h +TEST_PREPROCESSOR_HEADER = $(API_PREPROCESSOR_HEADER) \ + $(top_srcdir)/sql/mysql_priv.h # # Rules for checking that the abi/api has not changed. diff --git a/cmake/abi_check.cmake b/cmake/abi_check.cmake index 61b0d9e7970..8e8426d5245 100644 --- a/cmake/abi_check.cmake +++ b/cmake/abi_check.cmake @@ -29,12 +29,14 @@ IF(CMAKE_COMPILER_IS_GNUCC AND UNIX) ENDIF() SET(API_PREPROCESSOR_HEADER ${CMAKE_SOURCE_DIR}/include/mysql/plugin.h - ${CMAKE_SOURCE_DIR}/include/mysql.h) + ${CMAKE_SOURCE_DIR}/include/mysql.h + ${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_v1.h + ${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_v2.h + ) SET(TEST_PREPROCESSOR_HEADER - ${CMAKE_SOURCE_DIR}/include/mysql/plugin.h ${CMAKE_SOURCE_DIR}/sql/mysql_priv.h - ${CMAKE_SOURCE_DIR}/include/mysql.h) + ) ADD_CUSTOM_TARGET(abi_check ALL diff --git a/configure.in b/configure.in index 818281c33ff..32e06f87bd9 100644 --- a/configure.in +++ b/configure.in @@ -879,6 +879,42 @@ AC_CHECK_DECLS(MHA_MAPSIZE_VA, fi #-------------------------------------------------------------------- +# Check for IPv6 support +#-------------------------------------------------------------------- + +AC_CHECK_HEADERS(netinet/in6.h) + +AC_CHECK_TYPES([struct sockaddr_in6, struct in6_addr], + [have_in6_types=yes], + [have_in6_types=no], + [[ + #ifdef WIN32 + #include <winsock2.h> + #else + #include <sys/types.h> + #include <netinet/in.h> + #include <sys/socket.h> + #endif + + #ifdef HAVE_NETINET_IN6_H + #include <netinet/in6.h> + #endif + ]]) + +AC_MSG_CHECKING([for IPv6 support]) + +AC_ARG_ENABLE(ipv6, + AS_HELP_STRING([--disable-ipv6], [Disable support for IPv6 networking]), + [disable_ipv6=yes], [disable_ipv6=no]) + +if test x"$disable_ipv6" = xyes -o x"$have_in6_types" = xno; then + AC_MSG_RESULT([no]) +else + AC_DEFINE([HAVE_IPV6], [1], [Define if IPv6 networking support is present]) + AC_MSG_RESULT([yes]) +fi + +#-------------------------------------------------------------------- # Check for TCP wrapper support #-------------------------------------------------------------------- @@ -976,12 +1012,6 @@ AC_CHECK_TYPES([int8, uint8, int16, uint16, int32, uint32, int64, uint64, uchar, uint, ulong],[],[], [ #include <sys/types.h> ]) -AC_CHECK_TYPES([in_addr_t], [], [], [ -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -]) AC_CHECK_TYPES([fp_except], [], [], [ #include <sys/types.h> #include <ieeefp.h> diff --git a/include/Makefile.am b/include/Makefile.am index 3d866961389..02d047f9c81 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2006 MySQL AB +# Copyright (C) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -24,6 +24,8 @@ pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ my_xml.h mysql_embed.h mysql/services.h \ mysql/service_my_snprintf.h mysql/service_thd_alloc.h \ my_pthread.h my_no_pthread.h \ + mysql/psi/psi.h mysql/psi/mysql_thread.h \ + mysql/psi/mysql_file.h \ decimal.h errmsg.h my_global.h my_net.h \ my_getopt.h sslopt-longopts.h my_dir.h \ sslopt-vars.h sslopt-case.h sql_common.h keycache.h \ @@ -38,14 +40,16 @@ noinst_HEADERS = config-win.h config-netware.h lf.h my_bit.h \ my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \ thr_lock.h t_ctype.h violite.h my_md5.h base64.h \ my_handler.h my_time.h service_versions.h \ - my_rdtsc.h \ + my_rdtsc.h mysql/psi/psi_abi_v1.h mysql/psi/psi_abi_v2.h \ my_vle.h my_user.h my_atomic.h atomic/nolock.h \ atomic/rwlock.h atomic/x86-gcc.h atomic/generic-msvc.h \ atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h \ atomic/solaris.h EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp probes_mysql.d.base \ - CMakeLists.txt + CMakeLists.txt \ + mysql/psi/psi_abi_v1.h.pp \ + mysql/psi/psi_abi_v2.h.pp # Remove built files and the symlinked directories CLEANFILES = $(BUILT_SOURCES) readline openssl probes_mysql.d probes_mysql_nodtrace.h diff --git a/include/config-win.h b/include/config-win.h index 431bfcfa702..68248c09bef 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -20,6 +20,13 @@ #define BIG_TABLES +/* + Minimal version of Windows we should be able to run on. + Currently Windows XP. +*/ +#define _WIN32_WINNT 0x0501 + + #if defined(_MSC_VER) && _MSC_VER >= 1400 /* Avoid endless warnings about sprintf() etc. being unsafe. */ #define _CRT_SECURE_NO_DEPRECATE 1 @@ -27,6 +34,7 @@ #include <sys/locking.h> #include <winsock2.h> +#include <Ws2tcpip.h> #include <fcntl.h> #include <io.h> #include <malloc.h> @@ -88,6 +96,12 @@ #define S_IROTH S_IREAD /* for my_lib */ +/* Winsock2 constant (Vista SDK and later)*/ +#define IPPROTO_IPV6 41 +#ifndef IPV6_V6ONLY +#define IPV6_V6ONLY 27 +#endif + #ifdef __BORLANDC__ #define FILE_BINARY O_BINARY /* my_fopen in binary mode */ #define O_TEMPORARY 0 diff --git a/include/my_global.h b/include/my_global.h index 9405ed9d81c..5c3a7044c4c 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2009 Sun Microsystems, Inc 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 @@ -83,6 +83,16 @@ #endif #endif /* _WIN32... */ +#ifdef EMBEDDED_LIBRARY +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +#undef WITH_PERFSCHEMA_STORAGE_ENGINE +#endif +#endif /* EMBEDDED_LIBRARY */ + +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +#define HAVE_PSI_INTERFACE +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + /* Make it easier to add conditionl code for windows */ #ifdef __WIN__ #define IF_WIN(A,B) (A) diff --git a/include/my_net.h b/include/my_net.h index 3af79ea3db5..18fb3db8e88 100644 --- a/include/my_net.h +++ b/include/my_net.h @@ -43,7 +43,7 @@ C_MODE_START #include <sys/ioctl.h> #endif -#if !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__BEOS__) && !defined(__NETWARE__) +#if !defined(__WIN__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) && !defined(__NETWARE__) #include <netinet/in_systm.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -73,11 +73,6 @@ C_MODE_START #define in_addr_t uint32 #endif -/* On some operating systems (e.g. Solaris) INADDR_NONE is not defined */ -#ifndef INADDR_NONE -#define INADDR_NONE -1 /* Error value from inet_addr */ -#endif - /* Thread safe or portable version of some functions */ void my_inet_ntoa(struct in_addr in, char *buf); @@ -86,9 +81,6 @@ void my_inet_ntoa(struct in_addr in, char *buf); Handling of gethostbyname_r() */ -#if !defined(HPUX10) -struct hostent; -#endif /* HPUX */ #if !defined(HAVE_GETHOSTBYNAME_R) struct hostent *my_gethostbyname_r(const char *name, struct hostent *result, char *buffer, @@ -118,11 +110,5 @@ struct hostent *my_gethostbyname_r(const char *name, #define GETHOSTBYNAME_BUFF_SIZE 2048 #endif -/* On SCO you get a link error when refering to h_errno */ -#ifdef SCO -#undef h_errno -#define h_errno errno -#endif - C_MODE_END #endif diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h index 31c1bf2b6ac..995fc5e1774 100644 --- a/include/my_no_pthread.h +++ b/include/my_no_pthread.h @@ -1,7 +1,7 @@ #ifndef MY_NO_PTHREAD_INCLUDED #define MY_NO_PTHREAD_INCLUDED -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -48,5 +48,16 @@ #define rw_unlock(A) #define rwlock_destroy(A) +#define mysql_mutex_init(A, B, C) do {} while (0) +#define mysql_mutex_lock(A) do {} while (0) +#define mysql_mutex_unlock(A) do {} while (0) +#define mysql_mutex_destroy(A) do {} while (0) + +#define mysql_rwlock_init(A, B, C) do {} while (0) +#define mysql_rwlock_rdlock(A) do {} while (0) +#define mysql_rwlock_wrlock(A) do {} while (0) +#define mysql_rwlock_unlock(A) do {} while (0) +#define mysql_rwlock_destroy(A) do {} while (0) + #endif #endif /* MY_NO_PTHREAD_INCLUDED */ diff --git a/include/my_pthread.h b/include/my_pthread.h index 5a73cf5bce8..6e3763b6181 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. 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 @@ -99,7 +99,7 @@ struct timespec { int win_pthread_mutex_trylock(pthread_mutex_t *mutex); -int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *); +int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, @@ -139,8 +139,8 @@ int pthread_cancel(pthread_t thread); #define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0) #define pthread_mutex_lock(A) (EnterCriticalSection(A),0) #define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A)) -#define pthread_mutex_unlock(A) LeaveCriticalSection(A) -#define pthread_mutex_destroy(A) DeleteCriticalSection(A) +#define pthread_mutex_unlock(A) (LeaveCriticalSection(A), 0) +#define pthread_mutex_destroy(A) (DeleteCriticalSection(A), 0) #define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH) @@ -631,6 +631,10 @@ extern int pthread_dummy(int); #endif #endif +#include <mysql/psi/mysql_thread.h> + +#define INSTRUMENT_ME 0 + struct st_my_thread_var { int thr_errno; diff --git a/include/my_sys.h b/include/my_sys.h index ea466653372..c188b820245 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -1021,5 +1021,15 @@ void netware_reg_user(const char *ip, const char *user, const char *application); #endif +#include <mysql/psi/psi.h> + +#ifdef HAVE_PSI_INTERFACE +extern MYSQL_PLUGIN_IMPORT struct PSI_bootstrap *PSI_hook; +void my_init_mysys_psi_keys(void); +#endif + +struct st_mysql_file; +extern struct st_mysql_file *mysql_stdin; + C_MODE_END #endif /* _my_sys_h */ diff --git a/include/mysql/psi/mysql_file.h b/include/mysql/psi/mysql_file.h new file mode 100644 index 00000000000..18220a8dd4e --- /dev/null +++ b/include/mysql/psi/mysql_file.h @@ -0,0 +1,1398 @@ +/* Copyright (C) 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef MYSQL_FILE_H +#define MYSQL_FILE_H + +/* For strlen() */ +#include <string.h> +/* For MY_STAT */ +#include <my_dir.h> + +/** + @file mysql/psi/mysql_file.h + Instrumentation helpers for mysys file io. + This header file provides the necessary declarations + to use the mysys file API with the performance schema instrumentation. + In some compilers (SunStudio), 'static inline' functions, when declared + but not used, are not optimized away (because they are unused) by default, + so that including a static inline function from a header file does + create unwanted dependencies, causing unresolved symbols at link time. + Other compilers, like gcc, optimize these dependencies by default. + + Since the instrumented APIs declared here are wrapper on top + of mysys file io APIs, including mysql/psi/mysql_file.h assumes that + the dependency on my_sys already exists. +*/ + +#include "mysql/psi/psi.h" + +/** + @defgroup File_instrumentation File Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + @def mysql_file_fgets(P1, P2, F) + Instrumented fgets. + @c mysql_file_fgets is a replacement for @c fgets. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fgets(P1, P2, F) \ + inline_mysql_file_fgets(__FILE__, __LINE__, P1, P2, F) +#else + #define mysql_file_fgets(P1, P2, F) \ + inline_mysql_file_fgets(P1, P2, F) +#endif + +/** + @def mysql_file_fgetc(F) + Instrumented fgetc. + @c mysql_file_fgetc is a replacement for @c fgetc. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fgetc(F) inline_mysql_file_fgetc(__FILE__, __LINE__, F) +#else + #define mysql_file_fgetc(F) inline_mysql_file_fgetc(F) +#endif + +/** + @def mysql_file_fputs(P1, F) + Instrumented fputs. + @c mysql_file_fputs is a replacement for @c fputs. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fputs(P1, F) \ + inline_mysql_file_fputs(__FILE__, __LINE__, P1, F) +#else + #define mysql_file_fputs(P1, F)\ + inline_mysql_file_fputs(P1, F) +#endif + +/** + @def mysql_file_fputc(P1, F) + Instrumented fputc. + @c mysql_file_fputc is a replacement for @c fputc. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fputc(P1, F) \ + inline_mysql_file_fputc(__FILE__, __LINE__, P1, F) +#else + #define mysql_file_fputc(P1, F) \ + inline_mysql_file_fputc(P1, F) +#endif + +/** + @def mysql_file_fprintf + Instrumented fprintf. + @c mysql_file_fprintf is a replacement for @c fprintf. +*/ +#define mysql_file_fprintf inline_mysql_file_fprintf + +/** + @def mysql_file_vfprintf(F, P1, P2) + Instrumented vfprintf. + @c mysql_file_vfprintf is a replacement for @c vfprintf. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_vfprintf(F, P1, P2) \ + inline_mysql_file_vfprintf(__FILE__, __LINE__, F, P1, P2) +#else + #define mysql_file_vfprintf(F, P1, P2) \ + inline_mysql_file_vfprintf(F, P1, P2) +#endif + +/** + @def mysql_file_fflush(F, P1, P2) + Instrumented fflush. + @c mysql_file_fflush is a replacement for @c fflush. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fflush(F) \ + inline_mysql_file_fflush(__FILE__, __LINE__, F) +#else + #define mysql_file_fflush(F) \ + inline_mysql_file_fflush(F) +#endif + +/** + @def mysql_file_feof(F) + Instrumented feof. + @c mysql_file_feof is a replacement for @c feof. +*/ +#define mysql_file_feof(F) inline_mysql_file_feof(F) + +/** + @def mysql_file_fstat(FN, S, FL) + Instrumented fstat. + @c mysql_file_fstat is a replacement for @c my_fstat. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fstat(FN, S, FL) \ + inline_mysql_file_fstat(__FILE__, __LINE__, FN, S, FL) +#else + #define mysql_file_fstat(FN, S, FL) \ + inline_mysql_file_fstat(FN, S, FL) +#endif + +/** + @def mysql_file_stat(K, FN, S, FL) + Instrumented stat. + @c mysql_file_stat is a replacement for @c my_stat. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_stat(K, FN, S, FL) \ + inline_mysql_file_stat(K, __FILE__, __LINE__, FN, S, FL) +#else + #define mysql_file_stat(K, FN, S, FL) \ + inline_mysql_file_stat(FN, S, FL) +#endif + +/** + @def mysql_file_chsize(F, P1, P2, P3) + Instrumented chsize. + @c mysql_file_chsize is a replacement for @c my_chsize. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_chsize(F, P1, P2, P3) \ + inline_mysql_file_chsize(__FILE__, __LINE__, F, P1, P2, P3) +#else + #define mysql_file_chsize(F, P1, P2, P3) \ + inline_mysql_file_chsize(F, P1, P2, P3) +#endif + +/** + @def mysql_file_fopen(K, N, F1, F2) + Instrumented fopen. + @c mysql_file_fopen is a replacement for @c my_fopen. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fopen(K, N, F1, F2) \ + inline_mysql_file_fopen(K, __FILE__, __LINE__, N, F1, F2) +#else + #define mysql_file_fopen(K, N, F1, F2) \ + inline_mysql_file_fopen(N, F1, F2) +#endif + +/** + @def mysql_file_fclose(FD, FL) + Instrumented fclose. + @c mysql_file_fclose is a replacement for @c my_fclose. + Without the instrumentation, this call will have the same behavior as the + undocumented and possibly platform specific my_fclose(NULL, ...) behavior. + With the instrumentation, mysql_fclose(NULL, ...) will safely return 0, + which is an extension compared to my_fclose and is therefore compliant. + mysql_fclose is on purpose *not* implementing + @code DBUG_ASSERT(file != NULL) @endcode, + since doing so could introduce regressions. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fclose(FD, FL) \ + inline_mysql_file_fclose(__FILE__, __LINE__, FD, FL) +#else + #define mysql_file_fclose(FD, FL) \ + inline_mysql_file_fclose(FD, FL) +#endif + +/** + @def mysql_file_fread(FD, P1, P2, P3) + Instrumented fread. + @c mysql_file_fread is a replacement for @c my_fread. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fread(FD, P1, P2, P3) \ + inline_mysql_file_fread(__FILE__, __LINE__, FD, P1, P2, P3) +#else + #define mysql_file_fread(FD, P1, P2, P3) \ + inline_mysql_file_fread(FD, P1, P2, P3) +#endif + +/** + @def mysql_file_fwrite(FD, P1, P2, P3) + Instrumented fwrite. + @c mysql_file_fwrite is a replacement for @c my_fwrite. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fwrite(FD, P1, P2, P3) \ + inline_mysql_file_fwrite(__FILE__, __LINE__, FD, P1, P2, P3) +#else + #define mysql_file_fwrite(FD, P1, P2, P3) \ + inline_mysql_file_fwrite(FD, P1, P2, P3) +#endif + +/** + @def mysql_file_fseek(FD, P, W, F) + Instrumented fseek. + @c mysql_file_fseek is a replacement for @c my_fseek. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_fseek(FD, P, W, F) \ + inline_mysql_file_fseek(__FILE__, __LINE__, FD, P, W, F) +#else + #define mysql_file_fseek(FD, P, W, F) \ + inline_mysql_file_fseek(FD, P, W, F) +#endif + +/** + @def mysql_file_ftell(FD, F) + Instrumented ftell. + @c mysql_file_ftell is a replacement for @c my_ftell. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_ftell(FD, F) \ + inline_mysql_file_ftell(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_ftell(FD, F) \ + inline_mysql_file_ftell(FD, F) +#endif + +/** + @def mysql_file_create(K, N, F1, F2, F3) + Instrumented create. + @c mysql_file_create is a replacement for @c my_create. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_create(K, N, F1, F2, F3) \ + inline_mysql_file_create(K, __FILE__, __LINE__, N, F1, F2, F3) +#else + #define mysql_file_create(K, N, F1, F2, F3) \ + inline_mysql_file_create(N, F1, F2, F3) +#endif + +/** + @def mysql_file_create_temp(K, T, D, P, M, F) + Instrumented create_temp_file. + @c mysql_file_create_temp is a replacement for @c create_temp_file. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_create_temp(K, T, D, P, M, F) \ + inline_mysql_file_create_temp(K, T, D, P, M, F) +#else + #define mysql_file_create_temp(K, T, D, P, M, F) \ + inline_mysql_file_create_temp(T, D, P, M, F) +#endif + +/** + @def mysql_file_open(K, N, F1, F2) + Instrumented open. + @c mysql_file_open is a replacement for @c my_open. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_open(K, N, F1, F2) \ + inline_mysql_file_open(K, __FILE__, __LINE__, N, F1, F2) +#else + #define mysql_file_open(K, N, F1, F2) \ + inline_mysql_file_open(N, F1, F2) +#endif + +/** + @def mysql_file_close(FD, F) + Instrumented close. + @c mysql_file_close is a replacement for @c my_close. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_close(FD, F) \ + inline_mysql_file_close(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_close(FD, F) \ + inline_mysql_file_close(FD, F) +#endif + +/** + @def mysql_file_read(FD, B, S, F) + Instrumented read. + @c mysql_read is a replacement for @c my_read. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_read(FD, B, S, F) \ + inline_mysql_file_read(__FILE__, __LINE__, FD, B, S, F) +#else + #define mysql_file_read(FD, B, S, F) \ + inline_mysql_file_read(FD, B, S, F) +#endif + +/** + @def mysql_file_write(FD, B, S, F) + Instrumented write. + @c mysql_file_write is a replacement for @c my_write. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_write(FD, B, S, F) \ + inline_mysql_file_write(__FILE__, __LINE__, FD, B, S, F) +#else + #define mysql_file_write(FD, B, S, F) \ + inline_mysql_file_write(FD, B, S, F) +#endif + +/** + @def mysql_file_pread(FD, B, S, O, F) + Instrumented pread. + @c mysql_pread is a replacement for @c my_pread. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_pread(FD, B, S, O, F) \ + inline_mysql_file_pread(__FILE__, __LINE__, FD, B, S, O, F) +#else + #define mysql_file_pread(FD, B, S, O, F) \ + inline_mysql_file_pread(FD, B, S, O, F) +#endif + +/** + @def mysql_file_pwrite(FD, B, S, O, F) + Instrumented pwrite. + @c mysql_file_pwrite is a replacement for @c my_pwrite. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_pwrite(FD, B, S, O, F) \ + inline_mysql_file_pwrite(__FILE__, __LINE__, FD, B, S, O, F) +#else + #define mysql_file_pwrite(FD, B, S, O, F) \ + inline_mysql_file_pwrite(FD, B, S, O, F) +#endif + +/** + @def mysql_file_seek(FD, P, W, F) + Instrumented seek. + @c mysql_file_seek is a replacement for @c my_seek. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_seek(FD, P, W, F) \ + inline_mysql_file_seek(__FILE__, __LINE__, FD, P, W, F) +#else + #define mysql_file_seek(FD, P, W, F) \ + inline_mysql_file_seek(FD, P, W, F) +#endif + +/** + @def mysql_file_tell(FD, F) + Instrumented tell. + @c mysql_file_tell is a replacement for @c my_tell. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_tell(FD, F) \ + inline_mysql_file_tell(__FILE__, __LINE__, FD, F) +#else + #define mysql_file_tell(FD, F) \ + inline_mysql_file_tell(FD, F) +#endif + +/** + @def mysql_file_delete(K, P1, P2) + Instrumented delete. + @c mysql_file_delete is a replacement for @c my_delete. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_delete(K, P1, P2) \ + inline_mysql_file_delete(K, __FILE__, __LINE__, P1, P2) +#else + #define mysql_file_delete(K, P1, P2) \ + inline_mysql_file_delete(P1, P2) +#endif + +/** + @def mysql_file_rename(K, P1, P2, P3) + Instrumented rename. + @c mysql_file_rename is a replacement for @c my_rename. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_rename(K, P1, P2, P3) \ + inline_mysql_file_rename(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_rename(K, P1, P2, P3) \ + inline_mysql_file_rename(P1, P2, P3) +#endif + +/** + @def mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) + Instrumented create with symbolic link. + @c mysql_file_create_with_symlink is a replacement + for @c my_create_with_symlink. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ + inline_mysql_file_create_with_symlink(K, __FILE__, __LINE__, \ + P1, P2, P3, P4, P5) +#else + #define mysql_file_create_with_symlink(K, P1, P2, P3, P4, P5) \ + inline_mysql_file_create_with_symlink(P1, P2, P3, P4, P5) +#endif + +/** + @def mysql_file_delete_with_symlink(K, P1, P2) + Instrumented delete with symbolic link. + @c mysql_file_delete_with_symlink is a replacement + for @c my_delete_with_symlink. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_delete_with_symlink(K, P1, P2) \ + inline_mysql_file_delete_with_symlink(K, __FILE__, __LINE__, P1, P2) +#else + #define mysql_file_delete_with_symlink(K, P1, P2) \ + inline_mysql_file_delete_with_symlink(P1, P2) +#endif + +/** + @def mysql_file_rename_with_symlink(K, P1, P2, P3) + Instrumented rename with symbolic link. + @c mysql_file_rename_with_symlink is a replacement + for @c my_rename_with_symlink. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_rename_with_symlink(K, __FILE__, __LINE__, P1, P2, P3) +#else + #define mysql_file_rename_with_symlink(K, P1, P2, P3) \ + inline_mysql_file_rename_with_symlink(P1, P2, P3) +#endif + +/** + @def mysql_file_sync(P1, P2) + Instrumented file sync. + @c mysql_file_sync is a replacement for @c my_sync. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_file_sync(P1, P2) \ + inline_mysql_file_sync(__FILE__, __LINE__, P1, P2) +#else + #define mysql_file_sync(P1, P2) \ + inline_mysql_file_sync(P1, P2) +#endif + +/** + An instrumented FILE structure. + @sa MYSQL_FILE +*/ +struct st_mysql_file +{ + /** The real file. */ + FILE *m_file; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c MYSQL_FILE interface. + */ + struct PSI_file *m_psi; +}; + +/** + Type of an instrumented file. + @c MYSQL_FILE is a drop-in replacement for @c FILE. + @sa mysql_file_open +*/ +typedef struct st_mysql_file MYSQL_FILE; + +static inline char * +inline_mysql_file_fgets( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + char *str, int size, MYSQL_FILE *file) +{ + char *result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_READ); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) size, src_file, src_line); + } +#endif + result= fgets(str, size, file->m_file); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, result ? strlen(result) : 0); +#endif + return result; +} + +static inline int +inline_mysql_file_fgetc( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_READ); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 1, src_file, src_line); + } +#endif + result= fgetc(file->m_file); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 1); +#endif + return result; +} + +static inline int +inline_mysql_file_fputs( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + const char *str, MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + size_t bytes= 0; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_WRITE); + if (likely(locker != NULL)) + { + bytes= str ? strlen(str) : 0; + PSI_server->start_file_wait(locker, bytes, src_file, src_line); + } + } +#endif + result= fputs(str, file->m_file); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, bytes); +#endif + return result; +} + +static inline int +inline_mysql_file_fputc( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + char c, MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_WRITE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 1, src_file, src_line); + } +#endif + result= fputc(c, file->m_file); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 1); +#endif + return result; +} + +static inline int +inline_mysql_file_fprintf(MYSQL_FILE *file, const char *format, ...) +{ + /* + TODO: figure out how to pass src_file and src_line from the caller. + */ + int result; + va_list args; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_WRITE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, __FILE__, __LINE__); + } +#endif + va_start(args, format); + result= vfprintf(file->m_file, format, args); + va_end(args); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) result); +#endif + return result; +} + +static inline int +inline_mysql_file_vfprintf( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, const char *format, va_list args) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_WRITE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= vfprintf(file->m_file, format, args); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) result); +#endif + return result; +} + +static inline int +inline_mysql_file_fflush( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_FLUSH); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= fflush(file->m_file); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline int inline_mysql_file_feof(MYSQL_FILE *file) +{ + /* Not instrumented, there is no wait involved */ + return feof(file->m_file); +} + +static inline int +inline_mysql_file_fstat( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + int filenr, MY_STAT *stat_area, myf flags) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(filenr, + PSI_FILE_FSTAT); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_fstat(filenr, stat_area, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline MY_STAT * +inline_mysql_file_stat( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *path, MY_STAT *stat_area, myf flags) +{ + MY_STAT *result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_STAT, + path, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_open_wait(locker, src_file, src_line); + } +#endif + result= my_stat(path, stat_area, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline int +inline_mysql_file_chsize( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, my_off_t newlength, int filler, myf flags) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, + PSI_FILE_CHSIZE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) newlength, src_file, + src_line); + } +#endif + result= my_chsize(file, newlength, filler, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) newlength); +#endif + return result; +} + +static inline MYSQL_FILE* +inline_mysql_file_fopen( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int flags, myf myFlags) +{ + MYSQL_FILE *that; + that= (MYSQL_FILE*) my_malloc(sizeof(MYSQL_FILE), MYF(MY_WME)); + if (likely(that != NULL)) + { + that->m_psi= NULL; + { +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker + (key, PSI_FILE_STREAM_OPEN, filename, that); + if (likely(locker != NULL)) + that->m_psi= PSI_server->start_file_open_wait(locker, src_file, + src_line); + } +#endif + that->m_file= my_fopen(filename, flags, myFlags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_open_wait(locker); +#endif + if (unlikely(that->m_file == NULL)) + { + my_free(that, MYF(0)); + return NULL; + } + } + } + return that; +} + +static inline int +inline_mysql_file_fclose( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, myf flags) +{ + int result= 0; + if (likely(file != NULL)) + { +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + DBUG_ASSERT(file != NULL); + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_STREAM_CLOSE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_fclose(file->m_file, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + my_free(file, MYF(0)); + } + return result; +} + +static inline size_t +inline_mysql_file_fread( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, uchar *buffer, size_t count, myf flags) +{ + size_t result= 0; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_READ); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, count, src_file, src_line); + } +#endif + result= my_fread(file->m_file, buffer, count, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + { + size_t bytes_read; + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_server->end_file_wait(locker, bytes_read); + } +#endif + return result; +} + +static inline size_t +inline_mysql_file_fwrite( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, const uchar *buffer, size_t count, myf flags) +{ + size_t result= 0; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_WRITE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, count, src_file, src_line); + } +#endif + result= my_fwrite(file->m_file, buffer, count, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + { + size_t bytes_written; + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_server->end_file_wait(locker, bytes_written); + } +#endif + return result; +} + +static inline my_off_t +inline_mysql_file_fseek( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, my_off_t pos, int whence, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_SEEK); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_fseek(file->m_file, pos, whence, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline my_off_t +inline_mysql_file_ftell( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + MYSQL_FILE *file, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server && file->m_psi)) + { + locker= PSI_server->get_thread_file_stream_locker(file->m_psi, + PSI_FILE_TELL); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_ftell(file->m_file, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline File +inline_mysql_file_create( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int create_flags, int access_flags, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_CREATE, + filename, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_open_wait(locker, src_file, src_line); + } +#endif + file= my_create(filename, create_flags, access_flags, myFlags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_open_wait_and_bind_to_descriptor(locker, file); +#endif + return file; +} + +static inline File +inline_mysql_file_create_temp( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, +#endif + char *to, const char *dir, const char *pfx, int mode, myf myFlags) +{ + File file; + /* + TODO: This event is instrumented, but not timed. + The problem is that the file name is now known + before the create_temp_file call. + */ + file= create_temp_file(to, dir, pfx, mode, myFlags); +#ifdef HAVE_PSI_INTERFACE + if (likely(PSI_server != NULL)) + PSI_server->create_file(key, to, file); +#endif + return file; +} + +static inline File +inline_mysql_file_open( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *filename, int flags, myf myFlags) +{ + File file; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_OPEN, + filename, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_open_wait(locker, src_file, src_line); + } +#endif + file= my_open(filename, flags, myFlags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_open_wait_and_bind_to_descriptor(locker, file); +#endif + return file; +} + +static inline int +inline_mysql_file_close( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, myf flags) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, + PSI_FILE_CLOSE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_close(file, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline size_t +inline_mysql_file_read( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, uchar *buffer, size_t count, myf flags) +{ + size_t result= 0; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, + PSI_FILE_READ); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, count, src_file, src_line); + } +#endif + result= my_read(file, buffer, count, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + { + size_t bytes_read; + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_server->end_file_wait(locker, bytes_read); + } +#endif + return result; +} + +static inline size_t +inline_mysql_file_write( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, const uchar *buffer, size_t count, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, + PSI_FILE_WRITE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, count, src_file, src_line); + } +#endif + result= my_write(file, buffer, count, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + { + size_t bytes_written; + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_server->end_file_wait(locker, bytes_written); + } +#endif + return result; +} + +static inline size_t +inline_mysql_file_pread( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, uchar *buffer, size_t count, my_off_t offset, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, PSI_FILE_READ); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, count, src_file, src_line); + } +#endif + result= my_pread(file, buffer, count, offset, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + { + size_t bytes_read; + if (flags & (MY_NABP | MY_FNABP)) + bytes_read= (result == 0) ? count : 0; + else + bytes_read= (result != MY_FILE_ERROR) ? result : 0; + PSI_server->end_file_wait(locker, bytes_read); + } +#endif + return result; +} + +static inline size_t +inline_mysql_file_pwrite( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, const uchar *buffer, size_t count, my_off_t offset, myf flags) +{ + size_t result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, + PSI_FILE_WRITE); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, count, src_file, src_line); + } +#endif + result= my_pwrite(file, buffer, count, offset, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + { + size_t bytes_written; + if (flags & (MY_NABP | MY_FNABP)) + bytes_written= (result == 0) ? count : 0; + else + bytes_written= (result != MY_FILE_ERROR) ? result : 0; + PSI_server->end_file_wait(locker, bytes_written); + } +#endif + return result; +} + +static inline my_off_t +inline_mysql_file_seek( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, my_off_t pos, int whence, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, PSI_FILE_SEEK); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_seek(file, pos, whence, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline my_off_t +inline_mysql_file_tell( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File file, myf flags) +{ + my_off_t result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(file, PSI_FILE_TELL); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_tell(file, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline int +inline_mysql_file_delete( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *name, myf flags) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_DELETE, + name, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_delete(name, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline int +inline_mysql_file_rename( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *from, const char *to, myf flags) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_RENAME, + to, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_rename(from, to, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline File +inline_mysql_file_create_with_symlink( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *linkname, const char *filename, int create_flags, + int access_flags, myf flags) +{ + File file; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_CREATE, + filename, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_open_wait(locker, src_file, src_line); + } +#endif + file= my_create_with_symlink(linkname, filename, create_flags, access_flags, + flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_open_wait_and_bind_to_descriptor(locker, file); +#endif + return file; +} + +static inline int +inline_mysql_file_delete_with_symlink( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *name, myf flags) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_DELETE, + name, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_delete_with_symlink(name, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline int +inline_mysql_file_rename_with_symlink( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key key, const char *src_file, uint src_line, +#endif + const char *from, const char *to, myf flags) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_name_locker(key, PSI_FILE_RENAME, + to, &locker); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_rename_with_symlink(from, to, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +static inline int +inline_mysql_file_sync( +#ifdef HAVE_PSI_INTERFACE + const char *src_file, uint src_line, +#endif + File fd, myf flags) +{ + int result= 0; +#ifdef HAVE_PSI_INTERFACE + struct PSI_file_locker *locker= NULL; + if (likely(PSI_server != NULL)) + { + locker= PSI_server->get_thread_file_descriptor_locker(fd, PSI_FILE_SYNC); + if (likely(locker != NULL)) + PSI_server->start_file_wait(locker, (size_t) 0, src_file, src_line); + } +#endif + result= my_sync(fd, flags); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_file_wait(locker, (size_t) 0); +#endif + return result; +} + +/** @} (end of group File_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/mysql_thread.h b/include/mysql/psi/mysql_thread.h new file mode 100644 index 00000000000..18c4daa0cf2 --- /dev/null +++ b/include/mysql/psi/mysql_thread.h @@ -0,0 +1,884 @@ +/* Copyright (C) 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef MYSQL_THREAD_H +#define MYSQL_THREAD_H + +/** + @file mysql/psi/mysql_thread.h + Instrumentation helpers for mysys threads, mutexes, + read write locks and conditions. + This header file provides the necessary declarations + to use the mysys thread API with the performance schema instrumentation. + In some compilers (SunStudio), 'static inline' functions, when declared + but not used, are not optimized away (because they are unused) by default, + so that including a static inline function from a header file does + create unwanted dependencies, causing unresolved symbols at link time. + Other compilers, like gcc, optimize these dependencies by default. + + Since the instrumented APIs declared here are wrapper on top + of my_pthread / safemutex / etc APIs, + including mysql/psi/mysql_thread.h assumes that + the dependency on my_pthread and safemutex already exists. +*/ +/* + Note: there are several orthogonal dimensions here. + + Dimension 1: Instrumentation + HAVE_PSI_INTERFACE is defined when the instrumentation is compiled in. + This may happen both in debug or production builds. + + Dimension 2: Debug + SAFE_MUTEX is defined when debug is compiled in. + This may happen both with and without instrumentation. + + Dimension 3: Platform + Mutexes are implemented with one of: + - the pthread library + - fast mutexes + - window apis + This is implemented by various macro definitions in my_pthread.h + + This causes complexity with '#ifdef'-ery that can't be avoided. +*/ + +#include "mysql/psi/psi.h" + +/** + @defgroup Thread_instrumentation Thread Instrumentation + @ingroup Instrumentation_interface + @{ +*/ + +/** + An instrumented mutex structure. + @sa mysql_mutex_t +*/ +struct st_mysql_mutex +{ + /** The real mutex. */ + pthread_mutex_t m_mutex; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_mutex_t interface. + */ + struct PSI_mutex *m_psi; +}; + +/** + Type of an instrumented mutex. + @c mysql_mutex_t is a drop-in replacement for @c pthread_mutex_t. + @sa mysql_mutex_assert_owner + @sa mysql_mutex_assert_not_owner + @sa mysql_mutex_init + @sa mysql_mutex_lock + @sa mysql_mutex_unlock + @sa mysql_mutex_destroy +*/ +typedef struct st_mysql_mutex mysql_mutex_t; + +/** + An instrumented rwlock structure. + @sa mysql_rwlock_t +*/ +struct st_mysql_rwlock +{ + /** The real rwlock */ + rw_lock_t m_rwlock; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_rwlock_t interface. + */ + struct PSI_rwlock *m_psi; +}; + +/** + Type of an instrumented rwlock. + @c mysql_rwlock_t is a drop-in replacement for @c pthread_rwlock_t. + @sa mysql_rwlock_init + @sa mysql_rwlock_rdlock + @sa mysql_rwlock_tryrdlock + @sa mysql_rwlock_wrlock + @sa mysql_rwlock_trywrlock + @sa mysql_rwlock_unlock + @sa mysql_rwlock_destroy +*/ +typedef struct st_mysql_rwlock mysql_rwlock_t; + +/** + An instrumented cond structure. + @sa mysql_cond_t +*/ +struct st_mysql_cond +{ + /** The real condition */ + pthread_cond_t m_cond; + /** + The instrumentation hook. + Note that this hook is not conditionally defined, + for binary compatibility of the @c mysql_cond_t interface. + */ + struct PSI_cond *m_psi; +}; + +/** + Type of an instrumented condition. + @c mysql_cond_t is a drop-in replacement for @c pthread_cond_t. + @sa mysql_cond_init + @sa mysql_cond_wait + @sa mysql_cond_timedwait + @sa mysql_cond_signal + @sa mysql_cond_broadcast + @sa mysql_cond_destroy +*/ +typedef struct st_mysql_cond mysql_cond_t; + +/* + Consider the following code: + static inline void foo() { bar(); } + when foo() is never called. + + With gcc, foo() is a local static function, so the dependencies + are optimized away at compile time, and there is no dependency on bar(). + With other compilers (HP, Sun Studio), the function foo() implementation + is compiled, and bar() needs to be present to link. + + Due to the existing header dependencies in MySQL code, this header file + is sometime used when it is not needed, which in turn cause link failures + on some platforms. + The proper fix would be to cut these extra dependencies in the calling code. + DISABLE_MYSQL_THREAD_H is a work around to limit dependencies. +*/ +#ifndef DISABLE_MYSQL_THREAD_H + +/** + @def mysql_mutex_assert_owner(M) + Wrapper, to use safe_mutex_assert_owner with instrumented mutexes. + @c mysql_mutex_assert_owner is a drop-in replacement + for @c safe_mutex_assert_owner. +*/ +#define mysql_mutex_assert_owner(M) \ + safe_mutex_assert_owner(&(M)->m_mutex) + +/** + @def mysql_mutex_assert_not_owner(M) + Wrapper, to use safe_mutex_assert_not_owner with instrumented mutexes. + @c mysql_mutex_assert_not_owner is a drop-in replacement + for @c safe_mutex_assert_not_owner. +*/ +#define mysql_mutex_assert_not_owner(M) \ + safe_mutex_assert_not_owner(&(M)->m_mutex) + +/** + @def mysql_mutex_init(K, M, A) + Instrumented mutex_init. + @c mysql_mutex_init is a replacement for @c pthread_mutex_init. + @param K The PSI_mutex_key for this instrumented mutex + @param M The mutex to initialize + @param A Mutex attributes +*/ + +#ifdef HAVE_PSI_INTERFACE + #ifdef SAFE_MUTEX + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(K, M, A, __FILE__, __LINE__) + #else + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(K, M, A) + #endif +#else + #ifdef SAFE_MUTEX + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(M, A, __FILE__, __LINE__) + #else + #define mysql_mutex_init(K, M, A) \ + inline_mysql_mutex_init(M, A) + #endif +#endif + +/** + @def mysql_mutex_destroy(M) + Instrumented mutex_destroy. + @c mysql_mutex_destroy is a drop-in replacement + for @c pthread_mutex_destroy. +*/ +#ifdef SAFE_MUTEX + #define mysql_mutex_destroy(M) \ + inline_mysql_mutex_destroy(M, __FILE__, __LINE__) +#else + #define mysql_mutex_destroy(M) \ + inline_mysql_mutex_destroy(M) +#endif + +/** + @def mysql_mutex_lock(M) + Instrumented mutex_lock. + @c mysql_mutex_lock is a drop-in replacement for @c pthread_mutex_lock. + @param M The mutex to lock +*/ + +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_INTERFACE) + #define mysql_mutex_lock(M) \ + inline_mysql_mutex_lock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_lock(M) \ + inline_mysql_mutex_lock(M) +#endif + +/** + @def mysql_mutex_trylock(M) + Instrumented mutex_lock. + @c mysql_mutex_trylock is a drop-in replacement + for @c pthread_mutex_trylock. +*/ + +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_INTERFACE) + #define mysql_mutex_trylock(M) \ + inline_mysql_mutex_trylock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_trylock(M) \ + inline_mysql_mutex_trylock(M) +#endif + +/** + @def mysql_mutex_unlock(M) + Instrumented mutex_unlock. + @c mysql_mutex_unlock is a drop-in replacement for @c pthread_mutex_unlock. +*/ +#ifdef SAFE_MUTEX + #define mysql_mutex_unlock(M) \ + inline_mysql_mutex_unlock(M, __FILE__, __LINE__) +#else + #define mysql_mutex_unlock(M) \ + inline_mysql_mutex_unlock(M) +#endif + +/** + @def mysql_rwlock_init(K, RW) + Instrumented rwlock_init. + @c mysql_rwlock_init is a replacement for @c pthread_rwlock_init. + Note that pthread_rwlockattr_t is not supported in MySQL. + @param K The PSI_rwlock_key for this instrumented rwlock + @param RW The rwlock to initialize +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(K, RW) +#else + #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(RW) +#endif + +/** + @def mysql_rwlock_destroy(RW) + Instrumented rwlock_destroy. + @c mysql_rwlock_destroy is a drop-in replacement + for @c pthread_rwlock_destroy. +*/ +#define mysql_rwlock_destroy(RW) inline_mysql_rwlock_destroy(RW) + +/** + @def mysql_rwlock_rdlock(RW) + Instrumented rwlock_rdlock. + @c mysql_rwlock_rdlock is a drop-in replacement + for @c pthread_rwlock_rdlock. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_rwlock_rdlock(RW) \ + inline_mysql_rwlock_rdlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_rdlock(RW) \ + inline_mysql_rwlock_rdlock(RW) +#endif + +/** + @def mysql_rwlock_wrlock(RW) + Instrumented rwlock_wrlock. + @c mysql_rwlock_wrlock is a drop-in replacement + for @c pthread_rwlock_wrlock. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_rwlock_wrlock(RW) \ + inline_mysql_rwlock_wrlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_wrlock(RW) \ + inline_mysql_rwlock_wrlock(RW) +#endif + +/** + @def mysql_rwlock_tryrdlock(RW) + Instrumented rwlock_tryrdlock. + @c mysql_rwlock_tryrdlock is a drop-in replacement + for @c pthread_rwlock_tryrdlock. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_rwlock_tryrdlock(RW) \ + inline_mysql_rwlock_tryrdlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_tryrdlock(RW) \ + inline_mysql_rwlock_tryrdlock(RW) +#endif + +/** + @def mysql_rwlock_trywrlock(RW) + Instrumented rwlock_trywrlock. + @c mysql_rwlock_trywrlock is a drop-in replacement + for @c pthread_rwlock_trywrlock. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_rwlock_trywrlock(RW) \ + inline_mysql_rwlock_trywrlock(RW, __FILE__, __LINE__) +#else + #define mysql_rwlock_trywrlock(RW) \ + inline_mysql_rwlock_trywrlock(RW) +#endif + +/** + @def mysql_rwlock_unlock(RW) + Instrumented rwlock_unlock. + @c mysql_rwlock_unlock is a drop-in replacement + for @c pthread_rwlock_unlock. +*/ +#define mysql_rwlock_unlock(RW) inline_mysql_rwlock_unlock(RW) + +/** + @def mysql_cond_init(K, C, A) + Instrumented rwlock_init. + @c mysql_cond_init is a replacement for @c pthread_cond_init. + @param C The cond to initialize + @param K The PSI_cond_key for this instrumented cond + @param A Condition attributes +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_cond_init(K, C, A) inline_mysql_cond_init(K, C, A) +#else + #define mysql_cond_init(K, C, A) inline_mysql_cond_init(C, A) +#endif + +/** + @def mysql_cond_destroy(C) + Instrumented cond_destroy. + @c mysql_cond_destroy is a drop-in replacement for @c pthread_cond_destroy. +*/ +#define mysql_cond_destroy(C) inline_mysql_cond_destroy(C) + +/** + @def mysql_cond_wait(C) + Instrumented cond_wait. + @c mysql_cond_wait is a drop-in replacement for @c pthread_cond_wait. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_cond_wait(C, M) \ + inline_mysql_cond_wait(C, M, __FILE__, __LINE__) +#else + #define mysql_cond_wait(C, M) \ + inline_mysql_cond_wait(C, M) +#endif + +/** + @def mysql_cond_timedwait(C, M, W) + Instrumented cond_timedwait. + @c mysql_cond_timedwait is a drop-in replacement + for @c pthread_cond_timedwait. +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_cond_timedwait(C, M, W) \ + inline_mysql_cond_timedwait(C, M, W, __FILE__, __LINE__) +#else + #define mysql_cond_timedwait(C, M, W) \ + inline_mysql_cond_timedwait(C, M, W) +#endif + +/** + @def mysql_cond_signal(C) + Instrumented cond_signal. + @c mysql_cond_signal is a drop-in replacement for @c pthread_cond_signal. +*/ +#define mysql_cond_signal(C) inline_mysql_cond_signal(C) + +/** + @def mysql_cond_broadcast(C) + Instrumented cond_broadcast. + @c mysql_cond_broadcast is a drop-in replacement + for @c pthread_cond_broadcast. +*/ +#define mysql_cond_broadcast(C) inline_mysql_cond_broadcast(C) + + +/** + @def mysql_thread_create(K, P1, P2, P3, P4) + Instrumented pthread_create. + This function creates both the thread instrumentation and a thread. + @c mysql_thread_create is a replacement for @c pthread_create. + The parameter P4 (or, if it is NULL, P1) will be used as the + instrumented thread "indentity". + Providing a P1 / P4 parameter with a different value for each call + will on average improve performances, since this thread identity value + is used internally to randomize access to data and prevent contention. + This is optional, and the improvement is not guaranteed, only statistical. + @param K The PSI_thread_key for this instrumented thread + @param P1 pthread_create parameter 1 + @param P2 pthread_create parameter 2 + @param P3 pthread_create parameter 3 + @param P4 pthread_create parameter 4 +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_thread_create(K, P1, P2, P3, P4) \ + inline_mysql_thread_create(K, P1, P2, P3, P4) +#else + #define mysql_thread_create(K, P1, P2, P3, P4) \ + pthread_create(P1, P2, P3, P4) +#endif + +/** + @def mysql_thread_set_psi_id(I) + Set the thread indentifier for the instrumentation. + @param I The thread identifier +*/ +#ifdef HAVE_PSI_INTERFACE + #define mysql_thread_set_psi_id(I) inline_mysql_thread_set_psi_id(I) +#else + #define mysql_thread_set_psi_id(I) do {} while (0) +#endif + +static inline int inline_mysql_mutex_init( +#ifdef HAVE_PSI_INTERFACE + PSI_mutex_key key, +#endif + mysql_mutex_t *that, + const pthread_mutexattr_t *attr +#ifdef SAFE_MUTEX + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_INTERFACE + that->m_psi= PSI_server ? PSI_server->init_mutex(key, &that->m_mutex) + : NULL; +#else + that->m_psi= NULL; +#endif +#ifdef SAFE_MUTEX + return safe_mutex_init(&that->m_mutex, attr, src_file, src_line); +#else + return pthread_mutex_init(&that->m_mutex, attr); +#endif +} + +static inline int inline_mysql_mutex_destroy( + mysql_mutex_t *that +#ifdef SAFE_MUTEX + , const char *src_file, uint src_line +#endif + ) +{ +#ifdef HAVE_PSI_INTERFACE + if (likely(PSI_server && that->m_psi)) + { + PSI_server->destroy_mutex(that->m_psi); + that->m_psi= NULL; + } +#endif +#ifdef SAFE_MUTEX + return safe_mutex_destroy(&that->m_mutex, src_file, src_line); +#else + return pthread_mutex_destroy(&that->m_mutex); +#endif +} + +static inline int inline_mysql_mutex_lock( + mysql_mutex_t *that +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_mutex_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_mutex_locker(that->m_psi, PSI_MUTEX_LOCK); + if (likely(locker != NULL)) + PSI_server->start_mutex_wait(locker, src_file, src_line); + } +#endif +#ifdef SAFE_MUTEX + result= safe_mutex_lock(&that->m_mutex, FALSE, src_file, src_line); +#else + result= pthread_mutex_lock(&that->m_mutex); +#endif +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_mutex_wait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_mutex_trylock( + mysql_mutex_t *that +#if defined(SAFE_MUTEX) || defined (HAVE_PSI_INTERFACE) + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_mutex_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_mutex_locker(that->m_psi, PSI_MUTEX_TRYLOCK); + if (likely(locker != NULL)) + PSI_server->start_mutex_wait(locker, src_file, src_line); + } +#endif +#ifdef SAFE_MUTEX + result= safe_mutex_lock(&that->m_mutex, TRUE, src_file, src_line); +#else + result= pthread_mutex_trylock(&that->m_mutex); +#endif +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_mutex_wait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_mutex_unlock( + mysql_mutex_t *that +#ifdef SAFE_MUTEX + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_thread *thread; + if (likely(PSI_server && that->m_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->unlock_mutex(thread, that->m_psi); + } +#endif +#ifdef SAFE_MUTEX + result= safe_mutex_unlock(&that->m_mutex, src_file, src_line); +#else + result= pthread_mutex_unlock(&that->m_mutex); +#endif + return result; +} + +static inline int inline_mysql_rwlock_init( +#ifdef HAVE_PSI_INTERFACE + PSI_rwlock_key key, +#endif + mysql_rwlock_t *that) +{ +#ifdef HAVE_PSI_INTERFACE + that->m_psi= (PSI_server ? PSI_server->init_rwlock(key, &that->m_rwlock) + : NULL); +#else + that->m_psi= NULL; +#endif + /* + pthread_rwlockattr_t is not used in MySQL. + */ + return my_rwlock_init(&that->m_rwlock, NULL); +} + +static inline int inline_mysql_rwlock_destroy( + mysql_rwlock_t *that) +{ +#ifdef HAVE_PSI_INTERFACE + if (likely(PSI_server && that->m_psi)) + { + PSI_server->destroy_rwlock(that->m_psi); + that->m_psi= NULL; + } +#endif + return rwlock_destroy(&that->m_rwlock); +} + +static inline int inline_mysql_rwlock_rdlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_rwlock_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_rwlock_locker(that->m_psi, + PSI_RWLOCK_READLOCK); + if (likely(locker != NULL)) + PSI_server->start_rwlock_rdwait(locker, src_file, src_line); + } +#endif + result= rw_rdlock(&that->m_rwlock); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_rwlock_rdwait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_rwlock_wrlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_rwlock_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_rwlock_locker(that->m_psi, + PSI_RWLOCK_WRITELOCK); + if (likely(locker != NULL)) + PSI_server->start_rwlock_wrwait(locker, src_file, src_line); + } +#endif + result= rw_wrlock(&that->m_rwlock); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_rwlock_wrwait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_rwlock_tryrdlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_rwlock_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_rwlock_locker(that->m_psi, + PSI_RWLOCK_TRYREADLOCK); + if (likely(locker != NULL)) + PSI_server->start_rwlock_rdwait(locker, src_file, src_line); + } +#endif + result= rw_tryrdlock(&that->m_rwlock); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_rwlock_rdwait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_rwlock_trywrlock( + mysql_rwlock_t *that +#ifdef HAVE_PSI_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_rwlock_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_rwlock_locker(that->m_psi, + PSI_RWLOCK_TRYWRITELOCK); + if (likely(locker != NULL)) + PSI_server->start_rwlock_wrwait(locker, src_file, src_line); + } +#endif + result= rw_trywrlock(&that->m_rwlock); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_rwlock_wrwait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_rwlock_unlock( + mysql_rwlock_t *that) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_thread *thread; + if (likely(PSI_server && that->m_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->unlock_rwlock(thread, that->m_psi); + } +#endif + result= rw_unlock(&that->m_rwlock); + return result; +} + +static inline int inline_mysql_cond_init( +#ifdef HAVE_PSI_INTERFACE + PSI_cond_key key, +#endif + mysql_cond_t *that, + const pthread_condattr_t *attr) +{ +#ifdef HAVE_PSI_INTERFACE + that->m_psi= (PSI_server ? PSI_server->init_cond(key, &that->m_cond) + : NULL); +#else + that->m_psi= NULL; +#endif + return pthread_cond_init(&that->m_cond, attr); +} + +static inline int inline_mysql_cond_destroy( + mysql_cond_t *that) +{ +#ifdef HAVE_PSI_INTERFACE + if (likely(PSI_server && that->m_psi)) + { + PSI_server->destroy_cond(that->m_psi); + that->m_psi= NULL; + } +#endif + return pthread_cond_destroy(&that->m_cond); +} + +static inline int inline_mysql_cond_wait( + mysql_cond_t *that, + mysql_mutex_t *mutex +#ifdef HAVE_PSI_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_cond_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_cond_locker(that->m_psi, mutex->m_psi, + PSI_COND_WAIT); + if (likely(locker != NULL)) + PSI_server->start_cond_wait(locker, src_file, src_line); + } +#endif + result= pthread_cond_wait(&that->m_cond, &mutex->m_mutex); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_cond_wait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_cond_timedwait( + mysql_cond_t *that, + mysql_mutex_t *mutex, + struct timespec *abstime +#ifdef HAVE_PSI_INTERFACE + , const char *src_file, uint src_line +#endif + ) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_cond_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_cond_locker(that->m_psi, mutex->m_psi, + PSI_COND_TIMEDWAIT); + if (likely(locker != NULL)) + PSI_server->start_cond_wait(locker, src_file, src_line); + } +#endif + result= pthread_cond_timedwait(&that->m_cond, &mutex->m_mutex, abstime); +#ifdef HAVE_PSI_INTERFACE + if (likely(locker != NULL)) + PSI_server->end_cond_wait(locker, result); +#endif + return result; +} + +static inline int inline_mysql_cond_signal( + mysql_cond_t *that) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_thread *thread; + if (likely(PSI_server && that->m_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->signal_cond(thread, that->m_psi); + } +#endif + result= pthread_cond_signal(&that->m_cond); + return result; +} + +static inline int inline_mysql_cond_broadcast( + mysql_cond_t *that) +{ + int result; +#ifdef HAVE_PSI_INTERFACE + struct PSI_thread *thread; + if (likely(PSI_server && that->m_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->broadcast_cond(thread, that->m_psi); + } +#endif + result= pthread_cond_broadcast(&that->m_cond); + return result; +} + +#ifdef HAVE_PSI_INTERFACE +static inline int inline_mysql_thread_create( + PSI_thread_key key, + pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg) +{ + int result; + if (likely(PSI_server != NULL)) + result= PSI_server->spawn_thread(key, thread, attr, start_routine, arg); + else + result= pthread_create(thread, attr, start_routine, arg); + return result; +} + +static inline void inline_mysql_thread_set_psi_id(ulong id) +{ + if (likely(PSI_server != NULL)) + { + struct PSI_thread *psi= PSI_server->get_thread(); + if (likely(psi != NULL)) + PSI_server->set_thread_id(psi, id); + } +} +#endif + +#endif /* DISABLE_MYSQL_THREAD_H */ + +/** @} (end of group Thread_instrumentation) */ + +#endif + diff --git a/include/mysql/psi/psi.h b/include/mysql/psi/psi.h new file mode 100644 index 00000000000..a9277cd18bd --- /dev/null +++ b/include/mysql/psi/psi.h @@ -0,0 +1,1086 @@ +/* Copyright (C) 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H +#define MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H + +#ifndef _global_h +/* + Make sure a .c or .cc file contains an include to my_global.h first. + When this include is missing, all the #ifdef HAVE_XXX have no effect, + and the resulting binary won't build, or won't link, + or will crash at runtime + since various structures will have different binary definitions. +*/ +#error "You must include my_global.h in the code for the build to be correct." +#endif + +C_MODE_START + +/** + @file mysql/psi/psi.h + Performance schema instrumentation interface. + + @defgroup Instrumentation_interface Instrumentation Interface + @ingroup Performance_schema + @{ +*/ + +/** + Interface for an instrumented mutex. + This is an opaque structure. +*/ +struct PSI_mutex; + +/** + Interface for an instrumented rwlock. + This is an opaque structure. +*/ +struct PSI_rwlock; + +/** + Interface for an instrumented condition. + This is an opaque structure. +*/ +struct PSI_cond; + +/** + Interface for an instrumented table share. + This is an opaque structure. +*/ +struct PSI_table_share; + +/** + Interface for an instrumented table handle. + This is an opaque structure. +*/ +struct PSI_table; + +/** + Interface for an instrumented thread. + This is an opaque structure. +*/ +struct PSI_thread; + +/** + Interface for an instrumented file handle. + This is an opaque structure. +*/ +struct PSI_file; + +/** Entry point for the performance schema interface. */ +struct PSI_bootstrap +{ + /** + ABI interface finder. + Calling this method with an interface version number returns either + an instance of the ABI for this version, or NULL. + @param version the interface version number to find + @return a versioned interface (PSI_v1, PSI_v2 or PSI) + @sa PSI_VERSION_1 + @sa PSI_v1 + @sa PSI_VERSION_2 + @sa PSI_v2 + @sa PSI_CURRENT_VERSION + @sa PSI + */ + void* (*get_interface)(int version); +}; + +#ifdef HAVE_PSI_INTERFACE + +/** + @def PSI_VERSION_1 + Performance Schema Interface number for version 1. + This version is supported. +*/ +#define PSI_VERSION_1 1 + +/** + @def PSI_VERSION_2 + Performance Schema Interface number for version 2. + This version is not implemented, it's a placeholder. +*/ +#define PSI_VERSION_2 2 + +/** + @def PSI_CURRENT_VERSION + Performance Schema Interface number for the most recent version. + The most current version is @c PSI_VERSION_1 +*/ +#define PSI_CURRENT_VERSION 1 + +#ifndef USE_PSI_2 +#ifndef USE_PSI_1 +#define USE_PSI_1 +#endif +#endif + +/** + Interface for an instrumented mutex operation. + This is an opaque structure. +*/ +struct PSI_mutex_locker; + +/** + Interface for an instrumented rwlock operation. + This is an opaque structure. +*/ + +struct PSI_rwlock_locker; +/** + Interface for an instrumented condition operation. + This is an opaque structure. +*/ + +struct PSI_cond_locker; + +/** + Interface for an instrumented file operation. + This is an opaque structure. +*/ +struct PSI_file_locker; + +/** Operation performed on an instrumented mutex. */ +enum PSI_mutex_operation +{ + /** Lock. */ + PSI_MUTEX_LOCK= 0, + /** Lock attempt. */ + PSI_MUTEX_TRYLOCK= 1 +}; + +/** Operation performed on an instrumented rwlock. */ +enum PSI_rwlock_operation +{ + /** Read lock. */ + PSI_RWLOCK_READLOCK= 0, + /** Write lock. */ + PSI_RWLOCK_WRITELOCK= 1, + /** Read lock attempt. */ + PSI_RWLOCK_TRYREADLOCK= 2, + /** Write lock attempt. */ + PSI_RWLOCK_TRYWRITELOCK= 3 +}; + +/** Operation performed on an instrumented condition. */ +enum PSI_cond_operation +{ + /** Wait. */ + PSI_COND_WAIT= 0, + /** Wait, with timeout. */ + PSI_COND_TIMEDWAIT= 1 +}; + +/** Operation performed on an instrumented file. */ +enum PSI_file_operation +{ + /** File creation, as in @c create(). */ + PSI_FILE_CREATE= 0, + /** Temporary file creation, as in @c create_temp_file(). */ + PSI_FILE_CREATE_TMP= 1, + /** File open, as in @c open(). */ + PSI_FILE_OPEN= 2, + /** File open, as in @c fopen(). */ + PSI_FILE_STREAM_OPEN= 3, + /** File close, as in @c close(). */ + PSI_FILE_CLOSE= 4, + /** File close, as in @c fclose(). */ + PSI_FILE_STREAM_CLOSE= 5, + /** + Generic file read, such as @c fgets(), @c fgetc(), @c fread(), @c read(), + @c pread(). + */ + PSI_FILE_READ= 6, + /** + Generic file write, such as @c fputs(), @c fputc(), @c fprintf(), + @c vfprintf(), @c fwrite(), @c write(), @c pwrite(). + */ + PSI_FILE_WRITE= 7, + /** Generic file seek, such as @c fseek() or @c seek(). */ + PSI_FILE_SEEK= 8, + /** Generic file tell, such as @c ftell() or @c tell(). */ + PSI_FILE_TELL= 9, + /** File flush, as in @c fflush(). */ + PSI_FILE_FLUSH= 10, + /** File stat, as in @c stat(). */ + PSI_FILE_STAT= 11, + /** File stat, as in @c fstat(). */ + PSI_FILE_FSTAT= 12, + /** File chsize, as in @c my_chsize(). */ + PSI_FILE_CHSIZE= 13, + /** File delete, such as @c my_delete() or @c my_delete_with_symlink(). */ + PSI_FILE_DELETE= 14, + /** File rename, such as @c my_rename() or @c my_rename_with_symlink(). */ + PSI_FILE_RENAME= 15, + /** File sync, as in @c fsync() or @c my_sync(). */ + PSI_FILE_SYNC= 16 +}; + +/** + Interface for an instrumented table operation. + This is an opaque structure. +*/ +struct PSI_table_locker; + +/** + Instrumented mutex key. + To instrument a mutex, a mutex key must be obtained using @c register_mutex. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_mutex_key; + +/** + Instrumented rwlock key. + To instrument a rwlock, a rwlock key must be obtained + using @c register_rwlock. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_rwlock_key; + +/** + Instrumented cond key. + To instrument a condition, a condition key must be obtained + using @c register_cond. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_cond_key; + +/** + Instrumented thread key. + To instrument a thread, a thread key must be obtained + using @c register_thread. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_thread_key; + +/** + Instrumented file key. + To instrument a file, a file key must be obtained using @c register_file. + Using a zero key always disable the instrumentation. +*/ +typedef unsigned int PSI_file_key; + +/** + @def USE_PSI_1 + Define USE_PSI_1 to use the interface version 1. +*/ + +/** + @def USE_PSI_2 + Define USE_PSI_2 to use the interface version 2. +*/ + +/** + @def HAVE_PSI_1 + Define HAVE_PSI_1 if the interface version 1 needs to be compiled in. +*/ + +/** + @def HAVE_PSI_2 + Define HAVE_PSI_2 if the interface version 2 needs to be compiled in. +*/ + +/** + Global flag. + This flag indicate that an instrumentation point is a global variable, + or a singleton. +*/ +#define PSI_FLAG_GLOBAL (1 << 0) + +#ifdef USE_PSI_1 +#define HAVE_PSI_1 +#endif + +#ifdef HAVE_PSI_1 + +/** + @defgroup Group_PSI_v1 Application Binary Interface, version 1 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Mutex information. + @since PSI_VERSION_1 + This structure is used to register an instrumented mutex. +*/ +struct PSI_mutex_info_v1 +{ + /** + Pointer to the key assigned to the registered mutex. + */ + PSI_mutex_key *m_key; + /** + The name of the mutex to register. + */ + const char *m_name; + /** + The flags of the mutex to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; + +/** + Rwlock information. + @since PSI_VERSION_1 + This structure is used to register an instrumented rwlock. +*/ +struct PSI_rwlock_info_v1 +{ + /** + Pointer to the key assigned to the registered rwlock. + */ + PSI_rwlock_key *m_key; + /** + The name of the rwlock to register. + */ + const char *m_name; + /** + The flags of the rwlock to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; + +/** + Condition information. + @since PSI_VERSION_1 + This structure is used to register an instrumented cond. +*/ +struct PSI_cond_info_v1 +{ + /** + Pointer to the key assigned to the registered cond. + */ + PSI_cond_key *m_key; + /** + The name of the cond to register. + */ + const char *m_name; + /** + The flags of the cond to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; + +/** + Thread instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented thread. +*/ +struct PSI_thread_info_v1 +{ + /** + Pointer to the key assigned to the registered thread. + */ + PSI_thread_key *m_key; + /** + The name of the thread instrument to register. + */ + const char *m_name; + /** + The flags of the thread to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; + +/** + File instrument information. + @since PSI_VERSION_1 + This structure is used to register an instrumented file. +*/ +struct PSI_file_info_v1 +{ + /** + Pointer to the key assigned to the registered file. + */ + PSI_file_key *m_key; + /** + The name of the file instrument to register. + */ + const char *m_name; + /** + The flags of the file instrument to register. + @sa PSI_FLAG_GLOBAL + */ + int m_flags; +}; + +/* Using typedef to make reuse between PSI_v1 and PSI_v2 easier later. */ + +/** + Mutex registration API. + @param category a category name (typically a plugin name) + @param info an array of mutex info to register + @param count the size of the info array +*/ +typedef void (*register_mutex_v1_t) + (const char *category, struct PSI_mutex_info_v1 *info, int count); + +/** + Rwlock registration API. + @param category a category name (typically a plugin name) + @param info an array of rwlock info to register + @param count the size of the info array +*/ +typedef void (*register_rwlock_v1_t) + (const char *category, struct PSI_rwlock_info_v1 *info, int count); + +/** + Cond registration API. + @param category a category name (typically a plugin name) + @param info an array of cond info to register + @param count the size of the info array +*/ +typedef void (*register_cond_v1_t) + (const char *category, struct PSI_cond_info_v1 *info, int count); + +/** + Thread registration API. + @param category a category name (typically a plugin name) + @param info an array of thread info to register + @param count the size of the info array +*/ +typedef void (*register_thread_v1_t) + (const char *category, struct PSI_thread_info_v1 *info, int count); + +/** + File registration API. + @param category a category name (typically a plugin name) + @param info an array of file info to register + @param count the size of the info array +*/ +typedef void (*register_file_v1_t) + (const char *category, struct PSI_file_info_v1 *info, int count); + +/** + Mutex instrumentation initialisation API. + @param key the registered mutex key + @param identity the address of the mutex itself + @return an instrumented mutex +*/ +typedef struct PSI_mutex* (*init_mutex_v1_t) + (PSI_mutex_key key, const void *identity); + +/** + Mutex instrumentation destruction API. + @param mutex the mutex to destroy +*/ +typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex); + +/** + Rwlock instrumentation initialisation API. + @param key the registered rwlock key + @param identity the address of the rwlock itself + @return an instrumented rwlock +*/ +typedef struct PSI_rwlock* (*init_rwlock_v1_t) + (PSI_rwlock_key key, const void *identity); + +/** + Rwlock instrumentation destruction API. + @param rwlock the rwlock to destroy +*/ +typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock); + +/** + Cond instrumentation initialisation API. + @param key the registered key + @param identity the address of the rwlock itself + @return an instrumented cond +*/ +typedef struct PSI_cond* (*init_cond_v1_t) + (PSI_cond_key key, const void *identity); + +/** + Cond instrumentation destruction API. + @param cond the rcond to destroy +*/ +typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond); + +/** + Acquire a table info by name. + @param schema_name name of the table schema + @param schema_name_length length of schema_name + @param table_name name of the table + @param table_name_length length of table_name + @param identity table identity pointer, typically the table share + @return a table info, or NULL if the table is not instrumented +*/ +typedef struct PSI_table_share* (*get_table_share_v1_t) + (const char *schema_name, int schema_name_length, const char *table_name, + int table_name_length, const void *identity); + +/** + Release a table share. + @param info the table share to release +*/ +typedef void (*release_table_share_v1_t)(struct PSI_table_share *share); + +/** + Open an instrumentation table handle. + @param share the table to open + @param identity table handle identity + @return a table handle, or NULL +*/ +typedef struct PSI_table* (*open_table_v1_t) + (struct PSI_table_share *share, const void *identity); + +/** + Close an instrumentation table handle. + Note that the table handle is invalid after this call. + @param table the table handle to close +*/ +typedef void (*close_table_v1_t)(struct PSI_table *table); + +/** + Create a file instrumentation for a created file. + This method does not create the file itself, but is used to notify the + instrumentation interface that a file was just created. + @param key the file instrumentation key for this file + @param name the file name + @param file the file handle +*/ +typedef void (*create_file_v1_t)(PSI_file_key key, const char *name, + File file); + +/** + Spawn a thread. + This method creates a new thread, with instrumentation. + @param key the instrumentation key for this thread + @param thread the resulting thread + @param attr the thread attributes + @param start_routine the thread start routine + @param arg the thread start routine argument +*/ +typedef int (*spawn_thread_v1_t)(PSI_thread_key key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); + +/** + Create instrumentation for a thread. + @param key the registered key + @param identity an address typical of the thread + @return an instrumented thread +*/ +typedef struct PSI_thread* (*new_thread_v1_t) + (PSI_thread_key key, const void *identity, ulong thread_id); + +/** + Assign an id to an instrumented thread. + @param thread the instrumented thread + @param id the id to assign +*/ +typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread, + unsigned long id); + +/** + Get the instrumentation for the running thread. + For this function to return a result, + the thread instrumentation must have been attached to the + running thread using @c set_thread() + @return the instrumentation for the running thread +*/ +typedef struct PSI_thread* (*get_thread_v1_t)(void); + +/** + Attach a thread instrumentation to the running thread. + In case of thread pools, this method should be called when + a worker thread picks a work item and runs it. + Also, this method should be called if the instrumented code does not + keep the pointer returned by @c new_thread() and relies on @c get_thread() + instead. + @param thread the thread instrumentation +*/ +typedef void (*set_thread_v1_t)(struct PSI_thread *thread); + +/** Delete the current thread instrumentation. */ +typedef void (*delete_current_thread_v1_t)(void); + +/** + Get a mutex instrumentation locker. + @param mutex the instrumented mutex to lock + @return a mutex locker, or NULL +*/ +typedef struct PSI_mutex_locker* (*get_thread_mutex_locker_v1_t) + (struct PSI_mutex *mutex, enum PSI_mutex_operation op); + +/** + Get a rwlock instrumentation locker. + @param rwlock the instrumented rwlock to lock + @return a rwlock locker, or NULL +*/ +typedef struct PSI_rwlock_locker* (*get_thread_rwlock_locker_v1_t) + (struct PSI_rwlock *rwlock, enum PSI_rwlock_operation op); + +/** + Get a cond instrumentation locker. + @param cond the instrumented condition to wait on + @param mutex the instrumented mutex associated with the condition + @return a condition locker, or NULL +*/ +typedef struct PSI_cond_locker* (*get_thread_cond_locker_v1_t) + (struct PSI_cond *cond, struct PSI_mutex *mutex, + enum PSI_cond_operation op); + +/** + Get a table instrumentation locker. + @param table the instrumented table to lock + @return a table locker, or NULL +*/ +typedef struct PSI_table_locker* (*get_thread_table_locker_v1_t) + (struct PSI_table *table); + +/** + Get a file instrumentation locker, for opening or creating a file. + @param key the file instrumentation key + @param op the operation to perform + @param name the file name + @param identity a pointer representative of this file. + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t) + (PSI_file_key key, enum PSI_file_operation op, const char *name, + const void *identity); + +/** + Get a file stream instrumentation locker. + @param file the file stream to access + @param op the operation to perform + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_stream_locker_v1_t) + (struct PSI_file *file, enum PSI_file_operation op); + +/** + Get a file instrumentation locker. + @param file the file descriptor to access + @param op the operation to perform + @return a file locker, or NULL +*/ +typedef struct PSI_file_locker* (*get_thread_file_descriptor_locker_v1_t) + (File file, enum PSI_file_operation op); + +/** + Record a mutex instrumentation unlock event. + @param thread the running thread instrumentation + @param mutex the mutex instrumentation +*/ +typedef void (*unlock_mutex_v1_t) + (struct PSI_thread *thread, struct PSI_mutex *mutex); + +/** + Record a rwlock instrumentation unlock event. + @param thread the running thread instrumentation + @param rwlock the rwlock instrumentation +*/ +typedef void (*unlock_rwlock_v1_t) + (struct PSI_thread *thread, struct PSI_rwlock *rwlock); + +/** + Record a condition instrumentation signal event. + @param thread the running thread instrumentation + @param cond the cond instrumentation +*/ +typedef void (*signal_cond_v1_t) + (struct PSI_thread *thread, struct PSI_cond *cond); + +/** + Record a condition instrumentation broadcast event. + @param thread the running thread instrumentation + @param cond the cond instrumentation +*/ +typedef void (*broadcast_cond_v1_t) + (struct PSI_thread *thread, struct PSI_cond *cond); + +/** + Record a mutex instrumentation wait start event. + @param locker a thread locker for the running thread +*/ +typedef void (*start_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, const char *src_file, uint src_line); + +/** + Record a mutex instrumentation wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, int rc); + +/** + Record a rwlock instrumentation read wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for lock, 0 for trylock +*/ +typedef void (*start_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, const char *src_file, uint src_line); + +/** + Record a rwlock instrumentation read wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); + +/** + Record a rwlock instrumentation write wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for lock, 0 for trylock +*/ +typedef void (*start_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, const char *src_file, uint src_line); + +/** + Record a rwlock instrumentation write wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); + +/** + Record a condition instrumentation wait start event. + @param locker a thread locker for the running thread + @param must must block: 1 for wait, 0 for timedwait +*/ +typedef void (*start_cond_wait_v1_t) + (struct PSI_cond_locker *locker, const char *src_file, uint src_line); + +/** + Record a condition instrumentation wait end event. + @param locker a thread locker for the running thread + @param rc the wait operation return code +*/ +typedef void (*end_cond_wait_v1_t) + (struct PSI_cond_locker *locker, int rc); + +/** + Record a table instrumentation wait start event. + @param locker a table locker for the running thread + @param file the source file name + @param line the source line number +*/ +typedef void (*start_table_wait_v1_t) + (struct PSI_table_locker *locker, const char *src_file, uint src_line); + +/** + Record a table instrumentation wait end event. + @param locker a table locker for the running thread +*/ +typedef void (*end_table_wait_v1_t)(struct PSI_table_locker *locker); + +/** + Start a file instrumentation open operation. + @param locker the file locker + @param op the operation to perform + @param src_file the source file name + @param src_line the source line number + @return an instrumented file handle +*/ +typedef struct PSI_file* (*start_file_open_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); + +/** + End a file instrumentation open operation, for file streams. + @param locker the file locker. +*/ +typedef void (*end_file_open_wait_v1_t)(struct PSI_file_locker *locker); + +/** + End a file instrumentation open operation, for non stream files. + @param locker the file locker. + @param file the file number assigned by open() or create() for this file. +*/ +typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file); + +/** + Record a file instrumentation start event. + @param locker a file locker for the running thread + @param op file operation to be performed + @param count the number of bytes requested, or 0 if not applicable + @param src_file the source file name + @param src_line the source line number +*/ +typedef void (*start_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count, + const char *src_file, uint src_line); + +/** + Record a file instrumentation end event. + Note that for file close operations, the instrumented file handle + associated with the file (which was provided to obtain a locker) + is invalid after this call. + @param locker a file locker for the running thread + @param count the number of bytes actually used in the operation, + or 0 if not applicable, or -1 if the operation failed + @sa get_thread_file_name_locker + @sa get_thread_file_stream_locker + @sa get_thread_file_descriptor_locker +*/ +typedef void (*end_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count); + +/** + Performance Schema Interface, version 1. + @since PSI_VERSION_1 +*/ +struct PSI_v1 +{ + /** @sa register_mutex_v1_t. */ + register_mutex_v1_t register_mutex; + /** @sa register_rwlock_v1_t. */ + register_rwlock_v1_t register_rwlock; + /** @sa register_cond_v1_t. */ + register_cond_v1_t register_cond; + /** @sa register_thread_v1_t. */ + register_thread_v1_t register_thread; + /** @sa register_file_v1_t. */ + register_file_v1_t register_file; + /** @sa init_mutex_v1_t. */ + init_mutex_v1_t init_mutex; + /** @sa destroy_mutex_v1_t. */ + destroy_mutex_v1_t destroy_mutex; + /** @sa init_rwlock_v1_t. */ + init_rwlock_v1_t init_rwlock; + /** @sa destroy_rwlock_v1_t. */ + destroy_rwlock_v1_t destroy_rwlock; + /** @sa init_cond_v1_t. */ + init_cond_v1_t init_cond; + /** @sa destroy_cond_v1_t. */ + destroy_cond_v1_t destroy_cond; + /** @sa get_table_share_v1_t. */ + get_table_share_v1_t get_table_share; + /** @sa release_table_share_v1_t. */ + release_table_share_v1_t release_table_share; + /** @sa open_table_v1_t. */ + open_table_v1_t open_table; + /** @sa close_table_v1_t. */ + close_table_v1_t close_table; + /** @sa create_file_v1_t. */ + create_file_v1_t create_file; + /** @sa spawn_thread_v1_t. */ + spawn_thread_v1_t spawn_thread; + /** @sa new_thread_v1_t. */ + new_thread_v1_t new_thread; + /** @sa set_thread_id_v1_t. */ + set_thread_id_v1_t set_thread_id; + /** @sa get_thread_v1_t. */ + get_thread_v1_t get_thread; + /** @sa set_thread_v1_t. */ + set_thread_v1_t set_thread; + /** @sa delete_current_thread_v1_t. */ + delete_current_thread_v1_t delete_current_thread; + /** @sa get_thread_mutex_locker_v1_t. */ + get_thread_mutex_locker_v1_t get_thread_mutex_locker; + /** @sa get_thread_rwlock_locker_v1_t. */ + get_thread_rwlock_locker_v1_t get_thread_rwlock_locker; + /** @sa get_thread_cond_locker_v1_t. */ + get_thread_cond_locker_v1_t get_thread_cond_locker; + /** @sa get_thread_table_locker_v1_t. */ + get_thread_table_locker_v1_t get_thread_table_locker; + /** @sa get_thread_file_name_locker_v1_t. */ + get_thread_file_name_locker_v1_t get_thread_file_name_locker; + /** @sa get_thread_file_stream_locker_v1_t. */ + get_thread_file_stream_locker_v1_t get_thread_file_stream_locker; + /** @sa get_thread_file_descriptor_locker_v1_t. */ + get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker; + /** @sa unlock_mutex_v1_t. */ + unlock_mutex_v1_t unlock_mutex; + /** @sa unlock_rwlock_v1_t. */ + unlock_rwlock_v1_t unlock_rwlock; + /** @sa signal_cond_v1_t. */ + signal_cond_v1_t signal_cond; + /** @sa broadcast_cond_v1_t. */ + broadcast_cond_v1_t broadcast_cond; + /** @sa start_mutex_wait_v1_t. */ + start_mutex_wait_v1_t start_mutex_wait; + /** @sa end_mutex_wait_v1_t. */ + end_mutex_wait_v1_t end_mutex_wait; + /** @sa start_rwlock_rdwait_v1_t. */ + start_rwlock_rdwait_v1_t start_rwlock_rdwait; + /** @sa end_rwlock_rdwait_v1_t. */ + end_rwlock_rdwait_v1_t end_rwlock_rdwait; + /** @sa start_rwlock_wrwait_v1_t. */ + start_rwlock_wrwait_v1_t start_rwlock_wrwait; + /** @sa end_rwlock_wrwait_v1_t. */ + end_rwlock_wrwait_v1_t end_rwlock_wrwait; + /** @sa start_cond_wait_v1_t. */ + start_cond_wait_v1_t start_cond_wait; + /** @sa end_cond_wait_v1_t. */ + end_cond_wait_v1_t end_cond_wait; + /** @sa start_table_wait_v1_t. */ + start_table_wait_v1_t start_table_wait; + /** @sa end_table_wait_v1_t. */ + end_table_wait_v1_t end_table_wait; + /** @sa start_file_open_wait_v1_t. */ + start_file_open_wait_v1_t start_file_open_wait; + /** @sa end_file_open_wait_v1_t. */ + end_file_open_wait_v1_t end_file_open_wait; + /** @sa end_file_open_wait_and_bind_to_descriptor_v1_t. */ + end_file_open_wait_and_bind_to_descriptor_v1_t + end_file_open_wait_and_bind_to_descriptor; + /** @sa start_file_wait_v1_t. */ + start_file_wait_v1_t start_file_wait; + /** @sa end_file_wait_v1_t. */ + end_file_wait_v1_t end_file_wait; +}; + +/** @} (end of group Group_PSI_v1) */ + +#endif /* HAVE_PSI_1 */ + +#ifdef USE_PSI_2 +#define HAVE_PSI_2 +#endif + +#ifdef HAVE_PSI_2 + +/** + @defgroup Group_PSI_v2 Application Binary Interface, version 2 + @ingroup Instrumentation_interface + @{ +*/ + +/** + Performance Schema Interface, version 2. + This is a placeholder, this interface is not defined yet. + @since PSI_VERSION_2 +*/ +struct PSI_v2 +{ + /** Placeholder */ + int placeholder; + /* ... extended interface ... */ +}; + +/** Placeholder */ +struct PSI_mutex_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_rwlock_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_cond_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_thread_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** Placeholder */ +struct PSI_file_info_v2 +{ + /** Placeholder */ + int placeholder; +}; + +/** @} (end of group Group_PSI_v2) */ + +#endif /* HAVE_PSI_2 */ + +/** + @typedef PSI + The instrumentation interface for the current version. + @sa PSI_CURRENT_VERSION +*/ + +/** + @typedef PSI_mutex_info + The mutex information structure for the current version. +*/ + +/** + @typedef PSI_rwlock_info + The rwlock information structure for the current version. +*/ + +/** + @typedef PSI_cond_info + The cond information structure for the current version. +*/ + +/** + @typedef PSI_thread_info + The thread information structure for the current version. +*/ + +/** + @typedef PSI_file_info + The file information structure for the current version. +*/ + +/* Export the required version */ +#ifdef USE_PSI_1 +typedef struct PSI_v1 PSI; +typedef struct PSI_mutex_info_v1 PSI_mutex_info; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info; +typedef struct PSI_cond_info_v1 PSI_cond_info; +typedef struct PSI_thread_info_v1 PSI_thread_info; +typedef struct PSI_file_info_v1 PSI_file_info; +#endif + +#ifdef USE_PSI_2 +typedef struct PSI_v2 PSI; +typedef struct PSI_mutex_info_v2 PSI_mutex_info; +typedef struct PSI_rwlock_info_v2 PSI_rwlock_info; +typedef struct PSI_cond_info_v2 PSI_cond_info; +typedef struct PSI_thread_info_v2 PSI_thread_info; +typedef struct PSI_file_info_v2 PSI_file_info; +#endif + +#else /* HAVE_PSI_INTERFACE */ + +/** + Dummy structure, used to declare PSI_server when no instrumentation + is available. + The content does not matter, since PSI_server will be NULL. +*/ +struct PSI_none +{ + int opaque; +}; +typedef struct PSI_none PSI; + +#endif /* HAVE_PSI_INTERFACE */ + +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; + +/** @} */ + +C_MODE_END +#endif /* MYSQL_PERFORMANCE_SCHEMA_INTERFACE_H */ + diff --git a/include/mysql/psi/psi_abi_v1.h b/include/mysql/psi/psi_abi_v1.h new file mode 100644 index 00000000000..c9dfd031668 --- /dev/null +++ b/include/mysql/psi/psi_abi_v1.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file mysql/psi/psi_abi_v1.h + ABI check for mysql/psi/psi.h, when using PSI_VERSION_1. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define USE_PSI_1 +#define HAVE_PSI_INTERFACE +#define _global_h +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v1.h.pp b/include/mysql/psi/psi_abi_v1.h.pp new file mode 100644 index 00000000000..aedf28ba694 --- /dev/null +++ b/include/mysql/psi/psi_abi_v1.h.pp @@ -0,0 +1,242 @@ +#include "mysql/psi/psi.h" +C_MODE_START +struct PSI_mutex; +struct PSI_rwlock; +struct PSI_cond; +struct PSI_table_share; +struct PSI_table; +struct PSI_thread; +struct PSI_file; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +struct PSI_mutex_locker; +struct PSI_rwlock_locker; +struct PSI_cond_locker; +struct PSI_file_locker; +enum PSI_mutex_operation +{ + PSI_MUTEX_LOCK= 0, + PSI_MUTEX_TRYLOCK= 1 +}; +enum PSI_rwlock_operation +{ + PSI_RWLOCK_READLOCK= 0, + PSI_RWLOCK_WRITELOCK= 1, + PSI_RWLOCK_TRYREADLOCK= 2, + PSI_RWLOCK_TRYWRITELOCK= 3 +}; +enum PSI_cond_operation +{ + PSI_COND_WAIT= 0, + PSI_COND_TIMEDWAIT= 1 +}; +enum PSI_file_operation +{ + PSI_FILE_CREATE= 0, + PSI_FILE_CREATE_TMP= 1, + PSI_FILE_OPEN= 2, + PSI_FILE_STREAM_OPEN= 3, + PSI_FILE_CLOSE= 4, + PSI_FILE_STREAM_CLOSE= 5, + PSI_FILE_READ= 6, + PSI_FILE_WRITE= 7, + PSI_FILE_SEEK= 8, + PSI_FILE_TELL= 9, + PSI_FILE_FLUSH= 10, + PSI_FILE_STAT= 11, + PSI_FILE_FSTAT= 12, + PSI_FILE_CHSIZE= 13, + PSI_FILE_DELETE= 14, + PSI_FILE_RENAME= 15, + PSI_FILE_SYNC= 16 +}; +struct PSI_table_locker; +typedef unsigned int PSI_mutex_key; +typedef unsigned int PSI_rwlock_key; +typedef unsigned int PSI_cond_key; +typedef unsigned int PSI_thread_key; +typedef unsigned int PSI_file_key; +struct PSI_mutex_info_v1 +{ + PSI_mutex_key *m_key; + const char *m_name; + int m_flags; +}; +struct PSI_rwlock_info_v1 +{ + PSI_rwlock_key *m_key; + const char *m_name; + int m_flags; +}; +struct PSI_cond_info_v1 +{ + PSI_cond_key *m_key; + const char *m_name; + int m_flags; +}; +struct PSI_thread_info_v1 +{ + PSI_thread_key *m_key; + const char *m_name; + int m_flags; +}; +struct PSI_file_info_v1 +{ + PSI_file_key *m_key; + const char *m_name; + int m_flags; +}; +typedef void (*register_mutex_v1_t) + (const char *category, struct PSI_mutex_info_v1 *info, int count); +typedef void (*register_rwlock_v1_t) + (const char *category, struct PSI_rwlock_info_v1 *info, int count); +typedef void (*register_cond_v1_t) + (const char *category, struct PSI_cond_info_v1 *info, int count); +typedef void (*register_thread_v1_t) + (const char *category, struct PSI_thread_info_v1 *info, int count); +typedef void (*register_file_v1_t) + (const char *category, struct PSI_file_info_v1 *info, int count); +typedef struct PSI_mutex* (*init_mutex_v1_t) + (PSI_mutex_key key, const void *identity); +typedef void (*destroy_mutex_v1_t)(struct PSI_mutex *mutex); +typedef struct PSI_rwlock* (*init_rwlock_v1_t) + (PSI_rwlock_key key, const void *identity); +typedef void (*destroy_rwlock_v1_t)(struct PSI_rwlock *rwlock); +typedef struct PSI_cond* (*init_cond_v1_t) + (PSI_cond_key key, const void *identity); +typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond); +typedef struct PSI_table_share* (*get_table_share_v1_t) + (const char *schema_name, int schema_name_length, const char *table_name, + int table_name_length, const void *identity); +typedef void (*release_table_share_v1_t)(struct PSI_table_share *share); +typedef struct PSI_table* (*open_table_v1_t) + (struct PSI_table_share *share, const void *identity); +typedef void (*close_table_v1_t)(struct PSI_table *table); +typedef void (*create_file_v1_t)(PSI_file_key key, const char *name, + File file); +typedef int (*spawn_thread_v1_t)(PSI_thread_key key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); +typedef struct PSI_thread* (*new_thread_v1_t) + (PSI_thread_key key, const void *identity, ulong thread_id); +typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread, + unsigned long id); +typedef struct PSI_thread* (*get_thread_v1_t)(void); +typedef void (*set_thread_v1_t)(struct PSI_thread *thread); +typedef void (*delete_current_thread_v1_t)(void); +typedef struct PSI_mutex_locker* (*get_thread_mutex_locker_v1_t) + (struct PSI_mutex *mutex, enum PSI_mutex_operation op); +typedef struct PSI_rwlock_locker* (*get_thread_rwlock_locker_v1_t) + (struct PSI_rwlock *rwlock, enum PSI_rwlock_operation op); +typedef struct PSI_cond_locker* (*get_thread_cond_locker_v1_t) + (struct PSI_cond *cond, struct PSI_mutex *mutex, + enum PSI_cond_operation op); +typedef struct PSI_table_locker* (*get_thread_table_locker_v1_t) + (struct PSI_table *table); +typedef struct PSI_file_locker* (*get_thread_file_name_locker_v1_t) + (PSI_file_key key, enum PSI_file_operation op, const char *name, + const void *identity); +typedef struct PSI_file_locker* (*get_thread_file_stream_locker_v1_t) + (struct PSI_file *file, enum PSI_file_operation op); +typedef struct PSI_file_locker* (*get_thread_file_descriptor_locker_v1_t) + (File file, enum PSI_file_operation op); +typedef void (*unlock_mutex_v1_t) + (struct PSI_thread *thread, struct PSI_mutex *mutex); +typedef void (*unlock_rwlock_v1_t) + (struct PSI_thread *thread, struct PSI_rwlock *rwlock); +typedef void (*signal_cond_v1_t) + (struct PSI_thread *thread, struct PSI_cond *cond); +typedef void (*broadcast_cond_v1_t) + (struct PSI_thread *thread, struct PSI_cond *cond); +typedef void (*start_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, const char *src_file, uint src_line); +typedef void (*end_mutex_wait_v1_t) + (struct PSI_mutex_locker *locker, int rc); +typedef void (*start_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, const char *src_file, uint src_line); +typedef void (*end_rwlock_rdwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); +typedef void (*start_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, const char *src_file, uint src_line); +typedef void (*end_rwlock_wrwait_v1_t) + (struct PSI_rwlock_locker *locker, int rc); +typedef void (*start_cond_wait_v1_t) + (struct PSI_cond_locker *locker, const char *src_file, uint src_line); +typedef void (*end_cond_wait_v1_t) + (struct PSI_cond_locker *locker, int rc); +typedef void (*start_table_wait_v1_t) + (struct PSI_table_locker *locker, const char *src_file, uint src_line); +typedef void (*end_table_wait_v1_t)(struct PSI_table_locker *locker); +typedef struct PSI_file* (*start_file_open_wait_v1_t) + (struct PSI_file_locker *locker, const char *src_file, uint src_line); +typedef void (*end_file_open_wait_v1_t)(struct PSI_file_locker *locker); +typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t) + (struct PSI_file_locker *locker, File file); +typedef void (*start_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count, + const char *src_file, uint src_line); +typedef void (*end_file_wait_v1_t) + (struct PSI_file_locker *locker, size_t count); +struct PSI_v1 +{ + register_mutex_v1_t register_mutex; + register_rwlock_v1_t register_rwlock; + register_cond_v1_t register_cond; + register_thread_v1_t register_thread; + register_file_v1_t register_file; + init_mutex_v1_t init_mutex; + destroy_mutex_v1_t destroy_mutex; + init_rwlock_v1_t init_rwlock; + destroy_rwlock_v1_t destroy_rwlock; + init_cond_v1_t init_cond; + destroy_cond_v1_t destroy_cond; + get_table_share_v1_t get_table_share; + release_table_share_v1_t release_table_share; + open_table_v1_t open_table; + close_table_v1_t close_table; + create_file_v1_t create_file; + spawn_thread_v1_t spawn_thread; + new_thread_v1_t new_thread; + set_thread_id_v1_t set_thread_id; + get_thread_v1_t get_thread; + set_thread_v1_t set_thread; + delete_current_thread_v1_t delete_current_thread; + get_thread_mutex_locker_v1_t get_thread_mutex_locker; + get_thread_rwlock_locker_v1_t get_thread_rwlock_locker; + get_thread_cond_locker_v1_t get_thread_cond_locker; + get_thread_table_locker_v1_t get_thread_table_locker; + get_thread_file_name_locker_v1_t get_thread_file_name_locker; + get_thread_file_stream_locker_v1_t get_thread_file_stream_locker; + get_thread_file_descriptor_locker_v1_t get_thread_file_descriptor_locker; + unlock_mutex_v1_t unlock_mutex; + unlock_rwlock_v1_t unlock_rwlock; + signal_cond_v1_t signal_cond; + broadcast_cond_v1_t broadcast_cond; + start_mutex_wait_v1_t start_mutex_wait; + end_mutex_wait_v1_t end_mutex_wait; + start_rwlock_rdwait_v1_t start_rwlock_rdwait; + end_rwlock_rdwait_v1_t end_rwlock_rdwait; + start_rwlock_wrwait_v1_t start_rwlock_wrwait; + end_rwlock_wrwait_v1_t end_rwlock_wrwait; + start_cond_wait_v1_t start_cond_wait; + end_cond_wait_v1_t end_cond_wait; + start_table_wait_v1_t start_table_wait; + end_table_wait_v1_t end_table_wait; + start_file_open_wait_v1_t start_file_open_wait; + end_file_open_wait_v1_t end_file_open_wait; + end_file_open_wait_and_bind_to_descriptor_v1_t + end_file_open_wait_and_bind_to_descriptor; + start_file_wait_v1_t start_file_wait; + end_file_wait_v1_t end_file_wait; +}; +typedef struct PSI_v1 PSI; +typedef struct PSI_mutex_info_v1 PSI_mutex_info; +typedef struct PSI_rwlock_info_v1 PSI_rwlock_info; +typedef struct PSI_cond_info_v1 PSI_cond_info; +typedef struct PSI_thread_info_v1 PSI_thread_info; +typedef struct PSI_file_info_v1 PSI_file_info; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/mysql/psi/psi_abi_v2.h b/include/mysql/psi/psi_abi_v2.h new file mode 100644 index 00000000000..e720c4c2b7c --- /dev/null +++ b/include/mysql/psi/psi_abi_v2.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file mysql/psi/psi_abi_v1.h + ABI check for mysql/psi/psi.h, when using PSI_VERSION_2. + This file is only used to automate detection of changes between versions. + Do not include this file, include mysql/psi/psi.h instead. +*/ +#define USE_PSI_2 +#define HAVE_PSI_INTERFACE +#define _global_h +#include "mysql/psi/psi.h" + diff --git a/include/mysql/psi/psi_abi_v2.h.pp b/include/mysql/psi/psi_abi_v2.h.pp new file mode 100644 index 00000000000..b32415a59b4 --- /dev/null +++ b/include/mysql/psi/psi_abi_v2.h.pp @@ -0,0 +1,92 @@ +#include "mysql/psi/psi.h" +C_MODE_START +struct PSI_mutex; +struct PSI_rwlock; +struct PSI_cond; +struct PSI_table_share; +struct PSI_table; +struct PSI_thread; +struct PSI_file; +struct PSI_bootstrap +{ + void* (*get_interface)(int version); +}; +struct PSI_mutex_locker; +struct PSI_rwlock_locker; +struct PSI_cond_locker; +struct PSI_file_locker; +enum PSI_mutex_operation +{ + PSI_MUTEX_LOCK= 0, + PSI_MUTEX_TRYLOCK= 1 +}; +enum PSI_rwlock_operation +{ + PSI_RWLOCK_READLOCK= 0, + PSI_RWLOCK_WRITELOCK= 1, + PSI_RWLOCK_TRYREADLOCK= 2, + PSI_RWLOCK_TRYWRITELOCK= 3 +}; +enum PSI_cond_operation +{ + PSI_COND_WAIT= 0, + PSI_COND_TIMEDWAIT= 1 +}; +enum PSI_file_operation +{ + PSI_FILE_CREATE= 0, + PSI_FILE_CREATE_TMP= 1, + PSI_FILE_OPEN= 2, + PSI_FILE_STREAM_OPEN= 3, + PSI_FILE_CLOSE= 4, + PSI_FILE_STREAM_CLOSE= 5, + PSI_FILE_READ= 6, + PSI_FILE_WRITE= 7, + PSI_FILE_SEEK= 8, + PSI_FILE_TELL= 9, + PSI_FILE_FLUSH= 10, + PSI_FILE_STAT= 11, + PSI_FILE_FSTAT= 12, + PSI_FILE_CHSIZE= 13, + PSI_FILE_DELETE= 14, + PSI_FILE_RENAME= 15, + PSI_FILE_SYNC= 16 +}; +struct PSI_table_locker; +typedef unsigned int PSI_mutex_key; +typedef unsigned int PSI_rwlock_key; +typedef unsigned int PSI_cond_key; +typedef unsigned int PSI_thread_key; +typedef unsigned int PSI_file_key; +struct PSI_v2 +{ + int placeholder; +}; +struct PSI_mutex_info_v2 +{ + int placeholder; +}; +struct PSI_rwlock_info_v2 +{ + int placeholder; +}; +struct PSI_cond_info_v2 +{ + int placeholder; +}; +struct PSI_thread_info_v2 +{ + int placeholder; +}; +struct PSI_file_info_v2 +{ + int placeholder; +}; +typedef struct PSI_v2 PSI; +typedef struct PSI_mutex_info_v2 PSI_mutex_info; +typedef struct PSI_rwlock_info_v2 PSI_rwlock_info; +typedef struct PSI_cond_info_v2 PSI_cond_info; +typedef struct PSI_thread_info_v2 PSI_thread_info; +typedef struct PSI_file_info_v2 PSI_file_info; +extern MYSQL_PLUGIN_IMPORT PSI *PSI_server; +C_MODE_END diff --git a/include/violite.h b/include/violite.h index 3e8e430392b..eed6c46271f 100644 --- a/include/violite.h +++ b/include/violite.h @@ -81,13 +81,19 @@ int vio_errno(Vio*vio); /* Get socket number */ my_socket vio_fd(Vio*vio); /* Remote peer's address and name in text form */ -my_bool vio_peer_addr(Vio* vio, char *buf, uint16 *port); -/* Remotes in_addr */ -void vio_in_addr(Vio *vio, struct in_addr *in); +my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen); my_bool vio_poll_read(Vio *vio, uint timeout); my_bool vio_is_connected(Vio *vio); ssize_t vio_pending(Vio *vio); +my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, int addr_length, + char *ip_string, size_t ip_string_size); + +int vio_getnameinfo(const struct sockaddr *sa, + char *hostname, size_t hostname_size, + char *port, size_t port_size, + int flags); + #ifdef HAVE_OPENSSL #include <openssl/opensslv.h> #if OPENSSL_VERSION_NUMBER < 0x0090700f @@ -154,8 +160,7 @@ void vio_end(void); #define vio_should_retry(vio) (vio)->should_retry(vio) #define vio_was_interrupted(vio) (vio)->was_interrupted(vio) #define vio_close(vio) ((vio)->vioclose)(vio) -#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt) -#define vio_in_addr(vio, in) (vio)->in_addr(vio, in) +#define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen) #define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds) #define vio_poll_read(vio, timeout) (vio)->poll_read(vio, timeout) #define vio_is_connected(vio) (vio)->is_connected(vio) @@ -180,8 +185,9 @@ struct st_vio HANDLE hPipe; my_bool localhost; /* Are we from localhost? */ int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */ - struct sockaddr_in local; /* Local internet address */ - struct sockaddr_in remote; /* Remote internet address */ + struct sockaddr_storage local; /* Local internet address */ + struct sockaddr_storage remote; /* Remote internet address */ + int addrLen; /* Length of remote address */ enum enum_vio_type type; /* Type of connection */ char desc[30]; /* String description */ char *read_buffer; /* buffer for vio_read_buff */ @@ -197,8 +203,8 @@ struct st_vio my_bool (*is_blocking)(Vio*); int (*viokeepalive)(Vio*, my_bool); int (*fastsend)(Vio*); - my_bool (*peer_addr)(Vio*, char *, uint16*); - void (*in_addr)(Vio*, struct in_addr*); + my_bool (*peer_addr)(Vio*, char *, uint16*, size_t); + void (*in_addr)(Vio*, struct sockaddr_storage*); my_bool (*should_retry)(Vio*); my_bool (*was_interrupted)(Vio*); int (*vioclose)(Vio*); diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index f67abfd8ac6..681b6fad1ff 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2004 MySQL AB +# Copyright (C) 2000-2004 MySQL AB, 2008-2009 Sun Microsystems, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 GNU General Public License as @@ -21,7 +21,9 @@ # This file is public domain and comes with NO WARRANTY of any kind target = libmysqlclient.la -target_defs = -DMYSQL_CLIENT_NO_THREADS -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ +target_defs = -DMYSQL_CLIENT_NO_THREADS -DDONT_USE_RAID \ + -DDISABLE_MYSQL_THREAD_H @LIB_EXTRA_CCFLAGS@ + LIBS = @CLIENT_LIBS@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ $(openssl_includes) @ZLIB_INCLUDES@ diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index acc709bfb89..b626d3343ce 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2004 MySQL AB +# Copyright (C) 2000-2004 MySQL AB, 2008-2009 Sun Microsystems, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 GNU General Public License as @@ -68,7 +68,8 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ mf_iocache2.lo my_seek.lo my_sleep.lo \ my_pread.lo mf_cache.lo md5.lo sha1.lo \ my_getopt.lo my_gethostbyname.lo my_port.lo \ - my_rename.lo my_chsize.lo my_sync.lo my_getsystime.lo + my_rename.lo my_chsize.lo my_sync.lo \ + my_getsystime.lo my_symlink2.lo mf_same.lo sqlobjects = net.lo sql_cmn_objects = pack.lo client.lo my_time.lo diff --git a/mysql-test/include/check_ipv6.inc b/mysql-test/include/check_ipv6.inc new file mode 100644 index 00000000000..14d04b11e83 --- /dev/null +++ b/mysql-test/include/check_ipv6.inc @@ -0,0 +1,14 @@ +# Check if ipv6 is available. If not, server is crashing (see BUG#48915). +--disable_query_log +--disable_abort_on_error +connect (checkcon123456789,::1,root,,test); +if($mysql_errno) +{ +skip wrong IP; +} +connection default; +disconnect checkcon123456789; +--enable_abort_on_error +--enable_query_log +# end check + diff --git a/mysql-test/include/ipv6.inc b/mysql-test/include/ipv6.inc new file mode 100644 index 00000000000..378733dd03a --- /dev/null +++ b/mysql-test/include/ipv6.inc @@ -0,0 +1,22 @@ +eval CREATE USER testuser@'$IPv6' identified by '1234'; +eval GRANT ALL ON test.* TO testuser@'$IPv6'; +eval SHOW GRANTS FOR testuser@'$IPv6'; +# deliver NULL instead of a valid number, see bug#34037 +eval SET @nip= inet_aton('$IPv6'); +SELECT @nip; +SELECT inet_ntoa(@nip); +# delivers a wrong value, see bug#34037 +SELECT USER(); +SELECT current_user(); +--disable_result_log +SHOW PROCESSLIST; +--enable_result_log +connect (con1, $IPv6, root, , test, $MASTER_MYPORT); +connection default; +disconnect con1; +eval REVOKE ALL ON test.* FROM testuser@'$IPv6'; +eval RENAME USER testuser@'$IPv6' to testuser1@'$IPv6'; +eval SET PASSWORD FOR testuser1@'$IPv6' = PASSWORD ('9876'); +SELECT USER(); +eval DROP USER testuser1@'$IPv6'; + diff --git a/mysql-test/include/ipv6_clients.inc b/mysql-test/include/ipv6_clients.inc new file mode 100644 index 00000000000..3f2b35d811a --- /dev/null +++ b/mysql-test/include/ipv6_clients.inc @@ -0,0 +1,7 @@ +--exec $MYSQLADMIN --no-defaults --default-character-set=latin1 -h $IPv6 -P $MASTER_MYPORT -u root ping +--disable_result_log +--exec $MYSQL_CHECK -h $IPv6 -P $MASTER_MYPORT -u root test +--exec $MYSQL_DUMP -h $IPv6 -P $MASTER_MYPORT -u root test +--exec $MYSQL_SHOW -h $IPv6 -P $MASTER_MYPORT -u root +--exec $MYSQL --host=$IPv6 --port=$MASTER_MYPORT --user=root test -e "SELECT current_user();SELECT user();" +--enable_result_log diff --git a/mysql-test/include/rpl_ip_mix.inc b/mysql-test/include/rpl_ip_mix.inc new file mode 100644 index 00000000000..96766e7dbdd --- /dev/null +++ b/mysql-test/include/rpl_ip_mix.inc @@ -0,0 +1,24 @@ +--echo connect (master,$IPv6,root,,test,MASTER_MYPORT); +connect (master,$IPv6,root,,test,$MASTER_MYPORT); +--echo connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT); +--echo connection master; +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +--echo connection slave; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +--echo disconnect slave; +disconnect slave; +--echo disconnect master; +disconnect master; +--echo connection default; +connection default; + diff --git a/mysql-test/include/rpl_ip_mix2.inc b/mysql-test/include/rpl_ip_mix2.inc new file mode 100644 index 00000000000..390c788a461 --- /dev/null +++ b/mysql-test/include/rpl_ip_mix2.inc @@ -0,0 +1,24 @@ +--echo connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT); +--echo connect (slave,$IPv6,root,,test,SLAVE_MYPORT); +connect (slave,$IPv6,root,,test,$SLAVE_MYPORT); +--echo connection master; +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +--echo connection slave; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +--echo disconnect slave; +disconnect slave; +--echo disconnect master; +disconnect master; +--echo connection default; +connection default; + diff --git a/mysql-test/include/rpl_ipv6.inc b/mysql-test/include/rpl_ipv6.inc new file mode 100644 index 00000000000..d2d53a4841a --- /dev/null +++ b/mysql-test/include/rpl_ipv6.inc @@ -0,0 +1,22 @@ +--echo connect (master,$IPv6,root,,test,MASTER_MYPORT); +connect (master,$IPv6,root,,test,$MASTER_MYPORT); +--echo connect (slave,$IPv6,root,,test,SLAVE_MYPORT); +connect (slave,$IPv6,root,,test,$SLAVE_MYPORT); +--echo connection master; +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +--echo connection slave; +connection slave; +reset slave; +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +--echo disconnect slave; +disconnect slave; +--echo disconnect master; +disconnect master; +--echo connection default; +connection default; + diff --git a/mysql-test/r/ipv4_as_ipv6.result b/mysql-test/r/ipv4_as_ipv6.result new file mode 100644 index 00000000000..8523dc82f02 --- /dev/null +++ b/mysql-test/r/ipv4_as_ipv6.result @@ -0,0 +1,179 @@ +=============Test of '127.0.0.1' (IPv4) =========================== +mysqld is alive +CREATE USER testuser@'127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'127.0.0.1'; +SHOW GRANTS FOR testuser@'127.0.0.1'; +Grants for testuser@127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'127.0.0.1' +SET @nip= inet_aton('127.0.0.1'); +SELECT @nip; +@nip +2130706433 +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +127.0.0.1 +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'127.0.0.1'; +RENAME USER testuser@'127.0.0.1' to testuser1@'127.0.0.1'; +SET PASSWORD FOR testuser1@'127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'127.0.0.1'; +=============Test of '0:0:0:0:0:FFFF:127.0.0.1' =================== +mysqld is alive +CREATE USER testuser@'0:0:0:0:0:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0:0:0:0:0:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0:0:0:0:0:FFFF:127.0.0.1'; +Grants for testuser@0:0:0:0:0:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0:0:0:0:0:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0:0:0:0:FFFF:127.0.0.1' +SET @nip= inet_aton('0:0:0:0:0:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0:0:0:0:0:FFFF:127.0.0.1'; +RENAME USER testuser@'0:0:0:0:0:FFFF:127.0.0.1' to testuser1@'0:0:0:0:0:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0:0:0:0:0:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0:0:0:0:0:FFFF:127.0.0.1'; +=============Test of '0000:0000:0000:0000:0000:FFFF:127.0.0.1' ==== +mysqld is alive +CREATE USER testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +Grants for testuser@0000:0000:0000:0000:0000:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' +SET @nip= inet_aton('0000:0000:0000:0000:0000:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +RENAME USER testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' to testuser1@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +=============Test of '0:0000:0000:0:0000:FFFF:127.0.0.1' ==== +mysqld is alive +CREATE USER testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +Grants for testuser@0:0000:0000:0:0000:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0:0000:0000:0:0000:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0000:0000:0:0000:FFFF:127.0.0.1' +SET @nip= inet_aton('0:0000:0000:0:0000:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +RENAME USER testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1' to testuser1@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0:0000:0000:0:0000:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +=============Test of '0::0000:FFFF:127.0.0.1' ==== +mysqld is alive +CREATE USER testuser@'0::0000:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0::0000:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0::0000:FFFF:127.0.0.1'; +Grants for testuser@0::0000:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0::0000:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0::0000:FFFF:127.0.0.1' +SET @nip= inet_aton('0::0000:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0::0000:FFFF:127.0.0.1'; +RENAME USER testuser@'0::0000:FFFF:127.0.0.1' to testuser1@'0::0000:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0::0000:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0::0000:FFFF:127.0.0.1'; +=============Test of '0:0:0:0:0:FFFF:127.0.0.1/96' ================ +=============Test of '::FFFF:127.0.0.1' =========================== +mysqld is alive +CREATE USER testuser@'::FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'::FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'::FFFF:127.0.0.1'; +Grants for testuser@::FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'::FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'::FFFF:127.0.0.1' +SET @nip= inet_aton('::FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'::FFFF:127.0.0.1'; +RENAME USER testuser@'::FFFF:127.0.0.1' to testuser1@'::FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'::FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'::FFFF:127.0.0.1'; +=============Test of '::FFFF:127.0.0.1/96' ======================== +=============Test of '::1' ======================== +connect (con1, ::1, root, , test, MASTER_MYPORT,); +Got one of the listed errors diff --git a/mysql-test/r/ipv4_as_ipv6_win.result b/mysql-test/r/ipv4_as_ipv6_win.result new file mode 100644 index 00000000000..45e23d4d7e6 --- /dev/null +++ b/mysql-test/r/ipv4_as_ipv6_win.result @@ -0,0 +1,32 @@ +=============Test of '127.0.0.1' (IPv4) =========================== +mysqld is alive +CREATE USER testuser@'127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'127.0.0.1'; +SHOW GRANTS FOR testuser@'127.0.0.1'; +Grants for testuser@127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'127.0.0.1' +SET @nip= inet_aton('127.0.0.1'); +SELECT @nip; +@nip +2130706433 +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +127.0.0.1 +SELECT USER(); +USER() +root@127.0.0.1 +SELECT current_user(); +current_user() +root@127.0.0.1 +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'127.0.0.1'; +RENAME USER testuser@'127.0.0.1' to testuser1@'127.0.0.1'; +SET PASSWORD FOR testuser1@'127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@127.0.0.1 +DROP USER testuser1@'127.0.0.1'; +=============Test of '::1' ======================== +connect (con1, ::1, root, , test, MASTER_MYPORT); +Got one of the listed errors diff --git a/mysql-test/r/ipv6.result b/mysql-test/r/ipv6.result new file mode 100644 index 00000000000..566938296a9 --- /dev/null +++ b/mysql-test/r/ipv6.result @@ -0,0 +1,264 @@ +=============Test of '::1' ======================================== +mysqld is alive +CREATE USER testuser@'::1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'::1'; +SHOW GRANTS FOR testuser@'::1'; +Grants for testuser@::1 +GRANT USAGE ON *.* TO 'testuser'@'::1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'::1' +SET @nip= inet_aton('::1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'::1'; +RENAME USER testuser@'::1' to testuser1@'::1'; +SET PASSWORD FOR testuser1@'::1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'::1'; +=============Test of '::1/128' ==================================== +=============Test of '0000:0000:0000:0000:0000:0000:0000:0001' ==== +mysqld is alive +CREATE USER testuser@'0000:0000:0000:0000:0000:0000:0000:0001' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0000:0000:0000:0000:0000:0000:0000:0001'; +SHOW GRANTS FOR testuser@'0000:0000:0000:0000:0000:0000:0000:0001'; +Grants for testuser@0000:0000:0000:0000:0000:0000:0000:0001 +GRANT USAGE ON *.* TO 'testuser'@'0000:0000:0000:0000:0000:0000:0000:0001' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0000:0000:0000:0000:0000:0000:0000:0001' +SET @nip= inet_aton('0000:0000:0000:0000:0000:0000:0000:0001'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0000:0000:0000:0000:0000:0000:0000:0001'; +RENAME USER testuser@'0000:0000:0000:0000:0000:0000:0000:0001' to testuser1@'0000:0000:0000:0000:0000:0000:0000:0001'; +SET PASSWORD FOR testuser1@'0000:0000:0000:0000:0000:0000:0000:0001' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0000:0000:0000:0000:0000:0000:0000:0001'; +=============Test of '0:0:0:0:0:0:0:1' ============================ +mysqld is alive +CREATE USER testuser@'0:0:0:0:0:0:0:1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0:0:0:0:0:0:0:1'; +SHOW GRANTS FOR testuser@'0:0:0:0:0:0:0:1'; +Grants for testuser@0:0:0:0:0:0:0:1 +GRANT USAGE ON *.* TO 'testuser'@'0:0:0:0:0:0:0:1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0:0:0:0:0:0:1' +SET @nip= inet_aton('0:0:0:0:0:0:0:1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0:0:0:0:0:0:0:1'; +RENAME USER testuser@'0:0:0:0:0:0:0:1' to testuser1@'0:0:0:0:0:0:0:1'; +SET PASSWORD FOR testuser1@'0:0:0:0:0:0:0:1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0:0:0:0:0:0:0:1'; +=============Test of '127.0.0.1' (IPv4) =========================== +mysqld is alive +CREATE USER testuser@'127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'127.0.0.1'; +SHOW GRANTS FOR testuser@'127.0.0.1'; +Grants for testuser@127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'127.0.0.1' +SET @nip= inet_aton('127.0.0.1'); +SELECT @nip; +@nip +2130706433 +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +127.0.0.1 +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'127.0.0.1'; +RENAME USER testuser@'127.0.0.1' to testuser1@'127.0.0.1'; +SET PASSWORD FOR testuser1@'127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'127.0.0.1'; +=============Test of '0:0:0:0:0:FFFF:127.0.0.1' =================== +mysqld is alive +CREATE USER testuser@'0:0:0:0:0:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0:0:0:0:0:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0:0:0:0:0:FFFF:127.0.0.1'; +Grants for testuser@0:0:0:0:0:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0:0:0:0:0:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0:0:0:0:FFFF:127.0.0.1' +SET @nip= inet_aton('0:0:0:0:0:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0:0:0:0:0:FFFF:127.0.0.1'; +RENAME USER testuser@'0:0:0:0:0:FFFF:127.0.0.1' to testuser1@'0:0:0:0:0:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0:0:0:0:0:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0:0:0:0:0:FFFF:127.0.0.1'; +=============Test of '0000:0000:0000:0000:0000:FFFF:127.0.0.1' ==== +mysqld is alive +CREATE USER testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +Grants for testuser@0000:0000:0000:0000:0000:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' +SET @nip= inet_aton('0000:0000:0000:0000:0000:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +RENAME USER testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' to testuser1@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +=============Test of '0:0000:0000:0:0000:FFFF:127.0.0.1' ==== +mysqld is alive +CREATE USER testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +Grants for testuser@0:0000:0000:0:0000:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0:0000:0000:0:0000:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0000:0000:0:0000:FFFF:127.0.0.1' +SET @nip= inet_aton('0:0000:0000:0:0000:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +RENAME USER testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1' to testuser1@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0:0000:0000:0:0000:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0:0000:0000:0:0000:FFFF:127.0.0.1'; +=============Test of '0::0000:FFFF:127.0.0.1' ==== +mysqld is alive +CREATE USER testuser@'0::0000:FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0::0000:FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'0::0000:FFFF:127.0.0.1'; +Grants for testuser@0::0000:FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'0::0000:FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0::0000:FFFF:127.0.0.1' +SET @nip= inet_aton('0::0000:FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0::0000:FFFF:127.0.0.1'; +RENAME USER testuser@'0::0000:FFFF:127.0.0.1' to testuser1@'0::0000:FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'0::0000:FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'0::0000:FFFF:127.0.0.1'; +=============Test of '0:0:0:0:0:FFFF:127.0.0.1/96' ================ +=============Test of '::FFFF:127.0.0.1' =========================== +mysqld is alive +CREATE USER testuser@'::FFFF:127.0.0.1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'::FFFF:127.0.0.1'; +SHOW GRANTS FOR testuser@'::FFFF:127.0.0.1'; +Grants for testuser@::FFFF:127.0.0.1 +GRANT USAGE ON *.* TO 'testuser'@'::FFFF:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'::FFFF:127.0.0.1' +SET @nip= inet_aton('::FFFF:127.0.0.1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@localhost +SELECT current_user(); +current_user() +root@localhost +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'::FFFF:127.0.0.1'; +RENAME USER testuser@'::FFFF:127.0.0.1' to testuser1@'::FFFF:127.0.0.1'; +SET PASSWORD FOR testuser1@'::FFFF:127.0.0.1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@localhost +DROP USER testuser1@'::FFFF:127.0.0.1'; +=============Test of '::FFFF:127.0.0.1/96' ======================== diff --git a/mysql-test/r/ipv6_win.result b/mysql-test/r/ipv6_win.result new file mode 100644 index 00000000000..8082e8aa25e --- /dev/null +++ b/mysql-test/r/ipv6_win.result @@ -0,0 +1,88 @@ +=============Test of '::1' ======================================== +mysqld is alive +CREATE USER testuser@'::1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'::1'; +SHOW GRANTS FOR testuser@'::1'; +Grants for testuser@::1 +GRANT USAGE ON *.* TO 'testuser'@'::1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'::1' +SET @nip= inet_aton('::1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@::1 +SELECT current_user(); +current_user() +root@::1 +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'::1'; +RENAME USER testuser@'::1' to testuser1@'::1'; +SET PASSWORD FOR testuser1@'::1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@::1 +DROP USER testuser1@'::1'; +=============Test of '::1/128' ==================================== +=============Test of '0000:0000:0000:0000:0000:0000:0000:0001' ==== +mysqld is alive +CREATE USER testuser@'0000:0000:0000:0000:0000:0000:0000:0001' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0000:0000:0000:0000:0000:0000:0000:0001'; +SHOW GRANTS FOR testuser@'0000:0000:0000:0000:0000:0000:0000:0001'; +Grants for testuser@0000:0000:0000:0000:0000:0000:0000:0001 +GRANT USAGE ON *.* TO 'testuser'@'0000:0000:0000:0000:0000:0000:0000:0001' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0000:0000:0000:0000:0000:0000:0000:0001' +SET @nip= inet_aton('0000:0000:0000:0000:0000:0000:0000:0001'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@::1 +SELECT current_user(); +current_user() +root@::1 +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0000:0000:0000:0000:0000:0000:0000:0001'; +RENAME USER testuser@'0000:0000:0000:0000:0000:0000:0000:0001' to testuser1@'0000:0000:0000:0000:0000:0000:0000:0001'; +SET PASSWORD FOR testuser1@'0000:0000:0000:0000:0000:0000:0000:0001' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@::1 +DROP USER testuser1@'0000:0000:0000:0000:0000:0000:0000:0001'; +=============Test of '0:0:0:0:0:0:0:1' ============================ +mysqld is alive +CREATE USER testuser@'0:0:0:0:0:0:0:1' identified by '1234'; +GRANT ALL ON test.* TO testuser@'0:0:0:0:0:0:0:1'; +SHOW GRANTS FOR testuser@'0:0:0:0:0:0:0:1'; +Grants for testuser@0:0:0:0:0:0:0:1 +GRANT USAGE ON *.* TO 'testuser'@'0:0:0:0:0:0:0:1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF' +GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0:0:0:0:0:0:1' +SET @nip= inet_aton('0:0:0:0:0:0:0:1'); +SELECT @nip; +@nip +NULL +SELECT inet_ntoa(@nip); +inet_ntoa(@nip) +NULL +SELECT USER(); +USER() +root@::1 +SELECT current_user(); +current_user() +root@::1 +SHOW PROCESSLIST; +REVOKE ALL ON test.* FROM testuser@'0:0:0:0:0:0:0:1'; +RENAME USER testuser@'0:0:0:0:0:0:0:1' to testuser1@'0:0:0:0:0:0:0:1'; +SET PASSWORD FOR testuser1@'0:0:0:0:0:0:0:1' = PASSWORD ('9876'); +SELECT USER(); +USER() +root@::1 +DROP USER testuser1@'0:0:0:0:0:0:0:1'; diff --git a/mysql-test/suite/rpl/r/rpl_ip_mix.result b/mysql-test/suite/rpl/r/rpl_ip_mix.result new file mode 100644 index 00000000000..11aa5a46cfa --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ip_mix.result @@ -0,0 +1,164 @@ +#################### IP: ::1 ########################### +connect (master,::1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: No such row +change master to master_host='::1'; +Master-Host: ::1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:0000:0000:0001 ########################### +connect (master,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::1 +change master to master_host='0000:0000:0000:0000:0000:0000:0000:0001'; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:0:0:1 ########################### +connect (master,0:0:0:0:0:0:0:1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0:0:0:0:0:0:1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:FFFF:127.0.0.1 ########################### +connect (master,0:0:0:0:0:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 127.0.0.1 +change master to master_host='0:0:0:0:0:FFFF:127.0.0.1'; +Master-Host: 0:0:0:0:0:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 ########################### +connect (master,0000:0000:0000:0000:0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0:0:0:0:FFFF:127.0.0.1 +change master to master_host='0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +Master-Host: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0000:0000:0:0000:FFFF:127.0.0.1 ########################### +connect (master,0:0000:0000:0:0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 +change master to master_host='0:0000:0000:0:0000:FFFF:127.0.0.1'; +Master-Host: 0:0000:0000:0:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0::0000:FFFF:127.0.0.1 ########################### +connect (master,0::0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0000:0000:0:0000:FFFF:127.0.0.1 +change master to master_host='0::0000:FFFF:127.0.0.1'; +Master-Host: 0::0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::FFFF:127.0.0.1 ########################### +connect (master,::FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0::0000:FFFF:127.0.0.1 +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 mix ####################### +connect (master,::1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/r/rpl_ip_mix2.result b/mysql-test/suite/rpl/r/rpl_ip_mix2.result new file mode 100644 index 00000000000..e5cc3e1621d --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ip_mix2.result @@ -0,0 +1,180 @@ +#################### IP: ::1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: No such row +change master to master_host='::1'; +Master-Host: ::1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::1 +change master to master_host='::1'; +Master-Host: ::1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:0000:0000:0001 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::1 +change master to master_host='0000:0000:0000:0000:0000:0000:0000:0001'; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:0:0:1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0:0:0:0:0:0:1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0:0:0:0:0:0:1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:FFFF:127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0:0:0:0:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 127.0.0.1 +change master to master_host='0:0:0:0:0:FFFF:127.0.0.1'; +Master-Host: 0:0:0:0:0:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0000:0000:0000:0000:0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0:0:0:0:FFFF:127.0.0.1 +change master to master_host='0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +Master-Host: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0000:0000:0:0000:FFFF:127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0000:0000:0:0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 +change master to master_host='0:0000:0000:0:0000:FFFF:127.0.0.1'; +Master-Host: 0:0000:0000:0:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0::0000:FFFF:127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0::0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0000:0000:0:0000:FFFF:127.0.0.1 +change master to master_host='0::0000:FFFF:127.0.0.1'; +Master-Host: 0::0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::FFFF:127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0::0000:FFFF:127.0.0.1 +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 mix ####################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/r/rpl_ip_mix2_win.result b/mysql-test/suite/rpl/r/rpl_ip_mix2_win.result new file mode 100644 index 00000000000..c7cec70ed6c --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ip_mix2_win.result @@ -0,0 +1,84 @@ +#################### IP: ::1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: No such row +change master to master_host='::1'; +Master-Host: ::1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:0000:0000:0001 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::1 +change master to master_host='0000:0000:0000:0000:0000:0000:0000:0001'; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:0:0:1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0:0:0:0:0:0:1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0:0:0:0:0:0:1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 mix ####################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/r/rpl_ip_mix_win.result b/mysql-test/suite/rpl/r/rpl_ip_mix_win.result new file mode 100644 index 00000000000..a1d11e109e5 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ip_mix_win.result @@ -0,0 +1,84 @@ +#################### IP: ::1 ########################### +connect (master,::1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: No such row +change master to master_host='::1'; +Master-Host: ::1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:0000:0000:0001 ########################### +connect (master,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::1 +change master to master_host='0000:0000:0000:0000:0000:0000:0000:0001'; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:0:0:1 ########################### +connect (master,0:0:0:0:0:0:0:1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 0:0:0:0:0:0:0:1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 mix ####################### +connect (master,::1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/r/rpl_ipv4_as_ipv6.result b/mysql-test/suite/rpl/r/rpl_ipv4_as_ipv6.result new file mode 100644 index 00000000000..4168cff1e97 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ipv4_as_ipv6.result @@ -0,0 +1,110 @@ +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:FFFF:127.0.0.1 ########################### +connect (master,0:0:0:0:0:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0:0:0:0:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0:0:0:0:0:FFFF:127.0.0.1'; +Master-Host: 0:0:0:0:0:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 ########################### +connect (master,0000:0000:0000:0000:0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0000:0000:0000:0000:0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +Master-Host: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0000:0000:0:0000:FFFF:127.0.0.1 ########################### +connect (master,0:0000:0000:0:0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0000:0000:0:0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0:0000:0000:0:0000:FFFF:127.0.0.1'; +Master-Host: 0:0000:0000:0:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0::0000:FFFF:127.0.0.1 ########################### +connect (master,0::0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0::0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0::0000:FFFF:127.0.0.1'; +Master-Host: 0::0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::FFFF:127.0.0.1 ########################### +connect (master,::FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/r/rpl_ipv4_as_ipv6_win.result b/mysql-test/suite/rpl/r/rpl_ipv4_as_ipv6_win.result new file mode 100644 index 00000000000..a1e48ea6610 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ipv4_as_ipv6_win.result @@ -0,0 +1,35 @@ +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/r/rpl_ipv6.result b/mysql-test/suite/rpl/r/rpl_ipv6.result new file mode 100644 index 00000000000..f46e60548a6 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ipv6.result @@ -0,0 +1,155 @@ +#################### IP: ::1 ########################### +connect (master,::1,root,,test,MASTER_MYPORT); +connect (slave,::1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='::1'; +Master-Host: ::1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:0000:0000:0001 ########################### +connect (master,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,MASTER_MYPORT); +connect (slave,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0000:0000:0000:0000:0000:0000:0000:0001'; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:0:0:1 ########################### +connect (master,0:0:0:0:0:0:0:1,root,,test,MASTER_MYPORT); +connect (slave,0:0:0:0:0:0:0:1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:FFFF:127.0.0.1 ########################### +connect (master,0:0:0:0:0:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0:0:0:0:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0:0:0:0:0:FFFF:127.0.0.1'; +Master-Host: 0:0:0:0:0:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 ########################### +connect (master,0000:0000:0000:0000:0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0000:0000:0000:0000:0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0000:0000:0000:0000:0000:FFFF:127.0.0.1'; +Master-Host: 0000:0000:0000:0000:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0000:0000:0:0000:FFFF:127.0.0.1 ########################### +connect (master,0:0000:0000:0:0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0:0000:0000:0:0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0:0000:0000:0:0000:FFFF:127.0.0.1'; +Master-Host: 0:0000:0000:0:0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0::0000:FFFF:127.0.0.1 ########################### +connect (master,0::0000:FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,0::0000:FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0::0000:FFFF:127.0.0.1'; +Master-Host: 0::0000:FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::FFFF:127.0.0.1 ########################### +connect (master,::FFFF:127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,::FFFF:127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 mix ####################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='::FFFF:127.0.0.1'; +Master-Host: ::FFFF:127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/r/rpl_ipv6_win.result b/mysql-test/suite/rpl/r/rpl_ipv6_win.result new file mode 100644 index 00000000000..79dc8422161 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_ipv6_win.result @@ -0,0 +1,80 @@ +#################### IP: ::1 ########################### +connect (master,::1,root,,test,MASTER_MYPORT); +connect (slave,::1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='::1'; +Master-Host: ::1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0000:0000:0000:0000:0000:0000:0000:0001 ########################### +connect (master,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,MASTER_MYPORT); +connect (slave,0000:0000:0000:0000:0000:0000:0000:0001,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0000:0000:0000:0000:0000:0000:0000:0001'; +Master-Host: 0000:0000:0000:0000:0000:0000:0000:0001 +disconnect slave; +disconnect master; +connection default; +#################### IP: 0:0:0:0:0:0:0:1 ########################### +connect (master,0:0:0:0:0:0:0:1,root,,test,MASTER_MYPORT); +connect (slave,0:0:0:0:0:0:0:1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; +#################### IP: 127.0.0.1 ########################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +disconnect slave; +disconnect master; +connection default; +#################### IP: ::1 mix ####################### +connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connection master; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB> +connection slave; +reset slave; +Master-Host: 127.0.0.1 +change master to master_host='::1'; +Master-Host: ::1 +change master to master_host='127.0.0.1'; +Master-Host: 127.0.0.1 +change master to master_host='0:0:0:0:0:0:0:1'; +Master-Host: 0:0:0:0:0:0:0:1 +disconnect slave; +disconnect master; +connection default; diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix.cnf new file mode 100644 index 00000000000..00e2637d822 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= :: + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= 0.0.0.0 + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix.test b/mysql-test/suite/rpl/t/rpl_ip_mix.test new file mode 100644 index 00000000000..68aa2fc87a9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix.test @@ -0,0 +1,93 @@ +# Copyright (C) 2009 SUN Microsystems +# All rights reserved. Use is subject to license terms. +# Author: Horst Hunger +# Nov. 19, 2009 +# Test of ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, master: --bind-address=::, slave: --bind-address=0.0.0.0 +# (see corresponding cnf file) +# +--source include/check_ipv6.inc +# Can't be tested with windows due to mixed format like 0::0000:FFFF:127.0.0.1 +--source include/not_windows.inc +--source include/have_log_bin.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= ::1/128; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix.inc + +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= 0:0:0:0:0:0:0:1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= 127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= 0::0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +#let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix.inc + +let $IPv6= ::FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +#let $IPv6= ::FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 mix ####################### +--echo connect (master,$IPv6,root,,test,MASTER_MYPORT); +connect (master,$IPv6,root,,test,$MASTER_MYPORT); +--echo connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT); +--echo connection master; +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +--echo connection slave; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='::FFFF:127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0:0:0:0:0:0:1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +--echo disconnect slave; +disconnect slave; +--echo disconnect master; +disconnect master; +--echo connection default; +connection default; + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf new file mode 100644 index 00000000000..306df437bcc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= 0.0.0.0 + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= :: + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2.test b/mysql-test/suite/rpl/t/rpl_ip_mix2.test new file mode 100644 index 00000000000..d6435d710c1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix2.test @@ -0,0 +1,109 @@ +# Copyright (C) 2009 SUN Microsystems +# All rights reserved. Use is subject to license terms. +# Author: Horst Hunger +# Nov. 19, 2009 +# Test of ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, master: --bind-address=0.0.0.0, slave: --bind-address=:: +# (see corresponding cnf file) +# +# Check if ipv6 is available. If not, server is crashing (see BUG#48915). +--disable_query_log +--disable_abort_on_error +connect (checkcon123456789,::1,root,,test,$SLAVE_MYPORT); +if($mysql_errno) +{ +skip wrong IP for slave; +} +connection default; +disconnect checkcon123456789; +--enable_abort_on_error +--enable_query_log +# end check + +# Can't be tested with windows due to mixed format like 0::0000:FFFF:127.0.0.1 +--source include/not_windows.inc +--source include/have_log_bin.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= ::1/128; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix2.inc + +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= 0:0:0:0:0:0:0:1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= 127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= 0::0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +#let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix2.inc + +let $IPv6= ::FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +#let $IPv6= ::FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix2.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 mix ####################### +--echo connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT); +--echo connect (slave,$IPv6,root,,test,SLAVE_MYPORT); +connect (slave,$IPv6,root,,test,$SLAVE_MYPORT); +--echo connection master; +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +--echo connection slave; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='::FFFF:127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0:0:0:0:0:0:1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +--echo disconnect slave; +disconnect slave; +--echo disconnect master; +disconnect master; +--echo connection default; +connection default; + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2_win.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix2_win.cnf new file mode 100644 index 00000000000..306df437bcc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix2_win.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= 0.0.0.0 + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= :: + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2_win.test b/mysql-test/suite/rpl/t/rpl_ip_mix2_win.test new file mode 100644 index 00000000000..f9a2022ddd4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix2_win.test @@ -0,0 +1,78 @@ +# Copyright (C) 2009 SUN Microsystems
+# All rights reserved. Use is subject to license terms.
+# Author: Horst Hunger
+# Nov. 19, 2009
+# Test of ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, master: --bind-address=0.0.0.0, slave: --bind-address=::
+# (see corresponding cnf file)
+#
+# Check if ipv6 is available. If not, server is crashing (see BUG#48915).
+--disable_query_log
+--disable_abort_on_error
+connect (checkcon123456789,::1,root,,test,$SLAVE_MYPORT);
+if($mysql_errno)
+{
+skip wrong IP for slave;
+}
+connection default;
+disconnect checkcon123456789;
+--enable_abort_on_error
+--enable_query_log
+# end check
+
+# For windows due to missing the mixed format like 0::0000:FFFF:127.0.0.1
+--source include/windows.inc
+--source include/have_log_bin.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix2.inc
+
+let $IPv6= ::1/128;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ip_mix2.inc
+
+let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix2.inc
+
+let $IPv6= 0:0:0:0:0:0:0:1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix2.inc
+
+let $IPv6= 127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix2.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 mix #######################
+--echo connect (master,127.0.0.1,root,,test,MASTER_MYPORT);
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT);
+--echo connect (slave,$IPv6,root,,test,SLAVE_MYPORT);
+connect (slave,$IPv6,root,,test,$SLAVE_MYPORT);
+--echo connection master;
+connection master;
+reset master;
+source include/show_master_status.inc;
+save_master_pos;
+--echo connection slave;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0:0:0:0:0:0:1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+--echo disconnect slave;
+disconnect slave;
+--echo disconnect master;
+disconnect master;
+--echo connection default;
+connection default;
+--exit
diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix_win.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix_win.cnf new file mode 100644 index 00000000000..00e2637d822 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix_win.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= :: + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= 0.0.0.0 + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix_win.test b/mysql-test/suite/rpl/t/rpl_ip_mix_win.test new file mode 100644 index 00000000000..7d78f71bd1b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix_win.test @@ -0,0 +1,65 @@ +# Copyright (C) 2009 SUN Microsystems
+# All rights reserved. Use is subject to license terms.
+# Author: Horst Hunger
+# Nov. 19, 2009
+# Test of ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, master: --bind-address=::, slave: --bind-address=0.0.0.0
+# (see corresponding cnf file)
+#
+--source include/check_ipv6.inc
+# For windows due to missing the mixed format like 0::0000:FFFF:127.0.0.1
+--source include/windows.inc
+--source include/have_log_bin.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix.inc
+
+let $IPv6= ::1/128;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ip_mix.inc
+
+let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix.inc
+
+let $IPv6= 0:0:0:0:0:0:0:1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix.inc
+
+let $IPv6= 127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ip_mix.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 mix #######################
+--echo connect (master,$IPv6,root,,test,MASTER_MYPORT);
+connect (master,$IPv6,root,,test,$MASTER_MYPORT);
+--echo connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
+--echo connection master;
+connection master;
+reset master;
+source include/show_master_status.inc;
+save_master_pos;
+--echo connection slave;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0:0:0:0:0:0:1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+--echo disconnect slave;
+disconnect slave;
+--echo disconnect master;
+disconnect master;
+--echo connection default;
+connection default;
+--exit
diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf new file mode 100644 index 00000000000..b646a4088ff --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= 0.0.0.0 + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= 0.0.0.0 + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test new file mode 100644 index 00000000000..f4e5ad6af7b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test @@ -0,0 +1,90 @@ +# Copyright (C) 2009 SUN Microsystems +# All rights reserved. Use is subject to license terms. +# Author: Horst Hunger +# Nov. 19, 2009 +# Test of ipv4 (127.0.0.1) in ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, --bind-address=0.0.0.0 (see corresponding cnf file) +# for master and slave +# +# Check if ipv4 is available. +--disable_query_log +--disable_abort_on_error +connect (checkcon123456789,127.0.0.1,root,,test); +if($mysql_errno) +{ +skip wrong IP; +} +connection default; +disconnect checkcon123456789; +--enable_abort_on_error +--enable_query_log +# end check + +# Can't be tested with windows due to mixed format like 0::0000:FFFF:127.0.0.1 +--source include/not_windows.inc +--source include/have_log_bin.inc + +let $IPv6= 127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0::0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +#let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= ::FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +#let $IPv6= ::FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--echo connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT); +--echo connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT); +--echo connection master; +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +--echo connection slave; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='::FFFF:127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0:0:0:0:0:0:1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +--echo disconnect slave; +disconnect slave; +--echo disconnect master; +disconnect master; +--echo connection default; +connection default; + diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6_win.cnf b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6_win.cnf new file mode 100644 index 00000000000..b646a4088ff --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6_win.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= 0.0.0.0 + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= 0.0.0.0 + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6_win.test b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6_win.test new file mode 100644 index 00000000000..db786536c2d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6_win.test @@ -0,0 +1,63 @@ +# Copyright (C) 2009 SUN Microsystems
+# All rights reserved. Use is subject to license terms.
+# Author: Horst Hunger
+# Nov. 19, 2009
+# Test of ipv4 (127.0.0.1) in ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, --bind-address=0.0.0.0 (see corresponding cnf file)
+# for master and slave
+#
+# Check if ipv4 is available.
+--disable_query_log
+--disable_abort_on_error
+connect (checkcon123456789,127.0.0.1,root,,test);
+if($mysql_errno)
+{
+skip wrong IP;
+}
+connection default;
+disconnect checkcon123456789;
+--enable_abort_on_error
+--enable_query_log
+# end check
+
+# For windows due to missing the mixed format like 0::0000:FFFF:127.0.0.1
+--source include/windows.inc
+--source include/have_log_bin.inc
+
+let $IPv6= 127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 ###########################
+--echo connect (master,127.0.0.1,root,,test,MASTER_MYPORT);
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT);
+--echo connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
+--echo connection master;
+connection master;
+reset master;
+source include/show_master_status.inc;
+save_master_pos;
+--echo connection slave;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0:0:0:0:0:0:1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+--echo disconnect slave;
+disconnect slave;
+--echo disconnect master;
+disconnect master;
+--echo connection default;
+connection default;
+--exit
+
diff --git a/mysql-test/suite/rpl/t/rpl_ipv6.cnf b/mysql-test/suite/rpl/t/rpl_ipv6.cnf new file mode 100644 index 00000000000..c657e7c5115 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv6.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= :: + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= :: + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ipv6.test b/mysql-test/suite/rpl/t/rpl_ipv6.test new file mode 100644 index 00000000000..71fedcb4208 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv6.test @@ -0,0 +1,93 @@ +# Copyright (C) 2009 SUN Microsystems +# All rights reserved. Use is subject to license terms. +# Author: Horst Hunger +# Nov. 19, 2009 +# Test of ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, --bind-address=:: (see corresponding cnf file) +# for master and slave. +# +--source include/check_ipv6.inc +# Can't be tested with windows due to mixed format like 0::0000:FFFF:127.0.0.1 +--source include/not_windows.inc +--source include/have_log_bin.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= ::1/128; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0:0:0:0:0:0:1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0::0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +#let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= ::FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +#let $IPv6= ::FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 mix ####################### +--echo connect (master,127.0.0.1,root,,test,MASTER_MYPORT); +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT); +--echo connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT); +--echo connection master; +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +--echo connection slave; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='::FFFF:127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0:0:0:0:0:0:1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +--echo disconnect slave; +disconnect slave; +--echo disconnect master; +disconnect master; +--echo connection default; +connection default; + diff --git a/mysql-test/suite/rpl/t/rpl_ipv6_win.cnf b/mysql-test/suite/rpl/t/rpl_ipv6_win.cnf new file mode 100644 index 00000000000..c657e7c5115 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv6_win.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= :: + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= :: + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ipv6_win.test b/mysql-test/suite/rpl/t/rpl_ipv6_win.test new file mode 100644 index 00000000000..7c9d437541a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv6_win.test @@ -0,0 +1,65 @@ +# Copyright (C) 2009 SUN Microsystems
+# All rights reserved. Use is subject to license terms.
+# Author: Horst Hunger
+# Nov. 19, 2009
+# Test of ipv6 format, especially "change master host=..."
+# Options: --skip-name-resolve, --bind-address=:: (see corresponding cnf file)
+# for master and slave.
+#
+--source include/check_ipv6.inc
+# For windows due to missing the mixed format like 0::0000:FFFF:127.0.0.1
+--source include/windows.inc
+--source include/have_log_bin.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= ::1/128;
+#--echo #################### IP: $IPv6 ###########################
+#--source include/rpl_ipv6.inc
+
+let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= 0:0:0:0:0:0:0:1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= 127.0.0.1;
+--echo #################### IP: $IPv6 ###########################
+--source include/rpl_ipv6.inc
+
+let $IPv6= ::1;
+--echo #################### IP: $IPv6 mix #######################
+--echo connect (master,127.0.0.1,root,,test,MASTER_MYPORT);
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT);
+--echo connect (slave,127.0.0.1,root,,test,SLAVE_MYPORT);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
+--echo connection master;
+connection master;
+reset master;
+source include/show_master_status.inc;
+save_master_pos;
+--echo connection slave;
+connection slave;
+reset slave;
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='$IPv6';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='127.0.0.1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+eval change master to master_host='0:0:0:0:0:0:0:1';
+let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1);
+--echo Master-Host: $master_host
+--echo disconnect slave;
+disconnect slave;
+--echo disconnect master;
+disconnect master;
+--echo connection default;
+connection default;
+--exit
diff --git a/mysql-test/t/ipv4_as_ipv6-master.opt b/mysql-test/t/ipv4_as_ipv6-master.opt new file mode 100644 index 00000000000..f55a8e9209d --- /dev/null +++ b/mysql-test/t/ipv4_as_ipv6-master.opt @@ -0,0 +1 @@ +--skip-name-resolve --bind-address=0.0.0.0 diff --git a/mysql-test/t/ipv4_as_ipv6.test b/mysql-test/t/ipv4_as_ipv6.test new file mode 100644 index 00000000000..4f4e68e8bfc --- /dev/null +++ b/mysql-test/t/ipv4_as_ipv6.test @@ -0,0 +1,65 @@ +# Copyright (C) 2009 SUN Microsystems +# All rights reserved. Use is subject to license terms. +# Author: Horst Hunger +# Nov. 19, 2009 +# Test of ipv4 (127.0.0.1) in ipv6 format +# Options: --skip-name-resolve, --bind-address=0.0.0.0 (see corresponding opt file). +# +# Can't be tested with windows due to mixed format like 0::0000:FFFF:127.0.0.1 +--source include/not_windows.inc +# Can't be tested with embedded server +--source include/not_embedded.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +echo =============Test of '127.0.0.1' (IPv4) ===========================; +let $IPv6= 127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0:0:0:0:FFFF:127.0.0.1' ===================; +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0000:0000:0000:0000:0000:FFFF:127.0.0.1' ====; +let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0000:0000:0:0000:FFFF:127.0.0.1' ====; +let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0::0000:FFFF:127.0.0.1' ====; +let $IPv6= 0::0000:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0:0:0:0:FFFF:127.0.0.1/96' ================; +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96; +#--source include/ipv6_clients.inc +#--source include/ipv6.inc + +echo =============Test of '::FFFF:127.0.0.1' ===========================; +let $IPv6= ::FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '::FFFF:127.0.0.1/96' ========================; +let $IPv6= ::FFFF:127.0.0.1/96; +#--source include/ipv6_clients.inc +#--source include/ipv6.inc + +echo =============Test of '::1' ========================; +let $IPv6= ::1; +--echo connect (con1, $IPv6, root, , test, MASTER_MYPORT,); +--disable_query_log +--error 2003,2006 +connect (con1, $IPv6, root, , test, $MASTER_MYPORT,); +--enable_query_log + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/ipv4_as_ipv6_win-master.opt b/mysql-test/t/ipv4_as_ipv6_win-master.opt new file mode 100644 index 00000000000..f55a8e9209d --- /dev/null +++ b/mysql-test/t/ipv4_as_ipv6_win-master.opt @@ -0,0 +1 @@ +--skip-name-resolve --bind-address=0.0.0.0 diff --git a/mysql-test/t/ipv4_as_ipv6_win.test b/mysql-test/t/ipv4_as_ipv6_win.test new file mode 100644 index 00000000000..04f908a119d --- /dev/null +++ b/mysql-test/t/ipv4_as_ipv6_win.test @@ -0,0 +1,31 @@ +# Copyright (C) 2009 SUN Microsystems
+# All rights reserved. Use is subject to license terms.
+# Author: Horst Hunger
+# Nov. 19, 2009
+# Test of ipv4 (127.0.0.1) in ipv6 format
+# Options: --skip-name-resolve, --bind-address=0.0.0.0 (see corresponding opt file).
+#
+# For windows due to missing the mixed format like 0::0000:FFFF:127.0.0.1
+--source include/windows.inc
+# Can't be tested with embedded server
+--source include/not_embedded.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+echo =============Test of '127.0.0.1' (IPv4) ===========================;
+let $IPv6= 127.0.0.1;
+--source include/ipv6_clients.inc
+--source include/ipv6.inc
+
+echo =============Test of '::1' ========================;
+let $IPv6= ::1;
+--echo connect (con1, $IPv6, root, , test, MASTER_MYPORT);
+--disable_query_log
+--error 2003,2006
+connect (con1, $IPv6, root, , test, $MASTER_MYPORT);
+--enable_query_log
+connection default;
+
+# Wait till all disconnects are completed
+--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/t/ipv6-master.opt b/mysql-test/t/ipv6-master.opt new file mode 100644 index 00000000000..d705811808c --- /dev/null +++ b/mysql-test/t/ipv6-master.opt @@ -0,0 +1 @@ +--skip-name-resolve --bind-address=:: diff --git a/mysql-test/t/ipv6.test b/mysql-test/t/ipv6.test new file mode 100644 index 00000000000..a1515e9d533 --- /dev/null +++ b/mysql-test/t/ipv6.test @@ -0,0 +1,79 @@ +# Copyright (C) 2009 SUN Microsystems +# All rights reserved. Use is subject to license terms. +# Author: Horst Hunger +# Nov. 19, 2009 +# Test of ipv6 format +# Options: --skip-name-resolve, --bind-address=:: (see corresponding opt file). +# +--source include/check_ipv6.inc + +# Can't be tested with windows due to the mixed format like 0:0:0:0:0:FFFF:127.0.0.1 +--source include/not_windows.inc +# Can't be tested with embedded server +--source include/not_embedded.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +echo =============Test of '::1' ========================================; +let $IPv6= ::1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '::1/128' ====================================; +let $IPv6= ::1/128; +#--source include/ipv6_clients.inc +#--source include/ipv6.inc + +echo =============Test of '0000:0000:0000:0000:0000:0000:0000:0001' ====; +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0:0:0:0:0:0:1' ============================; +let $IPv6= 0:0:0:0:0:0:0:1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '127.0.0.1' (IPv4) ===========================; +let $IPv6= 127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0:0:0:0:FFFF:127.0.0.1' ===================; +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0000:0000:0000:0000:0000:FFFF:127.0.0.1' ====; +let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0000:0000:0:0000:FFFF:127.0.0.1' ====; +let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0::0000:FFFF:127.0.0.1' ====; +let $IPv6= 0::0000:FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0:0:0:0:FFFF:127.0.0.1/96' ================; +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96; +#--source include/ipv6_clients.inc +#--source include/ipv6.inc + +echo =============Test of '::FFFF:127.0.0.1' ===========================; +let $IPv6= ::FFFF:127.0.0.1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '::FFFF:127.0.0.1/96' ========================; +let $IPv6= ::FFFF:127.0.0.1/96; +#--source include/ipv6_clients.inc +#--source include/ipv6.inc + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/ipv6_win-master.opt b/mysql-test/t/ipv6_win-master.opt new file mode 100644 index 00000000000..d705811808c --- /dev/null +++ b/mysql-test/t/ipv6_win-master.opt @@ -0,0 +1 @@ +--skip-name-resolve --bind-address=:: diff --git a/mysql-test/t/ipv6_win.test b/mysql-test/t/ipv6_win.test new file mode 100644 index 00000000000..86d867cc448 --- /dev/null +++ b/mysql-test/t/ipv6_win.test @@ -0,0 +1,39 @@ +# Copyright (C) 2009 SUN Microsystems +# All rights reserved. Use is subject to license terms. +# Author: Horst Hunger +# Nov. 19, 2009 +# Test of ipv6 format +# Options: --skip-name-resolve, --bind-address=:: (see corresponding opt file). +# +--source include/check_ipv6.inc + +# For windows due to missing the mixed format like 0::0000:FFFF:127.0.0.1 +--source include/windows.inc +# Can't be tested with embedded server +--source include/not_embedded.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +echo =============Test of '::1' ========================================; +let $IPv6= ::1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '::1/128' ====================================; +let $IPv6= ::1/128; +#--source include/ipv6_clients.inc +#--source include/ipv6.inc + +echo =============Test of '0000:0000:0000:0000:0000:0000:0000:0001' ====; +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +echo =============Test of '0:0:0:0:0:0:0:1' ============================; +let $IPv6= 0:0:0:0:0:0:0:1; +--source include/ipv6_clients.inc +--source include/ipv6.inc + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/skip_name_resolve.test b/mysql-test/t/skip_name_resolve.test index df010d15fa0..cd7ffe1690d 100644 --- a/mysql-test/t/skip_name_resolve.test +++ b/mysql-test/t/skip_name_resolve.test @@ -15,7 +15,7 @@ DROP USER mysqltest_1@'127.0.0.1/255.255.255.255'; # Bug#13407 Remote connecting crashes server # Server crashed when one used USER() function in connection for which # was impossible to obtain peer hostname. -connect (con1, 127.0.0.1, root, , test, $MASTER_MYPORT, ); +connect (con1, localhost, root, , test, $MASTER_MYPORT, ); --replace_column 1 # SELECT USER(); # We are only interested in the fact that statement below doesn't diff --git a/mysys/my_static.c b/mysys/my_static.c index 62e6d402315..fb62e92dfd1 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -111,3 +111,31 @@ my_bool NEAR my_disable_async_io=0; my_bool NEAR my_disable_flush_key_blocks=0; my_bool NEAR my_disable_symlinks=0; my_bool NEAR mysys_uses_curses=0; + +/* + Note that PSI_hook and PSI_server are unconditionally + (no ifdef HAVE_PSI_INTERFACE) defined. + This is to ensure binary compatibility between the server and plugins, + in the case when: + - the server is not compiled with HAVE_PSI_INTERFACE + - a plugin is compiled with HAVE_PSI_INTERFACE + See the doxygen documentation for the performance schema. +*/ + +/** + Hook for the instrumentation interface. + Code implementing the instrumentation interface should register here. +*/ +struct PSI_bootstrap *PSI_hook= NULL; + +/** + Instance of the instrumentation interface for the MySQL server. + @todo This is currently a global variable, which is handy when + compiling instrumented code that is bundled with the server. + When dynamic plugin are truly supported, this variable will need + to be replaced by a macro, so that each XYZ plugin can have it's own + xyz_psi_server variable, obtained from PSI_bootstrap::get_interface() + with the version used at compile time for plugin XYZ. +*/ +PSI *PSI_server= NULL; + diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index 35715832fc6..9fb1dd14b6c 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc 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 @@ -63,8 +63,8 @@ static unsigned int __stdcall pthread_start(void *p) } -int pthread_create(pthread_t *thread_id, pthread_attr_t *attr, - pthread_handler func, void *param) +int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr, + pthread_handler func, void *param) { uintptr_t handle; struct thread_start_parameter *par; diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index 03136fe9361..a7988b5198e 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -24,6 +24,7 @@ set @current_hostname= @@hostname; INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost'; REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); +REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); INSERT INTO tmp_user (host,user) VALUES ('localhost',''); INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost'; INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0; diff --git a/sql-common/client.c b/sql-common/client.c index 5114b645818..1f9c00f93be 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -38,6 +38,10 @@ #include "mysql.h" +#ifndef __WIN__ +#include <netdb.h> +#endif + /* Remove client convenience wrappers */ #undef max_allowed_packet #undef net_buffer_length @@ -2227,9 +2231,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, { char buff[NAME_LEN+USERNAME_LENGTH+100]; char *end,*host_info= NULL; - my_socket sock; - in_addr_t ip_addr; - struct sockaddr_in sock_addr; ulong pkt_length; NET *net= &mysql->net; #ifdef MYSQL_SERVER @@ -2335,7 +2336,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, else { mysql->options.protocol=MYSQL_PROTOCOL_MEMORY; - sock=0; unix_socket = 0; host=mysql->options.shared_memory_base_name; my_snprintf(host_info=buff, sizeof(buff)-1, @@ -2350,12 +2350,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, (unix_socket || mysql_unix_port) && (!host || !strcmp(host,LOCAL_HOST))) { - host=LOCAL_HOST; - if (!unix_socket) - unix_socket=mysql_unix_port; - host_info=(char*) ER(CR_LOCALHOST_CONNECTION); - DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket)); - if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR) + DBUG_PRINT("info", ("Using socket")); + my_socket sock= socket(AF_UNIX, SOCK_STREAM, 0); + if (sock == SOCKET_ERROR) { set_mysql_extended_error(mysql, CR_SOCKET_CREATE_ERROR, unknown_sqlstate, @@ -2363,12 +2360,28 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, socket_errno); goto error; } + net->vio= vio_new(sock, VIO_TYPE_SOCKET, VIO_LOCALHOST | VIO_BUFFERED_READ); - bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); - UNIXaddr.sun_family = AF_UNIX; + if (!net->vio) + { + DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol)); + set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate); + closesocket(sock); + goto error; + } + + host= LOCAL_HOST; + if (!unix_socket) + unix_socket= mysql_unix_port; + host_info= (char*) ER(CR_LOCALHOST_CONNECTION); + DBUG_PRINT("info", ("Using UNIX sock '%s'", unix_socket)); + + bzero((char*) &UNIXaddr, sizeof(UNIXaddr)); + UNIXaddr.sun_family= AF_UNIX; strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1); - if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), + + if (my_connect(sock, (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), mysql->options.connect_timeout)) { DBUG_PRINT("error",("Got error %d on connect to local server", @@ -2377,6 +2390,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, unknown_sqlstate, ER(CR_CONNECTION_ERROR), unix_socket, socket_errno); + vio_delete(net->vio); + net->vio= 0; goto error; } mysql->options.protocol=MYSQL_PROTOCOL_SOCKET; @@ -2387,7 +2402,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) || (! have_tcpip && (unix_socket || !host && is_NT())))) { - sock=0; if ((hPipe= create_named_pipe(mysql, mysql->options.connect_timeout, (char**) &host, (char**) &unix_socket)) == INVALID_HANDLE_VALUE) @@ -2417,94 +2431,124 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, (!mysql->options.protocol || mysql->options.protocol == MYSQL_PROTOCOL_TCP)) { - int status= -1; + struct addrinfo *res_lst, hints, *t_res; + int gai_errno; + char port_buf[NI_MAXSERV]; + my_socket sock= SOCKET_ERROR; + int UNINIT_VAR(saved_error), status= -1; + unix_socket=0; /* This is not used */ + if (!port) - port=mysql_port; + port= mysql_port; + if (!host) - host=LOCAL_HOST; - my_snprintf(host_info=buff,sizeof(buff)-1,ER(CR_TCP_CONNECTION),host); - DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port)); + host= LOCAL_HOST; + + my_snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host); + DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host, port)); #ifdef MYSQL_SERVER thr_alarm_init(&alarmed); thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff); #endif - /* _WIN64 ; Assume that the (int) range is enough for socket() */ - sock = (my_socket) socket(AF_INET,SOCK_STREAM,0); + + DBUG_PRINT("info",("IP '%s'", "client")); + #ifdef MYSQL_SERVER thr_end_alarm(&alarmed); #endif - if (sock == SOCKET_ERROR) - { - set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate, - ER(CR_IPSOCK_ERROR), socket_errno); + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype= SOCK_STREAM; + hints.ai_protocol= IPPROTO_TCP; + hints.ai_family= AF_UNSPEC; + + DBUG_PRINT("info",("IPV6 getaddrinfo %s", host)); + my_snprintf(port_buf, NI_MAXSERV, "%d", port); + gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst); + + if (gai_errno != 0) + { + /* + For DBUG we are keeping the right message but for client we default to + historical error message. + */ + DBUG_PRINT("info",("IPV6 getaddrinfo error %d", gai_errno)); + set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate, + ER(CR_UNKNOWN_HOST), host, errno); + goto error; } - net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ); - bzero((char*) &sock_addr,sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_port = (ushort) htons((ushort) port); /* - The server name may be a host name or IP address + A hostname might map to multiple IP addresses (IPv4/IPv6). Go over the + list of IP addresses until a successful connection can be established. */ - - if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) - { - memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); - status= my_connect(sock, (struct sockaddr *) &sock_addr, - sizeof(sock_addr), mysql->options.connect_timeout); - } - else + DBUG_PRINT("info", ("Try connect on all addresses for host.")); + for (t_res= res_lst; t_res; t_res= t_res->ai_next) { - int i, tmp_errno; - struct hostent tmp_hostent,*hp; - char buff2[GETHOSTBYNAME_BUFF_SIZE]; - hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), - &tmp_errno); + DBUG_PRINT("info", ("Create socket, family: %d type: %d proto: %d", + t_res->ai_family, t_res->ai_socktype, + t_res->ai_protocol)); + sock= socket(t_res->ai_family, t_res->ai_socktype, t_res->ai_protocol); + if (sock == SOCKET_ERROR) + { + saved_error= socket_errno; + continue; + } + DBUG_PRINT("info", ("Connect socket")); + status= my_connect(sock, t_res->ai_addr, t_res->ai_addrlen, + mysql->options.connect_timeout); /* - Don't attempt to connect to non IPv4 addresses as the client could - end up sending information to a unknown server. For example, a IPv6 - address might be returned from gethostbyname depending on options - set via the RES_OPTIONS environment variable. + Here we rely on my_connect() to return success only if the + connect attempt was really successful. Otherwise we would stop + trying another address, believing we were successful. */ - if (!hp || (hp->h_addrtype != AF_INET)) - { - my_gethostbyname_r_free(); - set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate, - ER(CR_UNKNOWN_HOST), host, tmp_errno); - goto error; - } + if (!status) + break; - for (i= 0; status && hp->h_addr_list[i]; i++) - { - char ipaddr[18] __attribute__((unused)); - memcpy(&sock_addr.sin_addr, hp->h_addr_list[i], - min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length)); - DBUG_PRINT("info",("Trying %s...", - (my_inet_ntoa(sock_addr.sin_addr, ipaddr), ipaddr))); - /* - Here we rely on my_connect() to return success only if the - connect attempt was really successful. Otherwise we would stop - trying another address, believing we were successful. - */ - status= my_connect(sock, (struct sockaddr *) &sock_addr, - sizeof(sock_addr), mysql->options.connect_timeout); - } + /* + Save value as socket errno might be overwritten due to + calling a socket function below. + */ + saved_error= socket_errno; - my_gethostbyname_r_free(); + DBUG_PRINT("info", ("No success, close socket, try next address.")); + closesocket(sock); + } + DBUG_PRINT("info", + ("End of connect attempts, sock: %d status: %d error: %d", + sock, status, saved_error)); + + freeaddrinfo(res_lst); + + if (sock == SOCKET_ERROR) + { + set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate, + ER(CR_IPSOCK_ERROR), saved_error); + goto error; } if (status) { - DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno, - host)); + DBUG_PRINT("error",("Got error %d on connect to '%s'", saved_error, host)); set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate, - ER(CR_CONN_HOST_ERROR), host, socket_errno); + ER(CR_CONN_HOST_ERROR), host, saved_error); + goto error; + } + + net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ); + if (! net->vio ) + { + DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol)); + set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate); + closesocket(sock); goto error; } } + + DBUG_PRINT("info", ("net->vio: %p", net->vio)); if (!net->vio) { DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); @@ -2640,14 +2684,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, if (client_flag & CLIENT_MULTI_STATEMENTS) client_flag|= CLIENT_MULTI_RESULTS; -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) if (mysql->options.ssl_key || mysql->options.ssl_cert || mysql->options.ssl_ca || mysql->options.ssl_capath || mysql->options.ssl_cipher) mysql->options.use_ssl= 1; if (mysql->options.use_ssl) client_flag|=CLIENT_SSL; -#endif /* HAVE_OPENSSL */ +#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/ if (db) client_flag|=CLIENT_CONNECT_WITH_DB; @@ -2676,7 +2720,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, } mysql->client_flag=client_flag; -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) if (client_flag & CLIENT_SSL) { /* Do the SSL layering. */ @@ -2727,7 +2771,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, } } -#endif /* HAVE_OPENSSL */ +#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu", mysql->server_version,mysql->server_capabilities, diff --git a/sql/client_settings.h b/sql/client_settings.h index fd50bfdbb88..7d103d5904d 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -30,10 +30,6 @@ #define set_sigpipe(mysql) #define reset_sigpipe(mysql) #define read_user_name(A) {} -#define mysql_rpl_query_type(A,B) MYSQL_RPL_ADMIN -#define mysql_master_send_query(A, B, C) 1 -#define mysql_slave_send_query(A, B, C) 1 -#define mysql_rpl_probe(mysql) 0 #undef HAVE_SMEM #undef _CUSTOMCONFIG_ diff --git a/sql/hostname.cc b/sql/hostname.cc index b498c548e61..cf35e60061f 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -18,10 +18,10 @@ @file @brief - Get hostname for an IP. + Get hostname for an IP address. - Hostnames are checked with reverse name lookup and - checked that they doesn't resemble an ip. + Hostnames are checked with reverse name lookup and checked that they + doesn't resemble an IP address. */ #include "mysql_priv.h" @@ -34,24 +34,54 @@ extern "C" { // Because of SCO 3.2V4.2 #ifdef HAVE_SYS_UN_H #include <sys/un.h> #endif -#include <netdb.h> #include <sys/utsname.h> #endif // __WIN__ #ifdef __cplusplus } #endif +/* + HOST_ENTRY_KEY_SIZE -- size of IP address string in the hash cache. +*/ + +#define HOST_ENTRY_KEY_SIZE INET6_ADDRSTRLEN + +/** + An entry in the hostname hash table cache. + + Host name cache does two things: + - caches host names to save DNS look ups; + - counts connect errors from IP. -class host_entry :public hash_filo_element + Host name can be NULL (that means DNS look up failed), but connect errors + still are counted. +*/ + +class Host_entry :public hash_filo_element { public: - char ip[sizeof(((struct in_addr *) 0)->s_addr)]; - uint errors; - char *hostname; + /** + Client IP address. This is the key used with the hash table. + + The client IP address is always expressed in IPv6, even when the + network IPv6 stack is not present. + + This IP address is never used to connect to a socket. + */ + char ip_key[HOST_ENTRY_KEY_SIZE]; + + /** + Number of errors during handshake phase from the IP address. + */ + uint connect_errors; + + /** + One of the host names for the IP address. May be NULL. + */ + const char *hostname; }; static hash_filo *hostname_cache; -static pthread_mutex_t LOCK_hostname; void hostname_cache_refresh() { @@ -60,219 +90,468 @@ void hostname_cache_refresh() bool hostname_cache_init() { - host_entry tmp; - uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp); - if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset, - sizeof(struct in_addr),NULL, - (my_hash_free_key) free, - &my_charset_bin))) + Host_entry tmp; + uint key_offset= (uint) ((char*) (&tmp.ip_key) - (char*) &tmp); + + if (!(hostname_cache= new hash_filo(HOST_CACHE_SIZE, + key_offset, HOST_ENTRY_KEY_SIZE, + NULL, (my_hash_free_key) free, + &my_charset_bin))) return 1; + hostname_cache->clear(); - (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); + return 0; } void hostname_cache_free() { - if (hostname_cache) - { - (void) pthread_mutex_destroy(&LOCK_hostname); - delete hostname_cache; - hostname_cache= 0; - } + delete hostname_cache; + hostname_cache= NULL; } +static void prepare_hostname_cache_key(const char *ip_string, + char *ip_key) +{ + int ip_string_length= strlen(ip_string); + DBUG_ASSERT(ip_string_length < HOST_ENTRY_KEY_SIZE); -static void add_hostname(struct in_addr *in,const char *name) + memset(ip_key, 0, HOST_ENTRY_KEY_SIZE); + memcpy_fixed(ip_key, ip_string, ip_string_length); +} + +static inline Host_entry *hostname_cache_search(const char *ip_key) { - if (!(specialflag & SPECIAL_NO_HOST_CACHE)) + return (Host_entry *) hostname_cache->search((uchar *) ip_key, 0); +} + +static bool add_hostname_impl(const char *ip_key, const char *hostname) +{ + if (hostname_cache_search(ip_key)) + return FALSE; + + size_t hostname_size= hostname ? strlen(hostname) + 1 : 0; + + Host_entry *entry= (Host_entry *) malloc(sizeof (Host_entry) + hostname_size); + + if (!entry) + return TRUE; + + char *hostname_copy; + + memcpy_fixed(&entry->ip_key, ip_key, HOST_ENTRY_KEY_SIZE); + + if (hostname_size) { - pthread_mutex_lock(&hostname_cache->lock); - host_entry *entry; - if (!(entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) - { - uint length=name ? (uint) strlen(name) : 0; + hostname_copy= (char *) (entry + 1); + memcpy(hostname_copy, hostname, hostname_size); - if ((entry=(host_entry*) malloc(sizeof(host_entry)+length+1))) - { - char *new_name; - memcpy_fixed(&entry->ip, &in->s_addr, sizeof(in->s_addr)); - if (length) - memcpy(new_name= (char *) (entry+1), name, length+1); - else - new_name=0; - entry->hostname=new_name; - entry->errors=0; - (void) hostname_cache->add(entry); - } - } - pthread_mutex_unlock(&hostname_cache->lock); + DBUG_PRINT("info", ("Adding '%s' -> '%s' to the hostname cache...'", + (const char *) ip_key, + (const char *) hostname_copy)); } -} + else + { + hostname_copy= NULL; + + DBUG_PRINT("info", ("Adding '%s' -> NULL to the hostname cache...'", + (const char *) ip_key)); + } + + entry->hostname= hostname_copy; + entry->connect_errors= 0; + return hostname_cache->add(entry); +} -inline void add_wrong_ip(struct in_addr *in) +static bool add_hostname(const char *ip_key, const char *hostname) { - add_hostname(in,NullS); + if (specialflag & SPECIAL_NO_HOST_CACHE) + return FALSE; + + pthread_mutex_lock(&hostname_cache->lock); + + bool err_status= add_hostname_impl(ip_key, hostname); + + pthread_mutex_unlock(&hostname_cache->lock); + + return err_status; } -void inc_host_errors(struct in_addr *in) +void inc_host_errors(const char *ip_string) { + if (!ip_string) + return; + + char ip_key[HOST_ENTRY_KEY_SIZE]; + prepare_hostname_cache_key(ip_string, ip_key); + pthread_mutex_lock(&hostname_cache->lock); - host_entry *entry; - if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) - entry->errors++; + + Host_entry *entry= hostname_cache_search(ip_key); + + if (entry) + entry->connect_errors++; + pthread_mutex_unlock(&hostname_cache->lock); } -void reset_host_errors(struct in_addr *in) + +void reset_host_errors(const char *ip_string) { + if (!ip_string) + return; + + char ip_key[HOST_ENTRY_KEY_SIZE]; + prepare_hostname_cache_key(ip_string, ip_key); + pthread_mutex_lock(&hostname_cache->lock); - host_entry *entry; - if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) - entry->errors=0; + + Host_entry *entry= hostname_cache_search(ip_key); + + if (entry) + entry->connect_errors= 0; + pthread_mutex_unlock(&hostname_cache->lock); } -/* Deal with systems that don't defined INADDR_LOOPBACK */ -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK 0x7f000001UL -#endif -char * ip_to_hostname(struct in_addr *in, uint *errors) +static inline bool is_ip_loopback(const struct sockaddr *ip) +{ + switch (ip->sa_family) { + case AF_INET: + { + /* Check for IPv4 127.0.0.1. */ + struct in_addr *ip4= &((struct sockaddr_in *) ip)->sin_addr; + return ntohl(ip4->s_addr) == INADDR_LOOPBACK; + } + +#ifdef HAVE_IPV6 + case AF_INET6: + { + /* Check for IPv6 ::1. */ + struct in6_addr *ip6= &((struct sockaddr_in6 *) ip)->sin6_addr; + return IN6_IS_ADDR_LOOPBACK(ip6); + } +#endif /* HAVE_IPV6 */ + + default: + return FALSE; + } +} + +static inline bool is_hostname_valid(const char *hostname) { - uint i; - host_entry *entry; + /* + A hostname is invalid if it starts with a number followed by a dot + (IPv4 address). + */ + + if (!my_isdigit(&my_charset_latin1, hostname[0])) + return TRUE; + + const char *p= hostname + 1; + + while (my_isdigit(&my_charset_latin1, *p)) + ++p; + + return *p != '.'; +} + +/** + Resolve IP-address to host name. + + This function does the following things: + - resolves IP-address; + - employs Forward Confirmed Reverse DNS technique to validate IP-address; + - returns host name if IP-address is validated; + - set value to out-variable connect_errors -- this variable represents the + number of connection errors from the specified IP-address. + + NOTE: connect_errors are counted (are supported) only for the clients + where IP-address can be resolved and FCrDNS check is passed. + + @param [in] ip_storage IP address (sockaddr). Must be set. + @param [in] ip_string IP address (string). Must be set. + @param [out] hostname + @param [out] connect_errors + + @return Error status + @retval FALSE Success + @retval TRUE Error + + The function does not set/report MySQL server error in case of failure. + It's caller's responsibility to handle failures of this function + properly. +*/ + +bool ip_to_hostname(struct sockaddr_storage *ip_storage, + const char *ip_string, + char **hostname, uint *connect_errors) +{ + const struct sockaddr *ip= (const sockaddr *) ip_storage; + int err_code; + bool err_status; + DBUG_ENTER("ip_to_hostname"); - *errors=0; + DBUG_PRINT("info", ("IP address: '%s'; family: %d.", + (const char *) ip_string, + (int) ip->sa_family)); - /* We always treat the loopback address as "localhost". */ - if (in->s_addr == htonl(INADDR_LOOPBACK)) // is expanded inline by gcc - DBUG_RETURN((char *)my_localhost); + /* Check if we have loopback address (127.0.0.1 or ::1). */ + + if (is_ip_loopback(ip)) + { + DBUG_PRINT("info", ("Loopback address detected.")); + + *connect_errors= 0; /* Do not count connect errors from localhost. */ + *hostname= (char *) my_localhost; + + DBUG_RETURN(FALSE); + } + + /* Prepare host name cache key. */ + + char ip_key[HOST_ENTRY_KEY_SIZE]; + prepare_hostname_cache_key(ip_string, ip_key); + + /* Check first if we have host name in the cache. */ - /* Check first if we have name in cache */ if (!(specialflag & SPECIAL_NO_HOST_CACHE)) { pthread_mutex_lock(&hostname_cache->lock); - if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) + + Host_entry *entry= hostname_cache_search(ip_key); + + if (entry) { - char *name; - if (!entry->hostname) - name=0; // Don't allow connection - else - name=my_strdup(entry->hostname,MYF(0)); - *errors= entry->errors; + *connect_errors= entry->connect_errors; + *hostname= NULL; + + if (entry->hostname) + *hostname= my_strdup(entry->hostname, MYF(0)); + + DBUG_PRINT("info",("IP (%s) has been found in the cache. " + "Hostname: '%s'; connect_errors: %d", + (const char *) ip_key, + (const char *) (*hostname? *hostname : "null"), + (int) *connect_errors)); + pthread_mutex_unlock(&hostname_cache->lock); - DBUG_RETURN(name); + + DBUG_RETURN(FALSE); } + pthread_mutex_unlock(&hostname_cache->lock); } - struct hostent *hp, *check; - char *name; - LINT_INIT(check); -#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) - char buff[GETHOSTBYADDR_BUFF_SIZE],buff2[GETHOSTBYNAME_BUFF_SIZE]; - int tmp_errno; - struct hostent tmp_hostent, tmp_hostent2; -#ifdef HAVE_purify - bzero(buff,sizeof(buff)); // Bug in purify -#endif - if (!(hp=gethostbyaddr_r((char*) in,sizeof(*in), - AF_INET, - &tmp_hostent,buff,sizeof(buff),&tmp_errno))) - { - DBUG_PRINT("error",("gethostbyaddr_r returned %d",tmp_errno)); - return 0; - } - if (!(check=my_gethostbyname_r(hp->h_name,&tmp_hostent2,buff2,sizeof(buff2), - &tmp_errno))) + /* + Resolve host name. Return an error if a host name can not be resolved + (instead of returning the numeric form of the host name). + */ + + char hostname_buffer[NI_MAXHOST]; + + DBUG_PRINT("info", ("Resolving '%s'...", (const char *) ip_key)); + + err_code= vio_getnameinfo(ip, hostname_buffer, NI_MAXHOST, NULL, 0, + NI_NAMEREQD); + + if (err_code == EAI_NONAME) { - DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno)); /* - Don't cache responses when the DSN server is down, as otherwise - transient DNS failure may leave any number of clients (those - that attempted to connect during the outage) unable to connect - indefinitely. + There is no reverse address mapping for the IP address. A host name + can not be resolved. */ - if (tmp_errno == HOST_NOT_FOUND || tmp_errno == NO_DATA) - add_wrong_ip(in); - my_gethostbyname_r_free(); - DBUG_RETURN(0); - } - if (!hp->h_name[0]) - { - DBUG_PRINT("error",("Got an empty hostname")); - add_wrong_ip(in); - my_gethostbyname_r_free(); - DBUG_RETURN(0); // Don't allow empty hostnames - } - if (!(name=my_strdup(hp->h_name,MYF(0)))) - { - my_gethostbyname_r_free(); - DBUG_RETURN(0); // out of memory + + DBUG_PRINT("error", ("IP address '%s' could not be resolved: " + "no reverse address mapping.", + (const char *) ip_key)); + + sql_print_warning("IP address '%s' could not be resolved: " + "no reverse address mapping.", + (const char *) ip_key); + + err_status= add_hostname(ip_key, NULL); + + *hostname= NULL; + *connect_errors= 0; /* New IP added to the cache. */ + + DBUG_RETURN(err_status); } - my_gethostbyname_r_free(); -#else - pthread_mutex_lock(&LOCK_hostname); - if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET))) + else if (err_code) { - pthread_mutex_unlock(&LOCK_hostname); - DBUG_PRINT("error",("gethostbyaddr returned %d",errno)); + DBUG_PRINT("error", ("IP address '%s' could not be resolved: " + "getnameinfo() returned %d.", + (const char *) ip_key, + (int) err_code)); + + sql_print_warning("IP address '%s' could not be resolved: " + "getnameinfo() returned error (code: %d).", + (const char *) ip_key, + (int) err_code); - if (errno == HOST_NOT_FOUND || errno == NO_DATA) - goto add_wrong_ip_and_return; - /* Failure, don't cache responce */ - DBUG_RETURN(0); + DBUG_RETURN(TRUE); } - if (!hp->h_name[0]) // Don't allow empty hostnames + + DBUG_PRINT("info", ("IP '%s' resolved to '%s'.", + (const char *) ip_key, + (const char *) hostname_buffer)); + + /* + Validate hostname: the server does not accept host names, which + resemble IP addresses. + + The thing is that theoretically, a host name can be in a form of IPv4 + address (123.example.org, or 1.2 or even 1.2.3.4). We have to deny such + host names because ACL-systems is not designed to work with them. + + For example, it is possible to specify a host name mask (like + 192.168.1.%) for an ACL rule. Then, if IPv4-like hostnames are allowed, + there is a security hole: instead of allowing access for + 192.168.1.0/255 network (which was assumed by the user), the access + will be allowed for host names like 192.168.1.example.org. + */ + + if (!is_hostname_valid(hostname_buffer)) { - pthread_mutex_unlock(&LOCK_hostname); - DBUG_PRINT("error",("Got an empty hostname")); - goto add_wrong_ip_and_return; + DBUG_PRINT("error", ("IP address '%s' has been resolved " + "to the host name '%s', which resembles " + "IPv4-address itself.", + (const char *) ip_key, + (const char *) hostname_buffer)); + + sql_print_warning("IP address '%s' has been resolved " + "to the host name '%s', which resembles " + "IPv4-address itself.", + (const char *) ip_key, + (const char *) hostname_buffer); + + err_status= add_hostname(ip_key, NULL); + + *hostname= NULL; + *connect_errors= 0; /* New IP added to the cache. */ + + DBUG_RETURN(err_status); } - if (!(name=my_strdup(hp->h_name,MYF(0)))) + + /* Get IP-addresses for the resolved host name (FCrDNS technique). */ + + struct addrinfo hints; + struct addrinfo *addr_info_list; + + memset(&hints, 0, sizeof (struct addrinfo)); + hints.ai_flags= AI_PASSIVE; + hints.ai_socktype= SOCK_STREAM; + hints.ai_family= AF_UNSPEC; + + DBUG_PRINT("info", ("Getting IP addresses for hostname '%s'...", + (const char *) hostname_buffer)); + + err_code= getaddrinfo(hostname_buffer, NULL, &hints, &addr_info_list); + + if (err_code == EAI_NONAME) { - pthread_mutex_unlock(&LOCK_hostname); - DBUG_RETURN(0); // out of memory + /* + Don't cache responses when the DNS server is down, as otherwise + transient DNS failure may leave any number of clients (those + that attempted to connect during the outage) unable to connect + indefinitely. + */ + + err_status= add_hostname(ip_key, NULL); + + *hostname= NULL; + *connect_errors= 0; /* New IP added to the cache. */ + + DBUG_RETURN(err_status); } - check=gethostbyname(name); - pthread_mutex_unlock(&LOCK_hostname); - if (!check) + else if (err_code) { - DBUG_PRINT("error",("gethostbyname returned %d",errno)); - my_free(name,MYF(0)); - DBUG_RETURN(0); + DBUG_PRINT("error", ("getaddrinfo() failed with error code %d.", err_code)); + DBUG_RETURN(TRUE); } -#endif - /* Don't accept hostnames that starts with digits because they may be - false ip:s */ - if (my_isdigit(&my_charset_latin1,name[0])) + /* Check that getaddrinfo() returned the used IP (FCrDNS technique). */ + + DBUG_PRINT("info", ("The following IP addresses found for '%s':", + (const char *) hostname_buffer)); + + for (struct addrinfo *addr_info= addr_info_list; + addr_info; addr_info= addr_info->ai_next) { - char *pos; - for (pos= name+1 ; my_isdigit(&my_charset_latin1,*pos); pos++) ; - if (*pos == '.') + char ip_buffer[HOST_ENTRY_KEY_SIZE]; + + { + err_status= + vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen, + ip_buffer, sizeof (ip_buffer)); + DBUG_ASSERT(!err_status); + } + + DBUG_PRINT("info", (" - '%s'", (const char *) ip_buffer)); + + if (strcmp(ip_key, ip_buffer) == 0) { - DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'")); - my_free(name,MYF(0)); - goto add_wrong_ip_and_return; + /* Copy host name string to be stored in the cache. */ + + *hostname= my_strdup(hostname_buffer, MYF(0)); + + if (!*hostname) + { + DBUG_PRINT("error", ("Out of memory.")); + + freeaddrinfo(addr_info_list); + DBUG_RETURN(TRUE); + } + + break; } } - /* Check that 'gethostbyname' returned the used ip */ - for (i=0; check->h_addr_list[i]; i++) + /* Log resolved IP-addresses if no match was found. */ + + if (!*hostname) { - if (*(uint32*)(check->h_addr_list)[i] == in->s_addr) + sql_print_information("Hostname '%s' does not resolve to '%s'.", + (const char *) hostname_buffer, + (const char *) ip_key); + sql_print_information("Hostname '%s' has the following IP addresses:", + (const char *) hostname_buffer); + + for (struct addrinfo *addr_info= addr_info_list; + addr_info; addr_info= addr_info->ai_next) { - add_hostname(in,name); - DBUG_RETURN(name); + char ip_buffer[HOST_ENTRY_KEY_SIZE]; + + err_status= + vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen, + ip_buffer, sizeof (ip_buffer)); + DBUG_ASSERT(!err_status); + + sql_print_information(" - %s\n", (const char *) ip_buffer); } } - DBUG_PRINT("error",("Couldn't verify hostname with gethostbyname")); - my_free(name,MYF(0)); -add_wrong_ip_and_return: - add_wrong_ip(in); - DBUG_RETURN(0); + /* Free the result of getaddrinfo(). */ + + freeaddrinfo(addr_info_list); + + /* Add an entry for the IP to the cache. */ + + if (*hostname) + { + err_status= add_hostname(ip_key, *hostname); + *connect_errors= 0; + } + else + { + DBUG_PRINT("error",("Couldn't verify hostname with getaddrinfo().")); + + err_status= add_hostname(ip_key, NULL); + *hostname= NULL; + *connect_errors= 0; + } + + DBUG_RETURN(err_status); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 43546334199..9900de9439b 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -53,6 +53,9 @@ #include "sql_array.h" #include "sql_plugin.h" #include "scheduler.h" +#ifndef __WIN__ +#include <netdb.h> +#endif class Parser_state; @@ -2254,10 +2257,11 @@ uint build_table_shadow_filename(char *buff, size_t bufflen, #define FRM_ONLY (1 << 3) /* from hostname.cc */ -struct in_addr; -char * ip_to_hostname(struct in_addr *in,uint *errors); -void inc_host_errors(struct in_addr *in); -void reset_host_errors(struct in_addr *in); +bool ip_to_hostname(struct sockaddr_storage *ip_storage, + const char *ip_string, + char **hostname, uint *connect_errors); +void inc_host_errors(const char *ip_string); +void reset_host_errors(const char *ip_string); bool hostname_cache_init(); void hostname_cache_free(); void hostname_cache_refresh(void); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 24477f0879a..30ea646d2fd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -106,7 +106,6 @@ extern "C" { // Because of SCO 3.2V4.2 #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif -#include <netdb.h> #ifdef HAVE_SELECT_H # include <select.h> #endif @@ -176,7 +175,7 @@ static void registerwithneb(); static void getvolumename(); static void getvolumeID(BYTE *volumeName); #endif /* __NETWARE__ */ - + #ifdef _AIX41 int initgroups(const char *,unsigned int); @@ -390,7 +389,6 @@ static my_bool opt_short_log_format= 0; static uint kill_cached_threads, wake_thread; static ulong killed_threads, thread_created; static ulong max_used_connections; -static ulong my_bind_addr; /**< the address we bind to */ static volatile ulong cached_thread_count= 0; static const char *sql_mode_str= "OFF"; /* Text representation for OPTIMIZER_SWITCH_DEFAULT */ @@ -1630,17 +1628,18 @@ static void set_root(const char *path) #endif } + static void network_init(void) { - struct sockaddr_in IPaddr; #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif - int arg=1; + int arg; int ret; uint waited; uint this_wait; uint retry; + char port_buf[NI_MAXSERV]; DBUG_ENTER("network_init"); LINT_INIT(ret); @@ -1651,26 +1650,65 @@ static void network_init(void) if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap) { + struct addrinfo *ai, *a; + struct addrinfo hints; + int error; DBUG_PRINT("general",("IP Socket is %d",mysqld_port)); - ip_sock = socket(AF_INET, SOCK_STREAM, 0); + + bzero(&hints, sizeof (hints)); + hints.ai_flags= AI_PASSIVE; + hints.ai_socktype= SOCK_STREAM; + hints.ai_family= AF_UNSPEC; + + my_snprintf(port_buf, NI_MAXSERV, "%d", mysqld_port); + error= getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai); + if (error != 0) + { + DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error)); + sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ + unireg_abort(1); /* purecov: tested */ + } + + for (a= ai; a != NULL; a= a->ai_next) + { + ip_sock= socket(a->ai_family, a->ai_socktype, a->ai_protocol); + if (ip_sock != INVALID_SOCKET) + break; + } + if (ip_sock == INVALID_SOCKET) { DBUG_PRINT("error",("Got error: %d from socket()",socket_errno)); - sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */ + sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ unireg_abort(1); /* purecov: tested */ } - bzero((char*) &IPaddr, sizeof(IPaddr)); - IPaddr.sin_family = AF_INET; - IPaddr.sin_addr.s_addr = my_bind_addr; - IPaddr.sin_port = (unsigned short) htons((unsigned short) mysqld_port); #ifndef __WIN__ /* We should not use SO_REUSEADDR on windows as this would enable a user to open two mysqld servers with the same TCP/IP port. */ + arg= 1; (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg)); #endif /* __WIN__ */ + +#ifdef IPV6_V6ONLY + /* + For interoperability with older clients, IPv6 socket should + listen on both IPv6 and IPv4 wildcard addresses. + Turn off IPV6_V6ONLY option. + + NOTE: this will work starting from Windows Vista only. + On Windows XP dual stack is not available, so it will not + listen on the corresponding IPv4-address. + */ + if (a->ai_family == AF_INET6) + { + arg= 0; + (void) setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, + sizeof(arg)); + } +#endif /* Sometimes the port is not released fast enough when stopping and restarting the server. This happens quite often with the test suite @@ -1681,8 +1719,7 @@ static void network_init(void) */ for (waited= 0, retry= 1; ; retry++, waited+= this_wait) { - if (((ret= bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), - sizeof(IPaddr))) >= 0) || + if (((ret= bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) || (socket_errno != SOCKET_EADDRINUSE) || (waited >= mysqld_port_timeout)) break; @@ -1690,6 +1727,7 @@ static void network_init(void) this_wait= retry * retry / 3 + 1; sleep(this_wait); } + freeaddrinfo(ai); if (ret < 0) { DBUG_PRINT("error",("Got error: %d from bind",socket_errno)); @@ -1711,7 +1749,6 @@ static void network_init(void) if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap && opt_enable_named_pipe) { - strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\", mysqld_unix_port, NullS); bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity)); @@ -1777,6 +1814,7 @@ static void network_init(void) UNIXaddr.sun_family = AF_UNIX; strmov(UNIXaddr.sun_path, mysqld_unix_port); (void) unlink(mysqld_unix_port); + arg= 1; (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg, sizeof(arg)); umask(0); @@ -4832,7 +4870,7 @@ static bool read_init_file(char *file_name) When we enter this function, LOCK_thread_count is hold! */ - + void handle_connection_in_main_thread(THD *thd) { safe_mutex_assert_owner(&LOCK_thread_count); @@ -4915,7 +4953,6 @@ void create_thread_to_handle_connection(THD *thd) static void create_new_thread(THD *thd) { - NET *net=&thd->net; DBUG_ENTER("create_new_thread"); /* @@ -4985,6 +5022,7 @@ inline void kill_broken_server() /* Handle new connections and spawn new process to handle them */ #ifndef EMBEDDED_LIBRARY + void handle_connections_sockets() { my_socket sock,new_sock; @@ -4992,7 +5030,7 @@ void handle_connections_sockets() uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1); fd_set readFDs,clientFDs; THD *thd; - struct sockaddr_in cAddr; + struct sockaddr_storage cAddr; int ip_flags=0,socket_flags=0,flags; st_vio *vio_tmp; DBUG_ENTER("handle_connections_sockets"); @@ -5066,9 +5104,9 @@ void handle_connections_sockets() #endif /* NO_FCNTL_NONBLOCK */ for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++) { - size_socket length=sizeof(struct sockaddr_in); - new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr), - &length); + size_socket length= sizeof(struct sockaddr_storage); + new_sock= accept(sock, (struct sockaddr *)(&cAddr), + &length); #ifdef __NETWARE__ // TODO: temporary fix, waiting for TCP/IP fix - DEFECT000303149 if ((new_sock == INVALID_SOCKET) && (socket_errno == EINVAL)) @@ -5139,9 +5177,10 @@ void handle_connections_sockets() { size_socket dummyLen; - struct sockaddr dummy; - dummyLen = sizeof(struct sockaddr); - if (getsockname(new_sock,&dummy, &dummyLen) < 0) + struct sockaddr_storage dummy; + dummyLen = sizeof(dummy); + if ( getsockname(new_sock,(struct sockaddr *)&dummy, + (SOCKET_SIZE_TYPE *)&dummyLen) < 0 ) { sql_perror("Error on new connection socket"); (void) shutdown(new_sock, SHUT_RDWR); @@ -5487,7 +5526,7 @@ errorconn: NullS); sql_perror(buff); } - if (handle_client_file_map) + if (handle_client_file_map) CloseHandle(handle_client_file_map); if (handle_client_map) UnmapViewOfFile(handle_client_map); @@ -7718,7 +7757,6 @@ static int mysql_init_variables(void) strmov(server_version, MYSQL_SERVER_VERSION); myisam_recover_options_str= sql_mode_str= "OFF"; myisam_stats_method_str= "nulls_unequal"; - my_bind_addr = htonl(INADDR_ANY); threads.empty(); thread_cache.empty(); key_caches.empty(); @@ -8153,27 +8191,25 @@ mysqld_get_one_option(int optid, my_use_symdir=0; break; case (int) OPT_BIND_ADDRESS: - if ((my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE) { - struct hostent *ent; - if (argument[0]) - ent=gethostbyname(argument); - else + struct addrinfo *res_lst, hints; + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_socktype= SOCK_STREAM; + hints.ai_protocol= IPPROTO_TCP; + + if (getaddrinfo(argument, NULL, &hints, &res_lst) != 0) { - char myhostname[255]; - if (gethostname(myhostname,sizeof(myhostname)) < 0) - { - sql_perror("Can't start server: cannot get my own hostname!"); - return 1; - } - ent=gethostbyname(myhostname); + sql_print_error("Can't start server: cannot resolve hostname!"); + return 1; } - if (!ent) + + if (res_lst->ai_next) { - sql_perror("Can't start server: cannot resolve hostname!"); + sql_print_error("Can't start server: bind-address refers to multiple interfaces!"); return 1; } - my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr; + freeaddrinfo(res_lst); } break; case (int) OPT_PID_FILE: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 641423605aa..155e7298e90 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1785,24 +1785,83 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, (ip && !wild_compare(ip, host->hostname, 0))); } +/** + Check if the given host name needs to be resolved or not. + Host name has to be resolved if it actually contains *name*. + + For example: + 192.168.1.1 --> FALSE + 192.168.1.0/255.255.255.0 --> FALSE + % --> FALSE + 192.168.1.% --> FALSE + AB% --> FALSE + + AAAAFFFF --> TRUE (Hostname) + AAAA:FFFF:1234:5678 --> FALSE + ::1 --> FALSE + + This function does not check if the given string is a valid host name or + not. It assumes that the argument is a valid host name. + + @param hostname the string to check. + + @return a flag telling if the argument needs to be resolved or not. + @retval TRUE the argument is a host name and needs to be resolved. + @retval FALSE the argument is either an IP address, or a patter and + should not be resolved. +*/ + bool hostname_requires_resolving(const char *hostname) { - char cur; if (!hostname) return FALSE; - size_t namelen= strlen(hostname); - size_t lhlen= strlen(my_localhost); - if ((namelen == lhlen) && - !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, - (const uchar *)my_localhost, strlen(my_localhost))) + + /* Check if hostname is the localhost. */ + + size_t hostname_len= strlen(hostname); + size_t localhost_len= strlen(my_localhost); + + if (hostname == my_localhost || + (hostname_len == localhost_len && + !my_strnncoll(system_charset_info, + (const uchar *) hostname, hostname_len, + (const uchar *) my_localhost, strlen(my_localhost)))) + { return FALSE; - for (; (cur=*hostname); hostname++) + } + + /* + If the string contains any of {':', '%', '_', '/'}, it is definitely + not a host name: + - ':' means that the string is an IPv6 address; + - '%' or '_' means that the string is a pattern; + - '/' means that the string is an IPv4 network address; + */ + + for (const char *p= hostname; *p; ++p) { - if ((cur != '%') && (cur != '_') && (cur != '.') && (cur != '/') && - ((cur < '0') || (cur > '9'))) - return TRUE; + switch (*p) { + case ':': + case '%': + case '_': + case '/': + return FALSE; + } } - return FALSE; + + /* + Now we have to tell a host name (ab.cd, 12.ab) from an IPv4 address + (12.34.56.78). The assumption is that if the string contains only + digits and dots, it is an IPv4 address. Otherwise -- a host name. + */ + + for (const char *p= hostname; *p; ++p) + { + if (*p != '.' && !my_isdigit(&my_charset_latin1, *p)) + return TRUE; /* a "letter" has been found. */ + } + + return FALSE; /* all characters are either dots or digits. */ } diff --git a/sql/sql_class.h b/sql/sql_class.h index ead4b67bd6c..6b8617c8842 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1238,7 +1238,6 @@ public: HASH user_vars; // hash for user variables String packet; // dynamic buffer for network I/O String convert_buffer; // buffer for charset conversions - struct sockaddr_in remote; // client socket address struct rand_struct rand; // used for authentication struct system_variables variables; // Changeable local variables struct system_status_var status_var; // Per thread statistic vars diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index f5f962a02a3..8ecafce6f93 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -377,7 +377,8 @@ check_user(THD *thd, enum enum_server_command command, if (send_old_password_request(thd) || my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); DBUG_RETURN(1); } @@ -498,9 +499,9 @@ check_user(THD *thd, enum enum_server_command command, thd->main_security_ctx.host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); /* - log access denied messages to the error log when log-warnings = 2 + Log access denied messages to the error log when log-warnings = 2 so that the overhead of the general query log is not required to track - failed connections + failed connections. */ if (global_system_variables.log_warnings > 1) { @@ -666,9 +667,9 @@ static int check_connection(THD *thd) if (!thd->main_security_ctx.host) // If TCP/IP connection { - char ip[30]; + char ip[NI_MAXHOST]; - if (vio_peer_addr(net->vio, ip, &thd->peer_port)) + if (vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST)) { my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; @@ -676,12 +677,15 @@ static int check_connection(THD *thd) if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME)))) return 1; /* The error is set by my_strdup(). */ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; - vio_in_addr(net->vio,&thd->remote.sin_addr); if (!(specialflag & SPECIAL_NO_RESOLVE)) { - vio_in_addr(net->vio,&thd->remote.sin_addr); - thd->main_security_ctx.host= - ip_to_hostname(&thd->remote.sin_addr, &connect_errors); + if (ip_to_hostname(&net->vio->remote, thd->main_security_ctx.ip, + &thd->main_security_ctx.host, &connect_errors)) + { + my_error(ER_BAD_HOST_ERROR, MYF(0), ip); + return 1; + } + /* Cut very long hostnames to avoid possible overflows */ if (thd->main_security_ctx.host) { @@ -714,7 +718,7 @@ static int check_connection(THD *thd) thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; thd->main_security_ctx.ip= 0; /* Reset sin_addr */ - bzero((char*) &thd->remote, sizeof(thd->remote)); + bzero((char*) &net->vio->remote, sizeof(net->vio->remote)); } vio_keepalive(net->vio, TRUE); @@ -769,7 +773,8 @@ static int check_connection(THD *thd) (pkt_len= my_net_read(net)) == packet_error || pkt_len < MIN_HANDSHAKE_SIZE) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; @@ -779,7 +784,7 @@ static int check_connection(THD *thd) #include "_cust_sql_parse.h" #endif if (connect_errors) - reset_host_errors(&thd->remote.sin_addr); + reset_host_errors(thd->main_security_ctx.ip); if (thd->packet.alloc(thd->variables.net_buffer_length)) return 1; /* The error is set by alloc(). */ @@ -813,7 +818,7 @@ static int check_connection(THD *thd) /* Do the SSL layering. */ if (!ssl_acceptor_fd) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -821,7 +826,8 @@ static int check_connection(THD *thd) if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout)) { DBUG_PRINT("error", ("Failed to accept new SSL connection")); - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -831,7 +837,8 @@ static int check_connection(THD *thd) { DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", pkt_len)); - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -840,7 +847,8 @@ static int check_connection(THD *thd) if (end >= (char*) net->read_pos+ pkt_len +2) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -878,7 +886,8 @@ static int check_connection(THD *thd) if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } diff --git a/strings/Makefile.am b/strings/Makefile.am index ddd41e627dc..4c34a923d81 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2006 MySQL AB +# Copyright (C) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc. # # 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 @@ -15,7 +15,16 @@ # This file is public domain and comes with NO WARRANTY of any kind -INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include +# +# Note that the string library is built with #define THREAD, +# which by default cause all the thread related code (my_pthread.h) +# and therefore the associated instrumentation (mysql/psi/mysql_thread.h) +# to be used. +# Since the string code itself is not instrumented, we use +# #define DISABLE_MYSQL_THREAD_H here to avoid unneeded dependencies. +# + +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -DDISABLE_MYSQL_THREAD_H pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X diff --git a/vio/vio.c b/vio/vio.c index 34e02adae3d..b7bac69fc3c 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -78,7 +78,6 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_close_pipe; vio->peer_addr =vio_peer_addr; - vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking; @@ -108,7 +107,6 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_close_shared_memory; vio->peer_addr =vio_peer_addr; - vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking; @@ -136,7 +134,6 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_ssl_close; vio->peer_addr =vio_peer_addr; - vio->in_addr =vio_in_addr; vio->vioblocking =vio_ssl_blocking; vio->is_blocking =vio_is_blocking; vio->timeout =vio_timeout; @@ -156,7 +153,6 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_close; vio->peer_addr =vio_peer_addr; - vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking; vio->timeout =vio_timeout; diff --git a/vio/vio_priv.h b/vio/vio_priv.h index c1ac2ab8365..69eb26083d6 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -25,6 +25,11 @@ #include <m_string.h> #include <violite.h> +#ifndef __WIN__ +#include <sys/socket.h> +#include <netdb.h> +#endif + #ifdef _WIN32 void vio_win32_timeout(Vio *vio, uint which, uint timeout); #endif diff --git a/vio/viosocket.c b/vio/viosocket.c index 51345d072b2..8dcf978f2fa 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -300,53 +300,209 @@ my_socket vio_fd(Vio* vio) return vio->sd; } +/** + Convert a sock-address (AF_INET or AF_INET6) into the "normalized" form, + which is the IPv4 form for IPv4-mapped or IPv4-compatible IPv6 addresses. + + @note Background: when IPv4 and IPv6 are used simultaneously, IPv4 + addresses may be written in a form of IPv4-mapped or IPv4-compatible IPv6 + addresses. That means, one address (a.b.c.d) can be written in three forms: + - IPv4: a.b.c.d; + - IPv4-compatible IPv6: ::a.b.c.d; + - IPv4-mapped IPv4: ::ffff:a.b.c.d; + + Having three forms of one address makes it a little difficult to compare + addresses with each other (the IPv4-compatible IPv6-address of foo.bar + will be different from the IPv4-mapped IPv6-address of foo.bar). + + @note This function can be made public when it's needed. + + @param src [in] source IP address (AF_INET or AF_INET6). + @param src_length [in] length of the src. + @param dst [out] a buffer to store normalized IP address + (sockaddr_storage). + @param dst_length [out] actual length of the normalized IP address. +*/ +static void vio_get_normalized_ip(const struct sockaddr *src, + int src_length, + struct sockaddr *dst, + int *dst_length) +{ + switch (src->sa_family) { + case AF_INET: + memcpy(dst, src, src_length); + *dst_length= src_length; + break; + +#ifdef HAVE_IPV6 + case AF_INET6: + { + const struct sockaddr_in6 *src_addr6= (const struct sockaddr_in6 *) src; + const struct in6_addr *src_ip6= &(src_addr6->sin6_addr); + const uint32 *src_ip6_int32= (uint32 *) src_ip6->s6_addr; + + if (IN6_IS_ADDR_V4MAPPED(src_ip6) || IN6_IS_ADDR_V4COMPAT(src_ip6)) + { + struct sockaddr_in *dst_ip4= (struct sockaddr_in *) dst; + + /* + This is an IPv4-mapped or IPv4-compatible IPv6 address. It should + be converted to the IPv4 form. + */ + + *dst_length= sizeof (struct sockaddr_in); -my_bool vio_peer_addr(Vio * vio, char *buf, uint16 *port) + memset(dst_ip4, 0, *dst_length); + dst_ip4->sin_family= AF_INET; + dst_ip4->sin_port= src_addr6->sin6_port; + + /* + In an IPv4 mapped or compatible address, the last 32 bits represent + the IPv4 address. The byte orders for IPv6 and IPv4 addresses are + the same, so a simple copy is possible. + */ + dst_ip4->sin_addr.s_addr= src_ip6_int32[3]; + } + else + { + /* This is a "native" IPv6 address. */ + + memcpy(dst, src, src_length); + *dst_length= src_length; + } + + break; + } +#endif /* HAVE_IPV6 */ + } +} + + +/** + Return the normalized IP address string for a sock-address. + + The idea is to return an IPv4-address for an IPv4-mapped and + IPv4-compatible IPv6 address. + + The function writes the normalized IP address to the given buffer. + The buffer should have enough space, otherwise error flag is returned. + The system constant INET6_ADDRSTRLEN can be used to reserve buffers of + the right size. + + @param addr [in] sockaddr object (AF_INET or AF_INET6). + @param addr_length [in] length of the addr. + @param ip_string [out] buffer to write normalized IP address. + @param ip_string_size [in] size of the ip_string. + + @return Error status. + @retval TRUE in case of error (the ip_string buffer is not enough). + @retval FALSE on success. +*/ + +my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, + int addr_length, + char *ip_string, + size_t ip_string_size) +{ + struct sockaddr_storage norm_addr_storage; + struct sockaddr *norm_addr= (struct sockaddr *) &norm_addr_storage; + int norm_addr_length; + int err_code; + + vio_get_normalized_ip(addr, addr_length, norm_addr, &norm_addr_length); + + err_code= vio_getnameinfo(norm_addr, ip_string, ip_string_size, NULL, 0, + NI_NUMERICHOST); + + if (!err_code) + return FALSE; + + DBUG_PRINT("error", ("getnameinfo() failed with %d (%s).", + (int) err_code, + (const char *) gai_strerror(err_code))); + return TRUE; +} + + +/** + Return IP address and port of a VIO client socket. + + The function returns an IPv4 address if IPv6 support is disabled. + + The function returns an IPv4 address if the client socket is associated + with an IPv4-compatible or IPv4-mapped IPv6 address. Otherwise, the native + IPv6 address is returned. +*/ + +my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port, + size_t ip_buffer_size) { DBUG_ENTER("vio_peer_addr"); - DBUG_PRINT("enter", ("sd: %d", vio->sd)); + DBUG_PRINT("enter", ("Client socked fd: %d", (int) vio->sd)); + if (vio->localhost) { - strmov(buf,"127.0.0.1"); + /* + Initialize vio->remote and vio->addLen. Set vio->remote to IPv4 loopback + address. + */ + struct in_addr *ip4= &((struct sockaddr_in *) &(vio->remote))->sin_addr; + + vio->remote.ss_family= AF_INET; + vio->addrLen= sizeof (struct sockaddr_in); + + ip4->s_addr= htonl(INADDR_LOOPBACK); + + /* Initialize ip_buffer and port. */ + + strmov(ip_buffer, "127.0.0.1"); *port= 0; } else { - size_socket addrLen = sizeof(vio->remote); - if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote), - &addrLen) != 0) + int err_code; + char port_buffer[NI_MAXSERV]; + + struct sockaddr_storage addr_storage; + struct sockaddr *addr= (struct sockaddr *) &addr_storage; + size_socket addr_length= sizeof (addr_storage); + + /* Get sockaddr by socked fd. */ + + err_code= getpeername(vio->sd, addr, &addr_length); + + if (err_code) { - DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno)); - DBUG_RETURN(1); + DBUG_PRINT("exit", ("getpeername() gave error: %d", socket_errno)); + DBUG_RETURN(TRUE); } - my_inet_ntoa(vio->remote.sin_addr,buf); - *port= ntohs(vio->remote.sin_port); - } - DBUG_PRINT("exit", ("addr: %s", buf)); - DBUG_RETURN(0); -} + /* Normalize IP address. */ -/* - Get in_addr for a TCP/IP connection + vio_get_normalized_ip(addr, addr_length, + (struct sockaddr *) &vio->remote, &vio->addrLen); - SYNOPSIS - vio_in_addr() - vio vio handle - in put in_addr here + /* Get IP address & port number. */ - NOTES - one must call vio_peer_addr() before calling this one -*/ + err_code= vio_getnameinfo((struct sockaddr *) &vio->remote, + ip_buffer, ip_buffer_size, + port_buffer, NI_MAXSERV, + NI_NUMERICHOST | NI_NUMERICSERV); -void vio_in_addr(Vio *vio, struct in_addr *in) -{ - DBUG_ENTER("vio_in_addr"); - if (vio->localhost) - bzero((char*) in, sizeof(*in)); - else - *in=vio->remote.sin_addr; - DBUG_VOID_RETURN; + if (err_code) + { + DBUG_PRINT("exit", ("getnameinfo() gave error: %s", + gai_strerror(err_code))); + DBUG_RETURN(TRUE); + } + + *port= (uint16) strtol(port_buffer, NULL, 10); + } + + DBUG_PRINT("exit", ("Client IP address: %s; port: %d", + (const char *) ip_buffer, + (int) *port)); + DBUG_RETURN(FALSE); } @@ -377,7 +533,8 @@ static my_bool socket_poll_read(my_socket sd, uint timeout) FD_ZERO(&errorfds); FD_SET(fd, &readfds); FD_SET(fd, &errorfds); - if ((res= select(fd, &readfds, NULL, &errorfds, &tm) <= 0)) + /* The first argument is ignored on Windows, so a conversion to int is OK */ + if ((res= select((int) fd, &readfds, NULL, &errorfds, &tm) <= 0)) { DBUG_RETURN(res < 0 ? 0 : 1); } @@ -879,3 +1036,36 @@ ssize_t vio_pending(Vio *vio) return 0; } + + +/** + This is a wrapper for the system getnameinfo(), because different OS + differ in the getnameinfo() implementation. For instance, Solaris 10 + requires that the 2nd argument (salen) must match the actual size of the + struct sockaddr_storage passed to it. +*/ + +int vio_getnameinfo(const struct sockaddr *sa, + char *hostname, size_t hostname_size, + char *port, size_t port_size, + int flags) +{ + int sa_length= 0; + + switch (sa->sa_family) { + case AF_INET: + sa_length= sizeof (struct sockaddr_in); + break; + +#ifdef HAVE_IPV6 + case AF_INET6: + sa_length= sizeof (struct sockaddr_in6); + break; +#endif /* HAVE_IPV6 */ + } + + return getnameinfo(sa, sa_length, + hostname, hostname_size, + port, port_size, + flags); +} |